calc-cplx.el 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. ;;; calc-cplx.el --- Complex number functions for Calc
  2. ;; Copyright (C) 1990-1993, 2001-2012 Free Software Foundation, Inc.
  3. ;; Author: David Gillespie <daveg@synaptics.com>
  4. ;; Maintainer: Jay Belanger <jay.p.belanger@gmail.com>
  5. ;; This file is part of GNU Emacs.
  6. ;; GNU Emacs is free software: you can redistribute it and/or modify
  7. ;; it under the terms of the GNU General Public License as published by
  8. ;; the Free Software Foundation, either version 3 of the License, or
  9. ;; (at your option) any later version.
  10. ;; GNU Emacs is distributed in the hope that it will be useful,
  11. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;; GNU General Public License for more details.
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  16. ;;; Commentary:
  17. ;;; Code:
  18. ;; This file is autoloaded from calc-ext.el.
  19. (require 'calc-ext)
  20. (require 'calc-macs)
  21. (defun calc-argument (arg)
  22. (interactive "P")
  23. (calc-slow-wrapper
  24. (calc-unary-op "arg" 'calcFunc-arg arg)))
  25. (defun calc-re (arg)
  26. (interactive "P")
  27. (calc-slow-wrapper
  28. (calc-unary-op "re" 'calcFunc-re arg)))
  29. (defun calc-im (arg)
  30. (interactive "P")
  31. (calc-slow-wrapper
  32. (calc-unary-op "im" 'calcFunc-im arg)))
  33. (defun calc-polar ()
  34. (interactive)
  35. (calc-slow-wrapper
  36. (let ((arg (calc-top-n 1)))
  37. (if (or (calc-is-inverse)
  38. (eq (car-safe arg) 'polar))
  39. (calc-enter-result 1 "p-r" (list 'calcFunc-rect arg))
  40. (calc-enter-result 1 "r-p" (list 'calcFunc-polar arg))))))
  41. (defun calc-complex-notation ()
  42. (interactive)
  43. (calc-wrapper
  44. (calc-change-mode 'calc-complex-format nil t)
  45. (message "Displaying complex numbers in (X,Y) format")))
  46. (defun calc-i-notation ()
  47. (interactive)
  48. (calc-wrapper
  49. (calc-change-mode 'calc-complex-format 'i t)
  50. (message "Displaying complex numbers in X+Yi format")))
  51. (defun calc-j-notation ()
  52. (interactive)
  53. (calc-wrapper
  54. (calc-change-mode 'calc-complex-format 'j t)
  55. (message "Displaying complex numbers in X+Yj format")))
  56. (defun calc-polar-mode (n)
  57. (interactive "P")
  58. (calc-wrapper
  59. (if (if n
  60. (> (prefix-numeric-value n) 0)
  61. (eq calc-complex-mode 'cplx))
  62. (progn
  63. (calc-change-mode 'calc-complex-mode 'polar)
  64. (message "Preferred complex form is polar"))
  65. (calc-change-mode 'calc-complex-mode 'cplx)
  66. (message "Preferred complex form is rectangular"))))
  67. ;;;; Complex numbers.
  68. (defun math-normalize-polar (a)
  69. (let ((r (math-normalize (nth 1 a)))
  70. (th (math-normalize (nth 2 a))))
  71. (cond ((math-zerop r)
  72. '(polar 0 0))
  73. ((or (math-zerop th))
  74. r)
  75. ((and (not (eq calc-angle-mode 'rad))
  76. (or (equal th '(float 18 1))
  77. (equal th 180)))
  78. (math-neg r))
  79. ((math-negp r)
  80. (math-neg (list 'polar (math-neg r) th)))
  81. (t
  82. (list 'polar r th)))))
  83. ;;; Coerce A to be complex (rectangular form). [c N]
  84. (defun math-complex (a)
  85. (cond ((eq (car-safe a) 'cplx) a)
  86. ((eq (car-safe a) 'polar)
  87. (if (math-zerop (nth 1 a))
  88. (nth 1 a)
  89. (let ((sc (calcFunc-sincos (nth 2 a))))
  90. (list 'cplx
  91. (math-mul (nth 1 a) (nth 1 sc))
  92. (math-mul (nth 1 a) (nth 2 sc))))))
  93. (t (list 'cplx a 0))))
  94. ;;; Coerce A to be complex (polar form). [c N]
  95. (defun math-polar (a)
  96. (cond ((eq (car-safe a) 'polar) a)
  97. ((math-zerop a) '(polar 0 0))
  98. (t
  99. (list 'polar
  100. (math-abs a)
  101. (calcFunc-arg a)))))
  102. ;;; Multiply A by the imaginary constant i. [N N] [Public]
  103. (defun math-imaginary (a)
  104. (if (and (or (Math-objvecp a) (math-infinitep a))
  105. (not calc-symbolic-mode))
  106. (math-mul a
  107. (if (or (eq (car-safe a) 'polar)
  108. (and (not (eq (car-safe a) 'cplx))
  109. (eq calc-complex-mode 'polar)))
  110. (list 'polar 1 (math-quarter-circle nil))
  111. '(cplx 0 1)))
  112. (math-mul a '(var i var-i))))
  113. (defun math-want-polar (a b)
  114. (cond ((eq (car-safe a) 'polar)
  115. (if (eq (car-safe b) 'cplx)
  116. (eq calc-complex-mode 'polar)
  117. t))
  118. ((eq (car-safe a) 'cplx)
  119. (if (eq (car-safe b) 'polar)
  120. (eq calc-complex-mode 'polar)
  121. nil))
  122. ((eq (car-safe b) 'polar)
  123. t)
  124. ((eq (car-safe b) 'cplx)
  125. nil)
  126. (t (eq calc-complex-mode 'polar))))
  127. ;;; Force A to be in the (-pi,pi] or (-180,180] range.
  128. (defun math-fix-circular (a &optional dir) ; [R R]
  129. (cond ((eq (car-safe a) 'hms)
  130. (cond ((and (Math-lessp 180 (nth 1 a)) (not (eq dir 1)))
  131. (math-fix-circular (math-add a '(float -36 1)) -1))
  132. ((or (Math-lessp -180 (nth 1 a)) (eq dir -1))
  133. a)
  134. (t
  135. (math-fix-circular (math-add a '(float 36 1)) 1))))
  136. ((eq calc-angle-mode 'rad)
  137. (cond ((and (Math-lessp (math-pi) a) (not (eq dir 1)))
  138. (math-fix-circular (math-sub a (math-two-pi)) -1))
  139. ((or (Math-lessp (math-neg (math-pi)) a) (eq dir -1))
  140. a)
  141. (t
  142. (math-fix-circular (math-add a (math-two-pi)) 1))))
  143. (t
  144. (cond ((and (Math-lessp '(float 18 1) a) (not (eq dir 1)))
  145. (math-fix-circular (math-add a '(float -36 1)) -1))
  146. ((or (Math-lessp '(float -18 1) a) (eq dir -1))
  147. a)
  148. (t
  149. (math-fix-circular (math-add a '(float 36 1)) 1))))))
  150. ;;;; Complex numbers.
  151. (defun calcFunc-polar (a) ; [C N] [Public]
  152. (cond ((Math-vectorp a)
  153. (math-map-vec 'calcFunc-polar a))
  154. ((Math-realp a) a)
  155. ((Math-numberp a)
  156. (math-normalize (math-polar a)))
  157. (t (list 'calcFunc-polar a))))
  158. (defun calcFunc-rect (a) ; [N N] [Public]
  159. (cond ((Math-vectorp a)
  160. (math-map-vec 'calcFunc-rect a))
  161. ((Math-realp a) a)
  162. ((Math-numberp a)
  163. (math-normalize (math-complex a)))
  164. (t (list 'calcFunc-rect a))))
  165. ;;; Compute the complex conjugate of A. [O O] [Public]
  166. (defun calcFunc-conj (a)
  167. (let (aa bb)
  168. (cond ((Math-realp a)
  169. a)
  170. ((eq (car a) 'cplx)
  171. (list 'cplx (nth 1 a) (math-neg (nth 2 a))))
  172. ((eq (car a) 'polar)
  173. (list 'polar (nth 1 a) (math-neg (nth 2 a))))
  174. ((eq (car a) 'vec)
  175. (math-map-vec 'calcFunc-conj a))
  176. ((eq (car a) 'calcFunc-conj)
  177. (nth 1 a))
  178. ((math-known-realp a)
  179. a)
  180. ((and (equal a '(var i var-i))
  181. (math-imaginary-i))
  182. (math-neg a))
  183. ((and (memq (car a) '(+ - * /))
  184. (progn
  185. (setq aa (calcFunc-conj (nth 1 a))
  186. bb (calcFunc-conj (nth 2 a)))
  187. (or (not (eq (car-safe aa) 'calcFunc-conj))
  188. (not (eq (car-safe bb) 'calcFunc-conj)))))
  189. (if (eq (car a) '+)
  190. (math-add aa bb)
  191. (if (eq (car a) '-)
  192. (math-sub aa bb)
  193. (if (eq (car a) '*)
  194. (math-mul aa bb)
  195. (math-div aa bb)))))
  196. ((eq (car a) 'neg)
  197. (math-neg (calcFunc-conj (nth 1 a))))
  198. ((let ((inf (math-infinitep a)))
  199. (and inf
  200. (math-mul (calcFunc-conj (math-infinite-dir a inf)) inf))))
  201. (t (calc-record-why 'numberp a)
  202. (list 'calcFunc-conj a)))))
  203. ;;; Compute the complex argument of A. [F N] [Public]
  204. (defun calcFunc-arg (a)
  205. (cond ((Math-anglep a)
  206. (if (math-negp a) (math-half-circle nil) 0))
  207. ((eq (car-safe a) 'cplx)
  208. (calcFunc-arctan2 (nth 2 a) (nth 1 a)))
  209. ((eq (car-safe a) 'polar)
  210. (nth 2 a))
  211. ((eq (car a) 'vec)
  212. (math-map-vec 'calcFunc-arg a))
  213. ((and (equal a '(var i var-i))
  214. (math-imaginary-i))
  215. (math-quarter-circle t))
  216. ((and (equal a '(neg (var i var-i)))
  217. (math-imaginary-i))
  218. (math-neg (math-quarter-circle t)))
  219. ((let ((signs (math-possible-signs a)))
  220. (or (and (memq signs '(2 4 6)) 0)
  221. (and (eq signs 1) (math-half-circle nil)))))
  222. ((math-infinitep a)
  223. (if (or (equal a '(var uinf var-uinf))
  224. (equal a '(var nan var-nan)))
  225. '(var nan var-nan)
  226. (calcFunc-arg (math-infinite-dir a))))
  227. (t (calc-record-why 'numvecp a)
  228. (list 'calcFunc-arg a))))
  229. (defun math-imaginary-i ()
  230. (let ((val (calc-var-value 'var-i)))
  231. (or (eq (car-safe val) 'special-const)
  232. (equal val '(cplx 0 1))
  233. (and (eq (car-safe val) 'polar)
  234. (eq (nth 1 val) 0)
  235. (Math-equal (nth 1 val) (math-quarter-circle nil))))))
  236. ;;; Extract the real or complex part of a complex number. [R N] [Public]
  237. ;;; Also extracts the real part of a modulo form.
  238. (defun calcFunc-re (a)
  239. (let (aa bb)
  240. (cond ((Math-realp a) a)
  241. ((memq (car a) '(mod cplx))
  242. (nth 1 a))
  243. ((eq (car a) 'polar)
  244. (math-mul (nth 1 a) (calcFunc-cos (nth 2 a))))
  245. ((eq (car a) 'vec)
  246. (math-map-vec 'calcFunc-re a))
  247. ((math-known-realp a) a)
  248. ((eq (car a) 'calcFunc-conj)
  249. (calcFunc-re (nth 1 a)))
  250. ((and (equal a '(var i var-i))
  251. (math-imaginary-i))
  252. 0)
  253. ((and (memq (car a) '(+ - *))
  254. (progn
  255. (setq aa (calcFunc-re (nth 1 a))
  256. bb (calcFunc-re (nth 2 a)))
  257. (or (not (eq (car-safe aa) 'calcFunc-re))
  258. (not (eq (car-safe bb) 'calcFunc-re)))))
  259. (if (eq (car a) '+)
  260. (math-add aa bb)
  261. (if (eq (car a) '-)
  262. (math-sub aa bb)
  263. (math-sub (math-mul aa bb)
  264. (math-mul (calcFunc-im (nth 1 a))
  265. (calcFunc-im (nth 2 a)))))))
  266. ((and (eq (car a) '/)
  267. (math-known-realp (nth 2 a)))
  268. (math-div (calcFunc-re (nth 1 a)) (nth 2 a)))
  269. ((eq (car a) 'neg)
  270. (math-neg (calcFunc-re (nth 1 a))))
  271. (t (calc-record-why 'numberp a)
  272. (list 'calcFunc-re a)))))
  273. (defun calcFunc-im (a)
  274. (let (aa bb)
  275. (cond ((Math-realp a)
  276. (if (math-floatp a) '(float 0 0) 0))
  277. ((eq (car a) 'cplx)
  278. (nth 2 a))
  279. ((eq (car a) 'polar)
  280. (math-mul (nth 1 a) (calcFunc-sin (nth 2 a))))
  281. ((eq (car a) 'vec)
  282. (math-map-vec 'calcFunc-im a))
  283. ((math-known-realp a)
  284. 0)
  285. ((eq (car a) 'calcFunc-conj)
  286. (math-neg (calcFunc-im (nth 1 a))))
  287. ((and (equal a '(var i var-i))
  288. (math-imaginary-i))
  289. 1)
  290. ((and (memq (car a) '(+ - *))
  291. (progn
  292. (setq aa (calcFunc-im (nth 1 a))
  293. bb (calcFunc-im (nth 2 a)))
  294. (or (not (eq (car-safe aa) 'calcFunc-im))
  295. (not (eq (car-safe bb) 'calcFunc-im)))))
  296. (if (eq (car a) '+)
  297. (math-add aa bb)
  298. (if (eq (car a) '-)
  299. (math-sub aa bb)
  300. (math-add (math-mul (calcFunc-re (nth 1 a)) bb)
  301. (math-mul aa (calcFunc-re (nth 2 a)))))))
  302. ((and (eq (car a) '/)
  303. (math-known-realp (nth 2 a)))
  304. (math-div (calcFunc-im (nth 1 a)) (nth 2 a)))
  305. ((eq (car a) 'neg)
  306. (math-neg (calcFunc-im (nth 1 a))))
  307. (t (calc-record-why 'numberp a)
  308. (list 'calcFunc-im a)))))
  309. (provide 'calc-cplx)
  310. ;;; calc-cplx.el ends here