;; ----------------------------------------------------------------------
;;  SRFI 143...
;; ----------------------------------------------------------------------
;(test-subsection "SRFI 143 - fixnums")

(test "fixnum? 1" #t (fixnum? 32767))
(test "fixnum? 2" #f (fixnum? 1.1))

(test "fx=? 1" #t (fx=? 1 1 1))
(test "fx=? 2" #f (fx=? 1 2 2))
(test "fx=? 3" #f (fx=? 1 1 2))
(test "fx=? 4" #f (fx=? 1 2 3))
(test "fx=? 5" #t (fx=? 1))

(test "fx<? 1" #t (fx<? 1 2 3))
(test "fx<? 2" #f (fx<? 1 1 2))
(test "fx<? 3" #t (fx<? 1))
(test "fx>? 1" #t (fx>? 3 2 1))
(test "fx>? 2" #f (fx>? 2 1 1))
(test "fx>? 3" #t (fx>? 2))
(test "fx<=? 1" #t (fx<=? 1 1 2))
(test "fx<=? 2" #f (fx<=? 1 2 1))
(test "fx<=? 3" #t (fx<=? 1))
(test "fx>=? 1" #t (fx>=? 2 1 1))
(test "fx>=? 2" #f (fx>=? 1 2 1))
(test "fx>=? 3" #t (fx>=? 1))

(test "fx<=? 3" '(#t #f) (list (fx<=? 1 1 2) (fx<=? 2 1 3)))

(test "fxzero? 1" #t (fxzero? 0))
(test "fxzero? 2" #f (fxzero? 1))

(test "fxpositive? 1" #f (fxpositive? 0))
(test "fxpositive? 2" #t (fxpositive? 1))
(test "fxpositive? 3" #f (fxpositive? -1))

(test "fxnegative? 1" #f (fxnegative? 0))
(test "fxnegative? 2" #f (fxnegative? 1))
(test "fxnegative? 3" #t (fxnegative? -1))

(test "fxodd? 1" #f (fxodd? 0))
(test "fxodd? 2" #t (fxodd? 1))
(test "fxodd? 3" #t (fxodd? -1))
(test "fxodd? 4" #f (fxodd? 102))

(test "fxeven? 1" #t (fxeven? 0))
(test "fxeven? 2" #f (fxeven? 1))
(test "fxeven? 3" #t (fxeven? -2))
(test "fxeven? 4" #t (fxeven? 102))

(test "fxmax 1" 4 (fxmax 3 4))
(test "fxmax 2" 5 (fxmax 3 5 4))
(test "fxmin 1" 3 (fxmin 3 4))
(test "fxmin 2" 3 (fxmin 3 5 4))

(test "fx+" 7 (fx+ 3 4))
(test "fx*" 12 (fx* 4 3))

(test "fx-" -1 (fx- 3 4))
(test "fxneg" -3 (fxneg 3))

(test "fxabs" 7 (fxabs -7))
(test "fxabs" 7 (fxabs 7))

(test "fxsquare 1" 1764 (fxsquare 42))
(test "fxsquare 2"    4 (fxsquare 2))

(test "fxquotient 1"  2 (fxquotient 5 2))
(test "fxquotient 2" -2 (fxquotient -5 2))
(test "fxquotient 3" -2 (fxquotient 5 -2))
(test "fxquotient 4"  2 (fxquotient -5 -2))

(test "fxremainder 1"  1 (fxremainder 13 4))
(test "fxremainder 2" -1 (fxremainder -13 4))
(test "fxremainder 3"  1 (fxremainder 13 -4))
(test "fxremainder 4" -1 (fxremainder -13 -4))

(let*-values (((root rem) (fxsqrt 32)))
  (test "fxsqrt" 35 (* root rem)))

(test "test-1" -1 (fxnot 0))
(test "test-2" 0 (fxand #b0 #b1))
(test "test-115" 6 (fxand 14 6))
(test "test-117" 14 (fxior 10 12))
(test "test-119" 6 (fxxor 10 12))
(test "test-122" 0 (fxnot -1))
(test "test-125" 9 (fxif 3 1 8))
(test "test-126" 0 (fxif 3 8 1))
(test "test-135" 2 (fxbit-count 12))
(test "test-137" 0 (fxlength 0))
(test "test-138" 8 (fxlength 128))
(test "test-139" 8 (fxlength 255))
(test "test-140" 9 (fxlength 256))
(test "test-141" -1 (fxfirst-set-bit 0))
(test "test-142" 0 (fxfirst-set-bit 1))
(test "test-143" 0 (fxfirst-set-bit 3))
(test "test-144" 2 (fxfirst-set-bit 4))
(test "test-145" 1 (fxfirst-set-bit 6))
(test "test-146" 0 (fxfirst-set-bit -1))
(test "test-147" 1 (fxfirst-set-bit -2))
(test "test-148" 0 (fxfirst-set-bit -3))
(test "test-149" 2 (fxfirst-set-bit -4))
(test "test-160" #t (fxbit-set? 0 1))
(test "test-161" #f (fxbit-set? 1 1))
(test "test-162" #f (fxbit-set? 1 8))

;;
;; The following do not seem to be correct:
;; (test "test-163" #t (fxbit-set? 10000 -1))
;; (test "test-167" #t (fxbit-set? 1000 -1))
;;
;; Theoretically, they'd be correct, considering negative numbers
;; reprsented as 2's complement, but in practice we can't do
;; x << HUGE_VALUE -- compilers do not like that, so we'd need to
;; do a somewhat slow operation to break the shift in smaller
;; shifts, etc... But:
;; SRFI-143 specifically says the index should not be larger than
;; the fixnum width, so one cannot expect any specific value
;; from the predicate when used like that.
;;
;; The tests pass on x86_64, but fails on ARM 32 bits.
;;

(test "test-168" 0 (fxcopy-bit 0 0 #f))
(test "test-174" -1 (fxcopy-bit 0 -1 #t))
(test "test-180" 1 (fxcopy-bit 0 0 #t))
(test "test-181" #x106 (fxcopy-bit 8 6 #t))
(test "test-182" 6 (fxcopy-bit 8 6 #f))
(test "test-183" -2 (fxcopy-bit 0 -1 #f))
(test "test-189" 0 (fxbit-field 6 0 1))
(test "test-190" 3 (fxbit-field 6 1 3))
(test "test-196" 2 (fxarithmetic-shift 1 1))
(test "test-197" 0 (fxarithmetic-shift 1 -1))
(test "test-200" #b110  (fxbit-field-rotate #b110 1 1 2))
(test "test-201" #b1010 (fxbit-field-rotate #b110 1 2 4))
(test "test-202" #b1011 (fxbit-field-rotate #b0111 -1 1 4))
(test "test-208" #b110 (fxbit-field-rotate #b110 0 0 10))
(test "test-211" 6 (fxbit-field-reverse 6 1 3))
(test "test-212" 12 (fxbit-field-reverse 6 1 4))
(test "test-248" -11 (fxnot 10))
(test "test-249" 36 (fxnot -37))
(test "test-250" 11 (fxior 3  10))
(test "test-251" 10 (fxand 11 26))
(test "test-252" 9 (fxxor 3 10))
(test "test-254" 4 (fxand 37 12))
(test "test-255" 32 (fxarithmetic-shift 8 2))
(test "test-256" 4 (fxarithmetic-shift 4 0))
(test "test-257" 4 (fxarithmetic-shift 8 -1))
(test "test-263" 0 (fxlength  0))
(test "test-264" 1 (fxlength  1))
(test "test-265" 0 (fxlength -1))
(test "test-266" 3 (fxlength  7))
(test "test-267" 3 (fxlength -7))
(test "test-268" 4 (fxlength  8))
(test "test-269" 3 (fxlength -8))
(test "test-272" #t (fxbit-set? 3 10))
(test "test-273" #t (fxbit-set? 2 6))
(test "test-274" #f (fxbit-set? 0 6))
(test "test-276" #b100 (fxcopy-bit 2 0 #t))
(test "test-277" #b1011 (fxcopy-bit 2 #b1111 #f))
(test "test-280" 1 (fxfirst-set-bit 2))
(test "test-282" 3 (fxfirst-set-bit 40))
(test "test-283" 2 (fxfirst-set-bit -28))
(test "test-288" 1 (fxand #b1 #b1))
(test "test-289" 0 (fxand #b1 #b10))
(test "test-290" #b10 (fxand #b11 #b10))
(test "test-291" #b101 (fxand #b101 #b111))
(test "test-292" #b111 (fxand -1 #b111))
(test "test-293" #b110 (fxand -2 #b111))
(test "test-331" 1 (fxarithmetic-shift 1 0))
(test "test-333" 4 (fxarithmetic-shift 1 2))
(test "test-334" 8 (fxarithmetic-shift 1 3))
(test "test-335" 16 (fxarithmetic-shift 1 4))
(test "test-346" -1 (fxarithmetic-shift -1 0))
(test "test-347" -2 (fxarithmetic-shift -1 1))
(test "test-348" -4 (fxarithmetic-shift -1 2))
(test "test-349" -8 (fxarithmetic-shift -1 3))
(test "test-350" -16 (fxarithmetic-shift -1 4))
(test "test-363" #b1010 (fxbit-field #b1101101010 0 4))
(test "test-364" #b101101 (fxbit-field #b1101101010 3 9))
(test "test-365" #b10110 (fxbit-field #b1101101010 4 9))
(test "test-366" #b110110 (fxbit-field #b1101101010 4 10))
(test "test-373" 3 (fxif 1 1 2))
(test "test-378" #b00110011 (fxif #b00111100 #b11110000 #b00001111))
(test "test-379" #b1 (fxcopy-bit 0 0 #t))


;; Bitwise operation with any number of parameters
(test "bitwise.1" 42       (fxand 42))
(test "bitwise.2" #b1      (fxand #b101011 #b1))
(test "bitwise.3" #b1      (fxand #b101011 #b1 #b100101))

(test "bitwise.4" 42       (fxior 42))
(test "bitwise.5" #b101011 (fxior #b101011 #b1))
(test "bitwise.6" #b101111 (fxior #b101011 #b1 #b100101))

(test "bitwise.7" 42       (fxxor 42))
(test "bitwise.8" #b101010 (fxxor #b101011 #b1))
(test "bitwise.9" #b001111 (fxxor #b101011 #b1 #b100101))



;; Extra tests for the tricky bit-field juggling functions:

(test "rotate 1"
      #b101010110
      (fxbit-field-rotate #b101011100 -2 1 5))
(test "rotate 2"
      #b101111011010
      (fxbit-field-rotate #b101011011110 -3 2 10))
(test "rotate 3"
      #b101011110110
      (fxbit-field-rotate #b101011011110 3 2 10))

(test "reverse 1"
      #b101001110
      (fxbit-field-reverse #b101011100 1 5))
(test "reverse 2"
      #b101110110110
      (fxbit-field-reverse #b101011011110 2 10))


;; simple test:

(test "fixnum width"
      #t
      (= fx-width (fixnum-width)))

(test "width and greatest fixnum"
      #t
      (= fx-greatest (- (expt 2 (- fx-width 1))  1)))

(test "is greatest-fixnum a fixnum?"
      #t
      (fixnum? fx-greatest))

(test "is greatest-fixnum +1 a fixnum?"
      #f
      (fixnum? (+ fx-greatest 1)))

(test "is greatest-fixnum a fixnum?"
      #t
      (fixnum? fx-least))

(test "is least-fixnum -1 a fixnum?"
      #f
      (fixnum? (- fx-least 1)))


;; extra tests

(test "fxbit-count.0"   0   (fxbit-count 0))
(test "fxbit-count.1"   1   (fxbit-count 1))
(test "fxbit-count.2"   1   (fxbit-count 2))
(test "fxbit-count.3"   2   (fxbit-count 3))
(test "fxbit-count.4"   1   (fxbit-count 4))
(test "fxbit-count.5"   2   (fxbit-count 5))
(test "fxbit-count.6"   2   (fxbit-count 6))
(test "fxbit-count.7"   3   (fxbit-count 7))
(test "fxbit-count.8"   1   (fxbit-count 8))
(test "fxbit-count.9"   2   (fxbit-count 9))
(test "fxbit-count.10"  2   (fxbit-count 10))
(test "fxbit-count.11"  3   (fxbit-count 11))
          
(test "fxbit-count.-1"   0   (fxbit-count -1))
(test "fxbit-count.-2"   1   (fxbit-count -2))
(test "fxbit-count.-3"   1   (fxbit-count -3))
(test "fxbit-count.-4"   2   (fxbit-count -4))
(test "fxbit-count.-5"   1   (fxbit-count -5))
(test "fxbit-count.-6"   2   (fxbit-count -6))
(test "fxbit-count.-7"   2   (fxbit-count -7))
(test "fxbit-count.-8"   3   (fxbit-count -8))
(test "fxbit-count.-9"   1   (fxbit-count -9))
(test "fxbit-count.-10"  2   (fxbit-count -10))
(test "fxbit-count.-11"  2   (fxbit-count -11))
(test "fxbit-count.-30"  4   (fxbit-count -30))

