bignum-low.scm 3.2 KB

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