~ chicken-core (chicken-5) 635578967909374ad36782888059a5f023f5b900
commit 635578967909374ad36782888059a5f023f5b900 Author: felix <felix@call-with-current-continuation.org> AuthorDate: Fri Sep 3 07:13:35 2010 -0400 Commit: felix <felix@call-with-current-continuation.org> CommitDate: Fri Sep 3 07:13:35 2010 -0400 internal overflow-detection fixnum ops diff --git a/chicken.h b/chicken.h index 12633b14..5830ae3d 100644 --- a/chicken.h +++ b/chicken.h @@ -1811,6 +1811,8 @@ C_fctexport C_word C_fcall C_a_i_atan2(C_word **a, int c, C_word n1, C_word n2) C_fctexport C_word C_fcall C_a_i_sqrt(C_word **a, int c, C_word n) C_regparm; C_fctexport C_word C_fcall C_i_o_fixnum_plus(C_word x, C_word y) C_regparm; C_fctexport C_word C_fcall C_i_o_fixnum_difference(C_word x, C_word y) C_regparm; +C_fctexport C_word C_fcall C_i_o_fixnum_times(C_word x, C_word y) C_regparm; +C_fctexport C_word C_fcall C_i_o_fixnum_quotient(C_word x, C_word y) C_regparm; C_fctexport C_word C_fcall C_i_o_fixnum_and(C_word x, C_word y) C_regparm; C_fctexport C_word C_fcall C_i_o_fixnum_ior(C_word x, C_word y) C_regparm; C_fctexport C_word C_fcall C_i_o_fixnum_xor(C_word x, C_word y) C_regparm; diff --git a/library.scm b/library.scm index dc3cde45..bb738448 100644 --- a/library.scm +++ b/library.scm @@ -702,12 +702,14 @@ EOF (define (fxshr x y) (##core#inline "C_fixnum_shift_right" x y)) (define (fxodd? x) (##core#inline "C_i_fixnumoddp" x)) (define (fxeven? x) (##core#inline "C_i_fixnumevenp" x)) +(define (fx/ x y) (##core#inline "C_fixnum_divide" x y) ) +(define (fxmod x y) (##core#inline "C_fixnum_modulo" x y) ) -(define (fx/ x y) - (##core#inline "C_fixnum_divide" x y) ) - -(define (fxmod x y) - (##core#inline "C_fixnum_modulo" x y) ) +;; these are currently undocumented +(define (fx+? x y) (##core#inline "C_i_o_fixnum_plus" x y) ) +(define (fx-? x y) (##core#inline "C_i_o_fixnum_difference" x y) ) +(define (fx*? x y) (##core#inline "C_i_o_fixnum_times" x y) ) +(define (fx/? x y) (##core#inline "C_i_o_fixnum_quotient" x y) ) (define maximum-flonum (foreign-value "DBL_MAX" double)) (define minimum-flonum (foreign-value "DBL_MIN" double)) @@ -969,25 +971,22 @@ EOF (define max) (define min) -(let ([> >] ;XXX could use faster versions - [< <] ) - (letrec ([maxmin - (lambda (n1 ns pred) - (let loop ((nbest n1) (ns ns)) - (if (eq? ns '()) - nbest - (let ([ni (##sys#slot ns 0)]) - (loop (if (pred ni nbest) - (if (and (##core#inline "C_blockp" nbest) - (##core#inline "C_flonump" nbest) - (not (##core#inline "C_blockp" ni)) ) - (##core#inline_allocate ("C_a_i_fix_to_flo" 4) ni) - ni) - nbest) - (##sys#slot ns 1) ) ) ) ) ) ] ) - - (set! max (lambda (n1 . ns) (maxmin n1 ns >))) - (set! min (lambda (n1 . ns) (maxmin n1 ns <))) ) ) +(letrec ((maxmin + (lambda (n1 ns pred) + (let loop ((nbest n1) (ns ns)) + (if (eq? ns '()) + nbest + (let ([ni (##sys#slot ns 0)]) + (loop (if (pred ni nbest) + (if (and (##core#inline "C_blockp" nbest) + (##core#inline "C_flonump" nbest) + (not (##core#inline "C_blockp" ni)) ) + (##core#inline_allocate ("C_a_i_fix_to_flo" 4) ni) + ni) + nbest) + (##sys#slot ns 1) ) ) ) ) ) ) ) + (set! max (lambda (n1 . ns) (maxmin n1 ns >))) + (set! min (lambda (n1 . ns) (maxmin n1 ns <))) ) (define (exp n) (##core#inline_allocate ("C_a_i_exp" 4) n) ) diff --git a/runtime.c b/runtime.c index ca4de104..eee31556 100644 --- a/runtime.c +++ b/runtime.c @@ -8613,6 +8613,68 @@ C_regparm C_word C_fcall C_i_o_fixnum_difference(C_word n1, C_word n2) } +C_regparm C_word C_fcall C_i_o_fixnum_times(C_word n1, C_word n2) +{ + C_word x1, x2; + /* otherwise gcc tries to be smart (and naturally fails) */ +#ifdef C_SIXTY_FOUR + static int seven_f = 0x7fffffffffffffff; + static int eight_0 = 0x8000000000000000; +#else + static int seven_f = 0x7fffffff; + static int eight_0 = 0x80000000; +#endif + + if((n1 & C_FIXNUM_BIT) == 0 || (n2 & C_FIXNUM_BIT) == 0) return C_SCHEME_FALSE; + + x1 = C_unfix(n1); + x2 = C_unfix(n2); + + if(x1 > 0) { + if(x2 > 0) { + if(x1 > (seven_f / x2)) return C_SCHEME_FALSE; + else goto ok; + } + else { + if(x2 < (eight_0 / x2)) return C_SCHEME_FALSE; + else goto ok; + } + } + else if(x2 > 0) { + if(x1 < (eight_0 / x2)) return C_SCHEME_FALSE; + else goto ok; + } + else { + if(x1 != 0 && x2 < (seven_f / x1)) return C_SCHEME_FALSE; + } + + ok: + return C_fix(x1 * x2); +} + + +C_regparm C_word C_fcall C_i_o_fixnum_quotient(C_word n1, C_word n2) +{ + C_word x1, x2; + + if((n1 & C_FIXNUM_BIT) == 0 || (n2 & C_FIXNUM_BIT) == 0) return C_SCHEME_FALSE; + + x1 = C_unfix(n1); + x2 = C_unfix(n2); + + if(x2 == 0) + barf(C_DIVISION_BY_ZERO_ERROR, "fx/?"); + +#ifdef C_SIXYT_FOUR + if(x1 == 0x8000000000000000L && x2 == -1) return C_SCHEME_FALSE; +#else + if(x1 == 0x80000000L && x2 == -1) return C_SCHEME_FALSE; +#endif + + return C_fix(x1 / x2); +} + + C_regparm C_word C_fcall C_i_o_fixnum_and(C_word n1, C_word n2) { C_uword x1, x2, r;Trap