Skip to content

Commit

Permalink
Add inline attributes to Num and Arith methods and functions (#1374)
Browse files Browse the repository at this point in the history
  • Loading branch information
YarinHeffes authored Feb 11, 2025
1 parent 76032c1 commit aecd03c
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 7 deletions.
17 changes: 17 additions & 0 deletions library/math/arith.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ The function `general/` is partial, and will error produce a run-time error if t
(general/ (:arg-type -> :arg-type -> :res-type)))

(define-instance (Reciprocable :a => Dividable :a :a)
(inline)
(define (general/ a b) (/ a b)))

(define-class (Transfinite :a)
Expand All @@ -111,12 +112,14 @@ The function `general/` is partial, and will error produce a run-time error if t
(define nan
(lisp Single-Float ()
float-features:single-float-nan))
(inline)
(define (nan? x)
(Lisp Boolean (x)
#+(not allegro)
(float-features:float-NaN-p x)
#+allegro
(cl:and (float-features:float-NaN-p x) cl:t)))
(inline)
(define (infinite? x)
(Lisp Boolean (x)
(float-features:float-infinity-p x))))
Expand All @@ -128,75 +131,89 @@ The function `general/` is partial, and will error produce a run-time error if t
(define nan
(lisp Double-Float ()
float-features:double-float-nan))
(inline)
(define (nan? x)
(Lisp Boolean (x)
#+(not allegro)
(float-features:float-NaN-p x)
#+allegro
(cl:and (float-features:float-NaN-p x) cl:t)))
(inline)
(define (infinite? x)
(Lisp Boolean (x)
(float-features:float-infinity-p x))))

(inline)
(declare negate (Num :a => :a -> :a))
(define (negate x)
"The negation, or additive inverse, of `x`."
(- 0 x))

(inline)
(declare abs ((Ord :a) (Num :a) => :a -> :a))
(define (abs x)
"Absolute value of `x`."
(if (< x 0)
(negate x)
x))

(inline)
(declare sign ((Ord :a) (Num :a) (Num :b) => :a -> :b))
(define (sign x)
"The sign of `x`, where `(sign 0) = 1`."
(if (< x 0)
-1
1))

(inline)
(declare ash (Integer -> Integer -> Integer))
(define (ash x n)
"Compute the \"arithmetic shift\" of `x` by `n`. "
(lisp Integer (x n) (cl:ash x n)))

(inline)
(declare 1+ ((Num :num) => :num -> :num))
(define (1+ num)
"Increment `num`."
(+ num 1))

(inline)
(declare 1- ((Num :num) => :num -> :num))
(define (1- num)
"Decrement `num`."
(- num 1))

(inline)
(declare positive? ((Num :a) (Ord :a) => :a -> Boolean))
(define (positive? x)
"Is `x` positive?"
(> x 0))

(inline)
(declare negative? ((Num :a) (Ord :a) => :a -> Boolean))
(define (negative? x)
"Is `x` negative?"
(< x 0))

(inline)
(declare nonpositive? ((Num :a) (Ord :a) => :a -> Boolean))
(define (nonpositive? x)
"Is `x` not positive?"
(<= x 0))

(inline)
(declare nonnegative? ((Num :a) (Ord :a) => :a -> Boolean))
(define (nonnegative? x)
"Is `x` not negative?"
(>= x 0))

(inline)
(declare zero? (Num :a => :a -> Boolean))
(define (zero? x)
"Is `x` zero?"
(== x 0))

(inline)
(declare nonzero? (Num :a => :a -> Boolean))
(define (nonzero? x)
"Is `x` not zero?"
Expand Down
53 changes: 46 additions & 7 deletions library/math/complex.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,17 @@ below.")
(imag-part (Complex :a -> :a)))

(define-instance ((Complex :a) => Into :a (Complex :a))
(inline)
(define (into a)
(complex a 0)))

(inline)
(declare conjugate ((Complex :a) => Complex :a -> Complex :a))
(define (conjugate n)
"The complex conjugate."
(complex (real-part n) (negate (imag-part n))))

(inline)
(declare square-magnitude (Complex :a => Complex :a -> :a))
(define (square-magnitude a)
"The length of a complex number."
Expand All @@ -76,12 +79,17 @@ below.")
(complex 0 1))

(define-instance (Complex :a => Eq (Complex :a))
(inline)
(define (== a b) (complex-equal a b)))

(define-instance (Complex :a => Num (Complex :a))
(inline)
(define (+ a b) (complex-plus a b))
(inline)
(define (- a b) (complex-minus a b))
(inline)
(define (* a b) (complex-times a b))
(inline)
(define (fromInt n)
(complex (fromInt n) 0)))

Expand All @@ -91,12 +99,10 @@ below.")
;; (define (general/ a b) (complex-divide a b)))

(define-instance ((Complex :a) (Reciprocable :a) => Reciprocable (Complex :a))
(inline)
(define (reciprocal x)
(let a = (real-part x))
(let b = (imag-part x))
(let divisor = (reciprocal (square-magnitude x)))
;; z^-1 = z*/|z|^2
(complex (* a divisor) (negate (* b divisor))))
(complex-reciprocal x))
(inline)
(define (/ a b)
(complex-divide a b)))

Expand All @@ -113,17 +119,21 @@ below.")
;; Below are specializable functions, as class methods cannot be specialized
;; This allows us to call out to faster lisp functions for doing arithmetic.
;; These will only be called from monomorphized forms.
(declare complex-equal (Complex :a => Complex :a -> Complex :a -> Boolean))
(define (complex-equal a b)
(and (== (real-part a) (real-part b))
(== (imag-part a) (imag-part b))))

