1 /*
2     Qalculate (library)
3 
4     Copyright (C) 2003-2007, 2008, 2016, 2018  Hanna Knutsson (hanna.knutsson@protonmail.com)
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 */
11 
12 #include "support.h"
13 
14 #include "BuiltinFunctions.h"
15 #include "util.h"
16 #include "MathStructure.h"
17 #include "Number.h"
18 #include "Calculator.h"
19 #include "Variable.h"
20 #include "Unit.h"
21 
22 #include <sstream>
23 #include <time.h>
24 #include <limits>
25 #include <algorithm>
26 
27 #include "MathStructure-support.h"
28 
29 using std::string;
30 using std::cout;
31 using std::vector;
32 using std::endl;
33 
34 #define FR_FUNCTION(FUNC)	Number nr(vargs[0].number()); if(!nr.FUNC() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity())) {return 0;} else {mstruct.set(nr); return 1;}
35 #define FR_FUNCTION_2(FUNC)	Number nr(vargs[0].number()); if(!nr.FUNC(vargs[1].number()) || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate() && !vargs[1].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex() && !vargs[1].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity() && !vargs[1].number().includesInfinity())) {return 0;} else {mstruct.set(nr); return 1;}
36 
FactorialFunction()37 FactorialFunction::FactorialFunction() : MathFunction("factorial", 1) {
38 	setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONNEGATIVE, true, false, INTEGER_TYPE_SLONG));
39 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)40 int FactorialFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
41 	FR_FUNCTION(factorial)
42 }
representsPositive(const MathStructure & vargs,bool) const43 bool FactorialFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsNegative(const MathStructure &,bool) const44 bool FactorialFunction::representsNegative(const MathStructure&, bool) const {return false;}
representsNonNegative(const MathStructure & vargs,bool) const45 bool FactorialFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsNonPositive(const MathStructure &,bool) const46 bool FactorialFunction::representsNonPositive(const MathStructure&, bool) const {return false;}
representsInteger(const MathStructure & vargs,bool) const47 bool FactorialFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsNumber(const MathStructure & vargs,bool) const48 bool FactorialFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsRational(const MathStructure & vargs,bool) const49 bool FactorialFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsReal(const MathStructure & vargs,bool) const50 bool FactorialFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsNonComplex(const MathStructure & vargs,bool) const51 bool FactorialFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;}
representsComplex(const MathStructure &,bool) const52 bool FactorialFunction::representsComplex(const MathStructure&, bool) const {return false;}
representsNonZero(const MathStructure & vargs,bool) const53 bool FactorialFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsEven(const MathStructure &,bool) const54 bool FactorialFunction::representsEven(const MathStructure&, bool) const {return false;}
representsOdd(const MathStructure &,bool) const55 bool FactorialFunction::representsOdd(const MathStructure&, bool) const {return false;}
representsUndefined(const MathStructure &) const56 bool FactorialFunction::representsUndefined(const MathStructure&) const {return false;}
57 
DoubleFactorialFunction()58 DoubleFactorialFunction::DoubleFactorialFunction() : MathFunction("factorial2", 1) {
59 	IntegerArgument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG);
60 	Number nr(-1, 1, 0);
61 	arg->setMin(&nr);
62 	setArgumentDefinition(1, arg);
63 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)64 int DoubleFactorialFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
65 	FR_FUNCTION(doubleFactorial)
66 }
representsPositive(const MathStructure & vargs,bool) const67 bool DoubleFactorialFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsNegative(const MathStructure &,bool) const68 bool DoubleFactorialFunction::representsNegative(const MathStructure&, bool) const {return false;}
representsNonNegative(const MathStructure & vargs,bool) const69 bool DoubleFactorialFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsNonPositive(const MathStructure &,bool) const70 bool DoubleFactorialFunction::representsNonPositive(const MathStructure&, bool) const {return false;}
representsInteger(const MathStructure & vargs,bool) const71 bool DoubleFactorialFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsNumber(const MathStructure & vargs,bool) const72 bool DoubleFactorialFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsRational(const MathStructure & vargs,bool) const73 bool DoubleFactorialFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsReal(const MathStructure & vargs,bool) const74 bool DoubleFactorialFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsNonComplex(const MathStructure & vargs,bool) const75 bool DoubleFactorialFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;}
representsComplex(const MathStructure &,bool) const76 bool DoubleFactorialFunction::representsComplex(const MathStructure&, bool) const {return false;}
representsNonZero(const MathStructure & vargs,bool) const77 bool DoubleFactorialFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsEven(const MathStructure &,bool) const78 bool DoubleFactorialFunction::representsEven(const MathStructure&, bool) const {return false;}
representsOdd(const MathStructure &,bool) const79 bool DoubleFactorialFunction::representsOdd(const MathStructure&, bool) const {return false;}
representsUndefined(const MathStructure &) const80 bool DoubleFactorialFunction::representsUndefined(const MathStructure&) const {return false;}
81 
MultiFactorialFunction()82 MultiFactorialFunction::MultiFactorialFunction() : MathFunction("multifactorial", 2) {
83 	setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONNEGATIVE, true, true, INTEGER_TYPE_SLONG));
84 	setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SLONG));
85 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)86 int MultiFactorialFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
87 	FR_FUNCTION_2(multiFactorial)
88 }
representsPositive(const MathStructure & vargs,bool) const89 bool MultiFactorialFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsNegative(const MathStructure &,bool) const90 bool MultiFactorialFunction::representsNegative(const MathStructure&, bool) const {return false;}
representsNonNegative(const MathStructure & vargs,bool) const91 bool MultiFactorialFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsNonPositive(const MathStructure &,bool) const92 bool MultiFactorialFunction::representsNonPositive(const MathStructure&, bool) const {return false;}
representsInteger(const MathStructure & vargs,bool) const93 bool MultiFactorialFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsNumber(const MathStructure & vargs,bool) const94 bool MultiFactorialFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsNonComplex(const MathStructure & vargs,bool) const95 bool MultiFactorialFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;}
representsRational(const MathStructure & vargs,bool) const96 bool MultiFactorialFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsReal(const MathStructure & vargs,bool) const97 bool MultiFactorialFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsComplex(const MathStructure &,bool) const98 bool MultiFactorialFunction::representsComplex(const MathStructure&, bool) const {return false;}
representsNonZero(const MathStructure & vargs,bool) const99 bool MultiFactorialFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();}
representsEven(const MathStructure &,bool) const100 bool MultiFactorialFunction::representsEven(const MathStructure&, bool) const {return false;}
representsOdd(const MathStructure &,bool) const101 bool MultiFactorialFunction::representsOdd(const MathStructure&, bool) const {return false;}
representsUndefined(const MathStructure &) const102 bool MultiFactorialFunction::representsUndefined(const MathStructure&) const {return false;}
103 
BinomialFunction()104 BinomialFunction::BinomialFunction() : MathFunction("binomial", 2) {
105 	setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true));
106 	setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_ULONG));
107 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)108 int BinomialFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
109 	Number nr;
110 	if(!nr.binomial(vargs[0].number(), vargs[1].number())) return 0;
111 	mstruct = nr;
112 	return 1;
113 }
114 
115