home: hub: zuo

Download patch

ref: 25ad19ea481a62ab7f332a6db33b54bfb74eeeff
parent: ebdc0451c39c70ce88b3b6ab9ba2b8e389ec519a
author: Matthew Flatt <mflatt@racket-lang.org>
date: Fri Dec 8 05:03:07 CST 2023

change `modulo` to `remainder` and add `modulo`

The function formerly known as `modulo` was actually `remainder`, so
rename it, but add `modulo` to the library. This change is not
technically less backward-compatible than most changes, since it
removes `modulo` from `zuo/kernel`.

Thanks to @soegaard for noticing the problem and providing a first cut
at a repair.

--- a/lib/zuo/build.zuo
+++ b/lib/zuo/build.zuo
@@ -79,7 +79,7 @@
                (string=? s no-sha256)
                ;; also allow a concatenation of SHA-256s for multi-file targets
                (and (>= (string-length s) sha256-length)
-                    (= 0 (modulo (string-length s) sha256-length)))))
+                    (= 0 (remainder (string-length s) sha256-length)))))
       (eq? s phony-sha256)))
 
 ;; public constructor
--- a/lib/zuo/private/base-common/lib.zuo
+++ b/lib/zuo/private/base-common/lib.zuo
@@ -41,3 +41,13 @@
 
 (define (gensym sym)
   (string->uninterned-symbol (symbol->string sym)))
+
+(define (modulo n m)
+  (let ([r (remainder n m)])
+    (if (>= m 0)
+        (if (>= n 0)
+            r
+            (- r))
+        (if (< n 0)
+            r
+            (+ r n)))))
--- a/lib/zuo/private/more.zuo
+++ b/lib/zuo/private/more.zuo
@@ -10,6 +10,8 @@
          boolean?
          string-tree?
 
+         modulo
+
          equal?
          assoc
          member
@@ -58,6 +60,17 @@
   (or (string? v)
       (and (list? v)
            (andmap string-tree? v))))
