Soar Kernel  9.3.2 08-06-12
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
rhsfun_math.cpp
Go to the documentation of this file.
1 #include <portability.h>
2 
3 /*************************************************************************
4  * PLEASE SEE THE FILE "license.txt" (INCLUDED WITH THIS SOFTWARE PACKAGE)
5  * FOR LICENSE AND COPYRIGHT INFORMATION.
6  *************************************************************************/
7 
8 /*************************************************************************
9  *
10  * file: rhsfun_math.cpp
11  *
12  * =======================================================================
13  * Support routines for doing math in the RHS of productions.
14  * Need more comments here. Nothing in soarkernel.h either.
15  *
16  *
17  * =======================================================================
18  */
19 
20 #include <stdlib.h>
21 
22 #include "rhsfun_math.h"
23 #include "symtab.h"
24 #include "kernel.h"
25 #include "mem.h"
26 #include "print.h"
27 #include "lexer.h"
28 #include "rhsfun.h"
29 #include "soar_rand.h"
30 
31 #include <math.h>
32 
33 
34 
35 /* --------------------------------------------------------------------
36  Plus
37 
38  Takes any number of int_constant or float_constant arguments, and
39  returns their sum.
40 -------------------------------------------------------------------- */
41 
42 Symbol *plus_rhs_function_code (agent* thisAgent, list *args, void* /*user_data*/) {
43  Bool float_found;
44  int64_t i;
45  double f = 0;
46  Symbol *arg;
47  cons *c;
48 
49  for (c=args; c!=NIL; c=c->rest) {
50  arg = static_cast<symbol_union *>(c->first);
51  if ((arg->common.symbol_type != INT_CONSTANT_SYMBOL_TYPE) &&
52  (arg->common.symbol_type != FLOAT_CONSTANT_SYMBOL_TYPE)) {
53  print_with_symbols (thisAgent, "Error: non-number (%y) passed to + function\n",
54  arg);
55  return NIL;
56  }
57  }
58 
59  i = 0;
60  float_found = FALSE;
61  while (args) {
62  arg = static_cast<symbol_union *>(args->first);
63  if (arg->common.symbol_type==INT_CONSTANT_SYMBOL_TYPE) {
64  if (float_found) f += arg->ic.value;
65  else i += arg->ic.value;
66  } else {
67  if (float_found) f += arg->fc.value;
68  else { float_found = TRUE; f = arg->fc.value + i; }
69  }
70  args = args->rest;
71  }
72  if (float_found) return make_float_constant (thisAgent, f);
73  return make_int_constant (thisAgent, i);
74 }
75 
76 /* --------------------------------------------------------------------
77  Times
78 
79  Takes any number of int_constant or float_constant arguments, and
80  returns their product.
81 -------------------------------------------------------------------- */
82 
83 Symbol *times_rhs_function_code (agent* thisAgent, list *args, void* /*user_data*/) {
84  Bool float_found;
85  int64_t i;
86  double f = 0;
87  Symbol *arg;
88  cons *c;
89 
90  for (c=args; c!=NIL; c=c->rest) {
91  arg = static_cast<symbol_union *>(c->first);
92  if ((arg->common.symbol_type != INT_CONSTANT_SYMBOL_TYPE) &&
93  (arg->common.symbol_type != FLOAT_CONSTANT_SYMBOL_TYPE)) {
94  print_with_symbols (thisAgent, "Error: non-number (%y) passed to * function\n",
95  arg);
96  return NIL;
97  }
98  }
99 
100  i = 1;
101  float_found = FALSE;
102  while (args) {
103  arg = static_cast<symbol_union *>(args->first);
104  if (arg->common.symbol_type==INT_CONSTANT_SYMBOL_TYPE) {
105  if (float_found) f *= arg->ic.value;
106  else i *= arg->ic.value;
107  } else {
108  if (float_found) f *= arg->fc.value;
109  else { float_found = TRUE; f = arg->fc.value * i; }
110  }
111  args = args->rest;
112  }
113  if (float_found) return make_float_constant (thisAgent, f);
114  return make_int_constant (thisAgent, i);
115 }
116 
117 /* --------------------------------------------------------------------
118  Minus
119 
120  Takes one or more int_constant or float_constant arguments.
121  If 0 arguments, returns NIL (error).
122  If 1 argument (x), returns -x.
123  If >=2 arguments (x, y1, ..., yk), returns x - y1 - ... - yk.
124 -------------------------------------------------------------------- */
125 
126 Symbol *minus_rhs_function_code (agent* thisAgent, list *args, void* /*user_data*/) {
127  Symbol *arg;
128  double f = 0; /* For gcc -Wall */
129  int64_t i = 0; /* For gcc -Wall */
130  cons *c;
131  Bool float_found;
132 
133  if (!args) {
134  print (thisAgent, "Error: '-' function called with no arguments\n");
135  return NIL;
136  }
137 
138  for (c=args; c!=NIL; c=c->rest) {
139  arg = static_cast<symbol_union *>(c->first);
140  if ((arg->common.symbol_type != INT_CONSTANT_SYMBOL_TYPE) &&
141  (arg->common.symbol_type != FLOAT_CONSTANT_SYMBOL_TYPE)) {
142  print_with_symbols (thisAgent, "Error: non-number (%y) passed to - function\n",
143  arg);
144  return NIL;
145  }
146  }
147 
148  if (! args->rest) {
149  /* --- only one argument --- */
150  arg = static_cast<symbol_union *>(args->first);
151  if (arg->common.symbol_type==INT_CONSTANT_SYMBOL_TYPE)
152  return make_int_constant (thisAgent, - arg->ic.value);
153  return make_float_constant (thisAgent, - arg->fc.value);
154  }
155 
156  /* --- two or more arguments --- */
157  arg = static_cast<symbol_union *>(args->first);
158  float_found = FALSE;
159  if (arg->common.symbol_type==INT_CONSTANT_SYMBOL_TYPE) i = arg->ic.value;
160  else { float_found = TRUE; f = arg->fc.value; }
161  for (c=args->rest; c!=NIL; c=c->rest) {
162  arg = static_cast<symbol_union *>(c->first);
163  if (arg->common.symbol_type==INT_CONSTANT_SYMBOL_TYPE) {
164  if (float_found) f -= arg->ic.value;
165  else i -= arg->ic.value;
166  } else {
167  if (float_found) f -= arg->fc.value;
168  else { float_found = TRUE; f = i - arg->fc.value; }
169  }
170  }
171 
172  if (float_found) return make_float_constant (thisAgent, f);
173  return make_int_constant (thisAgent, i);
174 }
175 
176 /* --------------------------------------------------------------------
177  Floating-Point Division
178 
179  Takes one or more int_constant or float_constant arguments.
180  If 0 arguments, returns NIL (error).
181  If 1 argument (x), returns 1/x.
182  If >=2 arguments (x, y1, ..., yk), returns x / y1 / ... / yk.
183 -------------------------------------------------------------------- */
184 
185 Symbol *fp_divide_rhs_function_code (agent* thisAgent, list *args, void* /*user_data*/) {
186  Symbol *arg;
187  double f;
188  cons *c;
189 
190  if (!args) {
191  print (thisAgent, "Error: '/' function called with no arguments\n");
192  return NIL;
193  }
194 
195  for (c=args; c!=NIL; c=c->rest) {
196  arg = static_cast<symbol_union *>(c->first);
197  if ((arg->common.symbol_type != INT_CONSTANT_SYMBOL_TYPE) &&
198  (arg->common.symbol_type != FLOAT_CONSTANT_SYMBOL_TYPE)) {
199  print_with_symbols (thisAgent, "Error: non-number (%y) passed to / function\n",
200  arg);
201  return NIL;
202  }
203  }
204 
205  if (! args->rest) {
206  /* --- only one argument --- */
207  arg = static_cast<symbol_union *>(args->first);
208  if (arg->common.symbol_type==INT_CONSTANT_SYMBOL_TYPE) f = static_cast<double>(arg->ic.value);
209  else f = arg->fc.value;
210  if (f != 0.0) return make_float_constant (thisAgent, 1.0 / f);
211  print (thisAgent, "Error: attempt to divide ('/') by zero.\n");
212  return NIL;
213  }
214 
215  /* --- two or more arguments --- */
216  arg = static_cast<symbol_union *>(args->first);
217  if (arg->common.symbol_type==INT_CONSTANT_SYMBOL_TYPE) f = static_cast<double>(arg->ic.value);
218  else f = arg->fc.value;
219  for (c=args->rest; c!=NIL; c=c->rest) {
220  arg = static_cast<symbol_union *>(c->first);
221  if (arg->common.symbol_type==INT_CONSTANT_SYMBOL_TYPE) {
222  if (arg->ic.value) f /= arg->ic.value;
223  else { print (thisAgent, "Error: attempt to divide ('/') by zero.\n"); return NIL; }
224  } else {
225  if (arg->fc.value != 0.0) f /= arg->fc.value;
226  else { print (thisAgent, "Error: attempt to divide ('/') by zero.\n"); return NIL; }
227  }
228  }
229  return make_float_constant (thisAgent, f);
230 }
231 
232 /* --------------------------------------------------------------------
233  Integer Division (Quotient)
234 
235  Takes two int_constant arguments, and returns their quotient.
236 -------------------------------------------------------------------- */
237 
238 Symbol *div_rhs_function_code (agent* thisAgent, list *args, void* /*user_data*/) {
239  Symbol *arg1, *arg2;
240 
241  arg1 = static_cast<symbol_union *>(args->first);
242  arg2 = static_cast<symbol_union *>(args->rest->first);
243 
244  if (arg1->common.symbol_type != INT_CONSTANT_SYMBOL_TYPE) {
245  print_with_symbols (thisAgent, "Error: non-integer (%y) passed to div function\n",
246  arg1);
247  return NIL;
248  }
249  if (arg2->common.symbol_type != INT_CONSTANT_SYMBOL_TYPE) {
250  print_with_symbols (thisAgent, "Error: non-integer (%y) passed to div function\n",
251  arg2);
252  return NIL;
253  }
254 
255  if (arg2->ic.value == 0) {
256  print (thisAgent, "Error: attempt to divide ('div') by zero.\n");
257  return NIL;
258  }
259 
260  return make_int_constant (thisAgent, arg1->ic.value / arg2->ic.value);
261  /* Warning: ANSI doesn't say precisely what happens if one or both of the
262  two args is negative. */
263 }
264 
265 /* --------------------------------------------------------------------
266  Integer Modulus
267 
268  Takes two int_constant arguments (x,y) and returns (x mod y), i.e.,
269  the remainder after dividing x by y.
270 -------------------------------------------------------------------- */
271 
272 Symbol *mod_rhs_function_code (agent* thisAgent, list *args, void* /*user_data*/) {
273  Symbol *arg1, *arg2;
274 
275  arg1 = static_cast<symbol_union *>(args->first);
276  arg2 = static_cast<symbol_union *>(args->rest->first);
277 
278  if (arg1->common.symbol_type != INT_CONSTANT_SYMBOL_TYPE) {
279  print_with_symbols (thisAgent, "Error: non-integer (%y) passed to mod function\n",
280  arg1);
281  return NIL;
282  }
283  if (arg2->common.symbol_type != INT_CONSTANT_SYMBOL_TYPE) {
284  print_with_symbols (thisAgent, "Error: non-integer (%y) passed to mod function\n",
285  arg2);
286  return NIL;
287  }
288 
289  if (arg2->ic.value == 0) {
290  print (thisAgent, "Error: attempt to divide ('mod') by zero.\n");
291  return NIL;
292  }
293 
294  return make_int_constant (thisAgent, arg1->ic.value % arg2->ic.value);
295  /* Warning: ANSI guarantees this does the right thing if both args are
296  positive. If one or both is negative, it only guarantees that
297  (a/b)*b + a%b == a. */
298 }
299 
300 /*
301  * SIN_RHS_FUNCTION_CODE
302  *
303  * Returns as a float the sine of an angle measured in radians.
304  */
305 Symbol *sin_rhs_function_code(agent* thisAgent, list *args, void* /*user_data*/)
306 {
307  Symbol *arg;
308  double arg_value;
309 
310  if (!args) {
311  print(thisAgent, "Error: 'sin' function called with no arguments\n");
312  return NIL;
313  }
314 
315  arg = static_cast<symbol_union *>(args->first);
316  if (arg->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE)
317  arg_value = arg->fc.value;
318  else if (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE)
319  arg_value = static_cast<double>(arg->ic.value) ;
320  else {
321  print_with_symbols(thisAgent, "Error: 'sin' function called with non-numeric argument %y\n", arg);
322  return NIL;
323  }
324 
325  return make_float_constant(thisAgent, sin(arg_value));
326 }
327 
328 
329 /*
330  * COS_RHS_FUNCTION_CODE
331  *
332  * Returns as a float the cosine of an angle measured in radians.
333  */
334 Symbol *cos_rhs_function_code(agent* thisAgent, list *args, void* /*user_data*/)
335 {
336  Symbol *arg;
337  double arg_value;
338 
339  if (!args) {
340  print(thisAgent, "Error: 'cos' function called with no arguments\n");
341  return NIL;
342  }
343 
344  arg = static_cast<symbol_union *>(args->first);
345  if (arg->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE)
346  arg_value = arg->fc.value;
347  else if (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE)
348  arg_value = static_cast<double>(arg->ic.value) ;
349  else {
350  print_with_symbols(thisAgent, "Error: 'cos' function called with non-numeric argument %y\n", arg);
351  return NIL;
352  }
353  return make_float_constant(thisAgent, cos(arg_value));
354 }
355 
356 
357 /*
358  * SQRT_RHS_FUNCTION_CODE
359  *
360  * Returns as a float the square root of its argument (integer or float).
361  */
362 Symbol *sqrt_rhs_function_code(agent* thisAgent, list *args, void* /*user_data*/)
363 {
364  Symbol *arg;
365  double arg_value;
366 
367  if (!args) {
368  print(thisAgent, "Error: 'sqrt' function called with no arguments\n");
369  return NIL;
370  }
371 
372  arg = static_cast<symbol_union *>(args->first);
373  if (arg->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE)
374  arg_value = arg->fc.value;
375  else if (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE)
376  arg_value = static_cast<double>(arg->ic.value);
377  else {
378  print_with_symbols(thisAgent, "Error: 'sqrt' function called with non-numeric argument %y\n", arg);
379  return NIL;
380  }
381  return make_float_constant(thisAgent, sqrt(arg_value));
382 }
383 
384 
385 /*
386  * ATAN2_RHS_FUNCTION_CODE
387  *
388  * Returns as a float in radians the arctangent of (first_arg/second_arg)
389  * which are floats or integers.
390  */
391 Symbol *atan2_rhs_function_code(agent* thisAgent, list *args, void* /*user_data*/)
392 {
393  Symbol *arg;
394  cons *c;
395  double numer_value,
396  denom_value;
397 
398  if (!args) {
399  print(thisAgent, "Error: 'atan2' function called with no arguments\n");
400  return NIL;
401  }
402 
403  for (c=args; c!=NIL; c=c->rest) {
404  arg = static_cast<symbol_union *>(c->first);
405  if ( (arg->common.symbol_type != INT_CONSTANT_SYMBOL_TYPE)
406  && (arg->common.symbol_type != FLOAT_CONSTANT_SYMBOL_TYPE)) {
407  print_with_symbols (thisAgent, "Error: non-number (%y) passed to atan2\n",
408  arg);
409  return NIL;
410  }
411  }
412 
413  if (!args->rest) {
414  print(thisAgent, "Error: 'atan2' function called with only one argument\n");
415  return NIL;
416  }
417 
418  arg = static_cast<symbol_union *>(args->first);
419  if (arg->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE)
420  numer_value = arg->fc.value;
421  else
422  numer_value = static_cast<double>(arg->ic.value) ;
423 
424  c = args->rest;
425  if (c->rest) {
426  print(thisAgent, "Error: 'atan2' function called with more than two arguments.\n");
427  return NIL;
428  }
429  arg = static_cast<symbol_union *>(c->first);
430  if (arg->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE)
431  denom_value = arg->fc.value;
432  else
433  denom_value = static_cast<double>(arg->ic.value) ;
434 
435  return make_float_constant(thisAgent, atan2(numer_value, denom_value));
436 }
437 
438 
439 /*
440  * ABS_RHS_FUNCTION_CODE
441  *
442  * Returns the absolute value of a float as a float, of an int as an int.
443  */
444 Symbol *abs_rhs_function_code(agent* thisAgent, list *args, void* /*user_data*/)
445 {
446  Symbol *arg,
447  *return_value;
448 
449  if (!args) {
450  print(thisAgent, "Error: 'abs' function called with no arguments\n");
451  return NIL;
452  }
453 
454  arg = static_cast<symbol_union *>(args->first);
455  if (arg->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE)
456  return_value = make_float_constant(thisAgent, fabs(arg->fc.value));
457  else if (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE)
458  return_value = make_int_constant(thisAgent, (arg->ic.value<0) ? -arg->ic.value : arg->ic.value);
459  else {
460  print_with_symbols(thisAgent, "Error: 'abs' function called with non-numeric argument %y\n", arg);
461  return NIL;
462  }
463  return return_value;
464 }
465 
466 
467 /* --------------------------------------------------------------------
468  int
469 
470  Casts the given symbol into an integer. If the symbol is a sym
471  constant, a conversion is done. If the symbol is a float, then
472  the integer portion is returned.
473 -------------------------------------------------------------------- */
474 
475 Symbol *int_rhs_function_code (agent* thisAgent, list *args, void* /*user_data*/) {
476  Symbol * sym;
477 
478  if (!args) {
479  print (thisAgent, "Error: 'int' function called with no arguments.\n");
480  return NIL;
481  }
482 
483  if (args->rest) {
484  print (thisAgent, "Error: 'int' takes exactly 1 argument.\n");
485  return NIL;
486  }
487 
488  sym = static_cast<Symbol *>(args->first);
489  if (sym->common.symbol_type == VARIABLE_SYMBOL_TYPE) {
490  print_with_symbols (thisAgent, "Error: variable (%y) passed to 'int' RHS function.\n",
491  sym);
492  return NIL;
493  } else if (sym->common.symbol_type == IDENTIFIER_SYMBOL_TYPE) {
494  print_with_symbols (thisAgent, "Error: identifier (%y) passed to 'int' RHS function.\n",
495  sym);
496  return NIL;
497  } else if (sym->common.symbol_type == SYM_CONSTANT_SYMBOL_TYPE) {
498  int64_t int_val;
499 
500  errno = 0;
501  int_val = strtol(symbol_to_string (thisAgent, sym, FALSE, NIL, 0), NULL, 10);
502  if (errno) {
503  print (thisAgent, "Error: bad integer (%y) given to 'int' RHS function\n",
504  sym);
505  return NIL;
506  }
507  return make_int_constant (thisAgent, int_val);
508  } else if (sym->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) {
509  symbol_add_ref(sym) ;
510  return sym;
511  } else if (sym->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE) {
512  double int_part;
513  modf(sym->fc.value, &int_part);
514  return make_int_constant(thisAgent, static_cast<int64_t>(int_part) );
515  }
516 
517  print (thisAgent, "Error: unknown symbol type (%y) given to 'int' RHS function\n",
518  sym);
519  return NIL;
520 }
521 
522 
523 /* --------------------------------------------------------------------
524  float
525 
526  Casts the given symbol into an float. If the symbol is a sym
527  constant, a conversion is done. If the symbol is an int, then
528  the integer portion is converted.
529 -------------------------------------------------------------------- */
530 
531 Symbol *float_rhs_function_code (agent* thisAgent, list *args, void* /*user_data*/) {
532  Symbol * sym;
533 
534  if (!args) {
535  print (thisAgent, "Error: 'float' function called with no arguments.\n");
536  return NIL;
537  }
538 
539  if (args->rest) {
540  print (thisAgent, "Error: 'float' takes exactly 1 argument.\n");
541  return NIL;
542  }
543 
544  sym = static_cast<Symbol *>(args->first);
545  if (sym->common.symbol_type == VARIABLE_SYMBOL_TYPE) {
546  print_with_symbols (thisAgent, "Error: variable (%y) passed to 'float' RHS function.\n",
547  sym);
548  return NIL;
549  } else if (sym->common.symbol_type == IDENTIFIER_SYMBOL_TYPE) {
550  print_with_symbols (thisAgent, "Error: identifier (%y) passed to 'float' RHS function.\n",
551  sym);
552  return NIL;
553  } else if (sym->common.symbol_type == SYM_CONSTANT_SYMBOL_TYPE) {
554  double float_val;
555 
556  errno = 0;
557  float_val = strtod(symbol_to_string (thisAgent, sym, FALSE, NIL, 0), NULL);
558  if (errno) {
559  print (thisAgent, "Error: bad float (%y) given to 'float' RHS function\n",
560  sym);
561  return NIL;
562  }
563  return make_float_constant (thisAgent, float_val);
564  } else if (sym->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE) {
565  symbol_add_ref(sym) ;
566  return sym;
567  } else if (sym->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) {
568  return make_float_constant(thisAgent, static_cast<double>(sym->ic.value) );
569  }
570 
571  print (thisAgent, "Error: unknown symbol type (%y) given to 'float' RHS function\n",
572  sym);
573  return NIL;
574 }
575 
576 /* voigtjr 6/12/2007: added these built in functions on laird's request
577 these are straight out of the <8.6 kernel */
578 
579 /***********************************************************
580 These RHS functions are used in the Quake-Soar agent. They
581 are modified versions of the routines taken from TacAir-Soar.
582 *************************************************************/
583 
584 /* "Normalizes" an integral heading to be between -180 and +180 */
585 int64_t normalize_heading_int(int64_t n)
586 {
587  /* we need to make sure that -180 < value <= 180 so we modify */
588  /* the original rounded value using the fact that for heading, */
589  /* for any integer value of x, the following holds: */
590  /* heading1 = x*360 + heading2 */
591  while (n <= -180)
592  n += 360;
593  while (n > 180)
594  n -= 360;
595 
596  return n;
597 }
598 
599 /* "Normalizes" a floating point heading to be between -180.0 and +180.0 */
600 double normalize_heading_float(double n)
601 {
602  /* we need to make sure that -180 < value <= 180 so we modify */
603  /* the original rounded value using the fact that for heading, */
604  /* for any integer value of x, the following holds: */
605  /* heading1 = x*360 + heading2 */
606  while (n <= -180.0)
607  n += 360.0;
608  while (n > 180.0)
609  n -= 360.0;
610 
611  return n;
612 }
613 
614 int64_t round_off_heading_int(int64_t n, int64_t m)
615 {
616  int64_t unbounded_rounded;
617 
618  /* need to round the first (i_n) to the nearest second (i_m) */
619  if (n < 0)
620  unbounded_rounded = m * ((n - (m / 2L)) / m);
621  else
622  unbounded_rounded = m * ((n + (m / 2L)) / m);
623 
624  return unbounded_rounded;
625 }
626 
627 double round_off_heading_float(double n, double m)
628 {
629  double n_10, m_10, unbounded_rounded;
630  double ip;
631  double ip2;
632 
633  /* OK. Both n and m can have tenths, so multiply by 10 and treat
634  as integers */
635  modf((n * 10.0), &ip);
636  n_10 = ip;
637  modf((m * 10.0), &ip);
638  m_10 = ip;
639 
640  if (n_10 < 0.0) {
641 
642  modf((m_10 / 2.0), &ip2);
643  modf(((n_10 - ip2) / m_10), &ip);
644  unbounded_rounded = (m_10 * ip);
645  } else {
646 
647  modf((m_10 / 2.0), &ip2);
648  modf(((n_10 + ip2) / m_10), &ip);
649  unbounded_rounded = (m_10 * ip);
650  }
651 
652  /* Divide by 10 to get tenths back and return */
653  return unbounded_rounded / 10.0;
654 }
655 
656 Symbol *round_off_heading_air_rhs_function_code(agent* thisAgent, list *args, void* /*user_data*/)
657 {
658  Symbol *arg;
659  double n = 0, f_m = 0;
660  int64_t i_m = 0;
661  cons *c;
662  bool float_found = FALSE;
663 
664  if (!args) {
665  print(thisAgent, "Error: 'round_off_heading' function called with no arguments\n");
666  return NIL;
667  }
668 
669  if (!args->rest) {
670  /* --- only one argument --- */
671  print(thisAgent, "Error: 'round_off_heading' function called with only one argument.\n");
672  return NIL;
673  }
674 
675  /* --- two or more arguments --- */
676  arg = static_cast<Symbol *>(args->first);
677  if (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE)
678  n = static_cast<double>(arg->ic.value) ;
679  else if (arg->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE) {
680  n = arg->fc.value;
681  }
682 
683  c = args->rest;
684  if (c->rest) {
685  /* --- more than two arguments --- */
686  print(thisAgent, "Error: 'round_off_heading' function called with more than two arguments.\n");
687  return NIL;
688  }
689  arg = static_cast<Symbol *>(c->first);
690  if (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE)
691  i_m = arg->ic.value;
692  else if (arg->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE) {
693  float_found = TRUE;
694  f_m = arg->fc.value;
695  }
696 
697  /* Now, deal with the arguments based on type and return result */
698  if (float_found)
700  else
701  return make_int_constant(thisAgent, normalize_heading_int(round_off_heading_int(static_cast<int64_t>(n) , i_m)));
702 
703 }
704 
705 /* code for round_off_heading */
706 
707 /* --------------------------------------------------------------------
708  round_off
709 
710  Takes two numbers and returns the first rounded to the nearest second.
711 -------------------------------------------------------------------- */
712 Symbol *round_off_air_rhs_function_code(agent* thisAgent, list *args, void* /*user_data*/)
713 {
714  Symbol *arg;
715  double n = 0, f_m = 0;
716  int64_t i_m = 0;
717  cons *c;
718  bool float_found = FALSE;
719 
720  if (!args) {
721  print(thisAgent, "Error: 'round_off' function called with no arguments\n");
722  return NIL;
723  }
724 
725  if (!args->rest) {
726  /* --- only one argument --- */
727  print(thisAgent, "Error: 'round_off' function called with only one argument.\n");
728  return NIL;
729  }
730 
731  /* --- two or more arguments --- */
732  arg = static_cast<Symbol *>(args->first);
733  if (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE)
734  n = static_cast<double>(arg->ic.value) ;
735  else if (arg->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE) {
736  n = arg->fc.value;
737  }
738 
739  c = args->rest;
740  if (c->rest) {
741  /* --- more than two arguments --- */
742  print(thisAgent, "Error: 'round_off' function called with more than two arguments.\n");
743  return NIL;
744  }
745  arg = static_cast<Symbol *>(c->first);
746  if (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE)
747  i_m = arg->ic.value;
748  else if (arg->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE) {
749  float_found = TRUE;
750  f_m = arg->fc.value;
751  }
752 
753  /* Now, deal with the arguments based on type and return result */
754  if (float_found)
755  return make_float_constant(thisAgent, round_off_heading_float(n, f_m));
756  else
757  return make_int_constant(thisAgent, round_off_heading_int(static_cast<int64_t>(n), i_m));
758 }
759 
760 #define PI 3.141592653589
761 #define PI_OVER_TWO (PI/2)
762 #define TWO_PI (PI*2)
763 #define RAD_TO_DEG(X) ((X*180)/PI)
764 #define X 0
765 #define Y 1
766 #define Z 2
767 
768 void vector_from_to_position(double pos1[3], double pos2[3], double vector[3])
769 {
770  vector[X] = pos2[X] - pos1[X];
771  vector[Y] = pos2[Y] - pos1[Y];
772  vector[Z] = pos2[Z] - pos1[Z];
773 }
774 
775 void vec2_norm(double v[3], double r[3], int abort)
776 {
777  double mag, mag2;
778  mag2 = v[X] * v[X] + v[Y] * v[Y];
779  mag = sqrt(mag2);
780  if (!abort && (mag < 0.01)) {
781  r[0] = 1.0;
782  r[1] = 0.0;
783  return;
784  }
785  r[0] = v[0] / mag;
786  r[1] = v[1] / mag;
787 }
788 
789 double convert_to_soar_angle(double heading_in_rads)
790 {
791  double heading;
792 
793  /* Not only correct, but more efficient! */
794  heading = heading_in_rads - PI_OVER_TWO;
795  if (heading < 0.0)
796  heading += TWO_PI;
797  heading = TWO_PI - heading;
798  if (heading > PI)
799  heading -= TWO_PI;
800 
801  return heading;
802 }
803 
804 void hrl_xydof_to_heading(double xydof[3], double * output)
805 {
806  double heading_in_rads;
807 
808  heading_in_rads = convert_to_soar_angle(atan2(xydof[Y], xydof[X]));
809 
810  (*output) = heading_in_rads;
811 }
812 
813 int64_t air_soar_round_off_angle(int64_t n, int64_t m)
814 {
815  int64_t unbounded_rounded, bounded_rounded;
816 
817  /* need to round the first (n) to the nearest second (m) */
818  if (n < 0)
819  unbounded_rounded = m * ((n - (m / 2L)) / m);
820  else
821  unbounded_rounded = m * ((n + (m / 2L)) / m);
822 
823  /* we need to make sure that -180 < value <= 180. */
824 
825  // FIXME replace this code with the much faster mod2pi in ed olson's linalg library
826  bounded_rounded = (unbounded_rounded % 360);
827  if (bounded_rounded > 180)
828  bounded_rounded -= 360;
829  if (bounded_rounded <= -180)
830  bounded_rounded += 360;
831 
832  return bounded_rounded;
833 }
834 
835 double bracket_rad_to_deg(double var)
836 {
837  return static_cast<double>(air_soar_round_off_angle(static_cast<int64_t>(RAD_TO_DEG(var)), 1)) ;
838 }
839 
840 int64_t convert(double flo)
841 {
842  return static_cast<int64_t>(flo);
843 }
844 
845 int64_t heading_to_point(int64_t current_x, int64_t current_y, int64_t x, int64_t y)
846 {
847  double plane_pos[3], waypoint_pos[3], dir[3];
848  double heading;
849 
850  plane_pos[0] = static_cast<double>(current_x) ;
851  plane_pos[1] = static_cast<double>(current_y) ;
852  plane_pos[2] = 0;
853 
854  waypoint_pos[0] = static_cast<double>(x) ;
855  waypoint_pos[1] = static_cast<double>(y) ;
856  waypoint_pos[2] = 0;
857 
858  vector_from_to_position(plane_pos, waypoint_pos, dir);
859  vec2_norm(dir, dir, FALSE);
860  hrl_xydof_to_heading(dir, &heading);
861 
862  return convert(bracket_rad_to_deg(heading));
863 }
864 
865 /* --------------------------------------------------------------------
866  compute-heading
867 
868  Takes 4 args and returns integer heading from x1,y1 to x2,y2
869 -------------------------------------------------------------------- */
870 
871 Symbol *compute_heading_rhs_function_code(agent* thisAgent, list *args, void* /*user_data*/)
872 {
873  Symbol *arg;
874  int64_t current_x, current_y;
875  int64_t waypoint_x, waypoint_y;
876  int count;
877  cons *c;
878 
879  if (!args) {
880  print(thisAgent, "Error: 'compute-heading' function called with no arguments\n");
881  return NIL;
882  }
883 
884  for (c = args; c != NIL; c = c->rest) {
885  arg = static_cast<Symbol *>(c->first);
886  if ((arg->common.symbol_type != INT_CONSTANT_SYMBOL_TYPE) &&
887  (arg->common.symbol_type != FLOAT_CONSTANT_SYMBOL_TYPE)) {
888  print_with_symbols(thisAgent, "Error: non-number (%y) passed to - compute-heading\n", arg);
889  return NIL;
890  }
891  }
892 
893  count = 1;
894 
895  for (c = args->rest; c != NIL; c = c->rest) {
896  arg = static_cast<Symbol *>(c->first);
897  if ((arg->common.symbol_type != INT_CONSTANT_SYMBOL_TYPE) &&
898  (arg->common.symbol_type != FLOAT_CONSTANT_SYMBOL_TYPE)) {
899  print_with_symbols(thisAgent, "Error: non-number (%y) passed to compute-heading function.\n", arg);
900  return NIL;
901  } else {
902  count++;
903  }
904  }
905 
906  if (count != 4) {
907  print(thisAgent, "Error: 'compute-heading' takes exactly 4 arguments.\n");
908  return NIL;
909  }
910 
911  arg = static_cast<Symbol *>(args->first);
912  current_x = (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) ? arg->ic.value : static_cast<int64_t>(arg->fc.value);
913 
914  arg = static_cast<Symbol *>(args->rest->first);
915  current_y = (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) ? arg->ic.value : static_cast<int64_t>(arg->fc.value);
916 
917  arg = static_cast<Symbol *>(args->rest->rest->first);
918  waypoint_x = (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) ? arg->ic.value : static_cast<int64_t>(arg->fc.value);
919 
920  arg = static_cast<Symbol *>(args->rest->rest->rest->first);
921  waypoint_y = (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) ? arg->ic.value : static_cast<int64_t>(arg->fc.value);
922 
923  return make_int_constant(thisAgent, heading_to_point(current_x, current_y, waypoint_x, waypoint_y));
924 }
925 
926 /* --------------------------------------------------------------------
927  compute-range
928 
929  Takes 4 args and returns integer range from x1,y1 to x2,y2
930 -------------------------------------------------------------------- */
931 
932 Symbol *compute_range_rhs_function_code(agent* thisAgent, list *args, void* /*user_data*/)
933 {
934  Symbol *arg;
935  double current_x, current_y;
936  double waypoint_x, waypoint_y;
937  int count;
938  cons *c;
939 
940  if (!args) {
941  print(thisAgent, "Error: 'compute-range' function called with no arguments\n");
942  return NIL;
943  }
944 
945  for (c = args; c != NIL; c = c->rest) {
946  arg = static_cast<Symbol *>(c->first);
947  if ((arg->common.symbol_type != INT_CONSTANT_SYMBOL_TYPE)
948  && (arg->common.symbol_type != FLOAT_CONSTANT_SYMBOL_TYPE)) {
949  print_with_symbols(thisAgent, "Error: non-number (%y) passed to - compute-range\n", arg);
950  return NIL;
951  }
952  }
953 
954  count = 1;
955 
956  for (c = args->rest; c != NIL; c = c->rest) {
957  arg = static_cast<Symbol *>(c->first);
958  if ((arg->common.symbol_type != INT_CONSTANT_SYMBOL_TYPE)
959  && (arg->common.symbol_type != FLOAT_CONSTANT_SYMBOL_TYPE)) {
960  print_with_symbols(thisAgent, "Error: non-number (%y) passed to compute-range function.\n", arg);
961  return NIL;
962  } else {
963  count++;
964  }
965  }
966 
967  if (count != 4) {
968  print(thisAgent, "Error: 'compute-range' takes exactly 4 arguments.\n");
969  return NIL;
970  }
971 
972  arg = static_cast<Symbol *>(args->first);
973  current_x = (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) ? static_cast<double>(arg->ic.value) : arg->fc.value;
974 
975  arg = static_cast<Symbol *>(args->rest->first);
976  current_y = (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) ? static_cast<double>(arg->ic.value) : arg->fc.value;
977 
978  arg = static_cast<Symbol *>(args->rest->rest->first);
979  waypoint_x = (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) ? static_cast<double>(arg->ic.value) : arg->fc.value;
980 
981  arg = static_cast<Symbol *>(args->rest->rest->rest->first);
982  waypoint_y = (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) ? static_cast<double>(arg->ic.value) : arg->fc.value;
983 
984  return make_int_constant(thisAgent, static_cast<int64_t>(sqrt((current_x - waypoint_x)
985  * (current_x - waypoint_x)
986  + (current_y - waypoint_y)
987  * (current_y - waypoint_y))));
988 }
989 
990 /* --------------------------------------------------------------------
991  rand-float
992 
993  Takes an optional integer argument.
994  Returns [0,1.0] of no argument, or if argument is not positive.
995  Returns [0,n] if argument is positive.
996 -------------------------------------------------------------------- */
997 Symbol* rand_float_rhs_function_code(agent* thisAgent, list* args, void* /*user_data*/)
998 {
999  double n = 0;
1000  if (args)
1001  {
1002  cons* c = args;
1003  Symbol* arg = static_cast<Symbol*>(c->first);
1004  if (arg) {
1005  if (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) {
1006  n = static_cast<double>(arg->ic.value);
1007  } else if (arg->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE) {
1008  n = arg->fc.value;
1009  } else {
1010  print_with_symbols(thisAgent, "Error: non-number (%y) passed to - rand-float\n", arg);
1011  return NIL;
1012  }
1013  } else {
1014  // assume default behavior (no arg)
1015  // possibly warn? when can this happen?
1016  }
1017  }
1018 
1019  if (n > 0) {
1020  return make_float_constant(thisAgent, SoarRand(n));
1021  }
1022  return make_float_constant(thisAgent, SoarRand());
1023 }
1024 
1025 /* --------------------------------------------------------------------
1026  rand-int
1027 
1028  Takes an optional integer argument.
1029  Returns [-2^31,2^31-1] of no argument, or if argument is not positive.
1030  Returns [0,n] if argument is positive.
1031 -------------------------------------------------------------------- */
1032 Symbol* rand_int_rhs_function_code(agent* thisAgent, list* args, void* /*user_data*/)
1033 {
1034  int64_t n = 0;
1035  if (args)
1036  {
1037  cons* c = args;
1038  Symbol* arg = static_cast<Symbol*>(c->first);
1039  if (arg) {
1040  if (arg->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE) {
1041  n = arg->ic.value;
1042  } else if (arg->common.symbol_type == FLOAT_CONSTANT_SYMBOL_TYPE) {
1043  n = static_cast<int64_t>(arg->fc.value);
1044  } else {
1045  print_with_symbols(thisAgent, "Error: non-number (%y) passed to - rand-int\n", arg);
1046  return NIL;
1047  }
1048  } else {
1049  // assume default behavior (no arg)
1050  // possibly warn? when can this happen?
1051  }
1052  }
1053 
1054  if (n > 0) {
1055  return make_int_constant(thisAgent, static_cast<int64_t>(SoarRandInt(static_cast<uint32_t>(n))));
1056  }
1057  return make_int_constant(thisAgent, SoarRandInt());
1058 }
1059 
1060 inline double _dice_zero_tolerance( double in )
1061 {
1062  return ( ( fabs( in ) <= 0.00001 )?( 0 ):( in ) );
1063 }
1064 
1065 // http://www.brpreiss.com/books/opus4/html/page467.html
1066 uint64_t _dice_binom( uint64_t n, uint64_t m )
1067 {
1068  uint64_t* b = new uint64_t[ n+1 ];
1069  uint64_t i, j, ret;
1070 
1071  b[0] = 1;
1072  for ( i=1; i<=n; ++i )
1073  {
1074  b[i] = 1;
1075  for ( j=(i-1); j>0; --j )
1076  {
1077  b[j] += b[j-1];
1078  }
1079  }
1080  ret = b[m];
1081  delete[] b;
1082 
1083  return ret;
1084 }
1085 
1086 double _dice_prob_exact( int64_t dice, int64_t sides, int64_t count )
1087 {
1088  // makes no sense
1089  if ( dice < 0 )
1090  return 0;
1091  if ( count < 0 )
1092  return 0;
1093  if ( sides < 1 )
1094  return 0;
1095 
1096  // if there are no dice, probability is zero unless count is also zero
1097  if ( dice == 0 )
1098  {
1099  if ( count == 0 )
1100  return 1;
1101 
1102  return 0;
1103  }
1104 
1105  if ( count > dice )
1106  return 0;
1107 
1108  double p1kd = pow( static_cast< double >( sides ), static_cast< double >( count ) );
1109  double p2nkn = pow( static_cast< double >( sides - 1 ), static_cast< double >( dice - count ) );
1110  double p2nkd = pow( static_cast< double >( sides ), static_cast< double >( dice - count ) );
1111 
1112  double result = static_cast< double >( _dice_binom( static_cast< uint64_t >( dice ), static_cast< uint64_t >( count ) ) );
1113  result *= ( static_cast< double >( 1.0 ) / p1kd );
1114  result *= ( p2nkn / p2nkd );
1115 
1116  return result;
1117 }
1118 
1119 double _dice_prob_atleast( int64_t dice, int64_t sides, int64_t count )
1120 {
1121  // makes no sense
1122  if ( dice < 0 )
1123  return 0;
1124  if ( count < 0 )
1125  return 0;
1126  if ( sides < 1 )
1127  return 0;
1128 
1129  double result = 0.0;
1130  for ( int64_t i=0; ( count + i <= dice ); ++i )
1131  {
1132  result += _dice_prob_exact( dice, sides, count+i );
1133  }
1134 
1135  return result;
1136 }
1137 
1138 // Taken primarily from Jon Voigt's soar-dice project
1139 // (compute-dice-probability dice sides count predicate) = 0..1
1140 Symbol* dice_prob_rhs_function_code(agent* thisAgent, list* args, void* /*user_data*/)
1141 {
1142  int64_t dice;
1143  int64_t sides;
1144  int64_t count;
1145 
1146  enum pred_type { eq, ne, lt, gt, le, ge, bad };
1147  pred_type pred = bad;
1148 
1149  // parse + validate
1150  {
1151  Symbol* temp_sym;
1152 
1153  // dice
1154  temp_sym = static_cast< Symbol* >( args->first );
1155  if ( ( temp_sym->common.symbol_type != INT_CONSTANT_SYMBOL_TYPE ) &&
1156  ( temp_sym->common.symbol_type != FLOAT_CONSTANT_SYMBOL_TYPE ) )
1157  {
1158  print_with_symbols( thisAgent, "Error: non-number (%y) passed as 'dice' to - compute-dice-probability\n", temp_sym );
1159  return NIL;
1160  }
1161  dice = ( ( temp_sym->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE )?( temp_sym->ic.value ):( static_cast< int64_t >( temp_sym->fc.value ) ) );
1162 
1163  // sides
1164  temp_sym = static_cast< Symbol* >( args->rest->first );
1165  if ( ( temp_sym->common.symbol_type != INT_CONSTANT_SYMBOL_TYPE ) &&
1166  ( temp_sym->common.symbol_type != FLOAT_CONSTANT_SYMBOL_TYPE ) )
1167  {
1168  print_with_symbols( thisAgent, "Error: non-number (%y) passed as 'sides' to - compute-dice-probability\n", temp_sym );
1169  return NIL;
1170  }
1171  sides = ( ( temp_sym->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE )?( temp_sym->ic.value ):( static_cast< int64_t >( temp_sym->fc.value ) ) );
1172 
1173  // count
1174  temp_sym = static_cast< Symbol* >( args->rest->rest->first );
1175  if ( ( temp_sym->common.symbol_type != INT_CONSTANT_SYMBOL_TYPE ) &&
1176  ( temp_sym->common.symbol_type != FLOAT_CONSTANT_SYMBOL_TYPE ) )
1177  {
1178  print_with_symbols( thisAgent, "Error: non-number (%y) passed as 'count' to - compute-dice-probability\n", temp_sym );
1179  return NIL;
1180  }
1181  count = ( ( temp_sym->common.symbol_type == INT_CONSTANT_SYMBOL_TYPE )?( temp_sym->ic.value ):( static_cast< int64_t >( temp_sym->fc.value ) ) );
1182 
1183  // pred
1184  temp_sym = static_cast< Symbol* >( args->rest->rest->rest->first );
1185  if ( temp_sym->common.symbol_type != SYM_CONSTANT_SYMBOL_TYPE )
1186  {
1187  print_with_symbols( thisAgent, "Error: non-string (%y) passed as 'pred' to - compute-dice-probability\n", temp_sym );
1188  return NIL;
1189  }
1190  if ( strcmp( temp_sym->sc.name, "eq" ) == 0 )
1191  {
1192  pred = eq;
1193  }
1194  else if ( strcmp( temp_sym->sc.name, "ne" ) == 0 )
1195  {
1196  pred = ne;
1197  }
1198  else if ( strcmp( temp_sym->sc.name, "lt" ) == 0 )
1199  {
1200  pred = lt;
1201  }
1202  else if ( strcmp( temp_sym->sc.name, "gt" ) == 0 )
1203  {
1204  pred = gt;
1205  }
1206  else if ( strcmp( temp_sym->sc.name, "le" ) == 0 )
1207  {
1208  pred = le;
1209  }
1210  else if ( strcmp( temp_sym->sc.name, "ge" ) == 0 )
1211  {
1212  pred = ge;
1213  }
1214  if ( pred == bad )
1215  {
1216  print_with_symbols( thisAgent, "Error: invalid string (%y) passed as 'pred' to - compute-dice-probability\n", temp_sym );
1217  return NIL;
1218  }
1219  }
1220 
1221  double ret = 0;
1222  if ( pred == eq )
1223  {
1224  if ( ( count < 0 ) || ( count > dice ) )
1225  {
1226  ret = 0;
1227  }
1228  else
1229  {
1230  ret = _dice_zero_tolerance( _dice_prob_exact( dice, sides, count ) );
1231  }
1232  }
1233  else if ( pred == ne )
1234  {
1235  if ( ( count < 0 ) || ( count > dice ) )
1236  {
1237  ret = 1;
1238  }
1239  else
1240  {
1241  ret = _dice_zero_tolerance( 1 - _dice_prob_exact( dice, sides, count ) );
1242  }
1243  }
1244  else if ( pred == lt )
1245  {
1246  if ( count <= 0 )
1247  {
1248  ret = 0;
1249  }
1250  else if ( count > dice )
1251  {
1252  ret = 1;
1253  }
1254  else
1255  {
1256  ret = _dice_zero_tolerance( 1 - _dice_prob_atleast( dice, sides, count ) );
1257  }
1258  }
1259  else if ( pred == gt )
1260  {
1261  if ( count < 0 )
1262  {
1263  ret = 1;
1264  }
1265  else if ( count >= dice )
1266  {
1267  ret = 0;
1268  }
1269  else
1270  {
1271  ret = _dice_zero_tolerance( _dice_prob_atleast( dice, sides, count ) - _dice_prob_exact( dice, sides, count ) );
1272  }
1273  }
1274  else if ( pred == le )
1275  {
1276  if ( count < 0 )
1277  {
1278  ret = 0;
1279  }
1280  else if ( count >= dice )
1281  {
1282  ret = 1;
1283  }
1284  else
1285  {
1286  ret = _dice_zero_tolerance( ( 1 - _dice_prob_atleast( dice, sides, count ) ) + _dice_prob_exact( dice, sides, count ) );
1287  }
1288  }
1289  else if ( pred == ge )
1290  {
1291  if ( count <= 0 )
1292  {
1293  ret = 1;
1294  }
1295  else if ( count > dice )
1296  {
1297  ret = 0;
1298  }
1299  else
1300  {
1301  ret = _dice_zero_tolerance( _dice_prob_atleast( dice, sides, count ) );
1302  }
1303  }
1304 
1305  return make_float_constant(thisAgent, ret);
1306 }
1307 
1308 /* ====================================================================
1309 
1310  Initialize the Built-In RHS Math Functions
1311 
1312 ====================================================================
1313 */
1314 
1316 {
1317  add_rhs_function (thisAgent, make_sym_constant (thisAgent, "+"), plus_rhs_function_code,
1318  -1, TRUE, FALSE, 0);
1319  add_rhs_function (thisAgent, make_sym_constant (thisAgent, "*"), times_rhs_function_code,
1320  -1, TRUE, FALSE, 0);
1321  add_rhs_function (thisAgent, make_sym_constant (thisAgent, "-"), minus_rhs_function_code,
1322  -1, TRUE, FALSE, 0);
1323  add_rhs_function (thisAgent, make_sym_constant (thisAgent, "/"), fp_divide_rhs_function_code,
1324  -1, TRUE, FALSE, 0);
1325  add_rhs_function (thisAgent, make_sym_constant (thisAgent, "div"), div_rhs_function_code,
1326  2, TRUE, FALSE, 0);
1327  add_rhs_function (thisAgent, make_sym_constant (thisAgent, "mod"), mod_rhs_function_code,
1328  2, TRUE, FALSE, 0);
1329 
1330  add_rhs_function (thisAgent, make_sym_constant(thisAgent, "sin"),
1332  1,
1333  TRUE,
1334  FALSE, 0);
1335  add_rhs_function (thisAgent, make_sym_constant(thisAgent, "cos"),
1337  1,
1338  TRUE,
1339  FALSE, 0);
1340  add_rhs_function (thisAgent, make_sym_constant(thisAgent, "atan2"),
1342  2,
1343  TRUE,
1344  FALSE, 0);
1345  add_rhs_function (thisAgent, make_sym_constant(thisAgent, "sqrt"),
1347  1,
1348  TRUE,
1349  FALSE, 0);
1350  add_rhs_function (thisAgent, make_sym_constant(thisAgent, "abs"),
1352  1,
1353  TRUE,
1354  FALSE, 0);
1355  add_rhs_function (thisAgent, make_sym_constant(thisAgent, "int"),
1357  1,
1358  TRUE,
1359  FALSE, 0);
1360  add_rhs_function (thisAgent, make_sym_constant(thisAgent, "float"),
1362  1,
1363  TRUE,
1364  FALSE, 0);
1365 
1366  /* voigtjr 6/12/2007: added these built in functions on laird's request
1367  these are straight out of the <8.6 kernel */
1368  add_rhs_function (thisAgent, make_sym_constant(thisAgent, "round-off-heading"),
1370 
1371  add_rhs_function (thisAgent, make_sym_constant(thisAgent, "round-off"),
1373 
1374  add_rhs_function (thisAgent, make_sym_constant(thisAgent, "compute-heading"),
1376 
1377  add_rhs_function (thisAgent, make_sym_constant(thisAgent, "compute-range"),
1379 
1380  // NLD: 11/11 (ditto voigtjr's motivation above)
1381  add_rhs_function (thisAgent, make_sym_constant(thisAgent, "compute-dice-probability"),
1383 
1384  // Bug 800: implement rhs rand functions
1385  add_rhs_function (thisAgent, make_sym_constant(thisAgent, "rand-int"),
1387 
1388  add_rhs_function (thisAgent, make_sym_constant(thisAgent, "rand-float"),
1390 
1391 }
1392 
1394 {
1395  // DJP-FREE: These used to call make_sym_constant, but the symbols must already exist and if we call make here again we leak a reference.
1396  remove_rhs_function (thisAgent, find_sym_constant (thisAgent, "+"));
1397  remove_rhs_function (thisAgent, find_sym_constant (thisAgent, "*"));
1398  remove_rhs_function (thisAgent, find_sym_constant (thisAgent, "-"));
1399  remove_rhs_function (thisAgent, find_sym_constant (thisAgent, "/"));
1400  remove_rhs_function (thisAgent, find_sym_constant (thisAgent, "div"));
1401  remove_rhs_function (thisAgent, find_sym_constant (thisAgent, "mod"));
1402  remove_rhs_function (thisAgent, find_sym_constant(thisAgent, "sin"));
1403  remove_rhs_function (thisAgent, find_sym_constant(thisAgent, "cos"));
1404  remove_rhs_function (thisAgent, find_sym_constant(thisAgent, "atan2"));
1405  remove_rhs_function (thisAgent, find_sym_constant(thisAgent, "sqrt"));
1406  remove_rhs_function (thisAgent, find_sym_constant(thisAgent, "abs"));
1407  remove_rhs_function (thisAgent, find_sym_constant(thisAgent, "int"));
1408  remove_rhs_function (thisAgent, find_sym_constant(thisAgent, "float"));
1409 
1410  /* voigtjr 6/12/2007: added these built in functions on laird's request
1411  these are straight out of the <8.6 kernel */
1412  remove_rhs_function(thisAgent, find_sym_constant(thisAgent, "round-off-heading"));
1413  remove_rhs_function(thisAgent, find_sym_constant(thisAgent, "round-off"));
1414  remove_rhs_function(thisAgent, find_sym_constant(thisAgent, "compute-heading"));
1415  remove_rhs_function(thisAgent, find_sym_constant(thisAgent, "compute-range"));
1416 
1417  // NLD: 11/11
1418  remove_rhs_function(thisAgent, find_sym_constant(thisAgent, "compute-dice-probability"));
1419 
1420  // Bug 800: implement rand
1421  remove_rhs_function(thisAgent, find_sym_constant(thisAgent, "rand-int"));
1422  remove_rhs_function(thisAgent, find_sym_constant(thisAgent, "rand-float"));
1423 }