4 F_FIXNUM
to_fixnum(CELL tagged
)
9 return untag_fixnum_fast(tagged
);
11 return bignum_to_fixnum(untag_object(tagged
));
13 type_error(FIXNUM_TYPE
,tagged
);
14 return -1; /* can't happen */
18 CELL
to_cell(CELL tagged
)
20 return (CELL
)to_fixnum(tagged
);
23 void primitive_bignum_to_fixnum(void)
25 drepl(tag_fixnum(bignum_to_fixnum(untag_object(dpeek()))));
28 void primitive_float_to_fixnum(void)
30 drepl(tag_fixnum(float_to_fixnum(dpeek())));
33 /* The fixnum+, fixnum- and fixnum* primitives are defined in cpu_*.S. On
34 overflow, they call these functions. */
35 F_FASTCALL
void overflow_fixnum_add(F_FIXNUM x
, F_FIXNUM y
)
37 drepl(tag_bignum(fixnum_to_bignum(
38 untag_fixnum_fast(x
) + untag_fixnum_fast(y
))));
41 F_FASTCALL
void overflow_fixnum_subtract(F_FIXNUM x
, F_FIXNUM y
)
43 drepl(tag_bignum(fixnum_to_bignum(
44 untag_fixnum_fast(x
) - untag_fixnum_fast(y
))));
47 F_FASTCALL
void overflow_fixnum_multiply(F_FIXNUM x
, F_FIXNUM y
)
49 F_ARRAY
*bx
= fixnum_to_bignum(x
);
51 F_ARRAY
*by
= fixnum_to_bignum(y
);
52 UNREGISTER_BIGNUM(bx
);
53 drepl(tag_bignum(bignum_multiply(bx
,by
)));
56 /* Division can only overflow when we are dividing the most negative fixnum
58 void primitive_fixnum_divint(void)
60 F_FIXNUM y
= untag_fixnum_fast(dpop()); \
61 F_FIXNUM x
= untag_fixnum_fast(dpeek());
62 F_FIXNUM result
= x
/ y
;
63 if(result
== -FIXNUM_MIN
)
64 drepl(allot_integer(-FIXNUM_MIN
));
66 drepl(tag_fixnum(result
));
69 void primitive_fixnum_divmod(void)
72 F_FIXNUM x
= get(ds
- CELLS
);
73 if(y
== tag_fixnum(-1) && x
== tag_fixnum(FIXNUM_MIN
))
75 put(ds
- CELLS
,allot_integer(-FIXNUM_MIN
));
76 put(ds
,tag_fixnum(0));
80 put(ds
- CELLS
,tag_fixnum(x
/ y
));
86 * If we're shifting right by n bits, we won't overflow as long as none of the
87 * high WORD_SIZE-TAG_BITS-n bits are set.
89 #define SIGN_MASK(x) ((x) >> (WORD_SIZE - 1))
90 #define BRANCHLESS_MAX(x,y) ((x) - (((x) - (y)) & SIGN_MASK((x) - (y))))
91 #define BRANCHLESS_ABS(x) ((x ^ SIGN_MASK(x)) - SIGN_MASK(x))
93 void primitive_fixnum_shift(void)
95 F_FIXNUM y
= untag_fixnum_fast(dpop()); \
96 F_FIXNUM x
= untag_fixnum_fast(dpeek());
102 y
= BRANCHLESS_MAX(y
,-WORD_SIZE
+ 1);
103 drepl(tag_fixnum(x
>> -y
));
106 else if(y
< WORD_SIZE
- TAG_BITS
)
108 F_FIXNUM mask
= -((F_FIXNUM
)1 << (WORD_SIZE
- 1 - TAG_BITS
- y
));
109 if(!(BRANCHLESS_ABS(x
) & mask
))
111 drepl(tag_fixnum(x
<< y
));
116 drepl(tag_bignum(bignum_arithmetic_shift(
117 fixnum_to_bignum(x
),y
)));
121 void primitive_fixnum_to_bignum(void)
123 drepl(tag_bignum(fixnum_to_bignum(untag_fixnum_fast(dpeek()))));
126 void primitive_float_to_bignum(void)
128 drepl(tag_bignum(float_to_bignum(dpeek())));
131 #define POP_BIGNUMS(x,y) \
132 F_ARRAY *y = untag_object(dpop()); \
133 F_ARRAY *x = untag_object(dpop());
135 void primitive_bignum_eq(void)
138 box_boolean(bignum_equal_p(x
,y
));
141 void primitive_bignum_add(void)
144 dpush(tag_bignum(bignum_add(x
,y
)));
147 void primitive_bignum_subtract(void)
150 dpush(tag_bignum(bignum_subtract(x
,y
)));
153 void primitive_bignum_multiply(void)
156 dpush(tag_bignum(bignum_multiply(x
,y
)));
159 void primitive_bignum_divint(void)
162 dpush(tag_bignum(bignum_quotient(x
,y
)));
165 void primitive_bignum_divmod(void)
169 bignum_divide(x
,y
,&q
,&r
);
170 dpush(tag_bignum(q
));
171 dpush(tag_bignum(r
));
174 void primitive_bignum_mod(void)
177 dpush(tag_bignum(bignum_remainder(x
,y
)));
180 void primitive_bignum_and(void)
183 dpush(tag_bignum(bignum_bitwise_and(x
,y
)));
186 void primitive_bignum_or(void)
189 dpush(tag_bignum(bignum_bitwise_ior(x
,y
)));
192 void primitive_bignum_xor(void)
195 dpush(tag_bignum(bignum_bitwise_xor(x
,y
)));
198 void primitive_bignum_shift(void)
200 F_FIXNUM y
= untag_fixnum_fast(dpop());
201 F_ARRAY
* x
= untag_object(dpop());
202 dpush(tag_bignum(bignum_arithmetic_shift(x
,y
)));
205 void primitive_bignum_less(void)
208 box_boolean(bignum_compare(x
,y
) == bignum_comparison_less
);
211 void primitive_bignum_lesseq(void)
214 box_boolean(bignum_compare(x
,y
) != bignum_comparison_greater
);
217 void primitive_bignum_greater(void)
220 box_boolean(bignum_compare(x
,y
) == bignum_comparison_greater
);
223 void primitive_bignum_greatereq(void)
226 box_boolean(bignum_compare(x
,y
) != bignum_comparison_less
);
229 void primitive_bignum_not(void)
231 drepl(tag_bignum(bignum_bitwise_not(untag_object(dpeek()))));
234 void primitive_bignum_bitp(void)
236 F_FIXNUM bit
= to_fixnum(dpop());
237 F_ARRAY
*x
= untag_object(dpop());
238 box_boolean(bignum_logbitp(bit
,x
));
241 void primitive_bignum_log2(void)
243 drepl(tag_bignum(bignum_integer_length(untag_object(dpeek()))));
246 unsigned int bignum_producer(unsigned int digit
)
248 unsigned char *ptr
= alien_offset(dpeek());
249 return *(ptr
+ digit
);
252 void primitive_byte_array_to_bignum(void)
254 type_check(BYTE_ARRAY_TYPE
,dpeek());
255 CELL n_digits
= array_capacity(untag_object(dpeek()));
256 bignum_type bignum
= digit_stream_to_bignum(
257 n_digits
,bignum_producer
,0x100,0);
258 drepl(tag_bignum(bignum
));
261 void box_signed_1(s8 n
)
263 dpush(tag_fixnum(n
));
266 void box_unsigned_1(u8 n
)
268 dpush(tag_fixnum(n
));
271 void box_signed_2(s16 n
)
273 dpush(tag_fixnum(n
));
276 void box_unsigned_2(u16 n
)
278 dpush(tag_fixnum(n
));
281 void box_signed_4(s32 n
)
283 dpush(allot_integer(n
));
286 void box_unsigned_4(u32 n
)
288 dpush(allot_cell(n
));
291 void box_signed_cell(F_FIXNUM integer
)
293 dpush(allot_integer(integer
));
296 void box_unsigned_cell(CELL cell
)
298 dpush(allot_cell(cell
));
301 void box_signed_8(s64 n
)
303 if(n
< FIXNUM_MIN
|| n
> FIXNUM_MAX
)
304 dpush(tag_bignum(long_long_to_bignum(n
)));
306 dpush(tag_fixnum(n
));
309 s64
to_signed_8(CELL obj
)
314 return untag_fixnum_fast(obj
);
316 return bignum_to_long_long(untag_object(obj
));
318 type_error(BIGNUM_TYPE
,obj
);
323 void box_unsigned_8(u64 n
)
326 dpush(tag_bignum(ulong_long_to_bignum(n
)));
328 dpush(tag_fixnum(n
));
331 u64
to_unsigned_8(CELL obj
)
336 return untag_fixnum_fast(obj
);
338 return bignum_to_ulong_long(untag_object(obj
));
340 type_error(BIGNUM_TYPE
,obj
);
345 CELL
unbox_array_size(void)
347 switch(type_of(dpeek()))
351 F_FIXNUM n
= untag_fixnum_fast(dpeek());
352 if(n
>= 0 && n
< ARRAY_SIZE_MAX
)
361 bignum_type zero
= untag_object(bignum_zero
);
362 bignum_type max
= cell_to_bignum(ARRAY_SIZE_MAX
);
363 bignum_type n
= untag_object(dpeek());
364 if(bignum_compare(n
,zero
) != bignum_comparison_less
365 && bignum_compare(n
,max
) == bignum_comparison_less
)
368 return bignum_to_cell(n
);
374 general_error(ERROR_ARRAY_SIZE
,dpop(),tag_fixnum(ARRAY_SIZE_MAX
),NULL
);
375 return 0; /* can't happen */
380 /* Does not reduce to lowest terms, so should only be used by math
381 library implementation, to avoid breaking invariants. */
382 void primitive_from_fraction(void)
384 F_RATIO
* ratio
= allot_object(RATIO_TYPE
,sizeof(F_RATIO
));
385 ratio
->denominator
= dpop();
386 ratio
->numerator
= dpop();
387 dpush(RETAG(ratio
,RATIO_TYPE
));
391 void primitive_fixnum_to_float(void)
393 drepl(allot_float(fixnum_to_float(dpeek())));
396 void primitive_bignum_to_float(void)
398 drepl(allot_float(bignum_to_float(dpeek())));
401 void primitive_str_to_float(void)
405 F_STRING
*str
= untag_string(dpeek());
406 CELL capacity
= string_capacity(str
);
408 c_str
= to_char_string(str
,false);
410 f
= strtod(c_str
,&end
);
411 if(end
!= c_str
+ capacity
)
414 drepl(allot_float(f
));
417 void primitive_float_to_str(void)
420 snprintf(tmp
,32,"%.16g",untag_float(dpop()));
422 box_char_string(tmp
);
425 #define POP_FLOATS(x,y) \
426 double y = untag_float_fast(dpop()); \
427 double x = untag_float_fast(dpop());
429 void primitive_float_eq(void)
435 void primitive_float_add(void)
441 void primitive_float_subtract(void)
447 void primitive_float_multiply(void)
453 void primitive_float_divfloat(void)
459 void primitive_float_mod(void)
462 box_double(fmod(x
,y
));
465 void primitive_float_less(void)
471 void primitive_float_lesseq(void)
477 void primitive_float_greater(void)
483 void primitive_float_greatereq(void)
489 void primitive_float_bits(void)
491 box_unsigned_4(float_bits(untag_float(dpop())));
494 void primitive_bits_float(void)
496 box_float(bits_float(to_cell(dpop())));
499 void primitive_double_bits(void)
501 box_unsigned_8(double_bits(untag_float(dpop())));
504 void primitive_bits_double(void)
506 box_double(bits_double(to_unsigned_8(dpop())));
509 float to_float(CELL value
)
511 return untag_float(value
);
514 double to_double(CELL value
)
516 return untag_float(value
);
519 void box_float(float flo
)
521 dpush(allot_float(flo
));
524 void box_double(double flo
)
526 dpush(allot_float(flo
));
529 /* Complex numbers */
531 void primitive_from_rect(void)
533 F_COMPLEX
* complex = allot_object(COMPLEX_TYPE
,sizeof(F_COMPLEX
));
534 complex->imaginary
= dpop();
535 complex->real
= dpop();
536 dpush(RETAG(complex,COMPLEX_TYPE
));