AERA
operator.cpp
1 //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
2 //_/_/
3 //_/_/ AERA
4 //_/_/ Autocatalytic Endogenous Reflective Architecture
5 //_/_/
6 //_/_/ Copyright (c) 2018-2025 Jeff Thompson
7 //_/_/ Copyright (c) 2018-2025 Kristinn R. Thorisson
8 //_/_/ Copyright (c) 2018-2025 Icelandic Institute for Intelligent Machines
9 //_/_/ Copyright (c) 2023 Leonard M. Eberding
10 //_/_/ http://www.iiim.is
11 //_/_/
12 //_/_/ Copyright (c) 2010-2012 Eric Nivel
13 //_/_/ Center for Analysis and Design of Intelligent Agents
14 //_/_/ Reykjavik University, Menntavegur 1, 102 Reykjavik, Iceland
15 //_/_/ http://cadia.ru.is
16 //_/_/
17 //_/_/ Part of this software was developed by Eric Nivel
18 //_/_/ in the HUMANOBS EU research project, which included
19 //_/_/ the following parties:
20 //_/_/
21 //_/_/ Autonomous Systems Laboratory
22 //_/_/ Technical University of Madrid, Spain
23 //_/_/ http://www.aslab.org/
24 //_/_/
25 //_/_/ Communicative Machines
26 //_/_/ Edinburgh, United Kingdom
27 //_/_/ http://www.cmlabs.com/
28 //_/_/
29 //_/_/ Istituto Dalle Molle di Studi sull'Intelligenza Artificiale
30 //_/_/ University of Lugano and SUPSI, Switzerland
31 //_/_/ http://www.idsia.ch/
32 //_/_/
33 //_/_/ Institute of Cognitive Sciences and Technologies
34 //_/_/ Consiglio Nazionale delle Ricerche, Italy
35 //_/_/ http://www.istc.cnr.it/
36 //_/_/
37 //_/_/ Dipartimento di Ingegneria Informatica
38 //_/_/ University of Palermo, Italy
39 //_/_/ http://diid.unipa.it/roboticslab/
40 //_/_/
41 //_/_/
42 //_/_/ --- HUMANOBS Open-Source BSD License, with CADIA Clause v 1.0 ---
43 //_/_/
44 //_/_/ Redistribution and use in source and binary forms, with or without
45 //_/_/ modification, is permitted provided that the following conditions
46 //_/_/ are met:
47 //_/_/ - Redistributions of source code must retain the above copyright
48 //_/_/ and collaboration notice, this list of conditions and the
49 //_/_/ following disclaimer.
50 //_/_/ - Redistributions in binary form must reproduce the above copyright
51 //_/_/ notice, this list of conditions and the following disclaimer
52 //_/_/ in the documentation and/or other materials provided with
53 //_/_/ the distribution.
54 //_/_/
55 //_/_/ - Neither the name of its copyright holders nor the names of its
56 //_/_/ contributors may be used to endorse or promote products
57 //_/_/ derived from this software without specific prior
58 //_/_/ written permission.
59 //_/_/
60 //_/_/ - CADIA Clause: The license granted in and to the software
61 //_/_/ under this agreement is a limited-use license.
62 //_/_/ The software may not be used in furtherance of:
63 //_/_/ (i) intentionally causing bodily injury or severe emotional
64 //_/_/ distress to any person;
65 //_/_/ (ii) invading the personal privacy or violating the human
66 //_/_/ rights of any person; or
67 //_/_/ (iii) committing or preparing for any act of war.
68 //_/_/
69 //_/_/ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
70 //_/_/ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
71 //_/_/ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
72 //_/_/ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
73 //_/_/ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
74 //_/_/ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
75 //_/_/ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
76 //_/_/ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
77 //_/_/ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
78 //_/_/ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
79 //_/_/ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
80 //_/_/ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
81 //_/_/ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
82 //_/_/ OF SUCH DAMAGE.
83 //_/_/
84 //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
85 
86 #include "operator.h"
87 #include "context.h"
88 #include "mem.h"
89 #include "init.h"
90 #include "opcodes.h"
91 #include "group.h"
92 #include "../submodules/CoreLibrary/CoreLibrary/utils.h"
93 #include "../r_code/utils.h"
94 #include <math.h>
95 #include "hlp_context.h"
96 
97 using namespace std;
98 using namespace std::chrono;
99 using namespace r_code;
100 
101 namespace r_exec {
102 
103 resized_vector<Operator> Operator::Operators_;
104 
105 void Operator::Register(uint16 opcode, bool(*o)(const Context &)) {
106 
107  if (Operators_[opcode].operator_)
108  Operators_[opcode].setOverload(o);
109  else
110  Operators_[opcode] = Operator(o);
111 }
112 
113 
114 std::vector<r_code::Atom> OpContext::build_and_evaluate_expression(_Fact* q0, _Fact* q1, Atom op) {
115  if (q0->get_reference(0)->code(MK_VAL_VALUE).isFloat() && q1->get_reference(0)->code(MK_VAL_VALUE).isFloat()) {
116 
117  float32 _q0 = q0->get_reference(0)->code(MK_VAL_VALUE).asFloat();
118  float32 _q1 = q1->get_reference(0)->code(MK_VAL_VALUE).asFloat();
119 
120  Atom result;
121  auto opcode = op.asOpcode();
122  if (opcode == Opcodes::Gtr) { result = Atom::Boolean(_q1 > _q0); }
123  else if (opcode == Opcodes::Lsr) { result = Atom::Boolean(_q1 < _q0); }
124  else if (opcode == Opcodes::Gte) { result = Atom::Boolean(_q1 >= _q0); }
125  else if (opcode == Opcodes::Lse) { result = Atom::Boolean(_q1 <= _q0); }
126  else if (opcode == Opcodes::Add) { result = Atom::Float(_q1 + _q0); }
127  else if (opcode == Opcodes::Sub) { result = Atom::Float(_q1 - _q0); }
128  else if (opcode == Opcodes::Mul) { result = Atom::Float(_q1 * _q0); }
129  else if (opcode == Opcodes::Div) {
130  if (_q0 == 0)
131  return std::vector<r_code::Atom>();
132  result = Atom::Float(_q1 / _q0);
133  }
134  if (!result.isUndefined()) {
135  std::vector<r_code::Atom> out;
136  out.push_back(result);
137  return out;
138  }
139  }
140  P<r_code::LocalObject> expression = build_expression_object(q0, q1, op);
141  return evaluate_expression(expression);
142 }
143 
144 P<r_code::LocalObject> OpContext::build_expression_object(_Fact* q0, _Fact* q1, Atom op) {
145 
146  uint16 target_source_index = 0;
147  uint16 consequent_source_index = 0;
148 
149  Atom target_val = q0->get_reference(0)->code(MK_VAL_VALUE);
150  Atom consequent_val = q1->get_reference(0)->code(MK_VAL_VALUE);
151 
152  // Build the expression (op q1 q0), copying the code structure at q1 and q0. For example (- q1 q0) in the case of subtraction.
153  P<LocalObject> expression = new LocalObject();
154  uint16 extent_index = 1;
155  expression->code(0) = op;
156  Atom* copy_ptr = &consequent_val;
157  if (consequent_val.getDescriptor() == Atom::I_PTR) {
158  consequent_source_index = consequent_val.asIndex();
159  copy_ptr = &q1->get_reference(0)->code(0);
160  extent_index += 2;
161  expression->code(1) = Atom::IPointer(extent_index);
162  }
163  StructureValue::copy_structure(expression, extent_index, copy_ptr, consequent_source_index);
164 
165  copy_ptr = &target_val;
166  if (target_val.getDescriptor() == Atom::I_PTR) {
167  target_source_index = target_val.asIndex();
168  copy_ptr = &q0->get_reference(0)->code(0);
169  expression->code(2) = Atom::IPointer(extent_index);
170  }
171  StructureValue::copy_structure(expression, extent_index, copy_ptr, target_source_index);
172 
173  return expression;
174 }
175 
176 std::vector<r_code::Atom> OpContext::evaluate_expression(r_code::LocalObject* expression) {
177  // Use HLPContext to evaluate the expression. The result goes in the OpContext's result array.
178  Overlay overlay((size_t)0);
179  HLPContext c(&expression->code(0), 0, (HLPOverlay*)&overlay);
180 
181  uint16 atom_count = c.get_children_count();
182  for (uint16 i = 1; i <= atom_count; ++i) {
183 
184  if (!c.get_child_deref(i).evaluate_no_dereference())
185  return std::vector<r_code::Atom>();
186  }
187 
188  Operator op = Operator::Get(c[0].asOpcode());
189  HLPContext* _c = new HLPContext(c);
190  OpContext op_context(_c);
191  op(op_context);
192  return op_context.result();
193 }
194 
195 
196 
198 
199 bool now(const Context &context) {
200 
201  context.setTimestampResult(Now());
202  return true;
203 }
204 
206 
207 bool rnd(const Context &context) {
208 
209  Context range = *context.get_child(1);
210 
211  if (!range[0].isFloat()) {
212 
213  context.setAtomicResult(Atom::Nil());
214  return false;
215  }
216 
217  /*Random r;float32 rng=range[0].asFloat();
218  float32 result=r(range[0].asFloat());
219  result/=ULONG_MAX;*/
220  float32 result = (((float32)(rand() % 100)) / 100)*range[0].asFloat();
221  context.setAtomicResult(Atom::Float(result));
222  return true;
223 }
224 
226 
227 bool equ(const Context &context) {
228 
229  Context lhs = *context.get_child(1);
230  Context rhs = *context.get_child(2);
231 
232  bool r = (lhs == rhs);
233  context.setAtomicResult(Atom::Boolean(r));
234  return true;
235 }
236 
238 
239 bool neq(const Context &context) {
240 
241  bool r = *context.get_child(1) != *context.get_child(2);
242  context.setAtomicResult(Atom::Boolean(r));
243  return true;
244 }
245 
247 
248 bool gtr(const Context &context) {
249 
250  Context lhs = *context.get_child(1);
251  Context rhs = *context.get_child(2);
252 
253  if (lhs[0].isFloat()) {
254 
255  if (rhs[0].isFloat()) {
256 
257  bool r = lhs[0].asFloat() > rhs[0].asFloat();
258  context.setAtomicResult(Atom::Boolean(r));
259  return true;
260  }
261  } else if (lhs[0].getDescriptor() == Atom::TIMESTAMP) {
262 
263  if (rhs[0].getDescriptor() == Atom::TIMESTAMP) {
264 
265  bool r = Utils::GetTimestamp(&lhs[0]) > Utils::GetTimestamp(&rhs[0]);
266  context.setAtomicResult(Atom::Boolean(r));
267  return true;
268  }
269  }
270  else if (lhs[0].getDescriptor() == Atom::DURATION) {
271  if (rhs[0].getDescriptor() == Atom::DURATION) {
272  bool r = Utils::GetDuration(&lhs[0]) > Utils::GetDuration(&rhs[0]);
273  context.setAtomicResult(Atom::Boolean(r));
274  return true;
275  }
276  }
277 
278  context.setAtomicResult(Atom::UndefinedBoolean());
279  return false;
280 }
281 
283 
284 bool lsr(const Context &context) {
285 
286  Context lhs = *context.get_child(1);
287  Context rhs = *context.get_child(2);
288 
289  if (lhs[0].isFloat()) {
290 
291  if (rhs[0].isFloat()) {
292 
293  bool r = lhs[0].asFloat() < rhs[0].asFloat();
294  context.setAtomicResult(Atom::Boolean(r));
295  return true;
296  }
297  } else if (lhs[0].getDescriptor() == Atom::TIMESTAMP) {
298 
299  if (rhs[0].getDescriptor() == Atom::TIMESTAMP) {
300 
301  bool r = Utils::GetTimestamp(&lhs[0]) < Utils::GetTimestamp(&rhs[0]);
302  context.setAtomicResult(Atom::Boolean(r));
303  return true;
304  }
305  }
306  else if (lhs[0].getDescriptor() == Atom::DURATION) {
307  if (rhs[0].getDescriptor() == Atom::DURATION) {
308  bool r = Utils::GetDuration(&lhs[0]) < Utils::GetDuration(&rhs[0]);
309  context.setAtomicResult(Atom::Boolean(r));
310  return true;
311  }
312  }
313 
314  context.setAtomicResult(Atom::UndefinedBoolean());
315  return false;
316 }
317 
319 
320 bool gte(const Context &context) {
321 
322  Context lhs = *context.get_child(1);
323  Context rhs = *context.get_child(2);
324 
325  if (lhs[0].isFloat()) {
326 
327  if (rhs[0].isFloat()) {
328 
329  bool r = lhs[0].asFloat() >= rhs[0].asFloat();
330  context.setAtomicResult(Atom::Boolean(r));
331  return true;
332  }
333  } else if (lhs[0].getDescriptor() == Atom::TIMESTAMP) {
334 
335  if (rhs[0].getDescriptor() == Atom::TIMESTAMP) {
336 
337  bool r = Utils::GetTimestamp(&lhs[0]) >= Utils::GetTimestamp(&rhs[0]);
338  context.setAtomicResult(Atom::Boolean(r));
339  return true;
340  }
341  }
342  else if (lhs[0].getDescriptor() == Atom::DURATION) {
343  if (rhs[0].getDescriptor() == Atom::DURATION) {
344  bool r = Utils::GetDuration(&lhs[0]) >= Utils::GetDuration(&rhs[0]);
345  context.setAtomicResult(Atom::Boolean(r));
346  return true;
347  }
348  }
349 
350  context.setAtomicResult(Atom::UndefinedBoolean());
351  return false;
352 }
353 
355 
356 bool lse(const Context &context) {
357 
358  Context lhs = *context.get_child(1);
359  Context rhs = *context.get_child(2);
360 
361  if (lhs[0].isFloat()) {
362 
363  if (rhs[0].isFloat()) {
364 
365  bool r = lhs[0].asFloat() <= rhs[0].asFloat();
366  context.setAtomicResult(Atom::Boolean(r));
367  return true;
368  }
369  } else if (lhs[0].getDescriptor() == Atom::TIMESTAMP) {
370 
371  if (rhs[0].getDescriptor() == Atom::TIMESTAMP) {
372 
373  bool r = Utils::GetTimestamp(&lhs[0]) <= Utils::GetTimestamp(&rhs[0]);
374  context.setAtomicResult(Atom::Boolean(r));
375  return true;
376  }
377  }
378  else if (lhs[0].getDescriptor() == Atom::DURATION) {
379  if (rhs[0].getDescriptor() == Atom::DURATION) {
380  bool r = Utils::GetDuration(&lhs[0]) <= Utils::GetDuration(&rhs[0]);
381  context.setAtomicResult(Atom::Boolean(r));
382  return true;
383  }
384  }
385 
386  context.setAtomicResult(Atom::UndefinedBoolean());
387  return false;
388 }
389 
391 
392 bool add(const Context &context) {
393 
394  Context lhs = *context.get_child(1);
395  Context rhs = *context.get_child(2);
396 
397  if (lhs[0].isFloat()) {
398 
399  if (rhs[0].isFloat()) {
400 
401  if (lhs[0] == Atom::PlusInfinity()) {
402 
403  context.setAtomicResult(Atom::PlusInfinity());
404  return true;
405  }
406 
407  if (rhs[0] == Atom::PlusInfinity()) {
408 
409  context.setAtomicResult(Atom::PlusInfinity());
410  return true;
411  }
412 
413  context.setAtomicResult(Atom::Float(lhs[0].asFloat() + rhs[0].asFloat()));
414  return true;
415  } else if (rhs[0].getDescriptor() == Atom::TIMESTAMP) {
416 
417  if (lhs[0] != Atom::PlusInfinity()) {
418 
419  context.setTimestampResult(Utils::GetTimestamp(&rhs[0]) + microseconds((int64)lhs[0].asFloat()));
420  return true;
421  }
422  }
423  else if (rhs[0].getDescriptor() == Atom::DURATION) {
424  if (lhs[0] != Atom::PlusInfinity()) {
425  context.setDurationResult(Utils::GetDuration(&rhs[0]) + microseconds((int64)lhs[0].asFloat()));
426  return true;
427  }
428  }
429  } else if (lhs[0].getDescriptor() == Atom::TIMESTAMP) {
430 
431  if (rhs[0].isFloat()) {
432 
433  if (rhs[0] != Atom::PlusInfinity()) {
434 
435  context.setTimestampResult(Utils::GetTimestamp(&lhs[0]) + microseconds((int64)rhs[0].asFloat()));
436  return true;
437  }
438  }
439  else if (rhs[0].getDescriptor() == Atom::DURATION) {
440  context.setTimestampResult(Utils::GetTimestamp(&lhs[0]) + Utils::GetDuration(&rhs[0]));
441  return true;
442  }
443  }
444  else if (lhs[0].getDescriptor() == Atom::DURATION) {
445  if (rhs[0].getDescriptor() == Atom::DURATION) {
446  context.setDurationResult(Utils::GetDuration(&lhs[0]) + Utils::GetDuration(&rhs[0]));
447  return true;
448  }
449  else if (rhs[0].getDescriptor() == Atom::TIMESTAMP) {
450  context.setTimestampResult(Utils::GetDuration(&lhs[0]) + Utils::GetTimestamp(&rhs[0]));
451  return true;
452  }
453  else if (rhs[0].isFloat()) {
454  if (rhs[0] != Atom::PlusInfinity()) {
455  context.setDurationResult(Utils::GetDuration(&lhs[0]) + microseconds((int64)rhs[0].asFloat()));
456  return true;
457  }
458  }
459  }
460 
461  context.setAtomicResult(Atom::Nil());
462  return false;
463 }
464 
466 
467 bool sub(const Context &context) {
468 
469  Context lhs = *context.get_child(1);
470  Context rhs = *context.get_child(2);
471 
472  if (lhs[0].isFloat()) {
473 
474  if (rhs[0].isFloat()) {
475 
476  if (lhs[0] == Atom::PlusInfinity()) {
477 
478  context.setAtomicResult(Atom::PlusInfinity());
479  return true;
480  }
481 
482  if (rhs[0] == Atom::PlusInfinity()) {
483 
484  context.setAtomicResult(Atom::Float(0));
485  return true;
486  }
487 
488  context.setAtomicResult(Atom::Float(lhs[0].asFloat() - rhs[0].asFloat()));
489  return true;
490  }
491  } else if (lhs[0].getDescriptor() == Atom::TIMESTAMP) {
492 
493  if (rhs[0].getDescriptor() == Atom::TIMESTAMP) {
494 
495  context.setDurationResult(duration_cast<microseconds>(Utils::GetTimestamp(&lhs[0]) - Utils::GetTimestamp(&rhs[0])));
496  return true;
497  } else if (rhs[0].isFloat()) {
498 
499  if (rhs[0] != Atom::PlusInfinity()) {
500 
501  context.setTimestampResult(Utils::GetTimestamp(&lhs[0]) - microseconds((int64)rhs[0].asFloat()));
502  return true;
503  }
504  }
505  else if (rhs[0].getDescriptor() == Atom::DURATION) {
506  context.setTimestampResult(Utils::GetTimestamp(&lhs[0]) - Utils::GetDuration(&rhs[0]));
507  return true;
508  }
509  }
510  else if (lhs[0].getDescriptor() == Atom::DURATION) {
511  if (rhs[0].getDescriptor() == Atom::DURATION) {
512  context.setDurationResult(Utils::GetDuration(&lhs[0]) - Utils::GetDuration(&rhs[0]));
513  return true;
514  }
515  else if (rhs[0].isFloat()) {
516  if (rhs[0] != Atom::PlusInfinity()) {
517  context.setDurationResult(Utils::GetDuration(&lhs[0]) - microseconds((int64)rhs[0].asFloat()));
518  return true;
519  }
520  }
521  }
522 
523  context.setAtomicResult(Atom::Nil());
524  return false;
525 }
526 
528 
529 bool mul(const Context &context) {
530 
531  Context lhs = *context.get_child(1);
532  Context rhs = *context.get_child(2);
533 
534  if (lhs[0].isFloat()) {
535 
536  if (rhs[0].isFloat()) {
537 
538  if (lhs[0] == Atom::PlusInfinity()) {
539 
540  if (rhs[0] == Atom::PlusInfinity()) {
541 
542  context.setAtomicResult(Atom::PlusInfinity());
543  return true;
544  }
545 
546  if (rhs[0].asFloat() > 0) {
547 
548  context.setAtomicResult(Atom::PlusInfinity());
549  return true;
550  }
551 
552  if (rhs[0].asFloat() <= 0) {
553 
554  context.setAtomicResult(Atom::Float(0));
555  return true;
556  }
557  }
558 
559  if (rhs[0] == Atom::PlusInfinity()) {
560 
561  if (lhs[0].asFloat() > 0) {
562 
563  context.setAtomicResult(Atom::PlusInfinity());
564  return true;
565  }
566 
567  if (lhs[0].asFloat() <= 0) {
568 
569  context.setAtomicResult(Atom::Float(0));
570  return true;
571  }
572  }
573 
574  context.setAtomicResult(Atom::Float(lhs[0].asFloat()*rhs[0].asFloat()));
575  return true;
576  }
577  else if (rhs[0].getDescriptor() == Atom::DURATION) {
578  if (lhs[0] != Atom::PlusInfinity()) {
579  context.setAtomicResult(Atom::Float(lhs[0].asFloat() * (float32)Utils::GetDuration(&rhs[0]).count()));
580  return true;
581  }
582  }
583  }
584  else if (lhs[0].getDescriptor() == Atom::DURATION) {
585  if (rhs[0].isFloat()) {
586  if (rhs[0] != Atom::PlusInfinity()) {
587  float64 lhs_float = (float64)Utils::GetDuration(&lhs[0]).count();
588  context.setDurationResult(microseconds((int64)(lhs_float * rhs[0].asFloat())));
589  return true;
590  }
591  }
592  else if (rhs[0].getDescriptor() == Atom::DURATION) {
593  // Counter-intuitive, but is the existing behavior.
594  context.setAtomicResult(Atom::Float((float32)Utils::GetDuration(&lhs[0]).count() * (float32)Utils::GetDuration(&rhs[0]).count()));
595  return true;
596  }
597  }
598 
599  context.setAtomicResult(Atom::Nil());
600  return false;
601 }
602 
604 
605 bool div(const Context &context) {
606 
607  Context lhs = *context.get_child(1);
608  Context rhs = *context.get_child(2);
609 
610  if (lhs[0].isFloat()) {
611 
612  if (rhs[0].isFloat()) {
613 
614  if (rhs[0].asFloat() != 0) {
615 
616  if (lhs[0] == Atom::PlusInfinity()) {
617 
618  if (rhs[0] == Atom::PlusInfinity()) {
619 
620  context.setAtomicResult(Atom::PlusInfinity());
621  return true;
622  }
623 
624  if (rhs[0].asFloat() > 0) {
625 
626  context.setAtomicResult(Atom::PlusInfinity());
627  return true;
628  }
629 
630  if (rhs[0].asFloat() <= 0) {
631 
632  context.setAtomicResult(Atom::Float(0));
633  return true;
634  }
635  }
636 
637  if (rhs[0] == Atom::PlusInfinity()) {
638 
639  if (lhs[0].asFloat() > 0) {
640 
641  context.setAtomicResult(Atom::PlusInfinity());
642  return true;
643  }
644 
645  if (lhs[0].asFloat() <= 0) {
646 
647  context.setAtomicResult(Atom::Float(0));
648  return true;
649  }
650  }
651 
652  context.setAtomicResult(Atom::Float(lhs[0].asFloat() / rhs[0].asFloat()));
653  return true;
654  }
655  }
656  else if (rhs[0].getDescriptor() == Atom::DURATION) {
657  if (lhs[0] != Atom::PlusInfinity()) {
658  context.setAtomicResult(Atom::Float(lhs[0].asFloat() / (float32)Utils::GetDuration(&rhs[0]).count()));
659  return true;
660  }
661  }
662  }
663  else if (lhs[0].getDescriptor() == Atom::DURATION) {
664  if (rhs[0].isFloat()) {
665  if (rhs[0] != Atom::PlusInfinity()) {
666  float64 lhs_float = (float64)Utils::GetDuration(&lhs[0]).count();
667  context.setDurationResult(microseconds((int64)(lhs_float / rhs[0].asFloat())));
668  return true;
669  }
670  }
671  else if (rhs[0].getDescriptor() == Atom::DURATION) {
672  // Counter-intuitive, but is the existing behavior.
673  context.setAtomicResult(Atom::Float((float32)Utils::GetDuration(&lhs[0]).count() / (float32)Utils::GetDuration(&rhs[0]).count()));
674  return true;
675  }
676  }
677 
678  context.setAtomicResult(Atom::Nil());
679  return false;
680 }
681 
683 
684 bool dis(const Context &context) {
685 
686  Context lhs = *context.get_child(1);
687  Context rhs = *context.get_child(2);
688 
689  if (lhs[0].isFloat()) {
690 
691  if (rhs[0].isFloat()) {
692 
693  context.setAtomicResult(Atom::Float(abs(lhs[0].asFloat() - rhs[0].asFloat())));
694  return true;
695  }
696  } else if (lhs[0].getDescriptor() == Atom::TIMESTAMP) {
697 
698  if (rhs[0].getDescriptor() == Atom::TIMESTAMP) {
699 
700  context.setDurationResult(abs(duration_cast<microseconds>(Utils::GetTimestamp(&lhs[0]) - Utils::GetTimestamp(&rhs[0]))));
701  return true;
702  }
703  }
704  else if (lhs[0].getDescriptor() == Atom::DURATION) {
705  if (rhs[0].getDescriptor() == Atom::DURATION) {
706  context.setDurationResult(abs(Utils::GetDuration(&lhs[0]) - Utils::GetDuration(&rhs[0])));
707  return true;
708  }
709  }
710 
711  context.setAtomicResult(Atom::Nil());
712  return false;
713 }
714 
716 
717 bool ln(const Context &context) {
718 
719  Context arg = *context.get_child(1);
720 
721  if (arg[0].isFloat()) {
722 
723  if (arg[0].asFloat() != 0) {
724 
725  context.setAtomicResult(Atom::Float(::log(arg[0].asFloat())));
726  return true;
727  }
728  }
729 
730  context.setAtomicResult(Atom::Nil());
731  return false;
732 }
733 
735 
736 bool exp(const Context &context) {
737 
738  Context arg = *context.get_child(1);
739 
740  if (arg[0].isFloat()) {
741 
742  context.setAtomicResult(Atom::Float(::exp(arg[0].asFloat())));
743  return true;
744  }
745 
746  context.setAtomicResult(Atom::Nil());
747  return false;
748 }
749 
751 
752 bool log(const Context &context) {
753 
754  Context arg = *context.get_child(1);
755 
756  if (arg[0].isFloat()) {
757 
758  if (arg[0].asFloat() != 0) {
759 
760  context.setAtomicResult(Atom::Float(log10(arg[0].asFloat())));
761  return true;
762  }
763  }
764 
765  context.setAtomicResult(Atom::Nil());
766  return false;
767 }
768 
770 
771 bool e10(const Context &context) {
772 
773  Context arg = *context.get_child(1);
774 
775  if (arg[0].isFloat()) {
776 
777  context.setAtomicResult(Atom::Float(pow(10, arg[0].asFloat())));
778  return true;
779  }
780 
781  context.setAtomicResult(Atom::Nil());
782  return false;
783 }
784 
786 
787 bool syn(const Context &context) {
788 
789  return true;
790 }
791 
793 
794 bool ins(const Context &context) {
795 
796  return IPGMContext::Ins(*(IPGMContext *)context.get_implementation());
797 }
798 
800 
801 bool red(const Context &context) {
802 
803  return IPGMContext::Red(*(IPGMContext *)context.get_implementation());
804 }
805 
807 
808 bool fvw(const Context &context) {
809 
810  return IPGMContext::Fvw(*(IPGMContext *)context.get_implementation());
811 }
812 
814 
815 bool is_sim(const Context &context) {
816 
817  const IPGMContext &ipgm_context = *(IPGMContext *)context.get_implementation();
818  IPGMContext arg = ipgm_context.get_child_deref(1);
819  Code* obj = arg.get_object();
820 
821  bool result = false;
822  if (obj->code(0).asOpcode() == Opcodes::Goal)
823  result = ((Goal*)obj)->is_simulation();
824  else if (obj->code(0).asOpcode() == Opcodes::Pred)
825  result = ((Pred*)obj)->is_simulation();
826 
827  context.setAtomicResult(Atom::Boolean(result));
828  return true;
829 }
830 
831 bool minimum(const Context &context) {
832  Context lhs = *context.get_child(1);
833  Context rhs = *context.get_child(2);
834 
835  if (lhs[0].isFloat() && rhs[0].isFloat()) {
836  if (lhs[0] == Atom::MinusInfinity() || rhs[0] == Atom::MinusInfinity()) {
837  context.setAtomicResult(Atom::MinusInfinity());
838  return true;
839  }
840 
841  if (lhs[0] == Atom::PlusInfinity()) {
842  context.setAtomicResult(Atom::Float(rhs[0].asFloat()));
843  return true;
844  }
845  if (rhs[0] == Atom::PlusInfinity()) {
846  context.setAtomicResult(Atom::Float(lhs[0].asFloat()));
847  return true;
848  }
849 
850  context.setAtomicResult(Atom::Float(min(lhs[0].asFloat(), rhs[0].asFloat())));
851  return true;
852  }
853  else if (lhs[0].getDescriptor() == Atom::TIMESTAMP && rhs[0].getDescriptor() == Atom::TIMESTAMP) {
854  context.setTimestampResult(min(Utils::GetTimestamp(&lhs[0]), Utils::GetTimestamp(&rhs[0])));
855  return true;
856  }
857  else if (lhs[0].getDescriptor() == Atom::DURATION && rhs[0].getDescriptor() == Atom::DURATION) {
858  context.setDurationResult(min(Utils::GetDuration(&lhs[0]), Utils::GetDuration(&rhs[0])));
859  return true;
860  }
861 
862  context.setAtomicResult(Atom::Nil());
863  return false;
864 }
865 
866 bool maximum(const Context &context) {
867  Context lhs = *context.get_child(1);
868  Context rhs = *context.get_child(2);
869 
870  if (lhs[0].isFloat() && rhs[0].isFloat()) {
871  if (lhs[0] == Atom::PlusInfinity() || rhs[0] == Atom::PlusInfinity()) {
872  context.setAtomicResult(Atom::PlusInfinity());
873  return true;
874  }
875 
876  if (lhs[0] == Atom::MinusInfinity()) {
877  context.setAtomicResult(Atom::Float(rhs[0].asFloat()));
878  return true;
879  }
880  if (rhs[0] == Atom::MinusInfinity()) {
881  context.setAtomicResult(Atom::Float(lhs[0].asFloat()));
882  return true;
883  }
884 
885  context.setAtomicResult(Atom::Float(max(lhs[0].asFloat(), rhs[0].asFloat())));
886  return true;
887  }
888  else if (lhs[0].getDescriptor() == Atom::TIMESTAMP && rhs[0].getDescriptor() == Atom::TIMESTAMP) {
889  context.setTimestampResult(max(Utils::GetTimestamp(&lhs[0]), Utils::GetTimestamp(&rhs[0])));
890  return true;
891  }
892  else if (lhs[0].getDescriptor() == Atom::DURATION && rhs[0].getDescriptor() == Atom::DURATION) {
893  context.setDurationResult(max(Utils::GetDuration(&lhs[0]), Utils::GetDuration(&rhs[0])));
894  return true;
895  }
896 
897  context.setAtomicResult(Atom::Nil());
898  return false;
899 }
900 
901 bool id(const Context& context) {
902  Context arg = *context.get_child(1);
903 
904  if (arg[0].isFloat()) {
905 
906  context.setAtomicResult(Atom::Float(arg[0].asFloat()));
907  return true;
908  }
909  // TODO: Support copying a structured object (with possible nested structures).
910 
911  context.setAtomicResult(Atom::Nil());
912  return false;
913 }
914 
915 }
r_code::resized_vector
Definition: resized_vector.h:137
r_code::Atom
Definition: atom.h:104
core::P
Definition: base.h:103
r_code::Code
Definition: r_code/object.h:224
r_code::LocalObject
Definition: r_code/object.h:377