Dev checkpoint

db4
Phil Dawes 2009-08-17 21:37:07 +01:00
parent 4f4c53c822
commit 552b9ecd81
2 changed files with 213 additions and 31 deletions

212
vm/math.cpp Normal file → Executable file
View File

@ -7,19 +7,29 @@ cell bignum_zero;
cell bignum_pos_one;
cell bignum_neg_one;
PRIMITIVE(bignum_to_fixnum)
inline void factorvm::vmprim_bignum_to_fixnum()
{
drepl(tag_fixnum(bignum_to_fixnum(untag<bignum>(dpeek()))));
}
PRIMITIVE(float_to_fixnum)
PRIMITIVE(bignum_to_fixnum)
{
PRIMITIVE_GETVM()->vmprim_bignum_to_fixnum();
}
inline void factorvm::vmprim_float_to_fixnum()
{
drepl(tag_fixnum(float_to_fixnum(dpeek())));
}
PRIMITIVE(float_to_fixnum)
{
PRIMITIVE_GETVM()->vmprim_float_to_fixnum();
}
/* Division can only overflow when we are dividing the most negative fixnum
by -1. */
PRIMITIVE(fixnum_divint)
inline void factorvm::vmprim_fixnum_divint()
{
fixnum y = untag_fixnum(dpop()); \
fixnum x = untag_fixnum(dpeek());
@ -30,7 +40,12 @@ PRIMITIVE(fixnum_divint)
drepl(tag_fixnum(result));
}
PRIMITIVE(fixnum_divmod)
PRIMITIVE(fixnum_divint)
{
PRIMITIVE_GETVM()->vmprim_fixnum_divint();
}
inline void factorvm::vmprim_fixnum_divmod()
{
cell y = ((cell *)ds)[0];
cell x = ((cell *)ds)[-1];
@ -46,26 +61,46 @@ PRIMITIVE(fixnum_divmod)
}
}
PRIMITIVE(fixnum_divmod)
{
PRIMITIVE_GETVM()->vmprim_fixnum_divmod();
}
/*
* If we're shifting right by n bits, we won't overflow as long as none of the
* high WORD_SIZE-TAG_BITS-n bits are set.
*/
static inline fixnum sign_mask(fixnum x)
inline fixnum factorvm::sign_mask(fixnum x)
{
return x >> (WORD_SIZE - 1);
}
static inline fixnum branchless_max(fixnum x, fixnum y)
inline fixnum sign_mask(fixnum x)
{
return vm->sign_mask(x);
}
inline fixnum factorvm::branchless_max(fixnum x, fixnum y)
{
return (x - ((x - y) & sign_mask(x - y)));
}
static inline fixnum branchless_abs(fixnum x)
inline fixnum branchless_max(fixnum x, fixnum y)
{
return vm->branchless_max(x,y);
}
inline fixnum factorvm::branchless_abs(fixnum x)
{
return (x ^ sign_mask(x)) - sign_mask(x);
}
PRIMITIVE(fixnum_shift)
inline fixnum branchless_abs(fixnum x)
{
return vm->branchless_abs(x);
}
inline void factorvm::vmprim_fixnum_shift()
{
fixnum y = untag_fixnum(dpop());
fixnum x = untag_fixnum(dpeek());
@ -92,51 +127,91 @@ PRIMITIVE(fixnum_shift)
fixnum_to_bignum(x),y)));
}
PRIMITIVE(fixnum_to_bignum)
PRIMITIVE(fixnum_shift)
{
PRIMITIVE_GETVM()->vmprim_fixnum_shift();
}
inline void factorvm::vmprim_fixnum_to_bignum()
{
drepl(tag<bignum>(fixnum_to_bignum(untag_fixnum(dpeek()))));
}
PRIMITIVE(float_to_bignum)
PRIMITIVE(fixnum_to_bignum)
{
PRIMITIVE_GETVM()->vmprim_fixnum_to_bignum();
}
inline void factorvm::vmprim_float_to_bignum()
{
drepl(tag<bignum>(float_to_bignum(dpeek())));
}
PRIMITIVE(float_to_bignum)
{
PRIMITIVE_GETVM()->vmprim_float_to_bignum();
}
#define POP_BIGNUMS(x,y) \
bignum * y = untag<bignum>(dpop()); \
bignum * x = untag<bignum>(dpop());
PRIMITIVE(bignum_eq)
inline void factorvm::vmprim_bignum_eq()
{
POP_BIGNUMS(x,y);
box_boolean(bignum_equal_p(x,y));
}
PRIMITIVE(bignum_add)
PRIMITIVE(bignum_eq)
{
PRIMITIVE_GETVM()->vmprim_bignum_eq();
}
inline void factorvm::vmprim_bignum_add()
{
POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_add(x,y)));
}
PRIMITIVE(bignum_subtract)
PRIMITIVE(bignum_add)
{
PRIMITIVE_GETVM()->vmprim_bignum_add();
}
inline void factorvm::vmprim_bignum_subtract()
{
POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_subtract(x,y)));
}
PRIMITIVE(bignum_multiply)
PRIMITIVE(bignum_subtract)
{
PRIMITIVE_GETVM()->vmprim_bignum_subtract();
}
inline void factorvm::vmprim_bignum_multiply()
{
POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_multiply(x,y)));
}
PRIMITIVE(bignum_divint)
PRIMITIVE(bignum_multiply)
{
PRIMITIVE_GETVM()->vmprim_bignum_multiply();
}
inline void factorvm::vmprim_bignum_divint()
{
POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_quotient(x,y)));
}
PRIMITIVE(bignum_divmod)
PRIMITIVE(bignum_divint)
{
PRIMITIVE_GETVM()->vmprim_bignum_divint();
}
inline void factorvm::vmprim_bignum_divmod()
{
bignum *q, *r;
POP_BIGNUMS(x,y);
@ -145,91 +220,166 @@ PRIMITIVE(bignum_divmod)
dpush(tag<bignum>(r));
}
PRIMITIVE(bignum_mod)
PRIMITIVE(bignum_divmod)
{
PRIMITIVE_GETVM()->vmprim_bignum_divmod();
}
inline void factorvm::vmprim_bignum_mod()
{
POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_remainder(x,y)));
}
PRIMITIVE(bignum_and)
PRIMITIVE(bignum_mod)
{
PRIMITIVE_GETVM()->vmprim_bignum_mod();
}
inline void factorvm::vmprim_bignum_and()
{
POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_bitwise_and(x,y)));
}
PRIMITIVE(bignum_or)
PRIMITIVE(bignum_and)
{
PRIMITIVE_GETVM()->vmprim_bignum_and();
}
inline void factorvm::vmprim_bignum_or()
{
POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_bitwise_ior(x,y)));
}
PRIMITIVE(bignum_xor)
PRIMITIVE(bignum_or)
{
PRIMITIVE_GETVM()->vmprim_bignum_or();
}
inline void factorvm::vmprim_bignum_xor()
{
POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_bitwise_xor(x,y)));
}
PRIMITIVE(bignum_shift)
PRIMITIVE(bignum_xor)
{
PRIMITIVE_GETVM()->vmprim_bignum_xor();
}
inline void factorvm::vmprim_bignum_shift()
{
fixnum y = untag_fixnum(dpop());
bignum* x = untag<bignum>(dpop());
dpush(tag<bignum>(bignum_arithmetic_shift(x,y)));
}
PRIMITIVE(bignum_less)
PRIMITIVE(bignum_shift)
{
PRIMITIVE_GETVM()->vmprim_bignum_shift();
}
inline void factorvm::vmprim_bignum_less()
{
POP_BIGNUMS(x,y);
box_boolean(bignum_compare(x,y) == bignum_comparison_less);
}
PRIMITIVE(bignum_lesseq)
PRIMITIVE(bignum_less)
{
PRIMITIVE_GETVM()->vmprim_bignum_less();
}
inline void factorvm::vmprim_bignum_lesseq()
{
POP_BIGNUMS(x,y);
box_boolean(bignum_compare(x,y) != bignum_comparison_greater);
}
PRIMITIVE(bignum_greater)
PRIMITIVE(bignum_lesseq)
{
PRIMITIVE_GETVM()->vmprim_bignum_lesseq();
}
inline void factorvm::vmprim_bignum_greater()
{
POP_BIGNUMS(x,y);
box_boolean(bignum_compare(x,y) == bignum_comparison_greater);
}
PRIMITIVE(bignum_greatereq)
PRIMITIVE(bignum_greater)
{
PRIMITIVE_GETVM()->vmprim_bignum_greater();
}
inline void factorvm::vmprim_bignum_greatereq()
{
POP_BIGNUMS(x,y);
box_boolean(bignum_compare(x,y) != bignum_comparison_less);
}
PRIMITIVE(bignum_not)
PRIMITIVE(bignum_greatereq)
{
PRIMITIVE_GETVM()->vmprim_bignum_greatereq();
}
inline void factorvm::vmprim_bignum_not()
{
drepl(tag<bignum>(bignum_bitwise_not(untag<bignum>(dpeek()))));
}
PRIMITIVE(bignum_bitp)
PRIMITIVE(bignum_not)
{
PRIMITIVE_GETVM()->vmprim_bignum_not();
}
inline void factorvm::vmprim_bignum_bitp()
{
fixnum bit = to_fixnum(dpop());
bignum *x = untag<bignum>(dpop());
box_boolean(bignum_logbitp(bit,x));
}
PRIMITIVE(bignum_log2)
PRIMITIVE(bignum_bitp)
{
PRIMITIVE_GETVM()->vmprim_bignum_bitp();
}
inline void factorvm::vmprim_bignum_log2()
{
drepl(tag<bignum>(bignum_integer_length(untag<bignum>(dpeek()))));
}
unsigned int bignum_producer(unsigned int digit)
PRIMITIVE(bignum_log2)
{
PRIMITIVE_GETVM()->vmprim_bignum_log2();
}
unsigned int factorvm::bignum_producer(unsigned int digit)
{
unsigned char *ptr = (unsigned char *)alien_offset(dpeek());
return *(ptr + digit);
}
PRIMITIVE(byte_array_to_bignum)
unsigned int bignum_producer(unsigned int digit)
{
return vm->bignum_producer(digit);
}
inline void factorvm::vmprim_byte_array_to_bignum()
{
cell n_digits = array_capacity(untag_check<byte_array>(dpeek()));
bignum * result = digit_stream_to_bignum(n_digits,bignum_producer,0x100,0);
bignum * result = factor::digit_stream_to_bignum(n_digits,factor::bignum_producer,0x100,0);
drepl(tag<bignum>(result));
}
PRIMITIVE(byte_array_to_bignum)
{
PRIMITIVE_GETVM()->vmprim_byte_array_to_bignum();
}
cell unbox_array_size()
{
switch(tagged<object>(dpeek()).type())

View File

@ -244,6 +244,38 @@ struct factorvm {
void update_word_xt(cell w_);
inline void vmprim_optimized_p();
inline void vmprim_wrapper();
//math
inline void vmprim_bignum_to_fixnum();
inline void vmprim_float_to_fixnum();
inline void vmprim_fixnum_divint();
inline void vmprim_fixnum_divmod();
inline fixnum sign_mask(fixnum x);
inline fixnum branchless_max(fixnum x, fixnum y);
inline fixnum branchless_abs(fixnum x);
inline void vmprim_fixnum_shift();
inline void vmprim_fixnum_to_bignum();
inline void vmprim_float_to_bignum();
inline void vmprim_bignum_eq();
inline void vmprim_bignum_add();
inline void vmprim_bignum_subtract();
inline void vmprim_bignum_multiply();
inline void vmprim_bignum_divint();
inline void vmprim_bignum_divmod();
inline void vmprim_bignum_mod();
inline void vmprim_bignum_and();
inline void vmprim_bignum_or();
inline void vmprim_bignum_xor();
inline void vmprim_bignum_shift();
inline void vmprim_bignum_less();
inline void vmprim_bignum_lesseq();
inline void vmprim_bignum_greater();
inline void vmprim_bignum_greatereq();
inline void vmprim_bignum_not();
inline void vmprim_bignum_bitp();
inline void vmprim_bignum_log2();
unsigned int bignum_producer(unsigned int digit);
inline void vmprim_byte_array_to_bignum();
// next method here: