generic.scm 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. #| -*-Scheme-*-
  2. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
  3. 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
  4. 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Massachusetts
  5. Institute of Technology
  6. This file is part of MIT/GNU Scheme.
  7. MIT/GNU Scheme is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11. MIT/GNU Scheme is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with MIT/GNU Scheme; if not, write to the Free Software
  17. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
  18. USA.
  19. |#
  20. ;;;; Primitive Generic Operation Declarations
  21. (declare (usual-integrations))
  22. ;;; Unary Operators
  23. (define g:type (make-generic-operator 1 'type))
  24. (define g:type-predicate (make-generic-operator 1 'type-predicate))
  25. (define g:arity (make-generic-operator 1 'arity (lambda (x) #f)))
  26. (define g:inexact?
  27. (make-generic-operator 1 'inexact?))
  28. (define g:zero-like
  29. (make-generic-operator 1 'zero-like (lambda (x) :zero)))
  30. (define g:one-like
  31. (make-generic-operator 1 'one-like (lambda (x) :one)))
  32. (define g:identity-like
  33. (make-generic-operator 1 'identity-like (lambda (x) g:identity)))
  34. ;;; Generic tests are conservative.
  35. ;;; They will return #f unless the answer is known true.
  36. (define generic:zero?
  37. (make-generic-operator 1 'zero? (lambda (x) #f)))
  38. (define (g:zero? x)
  39. (if (number? x) (exact-zero? x) (generic:zero? x)))
  40. (define generic:one? (make-generic-operator 1 'one? (lambda (x) #f)))
  41. (define (g:one? x)
  42. (if (number? x) (exact-one? x) (generic:one? x)))
  43. (define g:identity? (make-generic-operator 1 'identity? (lambda (x) #f)))
  44. (define g:negate (make-generic-operator 1 'negate))
  45. (define g:invert (make-generic-operator 1 'invert))
  46. (define g:square (make-generic-operator 1 'square (lambda (x) (g:* x x))))
  47. (define g:sqrt (make-generic-operator 1 'sqrt))
  48. (define g:exp (make-generic-operator 1 'exp))
  49. (define g:log (make-generic-operator 1 'log))
  50. (define g:sin (make-generic-operator 1 'sin))
  51. (define g:cos (make-generic-operator 1 'cos))
  52. (define g:asin (make-generic-operator 1 'asin))
  53. (define g:acos (make-generic-operator 1 'acos))
  54. (define g:sinh (make-generic-operator 1 'sinh))
  55. (define g:cosh (make-generic-operator 1 'cosh))
  56. (define g:abs (make-generic-operator 1 'abs))
  57. (define g:determinant (make-generic-operator 1 'determinant))
  58. ;;; FBE start: trace-both not defined
  59. ;; (define g:trace
  60. ;; (make-generic-operator 1
  61. ;; 'trace
  62. ;; ;;overlays system trace procedure trace-both
  63. ;; trace-both))
  64. (define g:trace
  65. (make-generic-operator 1 'trace))
  66. ;;; FBE end
  67. (define* (g:transpose thing #:optional shape)
  68. (if (default-object? shape)
  69. (g:transpose-1-arg thing)
  70. (s:transpose1 thing shape)))
  71. (define g:transpose-1-arg
  72. (make-generic-operator 1 'transpose))
  73. ;;; FBE start: coordinate-system-dimension is defined in
  74. ;;; 'generic-environment'. We copy here the definition from
  75. ;;; calculus/manifold.scm.
  76. (define (coordinate-system coordinate-system-name patch)
  77. ((patch 'get-coordinate-system) coordinate-system-name))
  78. (define (coordinate-system-dimension coordinate-system)
  79. (coordinate-system 'dimension))
  80. ;;; FBE end.
  81. (define g:dimension
  82. (make-generic-operator 1
  83. 'dimension
  84. (lambda (x)
  85. ;;definition in calculus/manifold.scm
  86. (coordinate-system-dimension x))))
  87. (define g:solve-linear
  88. (make-generic-operator 2 'solve-linear))
  89. ;;; Duplicate of text in OPERATOR.SCM, except that the explicit type
  90. ;;; tag is here rather than the variable operator-type-tag. This is
  91. ;;; necessary because of a problem of load order.
  92. (define* (make-operator p #:optional name subtype arity #:rest opts)
  93. (if (default-object? name) (set! name #f))
  94. (if (default-object? subtype) (set! subtype #f))
  95. (if (default-object? arity) (set! arity (procedure-arity p)))
  96. (make-apply-hook p `(*operator* ,subtype ,name ,arity ,@opts)))
  97. (define generic:partial-derivative
  98. (make-generic-operator 2 'partial-derivative))
  99. (define g:derivative
  100. (make-operator
  101. (lambda (f)
  102. (generic:partial-derivative f '()))
  103. 'derivative))
  104. (define (g:partial-derivative f . varspecs)
  105. (generic:partial-derivative f varspecs))
  106. (define (g:partial . varspecs)
  107. (make-operator
  108. (lambda (f)
  109. (generic:partial-derivative f varspecs))
  110. `(partial ,@varspecs)))
  111. ;;; Binary Operators
  112. (define generic:= (make-generic-operator 2 '= (lambda (x y) #f)))
  113. (define (g:=:bin x y)
  114. (if (and (number? x) (number? y)) (= x y) (generic:= x y)))
  115. (define generic:< (make-generic-operator 2 '< (lambda (x y) #f)))
  116. (define (g:<:bin x y)
  117. (if (and (number? x) (number? y)) (< x y) (generic:< x y)))
  118. (define generic:<= (make-generic-operator 2 '<= (lambda (x y) #f)))
  119. (define (g:<=:bin x y)
  120. (if (and (number? x) (number? y)) (<= x y) (generic:<= x y)))
  121. (define generic:> (make-generic-operator 2 '> (lambda (x y) #f)))
  122. (define (g:>:bin x y)
  123. (if (and (number? x) (number? y)) (> x y) (generic:> x y)))
  124. (define generic:>= (make-generic-operator 2 '>= (lambda (x y) #f)))
  125. (define (g:>=:bin x y)
  126. (if (and (number? x) (number? y)) (>= x y) (generic:>= x y)))
  127. (define generic:+ (make-generic-operator 2 '+))
  128. (define (g:+:bin x y)
  129. (cond ((and (number? x) (number? y)) (+ x y))
  130. ((g:zero? x) y)
  131. ((g:zero? y) x)
  132. (else (generic:+ x y))))
  133. (define generic:- (make-generic-operator 2 '-))
  134. (define (g:-:bin x y)
  135. (cond ((and (number? x) (number? y)) (- x y))
  136. ((g:zero? y) x)
  137. ((g:zero? x) (g:negate y))
  138. (else (generic:- x y))))
  139. (define generic:* (make-generic-operator 2 '*))
  140. (define (g:*:bin x y)
  141. (cond ((and (number? x) (number? y)) (* x y))
  142. ((exact-zero? x) (g:zero-like y))
  143. ((exact-zero? y) (g:zero-like x))
  144. ((g:one? x) y)
  145. ((g:one? y) x)
  146. (else (generic:* x y))))
  147. ;;; In g:*:bin we test for exact (numerical) zero
  148. ;;; because it is possible to produce a wrong-type
  149. ;;; zero here, as follows:
  150. ;;; |0| |0|
  151. ;;; |a b c| |0| |0| |0|
  152. ;;; |d e f| |0| = |0|, not |0|
  153. ;;; We are less worried about the zero? below,
  154. ;;; because any invertible matrix is square.
  155. (define generic:/ (make-generic-operator 2 '/))
  156. (define (g:/:bin x y)
  157. (cond ((and (number? x) (number? y)) (/ x y))
  158. ;; ((g:zero? x) (g:zero-like y)) ; Ancient bug! No consequence.
  159. ;; ((g:zero? x) x)
  160. ((g:one? y) x)
  161. (else (generic:/ x y))))
  162. (define generic:expt (make-generic-operator 2 'expt))
  163. (define (g:expt x y)
  164. (cond ((and (number? x) (number? y)) (n:expt x y))
  165. ;;((g:zero? x) x) ;No! consider 0^{-1}
  166. ((g:one? x) x)
  167. ((g:zero? y) (g:one-like x))
  168. ((g:one? y) x)
  169. (else (generic:expt x y))))
  170. (define g:gcd:bin (make-generic-operator 2 'gcd))
  171. (define g:dot-product (make-generic-operator 2 'dot-product))
  172. (define g:cross-product (make-generic-operator 2 'cross-product))
  173. (define g:outer-product (make-generic-operator 2 'outer-product))
  174. ;;; Complex Operators
  175. (define g:make-rectangular (make-generic-operator 2 'make-rectangular))
  176. (define g:make-polar (make-generic-operator 2 'make-polar))
  177. (define g:real-part (make-generic-operator 1 'real-part))
  178. (define g:imag-part (make-generic-operator 1 'imag-part))
  179. (define g:magnitude (make-generic-operator 1 'magnitude))
  180. (define g:angle (make-generic-operator 1 'angle))
  181. (define g:conjugate (make-generic-operator 1 'conjugate))
  182. ;;; Weird operators
  183. (define* (g:atan y #:optional x)
  184. (if (default-object? x) (g:atan1 y) (g:atan2 y x)))
  185. (define g:atan1 (make-generic-operator 1 'atan1))
  186. (define g:atan2 (make-generic-operator 2 'atan2))
  187. (define generic:apply (make-generic-operator 2 'apply))
  188. (define (g:apply f . apply-args)
  189. (define (collapse l)
  190. (if (null? (cdr l))
  191. (car l)
  192. (cons (car l)
  193. (collapse (cdr l)))))
  194. (if (null? apply-args)
  195. (error "No argument list for G:APPLY")
  196. (let ((args (collapse apply-args)))
  197. (cond ((procedure? f)
  198. (apply f args))
  199. ((applicable-literal? f)
  200. (apply
  201. (literal-function f
  202. (permissive-function-type (length args)))
  203. args))
  204. #|
  205. ((eq? f second)
  206. (apply (access second system-global-environment)
  207. args))
  208. |#
  209. (else
  210. (generic:apply f args))))))
  211. (define (applicable-literal? f)
  212. ;; FBE
  213. ;; (and (symbol? f) *enable-literal-apply*)
  214. (and (symbol? f) (*enable-literal-apply*)))
  215. ;;; *enable-literal-apply* is modulated by with-literal-apply-enabled.
  216. ;;; This procedure is defined in extapply.scm.
  217. ;;; This feature is used explicitly in ode/interface.scm.
  218. ;;; N-ary Operator extensions
  219. (define (g:= . args)
  220. (g:=:n args))
  221. (define (g:=:n args)
  222. (cond ((null? args) #t)
  223. ((null? (cdr args)) #t)
  224. (else
  225. (let lp ((args (cddr args))
  226. (larg (cadr args))
  227. (ans (g:=:bin (car args) (cadr args))))
  228. (if (null? args)
  229. ans
  230. (lp (cdr args)
  231. (car args)
  232. (and ans (g:=:bin larg (car args)))))))))
  233. (define (g:< . args)
  234. (g:<:n args))
  235. (define (g:<:n args)
  236. (cond ((null? args) #t)
  237. ((null? (cdr args)) #t)
  238. (else
  239. (let lp ((args (cddr args))
  240. (larg (cadr args))
  241. (ans (g:<:bin (car args) (cadr args))))
  242. (if (null? args)
  243. ans
  244. (lp (cdr args)
  245. (car args)
  246. (and ans (g:<:bin larg (car args)))))))))
  247. (define (g:<= . args)
  248. (g:<=:n args))
  249. (define (g:<=:n args)
  250. (cond ((null? args) #t)
  251. ((null? (cdr args)) #t)
  252. (else
  253. (let lp ((args (cddr args))
  254. (larg (cadr args))
  255. (ans (g:<=:bin (car args) (cadr args))))
  256. (if (null? args)
  257. ans
  258. (lp (cdr args)
  259. (car args)
  260. (and ans (g:<=:bin larg (car args)))))))))
  261. (define (g:> . args)
  262. (g:>:n args))
  263. (define (g:>:n args)
  264. (cond ((null? args) #t)
  265. ((null? (cdr args)) #t)
  266. (else
  267. (let lp ((args (cddr args))
  268. (larg (cadr args))
  269. (ans (g:>:bin (car args) (cadr args))))
  270. (if (null? args)
  271. ans
  272. (lp (cdr args)
  273. (car args)
  274. (and ans (g:>:bin larg (car args)))))))))
  275. (define (g:>= . args)
  276. (g:>=:n args))
  277. (define (g:>=:n args)
  278. (cond ((null? args) #t)
  279. ((null? (cdr args)) #t)
  280. (else
  281. (let lp ((args (cddr args))
  282. (larg (cadr args))
  283. (ans (g:>=:bin (car args) (cadr args))))
  284. (if (null? args)
  285. ans
  286. (lp (cdr args)
  287. (car args)
  288. (and ans (g:>=:bin larg (car args)))))))))
  289. (define (g:+ . args)
  290. (g:+:n args))
  291. (define (g:+:n args)
  292. (cond ((null? args) :zero)
  293. ((null? (cdr args)) (car args))
  294. (else
  295. (let lp ((args (cddr args))
  296. (ans (g:+:bin (car args) (cadr args))))
  297. (if (null? args)
  298. ans
  299. (lp (cdr args)
  300. (g:+:bin ans (car args))))))))
  301. (define (g:* . args)
  302. (g:*:n args))
  303. (define (g:*:n args)
  304. (cond ((null? args) :one)
  305. ((null? (cdr args)) (car args))
  306. (else
  307. (let lp ((args (cddr args))
  308. (ans (g:*:bin (car args) (cadr args))))
  309. (if (null? args)
  310. ans
  311. (lp (cdr args)
  312. (g:*:bin ans (car args))))))))
  313. (define (g:- . args)
  314. (g:-:n args))
  315. (define (g:-:n args)
  316. (cond ((null? args) :zero)
  317. ((null? (cdr args)) (g:negate (car args)))
  318. (else
  319. (g:-:bin (car args)
  320. (g:+:n (cdr args))))))
  321. (define (g:/ . args)
  322. (g:/:n args))
  323. (define (g:/:n args)
  324. (cond ((null? args) :one)
  325. ((null? (cdr args)) (g:invert (car args)))
  326. (else
  327. (g:/:bin (car args)
  328. (g:*:n (cdr args))))))
  329. (define (g:gcd . args)
  330. (g:gcd:n args))
  331. (define (g:gcd:n args)
  332. (cond ((null? args) :zero)
  333. ((null? (cdr args)) (car args))
  334. (else
  335. (let lp
  336. ((as (cddr args))
  337. (ans (g:gcd:bin (car args) (cadr args))))
  338. (cond ((null? as) ans)
  339. ((g:one? ans) ans)
  340. (else
  341. (lp (cdr as) (g:gcd:bin ans (car as)))))))))