Minsky
evalOp.cc
Go to the documentation of this file.
1 /*
2  @copyright Steve Keen 2013
3  @author Russell Standish
4  This file is part of Minsky.
5 
6  Minsky is free software: you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  Minsky is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with Minsky. If not, see <http://www.gnu.org/licenses/>.
18 */
19 #define OPNAMEDEF
20 #include "minsky.h"
21 #include "cairoItems.h"
22 #include "dataOp.h"
23 #include "evalOp.h"
24 #include "variable.h"
25 #include "userFunction.h"
26 #include "str.h"
27 
28 #include "minsky_epilogue.h"
29 
30 #include <math.h>
31 #undef Complex
32 #include <boost/math/special_functions/gamma.hpp>
33 #include <boost/math/special_functions/polygamma.hpp>
34 
35 using namespace boost::posix_time;
36 
37 namespace minsky
38 {
39 
40  void ScalarEvalOp::eval(double fv[], size_t n, const double sv[])
41  {
42  assert(out>=0);
43  switch (numArgs())
44  {
45  case 0:
46  assert(size_t(out)<n);
47  fv[out]=evaluate(0,0);
48  break;
49  case 1:
50  assert(out+in1.size()<=n);
51  for (unsigned i=0; i<in1.size(); ++i)
52  fv[out+i]=evaluate(flow1? fv[in1[i]]: sv[in1[i]], 0);
53  break;
54  case 2:
55  assert(out+in1.size()<=n);
56  for (unsigned i=0; i<in1.size(); ++i)
57  {
58  double x2=0;
59  const double* v=flow2? fv: sv;
60  for (auto& j: in2[i])
61  x2+=j.weight*v[j.idx];
62  fv[out+i]=evaluate(flow1? fv[in1[i]]: sv[in1[i]], x2);
63  }
64  break;
65  }
66 
67  // This check may well be obsolete. ecolab::Plot will now elide
68  // non-finite data, and it appears that the RK solver can
69  // integrate through infinities. Leaving the code here for now,
70  // just in case we decide to enable it via a user preference.
71 // // check for NaNs only on scalars. For tensors, NaNs just means
72 // // element not present
73 // if (in1.size()==1)
74 // for (unsigned i=0; i<in1.size(); ++i)
75 // if (!std::isfinite(fv[out+i]))
76 // {
77 // if (state)
78 // cminsky().displayErrorItem(*state);
79 // string msg="Invalid: ";
80 // if (auto uf=dynamic_cast<UserFunction*>(state.get()))
81 // msg+=uf->description()+"(";
82 // else
83 // msg+=OperationBase::typeName(type())+"(";
84 // if (numArgs()>0)
85 // msg+=std::to_string(flow1? fv[in1[i]]: sv[in1[i]]);
86 // if (numArgs()>1)
87 // msg+=","+std::to_string(flow2? fv[in2[i][0].idx]: sv[in2[i][0].idx]);
88 // msg+=")";
89 // throw runtime_error(msg.c_str());
90 // }
91  };
92 
93  void ScalarEvalOp::deriv(double df[], size_t n, const double ds[],
94  const double sv[], const double fv[])
95  {
96  assert(out>=0 && size_t(out)<n);
97  switch (numArgs())
98  {
99  case 0:
100  df[out]=0;
101  return;
102  case 1:
103  {
104  assert((flow1 && in1[0]<ValueVector::flowVars.size()) ||
105  (!flow1 && in1[0]<ValueVector::stockVars.size()));
106  const double x1=flow1? fv[in1[0]]: sv[in1[0]];
107  const double dx1=flow1? df[in1[0]]: ds[in1[0]];
108  df[out] = dx1!=0? dx1 * d1(x1,0): 0;
109  break;
110  }
111  case 2:
112  {
113  assert((flow1 && in1[0]<ValueVector::flowVars.size()) ||
114  (!flow1 && in1[0]<ValueVector::stockVars.size()));
115  assert((flow2 && in2[0][0].idx<ValueVector::flowVars.size()) ||
116  (!flow2 && in2[0][0].idx<ValueVector::stockVars.size()));
117  const double x1=flow1? fv[in1[0]]: sv[in1[0]];
118  const double x2=flow2? fv[in2[0][0].idx]: sv[in2[0][0].idx];
119  const double dx1=flow1? df[in1[0]]: ds[in1[0]];
120  const double dx2=flow2? df[in2[0][0].idx]: ds[in2[0][0].idx];
121  df[out] = (dx1!=0? dx1 * d1(x1,x2): 0) +
122  (dx2!=0? dx2 * d2(x1,x2): 0);
123  break;
124  }
125  }
126  if (!std::isfinite(df[out]))
127  throw error("Invalid operation detected on a %s operation",
128  OperationBase::typeName(type()).c_str());
129  }
130 
131  double ConstantEvalOp::evaluate(double in1, double in2) const
132  {return value;}
133  template <>
134  double EvalOp<OperationType::constant>::evaluate(double in1, double in2) const
135  {return 0;}
136  template <>
137  double EvalOp<OperationType::constant>::d1(double x1, double x2) const
138  {return 0;}
139  template <>
140  double EvalOp<OperationType::constant>::d2(double x1, double x2) const
141  {return 0;}
142 
143  double EvalOpBase::t;
144  string EvalOpBase::timeUnit;
145 
146  template <>
147  double EvalOp<OperationType::time>::evaluate(double in1, double in2) const
148  {return t;}
149  template <>
150  double EvalOp<OperationType::time>::d1(double x1, double x2) const
151  {return 0;}
152  template <>
153  double EvalOp<OperationType::time>::d2(double x1, double x2) const
154  {return 0;}
155 
156  template <>
157  double EvalOp<OperationType::euler>::evaluate(double in1, double in2) const
158  {return 2.71828182845904523536028747135266249775724709369995;}
159  template <>
160  double EvalOp<OperationType::euler>::d1(double x1, double x2) const
161  {return 0;}
162  template <>
163  double EvalOp<OperationType::euler>::d2(double x1, double x2) const
164  {return 0;}
165 
166  template <>
167  double EvalOp<OperationType::pi>::evaluate(double in1, double in2) const
168  {return 3.14159265358979323846264338327950288419716939937510;}
169  template <>
170  double EvalOp<OperationType::pi>::d1(double x1, double x2) const
171  {return 0;}
172  template <>
173  double EvalOp<OperationType::pi>::d2(double x1, double x2) const
174  {return 0;}
175 
176  template <>
177  double EvalOp<OperationType::zero>::evaluate(double in1, double in2) const
178  {return 0;}
179  template <>
180  double EvalOp<OperationType::zero>::d1(double x1, double x2) const
181  {return 0;}
182  template <>
183  double EvalOp<OperationType::zero>::d2(double x1, double x2) const
184  {return 0;}
185 
186  template <>
187  double EvalOp<OperationType::one>::evaluate(double in1, double in2) const
188  {return 1;}
189  template <>
190  double EvalOp<OperationType::one>::d1(double x1, double x2) const
191  {return 0;}
192  template <>
193  double EvalOp<OperationType::one>::d2(double x1, double x2) const
194  {return 0;}
195 
196  template <>
197  double EvalOp<OperationType::inf>::evaluate(double in1, double in2) const
198  {return numeric_limits<double>::max();}
199  template <>
200  double EvalOp<OperationType::inf>::d1(double x1, double x2) const
201  {return 0;}
202  template <>
203  double EvalOp<OperationType::inf>::d2(double x1, double x2) const
204  {return 0;}
205 
206  template <>
207  double EvalOp<OperationType::percent>::evaluate(double in1, double in2) const
208  {return 100.0*in1;}
209  template <>
210  double EvalOp<OperationType::percent>::d1(double x1, double x2) const
211  {return 100.0;}
212  template <>
213  double EvalOp<OperationType::percent>::d2(double x1, double x2) const
214  {return 0;}
215 
216  template <>
217  double EvalOp<OperationType::copy>::evaluate(double in1, double in2) const
218  {return in1;}
219  template <>
220  double EvalOp<OperationType::copy>::d1(double x1, double x2) const
221  {return 1;}
222  template <>
223  double EvalOp<OperationType::copy>::d2(double x1, double x2) const
224  {return 0;}
225 
226  template <> double
227  EvalOp<OperationType::integrate>::evaluate(double in1, double in2) const
228  {throw error("evaluate for integral operator should not be called");}
229  template <>
230  double EvalOp<OperationType::integrate>::d1(double x1, double x2) const
231  {return x1;}
232  template <>
233  double EvalOp<OperationType::integrate>::d2(double x1, double x2) const
234  {return 0;}
235 
236  template <> double
238  {throw error("evaluate for derivative operator should not be called");}
239  template <>
240  double EvalOp<OperationType::differentiate>::d1(double x1, double x2) const
241  {return x1;}
242  template <>
243  double EvalOp<OperationType::differentiate>::d2(double x1, double x2) const
244  {return 0;}
245 
246  template <> double
247  EvalOp<OperationType::data>::evaluate(double in1, double in2) const
248  {return state? dynamic_cast<DataOp&>(*state).interpolate(in1): 0;}
249  template <>
250  double EvalOp<OperationType::data>::d1(double x1, double x2) const
251  {return state? dynamic_cast<DataOp&>(*state).deriv(x1): 0;}
252  template <>
253  double EvalOp<OperationType::data>::d2(double x1, double x2) const
254  {return 0;}
255 
256  template <> double
257  EvalOp<OperationType::ravel>::evaluate(double in1, double in2) const
258  {return in1;}
259  template <>
260  double EvalOp<OperationType::ravel>::d1(double x1, double x2) const
261  {return 1;}
262  template <>
263  double EvalOp<OperationType::ravel>::d2(double x1, double x2) const
264  {return 0;}
265 
266  template <>
267  double EvalOp<OperationType::sqrt>::evaluate(double in1, double in2) const
268  {return ::sqrt(fabs(in1));}
269  template <>
270  double EvalOp<OperationType::sqrt>::d1(double x1, double x2) const
271  {return 0.5/::sqrt(fabs(x1));}
272  template <>
273  double EvalOp<OperationType::sqrt>::d2(double x1, double x2) const
274  {return 0;}
275 
276  template <>
277  double EvalOp<OperationType::exp>::evaluate(double in1, double in2) const
278  {return ::exp(in1);}
279  template <>
280  double EvalOp<OperationType::exp>::d1(double x1, double x2) const
281  {return ::exp(x1);}
282  template <>
283  double EvalOp<OperationType::exp>::d2(double x1, double x2) const
284  {return 0;}
285 
286  template <>
287  double EvalOp<OperationType::ln>::evaluate(double in1, double in2) const
288  {return ::log(in1);}
289  template <>
290  double EvalOp<OperationType::ln>::d1(double x1, double x2) const
291  {return 1/x1;}
292  template <>
293  double EvalOp<OperationType::ln>::d2(double x1, double x2) const
294  {return 0;}
295 
296  template <>
297  double EvalOp<OperationType::log>::evaluate(double in1, double in2) const
298  {return ::log(in1)/::log(in2);}
299  template <>
300  double EvalOp<OperationType::log>::d1(double x1, double x2) const
301  {return 1/(x1*::log(x2));}
302  template <>
303  double EvalOp<OperationType::log>::d2(double x1, double x2) const
304  {return -::log(x1)/(x2*sqr(::log(x2)));}
305 
306  template <>
307  double EvalOp<OperationType::pow>::evaluate(double in1, double in2) const
308  {return ::pow(in1,in2);}
309  template <>
310  double EvalOp<OperationType::pow>::d1(double x1, double x2) const
311  {return ::pow(x1,x2)*x2/x1;}
312  template <>
313  double EvalOp<OperationType::pow>::d2(double x1, double x2) const
314  {return ::pow(x1,x2)*::log(x1);}
315 
316  template <>
317  double EvalOp<OperationType::lt>::evaluate(double in1, double in2) const
318  {return in1<in2;}
319  template <>
320  double EvalOp<OperationType::lt>::d1(double x1, double x2) const
321  {throw error("lt cannot be used with an implicit method");}
322  template <>
323  double EvalOp<OperationType::lt>::d2(double x1, double x2) const
324  {return 0;}
325 
326  template <>
327  double EvalOp<OperationType::le>::evaluate(double in1, double in2) const
328  {return in1<=in2;}
329  template <>
330  double EvalOp<OperationType::le>::d1(double x1, double x2) const
331  {throw error("le cannot be used with an implicit method");}
332  template <>
333  double EvalOp<OperationType::le>::d2(double x1, double x2) const
334  {return 0;}
335 
336  template <>
337  double EvalOp<OperationType::eq>::evaluate(double in1, double in2) const
338  {return in1==in2;}
339  template <>
340  double EvalOp<OperationType::eq>::d1(double x1, double x2) const
341  {throw error("eq cannot be used with an implicit method");}
342  template <>
343  double EvalOp<OperationType::eq>::d2(double x1, double x2) const
344  {return 0;}
345 
346  template <>
347  double EvalOp<OperationType::userFunction>::evaluate(double in1, double in2) const
348  {return state? dynamic_cast<UserFunction&>(*state).evaluate(in1,in2): 0;}
349  template <>
350  double EvalOp<OperationType::userFunction>::d1(double x1, double x2) const
351  {throw error("user functions cannot be used with an implicit method");}
352  template <>
353  double EvalOp<OperationType::userFunction>::d2(double x1, double x2) const
354  {throw error("user functions cannot be used with an implicit method");}
355 
356  template <>
357  double EvalOp<OperationType::min>::evaluate(double in1, double in2) const
358  {
359  if (isnan(in1)) return in2; // see ravel #175
360  if (isnan(in2)) return in1;
361  return std::min(in1,in2);
362  }
363  template <>
364  double EvalOp<OperationType::min>::d1(double x1, double x2) const
365  {return x1<=x2;} // TODO: thow exception if x1==x2?
366  template <>
367  double EvalOp<OperationType::min>::d2(double x1, double x2) const
368  {return x1>x2;}
369 
370  template <>
371  double EvalOp<OperationType::max>::evaluate(double in1, double in2) const
372  {
373  if (isnan(in1)) return in2; // see ravel #175
374  if (isnan(in2)) return in1;
375  return std::max(in1,in2);
376  }
377  template <>
378  double EvalOp<OperationType::max>::d1(double x1, double x2) const
379  {return x1>x2;} // TODO: thow exception if x1==x2?
380  template <>
381  double EvalOp<OperationType::max>::d2(double x1, double x2) const
382  {return x1<=x2;}
383 
384  template <>
385  double EvalOp<OperationType::and_>::evaluate(double in1, double in2) const
386  {return in1>0.5 && in2>0.5;}
387  template <>
388  double EvalOp<OperationType::and_>::d1(double x1, double x2) const
389  {throw error("and cannot be used with an implicit method");}
390  template <>
391  double EvalOp<OperationType::and_>::d2(double x1, double x2) const
392  {return 0;}
393 
394  template <>
395  double EvalOp<OperationType::or_>::evaluate(double in1, double in2) const
396  {return in1>0.5 || in2>0.5;}
397  template <>
398  double EvalOp<OperationType::or_>::d1(double x1, double x2) const
399  {throw error("or cannot be used with an implicit method");}
400  template <>
401  double EvalOp<OperationType::or_>::d2(double x1, double x2) const
402  {return 0;}
403 
404  template <>
405  double EvalOp<OperationType::not_>::evaluate(double in1, double in2) const
406  {return in1<=0.5;}
407  template <>
408  double EvalOp<OperationType::not_>::d1(double x1, double x2) const
409  {throw error("not cannot be used with an implicit method");}
410  template <>
411  double EvalOp<OperationType::not_>::d2(double x1, double x2) const
412  {return 0;}
413 
414  template <>
415  double EvalOp<OperationType::sin>::evaluate(double in1, double in2) const
416  {return ::sin(in1);}
417  template <>
418  double EvalOp<OperationType::sin>::d1(double x1, double x2) const
419  {return ::cos(x1);}
420  template <>
421  double EvalOp<OperationType::sin>::d2(double x1, double x2) const
422  {return 0;}
423 
424  template <>
425  double EvalOp<OperationType::cos>::evaluate(double in1, double in2) const
426  {return ::cos(in1);}
427  template <>
428  double EvalOp<OperationType::cos>::d1(double x1, double x2) const
429  {return -::sin(x1);}
430  template <>
431  double EvalOp<OperationType::cos>::d2(double x1, double x2) const
432  {return 0;}
433 
434  template <>
435  double EvalOp<OperationType::tan>::evaluate(double in1, double in2) const
436  {return ::tan(in1);}
437  template <>
438  double EvalOp<OperationType::tan>::d1(double x1, double x2) const
439  {return 1/sqr(::cos(x1));}
440  template <>
441  double EvalOp<OperationType::tan>::d2(double x1, double x2) const
442  {return 0;}
443 
444  template <>
445  double EvalOp<OperationType::asin>::evaluate(double in1, double in2) const
446  {return ::asin(in1);}
447  template <>
448  double EvalOp<OperationType::asin>::d1(double x1, double x2) const
449  {return 1/::sqrt(1-sqr(x1));}
450  template <>
451  double EvalOp<OperationType::asin>::d2(double x1, double x2) const
452  {return 0;}
453 
454  template <>
455  double EvalOp<OperationType::acos>::evaluate(double in1, double in2) const
456  {return ::acos(in1);}
457  template <>
458  double EvalOp<OperationType::acos>::d1(double x1, double x2) const
459  {return -1/::sqrt(1-sqr(x1));}
460  template <>
461  double EvalOp<OperationType::acos>::d2(double x1, double x2) const
462  {return 0;}
463 
464  template <>
465  double EvalOp<OperationType::atan>::evaluate(double in1, double in2) const
466  {return ::atan(in1);}
467  template <>
468  double EvalOp<OperationType::atan>::d1(double x1, double x2) const
469  {return 1/(1+sqr(x1));}
470  template <>
471  double EvalOp<OperationType::atan>::d2(double x1, double x2) const
472  {return 0;}
473 
474  template <>
475  double EvalOp<OperationType::sinh>::evaluate(double in1, double in2) const
476  {return ::sinh(in1);}
477  template <>
478  double EvalOp<OperationType::sinh>::d1(double x1, double x2) const
479  {return ::cosh(x1);}
480  template <>
481  double EvalOp<OperationType::sinh>::d2(double x1, double x2) const
482  {return 0;}
483 
484  template <>
485  double EvalOp<OperationType::cosh>::evaluate(double in1, double in2) const
486  {return ::cosh(in1);}
487  template <>
488  double EvalOp<OperationType::cosh>::d1(double x1, double x2) const
489  {return ::sinh(x1);}
490  template <>
491  double EvalOp<OperationType::cosh>::d2(double x1, double x2) const
492  {return 0;}
493 
494  template <>
495  double EvalOp<OperationType::tanh>::evaluate(double in1, double in2) const
496  {return ::tanh(in1);}
497  template <>
498  double EvalOp<OperationType::tanh>::d1(double x1, double x2) const
499  {return 1/sqr(::cosh(x1));}
500  template <>
501  double EvalOp<OperationType::tanh>::d2(double x1, double x2) const
502  {return 0;}
503 
504  template <>
505  double EvalOp<OperationType::abs>::evaluate(double in1, double in2) const
506  {return ::fabs(in1);}
507  template <>
508  double EvalOp<OperationType::abs>::d1(double x1, double x2) const
509  {return (x1<0)? -1: 1;}
510  template <>
511  double EvalOp<OperationType::abs>::d2(double x1, double x2) const
512  {return 0;}
513 
514  template <>
515  double EvalOp<OperationType::floor>::evaluate(double in1, double in2) const
516  {return ::floor(in1);}
517  template <>
518  double EvalOp<OperationType::floor>::d1(double x1, double x2) const
519  {throw error("floor cannot be used with an implicit method");}
520  template <>
521  double EvalOp<OperationType::floor>::d2(double x1, double x2) const
522  {return 0;}
523 
524  template <>
525  double EvalOp<OperationType::frac>::evaluate(double in1, double in2) const
526  {return in1-::floor(in1);}
527  template <>
528  double EvalOp<OperationType::frac>::d1(double x1, double x2) const
529  {throw error("frac cannot be used with an implicit method");}
530  template <>
531  double EvalOp<OperationType::frac>::d2(double x1, double x2) const
532  {return 0;}
533 
534  template <>
535  double EvalOp<OperationType::Gamma>::evaluate(double in1, double in2) const
536  {return in1 > 0? boost::math::tgamma(in1) : numeric_limits<double>::max();}
537  template <>
538  double EvalOp<OperationType::Gamma>::d1(double x1, double x2) const
539  {return boost::math::digamma(fabs(x1))*boost::math::tgamma(fabs(x1));}
540  template <>
541  double EvalOp<OperationType::Gamma>::d2(double x1, double x2) const
542  {return 0;}
543 
544  template <>
545  double EvalOp<OperationType::polygamma>::evaluate(double in1, double in2) const
546  {return in1 > 0? boost::math::polygamma(::floor(in2),in1) : numeric_limits<double>::max();}
547  template <>
548  double EvalOp<OperationType::polygamma>::d1(double x1, double x2) const
549  {return boost::math::polygamma(::floor(x2)+1,fabs(x1));}
550  template <>
551  double EvalOp<OperationType::polygamma>::d2(double x1, double x2) const
552  {return 0;}
553 
554  template <>
555  double EvalOp<OperationType::fact>::evaluate(double in1, double in2) const
556  {return in1 > -1? boost::math::tgamma(in1+1) : 1;}
557  template <>
558  double EvalOp<OperationType::fact>::d1(double x1, double x2) const
559  {return x1 > -1? boost::math::polygamma(0,x1+1)*boost::math::tgamma(x1+1) : 0;}
560  template <>
561  double EvalOp<OperationType::fact>::d2(double x1, double x2) const
562  {return 0;}
563 
564  template <>
565  double EvalOp<OperationType::add>::evaluate(double in1, double in2) const
566  {return in1+in2;}
567  template <>
568  double EvalOp<OperationType::add>::d1(double x1, double x2) const
569  {return 1;}
570  template <>
571  double EvalOp<OperationType::add>::d2(double x1, double x2) const
572  {return 1;}
573 
574  template <>
575  double EvalOp<OperationType::subtract>::evaluate(double in1, double in2) const
576  {return in1-in2;}
577  template <>
578  double EvalOp<OperationType::subtract>::d1(double x1, double x2) const
579  {return 1;}
580  template <>
581  double EvalOp<OperationType::subtract>::d2(double x1, double x2) const
582  {return -1;}
583 
584  template <>
585  double EvalOp<OperationType::multiply>::evaluate(double in1, double in2) const
586  {return in1*in2;}
587  template <>
588  double EvalOp<OperationType::multiply>::d1(double x1, double x2) const
589  {return x2;}
590  template <>
591  double EvalOp<OperationType::multiply>::d2(double x1, double x2) const
592  {return x1;}
593 
594  template <>
595  double EvalOp<OperationType::divide>::evaluate(double in1, double in2) const
596  {return in1/in2;}
597  template <>
598  double EvalOp<OperationType::divide>::d1(double x1, double x2) const
599  {return 1/x2;}
600  template <>
601  double EvalOp<OperationType::divide>::d2(double x1, double x2) const
602  {return -x1/(x2*x2);}
603 
604 
605  template <>
606  double EvalOp<OperationType::numOps>::evaluate(double in1, double in2) const
607  {throw error("calling evaluate() on EvalOp<numOps> invalid");}
608  template <>
609  double EvalOp<OperationType::numOps>::d1(double x1, double x2) const
610  {throw error("calling d1 on EvalOp<numOps> invalid");}
611  template <>
612  double EvalOp<OperationType::numOps>::d2(double x1, double x2) const
613  {throw error("calling d2() on EvalOp<numOps> invalid");}
614 
615  namespace {OperationFactory<ScalarEvalOp, EvalOp, OperationType::sum-1> evalOpFactory;}
616 
617  ScalarEvalOp* ScalarEvalOp::create(Type op, const ItemPtr& state)
618  {
619  switch (classify(op))
620  {
621  case general:
622  case binop:
623  case constop:
624  case function:
625  switch (op)
626  {
627  case constant:
628  return new ConstantEvalOp;
629  case numOps:
630  return nullptr;
631  case userFunction:
632  if (auto f=dynamic_cast<UserFunction*>(state.get()))
633  f->compile();
634  [[fallthrough]];
635  default:
636  auto r=evalOpFactory.create(op);
637  r->state=dynamic_pointer_cast<OperationBase>(state);
638  return r;
639  }
640  case reduction:
641  case scan:
642  case tensor:
643  case statistics:
644  return nullptr; //TODO should we be here?
645  }
646  assert(false); //shouldn't be here
647  return nullptr;
648  }
649 
650  EvalOpPtr::EvalOpPtr(OperationType::Type op, const ItemPtr& state,
651  const std::shared_ptr<VariableValue>& to,
652  const VariableValue& from1, const VariableValue& from2)
653  {
654  assert(to);
655  auto t=ScalarEvalOp::create(op,state);
656  t->result=to;
657  reset(t);
658  assert(t->numArgs()==0 || (from1.idx()>=0 && (t->numArgs()==1 || from2.idx()>=0)));
659 
660  if (auto f=dynamic_cast<UserFunction*>(state.get()))
661  f->compile();
662 
663  if (t->numArgs()>0)
664  t->in1.push_back(from1.idx());
665  if (t->numArgs()>1)
666  t->in2.emplace_back(1,EvalOpBase::Support{1,unsigned(from2.idx())});
667 
668  if (to->idx()==-1) to->allocValue();
669  t->out=to->idx();
670  t->flow1=from1.isFlowVar();
671  t->flow2=from2.isFlowVar();
672 
673  }
674 
675 }
function f
Definition: canvas.m:1
Expr sin(const Expr &x)
Definition: expr.h:131
Expr cos(const Expr &x)
Definition: expr.h:137
Expr polygamma(const Expr &x, const Expr &y)
Definition: expr.h:166
represents the operation when evaluating the equations
Definition: evalOp.h:138
bool isFlowVar() const
returns true if variable&#39;s data is allocated on the flowVariables vector
Definition: variableValue.h:97
UnitsExpressionWalker pow(const UnitsExpressionWalker &x, const UnitsExpressionWalker &y)
reset
Definition: minsky.tcl:1325
Expr sqrt(const Expr &x)
Definition: expr.h:154
double interpolate(double) const
interpolates y data between x values bounding the argument
Definition: dataOp.cc:59
std::shared_ptr< Item > ItemPtr
Definition: item.h:57
Legacy EvalOp base interface.
Definition: evalOp.h:111
Creation and access to the minskyTCL_obj object, which has code to record whenever Minsky&#39;s state cha...
Definition: constMap.h:22
Expr exp(const Expr &x)
Definition: expr.h:126
Expr sinh(const Expr &x)
Definition: expr.h:142
Expr cosh(const Expr &x)
Definition: expr.h:148
factory class template, for creating objects of type T<O>. N is the maximum value of O ...
Definition: operationType.h:76
double evaluate(double x, double y)
T sqr(T x)
Definition: geometry.h:36
UnitsExpressionWalker timeUnit
legacy data importer object
Definition: dataOp.h:28
OperationFactory< ScalarEvalOp, EvalOp, OperationType::sum-1 > evalOpFactory
Definition: evalOp.cc:615
Expr log(const Expr &x)
Definition: expr.h:120
double deriv(double) const
derivative of the interpolate function. At the data points, the derivative is defined as the weighted...
Definition: dataOp.cc:80
float d2(float x0, float y0, float x1, float y1)
Definition: wire.cc:568