diff --git a/devel/215_1.md b/devel/215_1.md new file mode 100644 index 00000000..8dd7ddc6 --- /dev/null +++ b/devel/215_1.md @@ -0,0 +1,40 @@ +# [215_1] (srfi srfi-143) 模块实现 + +## 任务相关的代码文件 ++ goldfish/srfi/srfi-143.scm ++ tests/goldfish/liii/fixnums-test.scm + +## 如何测试 + +```shell +xmake f -vyD +xmake b goldfish +bin/goldfish -m r7rs tests/goldfish/liii/fixnums-test.scm +``` + +## 2026/02/25 (srfi srfi-143) 模块实现 + +### What + +1. 新增 `goldfish/srfi/srfi-143.scm`,实现 SRFI-143 Fixnums 模块并按规范分组导出接口。 + +2. 实现 fixnum 常量 `fx-width` / `fx-greatest` / `fx-least`,基于 `*s7*` 的 `most-positive-fixnum` / `most-negative-fixnum` 推导位宽与范围。 + +3. 实现谓词与比较函数:`fixnum?`、`fx=?`、`fx?`、`fx<=?`、`fx>=?`、`fxzero?`、`fxpositive?`、`fxnegative?`、`fxodd?`、`fxeven?`、`fxmax`、`fxmin`。 + +4. 实现基础算术:`fx+`、`fx-`、`fxneg`、`fx*`、`fxquotient`、`fxremainder`、`fxabs`、`fxsquare`、`fxsqrt`,并在结果超出 fixnum 范围时抛出 `out-of-range`。 + +5. 实现带进位运算:`fx+/carry`、`fx-/carry`、`fx*/carry`,使用符号溢出检测返回 carry(-1/0/1)。 + +6. 实现位运算与位域:`fxnot`、`fxand`、`fxior`、`fxxor`、`fxarithmetic-shift`、`fxarithmetic-shift-left`、`fxarithmetic-shift-right`、`fxbit-count`、`fxlength`、`fxif`、`fxbit-set?`、`fxcopy-bit`、`fxfirst-set-bit`、`fxbit-field`、`fxbit-field-rotate`、`fxbit-field-reverse`。 + +7. 增加辅助函数:`fx-assert`、`fx-ensure`、`fx-check-index`、`fx-check-range`、`fx-safe-ash`,统一类型检查、范围校验与大位移分段处理;`fxbit-set?` / `fxcopy-bit` 对最高位做特判。 + + +### Why + +提供标准化的 fixnum 运算接口,确保与 SRFI-143 兼容,并对溢出与边界行为进行统一约束。 + +### How + +基于 SRFI-151 的位运算实现,结合 S7 提供的 fixnum 上下界完成范围推导与校验,通过辅助函数集中处理类型与边界问题,并以测试驱动补齐行为与边界场景。 \ No newline at end of file diff --git a/goldfish/srfi/srfi-143.scm b/goldfish/srfi/srfi-143.scm new file mode 100644 index 00000000..274be967 --- /dev/null +++ b/goldfish/srfi/srfi-143.scm @@ -0,0 +1,391 @@ +; +; Copyright (C) 2026 The Goldfish Scheme Authors +; +; Licensed under the Apache License, Version 2.0 (the "License"); +; you may not use this file except in compliance with the License. +; You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +; WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +; License for the specific language governing permissions and limitations +; under the License. +; + +(define-library (srfi srfi-143) + (import (liii base) + (liii error) + (srfi srfi-151)) + (export + ; Constants + fx-width + fx-greatest + fx-least + + ; Predicates + fixnum? + fx=? + fx? + fx<=? + fx>=? + fxzero? + fxpositive? + fxnegative? + fxodd? + fxeven? + fxmax + fxmin + + ; Basic arithmetic + fx+ + fx- + fxneg + fx* + fxquotient + fxremainder + fxabs + fxsquare + fxsqrt + + ; Arithmetic with carry + fx+/carry + fx-/carry + fx*/carry + + ; Bitwise operations + fxnot + fxand + fxior + fxxor + fxarithmetic-shift + fxarithmetic-shift-left + fxarithmetic-shift-right + fxbit-count + fxlength + fxif + fxbit-set? + fxcopy-bit + fxfirst-set-bit + fxbit-field + fxbit-field-rotate + fxbit-field-reverse) + (begin + + (define fx-greatest (*s7* 'most-positive-fixnum)) + (define fx-least (*s7* 'most-negative-fixnum)) + (define fx-width (+ (integer-length fx-greatest) 1)) + + (define (fixnum? obj) + (and (exact-integer? obj) + (<= fx-least obj fx-greatest))) + + (define (fx-assert name obj) + (unless (fixnum? obj) + (error 'type-error (string-append name ": expected fixnum") obj))) + + (define (fx-assert-all name args) + (for-each (lambda (x) (fx-assert name x)) args)) + + (define (fx-ensure name value) + (if (fixnum? value) + value + (error 'out-of-range (string-append name ": result not a fixnum") value))) + + (define (fx-check-index name index) + (fx-assert name index) + (when (or (< index 0) (>= index fx-width)) + (error 'out-of-range (string-append name ": index out of range") index))) + + (define (fx-check-range name start end) + (fx-assert name start) + (fx-assert name end) + (when (or (< start 0) (< end 0) (> start end) (> end fx-width)) + (error 'out-of-range (string-append name ": invalid start/end") start end))) + + (define (fx-field-mask width) + (cond + ((<= width 0) 0) + ((>= width fx-width) -1) + ((= width (- fx-width 1)) fx-greatest) + (else (- (arithmetic-shift 1 width) 1)))) + + (define (fx-extract-field i start end) + (let* ((width (- end start)) + (mask (fx-field-mask width))) + (bitwise-and (fx-safe-ash i (- start)) mask))) + + (define (fx-insert-field i field start width) + (let* ((mask (fx-field-mask width)) + (mask-shifted (arithmetic-shift mask start)) + (cleared (bitwise-and i (bitwise-not mask-shifted))) + (field-shifted (arithmetic-shift (bitwise-and field mask) start))) + (bitwise-ior cleared field-shifted))) + + (define (fx-add-carry a b) + (let ((r (+ a b))) + (cond + ((and (>= a 0) (>= b 0) (< r 0)) (values r 1)) + ((and (< a 0) (< b 0) (>= r 0)) (values r -1)) + (else (values r 0))))) + + (define (fx-sub-carry a b) + (let ((r (- a b))) + (cond + ((and (>= a 0) (< b 0) (< r 0)) (values r 1)) + ((and (< a 0) (>= b 0) (>= r 0)) (values r -1)) + (else (values r 0))))) + + (define (fx-safe-ash value count) + (let loop ((v value) (c count)) + (cond + ((= c 0) v) + ((> c 62) (loop (arithmetic-shift v 62) (- c 62))) + ((< c -62) (loop (arithmetic-shift v -62) (+ c 62))) + (else (arithmetic-shift v c))))) + + (define (fx=? . args) + (fx-assert-all "fx=?" args) + (apply = args)) + + (define (fx? . args) + (fx-assert-all "fx>?" args) + (apply > args)) + + (define (fx<=? . args) + (fx-assert-all "fx<=?" args) + (apply <= args)) + + (define (fx>=? . args) + (fx-assert-all "fx>=?" args) + (apply >= args)) + + (define (fxzero? i) + (fx-assert "fxzero?" i) + (zero? i)) + + (define (fxpositive? i) + (fx-assert "fxpositive?" i) + (positive? i)) + + (define (fxnegative? i) + (fx-assert "fxnegative?" i) + (negative? i)) + + (define (fxodd? i) + (fx-assert "fxodd?" i) + (odd? i)) + + (define (fxeven? i) + (fx-assert "fxeven?" i) + (even? i)) + + (define (fxmax . args) + (fx-assert-all "fxmax" args) + (fx-ensure "fxmax" (apply max args))) + + (define (fxmin . args) + (fx-assert-all "fxmin" args) + (fx-ensure "fxmin" (apply min args))) + + (define (fx+ i j) + (fx-assert-all "fx+" (list i j)) + (fx-ensure "fx+" (+ i j))) + + (define (fx- i j) + (fx-assert-all "fx-" (list i j)) + (fx-ensure "fx-" (- i j))) + + (define (fxneg i) + (fx-assert "fxneg" i) + (fx-ensure "fxneg" (- i))) + + (define (fx* i j) + (fx-assert-all "fx*" (list i j)) + (fx-ensure "fx*" (* i j))) + + (define (fxquotient i j) + (fx-assert-all "fxquotient" (list i j)) + (fx-ensure "fxquotient" (quotient i j))) + + (define (fxremainder i j) + (fx-assert-all "fxremainder" (list i j)) + (fx-ensure "fxremainder" (remainder i j))) + + (define (fxabs i) + (fx-assert "fxabs" i) + (fx-ensure "fxabs" (abs i))) + + (define (fxsquare i) + (fx-assert "fxsquare" i) + (fx-ensure "fxsquare" (* i i))) + + (define (fxsqrt i) + (fx-assert "fxsqrt" i) + (receive (s r) (exact-integer-sqrt i) + (values (fx-ensure "fxsqrt" s) + (fx-ensure "fxsqrt" r)))) + + (define (fx+/carry i j k) + (fx-assert-all "fx+/carry" (list i j k)) + (call-with-values + (lambda () (fx-add-carry i j)) + (lambda (s1 c1) + (call-with-values + (lambda () (fx-add-carry s1 k)) + (lambda (s2 c2) + (values (fx-ensure "fx+/carry" s2) + (fx-ensure "fx+/carry" (+ c1 c2)))))))) + + (define (fx-/carry i j k) + (fx-assert-all "fx-/carry" (list i j k)) + (call-with-values + (lambda () (fx-sub-carry i j)) + (lambda (s1 c1) + (call-with-values + (lambda () (fx-sub-carry s1 k)) + (lambda (s2 c2) + (values (fx-ensure "fx-/carry" s2) + (fx-ensure "fx-/carry" (+ c1 c2)))))))) + + (define (fx*/carry i j k) + (fx-assert-all "fx*/carry" (list i j k)) + (let ((p (* i j))) + (call-with-values + (lambda () (fx-add-carry p k)) + (lambda (s1 c1) + (values (fx-ensure "fx*/carry" s1) + (fx-ensure "fx*/carry" c1)))))) + + (define (fxnot i) + (fx-assert "fxnot" i) + (fx-ensure "fxnot" (bitwise-not i))) + + (define (fxand . args) + (fx-assert-all "fxand" args) + (let ((result (if (null? args) -1 (apply bitwise-and args)))) + (fx-ensure "fxand" result))) + + (define (fxior . args) + (fx-assert-all "fxior" args) + (let ((result (if (null? args) 0 (apply bitwise-ior args)))) + (fx-ensure "fxior" result))) + + (define (fxxor . args) + (fx-assert-all "fxxor" args) + (let ((result (if (null? args) 0 (apply bitwise-xor args)))) + (fx-ensure "fxxor" result))) + + (define (fxarithmetic-shift i count) + (fx-assert-all "fxarithmetic-shift" (list i count)) + (when (> (abs count) (- fx-width 1)) + (error 'out-of-range "fxarithmetic-shift: count exceeds fixnum width" count)) + (fx-ensure "fxarithmetic-shift" (fx-safe-ash i count))) + + (define (fxarithmetic-shift-left i count) + (fx-assert-all "fxarithmetic-shift-left" (list i count)) + (when (< count 0) + (error 'out-of-range "fxarithmetic-shift-left: count must be non-negative" count)) + (when (> count (- fx-width 1)) + (error 'out-of-range "fxarithmetic-shift-left: count exceeds fixnum width" count)) + (fx-ensure "fxarithmetic-shift-left" (fx-safe-ash i count))) + + (define (fxarithmetic-shift-right i count) + (fx-assert-all "fxarithmetic-shift-right" (list i count)) + (when (< count 0) + (error 'out-of-range "fxarithmetic-shift-right: count must be non-negative" count)) + (when (> count (- fx-width 1)) + (error 'out-of-range "fxarithmetic-shift-right: count exceeds fixnum width" count)) + (fx-ensure "fxarithmetic-shift-right" (fx-safe-ash i (- count)))) + + (define (fxbit-count i) + (fx-assert "fxbit-count" i) + (fx-ensure "fxbit-count" (bit-count i))) + + (define (fxlength i) + (fx-assert "fxlength" i) + (fx-ensure "fxlength" (integer-length i))) + + (define (fxif mask i j) + (fx-assert-all "fxif" (list mask i j)) + (fx-ensure "fxif" (bitwise-if mask i j))) + + (define (fxbit-set? index i) + (fx-check-index "fxbit-set?" index) + (fx-assert "fxbit-set?" i) + (if (= index (- fx-width 1)) + (negative? i) + (let ((mask (arithmetic-shift 1 index))) + (not (zero? (bitwise-and i mask)))))) + + (define (fxcopy-bit index i boolean) + (fx-check-index "fxcopy-bit" index) + (fx-assert "fxcopy-bit" i) + (unless (boolean? boolean) + (error 'type-error "fxcopy-bit: boolean must be #t or #f" boolean)) + (if (= index (- fx-width 1)) + (fx-ensure "fxcopy-bit" + (if boolean + (bitwise-ior i fx-least) + (bitwise-and i fx-greatest))) + (let ((mask (arithmetic-shift 1 index))) + (fx-ensure "fxcopy-bit" + (if boolean + (bitwise-ior i mask) + (bitwise-and i (bitwise-not mask))))))) + + (define (fxfirst-set-bit i) + (fx-assert "fxfirst-set-bit" i) + (fx-ensure "fxfirst-set-bit" (first-set-bit i))) + + (define (fxbit-field i start end) + (fx-assert "fxbit-field" i) + (fx-check-range "fxbit-field" start end) + (let* ((width (- end start))) + (if (<= width 0) + 0 + (fx-ensure "fxbit-field" + (fx-extract-field i start end))))) + + (define (fxbit-field-rotate i count start end) + (fx-assert-all "fxbit-field-rotate" (list i count start end)) + (fx-check-range "fxbit-field-rotate" start end) + (let* ((width (- end start))) + (if (<= width 0) + i + (let* ((field (fx-extract-field i start end)) + (rot (modulo count width))) + (if (= rot 0) + i + (let* ((mask (fx-field-mask width)) + (left (bitwise-and (fx-safe-ash field rot) mask)) + (right (fx-safe-ash field (- rot width))) + (rotated (bitwise-ior left right)) + (res (fx-insert-field i rotated start width))) + (fx-ensure "fxbit-field-rotate" res))))))) + + (define (fxbit-field-reverse i start end) + (fx-assert-all "fxbit-field-reverse" (list i start end)) + (fx-check-range "fxbit-field-reverse" start end) + (let* ((width (- end start))) + (if (<= width 1) + i + (let* ((field (fx-extract-field i start end)) + (rev (let loop ((n field) (k width) (acc 0)) + (if (= k 0) + acc + (loop (arithmetic-shift n -1) + (- k 1) + (bitwise-ior (arithmetic-shift acc 1) + (bitwise-and n 1)))))) + (res (fx-insert-field i rev start width))) + (fx-ensure "fxbit-field-reverse" res))))) + + ) ; end of begin + ) ; end of define-library diff --git a/tests/goldfish/liii/fixnums-test.scm b/tests/goldfish/liii/fixnums-test.scm new file mode 100644 index 00000000..c1d7da29 --- /dev/null +++ b/tests/goldfish/liii/fixnums-test.scm @@ -0,0 +1,1522 @@ +; +; Copyright (C) 2026 The Goldfish Scheme Authors +; +; Licensed under the Apache License, Version 2.0 (the "License"); +; you may not use this file except in compliance with the License. +; You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +; WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +; License for the specific language governing permissions and limitations +; under the License. +; + +(import (srfi srfi-143) + (liii check)) + +(check-set-mode! 'report-failed) + + +#| +fx-greatest +fixnum 最大值常量 + +语法 +---- +fx-greatest + +返回值 +---- +integer? + +边界行为 +---- +等于 (*s7* 'most-positive-fixnum)。 + +性能边界 +---- +常量时间读取。 + +错误处理 +---- +无。 +|# + +(check fx-greatest => (*s7* 'most-positive-fixnum)) + + +#| +fx-least +fixnum 最小值常量 + +语法 +---- +fx-least + +返回值 +---- +integer? + +边界行为 +---- +等于 (*s7* 'most-negative-fixnum)。 + +性能边界 +---- +常量时间读取。 + +错误处理 +---- +无。 +|# + +(check fx-least => (*s7* 'most-negative-fixnum)) + + +#| +fx-width +fixnum 位宽常量 + +语法 +---- +fx-width + +返回值 +---- +integer? + +边界行为 +---- +等于 (fxlength fx-greatest) + 1。 + +性能边界 +---- +常量时间读取。 + +错误处理 +---- +无。 +|# + +(check fx-width => (+ (fxlength fx-greatest) 1)) + + +#| +fixnum? +判断对象是否为 fixnum + +语法 +---- +(fixnum? x) + +参数 +---- +x : any + +返回值 +---- +boolean? + +边界行为 +---- +覆盖 fx-least 与 fx-greatest 边界。 + +性能边界 +---- +常量时间判断。 + +错误处理 +---- +非整数输入返回 #f。 +|# + +(check-true (fixnum? 0)) +(check-true (fixnum? fx-greatest)) +(check-true (fixnum? fx-least)) +(check-false (fixnum? 1.0)) +(check-false (fixnum? #\A)) + + +#| +fx=? +fixnum 相等比较 + +语法 +---- +(fx=? i ...) + +参数 +---- +i : fixnum? + +返回值 +---- +boolean? + +边界行为 +---- +支持多参数比较。 + +性能边界 +---- +与参数个数线性相关。 + +错误处理 +---- +非 fixnum 可能触发类型错误。 +|# + +(check-true (fx=? 1 1 1)) +(check-false (fx=? 1 2)) + + +#| +fx? +fixnum 大于比较 + +语法 +---- +(fx>? i ...) + +参数 +---- +i : fixnum? + +返回值 +---- +boolean? + +边界行为 +---- +支持多参数链式比较。 + +性能边界 +---- +与参数个数线性相关。 + +错误处理 +---- +非 fixnum 可能触发类型错误。 +|# + +(check-true (fx>? 3 2 1)) + + +#| +fx<=? +fixnum 小于等于比较 + +语法 +---- +(fx<=? i ...) + +参数 +---- +i : fixnum? + +返回值 +---- +boolean? + +边界行为 +---- +支持多参数链式比较。 + +性能边界 +---- +与参数个数线性相关。 + +错误处理 +---- +非 fixnum 可能触发类型错误。 +|# + +(check-true (fx<=? 1 1 2)) + + +#| +fx>=? +fixnum 大于等于比较 + +语法 +---- +(fx>=? i ...) + +参数 +---- +i : fixnum? + +返回值 +---- +boolean? + +边界行为 +---- +支持多参数链式比较。 + +性能边界 +---- +与参数个数线性相关。 + +错误处理 +---- +非 fixnum 可能触发类型错误。 +|# + +(check-true (fx>=? 3 3 2)) + + +#| +fxzero? +判断 fixnum 是否为 0 + +语法 +---- +(fxzero? i) + +参数 +---- +i : fixnum? + +返回值 +---- +boolean? + +边界行为 +---- +仅对 fixnum 有意义。 + +性能边界 +---- +常量时间判断。 + +错误处理 +---- +非 fixnum 可能触发类型错误。 +|# + +(check-true (fxzero? 0)) + + +#| +fxpositive? +判断 fixnum 是否为正数 + +语法 +---- +(fxpositive? i) + +参数 +---- +i : fixnum? + +返回值 +---- +boolean? + +边界行为 +---- +与 positive? 一致。 + +性能边界 +---- +常量时间判断。 + +错误处理 +---- +非 fixnum 可能触发类型错误。 +|# + +(check-true (fxpositive? 2)) + + +#| +fxnegative? +判断 fixnum 是否为负数 + +语法 +---- +(fxnegative? i) + +参数 +---- +i : fixnum? + +返回值 +---- +boolean? + +边界行为 +---- +与 negative? 一致。 + +性能边界 +---- +常量时间判断。 + +错误处理 +---- +非 fixnum 可能触发类型错误。 +|# + +(check-true (fxnegative? -1)) + + +#| +fxodd? +判断 fixnum 是否为奇数 + +语法 +---- +(fxodd? i) + +参数 +---- +i : fixnum? + +返回值 +---- +boolean? + +边界行为 +---- +与 odd? 一致。 + +性能边界 +---- +常量时间判断。 + +错误处理 +---- +非 fixnum 可能触发类型错误。 +|# + +(check-true (fxodd? 3)) + + +#| +fxeven? +判断 fixnum 是否为偶数 + +语法 +---- +(fxeven? i) + +参数 +---- +i : fixnum? + +返回值 +---- +boolean? + +边界行为 +---- +与 even? 一致。 + +性能边界 +---- +常量时间判断。 + +错误处理 +---- +非 fixnum 可能触发类型错误。 +|# + +(check-true (fxeven? 4)) + + +#| +fxmax +fixnum 最大值 + +语法 +---- +(fxmax i ...) + +参数 +---- +i : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +支持多参数。 + +性能边界 +---- +与参数个数线性相关。 + +错误处理 +---- +非 fixnum 可能触发类型错误。 +|# + +(check (fxmax 1 5 2) => 5) +(check (fxmax fx-least 0 fx-greatest) => fx-greatest) + + +#| +fxmin +fixnum 最小值 + +语法 +---- +(fxmin i ...) + +参数 +---- +i : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +支持多参数。 + +性能边界 +---- +与参数个数线性相关。 + +错误处理 +---- +非 fixnum 可能触发类型错误。 +|# + +(check (fxmin 1 5 2) => 1) +(check (fxmin fx-least 0 fx-greatest) => fx-least) + + +#| +fx+ +fixnum 加法 + +语法 +---- +(fx+ i j) + +参数 +---- +i, j : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +溢出违反 fixnum 规则。 + +性能边界 +---- +常量时间。 + +错误处理 +---- +非 fixnum 触发类型错误。 +|# + +(check (fx+ 1 2) => 3) +(check (fx+ fx-greatest 0) => fx-greatest) +(check (fx+ fx-least 0) => fx-least) +(check-catch 'type-error (fx+ 1 1.0)) + + +#| +fx- +fixnum 减法 + +语法 +---- +(fx- i j) + +参数 +---- +i, j : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +溢出违反 fixnum 规则。 + +性能边界 +---- +常量时间。 + +错误处理 +---- +非 fixnum 触发类型错误。 +|# + +(check (fx- 5 3) => 2) +(check (fx- fx-greatest 0) => fx-greatest) +(check (fx- fx-least 0) => fx-least) + + +#| +fxneg +fixnum 取负 + +语法 +---- +(fxneg i) + +参数 +---- +i : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +对 fx-least 取负违反 fixnum 规则。 + +性能边界 +---- +常量时间。 + +错误处理 +---- +非 fixnum 触发类型错误。 +|# + +(check (fxneg 3) => -3) +(check (fxneg 0) => 0) +(check-catch 'out-of-range (fxneg fx-least)) + + +#| +fx* +fixnum 乘法 + +语法 +---- +(fx* i j) + +参数 +---- +i, j : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +溢出违反 fixnum 规则。 + +性能边界 +---- +常量时间。 + +错误处理 +---- +非 fixnum 触发类型错误。 +|# + +(check (fx* 6 7) => 42) +(check (fx* 0 fx-greatest) => 0) +(check (fx* -1 1) => -1) + + +#| +fxquotient +fixnum 商 + +语法 +---- +(fxquotient i j) + +参数 +---- +i, j : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +遵循 quotient 行为。 + +性能边界 +---- +常量时间。 + +错误处理 +---- +非 fixnum 触发类型错误。 +|# + +(check (fxquotient 7 3) => 2) +(check (fxquotient -7 3) => -2) +(check (fxquotient 7 -3) => -2) + + +#| +fxremainder +fixnum 余数 + +语法 +---- +(fxremainder i j) + +参数 +---- +i, j : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +遵循 remainder 行为。 + +性能边界 +---- +常量时间。 + +错误处理 +---- +非 fixnum 触发类型错误。 +|# + +(check (fxremainder 7 3) => 1) +(check (fxremainder -7 3) => -1) +(check (fxremainder 7 -3) => 1) + + +#| +fxabs +fixnum 绝对值 + +语法 +---- +(fxabs i) + +参数 +---- +i : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +对 fx-least 调用违反 fixnum 规则。 + +性能边界 +---- +常量时间。 + +错误处理 +---- +fx-least 触发 out-of-range。 +|# + +(check (fxabs -5) => 5) +(check (fxabs 0) => 0) +(check-catch 'out-of-range (fxabs fx-least)) + + +#| +fxsquare +fixnum 平方 + +语法 +---- +(fxsquare i) + +参数 +---- +i : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +溢出违反 fixnum 规则。 + +性能边界 +---- +常量时间。 + +错误处理 +---- +非 fixnum 触发类型错误。 +|# + +(check (fxsquare 9) => 81) +(check (fxsquare 0) => 0) + + +#| +fxsqrt +fixnum 整数平方根 + +语法 +---- +(fxsqrt i) + +参数 +---- +i : fixnum? + +返回值 +---- +values +返回 (values s r),其中 s 为 floor(sqrt(i)),r 为余数。 + +边界行为 +---- +与 exact-integer-sqrt 一致。 + +性能边界 +---- +与输入位宽相关。 + +错误处理 +---- +非 fixnum 触发类型错误。 +|# + +(check (call-with-values (lambda () (fxsqrt 10)) list) => '(3 1)) +(check (call-with-values (lambda () (fxsqrt 81)) list) => '(9 0)) +(check (call-with-values (lambda () (fxsqrt 0)) list) => '(0 0)) + + +#| +fx+/carry +fixnum 加法带进位 + +语法 +---- +(fx+/carry i j k) + +参数 +---- +i, j, k : fixnum? + +返回值 +---- +values +返回 (values sum carry)。 + +边界行为 +---- +carry 取值为 -1/0/1。 + +性能边界 +---- +常量时间。 + +错误处理 +---- +非 fixnum 触发类型错误。 +|# + +(check (call-with-values (lambda () (fx+/carry 1 2 3)) list) => '(6 0)) +(check (call-with-values (lambda () (fx+/carry fx-greatest 1 0)) list) => (list fx-least 1)) +(check (call-with-values (lambda () (fx+/carry fx-greatest 0 0)) list) => (list fx-greatest 0)) +(check (call-with-values + (lambda () + (fx+/carry fx-greatest fx-greatest fx-greatest)) + list) + => (list (- fx-greatest 2) 1)) + + +#| +fx-/carry +fixnum 减法带借位 + +语法 +---- +(fx-/carry i j k) + +参数 +---- +i, j, k : fixnum? + +返回值 +---- +values +返回 (values diff carry)。 + +边界行为 +---- +carry 取值为 -1/0/1。 + +性能边界 +---- +常量时间。 + +错误处理 +---- +非 fixnum 触发类型错误。 +|# + +(check (call-with-values + (lambda () + (fx-/carry fx-least fx-greatest 0)) + list) + => '(1 -1)) +(check (call-with-values (lambda () (fx-/carry fx-least 1 0)) list) => (list fx-greatest -1)) +(check (call-with-values (lambda () (fx-/carry fx-least 0 0)) list) => (list fx-least 0)) + + +#| +fx*/carry +fixnum 乘法带进位 + +语法 +---- +(fx*/carry i j k) + +参数 +---- +i, j, k : fixnum? + +返回值 +---- +values +返回 (values prod carry)。 + +边界行为 +---- +carry 取值为 -1/0/1。 + +性能边界 +---- +常量时间。 + +错误处理 +---- +非 fixnum 触发类型错误。 +|# + +(check (call-with-values (lambda () (fx*/carry 2 3 4)) list) => '(10 0)) +(check (call-with-values (lambda () (fx*/carry -2 3 0)) list) => '(-6 0)) +(check (call-with-values (lambda () (fx*/carry fx-greatest 1 0)) list) => (list fx-greatest 0)) + + +#| +fxnot +fixnum 按位取反 + +语法 +---- +(fxnot i) + +参数 +---- +i : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +等价于 bitwise-not。 + +性能边界 +---- +常量时间。 + +错误处理 +---- +非 fixnum 触发类型错误。 +|# + +(check (fxnot 0) => -1) +(check (fxnot fx-greatest) => fx-least) +(check (fxand) => -1) +(check (fxior) => 0) +(check (fxxor) => 0) + + +#| +fxand +fixnum 按位与 + +语法 +---- +(fxand i ...) + +参数 +---- +i : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +空参数返回 -1。 + +性能边界 +---- +与参数个数线性相关。 + +错误处理 +---- +非 fixnum 触发类型错误。 +|# + +(check (fxand #b1100 #b1010) => #b1000) +(check (fxand -1 #b1010) => #b1010) + + +#| +fxior +fixnum 按位或 + +语法 +---- +(fxior i ...) + +参数 +---- +i : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +空参数返回 0。 + +性能边界 +---- +与参数个数线性相关。 + +错误处理 +---- +非 fixnum 触发类型错误。 +|# + +(check (fxior #b1100 #b1010) => #b1110) +(check (fxior 0 fx-least) => fx-least) + + +#| +fxxor +fixnum 按位异或 + +语法 +---- +(fxxor i ...) + +参数 +---- +i : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +空参数返回 0。 + +性能边界 +---- +与参数个数线性相关。 + +错误处理 +---- +非 fixnum 触发类型错误。 +|# + +(check (fxxor #b1100 #b1010) => #b0110) +(check (fxxor -1 -1) => 0) + + +#| +fxarithmetic-shift +fixnum 算术移位 + +语法 +---- +(fxarithmetic-shift i count) + +参数 +---- +i : fixnum? +count : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +|count| 不能超过 fx-width - 1。 + +性能边界 +---- +与位移量相关。 + +错误处理 +---- +位移越界触发 out-of-range。 +|# + +(check (fxarithmetic-shift 1 3) => 8) +(check (fxarithmetic-shift 8 -1) => 4) +(check (fxarithmetic-shift 1 (- fx-width 1)) => fx-least) +(check (fxarithmetic-shift fx-least (- 1 fx-width)) => -1) +(check-catch 'out-of-range (fxarithmetic-shift 1 fx-width)) + + +#| +fxarithmetic-shift-left +fixnum 左移 + +语法 +---- +(fxarithmetic-shift-left i count) + +参数 +---- +i : fixnum? +count : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +count 必须为非负且小于 fx-width。 + +性能边界 +---- +与位移量相关。 + +错误处理 +---- +位移越界触发 out-of-range。 +|# + +(check (fxarithmetic-shift-left 1 4) => 16) +(check-catch 'out-of-range (fxarithmetic-shift-left 1 -1)) +(check (fxarithmetic-shift-left 1 (- fx-width 1)) => fx-least) + + +#| +fxarithmetic-shift-right +fixnum 右移 + +语法 +---- +(fxarithmetic-shift-right i count) + +参数 +---- +i : fixnum? +count : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +count 必须为非负且小于 fx-width。 + +性能边界 +---- +与位移量相关。 + +错误处理 +---- +位移越界触发 out-of-range。 +|# + +(check (fxarithmetic-shift-right 16 2) => 4) +(check-catch 'out-of-range (fxarithmetic-shift-right 1 -1)) +(check (fxarithmetic-shift-right fx-least (- fx-width 1)) => -1) + + +#| +fxbit-count +fixnum 1 位计数 + +语法 +---- +(fxbit-count i) + +参数 +---- +i : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +对负数使用补码语义。 + +性能边界 +---- +与位宽相关。 + +错误处理 +---- +非 fixnum 触发类型错误。 +|# + +(check (fxbit-count #b101101) => 4) +(check (fxbit-count 0) => 0) +(check (fxbit-count -1) => 0) + + +#| +fxlength +fixnum 位长度 + +语法 +---- +(fxlength i) + +参数 +---- +i : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +等价于 integer-length。 + +性能边界 +---- +与位宽相关。 + +错误处理 +---- +非 fixnum 触发类型错误。 +|# + +(check (fxlength 0) => 0) +(check (fxlength 1) => 1) +(check (fxlength -1) => 1) +(check (fxlength fx-greatest) => (- fx-width 1)) + + +#| +fxif +fixnum 按位条件选择 + +语法 +---- +(fxif mask i j) + +参数 +---- +mask : fixnum? +i, j : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +等价于 (fxior (fxand mask i) (fxand (fxnot mask) j))。 + +性能边界 +---- +常量时间。 + +错误处理 +---- +非 fixnum 触发类型错误。 +|# + +(check (fxif 1 1 2) => 3) +(check (fxif 0 1 2) => 2) +(check (fxif -1 1 2) => 1) + + +#| +fxbit-set? +判断指定 bit 是否为 1 + +语法 +---- +(fxbit-set? index i) + +参数 +---- +index : fixnum? +i : fixnum? + +返回值 +---- +boolean? + +边界行为 +---- +index 需满足 0 <= index < fx-width。 + +性能边界 +---- +常量时间。 + +错误处理 +---- +越界触发 out-of-range。 +|# + +(check-true (fxbit-set? 0 1)) +(check-false (fxbit-set? 1 1)) +(check-true (fxbit-set? 63 -1)) +(check-catch 'out-of-range (fxbit-set? -1 0)) +(check-catch 'type-error (fxbit-set? 1.0 0)) +(check-false (fxbit-set? 0 fx-least)) +(check-true (fxbit-set? (- fx-width 1) fx-least)) +(check-catch 'out-of-range (fxbit-set? fx-width 0)) + + +#| +fxcopy-bit +设置指定 bit + +语法 +---- +(fxcopy-bit index i boolean) + +参数 +---- +index : fixnum? +i : fixnum? +boolean : boolean? + +返回值 +---- +fixnum? + +边界行为 +---- +index 需满足 0 <= index < fx-width。 + +性能边界 +---- +常量时间。 + +错误处理 +---- +越界触发 out-of-range。 +|# + +(check (fxcopy-bit 1 0 #t) => 2) +(check (fxcopy-bit 1 2 #f) => 0) +(check (fxcopy-bit 63 0 #t) => fx-least) +(check-catch 'out-of-range (fxcopy-bit -1 0 #t)) +(check-catch 'type-error (fxcopy-bit 0 0 1)) +(check (fxcopy-bit (- fx-width 1) -1 #f) => fx-greatest) +(check-catch 'out-of-range (fxcopy-bit fx-width 0 #t)) + + +#| +fxfirst-set-bit +返回最低位 1 的位置 + +语法 +---- +(fxfirst-set-bit i) + +参数 +---- +i : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +若 i 为 0,返回 -1。 + +性能边界 +---- +与位宽相关。 + +错误处理 +---- +非 fixnum 触发类型错误。 +|# + +(check (fxfirst-set-bit 0) => -1) +(check (fxfirst-set-bit 18) => 1) + + +#| +fxbit-field +提取位域 + +语法 +---- +(fxbit-field i start end) + +参数 +---- +i : fixnum? +start, end : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +start 与 end 满足 0 <= start <= end <= fx-width。 + +性能边界 +---- +与位宽相关。 + +错误处理 +---- +越界触发 out-of-range。 +|# + +(check (fxbit-field #b110110 1 4) => 3) +(check (fxbit-field #b110110 4 4) => 0) +(check-catch 'out-of-range (fxbit-field 1 0 (+ fx-width 1))) +(check-catch 'out-of-range (fxbit-field 1 -1 1)) +(check (fxbit-field fx-greatest 0 fx-width) => fx-greatest) +(check-catch 'out-of-range (fxbit-field 1 5 4)) + + +#| +fxbit-field-rotate +位域旋转 + +语法 +---- +(fxbit-field-rotate i count start end) + +参数 +---- +i : fixnum? +count : fixnum? +start, end : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +对 [start, end) 位域旋转。 + +性能边界 +---- +与位宽相关。 + +错误处理 +---- +越界触发 out-of-range。 +|# + +(check (fxbit-field-rotate #b110110 1 1 5) => 46) +(check (fxbit-field-rotate #b110110 -1 1 5) => 58) +(check (fxbit-field-rotate #b110110 0 1 5) => #b110110) +(check (fxbit-field-rotate #b110110 4 1 5) => #b110110) + + +#| +fxbit-field-reverse +位域反转 + +语法 +---- +(fxbit-field-reverse i start end) + +参数 +---- +i : fixnum? +start, end : fixnum? + +返回值 +---- +fixnum? + +边界行为 +---- +对 [start, end) 位域反转。 + +性能边界 +---- +与位宽相关。 + +错误处理 +---- +越界触发 out-of-range。 +|# + +(check (fxbit-field-reverse #b110110 1 5) => 58) +(check-catch 'out-of-range (fxbit-field-reverse 1 5 4)) +(check (fxbit-field-reverse #b110110 2 2) => #b110110) +(check (fxbit-field-reverse #b110110 2 3) => #b110110) + + +(check-report) +(if (check-failed?) (exit -1))