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(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;}
35 #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;}
36 #define FR_FUNCTION_2R(FUNC) Number nr(vargs[1].number()); if(!nr.FUNC(vargs[0].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;}
37 #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);
38
has_interval_unknowns(MathStructure & m)39 bool has_interval_unknowns(MathStructure &m) {
40 if(m.isVariable() && !m.variable()->isKnown()) {
41 Assumptions *ass = ((UnknownVariable*) m.variable())->assumptions();
42 return !((UnknownVariable*) m.variable())->interval().isUndefined() || (ass && ((ass->sign() != ASSUMPTION_SIGN_UNKNOWN && ass->sign() != ASSUMPTION_SIGN_NONZERO) || ass->min() || ass->max()));
43 }
44 for(size_t i = 0; i < m.size(); i++) {
45 if(has_interval_unknowns(m[i])) return true;
46 }
47 return false;
48 }
49
bernoulli_poly(MathStructure & m,Number n,const MathStructure & mx,const EvaluationOptions & eo)50 bool bernoulli_poly(MathStructure &m, Number n, const MathStructure &mx, const EvaluationOptions &eo) {
51 m.clear();
52 Number bin, k, nmk(n), nrB;
53 while(k <= n) {
54 if(nmk.isEven() || nmk.isOne()) {
55 nrB.set(nmk);
56 if(!bin.binomial(n, k) || !nrB.bernoulli() || !nrB.multiply(bin)) return false;
57 if(eo.approximation == APPROXIMATION_EXACT && nrB.isApproximate()) return false;
58 m.add(nrB, true);
59 m.last().multiply(mx);
60 m.last().last().raise(k);
61 m.childUpdated(m.size());
62 }
63 nmk--;
64 k++;
65 }
66 if(m.isAddition()) m.delChild(1, true);
67 return true;
68 }
69
ZetaFunction()70 ZetaFunction::ZetaFunction() : MathFunction("zeta", 1, 2, SIGN_ZETA) {
71 NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false);
72 setArgumentDefinition(1, arg);
73 arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false);
74 setArgumentDefinition(2, arg);
75 setDefaultValue(2, "1");
76 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)77 int ZetaFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
78 if(vargs.size() == 1 || vargs[1].isOne()) {
79 if(vargs[0].number().isInteger()) {
80 if(vargs[0].number().isZero()) {
81 mstruct.set(-1, 2, 0);
82 return 1;
83 } else if(vargs[0].number().isMinusOne()) {
84 mstruct.set(-1, 12, 0);
85 return 1;
86 } else if(vargs[0].number().isNegative() && vargs[0].number().isEven()) {
87 mstruct.clear();
88 return 1;
89 } else if(vargs[0].number().isNegative() && vargs[0].number() >= -497) {
90 Number nr(vargs[0].number());
91 nr.negate();
92 nr++;
93 nr.bernoulli();
94 nr.divide(vargs[0].number() - 1);
95 if(vargs[0].number().isEven()) nr.negate();
96 mstruct.set(nr);
97 mstruct.mergePrecision(vargs[0]);
98 return 1;
99 } else if(vargs[0].number().isEven() && vargs[0].number() <= 498) {
100 Number nr(vargs[0].number());
101 nr.bernoulli();
102 mstruct.set(nr);
103 mstruct.multiply(CALCULATOR->getVariableById(VARIABLE_ID_PI));
104 mstruct.last().multiply(nr_two);
105 mstruct.last().raise(vargs[0]);
106 mstruct.multiply(vargs[0]);
107 mstruct.last().transformById(FUNCTION_ID_FACTORIAL);
108 mstruct.last().inverse();
109 if(vargs[0].number().isIntegerDivisible(4)) mstruct.multiply(Number(-1, 2));
110 else mstruct.multiply(nr_half);
111 mstruct.childrenUpdated(true);
112 return 1;
113 }
114 }
115 FR_FUNCTION(zeta)
116 }
117 if(vargs[0].number().isZero()) {
118 mstruct.set(1, 2, 0);
119 if(!vargs[1].isZero()) mstruct.subtract(vargs[1]);
120 return 1;
121 } else if(vargs[0].number().isInteger() && vargs[0].number().isNegative()) {
122 Number nr(vargs[0].number());
123 nr.negate();
124 nr++;
125 MathStructure m2(vargs[1]);
126 replace_f_interval(m2, eo);
127 replace_intervals_f(m2);
128 if(bernoulli_poly(mstruct, nr, m2, eo)) {
129 mstruct.divide(nr);
130 mstruct.negate();
131 return 1;
132 }
133 } else if(vargs[1].number().isInteger() && vargs[1].number() >= 2 && ((eo.approximation == APPROXIMATION_EXACT && vargs[1].number() <= 1000) || (vargs[1].number() <= 50 && vargs[0].number() >= -10 && vargs[0].number() <= 10))) {
134 MathStructure m1(vargs[0]);
135 replace_f_interval(m1, eo);
136 replace_intervals_f(m1);
137 mstruct = m1;
138 m1.negate();
139 mstruct.transform(this);
140 mstruct.addChild(m_one);
141 mstruct.add(m_minus_one);
142 for(long int i = 2; vargs[1].number() > i; i++) {
143 mstruct.add(Number(i, 1), true);
144 mstruct.last().raise(m1);
145 mstruct.last().negate();
146 }
147 return true;
148 }
149 FR_FUNCTION_2(zeta)
150 }
GammaFunction()151 GammaFunction::GammaFunction() : MathFunction("gamma", 1, 1, SIGN_CAPITAL_GAMMA) {
152 NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1);
153 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)154 int GammaFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
155 if(vargs[0].number().isRational() && (eo.approximation == APPROXIMATION_EXACT || (eo.approximation == APPROXIMATION_TRY_EXACT && vargs[0].number().isLessThan(1000)))) {
156 if(vargs[0].number().isInteger() && vargs[0].number().isPositive()) {
157 mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_FACTORIAL), &vargs[0], NULL);
158 mstruct[0] -= 1;
159 return 1;
160 } else if(vargs[0].number().denominatorIsTwo()) {
161 Number nr(vargs[0].number());
162 nr.floor();
163 if(nr.isZero()) {
164 MathStructure mtmp(CALCULATOR->getVariableById(VARIABLE_ID_PI));
165 mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_SQRT), &mtmp, NULL);
166 return 1;
167 } else if(nr.isPositive()) {
168 Number nr2(nr);
169 nr2 *= 2;
170 nr2 -= 1;
171 nr2.doubleFactorial();
172 Number nr3(2, 1, 0);
173 nr3 ^= nr;
174 nr2 /= nr3;
175 mstruct = nr2;
176 MathStructure mtmp1(CALCULATOR->getVariableById(VARIABLE_ID_PI));
177 MathStructure mtmp2(CALCULATOR->getFunctionById(FUNCTION_ID_SQRT), &mtmp1, NULL);
178 mstruct *= mtmp2;
179 return 1;
180 } else {
181 nr.negate();
182 Number nr2(nr);
183 nr2 *= 2;
184 nr2 -= 1;
185 nr2.doubleFactorial();
186 Number nr3(2, 1, 0);
187 nr3 ^= nr;
188 if(nr.isOdd()) nr3.negate();
189 nr3 /= nr2;
190 mstruct = nr3;
191 MathStructure mtmp1(CALCULATOR->getVariableById(VARIABLE_ID_PI));
192 MathStructure mtmp2(CALCULATOR->getFunctionById(FUNCTION_ID_SQRT), &mtmp1, NULL);
193 mstruct *= mtmp2;
194 return 1;
195 }
196 }
197 }
198 FR_FUNCTION(gamma)
199 }
DigammaFunction()200 DigammaFunction::DigammaFunction() : MathFunction("digamma", 1) {
201 NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1);
202 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)203 int DigammaFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
204 if(vargs[0].number().isOne()) {
205 mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_EULER));
206 mstruct.negate();
207 return 1;
208 }
209 FR_FUNCTION(digamma)
210 }
BetaFunction()211 BetaFunction::BetaFunction() : MathFunction("beta", 2, 2, SIGN_CAPITAL_BETA) {
212 setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false));
213 setArgumentDefinition(2, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false));
214 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)215 int BetaFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
216 mstruct = vargs[0];
217 mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_GAMMA), &vargs[0], NULL);
218 MathStructure mstruct2(CALCULATOR->getFunctionById(FUNCTION_ID_GAMMA), &vargs[1], NULL);
219 mstruct *= mstruct2;
220 mstruct2[0] += vargs[0];
221 mstruct /= mstruct2;
222 return 1;
223 }
AiryFunction()224 AiryFunction::AiryFunction() : MathFunction("airy", 1) {
225 NumberArgument *arg = new NumberArgument();
226 Number fr(-500, 1, 0);
227 arg->setMin(&fr);
228 fr.set(500, 1, 0);
229 arg->setMax(&fr);
230 setArgumentDefinition(1, arg);
231 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)232 int AiryFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
233 FR_FUNCTION(airy)
234 }
BesseljFunction()235 BesseljFunction::BesseljFunction() : MathFunction("besselj", 2) {
236 setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG));
237 NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(2);
238 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)239 int BesseljFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
240 FR_FUNCTION_2R(besselj)
241 }
BesselyFunction()242 BesselyFunction::BesselyFunction() : MathFunction("bessely", 2) {
243 IntegerArgument *iarg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG);
244 Number nmax(1000);
245 iarg->setMax(&nmax);
246 setArgumentDefinition(1, iarg);
247 NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(2);
248 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)249 int BesselyFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
250 FR_FUNCTION_2R(bessely)
251 }
ErfFunction()252 ErfFunction::ErfFunction() : MathFunction("erf", 1) {
253 setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false));
254 }
representsPositive(const MathStructure & vargs,bool) const255 bool ErfFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsPositive();}
representsNegative(const MathStructure & vargs,bool) const256 bool ErfFunction::representsNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNegative();}
representsNonNegative(const MathStructure & vargs,bool) const257 bool ErfFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonNegative();}
representsNonPositive(const MathStructure & vargs,bool) const258 bool ErfFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonPositive();}
representsInteger(const MathStructure &,bool) const259 bool ErfFunction::representsInteger(const MathStructure&, bool) const {return false;}
representsNumber(const MathStructure & vargs,bool) const260 bool ErfFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();}
representsRational(const MathStructure &,bool) const261 bool ErfFunction::representsRational(const MathStructure&, bool) const {return false;}
representsReal(const MathStructure & vargs,bool) const262 bool ErfFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();}
representsNonComplex(const MathStructure & vargs,bool) const263 bool ErfFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();}
representsComplex(const MathStructure & vargs,bool) const264 bool ErfFunction::representsComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsComplex();}
representsNonZero(const MathStructure & vargs,bool) const265 bool ErfFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonZero();}
representsEven(const MathStructure &,bool) const266 bool ErfFunction::representsEven(const MathStructure&, bool) const {return false;}
representsOdd(const MathStructure &,bool) const267 bool ErfFunction::representsOdd(const MathStructure&, bool) const {return false;}
representsUndefined(const MathStructure &) const268 bool ErfFunction::representsUndefined(const MathStructure&) const {return false;}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)269 int ErfFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
270 Number nr(vargs[0].number());
271 if(!nr.erf() || (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())) {
272 if(vargs[0].number().hasImaginaryPart() && !vargs[0].number().hasRealPart()) {
273 mstruct = vargs[0].number().imaginaryPart();
274 MathFunction *f = CALCULATOR->getFunctionById(FUNCTION_ID_ERFI);
275 mstruct.transform(f);
276 mstruct *= nr_one_i;
277 return 1;
278 }
279 return 0;
280 }
281 mstruct.set(nr);
282 return 1;
283 }
ErfiFunction()284 ErfiFunction::ErfiFunction() : MathFunction("erfi", 1) {
285 setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false));
286 }
representsPositive(const MathStructure & vargs,bool) const287 bool ErfiFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsPositive();}
representsNegative(const MathStructure & vargs,bool) const288 bool ErfiFunction::representsNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNegative();}
representsNonNegative(const MathStructure & vargs,bool) const289 bool ErfiFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonNegative();}
representsNonPositive(const MathStructure & vargs,bool) const290 bool ErfiFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonPositive();}
representsInteger(const MathStructure &,bool) const291 bool ErfiFunction::representsInteger(const MathStructure&, bool) const {return false;}
representsNumber(const MathStructure & vargs,bool) const292 bool ErfiFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();}
representsRational(const MathStructure &,bool) const293 bool ErfiFunction::representsRational(const MathStructure&, bool) const {return false;}
representsReal(const MathStructure & vargs,bool) const294 bool ErfiFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsNonComplex(const MathStructure & vargs,bool) const295 bool ErfiFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();}
representsComplex(const MathStructure & vargs,bool) const296 bool ErfiFunction::representsComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsComplex();}
representsNonZero(const MathStructure & vargs,bool) const297 bool ErfiFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonZero();}
representsEven(const MathStructure &,bool) const298 bool ErfiFunction::representsEven(const MathStructure&, bool) const {return false;}
representsOdd(const MathStructure &,bool) const299 bool ErfiFunction::representsOdd(const MathStructure&, bool) const {return false;}
representsUndefined(const MathStructure &) const300 bool ErfiFunction::representsUndefined(const MathStructure&) const {return false;}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)301 int ErfiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
302 Number nr(vargs[0].number());
303 if(!nr.erfi() || (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())) {
304 if(vargs[0].number().hasImaginaryPart() && !vargs[0].number().hasRealPart()) {
305 mstruct = vargs[0].number().imaginaryPart();
306 mstruct.transformById(FUNCTION_ID_ERF);
307 mstruct *= nr_one_i;
308 return 1;
309 }
310 return 0;
311 }
312 mstruct.set(nr);
313 return 1;
314 }
ErfcFunction()315 ErfcFunction::ErfcFunction() : MathFunction("erfc", 1) {
316 setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false));
317 }
representsPositive(const MathStructure & vargs,bool) const318 bool ErfcFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsNegative(const MathStructure &,bool) const319 bool ErfcFunction::representsNegative(const MathStructure&, bool) const {return false;}
representsNonNegative(const MathStructure & vargs,bool) const320 bool ErfcFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsNonPositive(const MathStructure &,bool) const321 bool ErfcFunction::representsNonPositive(const MathStructure&, bool) const {return false;}
representsInteger(const MathStructure &,bool) const322 bool ErfcFunction::representsInteger(const MathStructure&, bool) const {return false;}
representsNumber(const MathStructure & vargs,bool) const323 bool ErfcFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();}
representsRational(const MathStructure &,bool) const324 bool ErfcFunction::representsRational(const MathStructure&, bool) const {return false;}
representsReal(const MathStructure & vargs,bool) const325 bool ErfcFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();}
representsNonComplex(const MathStructure & vargs,bool) const326 bool ErfcFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();}
representsComplex(const MathStructure & vargs,bool) const327 bool ErfcFunction::representsComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsComplex();}
representsNonZero(const MathStructure & vargs,bool) const328 bool ErfcFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsEven(const MathStructure &,bool) const329 bool ErfcFunction::representsEven(const MathStructure&, bool) const {return false;}
representsOdd(const MathStructure &,bool) const330 bool ErfcFunction::representsOdd(const MathStructure&, bool) const {return false;}
representsUndefined(const MathStructure &) const331 bool ErfcFunction::representsUndefined(const MathStructure&) const {return false;}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)332 int ErfcFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
333 FR_FUNCTION(erfc)
334 }
335
LiFunction()336 LiFunction::LiFunction() : MathFunction("Li", 2) {
337 names[0].case_sensitive = true;
338 Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false);
339 arg->setHandleVector(true);
340 setArgumentDefinition(1, arg);
341 arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false);
342 arg->setHandleVector(true);
343 setArgumentDefinition(2, arg);
344 }
representsReal(const MathStructure & vargs,bool) const345 bool LiFunction::representsReal(const MathStructure &vargs, bool) const {
346 return vargs.size() == 2 && vargs[0].representsInteger() && vargs[1].representsReal() && (vargs[1].representsNonPositive() || ((vargs[1].isNumber() && vargs[1].number().isLessThanOrEqualTo(1)) || (vargs[1].isVariable() && vargs[1].variable()->isKnown() && ((KnownVariable*) vargs[1].variable())->get().isNumber() && ((KnownVariable*) vargs[1].variable())->get().number().isLessThanOrEqualTo(1)))) && ((vargs[0].representsPositive() || ((vargs[1].isNumber() && COMPARISON_IS_NOT_EQUAL(vargs[1].number().compare(nr_one))) || (vargs[1].isVariable() && vargs[1].variable()->isKnown() && ((KnownVariable*) vargs[1].variable())->get().isNumber() && COMPARISON_IS_NOT_EQUAL(((KnownVariable*) vargs[1].variable())->get().number().compare(nr_one))))));
347 }
representsNonComplex(const MathStructure & vargs,bool) const348 bool LiFunction::representsNonComplex(const MathStructure &vargs, bool) const {
349 return vargs.size() == 2 && vargs[0].representsInteger() && vargs[1].representsNonComplex() && (vargs[1].representsNonPositive() || ((vargs[1].isNumber() && vargs[1].number().isLessThanOrEqualTo(1)) || (vargs[1].isVariable() && vargs[1].variable()->isKnown() && ((KnownVariable*) vargs[1].variable())->get().isNumber() && ((KnownVariable*) vargs[1].variable())->get().number().isLessThanOrEqualTo(1))));
350 }
representsNumber(const MathStructure & vargs,bool) const351 bool LiFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[0].representsInteger() && (vargs[0].representsPositive() || (vargs[1].representsNumber() && ((vargs[1].isNumber() && COMPARISON_IS_NOT_EQUAL(vargs[1].number().compare(nr_one))) || (vargs[1].isVariable() && vargs[1].variable()->isKnown() && ((KnownVariable*) vargs[1].variable())->get().isNumber() && COMPARISON_IS_NOT_EQUAL(((KnownVariable*) vargs[1].variable())->get().number().compare(nr_one))))));}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)352 int LiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
353 if(vargs[1].isVector()) return 0;
354 if(vargs[0].isInteger()) {
355 if(vargs[0].number().isOne()) {
356 mstruct.set(1, 1, 0);
357 mstruct -= vargs[1];
358 mstruct.transformById(FUNCTION_ID_LOG);
359 mstruct.negate();
360 return true;
361 } else if(vargs[0].number().isZero()) {
362 mstruct.set(1, 1, 0);
363 mstruct -= vargs[1];
364 mstruct.inverse();
365 mstruct += nr_minus_one;
366 return true;
367 } else if(vargs[0].number().isNegative()) {
368 if(vargs[0].number().isMinusOne()) {
369 mstruct.set(1, 1, 0);
370 mstruct -= vargs[1];
371 mstruct ^= Number(-2, 1);
372 mstruct *= vargs[1];
373 return true;
374 } else if(vargs[0].number() == -2) {
375 mstruct.set(1, 1, 0);
376 mstruct -= vargs[1];
377 mstruct ^= Number(-3, 1);
378 mstruct *= vargs[1];
379 mstruct.last() += m_one;
380 mstruct.last() *= vargs[1];
381 return true;
382 } else if(vargs[0].number() == -3) {
383 mstruct.set(1, 1, 0);
384 mstruct -= vargs[1];
385 mstruct ^= Number(-4, 1);
386 mstruct *= vargs[1];
387 mstruct.last() ^= nr_two;
388 mstruct.last() += Number(4, 1);
389 mstruct.last().last() *= vargs[1];
390 mstruct.last() += m_one;
391 mstruct.last() *= vargs[1];
392 return true;
393 } else if(vargs[0].number() == -4) {
394 mstruct.set(1, 1, 0);
395 mstruct -= vargs[1];
396 mstruct ^= Number(-5, 1);
397 mstruct *= vargs[1];
398 mstruct.last() ^= nr_two;
399 mstruct.last() += Number(10, 1);
400 mstruct.last().last() *= vargs[1];
401 mstruct.last() += m_one;
402 mstruct.last() *= vargs[1];
403 mstruct.last().last() += m_one;
404 mstruct.last() *= vargs[1];
405 return true;
406 }
407 }
408 }
409 mstruct = vargs[1];
410 mstruct.eval(eo);
411 if(mstruct.isVector()) return -2;
412 if(vargs[0].number() >= 1 && mstruct.isOne()) {
413 mstruct = vargs[0];
414 mstruct.transformById(FUNCTION_ID_ZETA);
415 return true;
416 }
417 if(mstruct.isNumber()) {
418 Number nr(mstruct.number());
419 if(nr.polylog(vargs[0].number()) && (eo.approximation != APPROXIMATION_EXACT || !nr.isApproximate() || vargs[0].isApproximate() || mstruct.isApproximate()) && (eo.allow_complex || !nr.isComplex() || vargs[0].number().isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || vargs[0].number().includesInfinity() || mstruct.number().includesInfinity())) {
420 mstruct.set(nr); return 1;
421 }
422 }
423 return -2;
424 }
425
HeavisideFunction()426 HeavisideFunction::HeavisideFunction() : MathFunction("heaviside", 1) {
427 NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false);
428 arg->setHandleVector(true);
429 arg->setComplexAllowed(false);
430 setArgumentDefinition(1, arg);
431 }
representsPositive(const MathStructure & vargs,bool) const432 bool HeavisideFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonNegative(true);}
representsNegative(const MathStructure &,bool) const433 bool HeavisideFunction::representsNegative(const MathStructure&, bool) const {return false;}
representsNonNegative(const MathStructure & vargs,bool) const434 bool HeavisideFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal(true);}
representsNonPositive(const MathStructure &,bool) const435 bool HeavisideFunction::representsNonPositive(const MathStructure&, bool) const {return false;}
representsInteger(const MathStructure & vargs,bool) const436 bool HeavisideFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonZero() && vargs[0].representsReal(true);}
representsNumber(const MathStructure & vargs,bool) const437 bool HeavisideFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal(true);}
representsRational(const MathStructure & vargs,bool) const438 bool HeavisideFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal(true);}
representsNonComplex(const MathStructure & vargs,bool) const439 bool HeavisideFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);}
representsReal(const MathStructure & vargs,bool) const440 bool HeavisideFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal(true);}
representsComplex(const MathStructure &,bool) const441 bool HeavisideFunction::representsComplex(const MathStructure&, bool) const {return false;}
representsNonZero(const MathStructure & vargs,bool) const442 bool HeavisideFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonNegative(true);}
representsEven(const MathStructure &,bool) const443 bool HeavisideFunction::representsEven(const MathStructure&, bool) const {return false;}
representsOdd(const MathStructure &,bool) const444 bool HeavisideFunction::representsOdd(const MathStructure&, bool) const {return false;}
representsUndefined(const MathStructure & vargs) const445 bool HeavisideFunction::representsUndefined(const MathStructure &vargs) const {return vargs.size() == 1 && vargs[0].representsUndefined();}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)446 int HeavisideFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
447 if(vargs[0].isVector()) return 0;
448 mstruct = vargs[0];
449 mstruct.eval(eo);
450 if(mstruct.isVector()) return -1;
451 if(!mstruct.representsNonComplex(true)) return false;
452 if(mstruct.representsPositive(true)) {
453 mstruct.set(1, 1, 0);
454 return 1;
455 }
456 if(mstruct.representsNegative(true)) {
457 mstruct.clear();
458 return 1;
459 }
460 if(mstruct.isZero()) {
461 mstruct = nr_half;
462 return 1;
463 }
464 if(mstruct.isNumber() && mstruct.number().isInterval()) {
465 if(!mstruct.number().isNonNegative()) {
466 mstruct.number().setInterval(nr_half, nr_one);
467 } else if(!mstruct.number().isNonPositive()) {
468 mstruct.number().setInterval(nr_zero, nr_half);
469 } else {
470 mstruct.number().setInterval(nr_zero, nr_one);
471 }
472 return 1;
473 }
474 if(eo.approximation == APPROXIMATION_EXACT || has_interval_unknowns(mstruct)) {
475 ComparisonResult cr = mstruct.compare(m_zero);
476 if(cr == COMPARISON_RESULT_LESS) {
477 mstruct.set(1, 1, 0);
478 return 1;
479 } else if(cr == COMPARISON_RESULT_GREATER) {
480 mstruct.clear();
481 return 1;
482 }
483 }
484 return -1;
485 }
DiracFunction()486 DiracFunction::DiracFunction() : MathFunction("dirac", 1) {
487 NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false);
488 arg->setComplexAllowed(false);
489 setArgumentDefinition(1, arg);
490 }
representsPositive(const MathStructure &,bool allow_units) const491 bool DiracFunction::representsPositive(const MathStructure&, bool allow_units) const {return false;}
representsNegative(const MathStructure &,bool) const492 bool DiracFunction::representsNegative(const MathStructure&, bool) const {return false;}
representsNonNegative(const MathStructure &,bool) const493 bool DiracFunction::representsNonNegative(const MathStructure&, bool) const {return true;}
representsNonPositive(const MathStructure &,bool) const494 bool DiracFunction::representsNonPositive(const MathStructure&, bool) const {return false;}
representsInteger(const MathStructure &,bool) const495 bool DiracFunction::representsInteger(const MathStructure&, bool) const {return false;}
representsNumber(const MathStructure &,bool) const496 bool DiracFunction::representsNumber(const MathStructure&, bool) const {return false;}
representsRational(const MathStructure &,bool) const497 bool DiracFunction::representsRational(const MathStructure&, bool) const {return false;}
representsNonComplex(const MathStructure & vargs,bool) const498 bool DiracFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);}
representsReal(const MathStructure &,bool) const499 bool DiracFunction::representsReal(const MathStructure&, bool) const {return false;}
representsComplex(const MathStructure &,bool) const500 bool DiracFunction::representsComplex(const MathStructure&, bool) const {return false;}
representsNonZero(const MathStructure &,bool) const501 bool DiracFunction::representsNonZero(const MathStructure&, bool) const {return false;}
representsEven(const MathStructure &,bool) const502 bool DiracFunction::representsEven(const MathStructure&, bool) const {return false;}
representsOdd(const MathStructure &,bool) const503 bool DiracFunction::representsOdd(const MathStructure&, bool) const {return false;}
representsUndefined(const MathStructure & vargs) const504 bool DiracFunction::representsUndefined(const MathStructure &vargs) const {return vargs.size() == 1 && vargs[0].representsUndefined();}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)505 int DiracFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
506 mstruct = vargs[0];
507 mstruct.eval(eo);
508 if(!mstruct.representsNonComplex(true)) return false;
509 if(mstruct.representsNonZero(true)) {
510 mstruct.clear();
511 return 1;
512 }
513 if(mstruct.isZero()) {
514 mstruct = nr_plus_inf;
515 return 1;
516 }
517 if(mstruct.isNumber() && mstruct.number().isInterval() && !mstruct.number().isNonZero()) {
518 mstruct.number().setInterval(nr_zero, nr_plus_inf);
519 return 1;
520 }
521 if(eo.approximation == APPROXIMATION_EXACT || has_interval_unknowns(mstruct)) {
522 ComparisonResult cr = mstruct.compare(m_zero);
523 if(COMPARISON_IS_NOT_EQUAL(cr)) {
524 mstruct.clear();
525 return 1;
526 }
527 }
528 return -1;
529 }
530
531