1 | //
|
---|
2 | // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
|
---|
3 | //
|
---|
4 | // The contents of this file are covered under the licence agreement in the
|
---|
5 | // file "LICENCE" distributed with Cforall.
|
---|
6 | //
|
---|
7 | // function-operator.c --
|
---|
8 | //
|
---|
9 | // Author : Rob Schluntz
|
---|
10 | // Created On : Fri Aug 25 15:21:11 2017
|
---|
11 | // Last Modified By : Rob Schluntz
|
---|
12 | // Last Modified On : Fri Aug 25 15:31:29 2017
|
---|
13 | // Update Count : 2
|
---|
14 | //
|
---|
15 |
|
---|
16 | #include <fstream>
|
---|
17 | #include <stdlib>
|
---|
18 |
|
---|
19 | #define length(array) (sizeof((array))/sizeof((array)[0]))
|
---|
20 | #define begin(array) (&array[0]) // there's currently a bug in passing an array to a polymorphic function, so ensure a pointer is passed instead
|
---|
21 | #define end(array) (&array[length(array)])
|
---|
22 |
|
---|
23 | // STL-like Algorithms
|
---|
24 | trait Assignable(dtype T, dtype U) { T ?=?(T &, U); };
|
---|
25 | trait Copyable(dtype T) { void ?{}(T &, T); };
|
---|
26 | trait Destructable(dtype T) { void ^?{}(T &); };
|
---|
27 |
|
---|
28 | trait Iterator(dtype iter | sized(iter) | Copyable(iter) | Destructable(iter), otype T) {
|
---|
29 | T & *?(iter);
|
---|
30 | iter ++?(iter &);
|
---|
31 | int ?!=?(iter, iter);
|
---|
32 | };
|
---|
33 |
|
---|
34 | forall(otype Tin, dtype Input | Iterator(Input, Tin), otype Tout, dtype Output | Iterator(Output, Tout) | Assignable(Tout, Tin))
|
---|
35 | Output copy(Input first, Input last, Output result) {
|
---|
36 | while (first != last) {
|
---|
37 | *result = *first;
|
---|
38 | ++result; ++first;
|
---|
39 | }
|
---|
40 | return result;
|
---|
41 | }
|
---|
42 |
|
---|
43 | // test ?()(T *, ...) -- ?() with function call-by-pointer
|
---|
44 | forall(otype Tin, dtype Input | Iterator(Input, Tin), otype Tout, dtype Output | Iterator(Output, Tout), otype FuncRet, dtype Func | { FuncRet ?()(Func *, Tin); } | Assignable(Tout, FuncRet))
|
---|
45 | Output transform (Input first, Input last, Output result, Func * op) {
|
---|
46 | while (first != last) {
|
---|
47 | *result = op(*first);
|
---|
48 | ++result; ++first;
|
---|
49 | }
|
---|
50 | return result;
|
---|
51 | }
|
---|
52 |
|
---|
53 | // test ?()(T, ...) -- ?() with function call-by-value
|
---|
54 | forall(dtype Iter, otype T | Iterator(Iter, T), otype Pred | { int ?()(Pred, T); })
|
---|
55 | Iter find_if (Iter first, Iter last, Pred pred) {
|
---|
56 | while (first != last) {
|
---|
57 | if (pred(*first)) return first;
|
---|
58 | ++first;
|
---|
59 | }
|
---|
60 | return last;
|
---|
61 | }
|
---|
62 |
|
---|
63 | // test ?()(T, ...) -- ?() with function call-by-reference
|
---|
64 | forall(otype Generator, otype GenRet | { GenRet ?()(Generator &); }, dtype Iter, otype T| Iterator(Iter, T) | Assignable(T, GenRet))
|
---|
65 | void generate(Iter first, Iter last, Generator & gen) {
|
---|
66 | int i = 0;
|
---|
67 | while (first != last) {
|
---|
68 | *first = gen();
|
---|
69 | ++first;
|
---|
70 | }
|
---|
71 | }
|
---|
72 |
|
---|
73 | // encapsulate a counter that increments by one every time it is called
|
---|
74 | struct Counter { int c; };
|
---|
75 | void ?{}(Counter & cnt) { cnt.c = 0; }
|
---|
76 | int ?()(Counter & cnt) { return cnt.c++; }
|
---|
77 |
|
---|
78 | // TODO: abstract over os type with ostream trait; resolver is currently too slow for this to be reasonable, but it does work.
|
---|
79 | struct os_wrapper {
|
---|
80 | ofstream * out;
|
---|
81 | };
|
---|
82 |
|
---|
83 | // TODO: abstract over (os, T)
|
---|
84 | os_wrapper ?=?(os_wrapper & wrapper, int x) {
|
---|
85 | wrapper.out | x | endl;
|
---|
86 | return wrapper;
|
---|
87 | }
|
---|
88 |
|
---|
89 | struct ostream_iterator {
|
---|
90 | os_wrapper * out;
|
---|
91 | };
|
---|
92 | void ?{}(ostream_iterator & iter, ofstream * out) {
|
---|
93 | iter.out = new(out);
|
---|
94 | }
|
---|
95 | // no destructor, memory leak. This is necessary for this to work at the moment, since
|
---|
96 | // *? requires its parameter by value and returns a reference.
|
---|
97 |
|
---|
98 | // implement Iterator
|
---|
99 | os_wrapper & *?(ostream_iterator iter) {
|
---|
100 | return *iter.out;
|
---|
101 | }
|
---|
102 | ostream_iterator ++?(ostream_iterator & iter) {
|
---|
103 | // nothing to do
|
---|
104 | return iter;
|
---|
105 | }
|
---|
106 | int ?!=?(ostream_iterator i1, ostream_iterator i2) {
|
---|
107 | return i1.out->out != i2.out->out;
|
---|
108 | }
|
---|
109 |
|
---|
110 | forall(otype T | { int ?==?(T, T); })
|
---|
111 | struct Equals {
|
---|
112 | T val;
|
---|
113 | };
|
---|
114 |
|
---|
115 | forall(otype T | { int ?==?(T, T); })
|
---|
116 | int ?()(Equals(T) eq, T x) {
|
---|
117 | return eq.val == x;
|
---|
118 | }
|
---|
119 |
|
---|
120 | forall(otype T | { T ?*?(T, T); })
|
---|
121 | struct Multiply {
|
---|
122 | T val;
|
---|
123 | };
|
---|
124 |
|
---|
125 | forall(otype T | { T ?*?(T, T); })
|
---|
126 | T ?()(Multiply(T) * mult, T x) {
|
---|
127 | return mult->val * x;
|
---|
128 | }
|
---|
129 |
|
---|
130 | // TODO: generalize to ttype return; doesn't work yet
|
---|
131 | // like std::function
|
---|
132 | forall(otype Return, ttype Args)
|
---|
133 | struct function {
|
---|
134 | Return (*f)(Args);
|
---|
135 | };
|
---|
136 | // TODO: missing adapter in these functions
|
---|
137 | // // value, reference, pointer operators
|
---|
138 | // forall(otype Return, ttype Args) Return ?()(function(Return, Args) func, Args args) { return func.f(args); }
|
---|
139 | // forall(otype Return, ttype Args) Return ?()(function(Return, Args) & func, Args args) { return func.f(args); }
|
---|
140 | // forall(otype Return, ttype Args) Return ?()(function(Return, Args) * func, Args args) { return func->f(args); }
|
---|
141 |
|
---|
142 | int main() {
|
---|
143 | // generate for array fill
|
---|
144 | Counter c;
|
---|
145 | int x[10], y[10];
|
---|
146 | generate(begin(x), end(x), c);
|
---|
147 | generate(begin(y), end(y), c);
|
---|
148 |
|
---|
149 | // copy for output
|
---|
150 | ostream_iterator out_iter = { sout };
|
---|
151 | copy(begin(x), end(x), out_iter);
|
---|
152 | copy(begin(y), end(y), out_iter);
|
---|
153 |
|
---|
154 | // find_if for searching
|
---|
155 | Equals(int) is5 = { 5 };
|
---|
156 | if (find_if(begin(x), end(x), is5) != end(y)) {
|
---|
157 | printf("Found 5 in x.\n");
|
---|
158 | } else {
|
---|
159 | printf("Did not find 5 in x.\n");
|
---|
160 | }
|
---|
161 | if (find_if(begin(y), end(y), is5) != end(y)) {
|
---|
162 | printf("Found 5 in y.\n");
|
---|
163 | } else {
|
---|
164 | printf("Did not find 5 in y.\n");
|
---|
165 | }
|
---|
166 |
|
---|
167 | Multiply(int) times2 = { 2 };
|
---|
168 | transform(begin(x), end(x), begin(x), ×2);
|
---|
169 | copy(begin(x), end(x), out_iter);
|
---|
170 | }
|
---|
171 |
|
---|
172 | // Local Variables: //
|
---|
173 | // tab-width: 4 //
|
---|
174 | // End: //
|
---|