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_pos_one;
cell bignum_neg_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())))); 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()))); 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 /* Division can only overflow when we are dividing the most negative fixnum
by -1. */ by -1. */
PRIMITIVE(fixnum_divint) inline void factorvm::vmprim_fixnum_divint()
{ {
fixnum y = untag_fixnum(dpop()); \ fixnum y = untag_fixnum(dpop()); \
fixnum x = untag_fixnum(dpeek()); fixnum x = untag_fixnum(dpeek());
@ -30,7 +40,12 @@ PRIMITIVE(fixnum_divint)
drepl(tag_fixnum(result)); 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 y = ((cell *)ds)[0];
cell x = ((cell *)ds)[-1]; 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 * 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. * 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); 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))); 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); 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 y = untag_fixnum(dpop());
fixnum x = untag_fixnum(dpeek()); fixnum x = untag_fixnum(dpeek());
@ -92,51 +127,91 @@ PRIMITIVE(fixnum_shift)
fixnum_to_bignum(x),y))); 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())))); 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()))); drepl(tag<bignum>(float_to_bignum(dpeek())));
} }
PRIMITIVE(float_to_bignum)
{
PRIMITIVE_GETVM()->vmprim_float_to_bignum();
}
#define POP_BIGNUMS(x,y) \ #define POP_BIGNUMS(x,y) \
bignum * y = untag<bignum>(dpop()); \ bignum * y = untag<bignum>(dpop()); \
bignum * x = untag<bignum>(dpop()); bignum * x = untag<bignum>(dpop());
PRIMITIVE(bignum_eq) inline void factorvm::vmprim_bignum_eq()
{ {
POP_BIGNUMS(x,y); POP_BIGNUMS(x,y);
box_boolean(bignum_equal_p(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); POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_add(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); POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_subtract(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); POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_multiply(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); POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_quotient(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; bignum *q, *r;
POP_BIGNUMS(x,y); POP_BIGNUMS(x,y);
@ -145,91 +220,166 @@ PRIMITIVE(bignum_divmod)
dpush(tag<bignum>(r)); 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); POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_remainder(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); POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_bitwise_and(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); POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_bitwise_ior(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); POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_bitwise_xor(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()); fixnum y = untag_fixnum(dpop());
bignum* x = untag<bignum>(dpop()); bignum* x = untag<bignum>(dpop());
dpush(tag<bignum>(bignum_arithmetic_shift(x,y))); 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); POP_BIGNUMS(x,y);
box_boolean(bignum_compare(x,y) == bignum_comparison_less); 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); POP_BIGNUMS(x,y);
box_boolean(bignum_compare(x,y) != bignum_comparison_greater); 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); POP_BIGNUMS(x,y);
box_boolean(bignum_compare(x,y) == bignum_comparison_greater); 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); POP_BIGNUMS(x,y);
box_boolean(bignum_compare(x,y) != bignum_comparison_less); 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())))); 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()); fixnum bit = to_fixnum(dpop());
bignum *x = untag<bignum>(dpop()); bignum *x = untag<bignum>(dpop());
box_boolean(bignum_logbitp(bit,x)); 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())))); 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()); unsigned char *ptr = (unsigned char *)alien_offset(dpeek());
return *(ptr + digit); 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())); 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)); drepl(tag<bignum>(result));
} }
PRIMITIVE(byte_array_to_bignum)
{
PRIMITIVE_GETVM()->vmprim_byte_array_to_bignum();
}
cell unbox_array_size() cell unbox_array_size()
{ {
switch(tagged<object>(dpeek()).type()) switch(tagged<object>(dpeek()).type())

View File

@ -244,6 +244,38 @@ struct factorvm {
void update_word_xt(cell w_); void update_word_xt(cell w_);
inline void vmprim_optimized_p(); inline void vmprim_optimized_p();
inline void vmprim_wrapper(); 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: // next method here: