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 
20 #include <sstream>
21 #include <time.h>
22 #include <limits>
23 #include <algorithm>
24 
25 using std::string;
26 using std::cout;
27 using std::vector;
28 using std::endl;
29 
TotalFunction()30 TotalFunction::TotalFunction() : MathFunction("total", 1) {
31 	setArgumentDefinition(1, new VectorArgument(""));
32 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)33 int TotalFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
34 	mstruct.clear();
35 	for(size_t index = 0; index < vargs[0].size(); index++) {
36 		if(CALCULATOR->aborted()) return 0;
37 		mstruct.calculateAdd(vargs[0][index], eo);
38 	}
39 	return 1;
40 }
PercentileFunction()41 PercentileFunction::PercentileFunction() : MathFunction("percentile", 2, 3) {
42 	setArgumentDefinition(1, new VectorArgument(""));
43 	NumberArgument *arg = new NumberArgument();
44 	Number fr;
45 	arg->setMin(&fr);
46 	fr.set(100, 1, 0);
47 	arg->setMax(&fr);
48 	arg->setIncludeEqualsMin(true);
49 	arg->setIncludeEqualsMax(true);
50 	setArgumentDefinition(2, arg);
51 	IntegerArgument *iarg = new IntegerArgument();
52 	fr.set(1, 1, 0);
53 	iarg->setMin(&fr);
54 	fr.set(9, 1, 0);
55 	iarg->setMax(&fr);
56 	setArgumentDefinition(3, iarg);
57 	setDefaultValue(3, "8");
58 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)59 int PercentileFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
60 	MathStructure v(vargs[0]);
61 	if(v.size() == 0) {mstruct.clear(); return 1;}
62 	MathStructure *mp;
63 	Number fr100(100, 1, 0);
64 	int i_variant = vargs[2].number().intValue();
65 	if(!v.sortVector()) {
66 		return 0;
67 	} else {
68 		Number pfr(vargs[1].number());
69 		if(pfr == fr100) {
70 			// Max value
71 			mstruct = v[v.size() - 1];
72 			return 1;
73 		} else if(pfr.isZero()) {
74 			// Min value
75 			mstruct = v[0];
76 			return 1;
77 		}
78 		pfr /= 100;
79 		if(pfr == nr_half) {
80 			// Median
81 			if(v.size() % 2 == 1) {
82 				mstruct = v[v.size() / 2];
83 			} else {
84 				mstruct = v[v.size() / 2 - 1];
85 				mstruct += v[v.size() / 2];
86 				mstruct *= nr_half;
87 			}
88 			return 1;
89 		}
90 		// Method numbers as in R
91 		switch(i_variant) {
92 			case 2: {
93 				Number ufr(pfr);
94 				ufr *= (long int) v.countChildren();
95 				if(ufr.isInteger()) {
96 					pfr = ufr;
97 					ufr++;
98 					mstruct = v[pfr.uintValue() - 1];
99 					if(ufr.uintValue() > v.size()) return 1;
100 					mstruct += v[ufr.uintValue() - 1];
101 					mstruct *= nr_half;
102 					return 1;
103 				}
104 			}
105 			case 1: {
106 				pfr *= (long int) v.countChildren();
107 				pfr.intervalToMidValue();
108 				pfr.ceil();
109 				size_t index = pfr.uintValue();
110 				if(index > v.size()) index = v.size();
111 				if(index == 0) index = 1;
112 				mstruct = v[index - 1];
113 				return 1;
114 			}
115 			case 3: {
116 				pfr *= (long int) v.countChildren();
117 				pfr.intervalToMidValue();
118 				pfr.round();
119 				size_t index = pfr.uintValue();
120 				if(index > v.size()) index = v.size();
121 				if(index == 0) index = 1;
122 				mstruct = v[index - 1];
123 				return 1;
124 			}
125 			case 4: {pfr *= (long int) v.countChildren(); break;}
126 			case 5: {pfr *= (long int) v.countChildren(); pfr += nr_half; break;}
127 			case 6: {pfr *= (long int) v.countChildren() + 1; break;}
128 			case 7: {pfr *= (long int) v.countChildren() - 1; pfr += 1; break;}
129 			case 9: {pfr *= Number(v.countChildren() * 4 + 1, 4); pfr += Number(3, 8); break;}
130 			case 8: {}
131 			default: {pfr *= Number(v.countChildren() * 3 + 1, 3); pfr += Number(1, 3); break;}
132 		}
133 		pfr.intervalToMidValue();
134 		Number ufr(pfr);
135 		ufr.ceil();
136 		Number lfr(pfr);
137 		lfr.floor();
138 		pfr -= lfr;
139 		size_t u_index = ufr.uintValue();
140 		size_t l_index = lfr.uintValue();
141 		if(u_index > v.size()) {
142 			mstruct = v[v.size() - 1];
143 			return 1;
144 		}
145 		if(l_index == 0) {
146 			mstruct = v[0];
147 			return 1;
148 		}
149 		mp = v.getChild(u_index);
150 		if(!mp) return 0;
151 		MathStructure gap(*mp);
152 		mp = v.getChild(l_index);
153 		if(!mp) return 0;
154 		gap -= *mp;
155 		gap *= pfr;
156 		mp = v.getChild(l_index);
157 		if(!mp) return 0;
158 		mstruct = *mp;
159 		mstruct += gap;
160 	}
161 	return 1;
162 }
MinFunction()163 MinFunction::MinFunction() : MathFunction("min", 1) {
164 	setArgumentDefinition(1, new VectorArgument(""));
165 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)166 int MinFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
167 	ComparisonResult cmp;
168 	const MathStructure *min = NULL;
169 	vector<const MathStructure*> unsolveds;
170 	bool b = false;
171 	for(size_t index = 0; index < vargs[0].size(); index++) {
172 		if(min == NULL) {
173 			min = &vargs[0][index];
174 		} else {
175 			cmp = min->compare(vargs[0][index]);
176 			if(cmp == COMPARISON_RESULT_LESS) {
177 				min = &vargs[0][index];
178 				b = true;
179 			} else if(COMPARISON_NOT_FULLY_KNOWN(cmp)) {
180 				if(CALCULATOR->showArgumentErrors()) {
181 					CALCULATOR->error(true, _("Unsolvable comparison in %s()."), name().c_str(), NULL);
182 				}
183 				unsolveds.push_back(&vargs[0][index]);
184 			} else {
185 				b = true;
186 			}
187 		}
188 	}
189 	if(min) {
190 		if(unsolveds.size() > 0) {
191 			if(!b) return 0;
192 			MathStructure margs; margs.clearVector();
193 			margs.addChild(*min);
194 			for(size_t i = 0; i < unsolveds.size(); i++) {
195 				margs.addChild(*unsolveds[i]);
196 			}
197 			mstruct.set(this, &margs, NULL);
198 			return 1;
199 		} else {
200 			mstruct = *min;
201 			return 1;
202 		}
203 	}
204 	return 0;
205 }
MaxFunction()206 MaxFunction::MaxFunction() : MathFunction("max", 1) {
207 	setArgumentDefinition(1, new VectorArgument(""));
208 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)209 int MaxFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
210 	ComparisonResult cmp;
211 	const MathStructure *max = NULL;
212 	vector<const MathStructure*> unsolveds;
213 	bool b = false;
214 	for(size_t index = 0; index < vargs[0].size(); index++) {
215 		if(max == NULL) {
216 			max = &vargs[0][index];
217 		} else {
218 			cmp = max->compare(vargs[0][index]);
219 			if(cmp == COMPARISON_RESULT_GREATER) {
220 				max = &vargs[0][index];
221 				b = true;
222 			} else if(COMPARISON_NOT_FULLY_KNOWN(cmp)) {
223 				if(CALCULATOR->showArgumentErrors()) {
224 					CALCULATOR->error(true, _("Unsolvable comparison in %s()."), name().c_str(), NULL);
225 				}
226 				unsolveds.push_back(&vargs[0][index]);
227 			} else {
228 				b = true;
229 			}
230 		}
231 	}
232 	if(max) {
233 		if(unsolveds.size() > 0) {
234 			if(!b) return 0;
235 			MathStructure margs; margs.clearVector();
236 			margs.addChild(*max);
237 			for(size_t i = 0; i < unsolveds.size(); i++) {
238 				margs.addChild(*unsolveds[i]);
239 			}
240 			mstruct.set(this, &margs, NULL);
241 			return 1;
242 		} else {
243 			mstruct = *max;
244 			return 1;
245 		}
246 	}
247 	return 0;
248 }
ModeFunction()249 ModeFunction::ModeFunction() : MathFunction("mode", 1) {
250 	setArgumentDefinition(1, new VectorArgument(""));
251 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)252 int ModeFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
253 	if(vargs[0].size() <= 0) {
254 		return 0;
255 	}
256 	size_t n = 0;
257 	bool b;
258 	vector<const MathStructure*> vargs_nodup;
259 	vector<size_t> is;
260 	const MathStructure *value = NULL;
261 	for(size_t index_c = 0; index_c < vargs[0].size(); index_c++) {
262 		b = true;
263 		for(size_t index = 0; index < vargs_nodup.size(); index++) {
264 			if(vargs_nodup[index]->equals(vargs[0][index_c])) {
265 				is[index]++;
266 				b = false;
267 				break;
268 			}
269 		}
270 		if(b) {
271 			vargs_nodup.push_back(&vargs[0][index_c]);
272 			is.push_back(1);
273 		}
274 	}
275 	for(size_t index = 0; index < is.size(); index++) {
276 		if(is[index] > n) {
277 			n = is[index];
278 			value = vargs_nodup[index];
279 		}
280 	}
281 	if(value) {
282 		mstruct = *value;
283 		return 1;
284 	}
285 	return 0;
286 }
287 
RandFunction()288 RandFunction::RandFunction() : MathFunction("rand", 0, 2) {
289 	setArgumentDefinition(1, new IntegerArgument());
290 	setDefaultValue(1, "0");
291 	setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE));
292 	setDefaultValue(2, "1");
293 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)294 int RandFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
295 	size_t n = (size_t) vargs[1].number().uintValue();
296 	if(n > 1) {mstruct.clearVector(); mstruct.resizeVector(n, m_zero);}
297 	Number nr;
298 	for(size_t i = 0; i < n; i++) {
299 		if(vargs[0].number().isZero() || vargs[0].number().isNegative()) {
300 			nr.rand();
301 		} else {
302 			nr.intRand(vargs[0].number());
303 			nr++;
304 		}
305 		if(n > 1) mstruct[i] = nr;
306 		else mstruct = nr;
307 	}
308 	return 1;
309 }
representsReal(const MathStructure &,bool) const310 bool RandFunction::representsReal(const MathStructure&, bool) const {return true;}
representsInteger(const MathStructure & vargs,bool) const311 bool RandFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() > 0 && vargs[0].isNumber() && vargs[0].number().isPositive();}
representsNonNegative(const MathStructure &,bool) const312 bool RandFunction::representsNonNegative(const MathStructure&, bool) const {return true;}
313 
RandnFunction()314 RandnFunction::RandnFunction() : MathFunction("randnorm", 0, 3) {
315 	setDefaultValue(1, "0");
316 	setDefaultValue(2, "1");
317 	setArgumentDefinition(3, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE));
318 	setDefaultValue(3, "1");
319 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)320 int RandnFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
321 	size_t n = (size_t) vargs[2].number().uintValue();
322 	if(n > 1) {mstruct.clearVector(); mstruct.resizeVector(n, m_zero);}
323 #if MPFR_VERSION_MAJOR < 4
324 	Number nr_u, nr_v, nr_r2;
325 	for(size_t i = 0; i < n; i++) {
326 		do {
327 			nr_u.rand(); nr_u *= 2; nr_u -= 1;
328 			nr_v.rand(); nr_v *= 2; nr_v -= 1;
329 			nr_r2 = (nr_u ^ 2) + (nr_v ^ 2);
330 		} while(nr_r2 > 1 || nr_r2.isZero());
331 		Number nr_rsq(nr_r2);
332 		nr_rsq.ln();
333 		nr_rsq /= nr_r2;
334 		nr_rsq *= -2;
335 		nr_rsq.sqrt();
336 		nr_u *= nr_rsq;
337 		if(n > 1) {
338 			mstruct[i] = nr_u;
339 			i++;
340 			if(i < n) {
341 				nr_v *= nr_rsq;
342 				mstruct[i] = nr_v;
343 			}
344 		} else {
345 			mstruct = nr_u;
346 		}
347 	}
348 #else
349 	Number nr;
350 	for(size_t i = 0; i < n; i++) {
351 		nr.randn();
352 		if(n > 1) mstruct[i] = nr;
353 		else mstruct = nr;
354 	}
355 #endif
356 	if(!vargs[1].isOne()) mstruct *= vargs[1];
357 	if(!vargs[0].isZero()) mstruct += vargs[0];
358 	return 1;
359 }
representsReal(const MathStructure &,bool) const360 bool RandnFunction::representsReal(const MathStructure&, bool) const {return true;}
representsNonComplex(const MathStructure &,bool) const361 bool RandnFunction::representsNonComplex(const MathStructure&, bool) const {return true;}
representsNumber(const MathStructure &,bool) const362 bool RandnFunction::representsNumber(const MathStructure&, bool) const {return true;}
363 
RandPoissonFunction()364 RandPoissonFunction::RandPoissonFunction() : MathFunction("randpoisson", 1, 2) {
365 	setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONNEGATIVE));
366 	setDefaultValue(1, "0");
367 	setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE));
368 	setDefaultValue(2, "1");
369 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)370 int RandPoissonFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
371 	size_t n = (size_t) vargs[2].number().uintValue();
372 	if(n > 1) {mstruct.clearVector(); mstruct.resizeVector(n, m_zero);}
373 	Number nr_L(vargs[1].number());
374 	nr_L.exp();
375 	Number nr_k, nr_p, nr_u;
376 	for(size_t i = 0; i < n; i++) {
377 		nr_k.clear(); nr_p = 1;
378 		do {
379 			nr_k++;
380 			nr_u.rand();
381 			nr_p *= nr_u;
382 		} while(nr_p > nr_L);
383 		nr_k--;
384 		if(n > 1) mstruct[i] = nr_k;
385 		else mstruct = nr_k;
386 	}
387 	return 1;
388 }
representsReal(const MathStructure &,bool) const389 bool RandPoissonFunction::representsReal(const MathStructure&, bool) const {return true;}
representsInteger(const MathStructure & vargs,bool) const390 bool RandPoissonFunction::representsInteger(const MathStructure &vargs, bool) const {return true;}
representsNonNegative(const MathStructure &,bool) const391 bool RandPoissonFunction::representsNonNegative(const MathStructure&, bool) const {return true;}
392 
393