potion  0.2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
number.c
Go to the documentation of this file.
1 //
6 // (c) 2008 why the lucky stiff, the freelance professor
7 // (c) 2013-2014 perel11.org
8 //
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdarg.h>
12 #include <math.h>
13 #include "potion.h"
14 #include "internal.h"
15 
17 PN potion_double(Potion *P, double v) {
18  vPN(Double) d = PN_ALLOC_N(PN_TNUMBER, struct PNDouble, 0);
19  d->value = v;
20  return (PN)d;
21 }
22 
24 PN potion_strtod(Potion *P, char *str, int len) {
25  char *ptr = str + len;
26  return potion_double(P, strtod(str, &ptr));
27 }
33 PN potion_num_pow(Potion *P, PN cl, PN self, PN sup) {
34  double x = PN_DBL(self), y = PN_DBL(sup);
35  double z = pow(x, y);
36  if (PN_IS_INT(self) && PN_IS_INT(sup) && fabs(z) < INT_MAX)
37  return PN_NUM((int)z);
38  return potion_double(P, z);
39 }
43 static PN potion_num_sqrt(Potion *P, PN cl, PN self) {
44  return potion_double(P, sqrt(PN_DBL(self)));
45 }
46 
47 #define PN_NUM_MATH(math_op) \
48  DBG_CHECK_NUM(self); \
49  DBG_CHECK_NUM(num); \
50  if (PN_IS_INT(self) && PN_IS_INT(num)) \
51  return PN_NUM(PN_INT(self) math_op PN_INT(num)); \
52  return potion_double(P, PN_DBL(self) math_op PN_DBL(num));
53 #define PN_INT_MATH(math_op) \
54  DBG_CHECK_INT(self); \
55  DBG_CHECK_INT(num); \
56  return PN_NUM(PN_INT(self) math_op PN_INT(num));
57 #define PN_DBL_MATH(math_op) \
58  DBG_CHECK_NUM(self); \
59  DBG_CHECK_NUM(num); \
60  return potion_double(P, PN_DBL(self) math_op PN_DBL(num));
61 
66 static PN potion_num_add(Potion *P, PN cl, PN self, PN num) {
67  PN_NUM_MATH(+)
68 }
69 
74 static PN potion_num_sub(Potion *P, PN cl, PN self, PN num) {
75  PN_NUM_MATH(-)
76 }
77 
82 static PN potion_num_mult(Potion *P, PN cl, PN self, PN num) {
83  PN_NUM_MATH(*)
84 }
85 
90 static PN potion_num_div(Potion *P, PN cl, PN self, PN num) {
91  PN_NUM_MATH(/)
92 }
93 
98 static PN potion_num_rem(Potion *P, PN cl, PN self, PN num) {
99  if (PN_IS_INT(self) && PN_IS_INT(num))
100  return PN_NUM(PN_INT(self) % PN_INT(num));
101  double x = PN_DBL(self), y = PN_DBL(num);
102  int z = (int)(x / y);
103  return potion_double(P, x - (y * (double)z));
104 }
105 
109 static PN potion_num_bitn(Potion *P, PN cl, PN self) {
110  if (PN_IS_INT(self))
111  return PN_NUM(~PN_INT(self));
112  return (PN)potion_double(P, 0.0);
113 }
114 
119 static PN potion_num_bitl(Potion *P, PN cl, PN self, PN num) {
120  if (PN_IS_INT(self) && PN_IS_INT(num))
121  return PN_NUM(PN_INT(self) << PN_INT(num));
122  return (PN)potion_double(P, 0.0);
123 }
124 
129 static PN potion_num_bitr(Potion *P, PN cl, PN self, PN num) {
130  if (PN_IS_INT(self) && PN_IS_INT(num))
131  return PN_NUM(PN_INT(self) >> PN_INT(num));
132  return (PN)potion_double(P, 0.0);
133 }
134 
139 static PN potion_int_add(Potion *P, PN cl, PN self, PN num) { PN_INT_MATH(+) }
144 static PN potion_int_sub(Potion *P, PN cl, PN self, PN num) { PN_INT_MATH(-) }
149 static PN potion_int_mult(Potion *P, PN cl, PN self, PN num) { PN_INT_MATH(*) }
154 static PN potion_int_div(Potion *P, PN cl, PN self, PN num) { PN_INT_MATH(/) }
155 
160 static PN potion_int_rem(Potion *P, PN cl, PN self, PN num) { PN_INT_MATH(%) }
161 
165 static PN potion_int_bitn(Potion *P, PN cl, PN self) {
166  return PN_NUM(~PN_INT(self));
167 }
168 
173 static PN potion_int_bitl(Potion *P, PN cl, PN self, PN num) {
174  return PN_NUM(PN_INT(self) << PN_INT(num));
175 }
176 
181 static PN potion_int_bitr(Potion *P, PN cl, PN self, PN num) {
182  return PN_NUM(PN_INT(self) >> PN_INT(num));
183 }
187 PN potion_int_string(Potion *P, PN cl, PN self) {
188  char ints[40];
189  sprintf(ints, "%ld", PN_INT(self));
190  return potion_str(P, ints);
191 }
192 
196 static PN potion_num_number(Potion *P, PN cl, PN self) {
197  return self;
198 }
202 static PN potion_num_double(Potion *P, PN cl, PN self) {
203  if (PN_IS_INT(self))
204  return potion_double(P, (double)PN_INT(self));
205  else
206  return self;
207 }
211 static PN potion_num_integer(Potion *P, PN cl, PN self) {
212  if (PN_IS_INT(self))
213  return self;
214  else
215  return PN_NUM(floor(((struct PNDouble *)self)->value));
216 }
221 static PN potion_dbl_add(Potion *P, PN cl, PN self, PN num) { PN_DBL_MATH(+) }
226 static PN potion_dbl_sub(Potion *P, PN cl, PN self, PN num) { PN_DBL_MATH(-) }
231 static PN potion_dbl_mult(Potion *P, PN cl, PN self, PN num) { PN_DBL_MATH(*) }
236 static PN potion_dbl_div(Potion *P, PN cl, PN self, PN num) { PN_DBL_MATH(/) }
237 
241 PN potion_dbl_string(Potion *P, PN cl, PN self) {
242  char ints[40];
243  int len = sprintf(ints, "%.16f", ((struct PNDouble *)self)->value);
244  while (len > 0 && ints[len - 1] == '0') len--;
245  if (ints[len - 1] == '.') len++;
246  ints[len] = '\0';
247  return potion_str(P, ints);
248 }
252 PN potion_num_string(Potion *P, PN cl, PN self) {
253  char ints[40];
254  if (PN_IS_INT(self)) {
255  sprintf(ints, "%ld", PN_INT(self));
256  } else {
257  int len = sprintf(ints, "%.16f", ((struct PNDouble *)self)->value);
258  while (len > 0 && ints[len - 1] == '0') len--;
259  if (ints[len - 1] == '.') len++;
260  ints[len] = '\0';
261  }
262  return potion_str(P, ints);
263 }
282 static PN potion_int_times(Potion *P, PN cl, PN self, PN block) {
283  long i, j = PN_INT(self);
284  PN_CHECK_INT(self);
285  //PN_CHECK_CLOSURE(block);
286  if (PN_TYPE(block) != PN_TCLOSURE)
287  potion_fatal("block argument for times is not a closure");
288  for (i = 0; i < j; i++)
289  PN_CLOSURE(block)->method(P, block, P->lobby, PN_NUM(i));
290  return PN_NUM(i);
291 }
299 static PN potion_int_to(Potion *P, PN cl, PN self, PN end, PN block) {
300  long i, s = 1, j = PN_INT(self), k = PN_INT(end);
301  PN_CHECK_INT(self);
302  PN_CHECK_INT(end);
303  if (k < j) s = -1;
304  if (PN_TYPE(block) != PN_TCLOSURE)
305  potion_fatal("block argument for to is not a closure");
306  for (i = j; i != k + s; i += s)
307  PN_CLOSURE(block)->method(P, block, P->lobby, PN_NUM(i));
308  return PN_NUM(labs(i - j));
309 }
317 static PN potion_int_step(Potion *P, PN cl, PN self, PN end, PN step, PN block) {
318  long i, j = PN_INT(end), k = PN_INT(step);
319  PN_CHECK_INT(self);
320  PN_CHECK_INT(end);
321  PN_CHECK_INT(step);
322  if (PN_TYPE(block) != PN_TCLOSURE)
323  potion_fatal("block argument for step is not a closure");
324  for (i = PN_INT(self); i <= j; i += k) {
325  PN_CLOSURE(block)->method(P, block, P->lobby, PN_NUM(i));
326  }
327  return PN_NUM(labs(i - j) / k);
328 }
329 
333 static PN potion_int_chr(Potion *P, PN cl, PN self) {
334  char c = PN_INT(self);
335  DBG_CHECK_INT(self);
336  return PN_STRN(&c, 1);
337 }
341 static PN potion_num_is_number(Potion *P, PN cl, PN self) {
342  return (PN_IS_INT(self) || PN_IS_DBL(self)) ? PN_TRUE : PN_FALSE;
343 }
347 static PN potion_num_is_integer(Potion *P, PN cl, PN self) {
348  return PN_IS_INT(self) ? PN_TRUE : PN_FALSE;
349 }
353 static PN potion_num_is_double(Potion *P, PN cl, PN self) {
354  return PN_IS_DBL(self) ? PN_TRUE : PN_FALSE;
355 }
359 static PN potion_num_abs(Potion *P, PN cl, PN self) {
360  DBG_CHECK_NUM(self);
361  if (PN_IS_DBL(self)) {
362  double d = PN_DBL(self);
363  if (d < 0.0)
364  return (PN) potion_double(P, -d);
365  else
366  return self;
367  }
368  return PN_NUM(labs(PN_INT(self)));
369 }
373 static PN potion_int_abs(Potion *P, PN cl, PN self) {
374  PN_CHECK_INT(self);
375  return PN_NUM(labs(PN_INT(self)));
376 }
380 static PN potion_dbl_abs(Potion *P, PN cl, PN self) {
381  double d = PN_DBL(self);
382  DBG_CHECK_NUM(self);
383  if (d < 0.0)
384  return (PN) potion_double(P, -d);
385  else
386  return self;
387 }
396 static PN potion_num_cmp(Potion *P, PN cl, PN self, PN n) {
397  if (PN_IS_DBL(self)) {
398  double d1 = ((struct PNDouble *)self)->value;
399  double d2 = PN_DBL(potion_send(PN_number, n));
400  return d1 < d2 ? PN_NUM(-1) : d1 == d2 ? PN_ZERO : PN_NUM(1);
401  } else {
402  long n1, n2;
403  n1 = PN_INT(self);
404  n2 = PN_IS_INT(n) ? PN_INT(n) : PN_INT(potion_send(PN_number, n));
405  return n1 < n2 ? PN_NUM(-1) : n1 == n2 ? PN_ZERO : PN_NUM(1);
406  }
407 }
415 static PN potion_dbl_cmp(Potion *P, PN cl, PN self, PN n) {
416  double d1 = ((struct PNDouble *)self)->value;
417  double d2 = PN_DBL(n);
418  DBG_CHECK_DBL(self);
419  PN_CHECK_NUM(n);
420  return d1 < d2 ? PN_NUM(-1) : d1 == d2 ? PN_ZERO : PN_NUM(1);
421 }
430 static PN potion_int_cmp(Potion *P, PN cl, PN self, PN n) {
431  long n1, n2;
432  DBG_CHECK_INT(self);
433  DBG_CHECK_INT(n);
434  n1 = PN_INT(self);
435  n2 = PN_INT(n);
436  return n1 < n2 ? PN_NUM(-1) : n1 == n2 ? PN_ZERO : PN_NUM(1);
437 }
438 
440  PN num_vt = PN_VTABLE(PN_TNUMBER);
441  PN dbl_vt = PN_VTABLE(PN_TDOUBLE);
442  PN int_vt = PN_VTABLE(PN_TINTEGER);
443  potion_method(num_vt, "+", potion_num_add, "value=N");
444  potion_method(num_vt, "-", potion_num_sub, "value=N");
445  potion_method(num_vt, "*", potion_num_mult, "value=N");
446  potion_method(num_vt, "/", potion_num_div, "value=N");
447  potion_method(num_vt, "%", potion_num_rem, "value=N");
448  potion_method(num_vt, "~", potion_num_bitn, 0);
449  potion_method(num_vt, "<<", potion_num_bitl, "value=N");
450  potion_method(num_vt, ">>", potion_num_bitr, "value=N");
451  potion_method(num_vt, "**", potion_num_pow, "value=N");
452  potion_method(num_vt, "abs", potion_num_abs, 0);
453  potion_method(num_vt, "sqrt", potion_num_sqrt, 0);
454  potion_method(num_vt, "cmp", potion_num_cmp, "value=o");
455  potion_method(num_vt, "chr", potion_int_chr, 0);
456  potion_method(num_vt, "string", potion_num_string, 0);
457  potion_method(num_vt, "number", potion_num_number, 0);
458  potion_method(num_vt, "integer", potion_num_integer, 0);
459  potion_method(num_vt, "double", potion_num_double, 0);
460  potion_method(num_vt, "number?", potion_num_is_number, 0);
461  potion_method(num_vt, "integer?", potion_num_is_integer, 0);
462  potion_method(num_vt, "double?", potion_num_is_double, 0);
463  potion_method(num_vt, "rand", potion_num_rand, 0);
464  // optimized double-only methods, for both operands
465  potion_method(dbl_vt, "string", potion_dbl_string, 0);
466  potion_method(dbl_vt, "+", potion_dbl_add, "value=D");
467  potion_method(dbl_vt, "-", potion_dbl_sub, "value=D");
468  potion_method(dbl_vt, "*", potion_dbl_mult, "value=D");
469  potion_method(dbl_vt, "/", potion_dbl_div, "value=D");
470  potion_method(dbl_vt, "abs", potion_dbl_abs, 0);
471  potion_method(dbl_vt, "cmp", potion_dbl_cmp, "value=D");
472  //potion_method(dbl_vt, "rand", potion_dbl_rand, 0);
473  // optimized integer-only methods, for both operands
474  potion_method(int_vt, "+", potion_int_add, "value=I");
475  potion_method(int_vt, "-", potion_int_sub, "value=I");
476  potion_method(int_vt, "*", potion_int_mult, "value=I");
477  potion_method(int_vt, "/", potion_int_div, "value=I");
478  potion_method(int_vt, "%", potion_int_rem, "value=I");
479  potion_method(int_vt, "<<", potion_int_bitl, "value=I");
480  potion_method(int_vt, ">>", potion_int_bitr, "value=I");
481  potion_method(int_vt, "~", potion_int_bitn, 0);
482  potion_method(int_vt, "chr", potion_int_chr, 0);
483  potion_method(int_vt, "abs", potion_int_abs, 0);
484  potion_method(int_vt, "cmp", potion_int_cmp, "value=I");
485  //potion_method(int_vt, "rand", potion_int_rand, 0);
486  potion_method(num_vt, "step", potion_int_step, "end=N,step=N,block=&");
487  potion_method(num_vt, "times", potion_int_times, "block=&");
488  potion_method(num_vt, "to", potion_int_to, "end=N,block=&");
489 }
PN potion_num_string(Potion *, PN, PN)
PN potion_str(Potion *, const char *)
Definition: string.c:33
PN potion_double(Potion *P, double v)
new PNDouble (double)
Definition: number.c:17
#define vPN(t)
Definition: potion.h:132
#define PN_TCLOSURE
Definition: potion.h:114
#define PN_ALLOC_N(V, T, C)
Definition: internal.h:13
#define PN_CLOSURE(x)
Definition: potion.h:216
static PN potion_dbl_div(Potion *P, PN cl, PN self, PN num)
Definition: number.c:236
#define PN_INT_MATH(math_op)
Definition: number.c:53
static PN potion_dbl_mult(Potion *P, PN cl, PN self, PN num)
Definition: number.c:231
#define potion_method(RCV, MSG, FN, SIG)
Definition: potion.h:780
static PN potion_dbl_add(Potion *P, PN cl, PN self, PN num)
Definition: number.c:221
void potion_num_init(Potion *P)
Definition: number.c:439
static PN potion_dbl_sub(Potion *P, PN cl, PN self, PN num)
Definition: number.c:226
#define PN_TINTEGER
Definition: potion.h:111
#define PN_INT(x)
Definition: potion.h:205
#define PN_ZERO
Definition: potion.h:140
#define PN_NUM(i)
Definition: potion.h:204
PN potion_num_pow(Potion *, PN, PN, PN)
static PN potion_int_abs(Potion *P, PN cl, PN self)
Definition: number.c:373
PN lobby
root namespace
Definition: potion.h:648
PN potion_num_rand(Potion *P, PN cl, PN self)
Definition: mt19937ar.c:182
#define PN_DBL(num)
Definition: potion.h:206
#define PN_TDOUBLE
Definition: potion.h:110
static PN potion_int_mult(Potion *P, PN cl, PN self, PN num)
Definition: number.c:149
#define DBG_CHECK_DBL(obj)
Definition: potion.h:189
#define PN_FALSE
Definition: potion.h:141
static PN potion_int_div(Potion *P, PN cl, PN self, PN num)
Definition: number.c:154
#define DBG_CHECK_INT(obj)
Definition: potion.h:188
#define PN_TRUE
Definition: potion.h:142
#define PN_IS_DBL(v)
Definition: potion.h:163
static PN potion_int_cmp(Potion *P, PN cl, PN self, PN n)
Definition: number.c:430
non-API internal parts
PN potion_strtod(Potion *P, char *str, int len)
Convert string to double.
Definition: number.c:24
#define PN_CHECK_INT(obj)
Definition: potion.h:178
#define DBG_CHECK_NUM(obj)
Definition: potion.h:187
static PN potion_int_bitr(Potion *P, PN cl, PN self, PN num)
Definition: number.c:181
the global interpreter state P. currently singleton (not threads yet)
Definition: potion.h:644
The potion API.
PN potion_int_string(Potion *P, PN cl, PN self)
Definition: number.c:187
#define PN_TYPE(x)
Definition: potion.h:133
#define PN_CHECK_NUM(obj)
Definition: potion.h:177
#define PN_IS_INT(v)
Definition: potion.h:162
#define PN_NUM_MATH(math_op)
Definition: number.c:47
PN PN_number
Definition: internal.c:18
static PN potion_int_bitn(Potion *P, PN cl, PN self)
Definition: number.c:165
#define potion_send(RCV, MSG, ARGS...)
method caches (more great stuff from ian piumarta)
Definition: potion.h:772
doubles are floating point numbers stored as binary data.
Definition: potion.h:352
#define PN_STRN(x, l)
Definition: potion.h:211
static PN potion_dbl_abs(Potion *P, PN cl, PN self)
Definition: number.c:380
volatile _PN PN
Definition: potion.h:81
#define PN_TNUMBER
Definition: potion.h:108
static PN potion_int_sub(Potion *P, PN cl, PN self, PN num)
Definition: number.c:144
static PN potion_dbl_cmp(Potion *P, PN cl, PN self, PN n)
Definition: number.c:415
static PN potion_int_add(Potion *P, PN cl, PN self, PN num)
Definition: number.c:139
void potion_fatal(char *message)
Definition: internal.c:282
#define PN_DBL_MATH(math_op)
Definition: number.c:57
#define PN_VTABLE(t)
Definition: potion.h:136
static PN potion_int_bitl(Potion *P, PN cl, PN self, PN num)
Definition: number.c:173
PN potion_dbl_string(Potion *P, PN cl, PN self)
Definition: number.c:241