From e962184ad5409b5733089e36c52268813909b10b Mon Sep 17 00:00:00 2001 From: Job Henandez Lara Date: Wed, 18 Oct 2023 15:38:44 -0700 Subject: [PATCH] check if unsigned numbers underflow --- library/math/num.lisp | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/library/math/num.lisp b/library/math/num.lisp index 4ff65ea3..274e720e 100644 --- a/library/math/num.lisp +++ b/library/math/num.lisp @@ -161,6 +161,35 @@ ;;; Num instances for integers ;;; +(cl:eval-when (:compile-toplevel :load-toplevel) + (cl:defmacro define-unsigned-num-underflow (type bits) + "Define a `Num' instance for Type which signals an error on underflow." + `(define-instance (Num ,type) + (define (+ a b) + (lisp ,type (a b) + (cl:if (cl:and (cl:< b 0) (cl:< a (cl:- 0 b))) + (cl:error ,(cl:format cl:nil "Unsigned value underflowed ~D bits." bits)) + (cl:+ a b)))) + + (define (- a b) + (lisp ,type (a b) + (cl:if (cl:and (cl:>= b 0) (cl:< a (cl:+ 0 b))) + (cl:error ,(cl:format cl:nil "Unsigned value underflowed ~D bits." bits)) + (cl:- a b)))) + + (define (* a b) + (lisp ,type (a b) + (cl:if (cl:or (cl:and (cl:and (cl:> b 0) (cl:< a 0)) (cl:< a (cl:/ 0 b))) + (cl:and (cl:and (cl:< b 0) (cl:> a 0)) (cl:> a (cl:/ 0 b)))) + (cl:error ,(cl:format cl:nil "Unsigned value underflowed ~D bits." bits)) + (cl:* a b)))) + + (define (fromInt x) + (lisp ,type (x) + (cl:if (cl:< x 0) + (cl:error ,(cl:format cl:nil "Unsigned value underflowed ~D bits." bits)) + x)))))) + (cl:eval-when (:compile-toplevel :load-toplevel) (cl:defmacro define-num-checked (type overflow-handler) "Define a `Num' instance for TYPE which signals on overflow." @@ -214,7 +243,12 @@ (define-num-wrapping U16 16) (define-num-wrapping U32 32) (define-num-wrapping U64 64) - (define-num-wrapping UFix #.+unsigned-fixnum-bits+)) + (define-num-wrapping UFix #.+unsigned-fixnum-bits+) + + (define-unsigned-num-underflow U8 8) + (define-unsigned-num-underflow U16 16) + (define-unsigned-num-underflow U32 32) + (define-unsigned-num-underflow U64 64)) ;;; ;;; Num instances for floats