(declare complex-plus ((Complex :a) => Complex :a -> Complex :a -> Complex :a))
(define (complex-plus a b)
(complex (+ (real-part a) (real-part b))
(+ (imag-part a) (imag-part b))))

(declare complex-minus ((Complex :a) => Complex :a -> Complex :a -> Complex :a))
(define (complex-minus a b)
(complex (- (real-part a) (real-part b))
(- (imag-part a) (imag-part b))))

(declare complex-times ((Complex :a) => Complex :a -> Complex :a -> Complex :a))
(define (complex-times a b)
(let ra = (real-part a))
Expand All @@ -132,6 +142,15 @@ below.")
(let ib = (imag-part b))
(complex (- (* ra rb) (* ia ib))
(+ (* ra ib) (* ia rb))))

(declare complex-reciprocal ((Complex :a) (Reciprocable :a) => Complex :a -> Complex :a))
(define (complex-reciprocal x)
(let a = (real-part x))
(let b = (imag-part x))
(let divisor = (reciprocal (square-magnitude x)))
;; z^-1 = z*/|z|^2
(complex (* a divisor) (negate (* b divisor))))

(declare complex-divide ((Complex :a) (Complex :b) (Dividable :a :b)
=> Complex :a -> Complex :a -> Complex :b))
(define (complex-divide a b)
Expand All @@ -148,20 +167,24 @@ below.")
(plus (cl:intern (cl:concatenate 'cl:string (cl:symbol-name type) "-COMPLEX-PLUS")))
(minus (cl:intern (cl:concatenate 'cl:string (cl:symbol-name type) "-COMPLEX-MINUS")))
(times (cl:intern (cl:concatenate 'cl:string (cl:symbol-name type) "-COMPLEX-TIMES")))
(divide (cl:intern (cl:concatenate 'cl:string (cl:symbol-name type) "-COMPLEX-DIVIDE"))))
(divide (cl:intern (cl:concatenate 'cl:string (cl:symbol-name type) "-COMPLEX-DIVIDE")))
(recip (cl:intern (cl:concatenate 'cl:string (cl:symbol-name type) "-COMPLEX-RECIPROCAL"))))

`(cl:progn
(cl:pushnew ',repr *native-complex-types* :test 'cl:equal)

(coalton-toplevel
(define-instance (Complex ,type)
(inline)
(define (complex a b)
(lisp (Complex ,type) (a b)
(cl:declare (cl:type ,repr a b))
(cl:complex a b)))
(inline)
(define (real-part a)
(lisp ,type (a)
(cl:realpart a)))
(inline)
(define (imag-part a)
(lisp ,type (a)
(cl:imagpart a))))
Expand All @@ -175,39 +198,52 @@ below.")
(cl:conjugate a)))

(specialize complex-equal ,equal (Complex ,type -> Complex ,type -> Boolean))
(inline)
(declare ,equal (Complex ,type -> Complex ,type -> Boolean))
(define (,equal a b)
(lisp Boolean (a b)
(cl:declare (cl:type (cl:or ,repr (cl:complex ,repr)) a b))
(cl:= a b)))

(specialize complex-plus ,plus (Complex ,type -> Complex ,type -> Complex ,type))
(inline)
(declare ,plus (Complex ,type -> Complex ,type -> Complex ,type))
(define (,plus a b)
(lisp (Complex ,type) (a b)
(cl:declare (cl:type (cl:or ,repr (cl:complex ,repr)) a b))
(cl:+ a b)))

(specialize complex-minus ,minus (Complex ,type -> Complex ,type -> Complex ,type))
(inline)
(declare ,minus (Complex ,type -> Complex ,type -> Complex ,type))
(define (,minus a b)
(lisp (Complex ,type) (a b)
(cl:declare (cl:type (cl:or ,repr (cl:complex ,repr)) a b))
(cl:- a b)))

(specialize complex-times ,times (Complex ,type -> Complex ,type -> Complex ,type))
(inline)
(declare ,times (Complex ,type -> Complex ,type -> Complex ,type))
(define (,times a b)
(lisp (Complex ,type) (a b)
(cl:declare (cl:type (cl:or ,repr (cl:complex ,repr)) a b))
(cl:* a b)))

(specialize complex-divide ,divide (Complex ,type -> Complex ,type -> Complex ,type))
(inline)
(declare ,divide (Complex ,type -> Complex ,type -> Complex ,type))
(define (,divide a b)
(lisp (Complex ,type) (a b)
(cl:declare (cl:type (cl:or ,repr (cl:complex ,repr)) a b))
(cl:/ a b)))))))
(cl:/ a b)))

(specialize complex-reciprocal ,recip (Complex ,type -> Complex ,type))
(inline)
(declare ,recip (Complex ,type -> Complex ,type))
(define (,recip a)
(lisp (Complex ,type) (a)
(cl:declare (cl:type (cl:or ,repr (cl:complex ,repr)) a))
(cl:/ a)))))))

(%define-native-complex-instances U8 (cl:unsigned-byte 8))
(%define-native-complex-instances U16 (cl:unsigned-byte 16))
Expand All @@ -227,11 +263,14 @@ below.")
(cl:defmacro %define-standard-complex-instances (type)
`(coalton-toplevel
(define-instance (Complex ,type)
(inline)
(define (complex a b)
(%Complex a b))
(inline)
(define (real-part a)
(match a
((%Complex a _) a)))
(inline)
(define (imag-part a)
(match a
((%Complex _ b) b))))))
Expand Down
Loading

0 comments on commit aecd03c

Please sign in to comment.