+
+(define (modulo n m)
+  (unless (integer? n) (arg-error 'modulo "integer" n))
+  (unless (integer? m) (arg-error 'modulo "integer" m))
+  (when (= m 0) (error "modulo: divide by zero"))
+  (let ([r (remainder n m)])
+    (if (eq? (>= m 0) (>= n 0))
+        r
+        (if (= r 0)
+            0
+            (+ r m)))))
 
 (define (equal? a b)
   (or (eq? a b)
--- a/tests/integer.zuo
+++ b/tests/integer.zuo
@@ -63,16 +63,30 @@
 (check-arg-fail (quotient 5 'apple) not-integer)
 (check-arg-fail (quotient 5 0) "divide by zero")
 
+(check (remainder 5 2) 1)
+(check (remainder 2 2) 0)
+(check (remainder -5 2) -1)
+(check (remainder 5 -2) 1)
+(check (remainder -9223372036854775808 1) 0)
+(check (remainder -9223372036854775808 -1) 0)
+(check (remainder 9223372036854775807 -1) 0)
+(check (remainder -9223372036854775807 -1) 0)
+(check (remainder -9223372036854775808 9223372036854775807) -1)
+(check (remainder 9223372036854775807 -9223372036854775808) 9223372036854775807)
+(check-arg-fail (remainder -5) arity)
+(check-arg-fail (remainder 5 'apple) not-integer)
+(check-arg-fail (remainder 5 0) "divide by zero")
+
 (check (modulo 5 2) 1)
 (check (modulo 2 2) 0)
-(check (modulo -5 2) -1)
-(check (modulo 5 -2) 1)
+(check (modulo -5 2) 1)
+(check (modulo 5 -2) -1)
 (check (modulo -9223372036854775808 1) 0)
 (check (modulo -9223372036854775808 -1) 0)
 (check (modulo 9223372036854775807 -1) 0)
 (check (modulo -9223372036854775807 -1) 0)
-(check (modulo -9223372036854775808 9223372036854775807) -1)
-(check (modulo 9223372036854775807 -9223372036854775808) 9223372036854775807)
+(check (modulo -9223372036854775808 9223372036854775807) 9223372036854775806)
+(check (modulo 9223372036854775807 -9223372036854775808) -1)
 (check-arg-fail (modulo -5) arity)
 (check-arg-fail (modulo 5 'apple) not-integer)
 (check-arg-fail (modulo 5 0) "divide by zero")
--- a/zuo-doc/fake-zuo.rkt
+++ b/zuo-doc/fake-zuo.rkt
@@ -91,6 +91,7 @@
     *
     quotient
     modulo
+    remainder
     <
     <=
     =
--- a/zuo-doc/lang-zuo-kernel.scrbl
+++ b/zuo-doc/lang-zuo-kernel.scrbl
@@ -73,7 +73,7 @@
   pair? null? list? cons car cdr list append reverse length
   list-ref list-set
 
-  integer? + - * quotient modulo < <= = >= >
+  integer? + - * quotient remainder < <= = >= >
   bitwise-and bitwise-ior bitwise-xor bitwise-not
 
   string? string-length string-ref string-u32-ref substring string
--- a/zuo-doc/lang-zuo.scrbl
+++ b/zuo-doc/lang-zuo.scrbl
@@ -322,6 +322,7 @@
            [(- [z integer?] [w integer?] ...+) integer?])]
 @defproc[(* [z integer?] ...) integer?]
 @defproc[(quotient [n integer?] [m integer?]) integer?]
+@defproc[(remainder [n integer?] [m integer?]) integer?]
 @defproc[(modulo [n integer?] [m integer?]) integer?]
 @defproc[(= [z integer?] [w integer?]) boolean?]
 @defproc[(< [x integer?] [y integer?]) boolean?]
@@ -334,7 +335,7 @@
 @defproc[(bitwise-not [n integer?])  integer?]
 )]{
 
-Analogous to @realracket*[+ - * quotient modulo = < <= > >=
+Analogous to @realracket*[+ - * quotient remainder modulo = < <= > >=
 bitwise-ior bitwise-and bitwise-xor bitwise-not] from
 @racketmodname[racket], but on Zuo integers and sometimes constrained
 to two arguments.}
--- a/zuo.c
+++ b/zuo.c
@@ -2783,14 +2783,14 @@
   return zuo_integer(ZUO_INT_I(n) / m_i);
 }
 
-static zuo_t *zuo_modulo(zuo_t *n, zuo_t *m) {
-  const char *who = "modulo";
+static zuo_t *zuo_remainder(zuo_t *n, zuo_t *m) {
+  const char *who = "remainder";
   zuo_int_t m_i;
   check_ints(n, m, who);
   m_i = ZUO_UINT_I(m);
   if (m_i == 0) zuo_fail1w(who, "divide by zero", m);
   if (m_i == -1) {
-    /* avoid potential overflow a the minimum integer */
+    /* avoid potential overflow at the minimum integer */
     return zuo_integer(0);
   }
   return zuo_integer(ZUO_INT_I(n) % m_i);
@@ -7156,7 +7156,7 @@
   ZUO_TOP_ENV_SET_PRIMITIVEN("-", zuo_subtract, -2);
   ZUO_TOP_ENV_SET_PRIMITIVEN("*", zuo_multiply, -1);
   ZUO_TOP_ENV_SET_PRIMITIVE2("quotient", zuo_quotient);
-  ZUO_TOP_ENV_SET_PRIMITIVE2("modulo", zuo_modulo);
+  ZUO_TOP_ENV_SET_PRIMITIVE2("remainder", zuo_remainder);
   ZUO_TOP_ENV_SET_PRIMITIVE2("<", zuo_lt);
   ZUO_TOP_ENV_SET_PRIMITIVE2("<=", zuo_le);
   ZUO_TOP_ENV_SET_PRIMITIVE2("=", zuo_eql);