PEBL 2.2
Psychology Experiment Building Language - Cross-platform psychological experiment development system
PEBLMath.cpp
Go to the documentation of this file.
1//* -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- */
3// Name: src/libs/PEBLMATH.cpp
4// Purpose: Built-in math functions for PEBL
5// Author: Shane T. Mueller, Ph.D.
6// Copyright: (c) 2003-2026 Shane T. Mueller <smueller@obereed.net>
7// License: GPL 2
8//
9//
10//
11// This file is part of the PEBL project.
12//
13// PEBL is free software; you can redistribute it and/or modify
14// it under the terms of the GNU General Public License as published by
15// the Free Software Foundation; either version 2 of the License, or
16// (at your option) any later version.
17//
18// PEBL is distributed in the hope that it will be useful,
19// but WITHOUT ANY WARRANTY; without even the implied warranty of
20// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21// GNU General Public License for more details.
22//
23// You should have received a copy of the GNU General Public License
24// along with PEBL; if not, write to the Free Software
25// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27#include "PEBLMath.h"
28#include "../base/Variant.h"
29#include "../base/PList.h"
30#include "../base/PComplexData.h"
31#include "../utility/PEBLUtility.h"
32#include "../utility/PError.h"
33#include "../utility/Defs.h"
34#include "../base/PEBLObject.h"
35
36#include <stdlib.h> //Used for random numbers
37//#include <math.h>
38#include <cmath>
39#include <list>
40#include <string>
41#include <sstream>
42
43#ifdef WIN32
44#include <time.h>
45#endif
46
47using std::string;
48using std::cout;
49using std::endl;
50
51//Putatively precise to 50 digits:
52#define PI 3.141592653589793238462643383279502884197169399375
53#define E 2.718281828459045235360287471352662497757247093700
54
56{
57
58 //If this function is called, v is a list of elements.
59 //We should call the function on each element of the list, creating
60 //a list of the results, turn this into a variant, and return it.
61
62 //Get the list of variants.
63
64 PList * plist = v.GetComplexData()->GetList();
65 //Make a results list
66 PList * resultslist = new PList();
67 //Declare a temporary argument list.
68 //Now, apply
69
70
71 PList* arglist;
73 Variant tmpVariant;
74 PComplexData * tmpPCD;
75
76
77 std::vector<Variant>::iterator p = plist->Begin();
78 while(p != plist->End())
79 {
80
81 //Create new variant list to pass to function
82 arglist = new PList();
83
84 //Add the first element of plist to it
85 arglist->PushBack(*p);
86
87 //make it into a PCD
88 tmpObj = counted_ptr<PEBLObjectBase>(arglist);
89 tmpPCD = (new PComplexData(tmpObj));
90 //Create variant to hold it.
91 tmpVariant = Variant(tmpPCD);
92
93 //tmpPCD is now part of tmpVariant, so we don't need to destroy it.
94 //delete tmpPCD;
95 tmpPCD=NULL;
96
97
98 Variant result = funcname(tmpVariant);
99 resultslist->PushBack(result);
100
101 //Get rid of arglist so we can make a new one.
102 delete arglist;
103 arglist = NULL;
104 //plist->PopFront(); We need to do something here to handle recursion with vectors instead of lists
105 //e.g., an iterator.
106 //PError::SignalFatalError("Recursive operation not supported.");
107 p++;
108 }
109
110 //Now, resultslist is a PList. Put it into a PCD.
112 PComplexData * pcd = new PComplexData(tmp);
113
114 Variant tmp2 = Variant(pcd);
115 delete pcd;
116 pcd=NULL;
117 return tmp2;
118
119}
120
121
122//This is like the recurse above, but is used when there are other arguments
123//of interest, such as logn() or round()
125{
126
127 //If this function is called, v is a list of elements.
128 //We should call the function on each element of the list, creating
129 //a list of the results, turn this into a variant, and return it.
130
131 //Get the list of variants.
132
133 PList * plist = v.GetComplexData()->GetList();
134 //Make a results list
135
136 PList * resultslist = new PList();
137
138
139 std::vector<Variant>::iterator p = plist->Begin();
140
141 //Add the argument onto arglist. argument should be a list of variants.
142 //Declare an temporary argument list.
143 //counted_ptr<PEBLObjectBase> tmp2 = argument.GetComplexData()->GetObject();
144 //Variant arg2 = ((PList*)(tmp2.get()));
145
146 PList * arglist = NULL;
147
148 PComplexData * pcd;
149 while(p != plist->End())
150 {
151 arglist = new PList();
152 arglist->PushBack(*p); //Add the critical argument
153 arglist->PushBack(argument); //add second argument
155
156 pcd = new PComplexData(tmp3);
157 Variant tmp = Variant(pcd);
158 resultslist->PushBack(funcname(tmp)); //Execute
159
160 delete arglist;
161 arglist = NULL;
162
163
164 p++;
165 }
166
167 //Now, resultslist is a PList. Put it into a PCD.
168 pcd = new PComplexData(counted_ptr<PEBLObjectBase>(resultslist));
169 Variant tmp3 = Variant(pcd);
170 delete pcd;
171 pcd=NULL;
172
173 return tmp3;
174}
175
176
177
178//Logarithmic Functions
180{
181
182// std::cout << "log10a\n";
183// std::cout << "(" << v << ")" << std::endl;
184 PList * plist = v.GetComplexData()->GetList();
185 Variant v1 = plist->First();
186// std::cout << "v1: " << v1 << std::endl;
187 if(v1.IsNumber())
188 {
189 //return Variant((pDouble)log10l(v1.GetFloat()));
190 return Variant((pDouble)log10(v1.GetFloat()));
191
192 }
193#ifndef PEBL_EMSCRIPTEN
194 else if(v1.GetComplexData()->IsList())
195 {
196 return Recurse(v1, Log10);
197
198 }
199#endif
200 else
201 {
202 PError::SignalFatalError("Non-numeric argument in Log10");
203 }
204
205 return 0;
206}
207
209{
210
211 //std::cout <<"Log2: " << v << std::endl;
212 PList * plist = v.GetComplexData()->GetList();
213 Variant v1 = plist->First();
214 if(v1.IsNumber())
215 {
216 return Variant(PEBLUtility::Log2(v1.GetFloat()));
217 }
218 else if(v1.GetComplexData()->IsList())
219 {
220 return Recurse(v1, Log2);
221
222 }
223 else
224 {
225 PError::SignalFatalError("Non-numeric argument in Log2");
226 return 0;
227 }
228
229}
230
232{
233
234 PList * plist = v.GetComplexData()->GetList();
235
236 Variant v1 = plist->First();
237 if(v1.IsNumber())
238 {
239 //return Variant((pDouble)logl(v1.GetFloat()));
240 return Variant((pDouble)log(v1.GetFloat()));
241 }
242 else if(v1.GetComplexData()->IsList())
243 {
244 return Recurse(v1, Ln);
245
246 }
247 else
248 {
249
250 PError::SignalFatalError("Non-numeric argument in Ln");
251 return 0;
252 }
253
254}
255
256
258{
259 //This has two arguments; the number and the base.
260
261 PList * plist = v.GetComplexData()->GetList();
262 Variant number = plist->First(); //plist->PopFront();
263
264 //Don't get the second argument right away--if the first argument is
265 //a list, we should just pass it along to the recurse2 function.
266
267 Variant base = plist->Nth(2);// plist->PopFront(); //Get the base argument
268
269if(number.IsNumber())
270 {
271 //return Variant((pDouble)(logl(number.GetFloat())/ logl(base.GetFloat())));
272 return Variant((pDouble)(log(number.GetFloat())/ log(base.GetFloat())));
273 }
274 else if(number.GetComplexData()->IsList())
275 {
276
277 //counted_ptr<PEBLObjectBase>tmp2 = counted_ptr<PEBLObjectBase>(plist);
278 //PComplexData * pcd = new PComplexData(tmp2);
279
280 //Variant args = Variant(pcd);
281 //delete pcd;
282 //pcd=NULL;
283 Variant retval = Recurse2(number, LogN, base);
284 return retval;
285 }
286 else
287 {
288 PError::SignalFatalError("Non-numeric argument in LogN");
289 return 0;
290 }
291}
292
293
295{
296
297 PList * plist = v.GetComplexData()->GetList();
298 Variant v1 = plist->First();
299 if(v1.IsNumber())
300 {
301 //return Variant((pDouble)expl(v1.GetFloat()));
302 return Variant((pDouble)exp(v1.GetFloat()));
303 }
304 else if(v1.GetComplexData()->IsList())
305 {
306 return Recurse(v1, Exp);
307
308 }
309 else
310 {
311
312 PError::SignalFatalError("Non-numeric argument in Exp");
313 return 0;
314 }
315
316}
317
318
320{
321 //This has two arguments; the number and the base.
322
323 PList * plist = v.GetComplexData()->GetList();
324 Variant base = plist->First();// plist->PopFront();
325
326 //Don't get the second argument right away--if the first argument is
327 //a list, we should just pass it along to the recurse2 function.
328
329 if(base.IsNumber())
330 {
331 Variant power = plist->Nth(2); //plist->PopFront(); //Get the base argument
332 //return (pDouble)powl((pDouble)base, (pDouble)power);
333 return (pDouble)pow((pDouble)base, (pDouble)power);
334 }
335 else if(base.GetComplexData()->IsList())
336 {
337
339 PComplexData * pcd = new PComplexData(tmp);
340 Variant args = Variant(pcd);
341 delete pcd;
342 pcd=NULL;
343
344 Variant retval = Recurse2(base, Pow, args);
345
346 return retval;
347 }
348 else
349 {
350 PError::SignalFatalError("Non-numeric argument in Pow");
351 return 0;
352 }
353}
354
356{
357
358 PList * plist = v.GetComplexData()->GetList();
359 Variant v1 = plist->First();
360 if(v1.IsNumber())
361 {
362 //return Variant((pDouble)sqrtl(v1.GetFloat()));
363 return Variant((pDouble)sqrt(v1.GetFloat()));
364 }
365 else if(v1.GetComplexData()->IsList())
366 {
367 return Recurse(v1, Sqrt);
368
369 }
370 else
371 {
372 PError::SignalFatalError("Non-numeric argument in Sqrt");
373 return 0;
374 }
375
376}
377
378
380{
381 //This has two arguments; the number and the root.
382
383 PList * plist = v.GetComplexData()->GetList();
384 Variant number = plist->First(); //plist->PopFront();
385
386 //Don't get the second argument right away--if the first argument is
387 //a list, we should just pass it along to the recurse2 function.
388
389 if(number.IsNumber())
390 {
391 Variant root = plist->Nth(2);// plist->PopFront(); //Get the base argument
392 //return (pDouble)powl((pDouble)number,(pDouble)( 1 / root.GetFloat()));
393 return (pDouble)pow((pDouble)number,(pDouble)( 1 / root.GetFloat()));
394 }
395 else if(number.GetComplexData()->IsList())
396 {
398 PComplexData * pcd = new PComplexData(tmp);
399 Variant args = Variant(pcd);
400 delete pcd;
401 pcd=NULL;
402
403 Variant retval = Recurse2(number, NthRoot, args);
404 return retval;
405
406
407 }
408 else
409 {
410
411 PError::SignalFatalError("Non-numeric argument in NthRoot");
412 return 0;
413 }
414}
415
416
417
418 //Trigonometric Functions.
419
420
422{
423
424 PList * plist = v.GetComplexData()->GetList();
425 Variant v1 = plist->First();
426 if(v1.IsNumber())
427 {
428 //return Variant((pDouble)tanl(v1.GetFloat()));
429 return Variant((pDouble)tan(v1.GetFloat()));
430 }
431 else if(v1.GetComplexData()->IsList())
432 {
433 return Recurse(v1, Tan);
434
435 }
436 else
437 {
438 PError::SignalFatalError("Non-numeric argument in Tan");
439
440 return 0;
441 }
442
443}
444
445
446
449{
450
451 PList * plist = v.GetComplexData()->GetList();
452
453 Variant v1 = plist->First();
454 if(v1.IsNumber())
455 {
456 //return Variant((pDouble)sinl(v1.GetFloat()));
457 return Variant((pDouble)sin(v1.GetFloat()));
458 }
459 else if(v1.GetComplexData()->IsList())
460 {
461 return Recurse(v1, Sin);
462
463 }
464 else
465 {
466 PError::SignalFatalError("Non-numeric argument in [Sin]");
467
468 return 0;
469 }
470}
471
472
474{
475
476
477 PList * plist = v.GetComplexData()->GetList();
478
479 Variant v1 = plist->First();
480 if(v1.IsNumber())
481 {
482 //return Variant((pDouble)cosl(v1.GetFloat()));
483 return Variant((pDouble)cos(v1.GetFloat()));
484 }
485 else if(v1.GetComplexData()->IsList())
486 {
487 return Recurse(v1, Cos);
488 }
489 else
490 {
491
492 PError::SignalFatalError("Non-numeric argument in [Cos]");
493 return 0;
494 }
495}
496
497
499{
500
501 PList * plist = v.GetComplexData()->GetList();
502
503 Variant v1 = plist->First();
504 if(v1.IsNumber())
505 {
506
507 return Variant((pDouble)atan(v1.GetFloat()));
508 }
509 else if(v1.GetComplexData()->IsList())
510 {
511 return Recurse(v1, ATan);
512
513 }
514 else
515 {
516
517 PError::SignalFatalError("Non-numeric argument in [ATan]");
518 return 0;
519 }
520}
521
523{
524
525 PList * plist = v.GetComplexData()->GetList();
526
527
528 Variant v1 = plist->First();
529 if(v1.IsNumber())
530 {
531 return Variant((pDouble)asin(v1.GetFloat()));
532 //return Variant((pDouble)asinl(v1.GetFloat()));
533 }
534 else if(v1.GetComplexData()->IsList())
535 {
536 return Recurse(v1, ASin);
537
538 }
539 else
540 {
541 PError::SignalFatalError("Non-numeric argument in [ASin]");
542 return 0;
543 }
544}
545
547{
548
549 PList * plist = v.GetComplexData()->GetList();
550
551
552 Variant v1 = plist->First();
553 if(v1.IsNumber())
554 {
555 // return Variant((pDouble)acosl(v1.GetFloat()));
556 return Variant((pDouble)acos(v1.GetFloat()));
557 }
558 else if(v1.GetComplexData()->IsList())
559 {
560 return Recurse(v1, ACos);
561
562 }
563 else
564 {
565 PError::SignalFatalError("Non-numeric argument in [ACos]");
566 return 0;
567 }
568}
569
570
571
572//Converts radians to degrees. Does not truncate at 180.
574{
575
576 PList * plist = v.GetComplexData()->GetList();
577
578
579 Variant v1 = plist->First(); //plist->PopFront();
580
581 if(v1.IsNumber())
582 {
583 return Variant((pDouble)(v1.GetFloat() * PI / 180));
584 }
585 else if(v1.GetComplexData()->IsList())
586 {
587 return Recurse(v1, DegToRad);
588
589 }
590 else
591 {
592 PError::SignalFatalError("Non-numeric argument in [DegToRad]");
593 return 0;
594 }
595
596
597}
598
599
601{
602
603 PList * plist = v.GetComplexData()->GetList();
604
605
606 Variant v1 = plist->First(); //plist->PopFront();
607
608 if(v1.IsNumber())
609 {
610 return Variant(v1.GetFloat() * 180/ PI);
611 }
612 else if(v1.GetComplexData()->IsList())
613 {
614 return Recurse(v1, RadToDeg);
615
616 }
617 else
618 {
619 PError::SignalFatalError("Non-numeric argument in [RadToDeg]");
620 return 0;
621 }
622}
623
624
625//Rounding Functions. Most of these operate on a single number, rounding to the nearest integer.
627{
628
629
630 PList * plist = v.GetComplexData()->GetList();
631
632 Variant v1 = plist->First();
633 if(v1.IsNumber())
634 {
635
636 //plist->PopFront();
637
638 if(plist->Length()==1)
639 {
640 return Variant(PEBLUtility::Round(v1.GetFloat()));
641 }else{
642
643 Variant v2 =plist->Nth(2);
644
645 PError::AssertType(v2, PEAT_INTEGER,"Second (optional) argument in [Round(number, precision)] must be an integer: ");
647 }
648
649 }
650 else if(v1.GetComplexData()->IsList())
651 {
652 return Recurse(v1, Round);
653 }
654 else
655 {
656 PError::SignalFatalError("Non-numeric argument in [Round]");
657 return 0;
658 }
659}
660
661
663{
664
665
666 PList * plist = v.GetComplexData()->GetList();
667 Variant v1 = plist->First();
668 if(v1.IsNumber())
669 {
670 //return Variant((pInt)(floorl(v1.GetFloat())));
671 return Variant((pInt)(floor(v1.GetFloat())));
672 }
673 else if(v1.GetComplexData()->IsList())
674 {
675 return Recurse(v1, Floor);
676
677 }
678 else
679 {
680 PError::SignalFatalError("Non-numeric argument in [Floor]");
681 return 0;
682 }
683}
684
685
687{
688
689 PList * plist = v.GetComplexData()->GetList();
690 Variant v1 = plist->First();
691 if(v1.IsNumber())
692 {
693 //return Variant((pInt)(ceill(v1.GetFloat())));
694 return Variant((pInt)(ceil(v1.GetFloat())));
695 }
696 else if(v1.GetComplexData()->IsList())
697 {
698 return Recurse(v1, Ceiling);
699
700 }
701 else
702 {
703 PError::SignalFatalError("Non-numeric argument in [Ceiling]");
704 return 0;
705 }
706}
707
709{
710
711 PList * plist = v.GetComplexData()->GetList();
712 Variant v1 = plist->First();
713 if(v1.IsNumber())
714 {
716 }
717 else if(v1.GetComplexData()->IsList())
718 {
719 return Recurse(v1, AbsFloor);
720
721 }
722 else
723 {
724 PError::SignalFatalError("Non-numeric argument in [AbsFloor]");
725 return 0;
726 }
727
728}
729
730
731
732//Modular Arithmetic: This will even work for non-integers.
734{
735
736 PList * plist = v.GetComplexData()->GetList();
737
738
739 PError::AssertType( plist->First(), PEAT_NUMBER, "Argument error in first parameter of Mod(<number>,<number>)");
740 pInt v1 = plist->First(); //plist->PopFront();
741
742
743 PError::AssertType( plist->Nth(2), PEAT_NUMBER, "Argument error in second parameter of Mod(<number>,<number>)");
744 pInt v2 = plist->Nth(2); //plist->PopFront();
745
746
747 double remainder =((pDouble)v1/v2 - (v1/v2));
748 if( remainder < 0 ) remainder += 1.0;
749 if(remainder >= 1.0) remainder = 0;
750
751 return Variant((pInt)(remainder * v2 + .00001));
752}
753
754
755//Modular Arithmetic
757{
758 PError::SignalFatalError("Function [Div] Not implemented.");
759 return Variant(0);
760}
761
762
763//Coercion
765{
766
767
768 PList * plist = v.GetComplexData()->GetList();
769 return Variant(plist->First().GetInteger());
770}
771
773{
774 PList * plist = v.GetComplexData()->GetList();
775 return Variant(plist->First().GetFloat());
776
777}
778
780{
781 PList * plist = v.GetComplexData()->GetList();
782 return Variant(plist->First().GetString());
783}
784
785
787{
788
789 PList * plist = v.GetComplexData()->GetList();
790
791 Variant v1 = plist->First();
792
793 //If v is a string, then turn it either into an integer or a float,
794 //depending on whether there is a '.' in it.
795
796 if(v1.IsString())
797 {
798 bool hasPoint = false;
799
800 std::string tmp = v.GetString();
801 std::string::iterator i = tmp.begin();
802
803 while(i != tmp.end() && hasPoint == false)
804 {
805 if(*i == '.')
806 hasPoint = true;
807 i++;
808 }
809
810 if(hasPoint)
811 {
812 return Variant(v1.GetFloat());
813 }
814 else
815 {
816 return Variant(v1.GetInteger());
817 }
818
819 }
820
821 return Variant(v1.GetFloat());
822}
823
824//Other
826{
827
828
829 PList * plist = v.GetComplexData()->GetList();
830
831 Variant v1 = plist->First();
832 if(v1.IsNumber())
833 {
834 return (v1.GetFloat()<0)? -1: 1;
835 }
836 else if(v1.GetComplexData()->IsList())
837 {
838 return Recurse(v1, Sign);
839
840 }
841 else
842 {
843 PError::SignalFatalError("Non-numeric argument in Function [Sign]");
844 return 0;
845 }
846
847}
848
849
850
851
853{
854
855 PList * plist = v.GetComplexData()->GetList();
856
857 Variant v1 = plist->First();
858 if(v1.IsNumber())
859 {
860 return Variant((pDouble)fabsl(v1.GetFloat()));
861 }
862 else if(v1.GetComplexData()->IsList())
863 {
864 return Recurse(v1, Abs);
865
866 }
867 else
868 {
869 PError::SignalFatalError("Non-numeric argument in Function [AbsFloor]");
870 return 0;
871 }
872
873}
874
875
876// statistical functions replaced with PEBL functions.
877//
878// //Statistical (operates on a list; ignores non-numeric elements.)
879// Variant PEBLMath::Mean(Variant v)
880// {
881// PError::SignalFatalError("Function [Mean] Not implemented.");
882// return Variant(0);
883// }
884
885// Variant PEBLMath::Min(Variant v)
886// {
887//
888// PList * plist = v.GetComplexData()->GetList();
889
890// if(plist->First().IsComplexData())
891// {
892// if(plist->First().GetComplexData()->IsList())
893// {
894// Variant retval= Recurse(v, Min);
895// //This is a list; extract the first item and return it.
896// return retval.GetComplexData()->GetList()->First();
897// }
898// PError::SignalFatalError("Min() can only take numbers or lists as arguments.");
899// return Variant(0);
900// }
901
902
903// Variant min = plist->First();
904// std::vector<Variant>::const_iterator i = plist->Begin();
905
906// while(i != plist->End())
907// {
908// PError::AssertType(*i, PEAT_NUMBER, "Arguments of Min must be numbers.");
909// if(*i < min)
910// min = *i;
911// i++;
912// }
913// return min;
914// }
915
916
917
918// Variant PEBLMath::Max(Variant v)
919// {
920//
921// PList * plist = v.GetComplexData()->GetList();
922
923// if(plist->First().IsComplexData())
924// {
925// if(plist->First().GetComplexData()->IsList())
926// {
927// Variant retval = Recurse(v, Max);
928// return retval.GetComplexData()->GetList()->First();
929// }
930// PError::SignalFatalError("Min() can only take numbers or lists as arguments.");
931// return Variant(0);
932// }
933
934// Variant max = plist->First();
935// std::vector<Variant>::const_iterator i = plist->Begin();
936
937// while(i != plist->End())
938// {
939// PError::AssertType(*i, PEAT_NUMBER, "Arguments of Max must be numbers.");
940// if(*i > max)
941// max = *i;
942// i++;
943// }
944// return max;
945// }
946
947
948
949// Variant PEBLMath::StDev(Variant v)
950// {
951// PError::SignalFatalError("Function [StDev] Not implemented.");
952// return Variant(0);
953// }
954
955// Variant PEBLMath::Median(Variant v)
956// {
957// PError::SignalFatalError("Function [Median] Not implemented.");
958// return Variant(0);
959
960// }
961
962
966
968{
969 time_t now = time(0);
970 srand((unsigned int)now);
971 long unsigned int tmp = (long unsigned int)now;
972 return Variant(tmp);
973
974}
978{
979 //v[1] should have the parameter
980
981 PList * plist = v.GetComplexData()->GetList();
982
983 PError::AssertType(plist->First().GetInteger(), PEAT_NUMBER, "Argument error in function [SeedRNG(<number>)]: ");
984
985 pInt seed = plist->First();
986 srand((unsigned int)seed);
987
988 return Variant(true);
989}
990
991
992
996{
997 //v[1] should have nothing in it.
998
1000}
1001
1002
1009{
1010 //v[1] should have the parameter
1011
1012 PList * plist = v.GetComplexData()->GetList();
1013
1014
1015 PError::AssertType(plist->First(), PEAT_NUMBER, "Argument error in function [RandomDiscrete(<number>)]: ");
1016
1017 int v1 = plist->First();
1018 if(v1 < 1)
1019 {
1020 string message = "Function [RandomDiscrete] requires argument >= 1; received ";
1021 message += v1;
1022 message += ". Returning 1.";
1023 PError::SignalWarning(message);
1024 return Variant(1);
1025 }
1026
1027 //Since the most-significant digits are a bit predictable, use the remainder function
1028 unsigned int r = rand();
1029 return Variant((pInt)(r % v1)+ 1 );
1030
1031}
1032
1033
1038{
1039
1040
1041 PList * plist = v.GetComplexData()->GetList();
1042
1043 //v[1] should have the parameter
1044
1045 PError::AssertType(plist->First(), PEAT_NUMBER, "Argument error in function [RandomUniform(<number>)]: ");
1046
1047 pDouble upperbound = plist->First(); //plist->PopFront();
1048 if(upperbound < 0)
1049 {
1050 std::ostringstream message;
1051 message << "Function [RandomUniform] requires argument >= 0; received "
1052 << upperbound;
1053 PError::SignalFatalError(message.str().c_str());
1054 }
1055
1056 return Variant(upperbound * PEBLUtility::RandomUniform());
1057}
1058
1059
1060
1061
1066{
1067
1068 PList * plist = v.GetComplexData()->GetList();
1069
1070 //v[1] should be mean, v[2] should be standard deviation.
1071
1072 PError::AssertType(plist->First(), PEAT_NUMBER, "Argument error in first parameter of function [RandomNormal(<mean>, <stdev>)]: ");
1073 pDouble mean = plist->First(); //plist->PopFront();
1074
1075 PError::AssertType(plist->Nth(2), PEAT_NUMBER, "Argument error in second parameter function [RandomNormal(<mean>, <stdev>)]: ");
1076 pDouble stdev = plist->Nth(2);// plist->PopFront();
1077
1078 if(stdev < 0) PError::SignalFatalError("Standard Deviation parameter of function [RandomNormal(<mean>,<stdev>)] must be positive.");
1079
1080 return Variant(mean + PEBLUtility::RandomNormal()*stdev);
1081}
1082
1087{
1088 //v[1] should be lambda, the mean of the Exponential RV.
1089
1090 PList * plist = v.GetComplexData()->GetList();
1091
1092
1093 PError::AssertType(plist->First(), PEAT_NUMBER, "Argument error in function [RandomExponential(<number>)]: ");
1094 pDouble lambda = plist->First(); //plist->PopFront();
1095
1096 //The value of lambda may not be able to vary freely--It may not be able to be negative.
1097 //This should be checked for.
1098
1099 return Variant(-lambda * log(PEBLUtility::RandomUniform()));
1100}
1101
1102
1106{
1107 //v should have no parameters
1108
1109 double p = PEBLUtility::RandomUniform();
1110
1111 return Variant(log(p/(1-p)));
1112}
1113
1114
1118{
1119
1120
1121 PList * plist = v.GetComplexData()->GetList();
1122
1123 //v[1] should be median, v[2] should be the spread
1124 PError::AssertType(plist->First(), PEAT_NUMBER, "Argument error in first parameter function [RandomLogNormal(<median>, <spread>)]: ");
1125 pDouble median = plist->First(); //plist->PopFront();
1126
1127 PError::AssertType(plist->Nth(2), PEAT_NUMBER, "Argument error in second parameter function [RandomLogNormal(<median>, <spread>)]: ");
1128 pDouble spread = plist->Nth(2);// plist->PopFront();
1129
1130 return Variant(median * exp(spread * PEBLUtility::RandomNormal()));
1131}
1132
1136{
1137
1138 PList * plist = v.GetComplexData()->GetList();
1139
1140 //v[1] should have the parameter
1141
1142 PError::AssertType(plist->First(), PEAT_NUMBER, "Argument error in first parameter function [RandomBinomial(<p>, <N>)]: ");
1143 pDouble p = plist->First();// plist->PopFront();
1144 PError::AssertType(plist->Nth(2), PEAT_NUMBER, "Argument error in second parameter function [RandomBinomial(<p>, <N>)]: ");
1145 pInt N = plist->Nth(2); //plist->PopFront();
1146
1147 pInt count = 0;
1148 for(int i = 0; i < N; i++)
1149 {
1151 }
1152
1153
1154 return Variant(count);
1155}
1156
1157
1161{
1162
1163 PList * plist = v.GetComplexData()->GetList();
1164
1165 //v[1] should have the parameter
1166
1167 PError::AssertType(plist->First(), PEAT_NUMBER, "Argument error in first parameter function [RandomBinomial(<p>, <N>)]: ");
1168 pDouble p = plist->First();// plist->PopFront();
1169
1171 return Variant(1);
1172 else
1173 return Variant(0);
1174}
#define NULL
Definition BinReloc.cpp:317
#define pInt
Definition Defs.h:8
#define pDouble
Definition Defs.h:7
#define PI
Definition PEBLMath.cpp:52
@ PEAT_INTEGER
Definition PError.h:44
@ PEAT_NUMBER
Definition PError.h:43
counted_ptr< PEBLObjectBase > GetObject() const
PList * GetList() const
bool IsList() const
Definition PList.h:45
std::vector< Variant >::const_iterator End() const
Definition PList.cpp:132
std::vector< Variant >::const_iterator Begin() const
Definition PList.cpp:127
Variant Nth(unsigned int n)
Definition PList.cpp:181
unsigned long Length() const
Definition PList.h:89
void PushBack(const Variant &v)
Definition PList.cpp:149
Variant First()
Definition PList.cpp:169
pInt GetInteger() const
Definition Variant.cpp:997
bool IsString() const
Definition Variant.cpp:948
std::string GetString() const
Definition Variant.cpp:1056
PComplexData * GetComplexData() const
Definition Variant.cpp:1299
pDouble GetFloat() const
Definition Variant.cpp:1025
bool IsNumber() const
This tests whether the Variant is a number (i.e., a float or an integer.)
Definition Variant.cpp:930
Variant Sign(Variant v)
Definition PEBLMath.cpp:825
Variant LogN(Variant v)
Definition PEBLMath.cpp:257
Variant Sin(Variant v)
Sin takes one parameter.
Definition PEBLMath.cpp:448
Variant ASin(Variant v)
Definition PEBLMath.cpp:522
Variant ToFloat(Variant v)
Definition PEBLMath.cpp:772
Variant Sqrt(Variant v)
Definition PEBLMath.cpp:355
Variant ToString(Variant v)
Definition PEBLMath.cpp:779
Variant RandomBinomial(Variant v)
Variant NthRoot(Variant v)
Definition PEBLMath.cpp:379
Variant Recurse2(Variant v, Variant(*)(Variant), Variant argument)
Definition PEBLMath.cpp:124
Variant Cos(Variant v)
Definition PEBLMath.cpp:473
Variant Recurse(Variant v, Variant(*)(Variant))
Definition PEBLMath.cpp:55
Variant SeedRNG(Variant v)
Definition PEBLMath.cpp:977
Variant RandomDiscrete(Variant v)
Variant Div(Variant v)
Definition PEBLMath.cpp:756
Variant RadToDeg(Variant v)
Definition PEBLMath.cpp:600
Variant ToInt(Variant v)
Definition PEBLMath.cpp:764
Variant AbsFloor(Variant v)
Definition PEBLMath.cpp:708
Variant ACos(Variant v)
Definition PEBLMath.cpp:546
Variant Pow(Variant v)
Definition PEBLMath.cpp:319
Variant Ln(Variant v)
Definition PEBLMath.cpp:231
Variant Round(Variant v)
Definition PEBLMath.cpp:626
Variant Tan(Variant v)
Definition PEBLMath.cpp:421
Variant ATan(Variant v)
Definition PEBLMath.cpp:498
Variant RandomizeTimer(Variant v)
Definition PEBLMath.cpp:967
Variant RandomLogistic(Variant v)
Variant RandomUniform(Variant v)
Variant Random(Variant v)
Definition PEBLMath.cpp:995
Variant Exp(Variant v)
Definition PEBLMath.cpp:294
Variant RandomExponential(Variant v)
Variant Mod(Variant v)
Definition PEBLMath.cpp:733
Variant Abs(Variant v)
Definition PEBLMath.cpp:852
Variant ToNumber(Variant v)
Definition PEBLMath.cpp:786
Variant Log10(Variant v)
Definition PEBLMath.cpp:179
Variant DegToRad(Variant v)
Definition PEBLMath.cpp:573
Variant Ceiling(Variant v)
Definition PEBLMath.cpp:686
Variant RandomBernoulli(Variant v)
Variant RandomNormal(Variant v)
Variant RandomLogNormal(Variant v)
Variant Log2(Variant v)
Definition PEBLMath.cpp:208
Variant Floor(Variant v)
Definition PEBLMath.cpp:662
pDouble Log2(pDouble val)
pDouble RandomUniform()
pDouble RandomNormal()
pInt Round(pDouble val)
pInt Truncate(pDouble val)
void SignalWarning(const std::string &message)
Definition PError.cpp:119
void AssertType(Variant v, int type, const std::string &outsidemessage)
void SignalFatalError(const std::string &message)
int count
Definition test.cpp:12