1 /*
2 Qalculate (library)
3
4 Copyright (C) 2003-2007, 2008, 2016, 2018 Hanna Knutsson (hanna.knutsson@protonmail.com)
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 */
11
12 #include "support.h"
13
14 #include "BuiltinFunctions.h"
15 #include "util.h"
16 #include "MathStructure.h"
17 #include "Number.h"
18 #include "Calculator.h"
19 #include "Variable.h"
20 #include "Unit.h"
21
22 #include <sstream>
23 #include <time.h>
24 #include <limits>
25 #include <algorithm>
26
27 #include "MathStructure-support.h"
28
29 using std::string;
30 using std::cout;
31 using std::vector;
32 using std::endl;
33
34 #define FR_FUNCTION_2(FUNC) Number nr(vargs[0].number()); if(!nr.FUNC(vargs[1].number()) || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate() && !vargs[1].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex() && !vargs[1].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity() && !vargs[1].number().includesInfinity())) {return 0;} else {mstruct.set(nr); return 1;}
35
is_real_angle_value(const MathStructure & mstruct)36 bool is_real_angle_value(const MathStructure &mstruct) {
37 if(mstruct.isUnit()) {
38 return mstruct.unit()->baseUnit() == CALCULATOR->getRadUnit()->baseUnit();
39 } else if(mstruct.isMultiplication()) {
40 bool b = false;
41 for(size_t i = 0; i < mstruct.size(); i++) {
42 if(!b && mstruct[i].isUnit()) {
43 if(mstruct[i].unit()->baseUnit() == CALCULATOR->getRadUnit()->baseUnit()) {
44 b = true;
45 } else {
46 return false;
47 }
48 } else if(!mstruct[i].representsReal()) {
49 return false;
50 }
51 }
52 return b;
53 } else if(mstruct.isAddition()) {
54 for(size_t i = 0; i < mstruct.size(); i++) {
55 if(!is_real_angle_value(mstruct[i])) return false;
56 }
57 return true;
58 }
59 return false;
60 }
is_infinite_angle_value(const MathStructure & mstruct)61 bool is_infinite_angle_value(const MathStructure &mstruct) {
62 if(mstruct.isMultiplication() && mstruct.size() == 2) {
63 bool b = false;
64 for(size_t i = 0; i < mstruct.size(); i++) {
65 if(!b && mstruct[i].isUnit()) {
66 if(mstruct[i].unit()->baseUnit() == CALCULATOR->getRadUnit()->baseUnit()) {
67 b = true;
68 } else {
69 return false;
70 }
71 } else if(!mstruct[i].isNumber() || !mstruct[i].number().isInfinite()) {
72 return false;
73 }
74 }
75 return b;
76 }
77 return false;
78 }
is_number_angle_value(const MathStructure & mstruct,bool allow_infinity=false)79 bool is_number_angle_value(const MathStructure &mstruct, bool allow_infinity = false) {
80 if(mstruct.isUnit()) {
81 return mstruct.unit()->baseUnit() == CALCULATOR->getRadUnit()->baseUnit();
82 } else if(mstruct.isMultiplication()) {
83 bool b = false;
84 for(size_t i = 0; i < mstruct.size(); i++) {
85 if(!b && mstruct[i].isUnit()) {
86 if(mstruct[i].unit()->baseUnit() == CALCULATOR->getRadUnit()->baseUnit()) {
87 b = true;
88 } else {
89 return false;
90 }
91 } else if(!mstruct[i].representsNumber()) {
92 if(!allow_infinity || ((!mstruct[i].isNumber() || !mstruct[i].number().isInfinite()) && (!mstruct[i].isPower() || !mstruct[i][0].representsNumber() || !mstruct[i][1].representsNumber())) || mstruct[i].representsUndefined(true)) {
93 return false;
94 }
95 }
96 }
97 return b;
98 } else if(mstruct.isAddition()) {
99 for(size_t i = 0; i < mstruct.size(); i++) {
100 if(!is_number_angle_value(mstruct[i])) return false;
101 }
102 return true;
103 }
104 return false;
105 }
106
has_predominately_negative_sign(const MathStructure & mstruct)107 bool has_predominately_negative_sign(const MathStructure &mstruct) {
108 if(mstruct.hasNegativeSign() && !mstruct.containsType(STRUCT_ADDITION, true)) return true;
109 if(mstruct.containsInfinity(false, false, false) > 0) return false;
110 if(mstruct.isAddition() && mstruct.size() > 0) {
111 size_t p_count = 0;
112 for(size_t i = 0; i < mstruct.size(); i++) {
113 if(mstruct[i].hasNegativeSign()) {
114 p_count++;
115 if(p_count > mstruct.size() / 2) return true;
116 }
117 }
118 if(mstruct.size() % 2 == 0 && p_count == mstruct.size() / 2) return mstruct[0].hasNegativeSign();
119 }
120 return false;
121 }
122
negate_struct(MathStructure & mstruct)123 void negate_struct(MathStructure &mstruct) {
124 if(mstruct.isAddition()) {
125 for(size_t i = 0; i < mstruct.size(); i++) {
126 mstruct[i].negate();
127 }
128 } else {
129 mstruct.negate();
130 }
131 }
132
trig_remove_i(MathStructure & mstruct)133 bool trig_remove_i(MathStructure &mstruct) {
134 if(mstruct.isNumber() && mstruct.number().hasImaginaryPart() && !mstruct.number().hasRealPart()) {
135 mstruct.number() /= nr_one_i;
136 return true;
137 } else if(mstruct.isMultiplication() && mstruct.size() > 1 && mstruct[0].isNumber() && mstruct[0].number().hasImaginaryPart() && !mstruct[0].number().hasRealPart()) {
138 mstruct[0].number() /= nr_one_i;
139 return true;
140 } else if(mstruct.isAddition() && mstruct.size() > 0) {
141 for(size_t i = 0; i < mstruct.size(); i++) {
142 if(!(mstruct[i].isNumber() && mstruct[i].number().hasImaginaryPart() && !mstruct[i].number().hasRealPart()) && !(mstruct[i].isMultiplication() && mstruct[i].size() > 1 && mstruct[i][0].isNumber() && mstruct[i][0].number().hasImaginaryPart() && !mstruct[i][0].number().hasRealPart())) {
143 return false;
144 }
145 }
146 for(size_t i = 0; i < mstruct.size(); i++) {
147 if(mstruct[i].isNumber()) mstruct[i].number() /= nr_one_i;
148 else mstruct[i][0].number() /= nr_one_i;
149 }
150 return true;
151 }
152 return false;
153 }
154
SinFunction()155 SinFunction::SinFunction() : MathFunction("sin", 1) {
156 Argument *arg = new AngleArgument();
157 arg->setHandleVector(true);
158 setArgumentDefinition(1, arg);
159 }
representsNumber(const MathStructure & vargs,bool allow_units) const160 bool SinFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && ((allow_units && (vargs[0].representsNumber(true) || vargs[0].representsNonComplex(true))) || (!allow_units && is_number_angle_value(vargs[0], true)));}
representsReal(const MathStructure & vargs,bool) const161 bool SinFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && (is_real_angle_value(vargs[0]) || is_infinite_angle_value(vargs[0]));}
representsNonComplex(const MathStructure & vargs,bool) const162 bool SinFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)163 int SinFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
164
165 if(vargs[0].isVector()) return 0;
166 if(CALCULATOR->getRadUnit()) {
167 if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getRadUnit()) {
168 mstruct = vargs[0][0];
169 } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getRadUnit()) {
170 mstruct = vargs[0][1];
171 } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getDegUnit()) {
172 mstruct = vargs[0][0];
173 mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI);
174 mstruct.multiply(Number(1, 180), true);
175 } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getDegUnit()) {
176 mstruct = vargs[0][1];
177 mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI);
178 mstruct.multiply(Number(1, 180), true);
179 } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getGraUnit()) {
180 mstruct = vargs[0][0];
181 mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI);
182 mstruct.multiply(Number(1, 200), true);
183 } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getGraUnit()) {
184 mstruct = vargs[0][1];
185 mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI);
186 mstruct.multiply(Number(1, 200), true);
187 } else {
188 mstruct = vargs[0];
189 mstruct.convert(CALCULATOR->getRadUnit());
190 mstruct /= CALCULATOR->getRadUnit();
191 }
192 } else {
193 mstruct = vargs[0];
194 }
195
196 MathFunction *f = NULL;
197 if(eo.approximation == APPROXIMATION_APPROXIMATE && (eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES || eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS)) {
198 if(mstruct.isMultiplication() && mstruct.size() == 3 && mstruct[0].isFunction() && mstruct[0].size() == 1 && mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI && mstruct[2].isNumber() && mstruct[2].number().equals(Number(1, eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES ? 180 : 200))) {
199 f = mstruct[0].function();
200 }
201 }
202
203 if(eo.approximation == APPROXIMATION_TRY_EXACT) {
204 EvaluationOptions eo2 = eo;
205 eo2.approximation = APPROXIMATION_EXACT;
206 CALCULATOR->beginTemporaryStopMessages();
207 mstruct.eval(eo2);
208 } else if(!f) {
209 mstruct.eval(eo);
210 }
211
212 if(mstruct.isVector()) {
213 if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true);
214 if(CALCULATOR->getRadUnit()) {
215 for(size_t i = 0; i < mstruct.size(); i++) {
216 mstruct[i] *= CALCULATOR->getRadUnit();
217 }
218 }
219 return -1;
220 }
221
222 bool b = false, b_recalc = true;
223
224 if(eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES || eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS) {
225 if(!f && mstruct.isMultiplication() && mstruct.size() == 3 && mstruct[2].isFunction() && mstruct[2].size() == 1 && mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI && mstruct[0].isNumber() && mstruct[0].number().equals(Number(1, eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES ? 180 : 200))) {
226 f = mstruct[2].function();
227 }
228 } else if(mstruct.isFunction() && mstruct.size() == 1) {
229 f = mstruct.function();
230 }
231
232 if(mstruct.isVariable() && mstruct.variable()->id() == VARIABLE_ID_PI) {
233 mstruct.clear();
234 b = true;
235 } else if(f) {
236 if(f->id() == FUNCTION_ID_ASIN) {
237 if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true);
238 mstruct.setToChild(1, true);
239 b = true;
240 } else if(f->id() == FUNCTION_ID_ACOS) {
241 if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true);
242 mstruct.setToChild(1);
243 mstruct ^= nr_two;
244 mstruct.negate();
245 mstruct += nr_one;
246 mstruct ^= nr_half;
247 b = true;
248 } else if(f->id() == FUNCTION_ID_ATAN && (mstruct.isFunction() ? !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true) : (mstruct[2].isFunction() ? !mstruct[2][0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true) : !mstruct[0][0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)))) {
249 if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true);
250 mstruct.setToChild(1);
251 MathStructure *mmul = new MathStructure(mstruct);
252 mstruct ^= nr_two;
253 mstruct += nr_one;
254 mstruct ^= nr_minus_half;
255 mstruct.multiply_nocopy(mmul);
256 b = true;
257 }
258 } else if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isNumber() && mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI) {
259 if(mstruct[0].number().isInteger()) {
260 mstruct.clear();
261 b = true;
262 } else if(!mstruct[0].number().hasImaginaryPart() && !mstruct[0].number().includesInfinity() && !mstruct[0].number().isInterval()) {
263 Number nr(mstruct[0].number());
264 nr.frac();
265 Number nr_int(mstruct[0].number());
266 nr_int.floor();
267 bool b_even = nr_int.isEven();
268 nr.setNegative(false);
269 if(nr.equals(Number(1, 2, 0))) {
270 if(b_even) mstruct.set(1, 1, 0);
271 else mstruct.set(-1, 1, 0);
272 b = true;
273 } else if(nr.equals(Number(1, 4, 0)) || nr.equals(Number(3, 4, 0))) {
274 mstruct.set(2, 1, 0);
275 mstruct.raise_nocopy(new MathStructure(1, 2, 0));
276 mstruct.divide_nocopy(new MathStructure(2, 1, 0));
277 if(!b_even) mstruct.negate();
278 b = true;
279 } else if(nr.equals(Number(1, 3, 0)) || nr.equals(Number(2, 3, 0))) {
280 mstruct.set(3, 1, 0);
281 mstruct.raise_nocopy(new MathStructure(1, 2, 0));
282 mstruct.divide_nocopy(new MathStructure(2, 1, 0));
283 if(!b_even) mstruct.negate();
284 b = true;
285 } else if(nr.equals(Number(1, 6, 0)) || nr.equals(Number(5, 6, 0))) {
286 if(b_even) mstruct.set(1, 2, 0);
287 else mstruct.set(-1, 2, 0);
288 b = true;
289 } else if(eo.approximation == APPROXIMATION_EXACT && (mstruct[0].number().isNegative() || !mstruct[0].number().isFraction() || mstruct[0].number().isGreaterThan(nr_half))) {
290 nr_int = mstruct[0].number();
291 nr_int.floor();
292 Number nr_frac = mstruct[0].number();
293 nr_frac -= nr_int;
294 if(nr_frac.isGreaterThan(nr_half)) {
295 nr_frac -= nr_half;
296 mstruct[0].number() = nr_half;
297 mstruct[0].number() -= nr_frac;
298 } else {
299 mstruct[0].number() = nr_frac;
300 }
301 if(nr_int.isOdd()) {
302 if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();
303 mstruct.transform(this);
304 mstruct.negate();
305 b = true;
306 }
307 }
308 }
309 } else if(mstruct.isMultiplication() && mstruct.size() >= 2) {
310 bool b_pi = false;
311 for(size_t i = 0; i < mstruct.size(); i++) {
312 if(mstruct[i].isVariable() && mstruct[i].variable()->id() == VARIABLE_ID_PI) {
313 b_pi = !b_pi;
314 if(!b_pi) break;
315 } else if(!mstruct[i].representsInteger()) {
316 b_pi = false;
317 break;
318 }
319 }
320 if(b_pi) {
321 mstruct.clear();
322 b = true;
323 }
324 } else if(mstruct.isAddition()) {
325 size_t i = 0;
326 bool b_negate = false;
327 for(; i < mstruct.size(); i++) {
328 if((mstruct[i].isVariable() && mstruct[i].variable()->id() == VARIABLE_ID_PI) || (mstruct[i].isMultiplication() && mstruct[i].size() == 2 && mstruct[i][1].isVariable() && mstruct[i][1].variable()->id() == VARIABLE_ID_PI && mstruct[i][0].isNumber())) {
329 if(mstruct[i].isVariable() || mstruct[i][0].number().isInteger()) {
330 b_negate = mstruct[i].isVariable() || mstruct[i][0].number().isOdd();
331 mstruct.delChild(i + 1);
332 b_recalc = false;
333 break;
334 } else if(mstruct[i][0].number().isReal() && (mstruct[i][0].number().isNegative() || !mstruct[i][0].number().isFraction())) {
335 Number nr_int = mstruct[i][0].number();
336 nr_int.floor();
337 mstruct[i][0].number() -= nr_int;
338 b_negate = nr_int.isOdd();
339 b_recalc = false;
340 break;
341 }
342 }
343 }
344 b = b_negate;
345 if(b_negate) {
346 if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();
347 mstruct.transform(this);
348 mstruct.negate();
349 }
350 }
351 if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(b);
352 if(b) return 1;
353 if(eo.approximation == APPROXIMATION_TRY_EXACT && !mstruct.isNumber()) {
354 EvaluationOptions eo2 = eo;
355 eo2.approximation = APPROXIMATION_APPROXIMATE;
356 if(b_recalc) {
357 mstruct = vargs[0];
358 if(CALCULATOR->getRadUnit()) {
359 mstruct.convert(CALCULATOR->getRadUnit());
360 mstruct /= CALCULATOR->getRadUnit();
361 }
362 }
363 mstruct.eval(eo2);
364 }
365
366 if(mstruct.isNumber()) {
367 Number nr(mstruct.number());
368 if(nr.sin() && !(eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) && !(!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) && !(!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) {
369 mstruct.set(nr, true);
370 return 1;
371 }
372 }
373
374 if(trig_remove_i(mstruct)) {
375 mstruct.transformById(FUNCTION_ID_SINH);
376 mstruct *= nr_one_i;
377 return 1;
378 }
379
380 if(has_predominately_negative_sign(mstruct)) {
381 negate_struct(mstruct);
382 if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();
383 mstruct.transform(this);
384 mstruct.negate();
385 return 1;
386 }
387
388
389 if(CALCULATOR->getRadUnit()) {
390 if(mstruct.isVector()) {
391 for(size_t i = 0; i < mstruct.size(); i++) {
392 mstruct[i] *= CALCULATOR->getRadUnit();
393 }
394 } else {
395 mstruct *= CALCULATOR->getRadUnit();
396 }
397 }
398 return -1;
399 }
400
CosFunction()401 CosFunction::CosFunction() : MathFunction("cos", 1) {
402 Argument *arg = new AngleArgument();
403 arg->setHandleVector(true);
404 setArgumentDefinition(1, arg);
405 }
representsNumber(const MathStructure & vargs,bool allow_units) const406 bool CosFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && ((allow_units && (vargs[0].representsNumber(true) || vargs[0].representsNonComplex(true))) || (!allow_units && is_number_angle_value(vargs[0], true)));}
representsReal(const MathStructure & vargs,bool) const407 bool CosFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && (is_real_angle_value(vargs[0]) || is_infinite_angle_value(vargs[0]));}
representsNonComplex(const MathStructure & vargs,bool) const408 bool CosFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)409 int CosFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
410
411 if(vargs[0].isVector()) return 0;
412 if(CALCULATOR->getRadUnit()) {
413 if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getRadUnit()) {
414 mstruct = vargs[0][0];
415 } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getRadUnit()) {
416 mstruct = vargs[0][1];
417 } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getDegUnit()) {
418 mstruct = vargs[0][0];
419 mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI);
420 mstruct.multiply(Number(1, 180), true);
421 } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getDegUnit()) {
422 mstruct = vargs[0][1];
423 mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI);
424 mstruct.multiply(Number(1, 180), true);
425 } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getGraUnit()) {
426 mstruct = vargs[0][0];
427 mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI);
428 mstruct.multiply(Number(1, 200), true);
429 } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getGraUnit()) {
430 mstruct = vargs[0][1];
431 mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI);
432 mstruct.multiply(Number(1, 200), true);
433 } else {
434 mstruct = vargs[0];
435 mstruct.convert(CALCULATOR->getRadUnit());
436 mstruct /= CALCULATOR->getRadUnit();
437 }
438 } else {
439 mstruct = vargs[0];
440 }
441
442 MathFunction *f = NULL;
443 if(eo.approximation == APPROXIMATION_APPROXIMATE && (eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES || eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS)) {
444 if(mstruct.isMultiplication() && mstruct.size() == 3 && mstruct[0].isFunction() && mstruct[0].size() == 1 && mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI && mstruct[2].isNumber() && mstruct[2].number().equals(Number(1, eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES ? 180 : 200))) {
445 f = mstruct[0].function();
446 }
447 }
448
449 if(eo.approximation == APPROXIMATION_TRY_EXACT) {
450 EvaluationOptions eo2 = eo;
451 eo2.approximation = APPROXIMATION_EXACT;
452 CALCULATOR->beginTemporaryStopMessages();
453 mstruct.eval(eo2);
454 } else if(!f) {
455 mstruct.eval(eo);
456 }
457
458 if(mstruct.isVector()) {
459 if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true);
460 if(CALCULATOR->getRadUnit()) {
461 for(size_t i = 0; i < mstruct.size(); i++) {
462 mstruct[i] *= CALCULATOR->getRadUnit();
463 }
464 }
465 return -1;
466 }
467
468 bool b = false, b_recalc = true;
469
470 if(eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES || eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS) {
471 if(!f && mstruct.isMultiplication() && mstruct.size() == 3 && mstruct[2].isFunction() && mstruct[2].size() == 1 && mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI && mstruct[0].isNumber() && mstruct[0].number().equals(Number(1, eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES ? 180 : 200))) {
472 f = mstruct[2].function();
473 }
474 } else if(mstruct.isFunction() && mstruct.size() == 1) {
475 f = mstruct.function();
476 }
477
478 if(mstruct.isVariable() && mstruct.variable()->id() == VARIABLE_ID_PI) {
479 mstruct = -1;
480 b = true;
481 } else if(f) {
482 if(f->id() == FUNCTION_ID_ACOS) {
483 if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true);
484 mstruct.setToChild(1, true);
485 b = true;
486 } else if(f->id() == FUNCTION_ID_ASIN) {
487 if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true);
488 mstruct.setToChild(1);
489 mstruct ^= nr_two;
490 mstruct.negate();
491 mstruct += nr_one;
492 mstruct ^= nr_half;
493 b = true;
494 } else if(f->id() == FUNCTION_ID_ATAN) {
495 if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true);
496 mstruct.setToChild(1);
497 mstruct ^= nr_two;
498 mstruct += nr_one;
499 mstruct ^= nr_minus_half;
500 b = true;
501 }
502 } else if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isNumber() && mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI) {
503 if(mstruct[0].number().isInteger()) {
504 if(mstruct[0].number().isEven()) {
505 mstruct = 1;
506 } else {
507 mstruct = -1;
508 }
509 b = true;
510 } else if(!mstruct[0].number().hasImaginaryPart() && !mstruct[0].number().includesInfinity() && !mstruct[0].number().isInterval()) {
511 Number nr(mstruct[0].number());
512 nr.frac();
513 Number nr_int(mstruct[0].number());
514 nr_int.trunc();
515 bool b_even = nr_int.isEven();
516 nr.setNegative(false);
517 if(nr.equals(Number(1, 2, 0))) {
518 mstruct.clear();
519 b = true;
520 } else if(nr.equals(Number(1, 4, 0))) {
521 mstruct.set(2, 1, 0);
522 mstruct.raise_nocopy(new MathStructure(1, 2, 0));
523 mstruct.divide_nocopy(new MathStructure(2, 1, 0));
524 if(!b_even) mstruct.negate();
525 b = true;
526 } else if(nr.equals(Number(3, 4, 0))) {
527 mstruct.set(2, 1, 0);
528 mstruct.raise_nocopy(new MathStructure(1, 2, 0));
529 mstruct.divide_nocopy(new MathStructure(2, 1, 0));
530 if(b_even) mstruct.negate();
531 b = true;
532 } else if(nr.equals(Number(1, 3, 0))) {
533 if(b_even) mstruct.set(1, 2, 0);
534 else mstruct.set(-1, 2, 0);
535 b = true;
536 } else if(nr.equals(Number(2, 3, 0))) {
537 if(b_even) mstruct.set(-1, 2, 0);
538 else mstruct.set(1, 2, 0);
539 b = true;
540 } else if(nr.equals(Number(1, 6, 0))) {
541 mstruct.set(3, 1, 0);
542 mstruct.raise_nocopy(new MathStructure(1, 2, 0));
543 mstruct.divide_nocopy(new MathStructure(2, 1, 0));
544 if(!b_even) mstruct.negate();
545 b = true;
546 } else if(nr.equals(Number(5, 6, 0))) {
547 mstruct.set(3, 1, 0);
548 mstruct.raise_nocopy(new MathStructure(1, 2, 0));
549 mstruct.divide_nocopy(new MathStructure(2, 1, 0));
550 if(b_even) mstruct.negate();
551 b = true;
552 } else if(eo.approximation == APPROXIMATION_EXACT && (mstruct[0].number().isNegative() || !mstruct[0].number().isFraction() || mstruct[0].number().isGreaterThan(nr_half))) {
553 nr_int = mstruct[0].number();
554 nr_int.floor();
555 Number nr_frac = mstruct[0].number();
556 nr_frac -= nr_int;
557 if(nr_frac.isGreaterThan(nr_half)) {
558 nr_frac -= nr_half;
559 mstruct[0].number() = nr_half;
560 mstruct[0].number() -= nr_frac;
561 nr_int++;
562 } else {
563 mstruct[0].number() = nr_frac;
564 }
565 if(nr_int.isOdd()) {
566 if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();
567 mstruct.transform(this);
568 mstruct.negate();
569 b = true;
570 }
571 }
572 }
573 } else if(mstruct.isAddition()) {
574 size_t i = 0;
575 bool b_negate = false;
576 for(; i < mstruct.size(); i++) {
577 if((mstruct[i].isVariable() && mstruct[i].variable()->id() == VARIABLE_ID_PI) || (mstruct[i].isMultiplication() && mstruct[i].size() == 2 && mstruct[i][1].isVariable() && mstruct[i][1].variable()->id() == VARIABLE_ID_PI && mstruct[i][0].isNumber())) {
578 if(mstruct[i].isVariable() || mstruct[i][0].number().isInteger()) {
579 b_negate = mstruct[i].isVariable() || mstruct[i][0].number().isOdd();
580 mstruct.delChild(i + 1);
581 b_recalc = false;
582 break;
583 } else if(mstruct[i][0].number().isReal() && (mstruct[i][0].number().isNegative() || !mstruct[i][0].number().isFraction())) {
584 Number nr_int = mstruct[i][0].number();
585 nr_int.floor();
586 mstruct[i][0].number() -= nr_int;
587 b_negate = nr_int.isOdd();
588 b_recalc = false;
589 break;
590 }
591 }
592 }
593 b = b_negate;
594 if(b_negate) {
595 if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();
596 mstruct.transform(this);
597 mstruct.negate();
598 }
599 }
600 if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(b);
601 if(b) return 1;
602 if(eo.approximation == APPROXIMATION_TRY_EXACT && !mstruct.isNumber()) {
603 EvaluationOptions eo2 = eo;
604 eo2.approximation = APPROXIMATION_APPROXIMATE;
605 if(b_recalc) {
606 mstruct = vargs[0];
607 if(CALCULATOR->getRadUnit()) {
608 mstruct.convert(CALCULATOR->getRadUnit());
609 mstruct /= CALCULATOR->getRadUnit();
610 }
611 }
612 mstruct.eval(eo2);
613 }
614 if(mstruct.isNumber()) {
615 Number nr(mstruct.number());
616 if(nr.cos() && !(eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) && !(!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) && !(!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) {
617 mstruct.set(nr, true);
618 return 1;
619 }
620 }
621 if(trig_remove_i(mstruct)) {
622 mstruct.transformById(FUNCTION_ID_COSH);
623 return 1;
624 }
625 if(has_predominately_negative_sign(mstruct)) {
626 negate_struct(mstruct);
627 }
628 if(CALCULATOR->getRadUnit()) {
629 if(mstruct.isVector()) {
630 for(size_t i = 0; i < mstruct.size(); i++) {
631 mstruct[i] *= CALCULATOR->getRadUnit();
632 }
633 } else {
634 mstruct *= CALCULATOR->getRadUnit();
635 }
636 }
637 return -1;
638 }
639
TanFunction()640 TanFunction::TanFunction() : MathFunction("tan", 1) {
641 Argument *arg = new AngleArgument();
642 arg->setHandleVector(true);
643 setArgumentDefinition(1, arg);
644 }
representsNumber(const MathStructure &,bool) const645 bool TanFunction::representsNumber(const MathStructure&, bool) const {return false;}
representsReal(const MathStructure &,bool) const646 bool TanFunction::representsReal(const MathStructure&, bool) const {return false;}
representsNonComplex(const MathStructure & vargs,bool) const647 bool TanFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)648 int TanFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
649
650 if(vargs[0].isVector()) return 0;
651 if(CALCULATOR->getRadUnit()) {
652 if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getRadUnit()) {
653 mstruct = vargs[0][0];
654 } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getRadUnit()) {
655 mstruct = vargs[0][1];
656 } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getDegUnit()) {
657 mstruct = vargs[0][0];
658 mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI);
659 mstruct.multiply(Number(1, 180), true);
660 } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getDegUnit()) {
661 mstruct = vargs[0][1];
662 mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI);
663 mstruct.multiply(Number(1, 180), true);
664 } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getGraUnit()) {
665 mstruct = vargs[0][0];
666 mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI);
667 mstruct.multiply(Number(1, 200), true);
668 } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getGraUnit()) {
669 mstruct = vargs[0][1];
670 mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI);
671 mstruct.multiply(Number(1, 200), true);
672 } else {
673 mstruct = vargs[0];
674 mstruct.convert(CALCULATOR->getRadUnit());
675 mstruct /= CALCULATOR->getRadUnit();
676 }
677 } else {
678 mstruct = vargs[0];
679 }
680
681 MathFunction *f = NULL;
682 if(eo.approximation == APPROXIMATION_APPROXIMATE && (eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES || eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS)) {
683 if(mstruct.isMultiplication() && mstruct.size() == 3 && mstruct[0].isFunction() && mstruct[0].size() == 1 && mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI && mstruct[2].isNumber() && mstruct[2].number().equals(Number(1, eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES ? 180 : 200))) {
684 f = mstruct[0].function();
685 }
686 }
687
688 if(eo.approximation == APPROXIMATION_TRY_EXACT) {
689 EvaluationOptions eo2 = eo;
690 eo2.approximation = APPROXIMATION_EXACT;
691 CALCULATOR->beginTemporaryStopMessages();
692 mstruct.eval(eo2);
693 } else if(!f) {
694 mstruct.eval(eo);
695 }
696
697 if(mstruct.isVector()) {
698 if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true);
699 if(CALCULATOR->getRadUnit()) {
700 for(size_t i = 0; i < mstruct.size(); i++) {
701 mstruct[i] *= CALCULATOR->getRadUnit();
702 }
703 }
704 return -1;
705 }
706
707 bool b = false, b_recalc = true;
708
709 if(eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES || eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS) {
710 if(!f && mstruct.isMultiplication() && mstruct.size() == 3 && mstruct[2].isFunction() && mstruct[2].size() == 1 && mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI && mstruct[0].isNumber() && mstruct[0].number().equals(Number(1, eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES ? 180 : 200))) {
711 f = mstruct[2].function();
712 }
713 } else if(mstruct.isFunction() && mstruct.size() == 1) {
714 f = mstruct.function();
715 }
716
717 if(mstruct.isVariable() && mstruct.variable()->id() == VARIABLE_ID_PI) {
718 mstruct.clear();
719 b = true;
720 } else if(f) {
721 if(f->id() == FUNCTION_ID_ATAN) {
722 if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true);
723 mstruct.setToChild(1, true);
724 b = true;
725 } else if(f->id() == FUNCTION_ID_ASIN && (mstruct.isFunction() ? !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true) : (mstruct[2].isFunction() ? !mstruct[2][0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true) : !mstruct[0][0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)))) {
726 if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true);
727 mstruct.setToChild(1);
728 MathStructure *mmul = new MathStructure(mstruct);
729 mstruct ^= nr_two;
730 mstruct.negate();
731 mstruct += nr_one;
732 mstruct ^= nr_minus_half;
733 mstruct.multiply_nocopy(mmul);
734 b = true;
735 } else if(f->id() == FUNCTION_ID_ACOS && (mstruct.isFunction() ? !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true) : (mstruct[2].isFunction() ? !mstruct[2][0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true) : !mstruct[0][0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)))) {
736 if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true);
737 mstruct.setToChild(1);
738 MathStructure *mmul = new MathStructure(mstruct);
739 mstruct ^= nr_two;
740 mstruct.negate();
741 mstruct += nr_one;
742 mstruct ^= nr_half;
743 mstruct.divide_nocopy(mmul);
744 b = true;
745 }
746 } else if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isNumber() && mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI) {
747 if(mstruct[0].number().isInteger()) {
748 mstruct.clear();
749 b = true;
750 } else if(!mstruct[0].number().hasImaginaryPart() && !mstruct[0].number().includesInfinity() && !mstruct[0].number().isInterval()) {
751 Number nr(mstruct[0].number());
752 nr.frac();
753 bool b_neg = nr.isNegative();
754 nr.setNegative(false);
755 if(nr.equals(nr_half)) {
756 if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true);
757 if(!mstruct[0].number().numeratorIsOne() && !mstruct[0].number().numeratorEquals(3)) {
758 Number nr_int(mstruct[0].number());
759 nr_int.floor();
760 bool b_even = nr_int.isEven();
761 if(b_even) mstruct[0].set(nr_half, true);
762 else mstruct[0].set(Number(3, 2), true);
763 mstruct.childUpdated(1);
764 }
765 if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();
766 return -1;
767 } else if(nr.equals(Number(1, 4, 0))) {
768 if(b_neg) mstruct.set(-1, 1, 0);
769 else mstruct.set(1, 1, 0);
770 b = true;
771 } else if(nr.equals(Number(3, 4, 0))) {
772 if(!b_neg) mstruct.set(-1, 1, 0);
773 else mstruct.set(1, 1, 0);
774 b = true;
775 } else if(nr.equals(Number(1, 3, 0))) {
776 mstruct.set(3, 1, 0);
777 mstruct.raise_nocopy(new MathStructure(1, 2, 0));
778 if(b_neg) mstruct.negate();
779 b = true;
780 } else if(nr.equals(Number(2, 3, 0))) {
781 mstruct.set(3, 1, 0);
782 mstruct.raise_nocopy(new MathStructure(1, 2, 0));
783 if(!b_neg) mstruct.negate();
784 b = true;
785 } else if(nr.equals(Number(1, 6, 0))) {
786 mstruct.set(3, 1, 0);
787 mstruct.raise_nocopy(new MathStructure(-1, 2, 0));
788 if(b_neg) mstruct.negate();
789 b = true;
790 } else if(nr.equals(Number(5, 6, 0))) {
791 mstruct.set(3, 1, 0);
792 mstruct.raise_nocopy(new MathStructure(-1, 2, 0));
793 if(!b_neg) mstruct.negate();
794 b = true;
795 } else if(eo.approximation == APPROXIMATION_EXACT && (mstruct[0].number().isNegative() || !mstruct[0].number().isFraction() || mstruct[0].number().isGreaterThan(nr_half))) {
796 Number nr_int(mstruct[0].number());
797 nr_int.floor();
798 Number nr_frac = mstruct[0].number();
799 nr_frac -= nr_int;
800 if(nr_frac.isGreaterThan(nr_half)) {
801 nr_frac -= nr_half;
802 mstruct[0].number() = nr_half;
803 mstruct[0].number() -= nr_frac;
804 if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();
805 mstruct.transform(this);
806 mstruct.negate();
807 b = true;
808 } else {
809 mstruct[0].number() = nr_frac;
810 }
811 }
812 }
813 } else if(mstruct.isMultiplication() && mstruct.size() >= 2) {
814 bool b_pi = false;
815 for(size_t i = 0; i < mstruct.size(); i++) {
816 if(mstruct[i].isVariable() && mstruct[i].variable()->id() == VARIABLE_ID_PI) {
817 b_pi = !b_pi;
818 if(!b_pi) break;
819 } else if(!mstruct[i].representsInteger()) {
820 b_pi = false;
821 break;
822 }
823 }
824 if(b_pi) {
825 mstruct.clear();
826 b = true;
827 }
828 } else if(mstruct.isAddition()) {
829 size_t i = 0;
830 for(; i < mstruct.size(); i++) {
831 if((mstruct[i].isVariable() && mstruct[i].variable()->id() == VARIABLE_ID_PI) || (mstruct[i].isMultiplication() && mstruct[i].size() == 2 && mstruct[i][1].isVariable() && mstruct[i][1].variable()->id() == VARIABLE_ID_PI && mstruct[i][0].isNumber())) {
832 if(mstruct[i].isVariable() || mstruct[i][0].number().isInteger()) {
833 mstruct.delChild(i + 1);
834 b_recalc = false;
835 break;
836 } else if(mstruct[i][0].number().isReal() && (mstruct[i][0].number().isNegative() || !mstruct[i][0].number().isFraction())) {
837 Number nr_int = mstruct[i][0].number();
838 nr_int.floor();
839 mstruct[i][0].number() -= nr_int;
840 b_recalc = false;
841 break;
842 }
843 }
844 }
845 }
846 if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(b);
847 if(b) return 1;
848 if(eo.approximation == APPROXIMATION_TRY_EXACT && !mstruct.isNumber()) {
849 EvaluationOptions eo2 = eo;
850 eo2.approximation = APPROXIMATION_APPROXIMATE;
851 if(b_recalc) {
852 mstruct = vargs[0];
853 if(CALCULATOR->getRadUnit()) {
854 mstruct.convert(CALCULATOR->getRadUnit());
855 mstruct /= CALCULATOR->getRadUnit();
856 }
857 mstruct.eval(eo2);
858 }
859 }
860
861 if(mstruct.isNumber()) {
862 Number nr(mstruct.number());
863 if(nr.tan() && !(eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) && !(!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) && !(!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) {
864 mstruct.set(nr, true);
865 return 1;
866 }
867 }
868
869 if(trig_remove_i(mstruct)) {
870 mstruct.transformById(FUNCTION_ID_TANH);
871 mstruct *= nr_one_i;
872 return 1;
873 }
874
875 if(has_predominately_negative_sign(mstruct)) {
876 negate_struct(mstruct);
877 if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();
878 mstruct.transform(this);
879 mstruct.negate();
880 return 1;
881 }
882
883 if(CALCULATOR->getRadUnit()) {
884 if(mstruct.isVector()) {
885 for(size_t i = 0; i < mstruct.size(); i++) {
886 mstruct[i] *= CALCULATOR->getRadUnit();
887 }
888 } else {
889 mstruct *= CALCULATOR->getRadUnit();
890 }
891 }
892
893 return -1;
894 }
895
AsinFunction()896 AsinFunction::AsinFunction() : MathFunction("asin", 1) {
897 setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false));
898 }
representsNumber(const MathStructure & vargs,bool allow_units) const899 bool AsinFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)900 int AsinFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
901 if(vargs[0].isVector()) return 0;
902 mstruct = vargs[0];
903 if(eo.approximation == APPROXIMATION_TRY_EXACT) {
904 EvaluationOptions eo2 = eo;
905 eo2.approximation = APPROXIMATION_EXACT;
906 CALCULATOR->beginTemporaryStopMessages();
907 mstruct.eval(eo2);
908 } else {
909 mstruct.eval(eo);
910 }
911 if(mstruct.isVector()) {
912 if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true);
913 return -1;
914 }
915 if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0] == nr_half && mstruct[1].isPower() && mstruct[1][1] == nr_half) {
916 if(mstruct[1][0] == nr_two) {
917 switch(eo.parse_options.angle_unit) {
918 case ANGLE_UNIT_DEGREES: {mstruct.set(45, 1, 0); break;}
919 case ANGLE_UNIT_GRADIANS: {mstruct.set(50, 1, 0); break;}
920 case ANGLE_UNIT_RADIANS: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
921 default: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}}
922 }
923 if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true);
924 return 1;
925 } else if(mstruct[1][0] == nr_three) {
926 switch(eo.parse_options.angle_unit) {
927 case ANGLE_UNIT_DEGREES: {mstruct.set(60, 1, 0); break;}
928 case ANGLE_UNIT_GRADIANS: {mstruct.set(200, 3, 0); break;}
929 case ANGLE_UNIT_RADIANS: {mstruct.set(1, 3, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
930 default: {mstruct.set(1, 3, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}}
931 }
932 if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true);
933 return 1;
934 }
935 } else if(mstruct.isPower() && mstruct[1] == nr_minus_half && mstruct[0] == nr_two) {
936 switch(eo.parse_options.angle_unit) {
937 case ANGLE_UNIT_DEGREES: {mstruct.set(45, 1, 0); break;}
938 case ANGLE_UNIT_GRADIANS: {mstruct.set(50, 1, 0); break;}
939 case ANGLE_UNIT_RADIANS: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
940 default: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}}
941 }
942 if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true);
943 return 1;
944 }
945 if(eo.approximation == APPROXIMATION_TRY_EXACT) {
946 if(!mstruct.isNumber()) {
947 CALCULATOR->endTemporaryStopMessages(false);
948 EvaluationOptions eo2 = eo;
949 eo2.approximation = APPROXIMATION_APPROXIMATE;
950 mstruct = vargs[0];
951 mstruct.eval(eo2);
952 } else {
953 CALCULATOR->endTemporaryStopMessages(true);
954 }
955 }
956 if(!mstruct.isNumber()) {
957 if(trig_remove_i(mstruct)) {
958 mstruct.transformById(FUNCTION_ID_ASINH);
959 mstruct *= nr_one_i;
960 switch(eo.parse_options.angle_unit) {
961 case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
962 case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
963 case ANGLE_UNIT_RADIANS: {break;}
964 default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;}
965 }
966 return 1;
967 }
968 if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); mstruct.transform(this); mstruct.negate(); return 1;}
969 return -1;
970 }
971 if(mstruct.number().isZero()) {
972 mstruct.clear();
973 } else if(mstruct.number().isOne()) {
974 switch(eo.parse_options.angle_unit) {
975 case ANGLE_UNIT_DEGREES: {
976 mstruct.set(90, 1, 0);
977 break;
978 }
979 case ANGLE_UNIT_GRADIANS: {
980 mstruct.set(100, 1, 0);
981 break;
982 }
983 case ANGLE_UNIT_RADIANS: {
984 mstruct.set(1, 2, 0);
985 mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI)));
986 break;
987 }
988 default: {
989 mstruct.set(1, 2, 0);
990 mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI)));
991 if(CALCULATOR->getRadUnit()) {
992 mstruct *= CALCULATOR->getRadUnit();
993 }
994 }
995 }
996 } else if(mstruct.number().isMinusOne()) {
997 switch(eo.parse_options.angle_unit) {
998 case ANGLE_UNIT_DEGREES: {
999 mstruct.set(-90, 1, 0);
1000 break;
1001 }
1002 case ANGLE_UNIT_GRADIANS: {
1003 mstruct.set(-100, 1, 0);
1004 break;
1005 }
1006 case ANGLE_UNIT_RADIANS: {
1007 mstruct.set(-1, 2, 0);
1008 mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI)));
1009 break;
1010 }
1011 default: {
1012 mstruct.set(-1, 2, 0);
1013 mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI)));
1014 if(CALCULATOR->getRadUnit()) {
1015 mstruct *= CALCULATOR->getRadUnit();
1016 }
1017 }
1018 }
1019 } else if(mstruct.number().equals(nr_half)) {
1020 switch(eo.parse_options.angle_unit) {
1021 case ANGLE_UNIT_DEGREES: {
1022 mstruct.set(30, 1, 0);
1023 break;
1024 }
1025 case ANGLE_UNIT_GRADIANS: {
1026 mstruct.set(100, 3, 0);
1027 break;
1028 }
1029 case ANGLE_UNIT_RADIANS: {
1030 mstruct.set(1, 6, 0);
1031 mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI)));
1032 break;
1033 }
1034 default: {
1035 mstruct.set(1, 6, 0);
1036 mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI)));
1037 if(CALCULATOR->getRadUnit()) {
1038 mstruct *= CALCULATOR->getRadUnit();
1039 }
1040 }
1041 }
1042 } else {
1043 Number nr = mstruct.number();
1044 if(!nr.asin() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) {
1045 if(trig_remove_i(mstruct)) {
1046 mstruct.transformById(FUNCTION_ID_ASINH);
1047 mstruct *= nr_one_i;
1048 switch(eo.parse_options.angle_unit) {
1049 case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
1050 case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
1051 case ANGLE_UNIT_RADIANS: {break;}
1052 default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;}
1053 }
1054 return 1;
1055 }
1056 if(has_predominately_negative_sign(mstruct)) {mstruct.number().negate(); mstruct.transform(this); mstruct.negate(); return 1;}
1057 return -1;
1058 }
1059 mstruct = nr;
1060 switch(eo.parse_options.angle_unit) {
1061 case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
1062 case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
1063 case ANGLE_UNIT_RADIANS: {break;}
1064 default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;}
1065 }
1066 }
1067 return 1;
1068
1069 }
1070
AcosFunction()1071 AcosFunction::AcosFunction() : MathFunction("acos", 1) {
1072 setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false));
1073 }
representsNumber(const MathStructure & vargs,bool allow_units) const1074 bool AcosFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)1075 int AcosFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
1076 if(vargs[0].isVector()) return 0;
1077 mstruct = vargs[0];
1078 if(eo.approximation == APPROXIMATION_TRY_EXACT) {
1079 EvaluationOptions eo2 = eo;
1080 eo2.approximation = APPROXIMATION_EXACT;
1081 CALCULATOR->beginTemporaryStopMessages();
1082 mstruct.eval(eo2);
1083 } else {
1084 mstruct.eval(eo);
1085 }
1086 if(mstruct.isVector()) {
1087 if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true);
1088 return -1;
1089 }
1090 if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0] == nr_half && mstruct[1].isPower() && mstruct[1][1] == nr_half) {
1091 if(mstruct[1][0] == nr_two) {
1092 switch(eo.parse_options.angle_unit) {
1093 case ANGLE_UNIT_DEGREES: {mstruct.set(45, 1, 0); break;}
1094 case ANGLE_UNIT_GRADIANS: {mstruct.set(50, 1, 0); break;}
1095 case ANGLE_UNIT_RADIANS: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
1096 default: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}}
1097 }
1098 if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true);
1099 return 1;
1100 } else if(mstruct[1][0] == nr_three) {
1101 switch(eo.parse_options.angle_unit) {
1102 case ANGLE_UNIT_DEGREES: {mstruct.set(30, 1, 0); break;}
1103 case ANGLE_UNIT_GRADIANS: {mstruct.set(100, 3, 0); break;}
1104 case ANGLE_UNIT_RADIANS: {mstruct.set(1, 6, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
1105 default: {mstruct.set(1, 6, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}}
1106 }
1107 if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true);
1108 return 1;
1109 }
1110 } else if(mstruct.isPower() && mstruct[1] == nr_minus_half && mstruct[0] == nr_two) {
1111 switch(eo.parse_options.angle_unit) {
1112 case ANGLE_UNIT_DEGREES: {mstruct.set(45, 1, 0); break;}
1113 case ANGLE_UNIT_GRADIANS: {mstruct.set(50, 1, 0); break;}
1114 case ANGLE_UNIT_RADIANS: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
1115 default: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}}
1116 }
1117 if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true);
1118 return 1;
1119 }
1120 if(eo.approximation == APPROXIMATION_TRY_EXACT) {
1121 if(!mstruct.isNumber()) {
1122 CALCULATOR->endTemporaryStopMessages(false);
1123 EvaluationOptions eo2 = eo;
1124 eo2.approximation = APPROXIMATION_APPROXIMATE;
1125 mstruct = vargs[0];
1126 mstruct.eval(eo2);
1127 } else {
1128 CALCULATOR->endTemporaryStopMessages(true);
1129 }
1130 }
1131 if(!mstruct.isNumber()) {
1132 if(has_predominately_negative_sign(mstruct)) {
1133 negate_struct(mstruct); mstruct.transformById(FUNCTION_ID_ASIN);
1134 switch(eo.parse_options.angle_unit) {
1135 case ANGLE_UNIT_DEGREES: {mstruct += Number(90, 1, 0); break;}
1136 case ANGLE_UNIT_GRADIANS: {mstruct += Number(100, 1, 0); break;}
1137 case ANGLE_UNIT_RADIANS: {mstruct += CALCULATOR->getVariableById(VARIABLE_ID_PI); mstruct.last() *= nr_half; break;}
1138 default: {mstruct += CALCULATOR->getVariableById(VARIABLE_ID_PI); mstruct.last() *= nr_half; if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;}
1139 }
1140 return 1;
1141 }
1142 return -1;
1143 }
1144 if(mstruct.number().isZero()) {
1145 switch(eo.parse_options.angle_unit) {
1146 case ANGLE_UNIT_DEGREES: {
1147 mstruct.set(90, 1, 0);
1148 break;
1149 }
1150 case ANGLE_UNIT_GRADIANS: {
1151 mstruct.set(100, 1, 0);
1152 break;
1153 }
1154 case ANGLE_UNIT_RADIANS: {
1155 mstruct.set(1, 2, 0);
1156 mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI)));
1157 break;
1158 }
1159 default: {
1160 mstruct.set(1, 2, 0);
1161 mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI)));
1162 if(CALCULATOR->getRadUnit()) {
1163 mstruct *= CALCULATOR->getRadUnit();
1164 }
1165 }
1166 }
1167 } else if(mstruct.number().isOne()) {
1168 mstruct.clear();
1169 } else if(mstruct.number().isMinusOne()) {
1170 switch(eo.parse_options.angle_unit) {
1171 case ANGLE_UNIT_DEGREES: {
1172 mstruct.set(180, 1, 0);
1173 break;
1174 }
1175 case ANGLE_UNIT_GRADIANS: {
1176 mstruct.set(200, 1, 0);
1177 break;
1178 }
1179 case ANGLE_UNIT_RADIANS: {
1180 mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI));
1181 break;
1182 }
1183 default: {
1184 mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI));
1185 if(CALCULATOR->getRadUnit()) {
1186 mstruct *= CALCULATOR->getRadUnit();
1187 }
1188 }
1189 }
1190 } else if(mstruct.number().equals(nr_half)) {
1191 switch(eo.parse_options.angle_unit) {
1192 case ANGLE_UNIT_DEGREES: {
1193 mstruct.set(60, 1, 0);
1194 break;
1195 }
1196 case ANGLE_UNIT_GRADIANS: {
1197 mstruct.set(200, 3, 0);
1198 break;
1199 }
1200 case ANGLE_UNIT_RADIANS: {
1201 mstruct.set(1, 3, 0);
1202 mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI)));
1203 break;
1204 }
1205 default: {
1206 mstruct.set(1, 3, 0);
1207 mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI)));
1208 if(CALCULATOR->getRadUnit()) {
1209 mstruct *= CALCULATOR->getRadUnit();
1210 }
1211 }
1212 }
1213 } else {
1214 Number nr = mstruct.number();
1215 if(!nr.acos() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) {
1216 if(has_predominately_negative_sign(mstruct)) {
1217 mstruct.number().negate();
1218 mstruct.transformById(FUNCTION_ID_ASIN);
1219 switch(eo.parse_options.angle_unit) {
1220 case ANGLE_UNIT_DEGREES: {mstruct += Number(90, 1, 0); break;}
1221 case ANGLE_UNIT_GRADIANS: {mstruct += Number(100, 1, 0); break;}
1222 case ANGLE_UNIT_RADIANS: {mstruct += CALCULATOR->getVariableById(VARIABLE_ID_PI); mstruct.last() *= nr_half; break;}
1223 default: {mstruct += CALCULATOR->getVariableById(VARIABLE_ID_PI); mstruct.last() *= nr_half; if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;}
1224 }
1225 return 1;
1226 }
1227 return -1;
1228 }
1229 mstruct = nr;
1230 switch(eo.parse_options.angle_unit) {
1231 case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
1232 case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
1233 case ANGLE_UNIT_RADIANS: {break;}
1234 default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;}
1235 }
1236 }
1237 return 1;
1238
1239 }
1240
AtanFunction()1241 AtanFunction::AtanFunction() : MathFunction("atan", 1) {
1242 setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false));
1243 }
representsNumber(const MathStructure & vargs,bool allow_units) const1244 bool AtanFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && (vargs[0].representsReal(allow_units) || (vargs[0].isNumber() && !vargs[0].number().isI() && !vargs[0].number().isMinusI()));}
representsReal(const MathStructure & vargs,bool) const1245 bool AtanFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsNonComplex(const MathStructure & vargs,bool) const1246 bool AtanFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)1247 int AtanFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
1248 if(vargs[0].isVector()) return 0;
1249 mstruct = vargs[0];
1250 if(eo.approximation == APPROXIMATION_TRY_EXACT) {
1251 EvaluationOptions eo2 = eo;
1252 eo2.approximation = APPROXIMATION_EXACT;
1253 CALCULATOR->beginTemporaryStopMessages();
1254 mstruct.eval(eo2);
1255 } else {
1256 mstruct.eval(eo);
1257 }
1258 if(mstruct.isVector()) {
1259 if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true);
1260 return -1;
1261 }
1262 if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isNumber() && mstruct[1].isPower() && mstruct[1][1] == nr_half && mstruct[1][0] == nr_three && mstruct[0].number() == Number(1, 3)) {
1263 if(mstruct[1][0] == nr_three) {
1264 switch(eo.parse_options.angle_unit) {
1265 case ANGLE_UNIT_DEGREES: {mstruct.set(30, 1, 0); break;}
1266 case ANGLE_UNIT_GRADIANS: {mstruct.set(100, 3, 0); break;}
1267 case ANGLE_UNIT_RADIANS: {mstruct.set(1, 6, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
1268 default: {mstruct.set(1, 6, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}}
1269 }
1270 if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true);
1271 return 1;
1272 }
1273 } else if(mstruct.isPower() && mstruct[1] == nr_half && mstruct[0] == nr_three) {
1274 switch(eo.parse_options.angle_unit) {
1275 case ANGLE_UNIT_DEGREES: {mstruct.set(60, 1, 0); break;}
1276 case ANGLE_UNIT_GRADIANS: {mstruct.set(200, 3, 0); break;}
1277 case ANGLE_UNIT_RADIANS: {mstruct.set(1, 3, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
1278 default: {mstruct.set(1, 3, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}}
1279 }
1280 if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true);
1281 return 1;
1282 }
1283 if(eo.approximation == APPROXIMATION_TRY_EXACT) {
1284 if(!mstruct.isNumber()) {
1285 CALCULATOR->endTemporaryStopMessages(false);
1286 EvaluationOptions eo2 = eo;
1287 eo2.approximation = APPROXIMATION_APPROXIMATE;
1288 mstruct = vargs[0];
1289 mstruct.eval(eo2);
1290 } else {
1291 CALCULATOR->endTemporaryStopMessages(true);
1292 }
1293 }
1294 if(!mstruct.isNumber()) {
1295 if(trig_remove_i(mstruct)) {
1296 mstruct.transformById(FUNCTION_ID_ATANH);
1297 mstruct *= nr_one_i;
1298 switch(eo.parse_options.angle_unit) {
1299 case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
1300 case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
1301 case ANGLE_UNIT_RADIANS: {break;}
1302 default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;}
1303 }
1304 return 1;
1305 }
1306 if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); mstruct.transform(this); mstruct.negate(); return 1;}
1307 return -1;
1308 }
1309 if(mstruct.number().isZero()) {
1310 mstruct.clear();
1311 } else if(eo.allow_infinite && mstruct.number().isI()) {
1312 Number nr; nr.setImaginaryPart(nr_plus_inf);
1313 mstruct = nr;
1314 } else if(eo.allow_infinite && mstruct.number().isMinusI()) {
1315 Number nr; nr.setImaginaryPart(nr_minus_inf);
1316 mstruct = nr;
1317 } else if(mstruct.number().isPlusInfinity()) {
1318 switch(eo.parse_options.angle_unit) {
1319 case ANGLE_UNIT_DEGREES: {
1320 mstruct.set(90, 1, 0);
1321 break;
1322 }
1323 case ANGLE_UNIT_GRADIANS: {
1324 mstruct.set(100, 1, 0);
1325 break;
1326 }
1327 case ANGLE_UNIT_RADIANS: {
1328 mstruct.set(1, 2, 0);
1329 mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI)));
1330 break;
1331 }
1332 default: {
1333 mstruct.set(1, 2, 0);
1334 mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI)));
1335 if(CALCULATOR->getRadUnit()) {
1336 mstruct *= CALCULATOR->getRadUnit();
1337 }
1338 }
1339 }
1340 } else if(mstruct.number().isMinusInfinity()) {
1341 switch(eo.parse_options.angle_unit) {
1342 case ANGLE_UNIT_DEGREES: {
1343 mstruct.set(-90, 1, 0);
1344 break;
1345 }
1346 case ANGLE_UNIT_GRADIANS: {
1347 mstruct.set(-100, 1, 0);
1348 break;
1349 }
1350 case ANGLE_UNIT_RADIANS: {
1351 mstruct.set(-1, 2, 0);
1352 mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI)));
1353 break;
1354 }
1355 default: {
1356 mstruct.set(-1, 2, 0);
1357 mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI)));
1358 if(CALCULATOR->getRadUnit()) {
1359 mstruct *= CALCULATOR->getRadUnit();
1360 }
1361 }
1362 }
1363 } else if(mstruct.number().isOne()) {
1364 switch(eo.parse_options.angle_unit) {
1365 case ANGLE_UNIT_DEGREES: {
1366 mstruct.set(45, 1, 0);
1367 break;
1368 }
1369 case ANGLE_UNIT_GRADIANS: {
1370 mstruct.set(50, 1, 0);
1371 break;
1372 }
1373 case ANGLE_UNIT_RADIANS: {
1374 mstruct.set(1, 4, 0);
1375 mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI)));
1376 break;
1377 }
1378 default: {
1379 mstruct.set(1, 4, 0);
1380 mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI)));
1381 if(CALCULATOR->getRadUnit()) {
1382 mstruct *= CALCULATOR->getRadUnit();
1383 }
1384 }
1385 }
1386 } else if(mstruct.number().isMinusOne()) {
1387 switch(eo.parse_options.angle_unit) {
1388 case ANGLE_UNIT_DEGREES: {
1389 mstruct.set(-45, 1, 0);
1390 break;
1391 }
1392 case ANGLE_UNIT_GRADIANS: {
1393 mstruct.set(-50, 1, 0);
1394 break;
1395 }
1396 case ANGLE_UNIT_RADIANS: {
1397 mstruct.set(-1, 4, 0);
1398 mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI)));
1399 break;
1400 }
1401 default: {
1402 mstruct.set(-1, 4, 0);
1403 mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI)));
1404 if(CALCULATOR->getRadUnit()) {
1405 mstruct *= CALCULATOR->getRadUnit();
1406 }
1407 }
1408 }
1409 } else {
1410 Number nr = mstruct.number();
1411 if(!nr.atan() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) {
1412 if(trig_remove_i(mstruct)) {
1413 mstruct.transformById(FUNCTION_ID_ATANH);
1414 mstruct *= nr_one_i;
1415 switch(eo.parse_options.angle_unit) {
1416 case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
1417 case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
1418 case ANGLE_UNIT_RADIANS: {break;}
1419 default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;}
1420 }
1421 return 1;
1422 }
1423 if(has_predominately_negative_sign(mstruct)) {mstruct.number().negate(); mstruct.transform(this); mstruct.negate(); return 1;}
1424 return -1;
1425 }
1426 mstruct = nr;
1427 switch(eo.parse_options.angle_unit) {
1428 case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
1429 case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;}
1430 case ANGLE_UNIT_RADIANS: {break;}
1431 default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;}
1432 }
1433 }
1434 return 1;
1435
1436 }
1437
SinhFunction()1438 SinhFunction::SinhFunction() : MathFunction("sinh", 1) {
1439 setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false));
1440 }
representsNumber(const MathStructure & vargs,bool allow_units) const1441 bool SinhFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);}
representsReal(const MathStructure & vargs,bool) const1442 bool SinhFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsNonComplex(const MathStructure & vargs,bool) const1443 bool SinhFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)1444 int SinhFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
1445 if(vargs[0].isVector()) return 0;
1446 mstruct = vargs[0];
1447 mstruct.eval(eo);
1448 if(mstruct.isVector()) return -1;
1449 if(mstruct.isFunction() && mstruct.size() == 1) {
1450 if(mstruct.function()->id() == FUNCTION_ID_ASINH) {
1451 mstruct.setToChild(1, true);
1452 return 1;
1453 } else if(mstruct.function()->id() == FUNCTION_ID_ACOSH && !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, false, false, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)) {
1454 mstruct.setToChild(1);
1455 MathStructure *mmul = new MathStructure(mstruct);
1456 mstruct += nr_minus_one;
1457 mstruct ^= nr_half;
1458 *mmul += nr_one;
1459 *mmul ^= nr_half;
1460 mstruct.multiply_nocopy(mmul);
1461 return 1;
1462 } else if(mstruct.function()->id() == FUNCTION_ID_ATANH && !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, false, false, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)) {
1463 mstruct.setToChild(1);
1464 MathStructure *mmul = new MathStructure(mstruct);
1465 mstruct ^= nr_two;
1466 mstruct.negate();
1467 mstruct += nr_one;
1468 mstruct ^= nr_minus_half;
1469 mstruct.multiply_nocopy(mmul);
1470 return 1;
1471 }
1472 }
1473 if(!mstruct.isNumber()) {
1474 if(trig_remove_i(mstruct)) {mstruct *= CALCULATOR->getRadUnit(); mstruct.transformById(FUNCTION_ID_SIN); mstruct *= nr_one_i; return 1;}
1475 if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); mstruct.transform(this); mstruct.negate(); return 1;}
1476 return -1;
1477 }
1478 Number nr = mstruct.number();
1479 if(!nr.sinh() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) {
1480 if(trig_remove_i(mstruct)) {mstruct *= CALCULATOR->getRadUnit(); mstruct.transformById(FUNCTION_ID_SIN); mstruct *= nr_one_i; return 1;}
1481 if(has_predominately_negative_sign(mstruct)) {mstruct.number().negate(); mstruct.transform(this); mstruct.negate(); return 1;}
1482 return -1;
1483 }
1484 mstruct = nr;
1485 return 1;
1486 }
CoshFunction()1487 CoshFunction::CoshFunction() : MathFunction("cosh", 1) {
1488 setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false));
1489 }
representsNumber(const MathStructure & vargs,bool allow_units) const1490 bool CoshFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);}
representsReal(const MathStructure & vargs,bool) const1491 bool CoshFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsNonComplex(const MathStructure & vargs,bool) const1492 bool CoshFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)1493 int CoshFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
1494 if(vargs[0].isVector()) return 0;
1495 mstruct = vargs[0];
1496 mstruct.eval(eo);
1497 if(mstruct.isVector()) return -1;
1498 if(mstruct.isFunction() && mstruct.size() == 1) {
1499 if(mstruct.function()->id() == FUNCTION_ID_ACOSH) {
1500 mstruct.setToChild(1, true);
1501 return 1;
1502 } else if(mstruct.function()->id() == FUNCTION_ID_ASINH) {
1503 mstruct.setToChild(1);
1504 mstruct ^= nr_two;
1505 mstruct += nr_one;
1506 mstruct ^= nr_half;
1507 return 1;
1508 } else if(mstruct.function()->id() == FUNCTION_ID_ATANH) {
1509 mstruct.setToChild(1);
1510 mstruct ^= nr_two;
1511 mstruct.negate();
1512 mstruct += nr_one;
1513 mstruct ^= nr_minus_half;
1514 return 1;
1515 }
1516 }
1517 if(!mstruct.isNumber()) {
1518 if(trig_remove_i(mstruct)) {mstruct *= CALCULATOR->getRadUnit(); mstruct.transformById(FUNCTION_ID_COS); return 1;}
1519 if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); return -1;}
1520 return -1;
1521 }
1522 Number nr = mstruct.number();
1523 if(!nr.cosh() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) {
1524 if(trig_remove_i(mstruct)) {mstruct *= CALCULATOR->getRadUnit(); mstruct.transformById(FUNCTION_ID_COS); return 1;}
1525 if(has_predominately_negative_sign(mstruct)) mstruct.number().negate();
1526 return -1;
1527 }
1528 mstruct = nr;
1529 return 1;
1530 }
TanhFunction()1531 TanhFunction::TanhFunction() : MathFunction("tanh", 1) {
1532 setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false));
1533 }
representsNumber(const MathStructure & vargs,bool allow_units) const1534 bool TanhFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);}
representsReal(const MathStructure & vargs,bool) const1535 bool TanhFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsNonComplex(const MathStructure & vargs,bool) const1536 bool TanhFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)1537 int TanhFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&eo) {
1538 if(vargs[0].isVector()) return 0;
1539 mstruct = vargs[0];
1540 mstruct.eval(eo);
1541 if(mstruct.isVector()) return -1;
1542 if(mstruct.isFunction() && mstruct.size() == 1) {
1543 if(mstruct.function()->id() == FUNCTION_ID_ATANH) {
1544 mstruct.setToChild(1, true);
1545 return 1;
1546 } else if(mstruct.function()->id() == FUNCTION_ID_ASINH && !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, false, false, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)) {
1547 mstruct.setToChild(1);
1548 MathStructure *mmul = new MathStructure(mstruct);
1549 mstruct ^= nr_two;
1550 mstruct += nr_one;
1551 mstruct ^= nr_minus_half;
1552 mstruct.multiply_nocopy(mmul);
1553 return 1;
1554 } else if(mstruct.function()->id() == FUNCTION_ID_ACOSH && !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, false, false, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)) {
1555 mstruct.setToChild(1);
1556 MathStructure *mmul = new MathStructure(mstruct);
1557 MathStructure *mmul2 = new MathStructure(mstruct);
1558 *mmul2 ^= nr_minus_one;
1559 mstruct += nr_minus_one;
1560 mstruct ^= nr_half;
1561 *mmul += nr_one;
1562 *mmul ^= nr_half;
1563 mstruct.multiply_nocopy(mmul);
1564 mstruct.multiply_nocopy(mmul2);
1565 return 1;
1566 }
1567 }
1568 if(!mstruct.isNumber()) {
1569 if(trig_remove_i(mstruct)) {mstruct *= CALCULATOR->getRadUnit(); mstruct.transformById(FUNCTION_ID_TAN); mstruct *= nr_one_i; return 1;}
1570 if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); mstruct.transform(this); mstruct.negate(); return 1;}
1571 return -1;
1572 }
1573 Number nr = mstruct.number();
1574 if(!nr.tanh() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) {
1575 if(has_predominately_negative_sign(mstruct)) {mstruct.number().negate(); mstruct.transform(this); mstruct.negate(); return 1;}
1576 if(trig_remove_i(mstruct)) {mstruct *= CALCULATOR->getRadUnit(); mstruct.transformById(FUNCTION_ID_TAN); mstruct *= nr_one_i; return 1;}
1577 return -1;
1578 }
1579 mstruct = nr;
1580 return 1;
1581 }
AsinhFunction()1582 AsinhFunction::AsinhFunction() : MathFunction("asinh", 1) {
1583 setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false));
1584 }
representsNumber(const MathStructure & vargs,bool allow_units) const1585 bool AsinhFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);}
representsReal(const MathStructure & vargs,bool) const1586 bool AsinhFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();}
representsNonComplex(const MathStructure & vargs,bool) const1587 bool AsinhFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)1588 int AsinhFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
1589 if(vargs[0].isVector()) return 0;
1590 mstruct = vargs[0];
1591 mstruct.eval(eo);
1592 if(mstruct.isVector()) return -1;
1593 if(!mstruct.isNumber()) {
1594 if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); mstruct.transform(this); mstruct.negate(); return 1;}
1595 return -1;
1596 }
1597 Number nr = mstruct.number();
1598 if(!nr.asinh() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) {
1599 if(has_predominately_negative_sign(mstruct)) {mstruct.number().negate(); mstruct.transform(this); mstruct.negate(); return 1;}
1600 return -1;
1601 }
1602 mstruct = nr;
1603 return 1;
1604 }
AcoshFunction()1605 AcoshFunction::AcoshFunction() : MathFunction("acosh", 1) {
1606 setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false));
1607 }
representsNumber(const MathStructure & vargs,bool allow_units) const1608 bool AcoshFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)1609 int AcoshFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
1610 if(eo.allow_complex && vargs[0].isZero()) {
1611 mstruct.set(1, 2, 0);
1612 mstruct.number() *= nr_one_i;
1613 mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI);
1614 return 1;
1615 } else if(vargs[0].isOne()) {
1616 mstruct.clear();
1617 return 1;
1618 } else if(eo.approximation != APPROXIMATION_APPROXIMATE && eo.allow_complex && vargs[0].number() <= -1) {
1619 mstruct = nr_one_i;
1620 mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI);
1621 mstruct.add_nocopy(new MathStructure(this, &vargs[0], NULL));
1622 mstruct.last()[0].negate();
1623 return 1;
1624 }
1625 Number nr(vargs[0].number());
1626 if(!nr.acosh() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) {
1627 return 0;
1628 }
1629 mstruct = nr;
1630 return 1;
1631 }
AtanhFunction()1632 AtanhFunction::AtanhFunction() : MathFunction("atanh", 1) {
1633 setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false));
1634 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)1635 int AtanhFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
1636 if(vargs[0].isVector()) return 0;
1637 mstruct = vargs[0];
1638 mstruct.eval(eo);
1639 if(mstruct.isVector()) return -1;
1640 if(!mstruct.isNumber()) {
1641 if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); mstruct.transform(this); mstruct.negate(); return 1;}
1642 return -1;
1643 }
1644 if(eo.allow_complex && mstruct.number().includesInfinity()) {
1645 if(mstruct.number().isPlusInfinity() || (!mstruct.number().hasRealPart() && mstruct.number().hasImaginaryPart() && mstruct.number().internalImaginary()->isMinusInfinity())) {
1646 mstruct = nr_minus_half;
1647 mstruct *= nr_one_i;
1648 mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI);
1649 return true;
1650 } else if(mstruct.number().isMinusInfinity() || (!mstruct.number().hasRealPart() && mstruct.number().hasImaginaryPart() && mstruct.number().internalImaginary()->isPlusInfinity())) {
1651 mstruct = nr_half;
1652 mstruct *= nr_one_i;
1653 mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI);
1654 return true;
1655 }
1656 } else if(eo.approximation != APPROXIMATION_APPROXIMATE && eo.allow_complex && mstruct.number() > 1) {
1657 mstruct.set(-1, 2, 0);
1658 mstruct.number() *= nr_one_i;
1659 mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI);
1660 mstruct.add_nocopy(new MathStructure(this, &vargs[0], NULL));
1661 mstruct.last()[0].inverse();
1662 return 1;
1663 } else if(eo.approximation != APPROXIMATION_APPROXIMATE && eo.allow_complex && mstruct.number() < -1) {
1664 mstruct.set(1, 2, 0);
1665 mstruct.number() *= nr_one_i;
1666 mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI);
1667 mstruct.add_nocopy(new MathStructure(this, &vargs[0], NULL));
1668 mstruct.last()[0].inverse();
1669 mstruct.last()[0].negate();
1670 mstruct.last().negate();
1671 return 1;
1672 }
1673 Number nr = mstruct.number();
1674 if(!nr.atanh() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) {
1675 if(has_predominately_negative_sign(mstruct)) {mstruct.number().negate(); mstruct.transform(this); mstruct.negate(); return 1;}
1676 return -1;
1677 }
1678 mstruct = nr;
1679 return 1;
1680 }
SincFunction()1681 SincFunction::SincFunction() : MathFunction("sinc", 1) {
1682 Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false);
1683 arg->setHandleVector(true);
1684 setArgumentDefinition(1, arg);
1685 }
representsNumber(const MathStructure & vargs,bool) const1686 bool SincFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && (vargs[0].representsNumber() || is_number_angle_value(vargs[0]));}
representsReal(const MathStructure & vargs,bool) const1687 bool SincFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && (vargs[0].representsReal() || is_real_angle_value(vargs[0]));}
representsNonComplex(const MathStructure & vargs,bool) const1688 bool SincFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)1689 int SincFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
1690 if(vargs[0].isZero()) {
1691 mstruct.set(1, 1, 0, true);
1692 return 1;
1693 } else if(vargs[0].representsNonZero(true)) {
1694 mstruct = vargs[0];
1695 bool b = replace_f_interval(mstruct, eo);
1696 b = replace_intervals_f(mstruct) || b;
1697 MathStructure *m_sin = new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_SIN), &mstruct, NULL);
1698 if(CALCULATOR->getRadUnit()) (*m_sin)[0].multiply(CALCULATOR->getRadUnit());
1699 mstruct.inverse();
1700 mstruct.multiply_nocopy(m_sin);
1701 if(b) mstruct.eval(eo);
1702 return 1;
1703 }
1704 return -1;
1705 }
1706
Atan2Function()1707 Atan2Function::Atan2Function() : MathFunction("atan2", 2) {
1708 NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, true);
1709 arg->setComplexAllowed(false);
1710 setArgumentDefinition(1, arg);
1711 arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, true);
1712 arg->setComplexAllowed(false);
1713 setArgumentDefinition(2, arg);
1714 }
representsNumber(const MathStructure & vargs,bool) const1715 bool Atan2Function::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[0].representsNumber() && vargs[1].representsNumber();}
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)1716 int Atan2Function::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
1717 if(vargs[0].number().isZero()) {
1718 if(!vargs[1].number().isNonZero()) return 0;
1719 if(vargs[1].number().isNegative()) {
1720 switch(eo.parse_options.angle_unit) {
1721 case ANGLE_UNIT_DEGREES: {mstruct.set(180, 1, 0); break;}
1722 case ANGLE_UNIT_GRADIANS: {mstruct.set(200, 1, 0); break;}
1723 case ANGLE_UNIT_RADIANS: {mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); break;}
1724 default: {mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();}
1725 }
1726 } else {
1727 mstruct.clear();
1728 }
1729 } else if(vargs[1].number().isZero() && vargs[0].number().isNonZero()) {
1730 switch(eo.parse_options.angle_unit) {
1731 case ANGLE_UNIT_DEGREES: {mstruct.set(90, 1, 0); break;}
1732 case ANGLE_UNIT_GRADIANS: {mstruct.set(100, 1, 0); break;}
1733 case ANGLE_UNIT_RADIANS: {mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); mstruct.multiply(nr_half); break;}
1734 default: {mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); mstruct.multiply(nr_half); if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();}
1735 }
1736 if(vargs[0].number().hasNegativeSign()) mstruct.negate();
1737 } else if(!vargs[1].number().isNonZero()) {
1738 FR_FUNCTION_2(atan2)
1739 } else {
1740 MathStructure new_nr(vargs[0]);
1741 if(!new_nr.number().divide(vargs[1].number())) return -1;
1742 if(vargs[1].number().isNegative() && vargs[0].number().isNonZero()) {
1743 if(vargs[0].number().isNegative()) {
1744 mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_ATAN), &new_nr, NULL);
1745 switch(eo.parse_options.angle_unit) {
1746 case ANGLE_UNIT_DEGREES: {mstruct.add(-180); break;}
1747 case ANGLE_UNIT_GRADIANS: {mstruct.add(-200); break;}
1748 case ANGLE_UNIT_RADIANS: {mstruct.subtract(CALCULATOR->getVariableById(VARIABLE_ID_PI)); break;}
1749 default: {MathStructure msub(CALCULATOR->getVariableById(VARIABLE_ID_PI)); if(CALCULATOR->getRadUnit()) msub *= CALCULATOR->getRadUnit(); mstruct.subtract(msub);}
1750 }
1751 } else {
1752 mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_ATAN), &new_nr, NULL);
1753 switch(eo.parse_options.angle_unit) {
1754 case ANGLE_UNIT_DEGREES: {mstruct.add(180); break;}
1755 case ANGLE_UNIT_GRADIANS: {mstruct.add(200); break;}
1756 case ANGLE_UNIT_RADIANS: {mstruct.add(CALCULATOR->getVariableById(VARIABLE_ID_PI)); break;}
1757 default: {MathStructure madd(CALCULATOR->getVariableById(VARIABLE_ID_PI)); if(CALCULATOR->getRadUnit()) madd *= CALCULATOR->getRadUnit(); mstruct.add(madd);}
1758 }
1759 }
1760 } else {
1761 mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_ATAN), &new_nr, NULL);
1762 }
1763 }
1764 return 1;
1765 }
RadiansToDefaultAngleUnitFunction()1766 RadiansToDefaultAngleUnitFunction::RadiansToDefaultAngleUnitFunction() : MathFunction("radtodef", 1) {
1767 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)1768 int RadiansToDefaultAngleUnitFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
1769 mstruct = vargs[0];
1770 switch(eo.parse_options.angle_unit) {
1771 case ANGLE_UNIT_DEGREES: {
1772 mstruct *= 180;
1773 mstruct /= CALCULATOR->getVariableById(VARIABLE_ID_PI);
1774 break;
1775 }
1776 case ANGLE_UNIT_GRADIANS: {
1777 mstruct *= 200;
1778 mstruct /= CALCULATOR->getVariableById(VARIABLE_ID_PI);
1779 break;
1780 }
1781 case ANGLE_UNIT_RADIANS: {
1782 break;
1783 }
1784 default: {
1785 if(CALCULATOR->getRadUnit()) {
1786 mstruct *= CALCULATOR->getRadUnit();
1787 }
1788 }
1789 }
1790 return 1;
1791 }
1792
1793