1 /*
2     Qalculate (library)
3 
4     Copyright (C) 2003-2007, 2008, 2016, 2018  Hanna Knutsson (hanna.knutsson@protonmail.com)
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 */
11 
12 #include "support.h"
13 
14 #include "BuiltinFunctions.h"
15 #include "util.h"
16 #include "MathStructure.h"
17 #include "Number.h"
18 #include "Calculator.h"
19 #include "Variable.h"
20 #include "Unit.h"
21 
22 #include <sstream>
23 #include <time.h>
24 #include <limits>
25 #include <algorithm>
26 
27 #include "MathStructure-support.h"
28 
29 using std::string;
30 using std::cout;
31 using std::vector;
32 using std::endl;
33 
34 #define FR_FUNCTION_2(FUNC)	Number nr(vargs[0].number()); if(!nr.FUNC(vargs[1].number()) || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate() && !vargs[1].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex() && !vargs[1].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity() && !vargs[1].number().includesInfinity())) {return 0;} else {mstruct.set(nr); return 1;}
35 
BitXorFunction()36 BitXorFunction::BitXorFunction() : MathFunction("xor", 2) {
37 	ArgumentSet *arg = new ArgumentSet();
38 	arg->addArgument(new IntegerArgument("", ARGUMENT_MIN_MAX_NONE));
39 	arg->addArgument(new VectorArgument);
40 	setArgumentDefinition(1, arg);
41 	arg = new ArgumentSet();
42 	arg->addArgument(new IntegerArgument("", ARGUMENT_MIN_MAX_NONE));
43 	arg->addArgument(new VectorArgument);
44 	setArgumentDefinition(2, arg);
45 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)46 int BitXorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
47 	if(vargs[0].isNumber() && vargs[1].isNumber()) {
48 		Number nr(vargs[0].number());
49 		if(nr.bitXor(vargs[1].number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || vargs[0].number().isApproximate() || vargs[1].number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || vargs[0].number().isComplex() || vargs[1].number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || vargs[0].number().includesInfinity() || vargs[1].number().includesInfinity())) {
50 			mstruct.set(nr, true);
51 			return 1;
52 		}
53 	} else if(vargs[0].isVector() && vargs[1].isVector()) {
54 		int i1 = 0, i2 = 1;
55 		if(vargs[0].size() < vargs[1].size()) {
56 			i1 = 1;
57 			i2 = 0;
58 		}
59 		mstruct.clearVector();
60 		mstruct.resizeVector(vargs[i1].size(), m_undefined);
61 		size_t i = 0;
62 		for(; i < vargs[i2].size(); i++) {
63 			mstruct[i].set(CALCULATOR->getFunctionById(FUNCTION_ID_XOR), &vargs[i1][i], &vargs[i2][0], NULL);
64 		}
65 		for(; i < vargs[i1].size(); i++) {
66 			mstruct[i] = vargs[i1][i];
67 			mstruct[i].add(m_zero, OPERATION_GREATER);
68 		}
69 		return 1;
70 	}
71 	mstruct = vargs[0];
72 	mstruct.add(vargs[1], OPERATION_BITWISE_XOR);
73 	return 0;
74 }
XorFunction()75 XorFunction::XorFunction() : MathFunction("lxor", 2) {
76 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)77 int XorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
78 	int b0, b1;
79 	if(vargs[0].representsNonPositive(true)) {
80 		b0 = 0;
81 	} else if(vargs[0].representsPositive(true)) {
82 		b0 = 1;
83 	} else {
84 		b0 = -1;
85 	}
86 	if(vargs[1].representsNonPositive(true)) {
87 		b1 = 0;
88 	} else if(vargs[1].representsPositive(true)) {
89 		b1 = 1;
90 	} else {
91 		b1 = -1;
92 	}
93 	if((b0 == 1 && b1 == 0) || (b0 == 0 && b1 == 1)) {
94 		mstruct = m_one;
95 		return 1;
96 	} else if(b0 >= 0 && b1 >= 0) {
97 		return 1;
98 	} else if(b0 == 0) {
99 		mstruct = vargs[1];
100 		mstruct.add(m_zero, OPERATION_GREATER);
101 		return 1;
102 	} else if(b0 == 1) {
103 		mstruct = vargs[1];
104 		mstruct.add(m_zero, OPERATION_EQUALS_LESS);
105 		return 1;
106 	} else if(b1 == 0) {
107 		mstruct = vargs[0];
108 		mstruct.add(m_zero, OPERATION_GREATER);
109 		return 1;
110 	} else if(b1 == 1) {
111 		mstruct = vargs[0];
112 		mstruct.add(m_zero, OPERATION_EQUALS_LESS);
113 		return 1;
114 	}
115 	mstruct = vargs[1];
116 	mstruct.setLogicalNot();
117 	mstruct.add(vargs[0], OPERATION_LOGICAL_AND);
118 	MathStructure mstruct2(vargs[0]);
119 	mstruct2.setLogicalNot();
120 	mstruct2.add(vargs[1], OPERATION_LOGICAL_AND);
121 	mstruct.add(mstruct2, OPERATION_LOGICAL_OR);
122 	return 1;
123 }
124 
ShiftFunction()125 ShiftFunction::ShiftFunction() : MathFunction("shift", 2, 3) {
126 	setArgumentDefinition(1, new IntegerArgument());
127 	setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG));
128 	setArgumentDefinition(3, new BooleanArgument());
129 	setDefaultValue(3, "1");
130 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)131 int ShiftFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
132 	if(vargs.size() >= 3 && !vargs[2].number().getBoolean() && vargs[1].number().isNegative()) {
133 		Number nr(vargs[0].number());
134 		Number nr_div(vargs[1].number());
135 		if(!nr_div.negate() || !nr_div.exp2() || !nr.divide(nr_div) || !nr.trunc()) return false;
136 		mstruct.set(nr);
137 		return 1;
138 	}
139 	FR_FUNCTION_2(shift)
140 }
CircularShiftFunction()141 CircularShiftFunction::CircularShiftFunction() : MathFunction("bitrot", 2, 4) {
142 	setArgumentDefinition(1, new IntegerArgument());
143 	setArgumentDefinition(2, new IntegerArgument());
144 	setArgumentDefinition(3, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_UINT));
145 	setArgumentDefinition(4, new BooleanArgument());
146 	setDefaultValue(3, "0");
147 	setDefaultValue(4, "1");
148 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)149 int CircularShiftFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
150 	if(vargs[0].number().isZero()) {
151 		mstruct.clear();
152 		return 1;
153 	}
154 	Number nr(vargs[0].number());
155 	unsigned int bits = vargs[2].number().uintValue();
156 	if(bits == 0) {
157 		bits = nr.integerLength();
158 		if(bits <= 8) bits = 8;
159 		else if(bits <= 16) bits = 16;
160 		else if(bits <= 32) bits = 32;
161 		else if(bits <= 64) bits = 64;
162 		else if(bits <= 128) bits = 128;
163 		else {
164 			bits = (unsigned int) ::ceil(::log2(bits));
165 			bits = ::pow(2, bits);
166 		}
167 	}
168 	Number nr_n(vargs[1].number());
169 	nr_n.rem(bits);
170 	if(nr_n.isZero()) {
171 		mstruct = nr;
172 		return 1;
173 	}
174 	PrintOptions po;
175 	po.base = BASE_BINARY;
176 	po.base_display = BASE_DISPLAY_NONE;
177 	po.binary_bits = bits;
178 	string str = nr.print(po);
179 	remove_blanks(str);
180 	if(str.length() < bits) return 0;
181 	if(nr_n.isNegative()) {
182 		nr_n.negate();
183 		std::rotate(str.rbegin(), str.rbegin() + nr_n.uintValue(), str.rend());
184 	} else {
185 		std::rotate(str.begin(), str.begin() + nr_n.uintValue(), str.end());
186 	}
187 	ParseOptions pao;
188 	pao.base = BASE_BINARY;
189 	pao.twos_complement = vargs[3].number().getBoolean();
190 	mstruct = Number(str, pao);
191 	return 1;
192 }
BitCmpFunction()193 BitCmpFunction::BitCmpFunction() : MathFunction("bitcmp", 1, 3) {
194 	setArgumentDefinition(1, new IntegerArgument());
195 	setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_UINT));
196 	setDefaultValue(2, "0");
197 	setArgumentDefinition(3, new BooleanArgument());
198 	setDefaultValue(3, "0");
199 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)200 int BitCmpFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
201 	Number nr(vargs[0].number());
202 	if(vargs.size() >= 3 && vargs[2].number().getBoolean()) {
203 		if(nr.bitNot()) {
204 			mstruct = nr;
205 			return 1;
206 		}
207 		return 0;
208 	}
209 	unsigned int bits = vargs[1].number().uintValue();
210 	if(bits == 0) {
211 		bits = nr.integerLength();
212 		if(bits <= 8) bits = 8;
213 		else if(bits <= 16) bits = 16;
214 		else if(bits <= 32) bits = 32;
215 		else if(bits <= 64) bits = 64;
216 		else if(bits <= 128) bits = 128;
217 		else {
218 			bits = (unsigned int) ::ceil(::log2(bits));
219 			bits = ::pow(2, bits);
220 		}
221 	}
222 	if(nr.bitCmp(bits)) {
223 		mstruct = nr;
224 		return 1;
225 	}
226 	return 0;
227 }
228 
IFFunction()229 IFFunction::IFFunction() : MathFunction("if", 3, 4) {
230 	setArgumentDefinition(4, new BooleanArgument());
231 	setDefaultValue(4, "0");
232 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)233 int IFFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
234 	if(vargs[0].isNumber()) {
235 		int result = vargs[0].number().getBoolean();
236 		if(result > 0) {
237 			mstruct = vargs[1];
238 		} else if(result == 0 || vargs[3].isOne()) {
239 			mstruct = vargs[2];
240 		} else {
241 			return 0;
242 		}
243 		return 1;
244 	}
245 	mstruct = vargs[0];
246 	mstruct.eval(eo);
247 	if(mstruct.isVector()) {
248 		for(size_t i = 0; i < mstruct.size(); i++) {
249 			if(!mstruct[i].isNumber() && vargs[3].isZero()) {
250 				return -1;
251 			}
252 			int result = mstruct[i].number().getBoolean();
253 			if(result > 0) {
254 				if(vargs[1].isVector() && vargs[1].size() == vargs[0].size()) {
255 					mstruct = vargs[1][i];
256 				} else {
257 					mstruct = vargs[1];
258 				}
259 				return 1;
260 			} else if(result < 0 && vargs[3].isZero()) {
261 				return -1;
262 			}
263 		}
264 		mstruct = vargs[2];
265 		return 1;
266 	}
267 	if(mstruct.isNumber()) {
268 		int result = mstruct.number().getBoolean();
269 		if(result > 0) {
270 			mstruct = vargs[1];
271 		} else if(result == 0 || vargs[3].isOne()) {
272 			mstruct = vargs[2];
273 		} else {
274 			return -1;
275 		}
276 		return 1;
277 	}
278 	if(vargs[3].isOne()) {
279 		mstruct = vargs[2];
280 		return 1;
281 	}
282 	return -1;
283 }
ForFunction()284 ForFunction::ForFunction() : MathFunction("for", 7) {
285 	setArgumentDefinition(2, new SymbolicArgument());
286 	setArgumentDefinition(7, new SymbolicArgument());
287 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)288 int ForFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
289 
290 	mstruct = vargs[4];
291 	MathStructure mcounter = vargs[0];
292 	MathStructure mtest;
293 	MathStructure mcount;
294 	MathStructure mupdate;
295 	while(true) {
296 		mtest = vargs[2];
297 		mtest.replace(vargs[1], mcounter);
298 		mtest.eval(eo);
299 		if(!mtest.isNumber() || CALCULATOR->aborted()) return 0;
300 		if(!mtest.number().getBoolean()) {
301 			break;
302 		}
303 		if(vargs[5].isComparison() && vargs[5].comparisonType() == COMPARISON_EQUALS && vargs[5][0] == vargs[6]) mupdate = vargs[5][1];
304 		else mupdate = vargs[5];
305 		mupdate.replace(vargs[1], mcounter, vargs[6], mstruct);
306 		mstruct = mupdate;
307 		mstruct.calculatesub(eo, eo, false);
308 
309 		if(vargs[3].isComparison() && vargs[3].comparisonType() == COMPARISON_EQUALS && vargs[3][0] == vargs[1]) mcount = vargs[3][1];
310 		else mcount = vargs[3];
311 		mcount.replace(vargs[1], mcounter);
312 		mcounter = mcount;
313 		mcounter.calculatesub(eo, eo, false);
314 	}
315 	return 1;
316 
317 }
318 
319