aboutsummaryrefslogtreecommitdiff
path: root/src/clojure/contrib/generic/arithmetic.clj
diff options
context:
space:
mode:
Diffstat (limited to 'src/clojure/contrib/generic/arithmetic.clj')
-rw-r--r--src/clojure/contrib/generic/arithmetic.clj69
1 files changed, 47 insertions, 22 deletions
diff --git a/src/clojure/contrib/generic/arithmetic.clj b/src/clojure/contrib/generic/arithmetic.clj
index 558ec37b..98d5cfef 100644
--- a/src/clojure/contrib/generic/arithmetic.clj
+++ b/src/clojure/contrib/generic/arithmetic.clj
@@ -1,7 +1,7 @@
;; Generic interfaces for arithmetic operations
;; by Konrad Hinsen
-;; last updated March 12, 2009
+;; last updated March 13, 2009
;; Copyright (c) Konrad Hinsen, 2009. All rights reserved. The use
;; and distribution terms for this software are covered by the Eclipse
@@ -21,7 +21,8 @@
that can be defined for any type. The minimal required implementations
for a type are binary + and * plus unary - and /. Everything else
is derived from these automatically. Explicit binary definitions
- for - and / can be given for efficiency reasons."
+ for - and / can be provided for efficiency reasons."
+ (:use [clojure.contrib.types :only (defadt)])
(:refer-clojure :exclude [+ - * /]))
;
@@ -31,26 +32,26 @@
;
(defn- nary-dispatch
([] ::nulary)
- ([x] [::unary (type x)])
+ ([x] (type x))
([x y]
- (let [tx (type x)
- ty (type y)]
- (cond (isa? tx ty) [::binary ty]
- (isa? ty tx) [::binary tx]
- ; Should there be clause checking if tx and ty have
- ; a common ancestor? This would cover cases like
- ; java.lang.Integer and java.lang.Double, which have the
- ; common ancestor java.lang.Number.
- :else [::binary tx ty])))
+ [(type x) (type y)])
([x y & more] ::n-ary))
;
+; Universal zero and one values
+;
+(defadt ::zero zero)
+(defadt ::one one)
+
+;
; We can't use [::binary :default], so we need to define a root type
; of the type hierarcy. The derivation for Object covers all classes,
; but all non-class types will need an explicit derive clause.
; Ultimately, a macro might take care of this.
;
(derive Object ::any)
+(derive ::zero ::any)
+(derive ::one ::any)
;
; Addition
@@ -63,11 +64,17 @@
(defmethod + ::nulary
[]
- ::zero)
+ zero)
-(defmethod + [::unary ::any]
+(defmethod + ::any
[x] x)
+(defmethod + [::any ::zero]
+ [x y] x)
+
+(defmethod + [::zero ::any]
+ [x y] y)
+
(defmethod + ::n-ary
[x y & more]
(if more
@@ -88,7 +95,13 @@
(throw (java.lang.IllegalArgumentException.
"Wrong number of arguments passed")))
-(defmethod - [::binary ::any]
+(defmethod - [::any ::zero]
+ [x y] x)
+
+(defmethod - [::zero ::any]
+ [x y] (- y))
+
+(defmethod - [::any ::any]
[x y] (+ x (- y)))
(defmethod - ::n-ary
@@ -108,11 +121,17 @@
(defmethod * ::nulary
[]
- ::one)
+ one)
-(defmethod * [::unary ::any]
+(defmethod * ::any
[x] x)
+(defmethod * [::any ::one]
+ [x y] x)
+
+(defmethod * [::one ::any]
+ [x y] y)
+
(defmethod * ::n-ary
[x y & more]
(if more
@@ -133,7 +152,13 @@
(throw (java.lang.IllegalArgumentException.
"Wrong number of arguments passed")))
-(defmethod / [::binary ::any]
+(defmethod / [::any ::one]
+ [x y] x)
+
+(defmethod / [::one ::any]
+ [x y] (/ y))
+
+(defmethod / [::any ::any]
[x y] (* x (/ y)))
(defmethod / ::n-ary
@@ -145,15 +170,15 @@
;
; Minimal implementations for java.lang.Number
;
-(defmethod + [::binary java.lang.Number]
+(defmethod + [java.lang.Number java.lang.Number]
[x y] (clojure.core/+ x y))
-(defmethod - [::unary java.lang.Number]
+(defmethod - java.lang.Number
[x] (clojure.core/- x))
-(defmethod * [::binary java.lang.Number]
+(defmethod * [java.lang.Number java.lang.Number]
[x y] (clojure.core/* x y))
-(defmethod / [::unary java.lang.Number]
+(defmethod / java.lang.Number
[x] (clojure.core// x))