1 /* 2 3 HyPhy - Hypothesis Testing Using Phylogenies. 4 5 Copyright (C) 1997-now 6 Core Developers: 7 Sergei L Kosakovsky Pond (spond@ucsd.edu) 8 Art FY Poon (apoon42@uwo.ca) 9 Steven Weaver (sweaver@ucsd.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 #ifndef __FORMULAS__ 41 #define __FORMULAS__ 42 43 #include "baseobj.h" 44 #include "classes.h" 45 #include "defines.h" 46 #include "avllistxl.h" 47 #include "stack.h" 48 #include "operation.h" 49 50 51 #include "hy_string_buffer.h" 52 #include "formula_parsing_context.h" 53 54 class _Variable; 55 class _VariableContainer; 56 class _Polynomial; 57 58 59 union _SimpleFormulaDatum { 60 hyFloat value; 61 hyPointer reference; 62 }; 63 64 65 enum _hyFormulaStringConversionMode { 66 kFormulaStringConversionNormal = 0L, 67 kFormulaStringConversionSubstiteValues = 2L, 68 kFormulaStringConversionReportRanges = 3L 69 }; 70 71 class _Formula { 72 73 friend class _Variable; 74 friend class _VariableContainer; 75 76 protected: 77 78 unsigned long call_count; 79 HBLObjectRef recursion_calls; 80 _List* resultCache; 81 _Stack theStack; 82 _List theFormula; 83 long* simpleExpressionStatus; 84 /** 85 SLKP: 20200924 86 Added this shorthand to improve memory locality and speed-up SimpleCompute performance 87 one entry per formula operator with the following values 88 -1 : constant value 89 >=0 : reference to variable value 90 - 2: matrix storage 91 - 3 : matrix access 92 - 4 : no shortcut 93 < -10000: 94 - HY_OP_CODE : (-10000-HY_OP_CODE for binary operatons) 95 < -100000: 96 - HY_OP_CODE (-100000-HY_OP_CODE for unary operatons) 97 */ 98 99 node<long>* theTree; // this formula converted to a tree for operation purposes 100 // such as simplification, differentiation and printing. 101 // trees store numbers referencing operations inside 102 // "theFormula" 103 104 105 public: 106 _Formula (void); 107 _Formula (_String const&,_VariableContainer const* theParent=nil,_String* errorString = nil); 108 _Formula (const _Polynomial *); 109 110 long ParseFormula (_String const&,_VariableContainer const* theParent=nil,_String* errorString = nil); 111 112 _Formula (HBLObjectRef, bool isAVar = false); 113 _Formula (_Formula const & rhs); 114 const _Formula & operator = (_Formula const & rhs); 115 virtual ~_Formula (void); 116 HBLObjectRef Compute (long = 0, _VariableContainer const* = nil, _List* additionalCacheArguments = nil, _String *errMsg = nil, long object_type = HY_ANY_OBJECT, bool can_cache = true); 117 // compute the value of the formula 118 // 1st argument : execute from this instruction onwards 119 // see the commend for ExecuteFormula for the second argument 120 121 bool IsEmpty (void) const; // is there anything in the formula 122 long NumberOperations (void) const; // how many ops in the formula? 123 124 friend long Parse (_Formula*, _String&, _FormulaParsingContext&, _Formula*); 125 // the main expression parser 126 127 friend long ExecuteFormula (_Formula*, _Formula*, long, long, _VariableContainer*, char); 128 // the execution block for "compiled formulae 129 /* 130 SLKP 20100119: added an execution name space to allow correct scoping of "pass-by-reference" 131 arguments when calling ExecuteAFile within a namespace. 132 133 e.g. in 134 135 function foo (var&) 136 { 137 ... 138 } 139 140 foo ("varID"); 141 142 varID may need to be prefixed by a namespace ID. 143 */ 144 145 146 _MathObject*ConstructPolynomial (void); 147 148 virtual void Initialize (void); 149 virtual void Duplicate (_Formula const *); 150 void DuplicateReference (const _Formula*); 151 virtual BaseRef makeDynamic (void) const; 152 virtual BaseRef toStr (_hyFormulaStringConversionMode mode, _List* matchNames = nil, bool = false); 153 _StringBuffer const toRPN (_hyFormulaStringConversionMode mode, _List* matchNames = nil); 154 155 virtual long ObjectClass (void); 156 157 158 virtual void ScanFForVariables (_AVLList&l, bool includeGlobals = false, bool includeAll = false, bool includeCateg = true, bool skipMatrixAssignments = false, _AVLListX* tagger = nil, long weight = 0) const; 159 virtual void ScanFForType (_SimpleList&, int); 160 /* SLKP 20100716: 161 A simple utility function to retrieve all variables of a given type 162 */ 163 164 virtual bool CheckFForDependence (long, bool checkAll = false); 165 virtual bool CheckFForDependence (_AVLList const & indices, bool checkAll = false); 166 GetList(void)167 _List& GetList (void) { 168 return theFormula; 169 } 170 171 bool HasChanged (bool = false); // does the formula need recomputing 172 bool HasChangedSimple (_SimpleList&); 173 bool EqualFormula (_Formula*); 174 bool IsAConstant (void); // does this formula include variables, or is it just a constant? 175 bool IsConstant (bool strict = false); // does this formula depend on something other that constants and fixed parameters? 176 bool DependsOnVariable (long); 177 bool IsArrayAccess (void); // check to see if this formula performs a matrix access 178 /* 179 SLKP 20090315: added a missing utility function 180 given a variable index as an argument, returns true if 181 the formula depends on a it; false otherwise 182 */ 183 _Operation* GetIthTerm (long) const; 184 /* 185 SLKP 20090315: added a missing utility function 186 given an index (i) as the argument, the function retrieves 187 the i-th term of the formula 188 */ 189 190 _Operation* ItemAt (long) const; 191 /* 192 Same as GetIthTerm, but no range checking 193 */ 194 Length(void)195 unsigned long Length (void) const {return theFormula.lLength;} 196 197 void Clear (void); 198 HBLObjectRef GetTheMatrix (void); 199 200 void PushTerm (BaseRef); 201 202 /* 20151008: if the argument is a _List, then treat as a list of _Operations and push them onto this formula (increment reference counters as well) 203 otherwise assume it's a MathObject and push it to this forumla (+1 reference counter) 204 dynamic_cast is used to determine what type of object this is 205 206 */ 207 208 bool AmISimple (long& stack_depth, _AVLList& variable_index); 209 long StackDepth (long start_at = 0L, long end_at = -1L) const; 210 /** 211 starting at operation 'start_at', counting up to 'end_at' (-1 == the end), 212 evaluate how many values would be on the stack after the execution of these commands 213 */ 214 bool ConvertToSimple (_AVLList& variableIndex); 215 void ConvertFromSimple (_AVLList const& variableIndex); 216 void ConvertFromSimpleList (_SimpleList const& variableIndex); 217 void SimplifyConstants (void); 218 _Variable * Dereference (bool, _hyExecutionContext* = _hyDefaultExecutionContext); 219 220 hyFloat ComputeSimple (_SimpleFormulaDatum* stack, _SimpleFormulaDatum* varValues) ; 221 222 hyFloat Newton (_Formula&, _Variable*, hyFloat, hyFloat, hyFloat); 223 hyFloat Newton (_Formula&, hyFloat, hyFloat, hyFloat, _Variable*); 224 hyFloat Newton (_Variable*, hyFloat, hyFloat, hyFloat, hyFloat); 225 hyFloat Newton (_Variable*,hyFloat, hyFloat, hyFloat); 226 227 hyFloat Brent (_Variable*, hyFloat, hyFloat, hyFloat = 1.e-7, _List* = nil, hyFloat = 0.); 228 229 hyFloat Integral (_Variable*,hyFloat, hyFloat, bool inifinite = false); 230 hyFloat MeanIntegral (_Variable*,hyFloat, hyFloat, bool inifinite = false); 231 _Formula* Differentiate (_String const&, bool = true, bool convert_from_tree = true); 232 node<long>* InternalDifferentiate 233 (node<long>*, long,_SimpleList const &, _Formula * const *, _Formula&); 234 235 bool InternalSimplify (node<long>*); 236 237 void LocalizeFormula (_Formula&, _String& parentName, _SimpleList& iv, _SimpleList& iiv, _SimpleList& dv, _SimpleList& idv); 238 void ConvertMatrixArgumentsToSimpleOrComplexForm (bool); 239 long ExtractMatrixExpArguments (_List*); 240 241 virtual _Formula const operator + (const _Formula&); 242 virtual _Formula const operator - (const _Formula&); 243 virtual _Formula const operator * (const _Formula&); 244 virtual _Formula const operator / (const _Formula&); 245 virtual _Formula const operator ^ (const _Formula&); 246 247 static _Formula* PatchFormulasTogether (const _Formula& op1, const _Formula& op2, const char op_code); 248 static _Formula* PatchFormulasTogether (const _Formula& op1, HBLObjectRef op2, const char op_code); 249 250 void ScanFormulaForHBLFunctions (_AVLListX& collection , bool recursive, bool simplify = true); 251 252 253 /** A compute and forget utility function. 254 Parse an expression, optionally check to see that it's of the right type and return the value 255 256 @param expression : the string to parse 257 @param use_exceptions : if true, throw const _String exceptions, otherwise handle errors directly 258 @param requested_type: return nil if the computed value is not of this type 259 @param formula parsing contrext 260 261 @return expression value or nil; the value needs to be managed by the caller 262 Revision history 263 20170921 : SLKP initial implementation 264 265 */ 266 267 static HBLObjectRef ParseAndCompute (_String const& expression, bool use_exceptions = false, long requested_type = HY_ANY_OBJECT, _hyExecutionContext * context = nil); 268 269 270 protected: 271 272 void SubtreeToString (_StringBuffer & result, node<long>* top_node, int op_level, _List* match_names, _Operation* this_node_op, _hyFormulaStringConversionMode mode = kFormulaStringConversionNormal); 273 void ConvertToTree (bool err_msg = true); 274 void ConvertFromTree (void); 275 bool CheckSimpleTerm (HBLObjectRef); 276 node<long>* DuplicateFormula (node<long>*,_Formula&) const; 277 278 279 }; 280 281 extern _Formula * current_formula_being_computed; 282 283 #endif 284