1 ;;; calc-map.el --- higher-order functions for Calc
3 ;; Copyright (C) 1990, 1991, 1992, 1993, 2001, 2002, 2003, 2004,
4 ;; 2005, 2006, 2007 Free Software Foundation, Inc.
6 ;; Author: David Gillespie <daveg@synaptics.com>
7 ;; Maintainer: Jay Belanger <jay.p.belanger@gmail.com>
9 ;; This file is part of GNU Emacs.
11 ;; GNU Emacs is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 3, or (at your option)
16 ;; GNU Emacs is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 ;; Boston, MA 02110-1301, USA.
30 ;; This file is autoloaded from calc-ext.el.
35 (defun calc-apply (&optional oper
)
39 (calc-dollar-values (mapcar 'calc-get-stack-element
40 (nthcdr calc-stack-top calc-stack
)))
42 (oper (or oper
(calc-get-operator "Apply"
43 (if (math-vectorp (calc-top 1))
44 (1- (length (calc-top 1)))
46 (expr (calc-top-n (1+ calc-dollar-used
))))
47 (message "Working...")
48 (calc-set-command-flag 'clear-message
)
49 (calc-enter-result (1+ calc-dollar-used
)
50 (concat (substring "apl" 0 (- 4 (length (nth 2 oper
))))
53 (math-calcFunc-to-var (nth 1 oper
))
56 (defun calc-reduce (&optional oper accum
)
60 (nest (calc-is-hyperbolic))
61 (rev (calc-is-inverse))
62 (nargs (if (and nest
(not rev
)) 2 1))
63 (calc-dollar-values (mapcar 'calc-get-stack-element
64 (nthcdr calc-stack-top calc-stack
)))
66 (calc-mapping-dir (and (not accum
) (not nest
) ""))
67 (oper (or oper
(calc-get-operator
69 (concat (if accum
"Accumulate " "")
70 (if rev
"Fixed Point" "Nest"))
71 (concat (if rev
"Inv " "")
72 (if accum
"Accumulate" "Reduce")))
74 (message "Working...")
75 (calc-set-command-flag 'clear-message
)
76 (calc-enter-result (+ calc-dollar-used nargs
)
77 (concat (substring (if nest
79 (if accum
"acc" "red"))
80 0 (- 4 (length (nth 2 oper
))))
84 (if accum
'calcFunc-afixp
'calcFunc-fixp
)
85 (if accum
'calcFunc-anest
'calcFunc-nest
))
86 (cons (math-calcFunc-to-var (nth 1 oper
))
88 nargs
(1+ calc-dollar-used
))))
90 (if rev
'calcFunc-raccum
'calcFunc-accum
)
91 (intern (concat "calcFunc-"
95 (math-calcFunc-to-var (nth 1 oper
))
96 (calc-top-n (1+ calc-dollar-used
))))))))
98 (defun calc-accumulate (&optional oper
)
100 (calc-reduce oper t
))
102 (defun calc-map (&optional oper
)
105 (let* ((sel-mode nil
)
106 (calc-dollar-values (mapcar 'calc-get-stack-element
107 (nthcdr calc-stack-top calc-stack
)))
109 (calc-mapping-dir "")
110 (oper (or oper
(calc-get-operator "Map")))
112 (message "Working...")
113 (calc-set-command-flag 'clear-message
)
114 (calc-enter-result (+ nargs calc-dollar-used
)
115 (concat (substring "map" 0 (- 4 (length (nth 2 oper
))))
117 (cons (intern (concat "calcFunc-map" calc-mapping-dir
))
118 (cons (math-calcFunc-to-var (nth 1 oper
))
121 (1+ calc-dollar-used
))))))))
123 (defun calc-map-equation (&optional oper
)
126 (let* ((sel-mode nil
)
127 (calc-dollar-values (mapcar 'calc-get-stack-element
128 (nthcdr calc-stack-top calc-stack
)))
130 (oper (or oper
(calc-get-operator "Map-equation")))
132 (message "Working...")
133 (calc-set-command-flag 'clear-message
)
134 (calc-enter-result (+ nargs calc-dollar-used
)
135 (concat (substring "map" 0 (- 4 (length (nth 2 oper
))))
137 (cons (if (calc-is-inverse)
139 (if (calc-is-hyperbolic)
140 'calcFunc-mapeqp
'calcFunc-mapeq
))
141 (cons (math-calcFunc-to-var (nth 1 oper
))
144 (1+ calc-dollar-used
))))))))
146 (defvar calc-verify-arglist t
)
147 (defvar calc-mapping-dir nil
)
148 (defun calc-map-stack ()
149 "This is meant to be called by calc-keypad mode."
151 (let ((calc-verify-arglist nil
))
152 (calc-unread-command ?\$
)
155 (defun calc-outer-product (&optional oper
)
158 (let* ((sel-mode nil
)
159 (calc-dollar-values (mapcar 'calc-get-stack-element
160 (nthcdr calc-stack-top calc-stack
)))
162 (oper (or oper
(calc-get-operator "Outer" 2))))
163 (message "Working...")
164 (calc-set-command-flag 'clear-message
)
165 (calc-enter-result (+ 2 calc-dollar-used
)
166 (concat (substring "out" 0 (- 4 (length (nth 2 oper
))))
168 (cons 'calcFunc-outer
169 (cons (math-calcFunc-to-var (nth 1 oper
))
171 2 (1+ calc-dollar-used
))))))))
173 (defun calc-inner-product (&optional mul-oper add-oper
)
176 (let* ((sel-mode nil
)
177 (calc-dollar-values (mapcar 'calc-get-stack-element
178 (nthcdr calc-stack-top calc-stack
)))
180 (mul-oper (or mul-oper
(calc-get-operator "Inner (Mult)" 2)))
181 (mul-used calc-dollar-used
)
182 (calc-dollar-values (if (> mul-used
0)
183 (cdr calc-dollar-values
)
186 (add-oper (or add-oper
(calc-get-operator "Inner (Add)" 2))))
187 (message "Working...")
188 (calc-set-command-flag 'clear-message
)
189 (calc-enter-result (+ 2 mul-used calc-dollar-used
)
191 (substring (nth 2 mul-oper
) 0 1)
192 (substring (nth 2 add-oper
) 0 1))
193 (nconc (list 'calcFunc-inner
194 (math-calcFunc-to-var (nth 1 mul-oper
))
195 (math-calcFunc-to-var (nth 1 add-oper
)))
197 2 (+ 1 mul-used calc-dollar-used
)))))))
199 (defconst calc-oper-keys
'( ( ( ?
+ 2 calcFunc-add
)
200 ( ?-
2 calcFunc-sub
)
201 ( ?
* 2 calcFunc-mul
)
202 ( ?
/ 2 calcFunc-div
)
203 ( ?^
2 calcFunc-pow
)
204 ( ?|
2 calcFunc-vconcat
)
205 ( ?%
2 calcFunc-mod
)
206 ( ?
\\ 2 calcFunc-idiv
)
207 ( ?
! 1 calcFunc-fact
)
208 ( ?
& 1 calcFunc-inv
)
209 ( ?n
1 calcFunc-neg
)
212 ( ?A
1 calcFunc-abs
)
213 ( ?J
1 calcFunc-conj
)
214 ( ?G
1 calcFunc-arg
)
215 ( ?Q
1 calcFunc-sqrt
)
216 ( ?N
2 calcFunc-min
)
217 ( ?X
2 calcFunc-max
)
218 ( ?F
1 calcFunc-floor
)
219 ( ?R
1 calcFunc-round
)
220 ( ?S
1 calcFunc-sin
)
221 ( ?C
1 calcFunc-cos
)
222 ( ?T
1 calcFunc-tan
)
224 ( ?E
1 calcFunc-exp
)
225 ( ?B
2 calcFunc-log
) )
226 ( ( ?F
1 calcFunc-ceil
) ; inverse
227 ( ?R
1 calcFunc-trunc
)
228 ( ?Q
1 calcFunc-sqr
)
229 ( ?S
1 calcFunc-arcsin
)
230 ( ?C
1 calcFunc-arccos
)
231 ( ?T
1 calcFunc-arctan
)
232 ( ?L
1 calcFunc-exp
)
234 ( ?B
2 calcFunc-alog
)
235 ( ?^
2 calcFunc-nroot
)
236 ( ?|
2 calcFunc-vconcatrev
) )
237 ( ( ?F
1 calcFunc-ffloor
) ; hyperbolic
238 ( ?R
1 calcFunc-fround
)
239 ( ?S
1 calcFunc-sinh
)
240 ( ?C
1 calcFunc-cosh
)
241 ( ?T
1 calcFunc-tanh
)
242 ( ?L
1 calcFunc-log10
)
243 ( ?E
1 calcFunc-exp10
)
244 ( ?|
2 calcFunc-append
) )
245 ( ( ?F
1 calcFunc-fceil
) ; inverse-hyperbolic
246 ( ?R
1 calcFunc-ftrunc
)
247 ( ?S
1 calcFunc-arcsinh
)
248 ( ?C
1 calcFunc-arccosh
)
249 ( ?T
1 calcFunc-arctanh
)
250 ( ?L
1 calcFunc-exp10
)
251 ( ?E
1 calcFunc-log10
)
252 ( ?|
2 calcFunc-appendrev
) )))
254 (defconst calc-a-oper-keys
'( ( ( ?a
3 calcFunc-apart
)
255 ( ?b
3 calcFunc-subst
)
256 ( ?c
2 calcFunc-collect
)
257 ( ?d
2 calcFunc-deriv
)
258 ( ?e
1 calcFunc-esimplify
)
259 ( ?f
2 calcFunc-factor
)
260 ( ?g
2 calcFunc-pgcd
)
261 ( ?i
2 calcFunc-integ
)
262 ( ?m
2 calcFunc-match
)
263 ( ?n
1 calcFunc-nrat
)
264 ( ?r
2 calcFunc-rewrite
)
265 ( ?s
1 calcFunc-simplify
)
266 ( ?t
3 calcFunc-taylor
)
267 ( ?x
1 calcFunc-expand
)
268 ( ?M
2 calcFunc-mapeq
)
269 ( ?N
3 calcFunc-minimize
)
270 ( ?P
2 calcFunc-roots
)
271 ( ?R
3 calcFunc-root
)
272 ( ?S
2 calcFunc-solve
)
273 ( ?T
4 calcFunc-table
)
274 ( ?X
3 calcFunc-maximize
)
276 ( ?\
# 2 calcFunc-neq
)
279 ( ?\
[ 2 calcFunc-leq
)
280 ( ?\
] 2 calcFunc-geq
)
282 ( ?
! 1 calcFunc-lnot
)
283 ( ?
& 2 calcFunc-land
)
284 ( ?\|
2 calcFunc-lor
)
286 ( ?.
2 calcFunc-rmeq
)
287 ( ?
+ 4 calcFunc-sum
)
288 ( ?-
4 calcFunc-asum
)
289 ( ?
* 4 calcFunc-prod
)
290 ( ?_
2 calcFunc-subscr
)
291 ( ?
\\ 2 calcFunc-pdiv
)
292 ( ?%
2 calcFunc-prem
)
293 ( ?
/ 2 calcFunc-pdivrem
) )
294 ( ( ?m
2 calcFunc-matchnot
)
295 ( ?M
2 calcFunc-mapeqr
)
296 ( ?S
2 calcFunc-finv
) )
297 ( ( ?d
2 calcFunc-tderiv
)
298 ( ?f
2 calcFunc-factors
)
299 ( ?M
2 calcFunc-mapeqp
)
300 ( ?N
3 calcFunc-wminimize
)
301 ( ?R
3 calcFunc-wroot
)
302 ( ?S
2 calcFunc-fsolve
)
303 ( ?X
3 calcFunc-wmaximize
)
304 ( ?
/ 2 calcFunc-pdivide
) )
305 ( ( ?S
2 calcFunc-ffinv
) )))
307 (defconst calc-b-oper-keys
'( ( ( ?a
2 calcFunc-and
)
309 ( ?x
2 calcFunc-xor
)
310 ( ?d
2 calcFunc-diff
)
311 ( ?n
1 calcFunc-not
)
312 ( ?c
1 calcFunc-clip
)
313 ( ?l
2 calcFunc-lsh
)
314 ( ?r
2 calcFunc-rsh
)
315 ( ?L
2 calcFunc-ash
)
316 ( ?R
2 calcFunc-rash
)
317 ( ?t
2 calcFunc-rot
)
318 ( ?p
1 calcFunc-vpack
)
319 ( ?u
1 calcFunc-vunpack
)
320 ( ?D
4 calcFunc-ddb
)
322 ( ?I
1 calcFunc-irr
)
323 ( ?M
3 calcFunc-pmt
)
324 ( ?N
2 calcFunc-npv
)
326 ( ?S
3 calcFunc-sln
)
327 ( ?T
3 calcFunc-rate
)
328 ( ?Y
4 calcFunc-syd
)
329 ( ?\
# 3 calcFunc-nper
)
330 ( ?\%
2 calcFunc-relch
) )
331 ( ( ?F
3 calcFunc-fvb
)
332 ( ?I
1 calcFunc-irrb
)
333 ( ?M
3 calcFunc-pmtb
)
334 ( ?N
2 calcFunc-npvb
)
335 ( ?P
3 calcFunc-pvb
)
336 ( ?T
3 calcFunc-rateb
)
337 ( ?\
# 3 calcFunc-nperb
) )
338 ( ( ?F
3 calcFunc-fvl
)
339 ( ?M
3 calcFunc-pmtl
)
340 ( ?P
3 calcFunc-pvl
)
341 ( ?T
3 calcFunc-ratel
)
342 ( ?\
# 3 calcFunc-nperl
) )))
344 (defconst calc-c-oper-keys
'( ( ( ?d
1 calcFunc-deg
)
345 ( ?r
1 calcFunc-rad
)
346 ( ?h
1 calcFunc-hms
)
347 ( ?f
1 calcFunc-float
)
348 ( ?F
1 calcFunc-frac
) )))
350 (defconst calc-f-oper-keys
'( ( ( ?b
2 calcFunc-beta
)
351 ( ?e
1 calcFunc-erf
)
352 ( ?g
1 calcFunc-gamma
)
353 ( ?h
2 calcFunc-hypot
)
355 ( ?j
2 calcFunc-besJ
)
356 ( ?n
2 calcFunc-min
)
358 ( ?s
1 calcFunc-sign
)
359 ( ?x
2 calcFunc-max
)
360 ( ?y
2 calcFunc-besY
)
361 ( ?A
1 calcFunc-abssqr
)
362 ( ?B
3 calcFunc-betaI
)
363 ( ?E
1 calcFunc-expm1
)
364 ( ?G
2 calcFunc-gammaP
)
365 ( ?I
2 calcFunc-ilog
)
366 ( ?L
1 calcFunc-lnp1
)
367 ( ?M
1 calcFunc-mant
)
368 ( ?Q
1 calcFunc-isqrt
)
369 ( ?S
1 calcFunc-scf
)
370 ( ?T
2 calcFunc-arctan2
)
371 ( ?X
1 calcFunc-xpon
)
372 ( ?\
[ 2 calcFunc-decr
)
373 ( ?\
] 2 calcFunc-incr
) )
374 ( ( ?e
1 calcFunc-erfc
)
375 ( ?E
1 calcFunc-lnp1
)
376 ( ?G
2 calcFunc-gammaQ
)
377 ( ?L
1 calcFunc-expm1
) )
378 ( ( ?B
3 calcFunc-betaB
)
379 ( ?G
2 calcFunc-gammag
) )
380 ( ( ?G
2 calcFunc-gammaG
) )))
382 (defconst calc-k-oper-keys
'( ( ( ?b
1 calcFunc-bern
)
383 ( ?c
2 calcFunc-choose
)
384 ( ?d
1 calcFunc-dfact
)
385 ( ?e
1 calcFunc-euler
)
386 ( ?f
1 calcFunc-prfac
)
387 ( ?g
2 calcFunc-gcd
)
388 ( ?h
2 calcFunc-shuffle
)
389 ( ?l
2 calcFunc-lcm
)
390 ( ?m
1 calcFunc-moebius
)
391 ( ?n
1 calcFunc-nextprime
)
392 ( ?r
1 calcFunc-random
)
393 ( ?s
2 calcFunc-stir1
)
394 ( ?t
1 calcFunc-totient
)
395 ( ?B
3 calcFunc-utpb
)
396 ( ?C
2 calcFunc-utpc
)
397 ( ?F
3 calcFunc-utpf
)
398 ( ?N
3 calcFunc-utpn
)
399 ( ?P
2 calcFunc-utpp
)
400 ( ?T
2 calcFunc-utpt
) )
401 ( ( ?n
1 calcFunc-prevprime
)
402 ( ?B
3 calcFunc-ltpb
)
403 ( ?C
2 calcFunc-ltpc
)
404 ( ?F
3 calcFunc-ltpf
)
405 ( ?N
3 calcFunc-ltpn
)
406 ( ?P
2 calcFunc-ltpp
)
407 ( ?T
2 calcFunc-ltpt
) )
408 ( ( ?b
2 calcFunc-bern
)
409 ( ?c
2 calcFunc-perm
)
410 ( ?e
2 calcFunc-euler
)
411 ( ?s
2 calcFunc-stir2
) )))
413 (defconst calc-s-oper-keys
'( ( ( ?
: 2 calcFunc-assign
)
414 ( ?
= 1 calcFunc-evalto
) )))
416 (defconst calc-t-oper-keys
'( ( ( ?C
3 calcFunc-tzconv
)
417 ( ?D
1 calcFunc-date
)
418 ( ?I
2 calcFunc-incmonth
)
419 ( ?J
1 calcFunc-julian
)
420 ( ?M
1 calcFunc-newmonth
)
421 ( ?W
1 calcFunc-newweek
)
422 ( ?U
1 calcFunc-unixtime
)
423 ( ?Y
1 calcFunc-newyear
) )))
425 (defconst calc-u-oper-keys
'( ( ( ?C
2 calcFunc-vcov
)
426 ( ?G
1 calcFunc-vgmean
)
427 ( ?M
1 calcFunc-vmean
)
428 ( ?N
1 calcFunc-vmin
)
429 ( ?S
1 calcFunc-vsdev
)
430 ( ?X
1 calcFunc-vmax
) )
431 ( ( ?C
2 calcFunc-vpcov
)
432 ( ?M
1 calcFunc-vmeane
)
433 ( ?S
1 calcFunc-vpsdev
) )
434 ( ( ?C
2 calcFunc-vcorr
)
435 ( ?G
1 calcFunc-agmean
)
436 ( ?M
1 calcFunc-vmedian
)
437 ( ?S
1 calcFunc-vvar
) )
438 ( ( ?M
1 calcFunc-vhmean
)
439 ( ?S
1 calcFunc-vpvar
) )))
441 (defconst calc-v-oper-keys
'( ( ( ?a
2 calcFunc-arrange
)
442 ( ?b
2 calcFunc-cvec
)
443 ( ?c
2 calcFunc-mcol
)
444 ( ?d
2 calcFunc-diag
)
445 ( ?e
2 calcFunc-vexp
)
446 ( ?f
2 calcFunc-find
)
447 ( ?h
1 calcFunc-head
)
448 ( ?k
2 calcFunc-cons
)
449 ( ?l
1 calcFunc-vlen
)
450 ( ?m
2 calcFunc-vmask
)
451 ( ?n
1 calcFunc-rnorm
)
452 ( ?p
2 calcFunc-pack
)
453 ( ?r
2 calcFunc-mrow
)
454 ( ?s
3 calcFunc-subvec
)
455 ( ?t
1 calcFunc-trn
)
456 ( ?u
1 calcFunc-unpack
)
457 ( ?v
1 calcFunc-rev
)
458 ( ?x
1 calcFunc-index
)
459 ( ?A
1 calcFunc-apply
)
460 ( ?C
1 calcFunc-cross
)
461 ( ?D
1 calcFunc-det
)
462 ( ?E
1 calcFunc-venum
)
463 ( ?F
1 calcFunc-vfloor
)
464 ( ?G
1 calcFunc-grade
)
465 ( ?H
2 calcFunc-histogram
)
466 ( ?I
2 calcFunc-inner
)
467 ( ?L
1 calcFunc-lud
)
468 ( ?M
0 calcFunc-map
)
469 ( ?N
1 calcFunc-cnorm
)
470 ( ?O
2 calcFunc-outer
)
471 ( ?R
1 calcFunc-reduce
)
472 ( ?S
1 calcFunc-sort
)
474 ( ?U
1 calcFunc-accum
)
475 ( ?V
2 calcFunc-vunion
)
476 ( ?X
2 calcFunc-vxor
)
477 ( ?-
2 calcFunc-vdiff
)
478 ( ?^
2 calcFunc-vint
)
479 ( ?~
1 calcFunc-vcompl
)
480 ( ?
# 1 calcFunc-vcard
)
481 ( ?
: 1 calcFunc-vspan
)
482 ( ?
+ 1 calcFunc-rdup
) )
483 ( ( ?h
1 calcFunc-tail
)
484 ( ?s
3 calcFunc-rsubvec
)
485 ( ?G
1 calcFunc-rgrade
)
486 ( ?R
1 calcFunc-rreduce
)
487 ( ?S
1 calcFunc-rsort
)
488 ( ?U
1 calcFunc-raccum
) )
489 ( ( ?e
3 calcFunc-vexp
)
490 ( ?h
1 calcFunc-rhead
)
491 ( ?k
2 calcFunc-rcons
)
492 ( ?H
3 calcFunc-histogram
)
493 ( ?R
2 calcFunc-nest
)
494 ( ?U
2 calcFunc-anest
) )
495 ( ( ?h
1 calcFunc-rtail
)
496 ( ?R
1 calcFunc-fixp
)
497 ( ?U
1 calcFunc-afixp
) )))
500 ;;; Return a list of the form (nargs func name)
501 (defvar calc-get-operator-history nil
502 "History for calc-get-operator.")
504 (defun calc-get-operator (msg &optional nargs
)
505 (setq calc-aborted-prefix nil
)
506 (let ((inv nil
) (hyp nil
) (prefix nil
) (forcenargs nil
)
507 done key oper
(which 0)
508 (msgs '( "(Press ? for help)"
509 "+, -, *, /, ^, %, \\, :, &, !, |, Neg"
510 "SHIFT + Abs, conJ, arG; maX, miN; Floor, Round; sQrt"
511 "SHIFT + Inv, Hyp; Sin, Cos, Tan; Exp, Ln, logB"
512 "Algebra + Simp, Esimp, Deriv, Integ, !, =, etc."
513 "Binary + And, Or, Xor, Diff; l/r/t/L/R shifts; Not, Clip"
514 "Conversions + Deg, Rad, HMS; Float; SHIFT + Fraction"
515 "Functions + Re, Im; Hypot; Mant, Expon, Scale; etc."
516 "Kombinatorics + Dfact, Lcm, Gcd, Choose; Random; etc."
517 "Time/date + newYear, Incmonth, etc."
518 "Vectors + Length, Row, Col, Diag, Mask, etc."
519 "_ = mapr/reducea, : = mapc/reduced, = = reducer"
520 "X or Z = any function by name; ' = alg entry; $ = stack")))
522 (message "%s%s: %s: %s%s%s"
524 (cond ((equal calc-mapping-dir
"r") " rows")
525 ((equal calc-mapping-dir
"c") " columns")
526 ((equal calc-mapping-dir
"a") " across")
527 ((equal calc-mapping-dir
"d") " down")
531 forcenargs
(if (= forcenargs
1) "" "s"))
533 (if inv
"Inv " "") (if hyp
"Hyp " "")
534 (if prefix
(concat (char-to-string prefix
) "-") ""))
535 (setq key
(read-char))
536 (if (>= key
128) (setq key
(- key
128)))
537 (cond ((memq key
'(?\C-g ?q
))
539 ((memq key
'(?\C-u ?\e
)))
541 (setq which
(%
(1+ which
) (length msgs
))))
542 ((and (= key ?I
) (null prefix
))
543 (setq inv
(not inv
)))
544 ((and (= key ?H
) (null prefix
))
545 (setq hyp
(not hyp
)))
546 ((and (eq key prefix
) (not (eq key ?v
)))
548 ((and (memq key
'(?a ?b ?c ?f ?k ?s ?t ?u ?v ?V
))
550 (setq prefix
(downcase key
)))
551 ((and (eq key ?\
=) (null prefix
))
553 (setq calc-mapping-dir
(if (equal calc-mapping-dir
"r")
556 ((and (eq key ?\_
) (null prefix
))
558 (if (string-match "map$" msg
)
559 (setq calc-mapping-dir
(if (equal calc-mapping-dir
"r")
561 (setq calc-mapping-dir
(if (equal calc-mapping-dir
"a")
564 ((and (eq key ?\
:) (null prefix
))
566 (if (string-match "map$" msg
)
567 (setq calc-mapping-dir
(if (equal calc-mapping-dir
"c")
569 (setq calc-mapping-dir
(if (equal calc-mapping-dir
"d")
572 ((and (>= key ?
0) (<= key ?
9) (null prefix
))
573 (setq forcenargs
(if (eq forcenargs
(- key ?
0)) nil
(- key ?
0)))
574 (and nargs forcenargs
(/= nargs forcenargs
) (>= nargs
0)
575 (error "Must be a %d-argument operator" nargs
)))
576 ((memq key
'(?\$ ?
\'))
580 (expr (if (eq key ?\$
)
582 (setq calc-dollar-used
1)
583 (if calc-dollar-values
584 (car calc-dollar-values
)
585 (error "Stack underflow")))
586 (let* ((calc-dollar-values calc-arg-values
)
589 (func (calc-do-alg-entry "" "Function: " nil
590 'calc-get-operator-history
)))
591 (setq record-entry t
)
592 (or (= (length func
) 1)
593 (error "Bad format"))
594 (if (> calc-dollar-used
0)
596 (setq has-args calc-dollar-used
597 arglist
(calc-invent-args has-args
))
598 (math-multi-subst (car func
)
601 (if (> calc-hashes-used
0)
602 (setq has-args calc-hashes-used
603 arglist
(calc-invent-args has-args
)))
605 (if (eq (car-safe expr
) 'calcFunc-lambda
)
606 (setq oper
(list "$" (- (length expr
) 2) expr
)
610 (calc-default-formula-arglist expr
)
612 arglist
(sort arglist
'string-lessp
))
613 (if calc-verify-arglist
614 (setq arglist
(read-from-minibuffer
615 "Function argument list: "
617 (prin1-to-string arglist
)
621 (setq arglist
(mapcar (function
632 (append '(calcFunc-lambda) arglist
636 (calc-record (nth 2 oper
) "oper"))))
637 ((setq oper
(assq key
(nth (if inv
(if hyp
3 1) (if hyp
2 0))
640 (intern (format "calc-%c-oper-keys"
643 (if (eq (nth 1 oper
) 'user
)
645 (completing-read "Function name: "
648 (if (or forcenargs nargs
)
649 (setq oper
(list "z" (or forcenargs nargs
) func
)
652 (let* ((defn (symbol-function func
)))
654 (setq defn
(symbol-function defn
)))
655 (if (eq (car-safe defn
) 'lambda
)
656 (let ((args (nth 1 defn
))
658 (while (not (memq (car args
) '(&optional
660 (setq nargs
(1+ nargs
)
662 (setq oper
(list "z" nargs func
)
665 "Function is not suitable for this operation")))
666 (message "Number of arguments: ")
667 (let ((nargs (read-char)))
668 (if (and (>= nargs ?
0) (<= nargs ?
9))
669 (setq oper
(list "z" (- nargs ?
0) func
)
672 (if (or (and (eq prefix ?v
) (memq key
'(?A ?I ?M ?O ?R ?U
)))
673 (and (eq prefix ?a
) (eq key ?M
)))
674 (let* ((dir (cond ((and (equal calc-mapping-dir
"")
675 (string-match "map$" msg
))
676 (setq calc-mapping-dir
"r")
678 ((equal calc-mapping-dir
"r") " rows")
679 ((equal calc-mapping-dir
"c") " columns")
680 ((equal calc-mapping-dir
"a") " across")
681 ((equal calc-mapping-dir
"d") " down")
683 (calc-mapping-dir (and (memq (nth 2 oper
)
688 (oper2 (calc-get-operator
689 (format "%s%s, %s%s" msg dir
690 (substring (symbol-name (nth 2 oper
))
692 (if (eq key ?I
) " (mult)" ""))
693 (cdr (assq (nth 2 oper
)
694 '((calcFunc-reduce .
2)
695 (calcFunc-rreduce .
2)
697 (calcFunc-raccum .
2)
701 (calcFunc-afixp .
2))))))
702 (oper3 (if (eq (nth 2 oper
) 'calcFunc-inner
)
704 (format "%s%s, inner (add)" msg dir
))
707 (nargs (if (> (nth 1 oper
) 0)
712 (while (and p
(> n
0))
713 (or (math-expr-contains (nth 1 oper2
) (car p
))
714 (math-expr-contains (nth 1 oper3
) (car p
))
715 (setq args
(nconc args
(list (car p
)))
718 (setq oper
(list "" nargs
722 (list (math-build-call
725 (symbol-name (nth 2 oper
))
727 (cons (math-calcFunc-to-var
731 (math-calcFunc-to-var
738 (and nargs
(>= nargs
0)
739 (/= nargs
(nth 1 oper
))
740 (error "Must be a %d-argument operator" nargs
))
741 (append (if forcenargs
742 (cons forcenargs
(cdr (cdr oper
)))
745 (let ((name (concat (if inv
"I" "") (if hyp
"H" "")
746 (if prefix
(char-to-string prefix
) "")
747 (char-to-string key
))))
748 (if (> (length name
) 3)
753 ;;; Convert a variable name (as a formula) into a like-looking function name.
754 (defun math-var-to-calcFunc (f)
755 (if (eq (car-safe f
) 'var
)
756 (if (fboundp (nth 2 f
))
758 (intern (concat "calcFunc-" (symbol-name (nth 1 f
)))))
759 (if (memq (car-safe f
) '(lambda calcFunc-lambda
))
761 (math-reject-arg f
"*Expected a function name"))))
763 ;;; Convert a function name into a like-looking variable name formula.
764 (defun math-calcFunc-to-var (f)
766 (let* ((func (or (cdr (assq f
'( ( + . calcFunc-add
)
772 ( neg . calcFunc-neg
)
773 ( | . calcFunc-vconcat
) )))
775 (base (if (string-match "\\`calcFunc-\\(.+\\)\\'"
777 (math-match-substring (symbol-name func
) 1)
778 (symbol-name func
))))
781 (intern (concat "var-" base
))))
784 ;;; Expand a function call using "lambda" notation.
785 (defun math-build-call (f args
)
786 (if (eq (car-safe f
) 'calcFunc-lambda
)
787 (if (= (length args
) (- (length f
) 2))
788 (math-multi-subst (nth (1- (length f
)) f
) (cdr f
) args
)
789 (calc-record-why "*Wrong number of arguments" f
)
790 (cons 'calcFunc-call
(cons (math-calcFunc-to-var f
) args
)))
791 (if (and (eq f
'calcFunc-neg
)
793 (list 'neg
(car args
))
794 (let ((func (assq f
'( ( calcFunc-add .
+ )
800 ( calcFunc-vconcat . |
) ))))
801 (if (and func
(= (length args
) 2))
802 (cons (cdr func
) args
)
805 ;;; Do substitutions in parallel to avoid crosstalk.
807 ;; The variables math-ms-temp and math-ms-args are local to
808 ;; math-multi-subst, but are used by math-multi-subst-rec, which
809 ;; is called by math-multi-subst.
810 (defvar math-ms-temp
)
811 (defvar math-ms-args
)
813 (defun math-multi-subst (expr olds news
)
814 (let ((math-ms-args nil
)
816 (while (and olds news
)
817 (setq math-ms-args
(cons (cons (car olds
) (car news
)) math-ms-args
)
820 (math-multi-subst-rec expr
)))
822 (defun math-multi-subst-rec (expr)
823 (cond ((setq math-ms-temp
(assoc expr math-ms-args
))
825 ((Math-primp expr
) expr
)
826 ((and (eq (car expr
) 'calcFunc-lambda
) (> (length expr
) 2))
827 (let ((new (list (car expr
)))
828 (math-ms-args math-ms-args
))
829 (while (cdr (setq expr
(cdr expr
)))
830 (setq new
(cons (car expr
) new
))
831 (if (assoc (car expr
) math-ms-args
)
832 (setq math-ms-args
(cons (cons (car expr
) (car expr
))
834 (nreverse (cons (math-multi-subst-rec (car expr
)) new
))))
837 (mapcar 'math-multi-subst-rec
(cdr expr
))))))
839 (defun calcFunc-call (f &rest args
)
840 (setq args
(math-build-call (math-var-to-calcFunc f
) args
))
841 (if (eq (car-safe args
) 'calcFunc-call
)
843 (math-normalize args
)))
845 (defun calcFunc-apply (f args
)
846 (or (Math-vectorp args
)
847 (math-reject-arg args
'vectorp
))
848 (apply 'calcFunc-call
(cons f
(cdr args
))))
853 ;;; Map a function over a vector symbolically. [Public]
854 (defun math-symb-map (f mode args
)
855 (let* ((func (math-var-to-calcFunc f
))
856 (nargs (length args
))
857 (ptrs (vconcat args
))
858 (vflags (make-vector nargs nil
))
863 (math-working-step 0)
864 (math-working-step-2 nil
)
868 heads
'(calcFunc-eq calcFunc-neq calcFunc-lt calcFunc-gt
869 calcFunc-leq calcFunc-geq
))
870 (while (and (< (setq i
(1+ i
)) nargs
)
871 (not (math-matrixp (aref ptrs i
)))))
874 (setq func
(list 'lambda
'(&rest x
)
876 (list 'quote f
) '(quote elems
) 'x
))
880 (if (math-matrixp (aref ptrs i
))
881 (aset ptrs i
(math-transpose (aref ptrs i
))))
885 (while (< (setq i
(1+ i
)) nargs
)
886 (setq obj
(aref ptrs i
))
887 (if (and (memq (car-safe obj
) heads
)
895 (aref (aref [ [0 1 2 3 4 5]
901 (- 6 (length (memq head heads
))))
902 (- 6 (length (memq (car obj
) heads
))))
904 (setq head
(car obj
)))
906 (or (= (length obj
) len
)
907 (math-dimension-error))
908 (setq len
(length obj
))))))
911 (math-reject-arg (aref ptrs
0) 'vectorp
)
912 (math-reject-arg nil
"At least one argument must be a vector")))
913 (setq math-working-step-2
(1- len
))
914 (while (> (setq len
(1- len
)) 0)
917 (while (< (setq i
(1+ i
)) nargs
)
920 (aset ptrs i
(cdr (aref ptrs i
)))
921 (setq expr
(nconc expr
(list (car (aref ptrs i
))))))
922 (setq expr
(nconc expr
(list (aref ptrs i
))))))
923 (setq math-working-step
(1+ math-working-step
)
924 vec
(cons (math-normalize (math-build-call func expr
)) vec
)))
925 (setq vec
(cons head
(nreverse vec
)))
926 (if (and (eq mode
'cols
) (math-matrixp vec
))
930 (defun calcFunc-map (func &rest args
)
931 (math-symb-map func
'elems args
))
933 (defun calcFunc-mapr (func &rest args
)
934 (math-symb-map func
'rows args
))
936 (defun calcFunc-mapc (func &rest args
)
937 (math-symb-map func
'cols args
))
939 (defun calcFunc-mapa (func arg
)
940 (if (math-matrixp arg
)
941 (math-symb-map func
'elems
(cdr (math-transpose arg
)))
942 (math-symb-map func
'elems arg
)))
944 (defun calcFunc-mapd (func arg
)
945 (if (math-matrixp arg
)
946 (math-symb-map func
'elems
(cdr arg
))
947 (math-symb-map func
'elems arg
)))
949 (defun calcFunc-mapeq (func &rest args
)
950 (if (and (or (equal func
'(var mul var-mul
))
951 (equal func
'(var div var-div
)))
953 (if (math-negp (car args
))
954 (let ((func (nth 1 (assq (car-safe (nth 1 args
))
955 calc-tweak-eqn-table
))))
956 (and func
(setq args
(list (car args
)
957 (cons func
(cdr (nth 1 args
)))))))
958 (if (math-negp (nth 1 args
))
959 (let ((func (nth 1 (assq (car-safe (car args
))
960 calc-tweak-eqn-table
))))
961 (and func
(setq args
(list (cons func
(cdr (car args
)))
963 (if (or (and (equal func
'(var div var-div
))
964 (assq (car-safe (nth 1 args
)) calc-tweak-eqn-table
))
965 (equal func
'(var neg var-neg
))
966 (equal func
'(var inv var-inv
)))
967 (apply 'calcFunc-mapeqr func args
)
968 (apply 'calcFunc-mapeqp func args
)))
970 (defun calcFunc-mapeqr (func &rest args
)
971 (setq args
(mapcar (function (lambda (x)
972 (let ((func (assq (car-safe x
)
973 calc-tweak-eqn-table
)))
975 (cons (nth 1 func
) (cdr x
))
978 (apply 'calcFunc-mapeqp func args
))
980 (defun calcFunc-mapeqp (func &rest args
)
981 (if (or (and (memq (car-safe (car args
)) '(calcFunc-lt calcFunc-leq
))
982 (memq (car-safe (nth 1 args
)) '(calcFunc-gt calcFunc-geq
)))
983 (and (memq (car-safe (car args
)) '(calcFunc-gt calcFunc-geq
))
984 (memq (car-safe (nth 1 args
)) '(calcFunc-lt calcFunc-leq
))))
985 (setq args
(cons (car args
)
986 (cons (list (nth 1 (assq (car (nth 1 args
))
987 calc-tweak-eqn-table
))
989 (nth 1 (nth 1 args
)))
991 (math-symb-map func
'eqn args
))
995 ;;; Reduce a function over a vector symbolically. [Public]
996 (defun calcFunc-reduce (func vec
)
997 (if (math-matrixp vec
)
999 (setq func
(math-var-to-calcFunc func
))
1000 (while (setq vec
(cdr vec
))
1001 (setq row
(car vec
))
1002 (while (setq row
(cdr row
))
1004 (if (Math-numberp expr
)
1006 (math-build-call func
(list expr
(car row
))))
1007 (math-build-call func
(list expr
(car row
))))
1009 (math-normalize expr
))
1010 (calcFunc-reducer func vec
)))
1012 (defun calcFunc-rreduce (func vec
)
1013 (if (math-matrixp vec
)
1015 (setq func
(math-var-to-calcFunc func
)
1016 vec
(reverse (cdr vec
)))
1018 (setq row
(reverse (cdr (car vec
))))
1021 (math-build-call func
(list (car row
) expr
))
1024 (setq vec
(cdr vec
)))
1025 (math-normalize expr
))
1026 (calcFunc-rreducer func vec
)))
1028 (defun calcFunc-reducer (func vec
)
1029 (setq func
(math-var-to-calcFunc func
))
1030 (or (math-vectorp vec
)
1031 (math-reject-arg vec
'vectorp
))
1032 (let ((expr (car (setq vec
(cdr vec
)))))
1037 (let ((lfunc (or (cdr (assq func
1038 '( (calcFunc-add . math-add
)
1039 (calcFunc-sub . math-sub
)
1040 (calcFunc-mul . math-mul
)
1041 (calcFunc-div . math-div
)
1042 (calcFunc-pow . math-pow
)
1043 (calcFunc-mod . math-mod
)
1048 (setq expr
(funcall lfunc expr
(nth 1 vec
))
1051 (while (setq vec
(cdr vec
))
1052 (setq expr
(math-build-call func
(list expr
(car vec
)))))
1053 (math-normalize expr
))
1054 (or (math-identity-value func
)
1055 (math-reject-arg vec
"*Vector is empty")))))
1057 (defun math-identity-value (func)
1058 (cdr (assq func
'( (calcFunc-add .
0) (calcFunc-sub .
0)
1059 (calcFunc-mul .
1) (calcFunc-div .
1)
1060 (calcFunc-idiv .
1) (calcFunc-fdiv .
1)
1061 (calcFunc-min .
(var inf var-inf
))
1062 (calcFunc-max .
(neg (var inf var-inf
)))
1063 (calcFunc-vconcat .
(vec))
1064 (calcFunc-append .
(vec)) ))))
1066 (defun calcFunc-rreducer (func vec
)
1067 (setq func
(math-var-to-calcFunc func
))
1068 (or (math-vectorp vec
)
1069 (math-reject-arg vec
'vectorp
))
1070 (if (eq func
'calcFunc-sub
) ; do this in a way that looks nicer
1071 (let ((expr (car (setq vec
(cdr vec
)))))
1074 (while (setq vec
(cdr vec
))
1075 (setq expr
(math-build-call func
(list expr
(car vec
)))
1076 func
(if (eq func
'calcFunc-sub
)
1077 'calcFunc-add
'calcFunc-sub
)))
1078 (math-normalize expr
))
1080 (let ((expr (car (setq vec
(reverse (cdr vec
))))))
1083 (while (setq vec
(cdr vec
))
1084 (setq expr
(math-build-call func
(list (car vec
) expr
))))
1085 (math-normalize expr
))
1086 (or (math-identity-value func
)
1087 (math-reject-arg vec
"*Vector is empty"))))))
1089 (defun calcFunc-reducec (func vec
)
1090 (if (math-matrixp vec
)
1091 (calcFunc-reducer func
(math-transpose vec
))
1092 (calcFunc-reducer func vec
)))
1094 (defun calcFunc-rreducec (func vec
)
1095 (if (math-matrixp vec
)
1096 (calcFunc-rreducer func
(math-transpose vec
))
1097 (calcFunc-rreducer func vec
)))
1099 (defun calcFunc-reducea (func vec
)
1100 (if (math-matrixp vec
)
1102 (mapcar (function (lambda (x) (calcFunc-reducer func x
)))
1104 (calcFunc-reducer func vec
)))
1106 (defun calcFunc-rreducea (func vec
)
1107 (if (math-matrixp vec
)
1109 (mapcar (function (lambda (x) (calcFunc-rreducer func x
)))
1111 (calcFunc-rreducer func vec
)))
1113 (defun calcFunc-reduced (func vec
)
1114 (if (math-matrixp vec
)
1116 (mapcar (function (lambda (x) (calcFunc-reducer func x
)))
1117 (cdr (math-transpose vec
))))
1118 (calcFunc-reducer func vec
)))
1120 (defun calcFunc-rreduced (func vec
)
1121 (if (math-matrixp vec
)
1123 (mapcar (function (lambda (x) (calcFunc-rreducer func x
)))
1124 (cdr (math-transpose vec
))))
1125 (calcFunc-rreducer func vec
)))
1127 (defun calcFunc-accum (func vec
)
1128 (setq func
(math-var-to-calcFunc func
))
1129 (or (math-vectorp vec
)
1130 (math-reject-arg vec
'vectorp
))
1131 (let* ((expr (car (setq vec
(cdr vec
))))
1132 (res (list 'vec expr
)))
1134 (math-reject-arg vec
"*Vector is empty"))
1135 (while (setq vec
(cdr vec
))
1136 (setq expr
(math-build-call func
(list expr
(car vec
)))
1137 res
(nconc res
(list expr
))))
1138 (math-normalize res
)))
1140 (defun calcFunc-raccum (func vec
)
1141 (setq func
(math-var-to-calcFunc func
))
1142 (or (math-vectorp vec
)
1143 (math-reject-arg vec
'vectorp
))
1144 (let* ((expr (car (setq vec
(reverse (cdr vec
)))))
1147 (math-reject-arg vec
"*Vector is empty"))
1148 (while (setq vec
(cdr vec
))
1149 (setq expr
(math-build-call func
(list (car vec
) expr
))
1150 res
(cons (list expr
) res
)))
1151 (math-normalize (cons 'vec res
))))
1154 (defun math-nest-calls (func base iters accum tol
)
1156 (if (math-realp tol
)
1157 (or (math-numberp base
) (math-reject-arg base
'numberp
))
1158 (math-reject-arg tol
'realp
)))
1159 (setq func
(math-var-to-calcFunc func
))
1161 (if (equal iters
'(var inf var-inf
))
1164 (if (math-messy-integerp iters
)
1165 (setq iters
(math-trunc iters
)))
1166 (or (integerp iters
) (math-reject-arg iters
'fixnump
))
1167 (or (not tol
) (natnump iters
) (math-reject-arg iters
'fixnatnump
))
1169 (let* ((dummy '(var DummyArg var-DummyArg
))
1170 (dummy2 '(var DummyArg2 var-DummyArg2
))
1171 (finv (math-solve-for (math-build-call func
(list dummy2
))
1173 (or finv
(math-reject-arg nil
"*Unable to find an inverse"))
1174 (if (and (= (length finv
) 2)
1175 (equal (nth 1 finv
) dummy
))
1176 (setq func
(car finv
))
1177 (setq func
(list 'calcFunc-lambda dummy finv
)))
1178 (setq iters
(- iters
)))))))
1179 (math-with-extra-prec 1
1182 (avalues (list base
))
1183 (math-working-step 0)
1184 (math-working-step-2 iters
))
1185 (while (and (or (null iters
)
1186 (>= (setq iters
(1- iters
)) 0))
1190 (not (if (and (Math-numberp value
)
1191 (Math-numberp ovalue
))
1192 (math-nearly-equal value ovalue
)
1193 (Math-equal value ovalue
)))
1194 (if (math-numberp value
)
1195 (Math-lessp tol
(math-abs (math-sub value ovalue
)))
1196 (math-reject-arg value
'numberp
)))))
1198 math-working-step
(1+ math-working-step
)
1199 value
(math-normalize (math-build-call func
(list value
))))
1201 (setq avalues
(cons value avalues
))))
1203 (cons 'vec
(nreverse avalues
))
1206 (defun calcFunc-nest (func base iters
)
1207 (math-nest-calls func base iters nil nil
))
1209 (defun calcFunc-anest (func base iters
)
1210 (math-nest-calls func base iters t nil
))
1212 (defun calcFunc-fixp (func base
&optional iters tol
)
1213 (math-nest-calls func base iters nil
(or tol t
)))
1215 (defun calcFunc-afixp (func base
&optional iters tol
)
1216 (math-nest-calls func base iters t
(or tol t
)))
1219 (defun calcFunc-outer (func a b
)
1220 (or (math-vectorp a
) (math-reject-arg a
'vectorp
))
1221 (or (math-vectorp b
) (math-reject-arg b
'vectorp
))
1222 (setq func
(math-var-to-calcFunc func
))
1224 (while (setq a
(cdr a
))
1225 (setq mat
(cons (cons 'vec
1226 (mapcar (function (lambda (x)
1227 (math-build-call func
1232 (math-normalize (cons 'vec
(nreverse mat
)))))
1235 ;; The variables math-inner-mul-func and math-inner-add-func are
1236 ;; local to calcFunc-inner, but are used by math-inner-mats,
1237 ;; which is called by math-inner-mats.
1238 (defvar math-inner-mul-func
)
1239 (defvar math-inner-add-func
)
1241 (defun calcFunc-inner (math-inner-mul-func math-inner-add-func a b
)
1242 (or (math-vectorp a
) (math-reject-arg a
'vectorp
))
1243 (or (math-vectorp b
) (math-reject-arg b
'vectorp
))
1244 (if (math-matrixp a
)
1245 (if (math-matrixp b
)
1246 (if (= (length (nth 1 a
)) (length b
))
1247 (math-inner-mats a b
)
1248 (math-dimension-error))
1249 (if (= (length (nth 1 a
)) 2)
1250 (if (= (length a
) (length b
))
1251 (math-inner-mats a
(list 'vec b
))
1252 (math-dimension-error))
1253 (if (= (length (nth 1 a
)) (length b
))
1254 (math-mat-col (math-inner-mats a
(math-col-matrix b
))
1256 (math-dimension-error))))
1257 (if (math-matrixp b
)
1258 (nth 1 (math-inner-mats (list 'vec a
) b
))
1259 (calcFunc-reduce math-inner-add-func
(calcFunc-map math-inner-mul-func a b
)))))
1261 (defun math-inner-mats (a b
)
1263 (cols (length (nth 1 b
)))
1264 row col ap bp accum
)
1265 (while (setq a
(cdr a
))
1268 (while (> (setq col
(1- col
)) 0)
1269 (setq row
(cons (calcFunc-reduce math-inner-add-func
1270 (calcFunc-map math-inner-mul-func
1272 (math-mat-col b col
)))
1274 (setq mat
(cons (cons 'vec row
) mat
)))
1275 (cons 'vec
(nreverse mat
))))
1279 ;;; arch-tag: 980eac49-00e0-4870-b72a-e726b74c7990
1280 ;;; calc-map.el ends here