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