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 #if HAVE_UNORDERED_MAP
30 # include <unordered_map>
31 using std::unordered_map;
32 #elif defined(__GNUC__)
33
34 # ifndef __has_include
35 # define __has_include(x) 0
36 # endif
37
38 # if (defined(__clang__) && __has_include(<tr1/unordered_map>)) || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 3)
39 # include <tr1/unordered_map>
40 namespace Sgi = std;
41 # define unordered_map std::tr1::unordered_map
42 # else
43 # if __GNUC__ < 3
44 # include <hash_map.h>
45 namespace Sgi { using ::hash_map; }; // inherit globals
46 # else
47 # include <ext/hash_map>
48 # if __GNUC__ == 3 && __GNUC_MINOR__ == 0
49 namespace Sgi = std; // GCC 3.0
50 # else
51 namespace Sgi = ::__gnu_cxx; // GCC 3.1 and later
52 # endif
53 # endif
54 # define unordered_map Sgi::hash_map
55 # endif
56 #else // ... there are other compilers, right?
57 namespace Sgi = std;
58 # define unordered_map Sgi::hash_map
59 #endif
60
61 using std::string;
62 using std::cout;
63 using std::vector;
64 using std::endl;
65
66 #define FR_FUNCTION(FUNC) Number nr(vargs[0].number()); if(!nr.FUNC() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity())) {return 0;} else {mstruct.set(nr); return 1;}
67 #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;}
68
69 #define NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(i) NumberArgument *arg_non_complex##i = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false); arg_non_complex##i->setComplexAllowed(false); setArgumentDefinition(i, arg_non_complex##i);
70 #define NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR_NONZERO(i) NumberArgument *arg_non_complex##i = new NumberArgument("", ARGUMENT_MIN_MAX_NONZERO, true, false); arg_non_complex##i->setComplexAllowed(false); setArgumentDefinition(i, arg_non_complex##i);
71 #define RATIONAL_NUMBER_ARGUMENT_NO_ERROR(i) NumberArgument *arg_rational##i = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false); arg_rational##i->setRationalNumber(true); setArgumentDefinition(i, arg_rational##i);
72 #define RATIONAL_POLYNOMIAL_ARGUMENT(i) Argument *arg_poly##i = new Argument(); arg_poly##i->setRationalPolynomial(true); setArgumentDefinition(i, arg_poly##i);
73 #define RATIONAL_POLYNOMIAL_ARGUMENT_HV(i) Argument *arg_poly##i = new Argument(); arg_poly##i->setRationalPolynomial(true); arg_poly##i->setHandleVector(true); setArgumentDefinition(i, arg_poly##i);
74
OddFunction()75 OddFunction::OddFunction() : MathFunction("odd", 1) {
76 Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, false, false);
77 arg->setHandleVector(true);
78 setArgumentDefinition(1, arg);
79 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)80 int OddFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
81 if(vargs[0].isVector()) return 0;
82 if(vargs[0].representsOdd()) {
83 mstruct.set(1, 1, 0);
84 return 1;
85 } else if(vargs[0].representsEven()) {
86 mstruct.clear();
87 return 1;
88 }
89 mstruct = vargs[0];
90 mstruct.eval(eo);
91 if(mstruct.isVector()) return -1;
92 if(mstruct.representsOdd()) {
93 mstruct.set(1, 1, 0);
94 return 1;
95 } else if(mstruct.representsEven()) {
96 mstruct.clear();
97 return 1;
98 }
99 return -1;
100 }
EvenFunction()101 EvenFunction::EvenFunction() : MathFunction("even", 1) {
102 Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, false, false);
103 arg->setHandleVector(true);
104 setArgumentDefinition(1, arg);
105 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)106 int EvenFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
107 if(vargs[0].isVector()) return 0;
108 if(vargs[0].representsEven()) {
109 mstruct.set(1, 1, 0);
110 return 1;
111 } else if(vargs[0].representsOdd()) {
112 mstruct.clear();
113 return 1;
114 }
115 mstruct = vargs[0];
116 mstruct.eval(eo);
117 if(mstruct.isVector()) return -1;
118 if(mstruct.representsEven()) {
119 mstruct.set(1, 1, 0);
120 return 1;
121 } else if(mstruct.representsOdd()) {
122 mstruct.clear();
123 return 1;
124 }
125 return -1;
126 }
AbsFunction()127 AbsFunction::AbsFunction() : MathFunction("abs", 1) {
128 Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false);
129 arg->setHandleVector(true);
130 setArgumentDefinition(1, arg);
131 }
representsPositive(const MathStructure & vargs,bool allow_units) const132 bool AbsFunction::representsPositive(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units) && vargs[0].representsNonZero(allow_units);}
representsNegative(const MathStructure &,bool) const133 bool AbsFunction::representsNegative(const MathStructure&, bool) const {return false;}
representsNonNegative(const MathStructure & vargs,bool allow_units) const134 bool AbsFunction::representsNonNegative(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);}
representsNonPositive(const MathStructure &,bool) const135 bool AbsFunction::representsNonPositive(const MathStructure&, bool) const {return false;}
representsInteger(const MathStructure & vargs,bool allow_units) const136 bool AbsFunction::representsInteger(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsInteger(allow_units);}
representsNumber(const MathStructure & vargs,bool allow_units) const137 bool AbsFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);}
representsRational(const MathStructure & vargs,bool allow_units) const138 bool AbsFunction::representsRational(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsRational(allow_units);}
representsReal(const MathStructure & vargs,bool allow_units) const139 bool AbsFunction::representsReal(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);}
representsNonComplex(const MathStructure & vargs,bool) const140 bool AbsFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;}
representsComplex(const MathStructure &,bool) const141 bool AbsFunction::representsComplex(const MathStructure&, bool) const {return false;}
representsNonZero(const MathStructure & vargs,bool allow_units) const142 bool AbsFunction::representsNonZero(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units) && vargs[0].representsNonZero(allow_units);}
representsEven(const MathStructure & vargs,bool allow_units) const143 bool AbsFunction::representsEven(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsEven(allow_units);}
representsOdd(const MathStructure & vargs,bool allow_units) const144 bool AbsFunction::representsOdd(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsOdd(allow_units);}
representsUndefined(const MathStructure & vargs) const145 bool AbsFunction::representsUndefined(const MathStructure &vargs) const {return vargs.size() == 1 && vargs[0].representsUndefined();}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)146 int AbsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
147 if(vargs[0].isVector()) return 0;
148 mstruct = vargs[0];
149 mstruct.eval(eo);
150 if(mstruct.isVector()) return -1;
151 if(mstruct.isNumber()) {
152 if(eo.approximation != APPROXIMATION_APPROXIMATE && mstruct.number().hasImaginaryPart() && mstruct.number().hasRealPart()) {
153 MathStructure m_i(mstruct.number().imaginaryPart());
154 m_i ^= nr_two;
155 mstruct.number().clearImaginary();
156 mstruct.numberUpdated();
157 mstruct ^= nr_two;
158 mstruct += m_i;
159 mstruct ^= nr_half;
160 return 1;
161 }
162 Number nr(mstruct.number());
163 if(!nr.abs() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate())) {
164 return -1;
165 }
166 mstruct = nr;
167 return 1;
168 }
169 if(mstruct.isPower() && mstruct[0].representsPositive()) {
170 if(mstruct[1].isNumber() && !mstruct[1].number().hasRealPart()) {
171 mstruct.set(1, 1, 0, true);
172 return 1;
173 } else if(mstruct[1].isMultiplication() && mstruct.size() > 0 && mstruct[1][0].isNumber() && !mstruct[1][0].number().hasRealPart()) {
174 bool b = true;
175 for(size_t i = 1; i < mstruct[1].size(); i++) {
176 if(!mstruct[1][i].representsNonComplex()) {b = false; break;}
177 }
178 if(b) {
179 mstruct.set(1, 1, 0, true);
180 return 1;
181 }
182 }
183 }
184 if(mstruct.representsNegative(true)) {
185 mstruct.negate();
186 return 1;
187 }
188 if(mstruct.representsNonNegative(true)) {
189 return 1;
190 }
191 if(mstruct.isMultiplication()) {
192 for(size_t i = 0; i < mstruct.size(); i++) {
193 mstruct[i].transform(STRUCT_FUNCTION);
194 mstruct[i].setFunction(this);
195 }
196 mstruct.childrenUpdated();
197 return 1;
198 }
199 if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_SIGNUM && mstruct.size() == 2) {
200 mstruct[0].transform(this);
201 mstruct.childUpdated(1);
202 return 1;
203 }
204 if(mstruct.isPower() && mstruct[1].representsReal()) {
205 mstruct[0].transform(this);
206 return 1;
207 }
208 if(eo.approximation == APPROXIMATION_EXACT || has_interval_unknowns(mstruct)) {
209 ComparisonResult cr = mstruct.compare(m_zero);
210 if(COMPARISON_IS_EQUAL_OR_LESS(cr)) {
211 return 1;
212 } else if(COMPARISON_IS_EQUAL_OR_GREATER(cr)) {
213 mstruct.negate();
214 return 1;
215 }
216 }
217 return -1;
218 }
GcdFunction()219 GcdFunction::GcdFunction() : MathFunction("gcd", 2) {
220 RATIONAL_POLYNOMIAL_ARGUMENT_HV(1)
221 RATIONAL_POLYNOMIAL_ARGUMENT_HV(2)
222 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)223 int GcdFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
224 if(MathStructure::gcd(vargs[0], vargs[1], mstruct, eo)) {
225 return 1;
226 }
227 return 0;
228 }
LcmFunction()229 LcmFunction::LcmFunction() : MathFunction("lcm", 2) {
230 RATIONAL_POLYNOMIAL_ARGUMENT_HV(1)
231 RATIONAL_POLYNOMIAL_ARGUMENT_HV(2)
232 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)233 int LcmFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
234 if(MathStructure::lcm(vargs[0], vargs[1], mstruct, eo)) {
235 return 1;
236 }
237 return 0;
238 }
239
SignumFunction()240 SignumFunction::SignumFunction() : MathFunction("sgn", 1, 2) {
241 Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false);
242 arg->setHandleVector(true);
243 setArgumentDefinition(1, arg);
244 setDefaultValue(2, "0");
245 }
representsPositive(const MathStructure &,bool allow_units) const246 bool SignumFunction::representsPositive(const MathStructure&, bool allow_units) const {return false;}
representsNegative(const MathStructure &,bool) const247 bool SignumFunction::representsNegative(const MathStructure&, bool) const {return false;}
representsNonNegative(const MathStructure & vargs,bool) const248 bool SignumFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsNonNegative(true);}
representsNonPositive(const MathStructure & vargs,bool) const249 bool SignumFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsNonPositive(true);}
representsInteger(const MathStructure & vargs,bool) const250 bool SignumFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsReal(true);}
representsNumber(const MathStructure & vargs,bool) const251 bool SignumFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsNumber(true);}
representsRational(const MathStructure & vargs,bool) const252 bool SignumFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsReal(true);}
representsNonComplex(const MathStructure & vargs,bool) const253 bool SignumFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsNonComplex(true);}
representsReal(const MathStructure & vargs,bool) const254 bool SignumFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsReal(true);}
representsComplex(const MathStructure & vargs,bool) const255 bool SignumFunction::representsComplex(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsComplex(true);}
representsNonZero(const MathStructure & vargs,bool) const256 bool SignumFunction::representsNonZero(const MathStructure &vargs, bool) const {return (vargs.size() == 2 && !vargs[1].isZero()) || (vargs.size() >= 1 && vargs[0].representsNonZero(true));}
representsEven(const MathStructure &,bool) const257 bool SignumFunction::representsEven(const MathStructure&, bool) const {return false;}
representsOdd(const MathStructure & vargs,bool b) const258 bool SignumFunction::representsOdd(const MathStructure &vargs, bool b) const {return representsNonZero(vargs, b);}
representsUndefined(const MathStructure & vargs) const259 bool SignumFunction::representsUndefined(const MathStructure &vargs) const {return vargs.size() >= 1 && vargs[0].representsUndefined();}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)260 int SignumFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
261 if(vargs[0].isVector()) return 0;
262 mstruct = vargs[0];
263 mstruct.eval(eo);
264 if(mstruct.isVector()) return -1;
265 if(mstruct.isNumber() && (vargs.size() == 1 || vargs[1].isZero())) {
266 Number nr(mstruct.number());
267 if(!nr.signum() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate())) {
268 if(mstruct.number().isNonZero()) {
269 MathStructure *mabs = new MathStructure(mstruct);
270 mabs->transformById(FUNCTION_ID_ABS);
271 mstruct.divide_nocopy(mabs);
272 return 1;
273 }
274 return -1;
275 } else {
276 mstruct = nr;
277 return 1;
278 }
279 }
280 if((vargs.size() > 1 && vargs[1].isOne() && mstruct.representsNonNegative(true)) || mstruct.representsPositive(true)) {
281 mstruct.set(1, 1, 0);
282 return 1;
283 }
284 if((vargs.size() > 1 && vargs[1].isMinusOne() && mstruct.representsNonPositive(true)) || mstruct.representsNegative(true)) {
285 mstruct.set(-1, 1, 0);
286 return 1;
287 }
288 if(mstruct.isMultiplication()) {
289 for(size_t i = 0; i < mstruct.size(); i++) {
290 if(vargs.size() > 1) mstruct[i].transform(STRUCT_FUNCTION, vargs[1]);
291 else mstruct[i].transform(STRUCT_FUNCTION);
292 mstruct[i].setFunction(this);
293
294 }
295 mstruct.childrenUpdated();
296 return 1;
297 }
298 if(vargs.size() > 1 && mstruct.isZero()) {
299 mstruct.set(vargs[1], true);
300 return 1;
301 }
302 if(eo.approximation == APPROXIMATION_EXACT || has_interval_unknowns(mstruct)) {
303 ComparisonResult cr = mstruct.compare(m_zero);
304 if(cr == COMPARISON_RESULT_LESS || (vargs.size() > 1 && vargs[1].isOne() && COMPARISON_IS_EQUAL_OR_LESS(cr))) {
305 mstruct.set(1, 1, 0);
306 return 1;
307 } else if(cr == COMPARISON_RESULT_GREATER || (vargs.size() > 1 && vargs[1].isMinusOne() && COMPARISON_IS_EQUAL_OR_GREATER(cr))) {
308 mstruct.set(-1, 1, 0);
309 return 1;
310 }
311 }
312 return -1;
313 }
314
CeilFunction()315 CeilFunction::CeilFunction() : MathFunction("ceil", 1) {
316 NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false);
317 arg->setComplexAllowed(false);
318 arg->setHandleVector(true);
319 setArgumentDefinition(1, arg);
320 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)321 int CeilFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
322 if(vargs[0].isVector()) return 0;
323 if(vargs[0].isNumber()) {
324 FR_FUNCTION(ceil)
325 }
326 mstruct = vargs[0];
327 mstruct.eval(eo);
328 if(mstruct.isVector()) return -1;
329 if(mstruct.isNumber()) {
330 Number nr(mstruct.number());
331 if(nr.ceil() && (eo.approximation != APPROXIMATION_EXACT || !nr.isApproximate() || vargs[0].isApproximate())) {
332 mstruct.set(nr);
333 return 1;
334 }
335 } else if(!mstruct.isNumber() && eo.approximation == APPROXIMATION_EXACT && !vargs[0].isApproximate()) {
336 EvaluationOptions eo2 = eo;
337 eo2.approximation = APPROXIMATION_APPROXIMATE;
338 MathStructure mstruct2(mstruct);
339 mstruct2.eval(eo2);
340 if(mstruct2.isNumber()) {
341 Number nr(mstruct2.number());
342 if(nr.ceil() && !nr.isApproximate()) {
343 mstruct.set(nr);
344 return 1;
345 }
346 }
347 }
348 return -1;
349 }
representsPositive(const MathStructure & vargs,bool) const350 bool CeilFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsPositive();}
representsNegative(const MathStructure &,bool) const351 bool CeilFunction::representsNegative(const MathStructure&, bool) const {return false;}
representsNonNegative(const MathStructure & vargs,bool) const352 bool CeilFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative();}
representsNonPositive(const MathStructure & vargs,bool) const353 bool CeilFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonPositive();}
representsInteger(const MathStructure & vargs,bool) const354 bool CeilFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsNumber(const MathStructure & vargs,bool) const355 bool CeilFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsNonComplex(const MathStructure & vargs,bool) const356 bool CeilFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;}
representsRational(const MathStructure & vargs,bool) const357 bool CeilFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsReal(const MathStructure & vargs,bool) const358 bool CeilFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsComplex(const MathStructure &,bool) const359 bool CeilFunction::representsComplex(const MathStructure&, bool) const {return false;}
representsNonZero(const MathStructure & vargs,bool) const360 bool CeilFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsPositive();}
representsEven(const MathStructure & vargs,bool) const361 bool CeilFunction::representsEven(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsEven();}
representsOdd(const MathStructure & vargs,bool) const362 bool CeilFunction::representsOdd(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsOdd();}
representsUndefined(const MathStructure &) const363 bool CeilFunction::representsUndefined(const MathStructure&) const {return false;}
364
FloorFunction()365 FloorFunction::FloorFunction() : MathFunction("floor", 1) {
366 NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false);
367 arg->setComplexAllowed(false);
368 arg->setHandleVector(true);
369 setArgumentDefinition(1, arg);
370 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)371 int FloorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
372 if(vargs[0].isVector()) return 0;
373 if(vargs[0].isNumber()) {
374 FR_FUNCTION(floor)
375 }
376 mstruct = vargs[0];
377 mstruct.eval(eo);
378 if(mstruct.isVector()) return -1;
379 if(mstruct.isNumber()) {
380 Number nr(mstruct.number());
381 if(nr.floor() && (eo.approximation != APPROXIMATION_EXACT || !nr.isApproximate() || vargs[0].isApproximate())) {
382 mstruct.set(nr);
383 return 1;
384 }
385 } else if(!mstruct.isNumber() && eo.approximation == APPROXIMATION_EXACT && !vargs[0].isApproximate()) {
386 EvaluationOptions eo2 = eo;
387 eo2.approximation = APPROXIMATION_APPROXIMATE;
388 MathStructure mstruct2(mstruct);
389 mstruct2.eval(eo2);
390 if(mstruct2.isNumber()) {
391 Number nr(mstruct2.number());
392 if(nr.floor() && !nr.isApproximate()) {
393 mstruct.set(nr);
394 return 1;
395 }
396 }
397 }
398 return -1;
399 }
representsPositive(const MathStructure &,bool) const400 bool FloorFunction::representsPositive(const MathStructure&, bool) const {return false;}
representsNegative(const MathStructure & vargs,bool) const401 bool FloorFunction::representsNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNegative();}
representsNonNegative(const MathStructure & vargs,bool) const402 bool FloorFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative();}
representsNonPositive(const MathStructure & vargs,bool) const403 bool FloorFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonPositive();}
representsInteger(const MathStructure & vargs,bool) const404 bool FloorFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsNumber(const MathStructure & vargs,bool) const405 bool FloorFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsRational(const MathStructure & vargs,bool) const406 bool FloorFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsNonComplex(const MathStructure & vargs,bool) const407 bool FloorFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;}
representsReal(const MathStructure & vargs,bool) const408 bool FloorFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsComplex(const MathStructure &,bool) const409 bool FloorFunction::representsComplex(const MathStructure&, bool) const {return false;}
representsNonZero(const MathStructure & vargs,bool) const410 bool FloorFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNegative();}
representsEven(const MathStructure & vargs,bool) const411 bool FloorFunction::representsEven(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsEven();}
representsOdd(const MathStructure & vargs,bool) const412 bool FloorFunction::representsOdd(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsOdd();}
representsUndefined(const MathStructure &) const413 bool FloorFunction::representsUndefined(const MathStructure&) const {return false;}
414
TruncFunction()415 TruncFunction::TruncFunction() : MathFunction("trunc", 1) {
416 NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false);
417 arg->setComplexAllowed(false);
418 arg->setHandleVector(true);
419 setArgumentDefinition(1, arg);
420 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)421 int TruncFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
422 if(vargs[0].isVector()) return 0;
423 if(vargs[0].isNumber()) {
424 FR_FUNCTION(trunc)
425 }
426 mstruct = vargs[0];
427 mstruct.eval(eo);
428 if(mstruct.isVector()) return -1;
429 if(mstruct.isNumber()) {
430 Number nr(mstruct.number());
431 if(nr.trunc() && (eo.approximation != APPROXIMATION_EXACT || !nr.isApproximate() || vargs[0].isApproximate())) {
432 mstruct.set(nr);
433 return 1;
434 }
435 } else if(!mstruct.isNumber() && eo.approximation == APPROXIMATION_EXACT && !vargs[0].isApproximate()) {
436 EvaluationOptions eo2 = eo;
437 eo2.approximation = APPROXIMATION_APPROXIMATE;
438 MathStructure mstruct2(mstruct);
439 mstruct2.eval(eo2);
440 if(mstruct2.isNumber()) {
441 Number nr(mstruct2.number());
442 if(nr.trunc() && !nr.isApproximate()) {
443 mstruct.set(nr);
444 return 1;
445 }
446 }
447 }
448 return -1;
449 }
representsPositive(const MathStructure &,bool) const450 bool TruncFunction::representsPositive(const MathStructure&, bool) const {return false;}
representsNegative(const MathStructure &,bool) const451 bool TruncFunction::representsNegative(const MathStructure&, bool) const {return false;}
representsNonNegative(const MathStructure & vargs,bool) const452 bool TruncFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative();}
representsNonPositive(const MathStructure & vargs,bool) const453 bool TruncFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonPositive();}
representsInteger(const MathStructure & vargs,bool) const454 bool TruncFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsNumber(const MathStructure & vargs,bool) const455 bool TruncFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsRational(const MathStructure & vargs,bool) const456 bool TruncFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsReal(const MathStructure & vargs,bool) const457 bool TruncFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsNonComplex(const MathStructure & vargs,bool) const458 bool TruncFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;}
representsComplex(const MathStructure &,bool) const459 bool TruncFunction::representsComplex(const MathStructure&, bool) const {return false;}
representsNonZero(const MathStructure &,bool) const460 bool TruncFunction::representsNonZero(const MathStructure&, bool) const {return false;}
representsEven(const MathStructure & vargs,bool) const461 bool TruncFunction::representsEven(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsEven();}
representsOdd(const MathStructure & vargs,bool) const462 bool TruncFunction::representsOdd(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsOdd();}
representsUndefined(const MathStructure &) const463 bool TruncFunction::representsUndefined(const MathStructure&) const {return false;}
464
RoundFunction()465 RoundFunction::RoundFunction() : MathFunction("round", 1, 3) {
466 NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false);
467 arg->setComplexAllowed(false);
468 arg->setHandleVector(true);
469 setArgumentDefinition(1, arg);
470 setArgumentDefinition(2, new IntegerArgument());
471 setDefaultValue(2, "0");
472 setArgumentDefinition(3, new BooleanArgument());
473 setDefaultValue(3, "0");
474 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)475 int RoundFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
476 if(vargs[0].isVector()) return 0;
477 if(vargs[0].isNumber()) {
478 Number nr(vargs[0].number());
479 if(vargs.size() >= 2 && !vargs[1].isZero()) nr.exp10(vargs[1].number());
480 if(nr.round(vargs.size() >= 3 ? vargs[2].number().getBoolean() : true) && (eo.approximation != APPROXIMATION_EXACT || !nr.isApproximate() || vargs[0].isApproximate())) {
481 if(vargs.size() >= 2 && !vargs[1].isZero()) nr.exp10(-vargs[1].number());
482 mstruct.set(nr);
483 return 1;
484 }
485 return 0;
486 }
487 mstruct = vargs[0];
488 mstruct.eval(eo);
489 if(mstruct.isVector()) return -1;
490 if(mstruct.isNumber()) {
491 Number nr(mstruct.number());
492 if(vargs.size() >= 2 && !vargs[1].isZero()) nr.exp10(vargs[1].number());
493 if(nr.round(vargs.size() >= 3 ? vargs[2].number().getBoolean() : true) && (eo.approximation != APPROXIMATION_EXACT || !nr.isApproximate() || vargs[0].isApproximate())) {
494 if(vargs.size() >= 2 && !vargs[1].isZero()) nr.exp10(-vargs[1].number());
495 mstruct.set(nr);
496 return 1;
497 }
498 } else if(!mstruct.isNumber() && eo.approximation == APPROXIMATION_EXACT && !vargs[0].isApproximate()) {
499 EvaluationOptions eo2 = eo;
500 eo2.approximation = APPROXIMATION_APPROXIMATE;
501 MathStructure mstruct2(mstruct);
502 mstruct2.eval(eo2);
503 if(mstruct2.isNumber()) {
504 Number nr(mstruct2.number());
505 if(vargs.size() >= 2 && !vargs[1].isZero()) nr.exp10(vargs[1].number());
506 if(nr.round(vargs.size() >= 3 ? vargs[2].number().getBoolean() : true) && !nr.isApproximate()) {
507 if(vargs.size() >= 2 && !vargs[1].isZero()) nr.exp10(-vargs[1].number());
508 mstruct.set(nr);
509 return 1;
510 }
511 }
512 }
513 return -1;
514 }
representsPositive(const MathStructure &,bool) const515 bool RoundFunction::representsPositive(const MathStructure&, bool) const {return false;}
representsNegative(const MathStructure &,bool) const516 bool RoundFunction::representsNegative(const MathStructure&, bool) const {return false;}
representsNonNegative(const MathStructure & vargs,bool) const517 bool RoundFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative();}
representsNonPositive(const MathStructure & vargs,bool) const518 bool RoundFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonPositive();}
representsInteger(const MathStructure & vargs,bool) const519 bool RoundFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && (vargs.size() < 2 || vargs[1].representsNonPositive());}
representsNumber(const MathStructure & vargs,bool) const520 bool RoundFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsRational(const MathStructure & vargs,bool) const521 bool RoundFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsReal(const MathStructure & vargs,bool) const522 bool RoundFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsNonComplex(const MathStructure & vargs,bool) const523 bool RoundFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;}
representsComplex(const MathStructure &,bool) const524 bool RoundFunction::representsComplex(const MathStructure&, bool) const {return false;}
representsNonZero(const MathStructure &,bool) const525 bool RoundFunction::representsNonZero(const MathStructure&, bool) const {return false;}
representsEven(const MathStructure & vargs,bool) const526 bool RoundFunction::representsEven(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsEven() && (vargs.size() < 2 || vargs[1].representsNonPositive());}
representsOdd(const MathStructure & vargs,bool) const527 bool RoundFunction::representsOdd(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsOdd() && (vargs.size() < 2 || vargs[1].representsNonPositive());}
representsUndefined(const MathStructure &) const528 bool RoundFunction::representsUndefined(const MathStructure&) const {return false;}
529
FracFunction()530 FracFunction::FracFunction() : MathFunction("frac", 1) {
531 NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1)
532 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)533 int FracFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
534 FR_FUNCTION(frac)
535 }
IntFunction()536 IntFunction::IntFunction() : MathFunction("int", 1) {
537 NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1)
538 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)539 int IntFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
540 FR_FUNCTION(trunc)
541 }
NumeratorFunction()542 NumeratorFunction::NumeratorFunction() : MathFunction("numerator", 1) {
543 NumberArgument *arg_rational_1 = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false);
544 arg_rational_1->setRationalNumber(true);
545 arg_rational_1->setHandleVector(true);
546 setArgumentDefinition(1, arg_rational_1);
547 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)548 int NumeratorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
549 if(vargs[0].isVector()) return 0;
550 if(vargs[0].isNumber()) {
551 if(vargs[0].number().isInteger()) {
552 mstruct = vargs[0];
553 return 1;
554 } else if(vargs[0].number().isRational()) {
555 mstruct.set(vargs[0].number().numerator());
556 return 1;
557 }
558 return 0;
559 } else if(vargs[0].representsInteger()) {
560 mstruct = vargs[0];
561 return 1;
562 }
563 mstruct = vargs[0];
564 mstruct.eval(eo);
565 if(mstruct.isVector()) return -1;
566 if(mstruct.representsInteger()) {
567 return 1;
568 } else if(mstruct.isNumber() && mstruct.number().isRational()) {
569 Number nr(mstruct.number().numerator());
570 mstruct.set(nr);
571 return 1;
572 }
573 return -1;
574 }
DenominatorFunction()575 DenominatorFunction::DenominatorFunction() : MathFunction("denominator", 1) {
576 RATIONAL_NUMBER_ARGUMENT_NO_ERROR(1)
577 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)578 int DenominatorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
579 mstruct.set(vargs[0].number().denominator());
580 return 1;
581 }
RemFunction()582 RemFunction::RemFunction() : MathFunction("rem", 2) {
583 NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1)
584 NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR_NONZERO(2)
585 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)586 int RemFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
587 FR_FUNCTION_2(rem)
588 }
ModFunction()589 ModFunction::ModFunction() : MathFunction("mod", 2) {
590 NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1)
591 NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR_NONZERO(2)
592 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)593 int ModFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
594 FR_FUNCTION_2(mod)
595 }
596
BernoulliFunction()597 BernoulliFunction::BernoulliFunction() : MathFunction("bernoulli", 1, 2) {
598 setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONNEGATIVE));
599 setDefaultValue(2, "0");
600 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)601 int BernoulliFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
602 if(vargs.size() > 1 && !vargs[1].isZero()) {
603 MathStructure m2(vargs[1]);
604 replace_f_interval(m2, eo);
605 replace_intervals_f(m2);
606 mstruct.clear();
607 Number bin, k, nmk(vargs[0].number()), nrB;
608 while(k <= vargs[0].number()) {
609 if(nmk.isEven() || nmk.isOne()) {
610 nrB.set(nmk);
611 if(!bin.binomial(vargs[0].number(), k) || !nrB.bernoulli() || !nrB.multiply(bin)) return 0;
612 if(eo.approximation == APPROXIMATION_EXACT && nrB.isApproximate()) return 0;
613 mstruct.add(nrB, true);
614 mstruct.last().multiply(m2);
615 mstruct.last().last().raise(k);
616 mstruct.childUpdated(mstruct.size());
617 }
618 nmk--;
619 k++;
620 }
621 if(mstruct.isAddition()) mstruct.delChild(1, true);
622 return 1;
623 }
624 FR_FUNCTION(bernoulli)
625 }
626
TotientFunction()627 TotientFunction::TotientFunction() : MathFunction("totient", 1, 1) {
628 setArgumentDefinition(1, new IntegerArgument());
629 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)630 int TotientFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
631 if(vargs[0].number().isZero()) {mstruct.clear(); return 1;}
632 if(vargs[0].number() <= 2 && vargs[0].number() >= -2) {mstruct.set(1, 1, 0); return 1;}
633 mpz_t n, result, tmp, p_square, p;
634 mpz_inits(n, result, tmp, p_square, p, NULL);
635 mpz_set(n, mpq_numref(vargs[0].number().internalRational()));
636 mpz_abs(n, n);
637 mpz_set(result, n);
638 size_t i = 0;
639 while(true) {
640 if(CALCULATOR->aborted()) {mpz_clears(n, result, tmp, p, p_square, NULL); return 0;}
641 if(i < NR_OF_PRIMES) {
642 if(i < NR_OF_SQUARE_PRIMES) {
643 if(mpz_cmp_si(n, SQUARE_PRIMES[i]) < 0) break;
644 } else {
645 mpz_ui_pow_ui(p_square, PRIMES[i], 2);
646 if(mpz_cmp(n, p_square) < 0) break;
647 }
648 if(mpz_divisible_ui_p(n, PRIMES[i])) {
649 mpz_divexact_ui(n, n, PRIMES[i]);
650 while(mpz_divisible_ui_p(n, PRIMES[i])) mpz_divexact_ui(n, n, PRIMES[i]);
651 mpz_divexact_ui(tmp, result, PRIMES[i]);
652 mpz_sub(result, result, tmp);
653 }
654 i++;
655 } else {
656 if(i == NR_OF_PRIMES) {mpz_set_si(p, PRIMES[i - 1]); i++;}
657 mpz_add_ui(p, p, 2);
658 mpz_pow_ui(p_square, p, 2);
659 if(mpz_cmp(n, p_square) < 0) break;
660 if(mpz_divisible_p(n, p)) {
661 mpz_divexact(n, n, p);
662 while(mpz_divisible_p(n, p)) mpz_divexact(n, n, p);
663 mpz_divexact(tmp, result, p);
664 mpz_sub(result, result, tmp);
665 }
666 }
667 }
668 if(mpz_cmp_ui(n, 1) > 0) {
669 mpz_divexact(tmp, result, n);
670 mpz_sub(result, result, tmp);
671 }
672 mstruct.clear();
673 mstruct.number().setInternal(result);
674 mpz_clears(n, result, tmp, p, p_square, NULL);
675 return 1;
676 }
677
PolynomialUnitFunction()678 PolynomialUnitFunction::PolynomialUnitFunction() : MathFunction("punit", 1, 2) {
679 RATIONAL_POLYNOMIAL_ARGUMENT(1)
680 setArgumentDefinition(2, new SymbolicArgument());
681 setDefaultValue(2, "undefined");
682 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)683 int PolynomialUnitFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
684 mstruct.set(vargs[0].polynomialUnit(vargs[1]), 0);
685 return 1;
686 }
PolynomialPrimpartFunction()687 PolynomialPrimpartFunction::PolynomialPrimpartFunction() : MathFunction("primpart", 1, 2) {
688 RATIONAL_POLYNOMIAL_ARGUMENT(1)
689 setArgumentDefinition(2, new SymbolicArgument());
690 setDefaultValue(2, "undefined");
691 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)692 int PolynomialPrimpartFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
693 vargs[0].polynomialPrimpart(vargs[1], mstruct, eo);
694 return 1;
695 }
PolynomialContentFunction()696 PolynomialContentFunction::PolynomialContentFunction() : MathFunction("pcontent", 1, 2) {
697 RATIONAL_POLYNOMIAL_ARGUMENT(1)
698 setArgumentDefinition(2, new SymbolicArgument());
699 setDefaultValue(2, "undefined");
700 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)701 int PolynomialContentFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
702 vargs[0].polynomialContent(vargs[1], mstruct, eo);
703 return 1;
704 }
CoeffFunction()705 CoeffFunction::CoeffFunction() : MathFunction("coeff", 2, 3) {
706 RATIONAL_POLYNOMIAL_ARGUMENT(1)
707 setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_NONNEGATIVE));
708 setArgumentDefinition(3, new SymbolicArgument());
709 setDefaultValue(3, "undefined");
710 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)711 int CoeffFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
712 vargs[0].coefficient(vargs[2], vargs[1].number(), mstruct);
713 return 1;
714 }
LCoeffFunction()715 LCoeffFunction::LCoeffFunction() : MathFunction("lcoeff", 1, 2) {
716 RATIONAL_POLYNOMIAL_ARGUMENT(1)
717 setArgumentDefinition(2, new SymbolicArgument());
718 setDefaultValue(2, "undefined");
719 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)720 int LCoeffFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
721 vargs[0].lcoefficient(vargs[1], mstruct);
722 return 1;
723 }
TCoeffFunction()724 TCoeffFunction::TCoeffFunction() : MathFunction("tcoeff", 1, 2) {
725 RATIONAL_POLYNOMIAL_ARGUMENT(1)
726 setArgumentDefinition(2, new SymbolicArgument());
727 setDefaultValue(2, "undefined");
728 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)729 int TCoeffFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
730 vargs[0].tcoefficient(vargs[1], mstruct);
731 return 1;
732 }
DegreeFunction()733 DegreeFunction::DegreeFunction() : MathFunction("degree", 1, 2) {
734 RATIONAL_POLYNOMIAL_ARGUMENT(1)
735 setArgumentDefinition(2, new SymbolicArgument());
736 setDefaultValue(2, "undefined");
737 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)738 int DegreeFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
739 mstruct = vargs[0].degree(vargs[1]);
740 return 1;
741 }
LDegreeFunction()742 LDegreeFunction::LDegreeFunction() : MathFunction("ldegree", 1, 2) {
743 RATIONAL_POLYNOMIAL_ARGUMENT(1)
744 setArgumentDefinition(2, new SymbolicArgument());
745 setDefaultValue(2, "undefined");
746 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)747 int LDegreeFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
748 mstruct = vargs[0].ldegree(vargs[1]);
749 return 1;
750 }
751
752
BinFunction()753 BinFunction::BinFunction() : MathFunction("bin", 1, 2) {
754 setArgumentDefinition(1, new TextArgument());
755 setArgumentDefinition(2, new BooleanArgument());
756 setDefaultValue(2, "0");
757 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)758 int BinFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
759 ParseOptions po = eo.parse_options;
760 po.base = BASE_BINARY;
761 po.twos_complement = vargs[1].number().getBoolean();
762 CALCULATOR->parse(&mstruct, vargs[0].symbol(), po);
763 return 1;
764 }
OctFunction()765 OctFunction::OctFunction() : MathFunction("oct", 1) {
766 setArgumentDefinition(1, new TextArgument());
767 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)768 int OctFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
769 ParseOptions po = eo.parse_options;
770 po.base = BASE_OCTAL;
771 CALCULATOR->parse(&mstruct, vargs[0].symbol(), po);
772 return 1;
773 }
DecFunction()774 DecFunction::DecFunction() : MathFunction("dec", 1) {
775 setArgumentDefinition(1, new TextArgument());
776 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)777 int DecFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
778 ParseOptions po = eo.parse_options;
779 po.base = BASE_DECIMAL;
780 CALCULATOR->parse(&mstruct, vargs[0].symbol(), po);
781 return 1;
782 }
HexFunction()783 HexFunction::HexFunction() : MathFunction("hex", 1, 2) {
784 setArgumentDefinition(1, new TextArgument());
785 setArgumentDefinition(2, new BooleanArgument());
786 setDefaultValue(2, "0");
787 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)788 int HexFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
789 ParseOptions po = eo.parse_options;
790 po.base = BASE_HEXADECIMAL;
791 po.hexadecimal_twos_complement = vargs[1].number().getBoolean();
792 CALCULATOR->parse(&mstruct, vargs[0].symbol(), po);
793 return 1;
794 }
795
BaseFunction()796 BaseFunction::BaseFunction() : MathFunction("base", 2, 3) {
797 setArgumentDefinition(1, new TextArgument());
798 Argument *arg = new Argument();
799 arg->setHandleVector(true);
800 setArgumentDefinition(2, arg);
801 IntegerArgument *arg2 = new IntegerArgument();
802 arg2->setMin(&nr_zero);
803 arg2->setMax(&nr_three);
804 setArgumentDefinition(3, arg2);
805 setArgumentDefinition(3, new TextArgument());
806 setDefaultValue(3, "0");
807 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)808 int BaseFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
809 if(vargs[1].isVector()) return 0;
810 Number nbase;
811 int idigits = 0;
812 string sdigits;
813 if(vargs.size() > 2) sdigits = vargs[2].symbol();
814 if(sdigits.empty() || sdigits == "0" || sdigits == "auto") idigits = 0;
815 else if(sdigits == "1") idigits = 1;
816 else if(sdigits == "2") idigits = 2;
817 else if(sdigits == "3" || sdigits == "Unicode" || sdigits == "unicode" || sdigits == "escaped") idigits = 3;
818 else if(sdigits == "4" || sdigits == _("phoneword")) idigits = 4;
819 else {
820 size_t i = sdigits.find("|");
821 if(i != string::npos && sdigits.find("|", i + 1) != string::npos) {
822 idigits = -4;
823 } else {
824 i = sdigits.find(";");
825 if(i != string::npos && sdigits.find(";", i + 1) != string::npos) {
826 idigits = -3;
827 } else {
828 i = sdigits.find(",");
829 if(i != string::npos && sdigits.find(",", i + 1) != string::npos) idigits = -2;
830 else idigits = -1;
831 }
832 }
833 i = sdigits.find(" ");
834 if(i != string::npos && sdigits.find(" ", i + 1) != string::npos) remove_blanks(sdigits);
835 if(idigits == -2 || idigits == -3) {
836 if((sdigits[0] == LEFT_VECTOR_WRAP_CH && sdigits[sdigits.size() - 1] == RIGHT_VECTOR_WRAP_CH) || (sdigits[0] == LEFT_PARENTHESIS_CH && sdigits[sdigits.size() - 1] == RIGHT_PARENTHESIS_CH)) {
837 sdigits = sdigits.substr(1, sdigits.size() - 2);
838 }
839 }
840 }
841 if(vargs[1].isNumber() && idigits == 0) {
842 nbase = vargs[1].number();
843 } else {
844 mstruct = vargs[1];
845 mstruct.eval(eo);
846 if(mstruct.isVector()) return -2;
847 if(idigits == 0 && !mstruct.isNumber() && eo.approximation == APPROXIMATION_EXACT) {
848 MathStructure mstruct2(mstruct);
849 EvaluationOptions eo2 = eo;
850 eo2.approximation = APPROXIMATION_TRY_EXACT;
851 CALCULATOR->beginTemporaryStopMessages();
852 mstruct2.eval(eo2);
853 if(mstruct2.isVector() || mstruct2.isNumber()) {
854 mstruct = mstruct2;
855 CALCULATOR->endTemporaryStopMessages(true);
856 if(mstruct.isVector()) return -2;
857 } else {
858 CALCULATOR->endTemporaryStopMessages();
859 }
860 }
861 if(mstruct.isNumber() && idigits == 0) {
862 nbase = mstruct.number();
863 } else {
864 string number = vargs[0].symbol();
865 size_t i_dot = number.length();
866 vector<Number> digits;
867 bool b_minus = false;
868 if(idigits < 0) {
869 vector<unordered_map<string, long int>> vdigits;
870 string schar;
871 long int v = 0;
872 size_t d_i = 0;
873 for(size_t i = 0; i < sdigits.length();) {
874 if((idigits == -2 && sdigits[i] == ',') || (idigits == -3 && sdigits[i] == ';') || (idigits == -4 && sdigits[i] == '|')) {
875 d_i = 0; v++; i++;
876 } else {
877 size_t l = 1;
878 while(i + l < sdigits.length() && sdigits[i + l] <= 0 && (unsigned char) sdigits[i + l] < 0xC0) l++;
879 if(d_i == vdigits.size()) vdigits.resize(d_i + 1);
880 vdigits[d_i][sdigits.substr(i, l)] = v;
881 i += l;
882 if(idigits < -1) d_i++;
883 else v++;
884 }
885 }
886 i_dot = number.length();
887 for(size_t i = 0; i < number.length();) {
888 size_t l = 1;
889 while(i + l < number.length() && number[i + l] <= 0 && (unsigned char) number[i + l] < 0xC0) l++;
890 for(d_i = 0; d_i < vdigits.size(); d_i++) {
891 unordered_map<string, long int>::iterator it = vdigits[d_i].find(number.substr(i, l));
892 if(it != vdigits[d_i].end()) {
893 digits.push_back(it->second);
894 break;
895 }
896 }
897 if(d_i == vdigits.size()) {
898 if(l == 1 && (number[i] == CALCULATOR->getDecimalPoint()[0] || (!eo.parse_options.dot_as_separator && number[i] == '.'))) {
899 if(i_dot == number.length()) i_dot = digits.size();
900 } else if(!is_in(SPACES, number[i])) {
901 CALCULATOR->error(true, _("Character \'%s\' was ignored in the number \"%s\" with base %s."), number.substr(i, l).c_str(), number.c_str(), format_and_print(mstruct).c_str(), NULL);
902 }
903 }
904 i += l;
905 }
906 } else if(idigits == 4 || idigits == 5) {
907 for(size_t i = 0; i < number.length();) {
908 size_t l = 1;
909 while(i + l < number.length() && number[i + l] <= 0 && (unsigned char) number[i + l] < 0xC0) l++;
910 char c = 0;
911 if(l == 1) {
912 c = number[i];
913 } else if(l == 2 && number[i] == -61) {
914 if(number[i + 1] >= -128 && number[i + 1] <= -122) c = 'A';
915 else if(number[i + 1] == -121) c = 'C';
916 else if(number[i + 1] >= -120 && number[i + 1] <= -117) c = 'E';
917 else if(number[i + 1] >= -116 && number[i + 1] <= -113) c = 'I';
918 //else if(number[i + 1] == -112) c = 'D';
919 else if(number[i + 1] == -111) c = 'N';
920 else if(number[i + 1] >= -110 && number[i + 1] <= -106) c = 'O';
921 else if(number[i + 1] == -104) c = 'O';
922 else if(number[i + 1] >= -103 && number[i + 1] <= -100) c = 'U';
923 else if(number[i + 1] == -99) c = 'Y';
924 //else if(number[i + 1] == -98) c = 'T';
925 else if(number[i + 1] == -97) c = 'S';
926 else if(number[i + 1] >= -96 && number[i + 1] <= -90) c = 'a';
927 else if(number[i + 1] == -89) c = 'c';
928 else if(number[i + 1] >= -88 && number[i + 1] <= -85) c = 'e';
929 else if(number[i + 1] >= -84 && number[i + 1] <= -81) c = 'i';
930 //else if(number[i + 1] == -80) c = 'd';
931 else if(number[i + 1] == -79) c = 'n';
932 else if(number[i + 1] >= -78 && number[i + 1] <= -74) c = 'o';
933 else if(number[i + 1] == -72) c = 'o';
934 else if(number[i + 1] >= -71 && number[i + 1] <= -68) c = 'u';
935 else if(number[i + 1] == -67) c = 'y';
936 //else if(number[i + 1] == -66) c = 't';
937 else if(number[i + 1] == -65) c = 'y';
938 }
939 if(c != 0) {
940 if(c == '0') digits.push_back(0);
941 else if(c == '1') digits.push_back(1);
942 else if(is_in("2abcABC", c)) digits.push_back(2);
943 else if(is_in("3defDEF", c)) digits.push_back(3);
944 else if(is_in("4ghiGHI", c)) digits.push_back(4);
945 else if(is_in("5jklJKL", c)) digits.push_back(5);
946 else if(is_in("6mnoMNO", c)) digits.push_back(6);
947 else if(is_in("7pqrsPQRS", c)) digits.push_back(7);
948 else if(is_in("8tuvTUV", c)) digits.push_back(8);
949 else if(is_in("9wxyzWXYZ", c)) digits.push_back(9);
950 }
951 i += l;
952 }
953 } else if(idigits <= 2) {
954 remove_blanks(number);
955 bool b_case = (idigits == 2);
956 i_dot = number.length();
957 for(size_t i = 0; i < number.length(); i++) {
958 long int c = -1;
959 if(number[i] >= '0' && number[i] <= '9') {
960 c = number[i] - '0';
961 } else if(number[i] >= 'a' && number[i] <= 'z') {
962 if(b_case) c = number[i] - 'a' + 36;
963 else c = number[i] - 'a' + 10;
964 } else if(number[i] >= 'A' && number[i] <= 'Z') {
965 c = number[i] - 'A' + 10;
966 } else if(number[i] == CALCULATOR->getDecimalPoint()[0] || (!eo.parse_options.dot_as_separator && number[i] == '.')) {
967 if(i_dot == number.length()) i_dot = digits.size();
968 } else if(number[i] == '-' && digits.empty()) {
969 b_minus = !b_minus;
970 } else {
971 string str_char = number.substr(i, 1);
972 while(i + 1 < number.length() && number[i + 1] < 0 && number[i + 1] && (unsigned char) number[i + 1] < 0xC0) {
973 i++;
974 str_char += number[i];
975 }
976 CALCULATOR->error(true, _("Character \'%s\' was ignored in the number \"%s\" with base %s."), str_char.c_str(), number.c_str(), format_and_print(mstruct).c_str(), NULL);
977 }
978 if(c >= 0) {
979 digits.push_back(c);
980 }
981 }
982 } else {
983 for(size_t i = 0; i < number.length(); i++) {
984 long int c = (unsigned char) number[i];
985 bool b_esc = false;
986 if(number[i] == '\\' && i < number.length() - 1) {
987 i++;
988 Number nrd;
989 if(is_in(NUMBERS, number[i])) {
990 size_t i2 = number.find_first_not_of(NUMBERS, i);
991 if(i2 == string::npos) i2 = number.length();
992 nrd.set(number.substr(i, i2 - i));
993 i = i2 - 1;
994 b_esc = true;
995 } else if(number[i] == 'x' && i < number.length() - 1 && is_in(NUMBERS "ABCDEFabcdef", number[i + 1])) {
996 i++;
997 size_t i2 = number.find_first_not_of(NUMBERS "ABCDEFabcdef", i);
998 if(i2 == string::npos) i2 = number.length();
999 ParseOptions po;
1000 po.base = BASE_HEXADECIMAL;
1001 nrd.set(number.substr(i, i2 - i), po);
1002 i = i2 - 1;
1003 b_esc = true;
1004 }
1005 if(digits.empty() && number[i] == (char) -30 && i + 3 < number.length() && number[i + 1] == (char) -120 && number[i + 2] == (char) -110) {
1006 i += 2;
1007 b_minus = !b_minus;
1008 b_esc = true;
1009 } else if(digits.empty() && number[i] == '-') {
1010 b_minus = !b_minus;
1011 b_esc = true;
1012 } else if(i_dot == number.size() && (number[i] == CALCULATOR->getDecimalPoint()[0] || (!eo.parse_options.dot_as_separator && number[i] == '.'))) {
1013 i_dot = digits.size();
1014 b_esc = true;
1015 } else if(b_esc) {
1016 digits.push_back(nrd);
1017
1018 } else if(number[i] != '\\') {
1019 i--;
1020 }
1021 }
1022 if(!b_esc) {
1023 if((c & 0x80) != 0) {
1024 if(c<0xe0) {
1025 i++;
1026 if(i >= number.length()) return -2;
1027 c = ((c & 0x1f) << 6) | (((unsigned char) number[i]) & 0x3f);
1028 } else if(c<0xf0) {
1029 i++;
1030 if(i + 1 >= number.length()) return -2;
1031 c = (((c & 0xf) << 12) | ((((unsigned char) number[i]) & 0x3f) << 6)|(((unsigned char) number[i + 1]) & 0x3f));
1032 i++;
1033 } else {
1034 i++;
1035 if(i + 2 >= number.length()) return -2;
1036 c = ((c & 7) << 18) | ((((unsigned char) number[i]) & 0x3f) << 12) | ((((unsigned char) number[i + 1]) & 0x3f) << 6) | (((unsigned char) number[i + 2]) & 0x3f);
1037 i += 2;
1038 }
1039 }
1040 digits.push_back(c);
1041 }
1042 }
1043 }
1044 MathStructure mbase = mstruct;
1045 mstruct.clear();
1046 if(i_dot > digits.size()) i_dot = digits.size();
1047 for(size_t i = 0; i < digits.size(); i++) {
1048 long int exp = i_dot - 1 - i;
1049 MathStructure m;
1050 if(exp != 0) {
1051 m = mbase;
1052 m.raise(Number(exp, 1));
1053 m.multiply(digits[i]);
1054 } else {
1055 m.set(digits[i]);
1056 }
1057 if(mstruct.isZero()) mstruct = m;
1058 else mstruct.add(m, true);
1059 }
1060 if(b_minus) mstruct.negate();
1061 return 1;
1062 }
1063 }
1064 ParseOptions po = eo.parse_options;
1065 if(nbase.isInteger() && nbase >= 2 && nbase <= 36) {
1066 po.base = nbase.intValue();
1067 CALCULATOR->parse(&mstruct, vargs[0].symbol(), po);
1068 } else {
1069 po.base = BASE_CUSTOM;
1070 Number cb_save = CALCULATOR->customInputBase();
1071 CALCULATOR->setCustomInputBase(nbase);
1072 CALCULATOR->parse(&mstruct, vargs[0].symbol(), po);
1073 CALCULATOR->setCustomInputBase(cb_save);
1074 }
1075 return 1;
1076 }
RomanFunction()1077 RomanFunction::RomanFunction() : MathFunction("roman", 1) {
1078 setArgumentDefinition(1, new TextArgument());
1079 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)1080 int RomanFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
1081 if(vargs[0].symbol().find_first_not_of("0123456789.:" SIGNS) == string::npos && vargs[0].symbol().find_first_not_of("0" SIGNS) != string::npos) {
1082 CALCULATOR->parse(&mstruct, vargs[0].symbol(), eo.parse_options);
1083 PrintOptions po; po.base = BASE_ROMAN_NUMERALS;
1084 mstruct.eval(eo);
1085 mstruct.set(mstruct.print(po), true, true);
1086 return 1;
1087 }
1088 ParseOptions po = eo.parse_options;
1089 po.base = BASE_ROMAN_NUMERALS;
1090 CALCULATOR->parse(&mstruct, vargs[0].symbol(), po);
1091 return 1;
1092 }
BijectiveFunction()1093 BijectiveFunction::BijectiveFunction() : MathFunction("bijective", 1) {
1094 setArgumentDefinition(1, new TextArgument());
1095 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)1096 int BijectiveFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
1097 if(vargs[0].symbol().find_first_not_of("0123456789.:" SIGNS) == string::npos && vargs[0].symbol().find_first_not_of(SIGNS) != string::npos) {
1098 CALCULATOR->parse(&mstruct, vargs[0].symbol(), eo.parse_options);
1099 PrintOptions po; po.base = BASE_BIJECTIVE_26;
1100 mstruct.eval(eo);
1101 mstruct.set(mstruct.print(po), true, true);
1102 return 1;
1103 }
1104 ParseOptions po = eo.parse_options;
1105 po.base = BASE_BIJECTIVE_26;
1106 CALCULATOR->parse(&mstruct, vargs[0].symbol(), po);
1107 return 1;
1108 }
ImFunction()1109 ImFunction::ImFunction() : MathFunction("im", 1) {
1110 Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false);
1111 arg->setHandleVector(true);
1112 setArgumentDefinition(1, arg);
1113 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)1114 int ImFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
1115 if(vargs[0].isVector()) return 0;
1116 mstruct = vargs[0];
1117 mstruct.eval(eo);
1118 if(mstruct.isVector()) return -1;
1119 if(mstruct.isNumber()) {
1120 mstruct = mstruct.number().imaginaryPart();
1121 return 1;
1122 } else if(mstruct.representsReal(!eo.keep_zero_units)) {
1123 mstruct.clear(true);
1124 return 1;
1125 } else if(mstruct.isUnit_exp()) {
1126 mstruct *= m_zero;
1127 mstruct.swapChildren(1, 2);
1128 return 1;
1129 } else if(mstruct.isPower() && mstruct[1].isNumber() && mstruct[1].number().denominatorIsTwo() && mstruct[0].representsNegative()) {
1130 mstruct[0].negate();
1131 Number num = mstruct[1].number().numerator();
1132 num.rem(4);
1133 if(num == 3 || num == -1) mstruct.negate();
1134 return 1;
1135 } else if(mstruct.isMultiplication() && mstruct.size() > 0) {
1136 if(mstruct[0].isNumber()) {
1137 Number nr = mstruct[0].number();
1138 mstruct.delChild(1, true);
1139 if(nr.hasImaginaryPart()) {
1140 if(nr.hasRealPart()) {
1141 MathStructure *madd = new MathStructure(mstruct);
1142 mstruct.transformById(FUNCTION_ID_RE);
1143 madd->transform(this);
1144 madd->multiply(nr.realPart());
1145 mstruct.multiply(nr.imaginaryPart());
1146 mstruct.add_nocopy(madd);
1147 return 1;
1148 }
1149 mstruct.transformById(FUNCTION_ID_RE);
1150 mstruct.multiply(nr.imaginaryPart());
1151 return 1;
1152 }
1153 mstruct.transform(this);
1154 mstruct.multiply(nr.realPart());
1155 return 1;
1156 }
1157 MathStructure *mreal = NULL;
1158 for(size_t i = 0; i < mstruct.size();) {
1159 if(mstruct[i].representsReal(true)) {
1160 if(!mreal) {
1161 mreal = new MathStructure(mstruct[i]);
1162 } else {
1163 mstruct[i].ref();
1164 if(!mreal->isMultiplication()) mreal->transform(STRUCT_MULTIPLICATION);
1165 mreal->addChild_nocopy(&mstruct[i]);
1166 }
1167 mstruct.delChild(i + 1);
1168 } else {
1169 i++;
1170 }
1171 }
1172 if(mreal) {
1173 if(mstruct.size() == 0) mstruct.clear(true);
1174 else if(mstruct.size() == 1) mstruct.setToChild(1, true);
1175 mstruct.transform(this);
1176 mstruct.multiply_nocopy(mreal);
1177 return 1;
1178 }
1179 }
1180 return -1;
1181 }
representsPositive(const MathStructure &,bool) const1182 bool ImFunction::representsPositive(const MathStructure&, bool) const {return false;}
representsNegative(const MathStructure &,bool) const1183 bool ImFunction::representsNegative(const MathStructure&, bool) const {return false;}
representsNonNegative(const MathStructure & vargs,bool) const1184 bool ImFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsNonPositive(const MathStructure & vargs,bool) const1185 bool ImFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsInteger(const MathStructure & vargs,bool) const1186 bool ImFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsNumber(const MathStructure & vargs,bool) const1187 bool ImFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();}
representsRational(const MathStructure & vargs,bool) const1188 bool ImFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsReal(const MathStructure & vargs,bool) const1189 bool ImFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();}
representsNonComplex(const MathStructure & vargs,bool) const1190 bool ImFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;}
representsComplex(const MathStructure &,bool) const1191 bool ImFunction::representsComplex(const MathStructure&, bool) const {return false;}
representsNonZero(const MathStructure & vargs,bool) const1192 bool ImFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsComplex();}
representsEven(const MathStructure & vargs,bool) const1193 bool ImFunction::representsEven(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsOdd(const MathStructure &,bool) const1194 bool ImFunction::representsOdd(const MathStructure&, bool) const {return false;}
representsUndefined(const MathStructure &) const1195 bool ImFunction::representsUndefined(const MathStructure&) const {return false;}
1196
ReFunction()1197 ReFunction::ReFunction() : MathFunction("re", 1) {
1198 Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false);
1199 arg->setHandleVector(true);
1200 setArgumentDefinition(1, arg);
1201 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)1202 int ReFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
1203 if(vargs[0].isVector()) return 0;
1204 mstruct = vargs[0];
1205 mstruct.eval(eo);
1206 if(mstruct.isVector()) return -1;
1207 if(mstruct.isNumber()) {
1208 mstruct = mstruct.number().realPart();
1209 return 1;
1210 } else if(mstruct.representsReal(true)) {
1211 return 1;
1212 } else if(mstruct.isPower() && mstruct[1].isNumber() && mstruct[1].number().denominatorIsTwo() && mstruct[0].representsNegative()) {
1213 mstruct.clear(true);
1214 return 1;
1215 } else if(mstruct.isMultiplication() && mstruct.size() > 0) {
1216 if(mstruct[0].isNumber()) {
1217 Number nr = mstruct[0].number();
1218 mstruct.delChild(1, true);
1219 if(nr.hasImaginaryPart()) {
1220 if(nr.hasRealPart()) {
1221 MathStructure *madd = new MathStructure(mstruct);
1222 mstruct.transformById(FUNCTION_ID_IM);
1223 madd->transform(this);
1224 madd->multiply(nr.realPart());
1225 mstruct.multiply(-nr.imaginaryPart());
1226 mstruct.add_nocopy(madd);
1227 return 1;
1228 }
1229 mstruct.transformById(FUNCTION_ID_IM);
1230 mstruct.multiply(-nr.imaginaryPart());
1231 return 1;
1232 }
1233 mstruct.transform(this);
1234 mstruct.multiply(nr.realPart());
1235 return 1;
1236 }
1237 MathStructure *mreal = NULL;
1238 for(size_t i = 0; i < mstruct.size();) {
1239 if(mstruct[i].representsReal(true)) {
1240 if(!mreal) {
1241 mreal = new MathStructure(mstruct[i]);
1242 } else {
1243 mstruct[i].ref();
1244 if(!mreal->isMultiplication()) mreal->transform(STRUCT_MULTIPLICATION);
1245 mreal->addChild_nocopy(&mstruct[i]);
1246 }
1247 mstruct.delChild(i + 1);
1248 } else {
1249 i++;
1250 }
1251 }
1252 if(mreal) {
1253 if(mstruct.size() == 0) mstruct.clear(true);
1254 else if(mstruct.size() == 1) mstruct.setToChild(1, true);
1255 mstruct.transform(this);
1256 mstruct.multiply_nocopy(mreal);
1257 return 1;
1258 }
1259 }
1260 return -1;
1261 }
representsPositive(const MathStructure & vargs,bool allow_units) const1262 bool ReFunction::representsPositive(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsPositive(allow_units);}
representsNegative(const MathStructure & vargs,bool allow_units) const1263 bool ReFunction::representsNegative(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNegative(allow_units);}
representsNonNegative(const MathStructure & vargs,bool allow_units) const1264 bool ReFunction::representsNonNegative(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNonNegative(allow_units);}
representsNonPositive(const MathStructure & vargs,bool allow_units) const1265 bool ReFunction::representsNonPositive(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNonPositive(allow_units);}
representsInteger(const MathStructure & vargs,bool allow_units) const1266 bool ReFunction::representsInteger(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsInteger(allow_units);}
representsNumber(const MathStructure & vargs,bool allow_units) const1267 bool ReFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);}
representsRational(const MathStructure & vargs,bool allow_units) const1268 bool ReFunction::representsRational(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsRational(allow_units);}
representsReal(const MathStructure & vargs,bool allow_units) const1269 bool ReFunction::representsReal(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);}
representsNonComplex(const MathStructure & vargs,bool) const1270 bool ReFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;}
representsComplex(const MathStructure &,bool) const1271 bool ReFunction::representsComplex(const MathStructure&, bool) const {return false;}
representsNonZero(const MathStructure & vargs,bool allow_units) const1272 bool ReFunction::representsNonZero(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsReal(allow_units) && vargs[0].representsNonZero(true);}
representsEven(const MathStructure & vargs,bool allow_units) const1273 bool ReFunction::representsEven(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsEven(allow_units);}
representsOdd(const MathStructure & vargs,bool allow_units) const1274 bool ReFunction::representsOdd(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsOdd(allow_units);}
representsUndefined(const MathStructure &) const1275 bool ReFunction::representsUndefined(const MathStructure&) const {return false;}
1276
ArgFunction()1277 ArgFunction::ArgFunction() : MathFunction("arg", 1) {
1278 Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false);
1279 arg->setHandleVector(true);
1280 setArgumentDefinition(1, arg);
1281 }
representsNumber(const MathStructure & vargs,bool) const1282 bool ArgFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber(true);}
representsReal(const MathStructure & vargs,bool) const1283 bool ArgFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber(true);}
representsNonComplex(const MathStructure & vargs,bool) const1284 bool ArgFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)1285 int ArgFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
1286 if(vargs[0].isVector()) return 0;
1287 mstruct = vargs[0];
1288 mstruct.eval(eo);
1289 if(mstruct.isVector()) return -1;
1290
1291 MathStructure msave;
1292
1293 arg_test_non_number:
1294 if(!mstruct.isNumber()) {
1295 if(mstruct.representsPositive(true)) {
1296 mstruct.clear();
1297 return 1;
1298 }
1299 if(mstruct.representsNegative(true)) {
1300 switch(eo.parse_options.angle_unit) {
1301 case ANGLE_UNIT_DEGREES: {mstruct.set(180, 1, 0); break;}
1302 case ANGLE_UNIT_GRADIANS: {mstruct.set(200, 1, 0); break;}
1303 case ANGLE_UNIT_RADIANS: {mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); break;}
1304 default: {mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();}
1305 }
1306 return 1;
1307 }
1308 if(!msave.isZero()) {
1309 mstruct = msave;
1310 return -1;
1311 }
1312 if(mstruct.isMultiplication()) {
1313 bool b = false;
1314 for(size_t i = 0; i < mstruct.size();) {
1315 if(mstruct[i].representsPositive()) {
1316 mstruct.delChild(i + 1);
1317 b = true;
1318 } else {
1319 if(!mstruct[i].isMinusOne() && mstruct[i].representsNegative()) {
1320 mstruct[i].set(-1, 1, 0, true);
1321 b = true;
1322 }
1323 i++;
1324 }
1325 }
1326 if(b) {
1327 if(mstruct.size() == 1) {
1328 mstruct.setToChild(1);
1329 } else if(mstruct.size() == 0) {
1330 mstruct.clear(true);
1331 }
1332 mstruct.transform(STRUCT_FUNCTION);
1333 mstruct.setFunction(this);
1334 return 1;
1335 }
1336 }
1337 if(mstruct.isPower() && mstruct[0].representsComplex() && mstruct[1].representsInteger()) {
1338 mstruct.setType(STRUCT_MULTIPLICATION);
1339 mstruct[0].transform(STRUCT_FUNCTION);
1340 mstruct[0].setFunction(this);
1341 return 1;
1342 }
1343 if(mstruct.isPower() && mstruct[0].isVariable() && mstruct[0].variable()->id() == VARIABLE_ID_E && mstruct[1].isNumber() && mstruct[1].number().hasImaginaryPart() && !mstruct[1].number().hasRealPart()) {
1344 CALCULATOR->beginTemporaryEnableIntervalArithmetic();
1345 if(CALCULATOR->usesIntervalArithmetic()) {
1346 CALCULATOR->beginTemporaryStopMessages();
1347 Number nr(*mstruct[1].number().internalImaginary());
1348 Number nrpi; nrpi.pi();
1349 nr.add(nrpi);
1350 nr.divide(nrpi);
1351 nr.divide(2);
1352 Number nr_u(nr.upperEndPoint());
1353 nr = nr.lowerEndPoint();
1354 nr_u.floor();
1355 nr.floor();
1356 if(!CALCULATOR->endTemporaryStopMessages() && nr == nr_u) {
1357 CALCULATOR->endTemporaryEnableIntervalArithmetic();
1358 nr.setApproximate(false);
1359 nr *= 2;
1360 nr.negate();
1361 mstruct = mstruct[1].number().imaginaryPart();
1362 if(!nr.isZero()) {
1363 mstruct += nr;
1364 mstruct.last() *= CALCULATOR->getVariableById(VARIABLE_ID_PI);
1365 }
1366 return true;
1367 }
1368 }
1369 CALCULATOR->endTemporaryEnableIntervalArithmetic();
1370 }
1371 if(eo.approximation == APPROXIMATION_EXACT) {
1372 msave = mstruct;
1373 if(!test_eval(mstruct, eo)) {
1374 mstruct = msave;
1375 return -1;
1376 }
1377 }
1378 }
1379 if(mstruct.isNumber()) {
1380 if(!mstruct.number().hasImaginaryPart()) {
1381 if(!mstruct.number().isNonZero()) {
1382 if(!msave.isZero()) mstruct = msave;
1383 return -1;
1384 }
1385 if(mstruct.number().isNegative()) {
1386 switch(eo.parse_options.angle_unit) {
1387 case ANGLE_UNIT_DEGREES: {mstruct.set(180, 1, 0); break;}
1388 case ANGLE_UNIT_GRADIANS: {mstruct.set(200, 1, 0); break;}
1389 case ANGLE_UNIT_RADIANS: {mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); break;}
1390 default: {mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();}
1391 }
1392 } else {
1393 mstruct.clear();
1394 }
1395 } else if(!mstruct.number().hasRealPart() && mstruct.number().imaginaryPartIsNonZero()) {
1396 bool b_neg = mstruct.number().imaginaryPartIsNegative();
1397 switch(eo.parse_options.angle_unit) {
1398 case ANGLE_UNIT_DEGREES: {mstruct.set(90, 1, 0); break;}
1399 case ANGLE_UNIT_GRADIANS: {mstruct.set(100, 1, 0); break;}
1400 case ANGLE_UNIT_RADIANS: {mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); mstruct.multiply(nr_half); break;}
1401 default: {mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); mstruct.multiply(nr_half); if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();}
1402 }
1403 if(b_neg) mstruct.negate();
1404 } else if(!msave.isZero()) {
1405 mstruct = msave;
1406 return -1;
1407 } else if(!mstruct.number().realPartIsNonZero()) {
1408 FR_FUNCTION(arg)
1409 } else {
1410 MathStructure new_nr(mstruct.number().imaginaryPart());
1411 if(!new_nr.number().divide(mstruct.number().realPart())) return -1;
1412 if(mstruct.number().realPartIsNegative()) {
1413 if(mstruct.number().imaginaryPartIsNegative()) {
1414 mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_ATAN), &new_nr, NULL);
1415 switch(eo.parse_options.angle_unit) {
1416 case ANGLE_UNIT_DEGREES: {mstruct.add(-180); break;}
1417 case ANGLE_UNIT_GRADIANS: {mstruct.add(-200); break;}
1418 case ANGLE_UNIT_RADIANS: {mstruct.subtract(CALCULATOR->getVariableById(VARIABLE_ID_PI)); break;}
1419 default: {MathStructure msub(CALCULATOR->getVariableById(VARIABLE_ID_PI)); if(CALCULATOR->getRadUnit()) msub *= CALCULATOR->getRadUnit(); mstruct.subtract(msub);}
1420 }
1421 } else if(mstruct.number().imaginaryPartIsNonNegative()) {
1422 mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_ATAN), &new_nr, NULL);
1423 switch(eo.parse_options.angle_unit) {
1424 case ANGLE_UNIT_DEGREES: {mstruct.add(180); break;}
1425 case ANGLE_UNIT_GRADIANS: {mstruct.add(200); break;}
1426 case ANGLE_UNIT_RADIANS: {mstruct.add(CALCULATOR->getVariableById(VARIABLE_ID_PI)); break;}
1427 default: {MathStructure madd(CALCULATOR->getVariableById(VARIABLE_ID_PI)); if(CALCULATOR->getRadUnit()) madd *= CALCULATOR->getRadUnit(); mstruct.add(madd);}
1428 }
1429 } else {
1430 FR_FUNCTION(arg)
1431 }
1432 } else {
1433 mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_ATAN), &new_nr, NULL);
1434 }
1435 }
1436 return 1;
1437 }
1438 if(!msave.isZero()) {
1439 goto arg_test_non_number;
1440 }
1441 return -1;
1442 }
1443
IsNumberFunction()1444 IsNumberFunction::IsNumberFunction() : MathFunction("isNumber", 1) {
1445 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)1446 int IsNumberFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
1447 mstruct = vargs[0];
1448 if(!mstruct.isNumber()) mstruct.eval(eo);
1449 if(mstruct.isNumber()) {
1450 mstruct.number().setTrue();
1451 } else {
1452 mstruct.clear();
1453 mstruct.number().setFalse();
1454 }
1455 return 1;
1456 }
1457
1458 #define IS_NUMBER_FUNCTION(x, y) x::x() : MathFunction(#y, 1) {} int x::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {mstruct = vargs[0]; if(!mstruct.isNumber()) mstruct.eval(eo); if(mstruct.isNumber() && mstruct.number().y()) {mstruct.number().setTrue();} else {mstruct.clear(); mstruct.number().setFalse();} return 1;}
1459
IS_NUMBER_FUNCTION(IsIntegerFunction,isInteger)1460 IS_NUMBER_FUNCTION(IsIntegerFunction, isInteger)
1461 IS_NUMBER_FUNCTION(IsRealFunction, isReal)
1462 IS_NUMBER_FUNCTION(IsRationalFunction, isRational)
1463
1464 IEEE754FloatFunction::IEEE754FloatFunction() : MathFunction("float", 1, 3) {
1465 Argument *arg = new TextArgument();
1466 arg->setHandleVector(true);
1467 setArgumentDefinition(1, arg);
1468 IntegerArgument *iarg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_ULONG);
1469 Number nmin(8, 1);
1470 iarg->setMin(&nmin);
1471 setArgumentDefinition(2, iarg);
1472 setDefaultValue(2, "32");
1473 setArgumentDefinition(3, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_ULONG));
1474 setDefaultValue(3, "0");
1475 setCondition("\\z<\\y-1");
1476 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)1477 int IEEE754FloatFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
1478 string sbin = vargs[0].symbol();
1479 unsigned int bits = vargs[1].number().uintValue();
1480 unsigned int expbits = vargs[2].number().uintValue();
1481 remove_blanks(sbin);
1482 if(sbin.find_first_not_of("01") != string::npos) {
1483 MathStructure m;
1484 CALCULATOR->parse(&m, vargs[0].symbol(), eo.parse_options);
1485 m.eval(eo);
1486 if(!m.isInteger() || !m.number().isNonNegative()) return 0;
1487 PrintOptions po;
1488 po.base = BASE_BINARY;
1489 po.twos_complement = false;
1490 po.binary_bits = bits;
1491 po.min_exp = 0;
1492 po.base_display = BASE_DISPLAY_NONE;
1493 sbin = m.print(po);
1494 remove_blanks(sbin);
1495 }
1496 Number nr;
1497 int ret = from_float(nr, sbin, bits, expbits);
1498 if(ret == 0) return 0;
1499 if(ret < 0) mstruct.setUndefined();
1500 else mstruct = nr;
1501 return 1;
1502 }
IEEE754FloatBitsFunction()1503 IEEE754FloatBitsFunction::IEEE754FloatBitsFunction() : MathFunction("floatBits", 1, 3) {
1504 NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, true);
1505 arg->setComplexAllowed(false);
1506 arg->setHandleVector(true);
1507 setArgumentDefinition(1, arg);
1508 IntegerArgument *iarg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_ULONG);
1509 Number nmin(8, 1);
1510 iarg->setMin(&nmin);
1511 setArgumentDefinition(2, iarg);
1512 setDefaultValue(2, "32");
1513 setArgumentDefinition(3, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_ULONG));
1514 setDefaultValue(3, "0");
1515 setCondition("\\z<\\y-1");
1516 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)1517 int IEEE754FloatBitsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
1518 unsigned int bits = vargs[1].number().uintValue();
1519 unsigned int expbits = vargs[2].number().uintValue();
1520 string sbin = to_float(vargs[0].number(), bits, expbits);
1521 if(sbin.empty()) return 0;
1522 ParseOptions pa;
1523 pa.base = BASE_BINARY;
1524 Number nr(sbin, pa);
1525 if(nr.isInfinite() && !vargs[0].number().isInfinite()) CALCULATOR->error(false, _("Floating point overflow"), NULL);
1526 else if(nr.isZero() && !vargs[0].isZero()) CALCULATOR->error(false, _("Floating point underflow"), NULL);
1527 mstruct = nr;
1528 return 1;
1529 }
IEEE754FloatComponentsFunction()1530 IEEE754FloatComponentsFunction::IEEE754FloatComponentsFunction() : MathFunction("floatParts", 1, 3) {
1531 NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, true);
1532 arg->setComplexAllowed(false);
1533 arg->setHandleVector(true);
1534 setArgumentDefinition(1, arg);
1535 IntegerArgument *iarg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_ULONG);
1536 Number nmin(8, 1);
1537 iarg->setMin(&nmin);
1538 setArgumentDefinition(2, iarg);
1539 setDefaultValue(2, "32");
1540 setArgumentDefinition(3, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_ULONG));
1541 setDefaultValue(3, "0");
1542 setCondition("\\z<\\y-1");
1543 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)1544 int IEEE754FloatComponentsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
1545 unsigned int bits = vargs[1].number().uintValue();
1546 unsigned int expbits = vargs[2].number().uintValue();
1547 if(expbits == 0) expbits = standard_expbits(bits);
1548 string sbin = to_float(vargs[0].number(), bits, expbits);
1549 if(sbin.empty()) return 0;
1550 Number sign, exponent, significand;
1551 if(sbin[0] == '0') sign = 1;
1552 else sign = -1;
1553 ParseOptions pa;
1554 pa.base = BASE_BINARY;
1555 exponent.set(sbin.substr(1, expbits), pa);
1556 Number expbias(2);
1557 expbias ^= (expbits - 1);
1558 expbias--;
1559 bool subnormal = exponent.isZero();
1560 exponent -= expbias;
1561 if(exponent > expbias) return 0;
1562 if(subnormal) exponent++;
1563 if(subnormal) significand.set(string("0.") + sbin.substr(1 + expbits), pa);
1564 else significand.set(string("1.") + sbin.substr(1 + expbits), pa);
1565 if(subnormal && significand.isZero()) exponent.clear();
1566 mstruct.clearVector();
1567 mstruct.addChild(sign);
1568 mstruct.addChild(exponent);
1569 mstruct.addChild(significand);
1570 return 1;
1571 }
IEEE754FloatValueFunction()1572 IEEE754FloatValueFunction::IEEE754FloatValueFunction() : MathFunction("floatValue", 1, 3) {
1573 NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, true);
1574 arg->setComplexAllowed(false);
1575 arg->setHandleVector(true);
1576 setArgumentDefinition(1, arg);
1577 IntegerArgument *iarg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_ULONG);
1578 Number nmin(8, 1);
1579 iarg->setMin(&nmin);
1580 setArgumentDefinition(2, iarg);
1581 setDefaultValue(2, "32");
1582 setArgumentDefinition(3, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_ULONG));
1583 setDefaultValue(3, "0");
1584 setCondition("\\z<\\y-1");
1585 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)1586 int IEEE754FloatValueFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
1587 unsigned int bits = vargs[1].number().uintValue();
1588 unsigned int expbits = vargs[2].number().uintValue();
1589 string sbin = to_float(vargs[0].number(), bits, expbits);
1590 if(sbin.empty()) return 0;
1591 Number nr;
1592 int ret = from_float(nr, sbin, bits, expbits);
1593 if(ret == 0) mstruct.setUndefined();
1594 else mstruct = nr;
1595 return 1;
1596 }
IEEE754FloatErrorFunction()1597 IEEE754FloatErrorFunction::IEEE754FloatErrorFunction() : MathFunction("floatError", 1, 3) {
1598 NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, true);
1599 arg->setComplexAllowed(false);
1600 arg->setHandleVector(true);
1601 setArgumentDefinition(1, arg);
1602 IntegerArgument *iarg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_ULONG);
1603 Number nmin(8, 1);
1604 iarg->setMin(&nmin);
1605 setArgumentDefinition(2, iarg);
1606 setDefaultValue(2, "32");
1607 setArgumentDefinition(3, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_ULONG));
1608 setDefaultValue(3, "0");
1609 setCondition("\\z<\\y-1");
1610 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)1611 int IEEE754FloatErrorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
1612 unsigned int bits = vargs[1].number().uintValue();
1613 unsigned int expbits = vargs[2].number().uintValue();
1614 string sbin = to_float(vargs[0].number(), bits, expbits);
1615 if(sbin.empty()) return 0;
1616 Number nr;
1617 int ret = from_float(nr, sbin, bits, expbits);
1618 if(ret == 0) return 0;
1619 if(ret < 0 || (vargs[0].number().isInfinite() && nr.isInfinite())) {
1620 mstruct.clear();
1621 } else {
1622 nr -= vargs[0].number();
1623 nr.abs();
1624 mstruct = nr;
1625 }
1626 return 1;
1627 }
1628
1629