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 NON_COMPLEX_NUMBER_ARGUMENT(i) NumberArgument *arg_non_complex##i = new NumberArgument(); arg_non_complex##i->setComplexAllowed(false); setArgumentDefinition(i, arg_non_complex##i);
37
liFunction()38 liFunction::liFunction() : MathFunction("li", 1) {
39 names[0].case_sensitive = true;
40 setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false));
41 }
representsReal(const MathStructure & vargs,bool) const42 bool liFunction::representsReal(const MathStructure &vargs, bool) const {
43 return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative() && ((vargs[0].isNumber() && !COMPARISON_IS_NOT_EQUAL(vargs[0].number().compare(nr_one))) || (vargs[0].isVariable() && vargs[0].variable()->isKnown() && ((KnownVariable*) vargs[0].variable())->get().isNumber() && COMPARISON_IS_NOT_EQUAL(((KnownVariable*) vargs[0].variable())->get().number().compare(nr_one))));
44 }
representsNonComplex(const MathStructure & vargs,bool) const45 bool liFunction::representsNonComplex(const MathStructure &vargs, bool) const {
46 return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative();
47 }
representsNumber(const MathStructure & vargs,bool) const48 bool liFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber() && ((vargs[0].isNumber() && COMPARISON_IS_NOT_EQUAL(vargs[0].number().compare(nr_one))) || (vargs[0].isVariable() && vargs[0].variable()->isKnown() && ((KnownVariable*) vargs[0].variable())->get().isNumber() && COMPARISON_IS_NOT_EQUAL(((KnownVariable*) vargs[0].variable())->get().number().compare(nr_one))));}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)49 int liFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
50 FR_FUNCTION(logint)
51 }
EiFunction()52 EiFunction::EiFunction() : MathFunction("Ei", 1) {
53 names[0].case_sensitive = true;
54 setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false));
55 }
representsReal(const MathStructure & vargs,bool) const56 bool EiFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonZero();}
representsNonComplex(const MathStructure & vargs,bool) const57 bool EiFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();}
representsNumber(const MathStructure & vargs,bool) const58 bool EiFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber() && vargs[0].representsNonZero();}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)59 int EiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
60 FR_FUNCTION(expint)
61 }
FresnelSFunction()62 FresnelSFunction::FresnelSFunction() : MathFunction("fresnels", 1) {
63 NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false);
64 Number fr(-6, 1);
65 arg->setMin(&fr);
66 fr = 6;
67 arg->setMax(&fr);
68 setArgumentDefinition(1, arg);
69 }
representsPositive(const MathStructure & vargs,bool) const70 bool FresnelSFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsPositive();}
representsNegative(const MathStructure & vargs,bool) const71 bool FresnelSFunction::representsNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNegative();}
representsNonNegative(const MathStructure & vargs,bool) const72 bool FresnelSFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonNegative();}
representsNonPositive(const MathStructure & vargs,bool) const73 bool FresnelSFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonPositive();}
representsInteger(const MathStructure &,bool) const74 bool FresnelSFunction::representsInteger(const MathStructure&, bool) const {return false;}
representsNumber(const MathStructure & vargs,bool) const75 bool FresnelSFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();}
representsRational(const MathStructure &,bool) const76 bool FresnelSFunction::representsRational(const MathStructure&, bool) const {return false;}
representsReal(const MathStructure & vargs,bool) const77 bool FresnelSFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();}
representsNonComplex(const MathStructure & vargs,bool) const78 bool FresnelSFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();}
representsComplex(const MathStructure & vargs,bool) const79 bool FresnelSFunction::representsComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsComplex();}
representsNonZero(const MathStructure & vargs,bool) const80 bool FresnelSFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonZero();}
representsEven(const MathStructure &,bool) const81 bool FresnelSFunction::representsEven(const MathStructure&, bool) const {return false;}
representsOdd(const MathStructure &,bool) const82 bool FresnelSFunction::representsOdd(const MathStructure&, bool) const {return false;}
representsUndefined(const MathStructure &) const83 bool FresnelSFunction::representsUndefined(const MathStructure&) const {return false;}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)84 int FresnelSFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
85 mstruct = vargs[0];
86 mstruct.eval(eo);
87 if(contains_angle_unit(mstruct, eo.parse_options)) {mstruct /= CALCULATOR->getRadUnit(); mstruct.eval(eo);}
88 if(!mstruct.isNumber()) return -1;
89 Number nr(mstruct.number()); if(!nr.fresnels() || (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())) {
90 return -1;
91 }
92 mstruct.set(nr);
93 return 1;
94 }
FresnelCFunction()95 FresnelCFunction::FresnelCFunction() : MathFunction("fresnelc", 1) {
96 NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false);
97 Number fr(-6, 1);
98 arg->setMin(&fr);
99 fr = 6;
100 arg->setMax(&fr);
101 setArgumentDefinition(1, arg);
102 }
representsPositive(const MathStructure & vargs,bool) const103 bool FresnelCFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsPositive();}
representsNegative(const MathStructure & vargs,bool) const104 bool FresnelCFunction::representsNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNegative();}
representsNonNegative(const MathStructure & vargs,bool) const105 bool FresnelCFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonNegative();}
representsNonPositive(const MathStructure & vargs,bool) const106 bool FresnelCFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonPositive();}
representsInteger(const MathStructure &,bool) const107 bool FresnelCFunction::representsInteger(const MathStructure&, bool) const {return false;}
representsNumber(const MathStructure & vargs,bool) const108 bool FresnelCFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();}
representsRational(const MathStructure &,bool) const109 bool FresnelCFunction::representsRational(const MathStructure&, bool) const {return false;}
representsReal(const MathStructure & vargs,bool) const110 bool FresnelCFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();}
representsNonComplex(const MathStructure & vargs,bool) const111 bool FresnelCFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();}
representsComplex(const MathStructure & vargs,bool) const112 bool FresnelCFunction::representsComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsComplex();}
representsNonZero(const MathStructure & vargs,bool) const113 bool FresnelCFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonZero();}
representsEven(const MathStructure &,bool) const114 bool FresnelCFunction::representsEven(const MathStructure&, bool) const {return false;}
representsOdd(const MathStructure &,bool) const115 bool FresnelCFunction::representsOdd(const MathStructure&, bool) const {return false;}
representsUndefined(const MathStructure &) const116 bool FresnelCFunction::representsUndefined(const MathStructure&) const {return false;}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)117 int FresnelCFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
118 mstruct = vargs[0];
119 mstruct.eval(eo);
120 if(contains_angle_unit(mstruct, eo.parse_options)) {mstruct /= CALCULATOR->getRadUnit(); mstruct.eval(eo);}
121 if(!mstruct.isNumber()) return -1;
122 Number nr(mstruct.number()); if(!nr.fresnelc() || (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())) {
123 return -1;
124 }
125 mstruct.set(nr);
126 return 1;
127 }
SiFunction()128 SiFunction::SiFunction() : MathFunction("Si", 1) {
129 setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false));
130 }
representsNumber(const MathStructure & vargs,bool) const131 bool SiFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();}
representsReal(const MathStructure & vargs,bool) const132 bool SiFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsNonComplex(const MathStructure & vargs,bool) const133 bool SiFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)134 int SiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
135 if(vargs[0].isVector()) return 0;
136 mstruct = vargs[0];
137 mstruct.eval(eo);
138 if(mstruct.isVector()) return -1;
139 if(contains_angle_unit(mstruct, eo.parse_options)) {mstruct /= CALCULATOR->getRadUnit(); mstruct.eval(eo);}
140 if(mstruct.isNumber()) {
141 Number nr(mstruct.number());
142 if(nr.isPlusInfinity()) {
143 mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI), true);
144 mstruct *= nr_half;
145 return 1;
146 }
147 if(nr.isMinusInfinity()) {
148 mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI), true);
149 mstruct *= nr_minus_half;
150 return 1;
151 }
152 if(nr.hasImaginaryPart() && !nr.hasRealPart()) {
153 mstruct.set(nr.imaginaryPart());
154 mstruct.transformById(FUNCTION_ID_SINHINT);
155 mstruct *= nr_one_i;
156 return 1;
157 }
158 if(nr.sinint() && (eo.approximation != APPROXIMATION_EXACT || !nr.isApproximate() || mstruct.isApproximate()) && (eo.allow_complex || !nr.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || mstruct.number().includesInfinity())) {
159 mstruct.set(nr);
160 return 1;
161 }
162 }
163 if(has_predominately_negative_sign(mstruct)) {
164 negate_struct(mstruct);
165 mstruct.transform(this);
166 mstruct.negate();
167 return 1;
168 }
169 return -1;
170 }
CiFunction()171 CiFunction::CiFunction() : MathFunction("Ci", 1) {
172 names[0].case_sensitive = true;
173 setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false));
174 }
representsReal(const MathStructure & vargs,bool) const175 bool CiFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsPositive();}
representsNumber(const MathStructure & vargs,bool) const176 bool CiFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();}
representsNonComplex(const MathStructure & vargs,bool) const177 bool CiFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonNegative(true);}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)178 int CiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
179 if(vargs[0].isVector()) return 0;
180 mstruct = vargs[0];
181 mstruct.eval(eo);
182 if(mstruct.isVector()) return -1;
183 if(contains_angle_unit(mstruct, eo.parse_options)) {mstruct /= CALCULATOR->getRadUnit(); mstruct.eval(eo);}
184 if(mstruct.isNumber()) {
185 if(mstruct.number().isNegative()) {
186 if(!eo.allow_complex) return -1;
187 mstruct.negate();
188 mstruct.transform(this);
189 mstruct += CALCULATOR->getVariableById(VARIABLE_ID_PI);
190 mstruct.last() *= nr_one_i;
191 return 1;
192 }
193 Number nr(mstruct.number());
194 if(nr.isComplex() && nr.hasImaginaryPart() && !nr.hasRealPart()) {
195 mstruct.set(nr.imaginaryPart());
196 if(nr.imaginaryPartIsNegative()) mstruct.negate();
197 mstruct.transformById(FUNCTION_ID_COSHINT);
198 mstruct += CALCULATOR->getVariableById(VARIABLE_ID_PI);
199 mstruct.last() *= nr_half;
200 if(nr.imaginaryPartIsPositive()) mstruct.last() *= nr_one_i;
201 else mstruct.last() *= nr_minus_i;
202 return 1;
203 }
204 if(nr.cosint() && (eo.approximation != APPROXIMATION_EXACT || !nr.isApproximate() || mstruct.isApproximate()) && (eo.allow_complex || !nr.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || mstruct.number().includesInfinity())) {
205 mstruct.set(nr);
206 return 1;
207 }
208 }
209 return -1;
210 }
ShiFunction()211 ShiFunction::ShiFunction() : MathFunction("Shi", 1) {
212 names[0].case_sensitive = true;
213 setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false));
214 }
representsReal(const MathStructure & vargs,bool) const215 bool ShiFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsNumber(const MathStructure & vargs,bool) const216 bool ShiFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();}
representsNonComplex(const MathStructure & vargs,bool) const217 bool ShiFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)218 int ShiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
219 if(vargs[0].isVector()) return 0;
220 mstruct = vargs[0];
221 mstruct.eval(eo);
222 if(mstruct.isVector()) return -1;
223 if(mstruct.isNumber()) {
224 Number nr(mstruct.number());
225 if(nr.hasImaginaryPart() && !nr.hasRealPart()) {
226 mstruct.set(nr.imaginaryPart());
227 mstruct.transformById(FUNCTION_ID_SININT);
228 mstruct *= nr_one_i;
229 return 1;
230 }
231 if(nr.sinhint() && (eo.approximation != APPROXIMATION_EXACT || !nr.isApproximate() || mstruct.isApproximate()) && (eo.allow_complex || !nr.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || mstruct.number().includesInfinity())) {
232 mstruct.set(nr);
233 return 1;
234 }
235 }
236 if(has_predominately_negative_sign(mstruct)) {
237 negate_struct(mstruct);
238 mstruct.transform(this);
239 mstruct.negate();
240 return 1;
241 }
242 return -1;
243 }
ChiFunction()244 ChiFunction::ChiFunction() : MathFunction("Chi", 1) {
245 names[0].case_sensitive = true;
246 setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false));
247 }
representsReal(const MathStructure & vargs,bool) const248 bool ChiFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsPositive();}
representsNonComplex(const MathStructure & vargs,bool) const249 bool ChiFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonNegative();}
representsNumber(const MathStructure & vargs,bool) const250 bool ChiFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)251 int ChiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
252 if(vargs[0].isVector()) return 0;
253 mstruct = vargs[0];
254 mstruct.eval(eo);
255 if(mstruct.isVector()) return -1;
256 if(mstruct.isNumber()) {
257 if(eo.allow_complex && mstruct.number().isNegative()) {
258 if(!eo.allow_complex) return -1;
259 mstruct.negate();
260 mstruct.transform(this);
261 mstruct += CALCULATOR->getVariableById(VARIABLE_ID_PI);
262 mstruct.last() *= nr_one_i;
263 return 1;
264 }
265 Number nr(mstruct.number());
266 if(nr.isComplex() && nr.hasImaginaryPart() && !nr.hasRealPart()) {
267 mstruct.set(nr.imaginaryPart());
268 if(nr.imaginaryPartIsNegative()) mstruct.negate();
269 mstruct.transformById(FUNCTION_ID_COSINT);
270 mstruct += CALCULATOR->getVariableById(VARIABLE_ID_PI);
271 mstruct.last() *= nr_half;
272 if(nr.imaginaryPartIsPositive()) mstruct.last() *= nr_one_i;
273 else mstruct.last() *= nr_minus_i;
274 return 1;
275 }
276 if(nr.coshint() && (eo.approximation != APPROXIMATION_EXACT || !nr.isApproximate() || mstruct.isApproximate()) && (eo.allow_complex || !nr.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || mstruct.number().includesInfinity())) {
277 mstruct.set(nr);
278 return 1;
279 }
280 }
281 return -1;
282 }
283
IGammaFunction()284 IGammaFunction::IGammaFunction() : MathFunction("igamma", 2) {
285 setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false));
286 setArgumentDefinition(2, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false));
287 }
representsReal(const MathStructure & vargs,bool) const288 bool IGammaFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 2 && (vargs[1].representsPositive() || (vargs[0].representsInteger() && vargs[0].representsPositive()));}
representsNonComplex(const MathStructure & vargs,bool) const289 bool IGammaFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 2 && (vargs[1].representsNonNegative() || (vargs[0].representsInteger() && vargs[0].representsNonNegative()));}
representsNumber(const MathStructure & vargs,bool) const290 bool IGammaFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 2 && (vargs[1].representsNonZero() || vargs[0].representsPositive());}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)291 int IGammaFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
292 FR_FUNCTION_2(igamma)
293 }
294
LimitFunction()295 LimitFunction::LimitFunction() : MathFunction("limit", 2, 4) {
296 NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false);
297 arg->setComplexAllowed(false);
298 arg->setHandleVector(true);
299 setArgumentDefinition(2, arg);
300 setArgumentDefinition(3, new SymbolicArgument());
301 setDefaultValue(3, "x");
302 IntegerArgument *iarg = new IntegerArgument();
303 iarg->setMin(&nr_minus_one);
304 iarg->setMax(&nr_one);
305 setArgumentDefinition(4, iarg);
306 setDefaultValue(4, "0");
307 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)308 int LimitFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
309 if(vargs[1].isVector()) return 0;
310 mstruct = vargs[0];
311 EvaluationOptions eo2 = eo;
312 eo2.approximation = APPROXIMATION_EXACT;
313 if(mstruct.calculateLimit(vargs[2], vargs[1], eo2, vargs[3].number().intValue())) return 1;
314 CALCULATOR->error(true, _("Unable to find limit."), NULL);
315 return -1;
316 }
replace_diff_x(MathStructure & m,const MathStructure & mfrom,const MathStructure & mto)317 bool replace_diff_x(MathStructure &m, const MathStructure &mfrom, const MathStructure &mto) {
318 if(m.equals(mfrom, true, true)) {
319 m = mto;
320 return true;
321 }
322 if(m.type() == STRUCT_FUNCTION && m.function()->id() == FUNCTION_ID_DIFFERENTIATE) {
323 if(m.size() >= 4 && m[1] == mfrom && m[3].isUndefined()) {
324 m[3] = mto;
325 return true;
326 }
327 return false;
328 }
329 bool b = false;
330 for(size_t i = 0; i < m.size(); i++) {
331 if(replace_diff_x(m[i], mfrom, mto)) {
332 b = true;
333 m.childUpdated(i + 1);
334 }
335 }
336 return b;
337 }
338
DeriveFunction()339 DeriveFunction::DeriveFunction() : MathFunction("diff", 1, 4) {
340 setArgumentDefinition(2, new SymbolicArgument());
341 setDefaultValue(2, "undefined");
342 Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SINT);
343 arg->setHandleVector(false);
344 setArgumentDefinition(3, arg);
345 setDefaultValue(3, "1");
346 setDefaultValue(4, "undefined");
347 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)348 int DeriveFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
349 int i = vargs[2].number().intValue();
350 mstruct = vargs[0];
351 bool b = false;
352 while(i) {
353 if(CALCULATOR->aborted()) return 0;
354 if(!mstruct.differentiate(vargs[1], eo) && !b) {
355 return 0;
356 }
357 b = true;
358 i--;
359 if(i > 0) {
360 EvaluationOptions eo2 = eo;
361 eo2.approximation = APPROXIMATION_EXACT;
362 eo2.calculate_functions = false;
363 mstruct.eval(eo2);
364 }
365 }
366 if(!vargs[3].isUndefined()) replace_diff_x(mstruct, vargs[1], vargs[3]);
367 return 1;
368 }
369
RombergFunction()370 RombergFunction::RombergFunction() : MathFunction("romberg", 3, 6) {
371 Argument *arg = new Argument("", false, false);
372 arg->setHandleVector(true);
373 setArgumentDefinition(1, arg);
374 NON_COMPLEX_NUMBER_ARGUMENT(2)
375 NON_COMPLEX_NUMBER_ARGUMENT(3)
376 setCondition("\\z > \\y");
377 IntegerArgument *iarg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG);
378 Number nr(2, 1);
379 iarg->setMin(&nr);
380 setArgumentDefinition(4, iarg);
381 setDefaultValue(4, "6");
382 setArgumentDefinition(5, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG));
383 setDefaultValue(5, "20");
384 setArgumentDefinition(6, new SymbolicArgument());
385 setDefaultValue(6, "undefined");
386 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)387 int RombergFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
388 MathStructure minteg(vargs[0]);
389 EvaluationOptions eo2 = eo;
390 eo2.approximation = APPROXIMATION_APPROXIMATE;
391 Number nr_interval;
392 nr_interval.setInterval(vargs[1].number(), vargs[2].number());
393 UnknownVariable *var = new UnknownVariable("", format_and_print(vargs[5]));
394 var->setInterval(nr_interval);
395 MathStructure x_var(var);
396 minteg.replace(vargs[5], x_var);
397 var->destroy();
398 minteg.eval(eo2);
399 Number nr;
400 eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC;
401 eo2.warn_about_denominators_assumed_nonzero = false;
402 CALCULATOR->beginTemporaryStopMessages();
403 if(romberg(minteg, nr, x_var, eo2, vargs[1].number(), vargs[2].number(), vargs[4].number().lintValue(), vargs[3].number().lintValue(), false)) {
404 CALCULATOR->endTemporaryStopMessages();
405 mstruct = nr;
406 return 1;
407 }
408 CALCULATOR->endTemporaryStopMessages();
409 CALCULATOR->error(false, _("Unable to integrate the expression."), NULL);
410 return 0;
411 }
MonteCarloFunction()412 MonteCarloFunction::MonteCarloFunction() : MathFunction("montecarlo", 4, 5) {
413 Argument *arg = new Argument("", false, false);
414 arg->setHandleVector(true);
415 setArgumentDefinition(1, arg);
416 NON_COMPLEX_NUMBER_ARGUMENT(2)
417 NON_COMPLEX_NUMBER_ARGUMENT(3)
418 setCondition("\\z > \\y");
419 setArgumentDefinition(4, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE));
420 setArgumentDefinition(5, new SymbolicArgument());
421 setDefaultValue(5, "undefined");
422 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)423 int MonteCarloFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
424 MathStructure minteg(vargs[0]);
425 EvaluationOptions eo2 = eo;
426 eo2.approximation = APPROXIMATION_APPROXIMATE;
427 Number nr_interval;
428 nr_interval.setInterval(vargs[1].number(), vargs[2].number());
429 UnknownVariable *var = new UnknownVariable("", format_and_print(vargs[4]));
430 var->setInterval(nr_interval);
431 MathStructure x_var(var);
432 minteg.replace(vargs[4], x_var);
433 var->destroy();
434 minteg.eval(eo2);
435 Number nr;
436 eo2.interval_calculation = INTERVAL_CALCULATION_NONE;
437 if(montecarlo(minteg, nr, x_var, eo2, vargs[1].number(), vargs[2].number(), vargs[3].number())) {
438 mstruct = nr;
439 return 1;
440 }
441 CALCULATOR->error(false, _("Unable to integrate the expression."), NULL);
442 return 0;
443 }
444
IntegrateFunction()445 IntegrateFunction::IntegrateFunction() : MathFunction("integrate", 1, 5) {
446 Argument *arg = new Argument("", false, false);
447 arg->setHandleVector(true);
448 setArgumentDefinition(1, arg);
449 setDefaultValue(2, "undefined");
450 arg = new Argument("", false, false);
451 arg->setHandleVector(true);
452 setArgumentDefinition(2, arg);
453 setDefaultValue(3, "undefined");
454 arg = new Argument("", false, false);
455 arg->setHandleVector(true);
456 setArgumentDefinition(3, arg);
457 setArgumentDefinition(4, new SymbolicArgument());
458 setDefaultValue(4, "undefined");
459 setArgumentDefinition(5, new BooleanArgument());
460 setDefaultValue(5, "0");
461 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)462 int IntegrateFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
463 mstruct = vargs[0];
464 if(vargs.size() >= 2 && (vargs.size() == 2 || vargs[2].isUndefined()) && (vargs[1].isSymbolic() || (vargs[1].isVariable() && !vargs[1].variable()->isKnown()))) {
465 if(mstruct.integrate(vargs.size() < 3 ? m_undefined : vargs[2], vargs.size() < 4 ? m_undefined : vargs[3], vargs[1], eo, vargs.size() >= 4 && vargs[4].number().getBoolean(), true)) return 1;
466 } else {
467 if(mstruct.integrate(vargs.size() < 2 ? m_undefined : vargs[1], vargs.size() < 3 ? m_undefined : vargs[2], vargs.size() < 3 ? CALCULATOR->getVariableById(VARIABLE_ID_X) : vargs[3], eo, vargs.size() >= 4 && vargs[4].number().getBoolean(), true)) return 1;
468 }
469 return -1;
470 }
471
472