Mercurial > lasercutter
view src/clojure/contrib/generic/arithmetic.clj @ 10:ef7dbbd6452c
added clojure source goodness
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 21 Aug 2010 06:25:44 -0400 |
parents | |
children |
line wrap: on
line source
1 ;; Generic interfaces for arithmetic operations3 ;; by Konrad Hinsen4 ;; last updated May 5, 20096 ;; Copyright (c) Konrad Hinsen, 2009. All rights reserved. The use7 ;; and distribution terms for this software are covered by the Eclipse8 ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)9 ;; which can be found in the file epl-v10.html at the root of this10 ;; distribution. By using this software in any fashion, you are11 ;; agreeing to be bound by the terms of this license. You must not12 ;; remove this notice, or any other, from this software.14 (ns15 ^{:author "Konrad Hinsen"16 :doc "Generic arithmetic interface17 This library defines generic versions of + - * / as multimethods18 that can be defined for any type. The minimal required19 implementations for a type are binary + and * plus unary - and /.20 Everything else is derived from these automatically. Explicit21 binary definitions for - and / can be provided for22 efficiency reasons."}23 clojure.contrib.generic.arithmetic24 (:use [clojure.contrib.generic25 :only (root-type nulary-type nary-type nary-dispatch)]26 [clojure.contrib.types :only (defadt)])27 (:refer-clojure :exclude [+ - * /]))29 ;30 ; Universal zero and one values31 ;32 (defadt ::zero zero)33 (defadt ::one one)35 (derive ::zero root-type)36 (derive ::one root-type)38 ;39 ; Addition40 ;41 ; The minimal implementation is for binary my-type. It is possible42 ; in principle to implement [::unary my-type] as well, though this43 ; doesn't make any sense.44 ;45 (defmulti +46 "Return the sum of all arguments. The minimal implementation for type47 ::my-type is the binary form with dispatch value [::my-type ::my-type]."48 {:arglists '([x] [x y] [x y & more])}49 nary-dispatch)51 (defmethod + nulary-type52 []53 zero)55 (defmethod + root-type56 [x] x)58 (defmethod + [root-type ::zero]59 [x y] x)61 (defmethod + [::zero root-type]62 [x y] y)64 (defmethod + nary-type65 [x y & more]66 (if more67 (recur (+ x y) (first more) (next more))68 (+ x y)))70 ;71 ; Subtraction72 ;73 ; The minimal implementation is for unary my-type. A default binary74 ; implementation is provided as (+ x (- y)), but it is possible to75 ; implement unary my-type explicitly for efficiency reasons.76 ;77 (defmulti -78 "Return the difference of the first argument and the sum of all other79 arguments. The minimal implementation for type ::my-type is the binary80 form with dispatch value [::my-type ::my-type]."81 {:arglists '([x] [x y] [x y & more])}82 nary-dispatch)84 (defmethod - nulary-type85 []86 (throw (java.lang.IllegalArgumentException.87 "Wrong number of arguments passed")))89 (defmethod - [root-type ::zero]90 [x y] x)92 (defmethod - [::zero root-type]93 [x y] (- y))95 (defmethod - [root-type root-type]96 [x y] (+ x (- y)))98 (defmethod - nary-type99 [x y & more]100 (if more101 (recur (- x y) (first more) (next more))102 (- x y)))104 ;105 ; Multiplication106 ;107 ; The minimal implementation is for binary [my-type my-type]. It is possible108 ; in principle to implement unary my-type as well, though this109 ; doesn't make any sense.110 ;111 (defmulti *112 "Return the product of all arguments. The minimal implementation for type113 ::my-type is the binary form with dispatch value [::my-type ::my-type]."114 {:arglists '([x] [x y] [x y & more])}115 nary-dispatch)117 (defmethod * nulary-type118 []119 one)121 (defmethod * root-type122 [x] x)124 (defmethod * [root-type ::one]125 [x y] x)127 (defmethod * [::one root-type]128 [x y] y)130 (defmethod * nary-type131 [x y & more]132 (if more133 (recur (* x y) (first more) (next more))134 (* x y)))136 ;137 ; Division138 ;139 ; The minimal implementation is for unary my-type. A default binary140 ; implementation is provided as (* x (/ y)), but it is possible to141 ; implement binary [my-type my-type] explicitly for efficiency reasons.142 ;143 (defmulti /144 "Return the quotient of the first argument and the product of all other145 arguments. The minimal implementation for type ::my-type is the binary146 form with dispatch value [::my-type ::my-type]."147 {:arglists '([x] [x y] [x y & more])}148 nary-dispatch)150 (defmethod / nulary-type151 []152 (throw (java.lang.IllegalArgumentException.153 "Wrong number of arguments passed")))155 (defmethod / [root-type ::one]156 [x y] x)158 (defmethod / [::one root-type]159 [x y] (/ y))161 (defmethod / [root-type root-type]162 [x y] (* x (/ y)))164 (defmethod / nary-type165 [x y & more]166 (if more167 (recur (/ x y) (first more) (next more))168 (/ x y)))170 ;171 ; Macros to permit access to the / multimethod via namespace qualification172 ;173 (defmacro defmethod*174 "Define a method implementation for the multimethod name in namespace ns.175 Required for implementing the division function from another namespace."176 [ns name & args]177 (let [qsym (symbol (str ns) (str name))]178 `(defmethod ~qsym ~@args)))180 (defmacro qsym181 "Create the qualified symbol corresponding to sym in namespace ns.182 Required to access the division function from another namespace,183 e.g. as (qsym clojure.contrib.generic.arithmetic /)."184 [ns sym]185 (symbol (str ns) (str sym)))187 ;188 ; Minimal implementations for java.lang.Number189 ;190 (defmethod + [java.lang.Number java.lang.Number]191 [x y] (clojure.core/+ x y))193 (defmethod - java.lang.Number194 [x] (clojure.core/- x))196 (defmethod * [java.lang.Number java.lang.Number]197 [x y] (clojure.core/* x y))199 (defmethod / java.lang.Number200 [x] (clojure.core// x))