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