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
SumFunction()34 SumFunction::SumFunction() : MathFunction("sum", 3, 4) {
35 Argument *arg = new IntegerArgument();
36 arg->setHandleVector(false);
37 setArgumentDefinition(2, arg);
38 arg = new IntegerArgument();
39 arg->setHandleVector(false);
40 setArgumentDefinition(3, arg);
41 setArgumentDefinition(4, new SymbolicArgument());
42 setDefaultValue(4, "undefined");
43 setCondition("\\z >= \\y");
44 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)45 int SumFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
46
47 MathStructure m1(vargs[0]);
48 EvaluationOptions eo2 = eo;
49 eo2.calculate_functions = false;
50 eo2.expand = false;
51 Number i_nr(vargs[1].number());
52 if(eo2.approximation == APPROXIMATION_TRY_EXACT) {
53 Number nr(vargs[2].number());
54 nr.subtract(i_nr);
55 if(nr.isGreaterThan(100)) eo2.approximation = APPROXIMATION_APPROXIMATE;
56 }
57 CALCULATOR->beginTemporaryStopMessages();
58 m1.eval(eo2);
59 int im = 0;
60 if(CALCULATOR->endTemporaryStopMessages(NULL, &im) > 0 || im > 0) m1 = vargs[0];
61 eo2.calculate_functions = eo.calculate_functions;
62 eo2.expand = eo.expand;
63 mstruct.clear();
64 MathStructure mstruct_calc;
65 bool started = false;
66 while(i_nr.isLessThanOrEqualTo(vargs[2].number())) {
67 if(CALCULATOR->aborted()) {
68 if(!started) {
69 return 0;
70 } else if(i_nr != vargs[2].number()) {
71 MathStructure mmin(i_nr);
72 mstruct.add(MathStructure(this, &vargs[0], &mmin, &vargs[2], &vargs[3], NULL), true);
73 return 1;
74 }
75 }
76 mstruct_calc.set(m1);
77 mstruct_calc.replace(vargs[3], i_nr);
78 mstruct_calc.eval(eo2);
79 if(started) {
80 mstruct.calculateAdd(mstruct_calc, eo2);
81 } else {
82 mstruct = mstruct_calc;
83 mstruct.calculatesub(eo2, eo2);
84 started = true;
85 }
86 i_nr += 1;
87 }
88 return 1;
89
90 }
ProductFunction()91 ProductFunction::ProductFunction() : MathFunction("product", 3, 4) {
92 Argument *arg = new IntegerArgument();
93 arg->setHandleVector(false);
94 setArgumentDefinition(2, arg);
95 arg = new IntegerArgument();
96 arg->setHandleVector(false);
97 setArgumentDefinition(3, arg);
98 setArgumentDefinition(4, new SymbolicArgument());
99 setDefaultValue(4, "undefined");
100 setCondition("\\z >= \\y");
101 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)102 int ProductFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
103
104 MathStructure m1(vargs[0]);
105 EvaluationOptions eo2 = eo;
106 eo2.calculate_functions = false;
107 eo2.expand = false;
108 Number i_nr(vargs[1].number());
109 if(eo2.approximation == APPROXIMATION_TRY_EXACT) {
110 Number nr(vargs[2].number());
111 nr.subtract(i_nr);
112 if(nr.isGreaterThan(100)) eo2.approximation = APPROXIMATION_APPROXIMATE;
113 }
114 CALCULATOR->beginTemporaryStopMessages();
115 m1.eval(eo2);
116 int im = 0;
117 if(CALCULATOR->endTemporaryStopMessages(NULL, &im) || im > 0) m1 = vargs[0];
118 eo2.calculate_functions = eo.calculate_functions;
119 eo2.expand = eo.expand;
120 mstruct.clear();
121 MathStructure mstruct_calc;
122 bool started = false;
123 while(i_nr.isLessThanOrEqualTo(vargs[2].number())) {
124 if(CALCULATOR->aborted()) {
125 if(!started) {
126 return 0;
127 } else if(i_nr != vargs[2].number()) {
128 MathStructure mmin(i_nr);
129 mstruct.multiply(MathStructure(this, &vargs[0], &mmin, &vargs[2], &vargs[3], NULL), true);
130 return 1;
131 }
132 }
133 mstruct_calc.set(m1);
134 mstruct_calc.replace(vargs[3], i_nr);
135 mstruct_calc.eval(eo2);
136 if(started) {
137 mstruct.calculateMultiply(mstruct_calc, eo2);
138 } else {
139 mstruct = mstruct_calc;
140 mstruct.calculatesub(eo2, eo2);
141 started = true;
142 }
143 i_nr += 1;
144 }
145 return 1;
146
147 }
148
SolveFunction()149 SolveFunction::SolveFunction() : MathFunction("solve", 1, 2) {
150 setArgumentDefinition(2, new SymbolicArgument());
151 setDefaultValue(2, "undefined");
152 }
153 bool is_comparison_structure(const MathStructure &mstruct, const MathStructure &xvar, bool *bce = NULL, bool do_bce_or = false);
is_comparison_structure(const MathStructure & mstruct,const MathStructure & xvar,bool * bce,bool do_bce_or)154 bool is_comparison_structure(const MathStructure &mstruct, const MathStructure &xvar, bool *bce, bool do_bce_or) {
155 if(mstruct.isComparison()) {
156 if(bce) *bce = mstruct.comparisonType() == COMPARISON_EQUALS && mstruct[0] == xvar;
157 return true;
158 }
159 if(bce && do_bce_or && mstruct.isLogicalOr()) {
160 *bce = true;
161 for(size_t i = 0; i < mstruct.size(); i++) {
162 bool bcei = false;
163 if(!is_comparison_structure(mstruct[i], xvar, &bcei, false)) return false;
164 if(!bcei) *bce = false;
165 }
166 return true;
167 }
168 if(bce) *bce = false;
169 if(mstruct.isLogicalAnd()) {
170 for(size_t i = 0; i < mstruct.size(); i++) {
171 if(is_comparison_structure(mstruct[i], xvar)) return true;
172 }
173 return true;
174 } else if(mstruct.isLogicalOr()) {
175 for(size_t i = 0; i < mstruct.size(); i++) {
176 if(!is_comparison_structure(mstruct[i], xvar)) return false;
177 }
178 return true;
179 }
180 return false;
181 }
182
solve_handle_logical_and(MathStructure & mstruct,MathStructure ** mtruefor,ComparisonType ct,bool & b_partial,const MathStructure & x_var)183 MathStructure *solve_handle_logical_and(MathStructure &mstruct, MathStructure **mtruefor, ComparisonType ct, bool &b_partial, const MathStructure &x_var) {
184 MathStructure *mcondition = NULL;
185 for(size_t i2 = 0; i2 < mstruct.size(); ) {
186 if(ct == COMPARISON_EQUALS) {
187 if(mstruct[i2].isComparison() && ct == mstruct[i2].comparisonType() && mstruct[i2][0].contains(x_var)) {
188 if(mstruct[i2][0] == x_var) {
189 if(mstruct.size() == 2) {
190 if(i2 == 0) {
191 mstruct[1].ref();
192 mcondition = &mstruct[1];
193 } else {
194 mstruct[0].ref();
195 mcondition = &mstruct[0];
196 }
197 } else {
198 mcondition = new MathStructure();
199 mcondition->set_nocopy(mstruct);
200 mcondition->delChild(i2 + 1);
201 }
202 mstruct.setToChild(i2 + 1, true);
203 break;
204 } else {
205 b_partial = true;
206 i2++;
207 }
208 } else {
209 i2++;
210 }
211 } else {
212 if(mstruct[i2].isComparison() && mstruct[i2][0].contains(x_var)) {
213 i2++;
214 } else {
215 mstruct[i2].ref();
216 if(mcondition) {
217 mcondition->add_nocopy(&mstruct[i2], OPERATION_LOGICAL_AND, true);
218 } else {
219 mcondition = &mstruct[i2];
220 }
221 mstruct.delChild(i2 + 1);
222 }
223 }
224 }
225 if(ct == COMPARISON_EQUALS) {
226 if(mstruct.isLogicalAnd()) {
227 MathStructure *mtmp = new MathStructure();
228 mtmp->set_nocopy(mstruct);
229 if(!(*mtruefor)) {
230 *mtruefor = mtmp;
231 } else {
232 (*mtruefor)->add_nocopy(mtmp, OPERATION_LOGICAL_OR, true);
233 }
234 mstruct.clear(true);
235 }
236 } else {
237 if(mstruct.size() == 1) {
238 mstruct.setToChild(1, true);
239 if(ct != COMPARISON_EQUALS) mstruct.setProtected();
240 } else if(mstruct.size() == 0) {
241 mstruct.clear(true);
242 if(!(*mtruefor)) {
243 *mtruefor = mcondition;
244 } else {
245 (*mtruefor)->add_nocopy(mcondition, OPERATION_LOGICAL_OR, true);
246 }
247 mcondition = NULL;
248 } else if(ct != COMPARISON_EQUALS) {
249 for(size_t i = 0; i < mstruct.size(); i++) {
250 mstruct[i].setProtected();
251 }
252 }
253 }
254 return mcondition;
255 }
256
257 void simplify_constant(MathStructure &mstruct, const MathStructure &x_var, const MathStructure &y_var, const MathStructure &c_var, bool in_comparison = false, bool in_or = false, bool in_and = false);
simplify_constant(MathStructure & mstruct,const MathStructure & x_var,const MathStructure & y_var,const MathStructure & c_var,bool in_comparison,bool in_or,bool in_and)258 void simplify_constant(MathStructure &mstruct, const MathStructure &x_var, const MathStructure &y_var, const MathStructure &c_var, bool in_comparison, bool in_or, bool in_and) {
259 if(!in_comparison && mstruct.isComparison()) {
260 if(mstruct[0] == c_var) {
261 if(in_or) mstruct.clear(true);
262 else mstruct.set(1, 1, 0);
263 } else if(mstruct[0] == y_var) {
264 if(mstruct[1].contains(y_var, true) <= 0) simplify_constant(mstruct[1], x_var, y_var, c_var, true);
265 } else if(mstruct[0].contains(y_var, true) <= 0 && mstruct.contains(c_var, true) > 0) {
266 if(in_or) mstruct.clear(true);
267 else mstruct.set(1, 1, 0);
268 }
269 }
270 if(in_comparison) {
271 if(mstruct.contains(y_var, true) <= 0 && mstruct.contains(x_var, true) <= 0 && mstruct.contains(c_var, true) > 0) {
272 mstruct = c_var;
273 return;
274 }
275 }
276 if(in_comparison) {
277 int n_c = 0, b_cx = false;
278 size_t i_c = 0;
279 for(size_t i = 0; i < mstruct.size(); i++) {
280 if(mstruct[i].contains(c_var, true) > 0) {
281 n_c++;
282 i_c = i;
283 if(!b_cx && mstruct[i].contains(x_var, true) > 0) {
284 b_cx = true;
285 }
286 }
287 }
288 if(!b_cx && n_c >= 1 && (mstruct.isAddition() || mstruct.isMultiplication())) {
289 bool b_c = false;
290 for(size_t i = 0; i < mstruct.size();) {
291 if(mstruct[i].contains(c_var, true) > 0) {
292 if(b_c) {
293 mstruct.delChild(i + 1);
294 } else {
295 b_c = true;
296 mstruct[i] = c_var;
297 i++;
298 }
299 } else if(mstruct[i].contains(x_var, true) <= 0) {
300 mstruct.delChild(i + 1);
301 } else {
302 i++;
303 }
304 }
305 if(mstruct.size() == 1) mstruct.setToChild(1, true);
306 } else if(n_c == 1) {
307 if(b_cx) simplify_constant(mstruct[i_c], x_var, y_var, c_var, true);
308 else mstruct[i_c] = c_var;
309 }
310 } else {
311 for(size_t i = 0; i < mstruct.size(); i++) {
312 simplify_constant(mstruct[i], x_var, y_var, c_var, false, mstruct.isLogicalOr(), mstruct.isLogicalAnd());
313 }
314 }
315 }
316
test_equation(MathStructure & mstruct,const EvaluationOptions & eo,const MathStructure & x_var,const MathStructure & y_var,const MathStructure & x_value,const MathStructure & y_value)317 int test_equation(MathStructure &mstruct, const EvaluationOptions &eo, const MathStructure &x_var, const MathStructure &y_var, const MathStructure &x_value, const MathStructure &y_value) {
318 if(mstruct.isComparison() && mstruct.comparisonType() == COMPARISON_EQUALS && mstruct[0] == y_var) {
319 MathStructure mtest(mstruct);
320 mtest.replace(x_var, x_value);
321 MathStructure mtest2(y_var);
322 mtest2.transform(COMPARISON_EQUALS, y_value);
323 CALCULATOR->beginTemporaryStopMessages();
324 EvaluationOptions eo2 = eo;
325 eo2.approximation = APPROXIMATION_APPROXIMATE;
326 mtest.calculateFunctions(eo2);
327 mtest2.calculateFunctions(eo2);
328 int b = test_comparisons(mtest, mtest2, y_var, eo);
329 CALCULATOR->endTemporaryStopMessages();
330 if(!b) mstruct.clear(true);
331 return b;
332 }
333 bool b_ret = 0;
334 for(size_t i = 0; i < mstruct.size(); i++) {
335 int b = test_equation(mstruct[i], eo, x_var, y_var, x_value, y_value);
336 if(b < 0) return b;
337 else if(b > 0) b_ret = 1;
338 }
339 return b_ret;
340 }
341
solve_equation(MathStructure & mstruct,const MathStructure & m_eqn,const MathStructure & y_var,const EvaluationOptions & eo,bool dsolve=false,const MathStructure & x_var=m_undefined,const MathStructure & c_var=m_undefined,const MathStructure & x_value=m_undefined,const MathStructure & y_value=m_undefined)342 int solve_equation(MathStructure &mstruct, const MathStructure &m_eqn, const MathStructure &y_var, const EvaluationOptions &eo, bool dsolve = false, const MathStructure &x_var = m_undefined, const MathStructure &c_var = m_undefined, const MathStructure &x_value = m_undefined, const MathStructure &y_value = m_undefined) {
343
344 int itry = 0;
345 int ierror = 0;
346 int first_error = 0;
347
348 Assumptions *assumptions = NULL;
349 bool assumptions_added = false;
350 AssumptionSign as = ASSUMPTION_SIGN_UNKNOWN;
351 AssumptionType at = ASSUMPTION_TYPE_NUMBER;
352 MathStructure msave;
353 string strueforall;
354
355 while(true) {
356
357 if(itry == 1) {
358 if(ierror == 1) {
359 if(!dsolve) CALCULATOR->error(true, _("No equality or inequality to solve. The entered expression to solve is not correct (e.g. \"x + 5 = 3\" is correct)"), NULL);
360 return -1;
361 } else {
362 first_error = ierror;
363 msave = mstruct;
364 }
365 }
366
367 itry++;
368
369 if(itry == 2) {
370 if(y_var.isVariable() && y_var.variable()->subtype() == SUBTYPE_UNKNOWN_VARIABLE) {
371 assumptions = ((UnknownVariable*) y_var.variable())->assumptions();
372 if(!assumptions) {
373 assumptions = new Assumptions();
374 assumptions->setSign(CALCULATOR->defaultAssumptions()->sign());
375 assumptions->setType(CALCULATOR->defaultAssumptions()->type());
376 ((UnknownVariable*) y_var.variable())->setAssumptions(assumptions);
377 assumptions_added = true;
378 }
379 } else {
380 assumptions = CALCULATOR->defaultAssumptions();
381 }
382 if(assumptions->sign() != ASSUMPTION_SIGN_UNKNOWN) {
383 as = assumptions->sign();
384 assumptions->setSign(ASSUMPTION_SIGN_UNKNOWN);
385 } else {
386 itry++;
387 }
388 }
389 if(itry == 3) {
390 if(assumptions->type() > ASSUMPTION_TYPE_NUMBER) {
391 at = assumptions->type();
392 assumptions->setType(ASSUMPTION_TYPE_NUMBER);
393 as = assumptions->sign();
394 assumptions->setSign(ASSUMPTION_SIGN_UNKNOWN);
395 } else {
396 itry++;
397 }
398 }
399
400 if(itry > 3) {
401 if(as != ASSUMPTION_SIGN_UNKNOWN) assumptions->setSign(as);
402 if(at > ASSUMPTION_TYPE_NUMBER) assumptions->setType(at);
403 if(assumptions_added) ((UnknownVariable*) y_var.variable())->setAssumptions(NULL);
404 switch(first_error) {
405 case 2: {
406 CALCULATOR->error(true, _("The comparison is true for all %s (with current assumptions)."), format_and_print(y_var).c_str(), NULL);
407 break;
408 }
409 case 3: {
410 CALCULATOR->error(true, _("No possible solution was found (with current assumptions)."), NULL);
411 break;
412 }
413 case 4: {
414 CALCULATOR->error(true, _("Was unable to completely isolate %s."), format_and_print(y_var).c_str(), NULL);
415 break;
416 }
417 case 7: {
418 CALCULATOR->error(false, _("The comparison is true for all %s if %s."), format_and_print(y_var).c_str(), strueforall.c_str(), NULL);
419 break;
420 }
421 default: {
422 CALCULATOR->error(true, _("Was unable to isolate %s."), format_and_print(y_var).c_str(), NULL);
423 break;
424 }
425 }
426 mstruct = msave;
427 return -1;
428 }
429
430 ComparisonType ct = COMPARISON_EQUALS;
431
432 bool b = false;
433 bool b_partial = false;
434
435 if(m_eqn.isComparison()) {
436 ct = m_eqn.comparisonType();
437 mstruct = m_eqn;
438 b = true;
439 } else if(m_eqn.isLogicalAnd() && m_eqn.size() > 0 && m_eqn[0].isComparison()) {
440 ct = m_eqn[0].comparisonType();
441 for(size_t i = 0; i < m_eqn.size(); i++) {
442 if(m_eqn[i].isComparison() && m_eqn[i].contains(y_var, true) > 0) {
443 ct = m_eqn[i].comparisonType();
444 break;
445 }
446 }
447 mstruct = m_eqn;
448 b = true;
449 } else if(m_eqn.isLogicalOr() && m_eqn.size() > 0 && m_eqn[0].isComparison()) {
450 ct = m_eqn[0].comparisonType();
451 mstruct = m_eqn;
452 b = true;
453 } else if(m_eqn.isLogicalOr() && m_eqn.size() > 0 && m_eqn[0].isLogicalAnd() && m_eqn[0].size() > 0 && m_eqn[0][0].isComparison()) {
454 ct = m_eqn[0][0].comparisonType();
455 for(size_t i = 0; i < m_eqn[0].size(); i++) {
456 if(m_eqn[0][i].isComparison() && m_eqn[0][i].contains(y_var, true) > 0) {
457 ct = m_eqn[0][i].comparisonType();
458 break;
459 }
460 }
461 mstruct = m_eqn;
462 b = true;
463 } else if(m_eqn.isVariable() && m_eqn.variable()->isKnown() && (eo.approximation != APPROXIMATION_EXACT || !m_eqn.variable()->isApproximate()) && ((KnownVariable*) m_eqn.variable())->get().isComparison()) {
464 mstruct = ((KnownVariable*) m_eqn.variable())->get();
465 mstruct.unformat();
466 ct = m_eqn.comparisonType();
467 b = true;
468 } else {
469 EvaluationOptions eo2 = eo;
470 eo2.test_comparisons = false;
471 eo2.assume_denominators_nonzero = false;
472 eo2.isolate_x = false;
473 mstruct = m_eqn;
474 mstruct.eval(eo2);
475 if(mstruct.isComparison()) {
476 ct = mstruct.comparisonType();
477 b = true;
478 } else if(mstruct.isLogicalAnd() && mstruct.size() > 0 && mstruct[0].isComparison()) {
479 ct = mstruct[0].comparisonType();
480 b = true;
481 } else if(mstruct.isLogicalOr() && mstruct.size() > 0 && mstruct[0].isComparison()) {
482 ct = mstruct[0].comparisonType();
483 b = true;
484 } else if(mstruct.isLogicalOr() && mstruct.size() > 0 && mstruct[0].isLogicalAnd() && mstruct[0].size() > 0 && mstruct[0][0].isComparison()) {
485 ct = mstruct[0][0].comparisonType();
486 b = true;
487 }
488 }
489
490 if(!b) {
491 ierror = 1;
492 continue;
493 }
494
495 EvaluationOptions eo2 = eo;
496 eo2.isolate_var = &y_var;
497 eo2.isolate_x = true;
498 eo2.test_comparisons = true;
499 mstruct.eval(eo2);
500 if(dsolve) {
501 if(x_value.isUndefined() || y_value.isUndefined()) {
502 simplify_constant(mstruct, x_var, y_var, c_var);
503 mstruct.eval(eo2);
504 } else {
505 int test_r = test_equation(mstruct, eo2, x_var, y_var, x_value, y_value);
506 if(test_r < 0) {
507 ierror = 8;
508 continue;
509 } else if(test_r > 0) {
510 mstruct.eval(eo2);
511 }
512 }
513 }
514
515 if(mstruct.isOne()) {
516 ierror = 2;
517 continue;
518 } else if(mstruct.isZero()) {
519 ierror = 3;
520 continue;
521 }
522
523 if(mstruct.isComparison()) {
524 if((ct == COMPARISON_EQUALS && mstruct.comparisonType() != COMPARISON_EQUALS) || !mstruct.contains(y_var)) {
525 if(itry == 1) {
526 strueforall = format_and_print(mstruct);
527 }
528 ierror = 7;
529 continue;
530 } else if(ct == COMPARISON_EQUALS && mstruct[0] != y_var) {
531 ierror = 4;
532 continue;
533 }
534 if(ct == COMPARISON_EQUALS) {
535 mstruct.setToChild(2, true);
536 } else {
537 mstruct.setProtected();
538 }
539 if(itry > 1) {
540 assumptions->setSign(as);
541 if(itry == 2) {
542 CALCULATOR->error(false, _("Was unable to isolate %s with the current assumptions. The assumed sign was therefore temporarily set as unknown."), format_and_print(y_var).c_str(), NULL);
543 } else if(itry == 3) {
544 assumptions->setType(at);
545 CALCULATOR->error(false, _("Was unable to isolate %s with the current assumptions. The assumed type and sign was therefore temporarily set as unknown."), format_and_print(y_var).c_str(), NULL);
546 }
547 if(assumptions_added) ((UnknownVariable*) y_var.variable())->setAssumptions(NULL);
548 }
549 return 1;
550 } else if(mstruct.isLogicalAnd()) {
551 MathStructure *mtruefor = NULL;
552 bool b_partial;
553 MathStructure mcopy(mstruct);
554 MathStructure *mcondition = solve_handle_logical_and(mstruct, &mtruefor, ct, b_partial, y_var);
555 if((!mstruct.isComparison() && !mstruct.isLogicalAnd()) || (ct == COMPARISON_EQUALS && (!mstruct.isComparison() || mstruct.comparisonType() != COMPARISON_EQUALS || mstruct[0] != y_var)) || !mstruct.contains(y_var)) {
556 if(mtruefor) delete mtruefor;
557 if(mcondition) delete mcondition;
558 if(b_partial) {
559 ierror = 4;
560 } else {
561 ierror = 5;
562 }
563 mstruct = mcopy;
564 continue;
565 }
566 if(itry > 1) {
567 assumptions->setSign(as);
568 if(itry == 2) {
569 CALCULATOR->error(false, _("Was unable to isolate %s with the current assumptions. The assumed sign was therefore temporarily set as unknown."), format_and_print(y_var).c_str(), NULL);
570 } else if(itry == 3) {
571 assumptions->setType(at);
572 CALCULATOR->error(false, _("Was unable to isolate %s with the current assumptions. The assumed type and sign was therefore temporarily set as unknown."), format_and_print(y_var).c_str(), NULL);
573 }
574 if(assumptions_added) ((UnknownVariable*) y_var.variable())->setAssumptions(NULL);
575 }
576 if(mcondition) {
577 CALCULATOR->error(false, _("The solution requires that %s."), format_and_print(*mcondition).c_str(), NULL);
578 delete mcondition;
579 }
580 if(mtruefor) {
581 CALCULATOR->error(false, _("The comparison is true for all %s if %s."), format_and_print(y_var).c_str(), format_and_print(*mtruefor).c_str(), NULL);
582 delete mtruefor;
583 }
584 if(ct == COMPARISON_EQUALS) mstruct.setToChild(2, true);
585 return 1;
586 } else if(mstruct.isLogicalOr()) {
587 MathStructure mcopy(mstruct);
588 MathStructure *mtruefor = NULL;
589 vector<MathStructure*> mconditions;
590 for(size_t i = 0; i < mstruct.size(); ) {
591 MathStructure *mcondition = NULL;
592 bool b_and = false;
593 if(mstruct[i].isLogicalAnd()) {
594 mcondition = solve_handle_logical_and(mstruct[i], &mtruefor, ct, b_partial, y_var);
595 b_and = true;
596 }
597 if(!mstruct[i].isZero()) {
598 for(size_t i2 = 0; i2 < i; i2++) {
599 if(mstruct[i2] == mstruct[i]) {
600 mstruct[i].clear();
601 if(mcondition && mconditions[i2]) {
602 mconditions[i2]->add_nocopy(mcondition, OPERATION_LOGICAL_OR, true);
603 }
604 break;
605 }
606 }
607 }
608 bool b_del = false;
609 if((!mstruct[i].isComparison() && !mstruct[i].isLogicalAnd()) || (ct == COMPARISON_EQUALS && (!mstruct[i].isComparison() || mstruct[i].comparisonType() != COMPARISON_EQUALS)) || !mstruct[i].contains(y_var)) {
610 b_del = true;
611 } else if(ct == COMPARISON_EQUALS && mstruct[i][0] != y_var) {
612 b_partial = true;
613 b_del = true;
614 }
615 if(b_del) {
616 if(!mstruct[i].isZero()) {
617 mstruct[i].ref();
618 if(!mtruefor) {
619 mtruefor = &mstruct[i];
620 } else {
621 mtruefor->add_nocopy(&mstruct[i], OPERATION_LOGICAL_OR, true);
622 }
623 }
624 mstruct.delChild(i + 1);
625 } else {
626 mconditions.push_back(mcondition);
627 if(!b_and && ct != COMPARISON_EQUALS) mstruct[i].setProtected();
628 i++;
629 }
630 }
631 if(ct == COMPARISON_EQUALS) {
632 for(size_t i = 0; i < mstruct.size(); i++) {
633 if(mstruct[i].isComparison() && mstruct[i].comparisonType() == ct) mstruct[i].setToChild(2, true);
634 }
635 }
636 if(mstruct.size() == 1) {
637 mstruct.setToChild(1, true);
638 } else if(mstruct.size() == 0) {
639 if(mtruefor) delete mtruefor;
640 if(b_partial) ierror = 4;
641 else ierror = 5;
642 mstruct = mcopy;
643 continue;
644 } else {
645 mstruct.setType(STRUCT_VECTOR);
646 }
647 if(itry > 1) {
648 assumptions->setSign(as);
649 if(itry == 2) {
650 CALCULATOR->error(false, _("Was unable to isolate %s with the current assumptions. The assumed sign was therefore temporarily set as unknown."), format_and_print(y_var).c_str(), NULL);
651 } else if(itry == 3) {
652 assumptions->setType(at);
653 CALCULATOR->error(false, _("Was unable to isolate %s with the current assumptions. The assumed type and sign was therefore temporarily set as unknown."), format_and_print(y_var).c_str(), NULL);
654 }
655 if(assumptions_added) ((UnknownVariable*) y_var.variable())->setAssumptions(NULL);
656 }
657
658 if(mconditions.size() == 1) {
659 if(mconditions[0]) {
660 CALCULATOR->error(false, _("The solution requires that %s."), format_and_print(*mconditions[0]).c_str(), NULL);
661 delete mconditions[0];
662 }
663 } else {
664 string sconditions;
665 for(size_t i = 0; i < mconditions.size(); i++) {
666 if(mconditions[i]) {
667 CALCULATOR->error(false, _("Solution %s requires that %s."), i2s(i + 1).c_str(), format_and_print(*mconditions[i]).c_str(), NULL);
668 delete mconditions[i];
669 }
670 }
671 }
672 if(mtruefor) {
673 CALCULATOR->error(false, _("The comparison is true for all %s if %s."), format_and_print(y_var).c_str(), format_and_print(*mtruefor).c_str(), NULL);
674 delete mtruefor;
675 }
676 return 1;
677 } else {
678 ierror = 6;
679 }
680 }
681 return -1;
682
683 }
684
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)685 int SolveFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
686 return solve_equation(mstruct, vargs[0], vargs[1], eo);
687 }
688
SolveMultipleFunction()689 SolveMultipleFunction::SolveMultipleFunction() : MathFunction("multisolve", 2) {
690 setArgumentDefinition(1, new VectorArgument());
691 VectorArgument *arg = new VectorArgument();
692 arg->addArgument(new SymbolicArgument());
693 arg->setReoccuringArguments(true);
694 setArgumentDefinition(2, arg);
695 setCondition("dimension(\\x) = dimension(\\y)");
696 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)697 int SolveMultipleFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
698
699 mstruct.clearVector();
700
701 if(vargs[1].size() < 1) return 1;
702
703 vector<bool> eleft;
704 eleft.resize(vargs[0].size(), true);
705 vector<size_t> eorder;
706 bool b = false;
707 for(size_t i = 0; i < vargs[1].size(); i++) {
708 b = false;
709 for(size_t i2 = 0; i2 < vargs[0].size(); i2++) {
710 if(eleft[i2] && vargs[0][i2].contains(vargs[1][i], true)) {
711 eorder.push_back(i2);
712 eleft[i2] = false;
713 b = true;
714 break;
715 }
716 }
717 if(!b) {
718 eorder.clear();
719 for(size_t i2 = 0; i2 < vargs[0].size(); i2++) {
720 eorder.push_back(i2);
721 }
722 break;
723 }
724 }
725
726 for(size_t i = 0; i < eorder.size(); i++) {
727 MathStructure msolve(vargs[0][eorder[i]]);
728 EvaluationOptions eo2 = eo;
729 eo2.isolate_var = &vargs[1][i];
730 for(size_t i2 = 0; i2 < i; i2++) {
731 msolve.replace(vargs[1][i2], mstruct[i2]);
732 }
733 msolve.eval(eo2);
734
735 if(msolve.isComparison()) {
736 if(msolve[0] != vargs[1][i]) {
737 if(!b) {
738 CALCULATOR->error(true, _("Unable to isolate %s.\n\nYou might need to place the equations and variables in an appropriate order so that each equation at least contains the corresponding variable (if automatic reordering failed)."), format_and_print(vargs[1][i]).c_str(), NULL);
739 } else {
740 CALCULATOR->error(true, _("Unable to isolate %s."), format_and_print(vargs[1][i]).c_str(), NULL);
741 }
742 return 0;
743 } else {
744 if(msolve.comparisonType() == COMPARISON_EQUALS) {
745 mstruct.addChild(msolve[1]);
746 } else {
747 CALCULATOR->error(true, _("Inequalities is not allowed in %s()."), preferredName().name.c_str(), NULL);
748 return 0;
749 }
750 }
751 } else if(msolve.isLogicalOr()) {
752 for(size_t i2 = 0; i2 < msolve.size(); i2++) {
753 if(!msolve[i2].isComparison() || msolve[i2].comparisonType() != COMPARISON_EQUALS || msolve[i2][0] != vargs[1][i]) {
754 CALCULATOR->error(true, _("Unable to isolate %s."), format_and_print(vargs[1][i]).c_str(), NULL);
755 return 0;
756 } else {
757 msolve[i2].setToChild(2, true);
758 }
759 }
760 msolve.setType(STRUCT_VECTOR);
761 mstruct.addChild(msolve);
762 } else {
763 CALCULATOR->error(true, _("Unable to isolate %s."), format_and_print(vargs[1][i]).c_str(), NULL);
764 return 0;
765 }
766 for(size_t i2 = 0; i2 < i; i2++) {
767 for(size_t i3 = 0; i3 <= i; i3++) {
768 if(i2 != i3) {
769 mstruct[i2].replace(vargs[1][i3], mstruct[i3]);
770 }
771 }
772 }
773 }
774
775 return 1;
776
777 }
778
779 MathStructure *find_deqn(MathStructure &mstruct);
find_deqn(MathStructure & mstruct)780 MathStructure *find_deqn(MathStructure &mstruct) {
781 if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_DIFFERENTIATE) return &mstruct;
782 for(size_t i = 0; i < mstruct.size(); i++) {
783 MathStructure *m = find_deqn(mstruct[i]);
784 if(m) return m;
785 }
786 return NULL;
787 }
788
789 bool contains_ignore_diff(const MathStructure &m, const MathStructure &mstruct, const MathStructure &mdiff);
contains_ignore_diff(const MathStructure & m,const MathStructure & mstruct,const MathStructure & mdiff)790 bool contains_ignore_diff(const MathStructure &m, const MathStructure &mstruct, const MathStructure &mdiff) {
791 if(m.equals(mstruct)) return true;
792 if(m.equals(mdiff)) return false;
793 for(size_t i = 0; i < m.size(); i++) {
794 if(contains_ignore_diff(m[i], mstruct, mdiff)) return true;
795 }
796 if(m.isVariable() && m.variable()->isKnown()) {
797 return contains_ignore_diff(((KnownVariable*) m.variable())->get(), mstruct, mdiff);
798 } else if(m.isVariable()) {
799 if(mstruct.isNumber() || !m.representsNumber()) return true;
800 } else if(m.isAborted()) {
801 return true;
802 }
803 return false;
804 }
805
add_C(MathStructure & m_eqn,const MathStructure & m_x,const MathStructure & m_y,const MathStructure & x_value,const MathStructure & y_value)806 void add_C(MathStructure &m_eqn, const MathStructure &m_x, const MathStructure &m_y, const MathStructure &x_value, const MathStructure &y_value) {
807 if(!y_value.isUndefined() && !x_value.isUndefined()) {
808 MathStructure m_c(m_eqn);
809 m_c.replace(m_x, x_value);
810 m_c.replace(m_y, y_value);
811 m_c.setType(STRUCT_ADDITION);
812 m_c[1].negate();
813 m_c.childUpdated(2);
814 m_eqn[1] += m_c;
815 } else {
816 m_eqn[1] += CALCULATOR->getVariableById(VARIABLE_ID_C);
817 }
818 m_eqn.childrenUpdated();
819 }
820
dsolve(MathStructure & m_eqn,const EvaluationOptions & eo,const MathStructure & m_diff,const MathStructure & y_value,const MathStructure & x_value)821 bool dsolve(MathStructure &m_eqn, const EvaluationOptions &eo, const MathStructure &m_diff, const MathStructure &y_value, const MathStructure &x_value) {
822 MathStructure m_y(m_diff[0]), m_x(m_diff[1]);
823 bool b = false;
824 if(m_eqn[0] == m_diff) {
825 if(m_eqn[1].containsRepresentativeOf(m_y, true, true) == 0) {
826 // y'=f(x)
827 MathStructure m_fx(m_eqn[1]);
828 if(m_fx.integrate(m_x, eo, true, false) > 0) {
829 m_eqn[0] = m_y;
830 m_eqn[1] = m_fx;
831 b = true;
832 }
833 } else if(m_eqn[1].containsRepresentativeOf(m_x, true, true) == 0) {
834 MathStructure m_fy(m_eqn[1]);
835 m_fy.inverse();
836 if(m_fy.integrate(m_y, eo, true, false) > 0) {
837 m_eqn[0] = m_fy;
838 m_eqn[1] = m_x;
839 b = true;
840 }
841 } else if(m_eqn[1].isMultiplication() && m_eqn[1].size() >= 2) {
842 b = true;
843 MathStructure m_fx(1, 1, 0), m_fy(1, 1, 0);
844 for(size_t i = 0; i < m_eqn[1].size(); i++) {
845 if(m_eqn[1][i].containsRepresentativeOf(m_y, true, true) != 0) {
846 if(m_eqn[1][i].containsRepresentativeOf(m_x, true, true) != 0) {
847 b = false;
848 break;
849 }
850 if(m_fy.isOne()) m_fy = m_eqn[1][i];
851 else m_fy.multiply(m_eqn[1][i], true);
852 } else {
853 if(m_fx.isOne()) m_fx = m_eqn[1][i];
854 else m_fx.multiply(m_eqn[1][i], true);
855 }
856 }
857 if(b) {
858 // y'=f(x)*f(y)
859 m_fy.inverse();
860 if(m_fy.integrate(m_y, eo, true, false) > 0 && m_fx.integrate(m_x, eo, true, false) > 0) {
861 m_eqn[0] = m_fy;
862 m_eqn[1] = m_fx;
863 } else {
864 b = false;
865 }
866 }
867 } else {
868 MathStructure mfactor(m_eqn);
869 mfactor[1].factorize(eo, false, 0, 0, false, false, NULL, m_x);
870 if(mfactor[1].isMultiplication() && mfactor[1].size() >= 2) {
871 mfactor.childUpdated(2);
872 if(dsolve(mfactor, eo, m_diff, y_value, x_value)) {
873 m_eqn = mfactor;
874 return 1;
875 }
876 }
877 if(m_eqn[1].isAddition()) {
878 MathStructure m_left;
879 MathStructure m_muly;
880 MathStructure m_mul_exp;
881 MathStructure m_exp;
882 b = true;
883 for(size_t i = 0; i < m_eqn[1].size(); i++) {
884 if(m_eqn[1][i] == m_y) {
885 if(m_muly.isZero()) m_muly = m_one;
886 else m_muly.add(m_one, true);
887 } else if(m_eqn[1][i].containsRepresentativeOf(m_y, true, true) != 0) {
888 if(m_left.isZero() && m_eqn[1][i].isPower() && m_eqn[1][i][0] == m_y && (m_mul_exp.isZero() || m_eqn[1][i][1] == m_exp)) {
889 if(m_mul_exp.isZero()) {
890 m_exp = m_eqn[1][i][1];
891 m_mul_exp = m_one;
892 } else {
893 m_mul_exp.add(m_one, true);
894 }
895 } else if(m_eqn[1][i].isMultiplication()) {
896 size_t i_my = 0;
897 bool b2 = false, b2_exp = false;
898 for(size_t i2 = 0; i2 < m_eqn[1][i].size(); i2++) {
899 if(!b2 && m_eqn[1][i][i2] == m_y) {
900 i_my = i2;
901 b2 = true;
902 } else if(!b2 && m_left.isZero() && m_eqn[1][i][i2].isPower() && m_eqn[1][i][i2][0] == m_y && (m_mul_exp.isZero() || m_eqn[1][i][i2][1] == m_exp)) {
903 i_my = i2;
904 b2 = true;
905 b2_exp = true;
906 } else if(m_eqn[1][i][i2].containsRepresentativeOf(m_y, true, true) != 0) {
907 b2 = false;
908 break;
909 }
910 }
911 if(b2) {
912 MathStructure m_a(m_eqn[1][i]);
913 m_a.delChild(i_my + 1, true);
914 if(b2_exp) {
915 if(m_mul_exp.isZero()) {
916 m_exp = m_eqn[1][i][i_my][1];
917 m_mul_exp = m_a;
918 } else {
919 m_mul_exp.add(m_a, true);
920 }
921 } else {
922 if(m_muly.isZero()) m_muly = m_a;
923 else m_muly.add(m_a, true);
924 }
925 } else {
926 b = false;
927 break;
928 }
929 } else {
930 b = false;
931 break;
932 }
933 } else {
934 if(!m_mul_exp.isZero()) {
935 b = false;
936 break;
937 }
938 if(m_left.isZero()) m_left = m_eqn[1][i];
939 else m_left.add(m_eqn[1][i], true);
940 }
941 }
942 if(b && !m_muly.isZero()) {
943 if(!m_mul_exp.isZero()) {
944 if(m_exp.isOne() || !m_left.isZero()) return false;
945 // y' = f(x)*y+g(x)*y^c
946 b = false;
947 m_muly.calculateNegate(eo);
948 MathStructure m_y1_integ(m_muly);
949 if(m_y1_integ.integrate(m_x, eo, true, false) > 0) {
950 m_exp.negate();
951 m_exp += m_one;
952 MathStructure m_y1_exp(m_exp);
953 m_y1_exp *= m_y1_integ;
954 m_y1_exp.transform(STRUCT_POWER, CALCULATOR->getVariableById(VARIABLE_ID_E));
955 m_y1_exp.swapChildren(1, 2);
956 MathStructure m_y1_exp_integ(m_y1_exp);
957 m_y1_exp_integ *= m_mul_exp;
958 if(m_y1_exp_integ.integrate(m_x, eo, true, false) > 0) {
959 m_eqn[1] = m_exp;
960 m_eqn[1] *= m_y1_exp_integ;
961 m_eqn[0] = m_y;
962 m_eqn[0] ^= m_exp;
963 m_eqn[0] *= m_y1_exp;
964 add_C(m_eqn, m_x, m_y, x_value, y_value);
965 m_eqn[0].delChild(m_eqn[0].size());
966 m_eqn[1] /= m_y1_exp;
967 m_eqn.childrenUpdated();
968 return 1;
969 }
970 }
971 } else if(m_left.isZero()) {
972 // y'=f(x)*y+g(x)*y
973 MathStructure mtest(m_eqn);
974 MathStructure m_fy(m_y);
975 m_fy.inverse();
976 MathStructure m_fx(m_muly);
977 if(m_fy.integrate(m_y, eo, true, false) > 0 && m_fx.integrate(m_x, eo, true, false) > 0) {
978 m_eqn[0] = m_fy;
979 m_eqn[1] = m_fx;
980 b = true;
981 }
982 } else {
983 // y'=f(x)*y+g(x)
984 MathStructure integ_fac(m_muly);
985 integ_fac.negate();
986 if(integ_fac.integrate(m_x, eo, true, false) > 0) {
987 UnknownVariable *var = new UnknownVariable("", "u");
988 Assumptions *ass = new Assumptions();
989 if(false) {
990 ass->setType(ASSUMPTION_TYPE_REAL);
991 }
992 var->setAssumptions(ass);
993 MathStructure m_u(var);
994 m_u.inverse();
995 if(m_u.integrate(var, eo, false, false) > 0) {
996 MathStructure m_eqn2(integ_fac);
997 m_eqn2.transform(COMPARISON_EQUALS, m_u);
998 m_eqn2.isolate_x(eo, var);
999 if(m_eqn2.isComparison() && m_eqn2.comparisonType() == COMPARISON_EQUALS && m_eqn2[0] == var) {
1000 integ_fac = m_eqn2[1];
1001 MathStructure m_fx(m_left);
1002 m_fx *= integ_fac;
1003 if(m_fx.integrate(m_x, eo, true, false) > 0) {
1004 m_eqn[0] = m_y;
1005 m_eqn[0] *= integ_fac;
1006 m_eqn[1] = m_fx;
1007 add_C(m_eqn, m_x, m_y, x_value, y_value);
1008 m_eqn[0] = m_y;
1009 m_eqn[1] /= integ_fac;
1010 m_eqn.childrenUpdated();
1011 return 1;
1012 }
1013 } else if(m_eqn2.isLogicalOr() && m_eqn2.size() >= 2) {
1014 b = true;
1015 for(size_t i = 0; i < m_eqn2.size(); i++) {
1016 if(!m_eqn2[i].isComparison() || m_eqn2[i].comparisonType() != COMPARISON_EQUALS || m_eqn2[i][0] != var) {
1017 b = false;
1018 break;
1019 }
1020 }
1021 if(b) {
1022 MathStructure m_eqn_new;
1023 m_eqn_new.setType(STRUCT_LOGICAL_OR);
1024 for(size_t i = 0; i < m_eqn2.size(); i++) {
1025 integ_fac = m_eqn2[i][1];
1026 MathStructure m_fx(m_left);
1027 m_fx *= integ_fac;
1028 if(m_fx.integrate(m_x, eo, true, false) > 0) {
1029 MathStructure m_fy(m_y);
1030 m_fy *= integ_fac;
1031 m_eqn_new.addChild(m_fy);
1032 m_eqn_new.last().transform(COMPARISON_EQUALS, m_fx);
1033 add_C(m_eqn_new.last(), m_x, m_y, x_value, y_value);
1034 m_eqn_new.last()[0] = m_y;
1035 m_eqn_new.last()[1] /= integ_fac;
1036 m_eqn_new.last().childrenUpdated();
1037 m_eqn_new.childUpdated(m_eqn_new.size());
1038 } else {
1039 b = false;
1040 break;
1041 }
1042 }
1043 if(b) {
1044 m_eqn_new.childrenUpdated();
1045 m_eqn = m_eqn_new;
1046 return 1;
1047 }
1048 }
1049 }
1050 }
1051 var->destroy();
1052 }
1053 }
1054 } else {
1055 b = false;
1056 }
1057 }
1058 }
1059 if(b) {
1060 add_C(m_eqn, m_x, m_y, x_value, y_value);
1061 return 1;
1062 }
1063 }
1064 return false;
1065 }
1066
DSolveFunction()1067 DSolveFunction::DSolveFunction() : MathFunction("dsolve", 1, 3) {
1068 setDefaultValue(2, "undefined");
1069 setDefaultValue(3, "0");
1070 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)1071 int DSolveFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
1072 MathStructure m_eqn(vargs[0]);
1073 EvaluationOptions eo2 = eo;
1074 eo2.isolate_x = false;
1075 eo2.protected_function = CALCULATOR->getFunctionById(FUNCTION_ID_DIFFERENTIATE);
1076 m_eqn.eval(eo2);
1077 MathStructure *m_diff_p = NULL;
1078 if(m_eqn.isLogicalAnd()) {
1079 for(size_t i = 0; i < m_eqn.size(); i++) {
1080 if(m_eqn[i].isComparison() && m_eqn.comparisonType() == COMPARISON_EQUALS) {
1081 m_diff_p = find_deqn(m_eqn[i]);
1082 if(m_diff_p) break;
1083 }
1084 }
1085 } else if(m_eqn.isComparison() && m_eqn.comparisonType() == COMPARISON_EQUALS) {
1086 m_diff_p = find_deqn(m_eqn);
1087 }
1088 if(!m_diff_p) {
1089 CALCULATOR->error(true, _("No differential equation found."), NULL);
1090 mstruct = m_eqn; return -1;
1091 }
1092 MathStructure m_diff(*m_diff_p);
1093 if(m_diff.size() < 3 || (!m_diff[0].isSymbolic() && !m_diff[0].isVariable()) || (!m_diff[1].isSymbolic() && !m_diff[1].isVariable()) || !m_diff[2].isInteger() || !m_diff[2].number().isPositive() || !m_diff[2].number().isLessThanOrEqualTo(10)) {
1094 CALCULATOR->error(true, _("No differential equation found."), NULL);
1095 mstruct = m_eqn; return -1;
1096 }
1097 if(m_diff[2].number().intValue() != 1) {
1098 CALCULATOR->error(true, _("Unable to solve differential equation."), NULL);
1099 mstruct = m_eqn;
1100 return -1;
1101 }
1102 m_eqn.isolate_x(eo2, m_diff);
1103 mstruct = m_eqn;
1104 if(eo.approximation == APPROXIMATION_TRY_EXACT) eo2.approximation = APPROXIMATION_EXACT;
1105 if(m_eqn.isLogicalAnd()) {
1106 for(size_t i = 0; i < m_eqn.size(); i++) {
1107 if(m_eqn[i].isComparison() && m_eqn[i].comparisonType() == COMPARISON_EQUALS && m_eqn[i][0] == m_diff) {
1108 dsolve(m_eqn[i], eo2, m_diff, vargs[1], vargs[2]);
1109 }
1110 }
1111 } else if(m_eqn.isLogicalOr()) {
1112 for(size_t i = 0; i < m_eqn.size(); i++) {
1113 if(m_eqn[i].isComparison() && m_eqn[i].comparisonType() == COMPARISON_EQUALS && m_eqn[i][0] == m_diff) {
1114 dsolve(m_eqn[i], eo2, m_diff, vargs[1], vargs[2]);
1115 } else if(m_eqn[i].isLogicalAnd()) {
1116 for(size_t i2 = 0; i2 < m_eqn[i].size(); i2++) {
1117 if(m_eqn[i][i2].isComparison() && m_eqn[i][i2].comparisonType() == COMPARISON_EQUALS && m_eqn[i][i2][0] == m_diff) {
1118 dsolve(m_eqn[i][i2], eo2, m_diff, vargs[1], vargs[2]);
1119 }
1120 }
1121 }
1122 }
1123 } else if(m_eqn.isComparison() && m_eqn.comparisonType() == COMPARISON_EQUALS && m_eqn[0] == m_diff) {
1124 dsolve(m_eqn, eo2, m_diff, vargs[1], vargs[2]);
1125 }
1126 if(m_eqn.contains(m_diff)) {
1127 CALCULATOR->error(true, _("Unable to solve differential equation."), NULL);
1128 return -1;
1129 }
1130 m_eqn.calculatesub(eo2, eo2, true);
1131 MathStructure msolve(m_eqn);
1132 if(solve_equation(msolve, m_eqn, m_diff[0], eo, true, m_diff[1], MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_C)), vargs[2], vargs[1]) <= 0) {
1133 CALCULATOR->error(true, _("Unable to solve differential equation."), NULL);
1134 return -1;
1135 }
1136 mstruct = msolve;
1137 return 1;
1138 }
1139
1140