1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 package zeus.concepts.fn;
26
27 import java.util.*;
28 import zeus.util.*;
29 import zeus.concepts.*;
30
31 public class DefinedFn extends ValueFunction {
32 static final int ABS = 0;
33 static final int ACOS = 2;
34 static final int ASIN = 4;
35 static final int ATAN = 6;
36 static final int ATAN2 = 8;
37 static final int CEIL = 10;
38 static final int COS = 12;
39 static final int SIN = 14;
40 static final int TAN = 16;
41 static final int EXP = 18;
42 static final int FLOOR = 20;
43 static final int IEEE_REMAINDER = 22;
44 static final int LOG = 24;
45 static final int MAX = 26;
46 static final int MIN = 28;
47 static final int POW = 30;
48 static final int RANDOM = 32;
49 static final int RINT = 34;
50 static final int ROUND = 36;
51 static final int SQRT = 38;
52 static final int TO_DEGREES = 40;
53 static final int TO_RADIANS = 42;
54 static final int CONCAT = 44;
55 static final int NONVAR = 46;
56 static final int VAR = 48;
57
58 static final String[] FUNCTIONS = {
59 "abs", "1",
60 "acos", "1",
61 "asin", "1",
62 "atan", "1",
63 "atan2", "2",
64 "ceil", "1",
65 "cos", "1",
66 "sin", "1",
67 "tan", "1",
68 "exp", "1",
69 "floor", "1",
70 "IEEEremainder", "2",
71 "log", "1",
72 "max", "2",
73 "min", "2",
74 "pow", "2",
75 "random", "0",
76 "rint", "1",
77 "round", "1",
78 "sqrt", "1",
79 "toDegrees", "1",
80 "toRadians", "1",
81 "concat", "2",
82 "nonvar", "1",
83 "var", "1"
84 };
85
86 protected Object[] args = new Object[2];
87
88 public DefinedFn(String lhs, Vector rhs) {
89 super(FUNC,3);
90 args[0] = lhs;
91 args[1] = rhs;
92
93 int position = -1;
94 if ( (position = Misc.whichPosition(lhs,FUNCTIONS)) == -1 ||
95 ((position % 2) != 0) ) {
96 throw new IllegalArgumentException("Unknown function " + lhs +
97 " in expression.");
98 }
99
100 int arity = Integer.parseInt(FUNCTIONS[position+1]);
101 if ( rhs == null || rhs.size() != arity ) {
102 throw new IllegalArgumentException(
103 "Wrong number of arguments used in function " +
104 lhs + "/" + arity + ".");
105 }
106 }
107 public ValueFunction mirror() {
108 Vector List = (Vector)args[1];
109 Vector otherList = new Vector();
110 ValueFunction fn;
111 for(int i = 0; i < List.size(); i++ ) {
112 fn = (ValueFunction)List.elementAt(i);
113 fn = fn.mirror();
114 otherList.addElement(fn);
115 }
116 return new DefinedFn((String)args[0],otherList);
117 }
118
119 public String toString() {
120 String s = (String)args[0] + "(";
121 Vector List = (Vector)args[1];
122 ValueFunction fn;
123 for(int i = 0; i < List.size(); i++ ) {
124 fn = (ValueFunction)List.elementAt(i);
125 s += fn;
126 if ( i + 1 < List.size() )
127 s += ",";
128 }
129 s += ")";
130 return s;
131 }
132
133 ValueFunction simplify() {
134 Vector List = (Vector)args[1];
135 Vector otherList = new Vector();
136 ValueFunction fn;
137 for(int i = 0; i < List.size(); i++ ) {
138 fn = (ValueFunction)List.elementAt(i);
139 fn = fn.simplify();
140 otherList.addElement(fn);
141 }
142 return new DefinedFn((String)args[0],otherList);
143 }
144 Object getArg(int position) {
145 return args[position];
146 }
147 public boolean references(ValueFunction var) {
148 Vector List = (Vector)args[1];
149 ValueFunction fn;
150 for(int i = 0; i < List.size(); i++ ) {
151 fn = (ValueFunction)List.elementAt(i);
152 if ( fn.references(var) )
153 return true;
154 }
155 return false;
156 }
157 public Vector variables() {
158 Vector List = (Vector)args[1];
159 Vector otherList = new Vector();
160 ValueFunction fn;
161 for(int i = 0; i < List.size(); i++ ) {
162 fn = (ValueFunction)List.elementAt(i);
163 otherList = Misc.union(otherList,fn.variables());
164 }
165 return otherList;
166 }
167 public boolean isDeterminate() {
168 Vector List = (Vector)args[1];
169 ValueFunction fn;
170 for(int i = 0; i < List.size(); i++ ) {
171 fn = (ValueFunction)List.elementAt(i);
172 if ( !fn.isDeterminate() ) return false;
173 }
174 return true;
175 }
176 ValueFunction normalize() {
177 Vector List = (Vector)args[1];
178 Vector otherList = new Vector();
179 ValueFunction fn;
180 for(int i = 0; i < List.size(); i++ ) {
181 fn = (ValueFunction)List.elementAt(i);
182 fn = fn.normalize();
183 otherList.addElement(fn);
184 }
185 return new DefinedFn((String)args[0],otherList);
186 }
187 public ValueFunction resolve(ResolutionContext c, Bindings b) {
188 Vector List = (Vector)args[1];
189 Vector otherList = new Vector();
190 ValueFunction fn;
191 for(int i = 0; i < List.size(); i++ ) {
192 fn = (ValueFunction)List.elementAt(i);
193 fn = fn.resolve(c,b);
194 otherList.addElement(fn);
195 }
196 return (new DefinedFn((String)args[0],otherList)).evaluationFn();
197 }
198
199 public ValueFunction evaluationFn() {
200 if ( !args[0].equals("nonvar") && !args[0].equals("var") && !isDeterminate() ) return this;
201
202 try {
203 PrimitiveNumericFn a, b;
204 IdFn c, d;
205 ValueFunction x;
206
207 switch( Misc.whichPosition((String)args[0],FUNCTIONS) ) {
208 case ABS:
209 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
210 switch( ((ValueFunction)a).getID() ) {
211 case INT:
212 return new IntFn(Math.abs(a.longValue()));
213 case REAL:
214 return new RealFn(Math.abs(a.doubleValue()));
215 }
216 break;
217
218 case ACOS:
219 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
220 return new RealFn(Math.acos(a.doubleValue()));
221
222 case ASIN:
223 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
224 return new RealFn(Math.asin(a.doubleValue()));
225
226 case ATAN:
227 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
228 return new RealFn(Math.atan(a.doubleValue()));
229
230 case ATAN2:
231 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
232 b = (PrimitiveNumericFn)((Vector)args[1]).elementAt(1);
233 return new RealFn(Math.atan2(a.doubleValue(),b.doubleValue()));
234
235 case CEIL:
236 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
237 return new RealFn(Math.ceil(a.doubleValue()));
238
239 case COS:
240 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
241 return new RealFn(Math.cos(a.doubleValue()));
242
243 case EXP:
244 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
245 return new RealFn(Math.exp(a.doubleValue()));
246
247 case FLOOR:
248 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
249 return new RealFn(Math.floor(a.doubleValue()));
250
251 case IEEE_REMAINDER:
252 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
253 b = (PrimitiveNumericFn)((Vector)args[1]).elementAt(1);
254 return new RealFn(Math.IEEEremainder(a.doubleValue(),b.doubleValue()));
255
256 case LOG:
257 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
258 return new RealFn(Math.log(a.doubleValue()));
259
260 case MAX:
261 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
262 b = (PrimitiveNumericFn)((Vector)args[1]).elementAt(1);
263 if ( ((ValueFunction)a).getID() == INT && ((ValueFunction)b).getID() == INT )
264 return new IntFn(Math.max(a.longValue(),b.longValue()));
265 else
266 return new RealFn(Math.max(a.doubleValue(),b.doubleValue()));
267
268 case MIN:
269 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
270 b = (PrimitiveNumericFn)((Vector)args[1]).elementAt(1);
271 if ( ((ValueFunction)a).getID() == INT && ((ValueFunction)b).getID() == INT )
272 return new IntFn(Math.min(a.longValue(),b.longValue()));
273 else
274 return new RealFn(Math.min(a.doubleValue(),b.doubleValue()));
275
276 case POW:
277 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
278 b = (PrimitiveNumericFn)((Vector)args[1]).elementAt(1);
279 return new RealFn(Math.pow(a.doubleValue(),b.doubleValue()));
280
281 case RANDOM:
282 return new RealFn(Math.random());
283
284 case RINT:
285 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
286 return new RealFn(Math.rint(a.doubleValue()));
287
288 case ROUND:
289 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
290 return new IntFn(Math.round(a.doubleValue()));
291
292 case SIN:
293 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
294 return new RealFn(Math.sin(a.doubleValue()));
295
296 case SQRT:
297 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
298 return new RealFn(Math.sqrt(a.doubleValue()));
299
300 case TAN:
301 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
302 return new RealFn(Math.tan(a.doubleValue()));
303
304 case TO_DEGREES:
305 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
306 return new RealFn(Math.toDegrees(a.doubleValue()));
307
308 case TO_RADIANS:
309 a = (PrimitiveNumericFn)((Vector)args[1]).elementAt(0);
310 return new RealFn(Math.toRadians(a.doubleValue()));
311
312 case CONCAT:
313 c = (IdFn)((Vector)args[1]).elementAt(0);
314 d = (IdFn)((Vector)args[1]).elementAt(1);
315 return new IdFn(c.getValue() + d.getValue());
316
317 case NONVAR:
318 x = (ValueFunction)((Vector)args[1]).elementAt(0);
319 return BoolFn.newBoolFn(x.isDeterminate());
320
321 case VAR:
322 x = (ValueFunction)((Vector)args[1]).elementAt(0);
323 return BoolFn.newBoolFn(!(x.isDeterminate()));
324
325 default:
326 throw new IllegalArgumentException(
327 "Unknown function: \'" + args[0] + "\'");
328 }
329 }
330 catch(ClassCastException e) {
331 throw new IllegalArgumentException(
332 "Type mismatch in function \'" + this + "\'");
333 }
334 return null;
335 }
336
337 public ValueFunction duplicate(DuplicationTable table) {
338 Vector List = (Vector)args[1];
339 Vector otherList = new Vector();
340 ValueFunction fn;
341 for(int i = 0; i < List.size(); i++ ) {
342 fn = (ValueFunction)List.elementAt(i);
343 fn = fn.duplicate(table);
344 otherList.addElement(fn);
345 }
346 return new DefinedFn((String)args[0],otherList);
347 }
348 public boolean equals(Object any) {
349 if ( !(any instanceof DefinedFn) ) return false;
350 DefinedFn fn = (DefinedFn)any;
351
352 ValueFunction a = this.simplify();
353 ValueFunction b = fn.simplify();
354 return a.getArg(0).equals(b.getArg(0)) &&
355 Misc.sameVector((Vector)a.getArg(1),(Vector)b.getArg(1));
356
357 }
358 ValueFunction unify(ValueFunction fn, Bindings b) {
359 ValueFunction x = null;
360 if ( (x = evaluationFn()) == this )
361 return new AndFn(this,fn);
362 else
363 return x.unifiesWith(fn,b);
364 }
365 }