1 /*
2 
3  HyPhy - Hypothesis Testing Using Phylogenies.
4 
5  Copyright (C) 1997-now
6  Core Developers:
7  Sergei L Kosakovsky Pond (sergeilkp@icloud.com)
8  Art FY Poon    (apoon42@uwo.ca)
9  Steven Weaver (sweaver@temple.edu)
10 
11  Module Developers:
12  Lance Hepler (nlhepler@gmail.com)
13  Martin Smith (martin.audacis@gmail.com)
14 
15  Significant contributions from:
16  Spencer V Muse (muse@stat.ncsu.edu)
17  Simon DW Frost (sdf22@cam.ac.uk)
18 
19  Permission is hereby granted, free of charge, to any person obtaining a
20  copy of this software and associated documentation files (the
21  "Software"), to deal in the Software without restriction, including
22  without limitation the rights to use, copy, modify, merge, publish,
23  distribute, sublicense, and/or sell copies of the Software, and to
24  permit persons to whom the Software is furnished to do so, subject to
25  the following conditions:
26 
27  The above copyright notice and this permission notice shall be included
28  in all copies or substantial portions of the Software.
29 
30  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
31  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
32  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
33  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
34  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
35  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
36  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 
38  */
39 
40 #include "parser.h"
41 #include "mathobj.h"
42 #include "global_things.h"
43 
44 using namespace hy_global;
45 
46 
47 _MathObject  default_null_argument;
48 
_null_handler()49 _MathObject* _MathObject:: _null_handler() {
50     HandleApplicationError (kErrorStringNullOperand);
51     this->AddAReference();
52     return this;
53 }
54 
Add(_MathObject *,_MathObject *)55 _MathObject* _MathObject:: Add        (_MathObject*, _MathObject*)     {
56     return _null_handler();
57 }
Sub(_MathObject *,_MathObject *)58 _MathObject* _MathObject:: Sub        (_MathObject*, _MathObject*)     {
59     return _null_handler();
60 }
Minus(_MathObject *)61 _MathObject* _MathObject:: Minus      (_MathObject*)             {
62     return _null_handler();
63 }
Sum(_MathObject *)64 _MathObject* _MathObject:: Sum        (_MathObject*)             {
65     return _null_handler();
66 }
Mult(_MathObject *,_MathObject *)67 _MathObject* _MathObject:: Mult       (_MathObject*,_MathObject*)     {
68     return _null_handler();
69 }
Div(_MathObject *,_MathObject *)70 _MathObject* _MathObject:: Div        (_MathObject*,_MathObject*)     {
71     return _null_handler();
72 }
lDiv(_MathObject *,_MathObject *)73 _MathObject* _MathObject:: lDiv       (_MathObject*,_MathObject*)     {
74     return _null_handler();
75 }
longDiv(_MathObject *,_MathObject *)76 _MathObject* _MathObject:: longDiv    (_MathObject*,_MathObject*)     {
77     return _null_handler();
78 }
Raise(_MathObject *,_MathObject *)79 _MathObject* _MathObject:: Raise      (_MathObject*,_MathObject*)     {
80     return _null_handler();
81 }
82 
Equal(_MathObject * rhs)83 bool _MathObject::         Equal      (_MathObject* rhs)     {
84     if (rhs->ObjectClass() == HY_UNDEFINED) {
85         return true;
86     }
87     return false;
88     // null is equal to null, otherwise false\
89     return false;
90 }
Abs(_MathObject *)91 _MathObject* _MathObject:: Abs        (_MathObject*)             {
92     return _null_handler();
93 }
Sin(_MathObject *)94 _MathObject* _MathObject:: Sin        (_MathObject*)             {
95     return _null_handler();
96 }
Cos(_MathObject *)97 _MathObject* _MathObject:: Cos        (_MathObject*)             {
98     return _null_handler();
99 }
Tan(_MathObject *)100 _MathObject* _MathObject:: Tan        (_MathObject*)             {
101     return _null_handler();
102 }
Exp(_MathObject *)103 _MathObject* _MathObject:: Exp        (_MathObject*)             {
104     return _null_handler();
105 }
Log(_MathObject *)106 _MathObject* _MathObject:: Log        (_MathObject*)             {
107     return _null_handler();
108 }
Sqrt(_MathObject *)109 _MathObject* _MathObject:: Sqrt       (_MathObject*)             {
110     return _null_handler();
111 }
Gamma(_MathObject *)112 _MathObject* _MathObject:: Gamma      (_MathObject*)             {
113     return _null_handler();
114 }
Erf(_MathObject *)115 _MathObject* _MathObject:: Erf        (_MathObject*)             {
116     return _null_handler();
117 }
LnGamma(_MathObject *)118 _MathObject* _MathObject:: LnGamma    (_MathObject*)             {
119     return _null_handler();
120 }
121 
Beta(_MathObject *,_MathObject *)122 _MathObject* _MathObject:: Beta       (_MathObject*,_MathObject*)     {
123     return _null_handler();
124 }
IGamma(_MathObject *,_MathObject *)125 _MathObject* _MathObject:: IGamma     (_MathObject*,_MathObject*)     {
126     return _null_handler();
127 }
CChi2(_MathObject *,_MathObject *)128 _MathObject* _MathObject:: CChi2      (_MathObject*,_MathObject*)     {
129     return _null_handler();
130 }
IBeta(_MathObject *,_MathObject *,_MathObject *)131 _MathObject* _MathObject:: IBeta      (_MathObject*,_MathObject*,_MathObject*) {
132     return _null_handler();
133 }
Simplex(_MathObject *)134 _MathObject* _MathObject:: Simplex    (_MathObject*)             {
135     return _null_handler();
136 }
137 
Simplify(_MathObject *)138 _MathObject* _MathObject:: Simplify    (_MathObject*)             {
139     return _null_handler();
140 }
141 
Min(_MathObject *,_MathObject *)142 _MathObject* _MathObject:: Min        (_MathObject*,_MathObject*)     {
143     return _null_handler();
144 }
Max(_MathObject *,_MathObject *)145 _MathObject* _MathObject:: Max        (_MathObject*,_MathObject*)     {
146     return _null_handler();
147 }
InvChi2(_MathObject *,_MathObject *)148 _MathObject* _MathObject:: InvChi2    (_MathObject*,_MathObject*)     {
149     return _null_handler();
150 }
ZCDF(_MathObject *)151 _MathObject* _MathObject:: ZCDF       (_MathObject*)             {
152     return _null_handler();
153 }
Time(_MathObject *)154 _MathObject* _MathObject:: Time       (_MathObject*)             {
155     return _null_handler();
156 }
Arctan(_MathObject *)157 _MathObject* _MathObject:: Arctan     (_MathObject*)             {
158     return _null_handler();
159 }
Less(_MathObject *,_MathObject *)160 _MathObject* _MathObject:: Less       (_MathObject*,_MathObject*)     {
161     return _null_handler();
162 }
Random(_MathObject *,_MathObject *)163 _MathObject* _MathObject:: Random     (_MathObject*,_MathObject*)     {
164     return _null_handler();
165 }
Greater(_MathObject *,_MathObject *)166 _MathObject* _MathObject:: Greater    (_MathObject*,_MathObject*)     {
167     return _null_handler();
168 }
LessEq(_MathObject *,_MathObject *)169 _MathObject* _MathObject:: LessEq     (_MathObject*,_MathObject*)     {
170     return _null_handler();
171 }
GreaterEq(_MathObject *,_MathObject *)172 _MathObject* _MathObject:: GreaterEq  (_MathObject*,_MathObject*)     {
173     return _null_handler();
174 }
AreEqual(_MathObject *,_MathObject *)175 _MathObject* _MathObject:: AreEqual   (_MathObject*,_MathObject*)     {
176     return _null_handler();
177 }
NotEqual(_MathObject *,_MathObject *)178 _MathObject* _MathObject:: NotEqual   (_MathObject*,_MathObject*)     {
179     return _null_handler();
180 }
LAnd(_MathObject *,_MathObject *)181 _MathObject* _MathObject:: LAnd       (_MathObject*,_MathObject*)     {
182     return _null_handler();
183 }
LOr(_MathObject *,_MathObject *)184 _MathObject* _MathObject:: LOr        (_MathObject*,_MathObject*)     {
185     return _null_handler();
186 }
GammaDist(_MathObject *,_MathObject *,_MathObject *)187 _MathObject* _MathObject:: GammaDist  (_MathObject*,_MathObject*,_MathObject*) {
188     return _null_handler();
189 }
CGammaDist(_MathObject *,_MathObject *,_MathObject *)190 _MathObject* _MathObject:: CGammaDist (_MathObject*,_MathObject*,_MathObject*) {
191     return _null_handler();
192 }
LNot(_MathObject *)193 _MathObject* _MathObject:: LNot       (_MathObject*)             {
194     return _null_handler();
195 }
TipCount(_MathObject *)196 _MathObject* _MathObject:: TipCount   (_MathObject*)             {
197     return _null_handler();
198 }
BranchCount(_MathObject *)199 _MathObject* _MathObject:: BranchCount (_MathObject*)            {
200     return _null_handler();
201 }
TipName(_MathObject *,_MathObject *)202 _MathObject* _MathObject:: TipName     (_MathObject*,_MathObject*)    {
203     return _null_handler();
204 }
BranchName(_MathObject *,_MathObject *)205 _MathObject* _MathObject:: BranchName  (_MathObject*,_MathObject*)    {
206     return _null_handler();
207 }
BranchLength(_MathObject *,_MathObject *)208 _MathObject* _MathObject:: BranchLength(_MathObject*,_MathObject*)    {
209     return _null_handler();
210 }
RerootTree(_MathObject *,_MathObject *)211 _MathObject* _MathObject:: RerootTree  (_MathObject*,_MathObject*)    {
212     return _null_handler();
213 }
TEXTreeString(_MathObject *,_MathObject *) const214 _MathObject* _MathObject:: TEXTreeString(_MathObject*,_MathObject*) const {
215     HandleApplicationError (kErrorStringNullOperand);
216     return new _MathObject;
217 }
218 
PlainTreeString(_MathObject *,_MathObject *,_MathObject *)219 _MathObject* _MathObject:: PlainTreeString(_MathObject*,_MathObject*,_MathObject*) {
220     return _null_handler();
221 }
FormatNumberString(_MathObject *,_MathObject *,_MathObject *)222 _MathObject* _MathObject:: FormatNumberString (_MathObject*,_MathObject*,_MathObject*) {
223     return _null_handler();
224 }
Value(void)225 hyFloat _MathObject::   Value (void)              {
226     HandleApplicationError (kErrorStringNullOperand);
227     return 0.0;
228 }
229 
230 
_extract_argument(_List * arguments,unsigned long index,bool fill_in) const231 _MathObject* _MathObject:: _extract_argument (_List * arguments, unsigned long index, bool fill_in) const {
232   if (arguments && index < arguments->lLength) {
233     return (_MathObject*)arguments->GetItem(index);
234   }
235   return fill_in ? &default_null_argument : nil;
236 }
237 
238 
_returnConstantOrUseCache(hyFloat value,HBLObjectRef cache)239 HBLObjectRef _returnConstantOrUseCache (hyFloat value, HBLObjectRef cache) {
240     if (cache && cache->ObjectClass() == NUMBER) {
241         ((_Constant*)cache)->theValue = value;
242         return cache;
243     }
244     return new _Constant (value);
245 }
246 
247 //SW: This calls the function with the opcode after it's been parsed
ExecuteSingleOp(long opCode,_List * arguments,_hyExecutionContext * context,HBLObjectRef cache)248 HBLObjectRef _MathObject::ExecuteSingleOp (long opCode, _List* arguments, _hyExecutionContext* context, HBLObjectRef cache) {
249 
250     switch (opCode) { // first check operations without arguments
251       case HY_OP_CODE_NOT: // !
252         return LNot(cache);
253       case HY_OP_CODE_ABS: // Abs
254         return Abs(cache);
255       case HY_OP_CODE_ARCTAN: // Arctan
256         return Arctan(cache);
257       case HY_OP_CODE_COS: // Cos
258         return Cos(cache);
259       case HY_OP_CODE_COLUMNS: // Columns
260       case HY_OP_CODE_ROWS: // Rows
261         return _returnConstantOrUseCache (0., cache);
262       case HY_OP_CODE_ERF: // Erf
263         return Erf(cache);
264       case HY_OP_CODE_EVAL:
265         return (HBLObjectRef)Compute()->makeDynamic();
266       case HY_OP_CODE_EXP: // Exp
267         return Exp(cache);
268       case HY_OP_CODE_GAMMA: // Gamma
269         return Gamma(cache);
270       case HY_OP_CODE_LNGAMMA: // LnGamma
271         return LnGamma(cache);
272       case HY_OP_CODE_LOG: // Log
273         return Log(cache);
274       case HY_OP_CODE_MACCESS:
275         return new _MathObject; // indexing None returns None
276       case HY_OP_CODE_SIMPLEX: // Simplex
277         return Simplex(cache);
278       case HY_OP_CODE_SIN: // Sin
279         return Sin(cache);
280       case HY_OP_CODE_SQRT: // Sqrt
281         return Sqrt(cache);
282       case HY_OP_CODE_TAN: // Tan
283         return Tan(cache);
284       case HY_OP_CODE_TIME: // Time
285         return Time(cache);
286       case HY_OP_CODE_TYPE: // Type
287         return Type(cache);
288       case HY_OP_CODE_ZCDF: // ZCDF
289         return ZCDF(cache);
290     }
291 
292     _MathObject * arg0 = _extract_argument (arguments, 0UL, false);
293 
294     switch (opCode) { // next check operations without arguments or with one argument
295       case HY_OP_CODE_ADD: // +
296         if (arg0)
297           return Add(arg0,cache);
298         return Sum (cache);
299       case HY_OP_CODE_SUB: // -
300         if (arg0)
301           return Sub(arg0,cache);
302         return Minus(cache);
303         break;
304     }
305 
306     if (arg0) {
307       switch (opCode) { // operations that require exactly one argument
308           case HY_OP_CODE_NEQ: // !=
309             if (ObjectClass () == HY_UNDEFINED) {
310               if (arg0->ObjectClass () == HY_UNDEFINED)
311                 return _returnConstantOrUseCache (0., cache);
312                 //return new HY_CONSTANT_FALSE;
313               else
314                 return _returnConstantOrUseCache (1., cache);
315                 //return new HY_CONSTANT_TRUE;
316             }
317             if (arg0->ObjectClass() == NUMBER)
318               return NotEqual(arg0,cache);
319             return new HY_CONSTANT_TRUE;
320           case HY_OP_CODE_IDIV: // $
321             return longDiv(arg0,cache);
322           case HY_OP_CODE_MOD: // %
323             return lDiv(arg0,cache);
324           case HY_OP_CODE_AND: // &&
325             return LAnd(arg0,cache);
326           case HY_OP_CODE_MUL: // *
327             return Mult(arg0,cache);
328           case HY_OP_CODE_DIV: // /
329             return Div(arg0,cache);
330           case HY_OP_CODE_LESS: // <
331             return Less(arg0,cache);
332           case HY_OP_CODE_LEQ: // <=
333             return LessEq(arg0,cache);
334           case HY_OP_CODE_EQ: // ==
335           {
336             if (ObjectClass () == HY_UNDEFINED) {
337               if (arg0->ObjectClass () == HY_UNDEFINED)
338                 return _returnConstantOrUseCache (1., cache);
339                 //return new HY_CONSTANT_TRUE;
340               else
341                 return _returnConstantOrUseCache (0., cache);
342                 //return new HY_CONSTANT_FALSE;
343             }
344             if (arg0->ObjectClass() == NUMBER)
345               return AreEqual(arg0,cache);
346             return new HY_CONSTANT_FALSE;
347           }
348             break;
349           case HY_OP_CODE_GREATER: // >
350             return Greater(arg0,cache);
351           case HY_OP_CODE_GEQ: // >=
352             return GreaterEq(arg0,cache);
353           case HY_OP_CODE_BETA: // Beta
354             return Beta(arg0,cache);
355           case HY_OP_CODE_CCHI2: // CChi2
356             return CChi2(arg0,cache);
357           case HY_OP_CODE_IGAMMA: // IGamma
358             return IGamma(arg0,cache);
359           case HY_OP_CODE_INVCHI2: // InvChi2
360             return InvChi2(arg0,cache);
361           case HY_OP_CODE_MAX: // Max
362             return Max(arg0,cache);
363           case HY_OP_CODE_MIN: // Min
364             return Min(arg0,cache);
365           case HY_OP_CODE_RANDOM: // Random
366             return Random(arg0,cache);
367           case HY_OP_CODE_POWER: // ^
368             return Raise(arg0,cache);
369           case HY_OP_CODE_OR: // ||
370             return LOr(arg0,cache);
371       }
372 
373       _MathObject * arg1 = _extract_argument (arguments, 1UL, false);
374 
375       if (arg1) {
376         /** ops that require exactly TWO arguments */
377 
378         switch (opCode) {
379           case HY_OP_CODE_CGAMMADIST: // CGammaDist
380             return CGammaDist(arg0,arg1,cache);
381           case HY_OP_CODE_FORMAT: // Format
382             return FormatNumberString(arg0,arg1,cache);
383           case HY_OP_CODE_GAMMADIST: // GammaDist
384             return GammaDist(arg0,arg1,cache);
385           case HY_OP_CODE_IBETA: // IBeta
386             return IBeta(arg0,arg1,cache);
387         }
388       }
389 
390     }
391 
392     switch (opCode) {
393       case HY_OP_CODE_CGAMMADIST: // CGammaDist
394       case HY_OP_CODE_FORMAT: // Format
395       case HY_OP_CODE_GAMMADIST: // GammaDist
396       case HY_OP_CODE_IBETA: // IBeta
397       case HY_OP_CODE_NEQ: // !=
398       case HY_OP_CODE_IDIV: // $
399       case HY_OP_CODE_MOD: // %
400       case HY_OP_CODE_AND: // &&
401       case HY_OP_CODE_MUL: // *
402       case HY_OP_CODE_DIV: // /
403       case HY_OP_CODE_LESS: // <
404       case HY_OP_CODE_LEQ: // <=
405       case HY_OP_CODE_EQ: // ==
406       case HY_OP_CODE_GREATER: // >
407       case HY_OP_CODE_GEQ: // >=
408       case HY_OP_CODE_BETA: // Beta
409       case HY_OP_CODE_CCHI2: // CChi2
410       case HY_OP_CODE_IGAMMA: // IGamma
411       case HY_OP_CODE_INVCHI2: // InvChi2
412       case HY_OP_CODE_MAX: // Max
413       case HY_OP_CODE_MIN: // Min
414       case HY_OP_CODE_RANDOM: // Random
415       case HY_OP_CODE_POWER: // ^
416       case HY_OP_CODE_OR: // ||
417         WarnWrongNumberOfArguments (this, opCode,context, arguments);
418         break;
419       default:
420         WarnNotDefined (this, opCode,context);
421     }
422 
423     return new _MathObject;
424 }
425 
426 //__________________________________________________________________________________
427 
makeDynamic(void) const428 BaseRef _MathObject::makeDynamic (void) const {
429     return new _MathObject;
430 }
431 
432 //__________________________________________________________________________________
433 
Duplicate(BaseRefConst)434 void _MathObject::Duplicate (BaseRefConst) {
435 }
436 
437 
438 
439 //__________________________________________________________________________________
440 
441   //SW: Why do we need a string for the type?
Type(HBLObjectRef cache)442 HBLObjectRef _MathObject::Type (HBLObjectRef cache) {
443 
444   static const _FString kNumber       ("Number", false);
445   static const _FString kMatrix       ("Matrix", false);
446   static const _FString kContainer    ("Container", false);
447   static const _FString kTreeNode     ("TreeNode", false);
448   static const _FString kTree         ("Tree", false);
449   static const _FString kString       ("String", false);
450   static const _FString kAssociativeList
451                                       ("AssociativeList", false);
452   static const _FString kTopology     ("Topology", false);
453   static const _FString kPolynomial   ("Polynomial", false);
454   static const _FString kUnknown      ("Unknown", false);
455 
456   switch (ObjectClass()) {
457 
458     case NUMBER:
459       return new _FString (kNumber);
460     case MATRIX:
461       return new _FString (kMatrix);
462     case CONTAINER:
463       return new _FString (kContainer);
464     case TREE_NODE:
465       return new _FString (kTreeNode);
466     case TREE:
467       return new _FString (kTree);
468     case STRING:
469       return new _FString (kString);
470     case ASSOCIATIVE_LIST:
471       return new _FString (kAssociativeList);
472     case TOPOLOGY:
473       return new _FString (kTopology);
474     case POLYNOMIAL:
475       return new _FString (kPolynomial);
476 
477   }
478 
479   return new _FString (kUnknown);
480 }
481