bignum-low.scm 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Martin Gasbichler, Marcus Crestani
  3. ; fixnum-as-bignum-length - the maximum bignum digits required to hold a fixnum
  4. ; From struct.scm:
  5. ; bignum-length - usual length operator, gives number of bytes
  6. ; bignum-size - space to hold a bignum of N bytes
  7. ; Defined here:
  8. ; bignum-digits - number of digits in a bignum
  9. ; bignum-digits->size - space to hold a bignum of N digits
  10. ; fixnum-as-bignum-digits - number of digits to hold a fixnum
  11. ; The first word in a bignum is used as a header by the C code.
  12. (define (bignum-digits bignum)
  13. (- (bytes->cells (bignum-length bignum)) 1))
  14. (define (bignum-digits->size n)
  15. (bignum-size (cells->bytes (+ n 1))))
  16. (define bignum-digit-bits s48-useful-bits-per-word) ; BIGNUM_DIGIT_LENGTH in bignumint.h
  17. (define (bignum-bits-to-digits n)
  18. (quotient (+ n (- bignum-digit-bits 1))
  19. bignum-digit-bits))
  20. (define (bignum-bits-to-size x)
  21. (bignum-digits->size (bignum-bits-to-digits x)))
  22. (define fixnum-as-bignum-digits (bignum-bits-to-digits bits-per-fixnum))
  23. (define fixnum-as-bignum-size (bignum-digits->size fixnum-as-bignum-digits))
  24. ;----------------------------------------------------------------
  25. ; Manipulating bignums.
  26. (define (extract-bignum desc)
  27. (assert (bignum? desc))
  28. (address-after-header desc))
  29. (define (enter-bignum external-bignum)
  30. (let ((desc (address->stob-descriptor external-bignum)))
  31. (if (not (bignum? desc))
  32. (error "not a bignum" desc))
  33. (make-immutable! desc)
  34. desc))
  35. (define (initialize-bignums)
  36. (ensure-bignum-space! (+ (bignum-digits->size 0) ; zero
  37. (bignum-digits->size 1) ; 1
  38. (bignum-digits->size 1))) ; -1
  39. (external-bignum-make-cached-constants))
  40. (define *bignum-preallocation-key* 0)
  41. (define (set-bignum-preallocation-key! key)
  42. (if (checking-preallocation?)
  43. (set! *bignum-preallocation-key* key)))
  44. (define (ensure-bignum-space! needed)
  45. (set-bignum-preallocation-key! (ensure-space needed)))
  46. (define (s48-allocate-bignum size)
  47. (make-b-vector (enum stob bignum)
  48. size
  49. *bignum-preallocation-key*))
  50. ; This doesn't use ENTER-BIGNUM because we need to preserve mutability
  51. ; until the entire bignum operation has completed.
  52. ;
  53. ; If the new size is smaller we change the length in the header and install a
  54. ; new header at the beginning of the now-unused bytes at the end.
  55. (define (s48-shorten-bignum external-bignum number-of-digits)
  56. (let* ((bignum (address->stob-descriptor external-bignum))
  57. (new-size (cells->bytes (bignum-digits->size number-of-digits)))
  58. (new-data-size (- new-size stob-overhead-in-bytes))
  59. (old-data-size (header-length-in-bytes (stob-header bignum)))
  60. (waste-size (- old-data-size new-data-size))
  61. (waste-data-size (- waste-size stob-overhead-in-bytes)))
  62. (if (< waste-size 0)
  63. (error "shorten bignum" new-data-size old-data-size))
  64. (if (<= stob-overhead-in-bytes waste-size)
  65. (begin
  66. (stob-header-set! bignum
  67. (make-header (enum stob bignum) new-data-size))
  68. (stob-header-set! (address->stob-descriptor
  69. (address+ (address-after-header bignum)
  70. (bytes->a-units new-size)))
  71. (make-header (enum stob bignum) waste-data-size))))
  72. external-bignum))
  73. (define stob-overhead-in-bytes (cells->bytes stob-overhead))