1 ;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;; The data in this file contains enhancments. ;;;;;
5 ;;; Copyright (c) 1984,1987 by William Schelter,University of Texas ;;;;;
6 ;;; All rights reserved ;;;;;
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 ;;; (c) Copyright 1982 Massachusetts Institute of Technology ;;;
9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13 (macsyma-module combin
)
15 (declare-top (special *mfactl
*factlist donel nn
* dn
* *ans
* *var
*
16 $zerobern
*n $cflength
*a
* *a $prevfib $next_lucas
17 *infsumsimp
*times
*plus sum usum makef
18 varlist genvar $sumsplitfact $ratfac $simpsum
20 $ratprint $zeta%pi $bftorat
))
22 (load-macsyma-macros mhayat rzmac ratmac
)
24 ;; minfactorial and factcomb stuff
26 (defmfun $makefact
(e)
27 (let ((makef t
)) (if (atom e
) e
(simplify (makefact1 e
)))))
31 ((eq (caar e
) '%binomial
)
32 (subst (makefact1 (cadr e
)) 'x
33 (subst (makefact1 (caddr e
)) 'y
34 '((mtimes) ((mfactorial) x
)
35 ((mexpt) ((mfactorial) y
) -
1)
36 ((mexpt) ((mfactorial) ((mplus) x
((mtimes) -
1 y
)))
38 ((eq (caar e
) '%gamma
)
39 (list '(mfactorial) (list '(mplus) -
1 (makefact1 (cadr e
)))))
41 (makefact1 (subst (cadr e
) 'x
43 '((mtimes) ((%gamma
) x
)
45 ((mexpt) ((%gamma
) ((mplus) x y
)) -
1))))))
46 (t (recur-apply #'makefact1 e
))))
48 (defmfun $makegamma
(e)
49 (if (atom e
) e
(simplify (makegamma1 ($makefact e
)))))
51 (defmfun $minfactorial
(e)
52 (let (*mfactl
*factlist
)
53 (if (specrepp e
) (setq e
(specdisrep e
)))
55 (mapl #'evfac1
*factlist
)
60 ((eq (caar e
) 'mfactorial
)
61 ;; Replace factorial with simplified expression from *factlist.
62 (simplifya (cdr (assoc (cadr e
) *factlist
:test
#'equal
)) nil
))
63 ((member (caar e
) '(%sum %derivative %integrate %product
) :test
#'eq
)
64 (cons (list (caar e
)) (cons (evfact (cadr e
)) (cddr e
))))
65 (t (recur-apply #'evfact e
))))
69 (cond ((null l
) (push (list e
) *mfactl
))
70 ((numberp (setq n
($ratsimp
`((mplus) ,e
((mtimes) -
1 ,(caar l
))))))
72 (rplacd (car l
) (cons e
(cdar l
))))
73 ((rplaca l
(cons e
(car l
))))))
74 ((adfactl e
(cdr l
))))))
78 ((eq (caar e
) 'mfactorial
)
79 (and (null (member (cadr e
) *factlist
:test
#'equal
))
81 (push (cadr e
) *factlist
)
82 (adfactl (cadr e
) *mfactl
))))
83 ((member (caar e
) '(%sum %derivative %integrate %product
) :test
#'eq
)
85 ((mapc #'getfact
(cdr e
)))))
88 (do ((al *mfactl
(cdr al
)))
89 ((member (car e
) (car al
) :test
#'equal
)
94 ($ratsimp
(list '(mplus) (car e
)
95 (list '(mtimes) -
1 (caar al
)))) 1)
96 (list '(mfactorial) (caar al
))))))))
98 (defmfun $factcomb
(e)
99 (let ((varlist varlist
) genvar $ratfac
(ratrep (and (not (atom e
)) (eq (caar e
) 'mrat
))))
100 (and ratrep
(setq e
(ratdisrep e
)))
103 (t (simplify (cons (list (caar e
))
104 (mapcar #'factcomb1
(cdr e
)))))))
105 (or $sumsplitfact
(setq e
($minfactorial e
)))
106 (if ratrep
(ratf e
) e
)))
109 (cond ((free e
'mfactorial
) e
)
110 ((member (caar e
) '(mplus mtimes mexpt
) :test
#'eq
)
111 (cons (list (caar e
)) (mapcar #'factcomb1
(cdr e
))))
112 (t (setq e
(factcomb e
))
115 (cons (list (caar e
)) (mapcar #'factcomb1
(cdr e
)))))))
119 ((free e
'mfactorial
) e
)
120 ((member (caar e
) '(mplus mtimes
) :test
#'eq
)
121 (factpluscomb (factcombplus e
)))
122 ((eq (caar e
) 'mexpt
)
123 (simpexpt (list '(mexpt) (factcomb (cadr e
))
124 (factcomb (caddr e
)))
128 (t (cons (car e
) (mapcar #'factcomb
(cdr e
))))))
132 (setq e
(factqsnt ($ratdisrep
(cons (car e
) (cons (cadr e
) 1)))
133 ($ratdisrep
(cons (car e
) (cons (cddr e
) 1)))))
135 (div* (factpluscomb nn
*) (factpluscomb dn
*))))
137 (defun factqsnt (num den
)
139 (let (nn* dn
* (e (factpluscomb (div* den num
))))
141 (factpluscomb (div* dn
* nn
*)))))
143 (defun factcombplus (e)
145 (do ((l1 (nplus e
) (cdr l1
))
148 (simplus (cons '(mplus)
149 (mapcar #'(lambda (q) (factqsnt (car q
) (cdr q
))) l2
))
152 (do ((l3 l2
(cdr l3
))
154 ((null l3
) (setq l2
(nconc l2
(list (cons nn
* dn
*)))))
156 (cond ((not (free ($gcd dn
* (cdr l4
)) 'mfactorial
))
157 (numden (list '(mplus) (div* nn
* dn
*)
158 (div* (car l4
) (cdr l4
))))
159 (setq l2
(delete l4 l2
:count
1 :test
#'eq
))))))))
161 (defun factpluscomb (e)
162 (prog (donel fact indl tt
)
163 tag
(setq e
(factexpand e
)
164 fact
(getfactorial e
))
166 (setq indl
(mapcar #'(lambda (q) (factplusdep q fact
))
168 tt
(factpowerselect indl
(nplus e
) fact
)
170 (cons '(mplus) (mapcar #'(lambda (q) (factplus2 q fact
))
172 (t (factplus2 (car tt
) fact
))))
176 (if (eq (caar e
) 'mplus
)
180 (defun factexpand (e)
182 ((eq (caar e
) 'mplus
)
183 (simplus (cons '(mplus) (mapcar #'factexpand
(cdr e
)))
185 ((free e
'mfactorial
) e
)
188 (defun getfactorial (e)
190 ((member (caar e
) '(mplus mtimes
) :test
#'eq
)
191 (do ((e (cdr e
) (cdr e
))
194 (setq a
(getfactorial (car e
)))
196 ((eq (caar e
) 'mexpt
)
197 (getfactorial (cadr e
)))
198 ((eq (caar e
) 'mfactorial
)
199 (and (null (memalike (cadr e
) donel
))
201 (car (setq donel
(cons (cadr e
) donel
))))))))
203 (defun factplusdep (e fact
)
204 (cond ((alike1 e fact
) 1)
206 ((eq (caar e
) 'mtimes
)
207 (do ((l (cdr e
) (cdr l
))
211 (and (setq out
(factplusdep e fact
))
213 ((eq (caar e
) 'mexpt
)
214 (let ((fto (factplusdep (cadr e
) fact
)))
215 (and fto
(simptimes (list '(mtimes) fto
217 ((eq (caar e
) 'mplus
)
218 (same (mapcar #'(lambda (q) (factplusdep q fact
))
223 (cd (cdr l
) (cdr cd
))
230 (defun factpowerselect (indl e fact
)
232 (do ((i indl
(cdr i
))
238 (setq exp
($divide
(car j
) `((mexpt) ,fact
,expt
)))
239 ;; (car j) need not involve fact^expt since
240 ;; fact^expt may be the gcd of the num and denom
241 ;; of (car j) and $divide will cancel this out.
242 (if (not (equal (cadr exp
) 0))
248 (cond ((null l
) (setq l
(list (list expt exp
))))
249 ((setq fl
(assolike expt l
))
250 (nconc fl
(list exp
)))
251 (t (nconc l
(list (list expt exp
))))))))
253 (defun factplus2 (l fact
)
254 (let ((expt (car l
)))
255 (cond (expt (factplus0 (cond ((cddr l
) (rplaca l
'(mplus)))
258 (t (rplaca l
'(mplus))))))
260 (defun factplus0 (r e fact
)
262 (fpn fact
(list '(mplus) fact i
))
263 (j -
1) (exp) (rfpn) (div))
265 (setq rfpn
(simpexpt (list '(mexpt) fpn -
1) 1 nil
))
266 (setq div
(dypheyed r
(simpexpt (list '(mexpt) rfpn e
) 1 nil
)))
267 (cond ((or (null (or $sumsplitfact
(equal (cadr div
) 0)))
269 (return (simplus (cons '(mplus) (mapcar
272 (list '(mtimes) q
(list '(mexpt)
273 (list '(mfactorial) (list '(mplus) fpn j
)) e
)))
274 (factplus1 (cons r exp
) e fpn
)))
276 (t (setq r
(car div
))
277 (setq exp
(cons (cadr div
) exp
))))))
279 (defun factplus1 (exp e fact
)
282 (fpn (list '(mplus) fact
1) (list '(mplus) fact i
))
285 (setq div
(dypheyed (car l
) (list '(mexpt) fpn e
)))
286 (and (or $sumsplitfact
(equal (cadr div
) 0))
287 (null (equal (car div
) 0))
288 (rplaca l
(cadr div
))
289 (rplacd l
(cons (cond ((cadr l
)
290 (simplus (list '(mplus) (car div
) (cadr l
))
294 (cons (simplus fpn
1 nil
) donel
))
298 (defun dypheyed (r f
)
302 p1
(pdegreevector (cadr r1
))
303 p2
(pdegreevector (cddr r1
)))
306 (k (caddar r1
) (cdr k
)))
307 ((null k
) (kansel r
(cadr r1
) (cddr r1
)))
308 (cond ((> (car i
) (car j
))
309 (return (cdr ($divide r f
(car k
)))))))))
311 (defun kansel (r n d
)
314 p1
(testdivide (cadr r1
) n
)
315 p2
(testdivide (cddr r1
) d
))
317 (cons (rdis (cons p1 p2
)) '(0))
318 (cons '0 (list r
)))))
320 ;; euler and bernoulli stuff
322 (defvar *bn
* (make-array 17 :adjustable t
:element-type
'integer
323 :initial-contents
'(0 -
1 1 -
1 5. -
691.
7. -
3617.
43867. -
174611.
854513.
324 -
236364091.
8553103. -
23749461029.
8615841276005.
325 -
7709321041217.
2577687858367.
)))
327 (defvar *bd
* (make-array 17 :adjustable t
:element-type
'integer
328 :initial-contents
'(0 30.
42.
30.
66.
2730.
6.
510.
798.
330.
138.
2730.
329 6.
870.
14322.
510.
6.
)))
331 (defvar *eu
* (make-array 11 :adjustable t
:element-type
'integer
332 :initial-contents
'(-1 5. -
61.
1385. -
50521.
2702765. -
199360981.
19391512145.
333 -
2404879675441.
370371188237525. -
69348874393137901.
)))
335 (putprop '*eu
* 11 'lim
)
336 (putprop 'bern
16 'lim
)
341 (cond ((or (not (fixnump s
)) (< s
0)) (list '($euler
) s
))
342 ((zerop (setq %n s
)) 1)
345 ((null (> (ash %n -
1) (get '*eu
* 'lim
)))
346 (aref *eu
* (1- (ash %n -
1))))
347 ((eq $zerobern
'%$
/#&)
349 ((setq *eu
* (adjust-array *eu
* (1+ (ash %n -
1))))
351 ((<= %n
(get '*eu
* 'lim
))
353 ((setq *eu
* (adjust-array *eu
* (1+ %n
)))
357 (defun nxtbincoef (m nom
)
358 (truncate (* nom
(- *a
* m
)) m
))
361 (prog (nom %k e fl $zerobern
*a
*)
362 (setq nom
1 %k %a
* fl nil e
0 $zerobern
'%$
/#& *a
* (1+ %a
*))
365 (setf (aref *eu
* (1- (ash %a
* -
1))) e
)
366 (putprop '*eu
* (ash %a
* -
1) 'lim
)
368 (setq nom
(nxtbincoef (1+ (- %a
* %k
)) nom
) %k
(1- %k
))
369 (cond ((setq fl
(null fl
))
371 (incf e
(* nom
($euler %k
)))
374 (defun simpeuler (x vestigial z
)
375 (declare (ignore vestigial
))
377 (let ((u (simpcheck (cadr x
) z
)))
378 (if (and (fixnump u
) (>= u
0))
380 (eqtest (list '($euler
) u
) x
))))
385 (cond ((or (not (fixnump s
)) (< s
0)) (list '($bern
) s
))
386 ((= (setq %n s
) 0) 1)
387 ((= %n
1) '((rat) -
1 2))
388 ((= %n
2) '((rat) 1 6))
391 ((null (> (setq %n
(1- (ash %n -
1))) (get 'bern
'lim
)))
392 (list '(rat) (aref *bn
* %n
) (aref *bd
* %n
)))
393 ((eq $zerobern
'$
/#&) (bern (* 2 (1+ %n
))))
395 (setq *bn
* (adjust-array *bn
* (setq %n
(1+ %n
))))
396 (setq *bd
* (adjust-array *bd
* %n
))
398 ((null (> %n
(get 'bern
'lim
)))
399 (list '(rat) (aref *bn
* (- %n
2)) (aref *bd
* (- %n
2))))
401 (setq *bn
* (adjust-array *bn
* (1+ %n
)))
402 (setq *bd
* (adjust-array *bd
* (1+ %n
)))
403 (bern (* 2 (1- %n
)))))))
407 (prog (nom %k bb a b $zerobern l
*a
*)
417 (setq bb
(*red a
(* -
1 b %a
*)))
418 (putprop 'bern
(setq %a
* (1- (ash %a
* -
1))) 'lim
)
419 (setf (aref *bn
* %a
*) (cadr bb
))
420 (setf (aref *bd
* %a
*) (caddr bb
))
423 (setq a
(+ (* b
(setq nom
(nxtbincoef %k nom
))
424 (num1 (setq bb
($bern %k
))))
426 (setq b
(* b
(denom1 bb
)))
427 (setq a
(*red a b
) b
(denom1 a
) a
(num1 a
))
430 (defun simpbern (x vestigial z
)
431 (declare (ignore vestigial
))
433 (let ((u (simpcheck (cadr x
) z
)))
434 (if (and (fixnump u
) (not (< u
0)))
436 (eqtest (list '($bern
) u
) x
))))
438 ;;; ----------------------------------------------------------------------------
439 ;;; Bernoulli polynomials
441 ;;; The following explicit formula is directly implemented:
446 ;;; B (x) = > b binomial(n, k) x
451 ;;; The coeffizients b[k] are the Bernoulli numbers. The algorithm does not
452 ;;; skip over Beroulli numbers, which are zero. We have to ensure that
453 ;;; $zerobern is bound to true.
454 ;;; ----------------------------------------------------------------------------
456 (defmfun $bernpoly
(x s
)
457 (let ((%n
0) ($zerobern t
))
458 (cond ((not (fixnump s
)) (list '($bernpoly
) x s
))
460 (do ((sum (cons (if (and (= %n
0) (zerop1 x
))
464 (cons (mul (binocomp %n %k
)
466 (if (and (= %n %k
) (zerop1 x
))
468 (power x
(- %n %k
))))
471 ((> %k %n
) (addn sum t
))))
472 (t (list '($bernpoly
) x %n
)))))
474 ;;; ----------------------------------------------------------------------------
475 ;;; Euler polynomials
477 ;;; The following explicit formula is directly implemented:
480 ;;; ==== E binomial(n, k) (x - -)
482 ;;; E (x) = > ------------------------------
487 ;;; The coeffizients E[k] are the Euler numbers.
488 ;;; ----------------------------------------------------------------------------
490 (defmfun $eulerpoly
(x s
)
491 (let ((n 0) ($zerobern t
) (y 0))
492 (cond ((not (fixnump s
)) (list '($eulerpoly
) x s
))
494 (do ((sum (cons (if (and (zerop1 (setq y
(sub x
(div 1 2))))
499 (cons (mul (binocomp n k
)
502 (if (and (zerop1 (setq y
(sub x
(div 1 2))))
508 ((> k n
) ($expand
(addn sum t
)))))
509 (t (list '($eulerpoly
) x n
)))))
511 ;; zeta and fibonacci stuff
513 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
515 ;;; Implementation of the Riemann Zeta function as a simplifying function
517 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
520 (simplify (list '(%zeta
) z
)))
522 ;;; Set properties to give full support to the parser and display
524 (defprop $zeta %zeta alias
)
525 (defprop $zeta %zeta verb
)
527 (defprop %zeta $zeta reversealias
)
528 (defprop %zeta $zeta noun
)
530 ;;; The Riemann Zeta function is a simplifying function
532 (defprop %zeta simp-zeta operators
)
534 ;;; The Riemann Zeta function has mirror symmetry
536 (defprop %zeta t commutes-with-conjugate
)
538 ;;; The Riemann Zeta function distributes over lists, matrices, and equations
540 (defprop %zeta
(mlist $matrix mequal
) distribute_over
)
542 ;;; We support a simplim%function. The function is looked up in simplimit and
543 ;;; handles specific values of the function.
545 (defprop %zeta simplim%zeta simplim%function
)
547 (defun simplim%zeta
(expr var val
)
548 ;; Look for the limit of the argument
549 (let* ((arg (limit (cadr expr
) var val
'think
))
550 (dir (limit (add (cadr expr
) (neg arg
)) var val
'think
)))
552 ;; Handle an argument 1 at this place
554 (cond ((eq dir
'$zeroa
)
560 ;; All other cases are handled by the simplifier of the function.
561 (simplify (list '(%zeta
) arg
))))))
563 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
565 (defun simp-zeta (expr z simpflag
)
567 (setq z
(simpcheck (cadr expr
) simpflag
))
570 ;; Check for special values
572 ((alike1 z
'((mtimes) -
1 $minf
)) 1)
574 (cond (($bfloatp z
) ($bfloat
'((rat) -
1 2)))
576 (t '((rat simp
) -
1 2))))
578 (simp-domain-error (intl:gettext
"zeta: zeta(~:M) is undefined.") z
))
580 ;; Check for numerical evaluation
581 ((or (bigfloat-numerical-eval-p z
)
582 (complex-bigfloat-numerical-eval-p z
)
583 (float-numerical-eval-p z
)
584 (complex-float-numerical-eval-p z
))
586 ;; Check for transformations and argument simplifications
591 (eqtest (list '(%zeta
) z
) expr
))
593 (mul -
1 (div ($bern z
) z
)))))
595 ((not $zeta%pi
) (eqtest (list '(%zeta
) z
) expr
))
596 (t (let ($numer $float
)
598 (mul (div (power 2 (1- z
))
599 (take '(mfactorial) z
))
600 (take '(mabs) ($bern z
))))))))
602 (eqtest (list '(%zeta
) z
) expr
))))
604 ;; See http://numbers.computation.free.fr/Constants/constants.html
605 ;; and, in particular,
606 ;; http://numbers.computation.free.fr/Constants/Miscellaneous/zetaevaluations.pdf.
607 ;; We use the algorithm from Proposition 2:
609 ;; zeta(s) = 1/(1-2^(1-s)) *
610 ;; (sum((-1)^(k-1)/k^s,k,1,n) +
611 ;; 1/2^n*sum((-1)^(k-1)*e(k-n)/k^s,k,n+1,2*n))
614 ;; where e(k) = sum(binomial(n,j), j, k, n). Writing s = sigma + %i*t, when
615 ;; sigma is positive you get an error estimate of
617 ;; |g(n,s)| <= 1/8^n * h(s)
621 ;; h(s) = ((1 + abs (t / sigma)) exp (abs (t) * %pi / 2)) / abs (1 - 2^(1 - s))
623 ;; We need to figure out how many terms are required to make |g(n,s)|
624 ;; sufficiently small. The answer is
626 ;; n = (log h(s) - log (eps)) / log (8)
630 ;; log (h (s)) = (%pi/2 * abs (t)) + log (1 + t/sigma) - log (abs (1 - 2^(1 - s)))
632 ;; Notice that this bound is a bit rubbish when sigma is near zero. In that
633 ;; case, use the expansion zeta(s) = -1/2-1/2*log(2*pi)*s.
634 (defun float-zeta (s)
635 ;; If s is a rational (real or complex), convert to a float. This
636 ;; is needed so we can compute a sensible epsilon value. (What is
637 ;; the epsilon value for an exact rational?)
638 (setf s
(bigfloat:to s
))
643 (setf s
(coerce s
'(complex flonum
)))))
645 (let ((sigma (bigfloat:realpart s
)))
647 ;; abs(s)^2 < epsilon, use the expansion zeta(s) = -1/2-1/2*log(2*%pi)*s
648 ((bigfloat:< (bigfloat:abs
(bigfloat:* s s
)) (bigfloat:epsilon s
))
651 (bigfloat:log
(bigfloat:* 2 (bigfloat:%pi s
)))
654 ;; Reflection formula
655 ((bigfloat:minusp sigma
)
656 (let ((n (bigfloat:floor sigma
)))
657 ;; If sigma is a negative even integer, zeta(sigma) is zero,
658 ;; from the reflection formula because sin(%pi*n/2) is 0.
659 (when (and (bigfloat:= n sigma
) (evenp n
))
660 (return-from float-zeta
(bigfloat:float
0.0 sigma
))))
661 (bigfloat:* (bigfloat:expt
2 s
)
662 (bigfloat:expt
(bigfloat:%pi s
)
664 (bigfloat:sin
(bigfloat:* (bigfloat:/ (bigfloat:%pi s
)
667 (bigfloat:to
($gamma
(to (bigfloat:-
1 s
))))
668 (float-zeta (bigfloat:-
1 s
))))
670 ;; The general formula from above. Call the imaginary part "tau" rather
671 ;; than the "t" above, because that isn't a CL keyword...
673 (let* ((tau (bigfloat:imagpart s
))
676 (if (bigfloat:zerop tau
) 0
678 (bigfloat:* 1.6 (bigfloat:abs tau
))
679 (bigfloat:log
(bigfloat:1+
681 (bigfloat:/ tau sigma
))))))
684 (bigfloat:-
1 (bigfloat:expt
2 (bigfloat:-
1 s
)))))))
686 (logeps (bigfloat:log
(bigfloat:epsilon s
)))
688 (n (max (bigfloat:ceiling
689 (bigfloat:/ (bigfloat:- logh logeps
) (bigfloat:log
8)))
695 ;; sum(binomial(n,j), j, k, n) = sum(binomial(n,j), j, n, k)
698 (loop for j from n downto k
702 (setf term
(/ (* term j
) (+ n
1 (- j
))))))
704 ;; (format t "n = ~D terms~%" n)
705 ;; sum1 = sum((-1)^(k-1)/k^s,k,1,n)
706 ;; sum2 = sum((-1)^(k-1)/e(n,k-n)/k^s, k, n+1, 2*n)
707 ;; = (-1)^n*sum((-1)^(m-1)*e(n,m)/(n+k)^s, k, 1, n)
708 (loop for k from
1 to n
709 for d
= (bigfloat:expt k s
)
711 (bigfloat:incf sum1
(bigfloat:/ (cl:expt -
1 (- k
1)) d
))
712 (bigfloat:incf sum2
(bigfloat:/ (* (cl:expt -
1 (- k
1))
714 (bigfloat:expt
(+ k n
) s
))))
715 finally
(return (values sum1 sum2
)))
717 (setq sum2
(bigfloat:- sum2
)))
718 (bigfloat:/ (bigfloat:+ sum1
719 (bigfloat:/ sum2
(bigfloat:expt
2 n
)))
720 (bigfloat:-
1 (bigfloat:expt
2 (bigfloat:-
1 s
))))))))))
722 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
725 (cond ((fixnump n
) (ffib n
))
726 (t (setq $prevfib
`(($fib
) ,(add2* n -
1)))
730 (declare (fixnum %n
))
738 (let* ((f2 (ffib (ash (logandc2 %n
1) -
1))) ; f2 = fib(n/2) or fib((n-1)/2)
740 (y (* $prevfib $prevfib
))
742 (setq f2
(- (* x x
) y
)
751 ((fixnump n
) (lucas n
))
752 (t (setq $next_lucas
`(($lucas
) ,(add2* n
1)))
757 (let ((w 2) (x 2) (y 1) u v
(sign (signum n
))) (declare (fixnum sign
))
759 (do ((i (1- (integer-length n
)) (1- i
)))
762 (setq u
(* x x
) v
(* y y
))
764 (setq y
(+ v w
) x
(+ y
(- u
) w
) w -
2)
765 (setq x
(- u w
) y
(+ v w
(- x
)) w
2) ))
767 ((or (= 1 sign
) (not (logbitp 0 n
)))
771 (setq $next_lucas
(neg y
))
774 ;; continued fraction stuff
776 (defmfun $cfdisrep
(a)
777 (cond ((not ($listp a
))
778 (merror (intl:gettext
"cfdisrep: argument must be a list; found ~M") a
))
779 ((null (cddr a
)) (cadr a
))
781 (list '(mexpt) (cfdisrep1 (cddr a
)) -
1))
782 ((cfdisrep1 (cdr a
)))))
786 (list '(mplus simp cf
) (car a
)
787 (prog2 (setq a
(cfdisrep1 (cdr a
)))
788 (cond ((integerp a
) (list '(rat simp
) 1 a
))
789 (t (list '(mexpt simp
) a -
1))))))
794 (cond ((integerp a
) (list a
))
795 ((eq (caar a
) 'mlist
) (cdr a
))
796 ((eq (caar a
) 'rat
) (ratcf (cadr a
) (caddr a
)))
797 ((merror (intl:gettext
"cf: continued fractions must be lists or integers; found ~M") a
))))
800 (cond ((null (cdr a
)) (car a
))
801 ((cons '(mlist simp cf
) a
))))
803 ;;; Translation properties for $CF defined in MAXSRC;TRANS5 >
806 (cfratsimp (let ($listarith
)
807 (cfeval (meval (fexprcheck a
))))))
809 ;; Definition of cfratsimp as given in SF bug report # 620928.
812 ((member 'cf
(car a
) :test
#'eq
) a
)
813 (t (cons '(mlist cf simp
)
814 (apply 'find-cf
(cf-back-recurrence (cdr a
)))))))
816 ; Code to expand nth degree roots of integers into continued fraction
817 ; approximations. E.g. cf(2^(1/3))
818 ; Courtesy of Andrei Zorine (feniy@mail.nnov.ru) 2005/05/07
821 (let ((ans (list '(mlist xf
))) ent
($algebraic $true
))
822 (dotimes (i $cflength
(nreverse ans
))
823 (setq ent
(meval `(($floor
) ,b
))
825 b
($ratsimp
(m// (m- b ent
)))))))
828 (let (temp $ratprint
)
829 (cond ((integerp a
) (list '(mlist cf
) a
))
831 (let ((a (maxima-rationalize a
)))
832 (cons '(mlist cf
) (ratcf (car a
) (cdr a
)))))
835 (setq a
(bigfloat2rat a
))
836 (cons '(mlist cf
) (ratcf (car a
) (cdr a
)))))
838 (merror (intl:gettext
"cf: ~:M is not a continued fraction.") a
))
840 (cons '(mlist cf
) (ratcf (cadr a
) (caddr a
))))
841 ((eq (caar a
) 'mlist
)
843 ;;the following doesn't work for non standard form
844 ;; (cfplus a '((mlist) 0)))
845 ((and (mtimesp a
) (cddr a
) (null (cdddr a
))
848 (fixnump (cadr (caddr a
)))
849 (alike1 (caddr (caddr a
)) '((rat) 1 2)))
850 (cfsqrt (cfeval (* (expt (cadr a
) 2) (cadr (caddr a
))))))
851 ((eq (caar a
) 'mexpt
)
852 (cond ((alike1 (caddr a
) '((rat) 1 2))
853 (cfsqrt (cfeval (cadr a
))))
854 ((integerp (m* 2 (caddr a
))) ; a^(n/2) was sqrt(a^n)
855 (cfsqrt (cfeval (cfexpt (cadr a
) (m* 2 (caddr a
))))))
856 ((integerp (cadr a
)) (cfnroot a
)) ; <=== new case x
857 ((cfexpt (cfeval (cadr a
)) (caddr a
)))))
858 ((setq temp
(assoc (caar a
) '((mplus . cfplus
) (mtimes . cftimes
) (mquotient . cfquot
)
859 (mdifference . cfdiff
) (mminus . cfminus
)) :test
#'eq
))
860 (cf (cfeval (cadr a
)) (cddr a
) (cdr temp
)))
862 (cfeval ($ratdisrep a
)))
863 (t (merror (intl:gettext
"cf: ~:M is not a continued fraction.") a
)))))
867 ((cf (funcall fun a
(meval (list '($cf
) (car l
)))) (cdr l
) fun
))))
870 (setq a
(cfmak a
) b
(cfmak b
))
871 (makcf (cffun '(0 1 1 0) '(0 0 0 1) a b
)))
874 (setq a
(cfmak a
) b
(cfmak b
))
875 (makcf (cffun '(1 0 0 0) '(0 0 0 1) a b
)))
878 (setq a
(cfmak a
) b
(cfmak b
))
879 (makcf (cffun '(0 1 -
1 0) '(0 0 0 1) a b
)))
883 (makcf (cffun '(0 0 -
1 0) '(0 0 0 1) a
'(0))))
886 (setq a
(cfmak a
) b
(cfmak b
))
887 (makcf (cffun '(0 1 0 0) '(0 0 1 0) a b
)))
891 (cond ((null (integerp e
))
892 (merror (intl:gettext
"cf: can't raise continued fraction to non-integral power ~M") e
))
894 (do ((n (ash n -
1) (ash n -
1))
895 (s (cond ((oddp n
) b
)
901 ((cffun '(0 0 0 1) '(0 1 0 0) b
'(1))))))
902 (setq b
(cffun '(1 0 0 0) '(0 0 0 1) b b
))
904 (setq s
(cffun '(1 0 0 0) '(0 0 0 1) s b
))))))))
907 (defun conf1 (f g a b
&aux
(den (conf2 g a b
)))
909 (* (signum (conf2 f a b
)) ; (/ most-positive-fixnum (^ 2 4))
911 (t (truncate (conf2 f a b
) den
))))
913 (defun conf2 (n a b
) ;2*(abn_0+an_1+bn_2+n_3)
914 (* 2 (+ (* (car n
) a b
)
919 ;;(cffun '(0 1 1 0) '(0 0 0 1) '(1 2) '(1 1 1 2)) gets error
922 (defun cf-convergents-p-q (cf &optional
(n (length cf
)) &aux pp qq
)
923 "returns two lists such that pp_i/qq_i is the quotient of the first i terms
929 (setq pp
(list (1+ (* (first cf
) (second cf
))) (car cf
)))
930 (setq qq
(list (second cf
) 1))
933 (loop for i from
2 to n
936 (push (+ (* (car cf
) (car pp
))
938 (push (+ (* (car cf
) (car qq
))
941 finally
(return (list (reverse pp
) (reverse qq
)))))))
944 (defun find-cf1 (p q so-far
)
945 (multiple-value-bind (quot rem
) (truncate p q
)
946 (cond ((< rem
0) (incf rem q
) (incf quot -
1))
947 ((zerop rem
) (return-from find-cf1
(cons quot so-far
))))
948 (setq so-far
(cons quot so-far
))
949 (find-cf1 q rem so-far
)))
952 "returns the continued fraction for p and q integers, q not zero"
953 (cond ((zerop q
) (maxima-error "find-cf: quotient by zero"))
954 ((< q
0) (setq p
(- p
)) (setq q
(- q
))))
955 (nreverse (find-cf1 p q
())))
957 (defun cf-back-recurrence (cf &aux tem
(num-gg 0)(den-gg 1))
958 "converts CF (a continued fraction list) to a list of numerator
959 denominator using recurrence from end
960 and not calculating intermediate quotients.
961 The numerator and denom are relatively
963 (loop for v in
(reverse cf
)
964 do
(setq tem
(* den-gg v
))
965 (setq tem
(+ tem num-gg
))
970 (cond ((and (<= den-gg
0) (< num-gg
0))
971 (list (- den-gg
) (- num-gg
)))
972 (t(list den-gg num-gg
))))))
974 (declare-top (unspecial w
))
976 ;;(cffun '(0 1 1 0) '(0 0 0 1) '(1 2) '(1 1 1 2)) gets error
979 (defun cffun (f g a b
)
981 (declare (special v
))
982 a
(and (zerop (cadddr g
))
986 (return (reverse c
)))
987 (and (equal (setq w
(conf1 f g
(car a
) (1+ (car b
))))
988 (setq v
(conf1 f g
(car a
) (car b
))))
989 (equal (conf1 f g
(1+ (car a
)) (car b
)) v
)
990 (equal (conf1 f g
(1+ (car a
)) (1+ (car b
))) v
)
991 (setq g
(mapcar #'(lambda (a b
)
992 (declare (special v
))
997 (cond ((< (abs (- (conf1 f g
(1+ (car a
)) (car b
)) v
))
999 (cond ((setq v
(cdr b
))
1000 (setq f
(conf6 f b
))
1001 (setq g
(conf6 g b
))
1003 (t (setq f
(conf7 f b
)) (setq g
(conf7 g b
)))))
1005 (cond ((setq v
(cdr a
))
1006 (setq f
(conf4 f a
))
1007 (setq g
(conf4 g a
))
1009 (t (setq f
(conf5 f a
)) (setq g
(conf5 g a
))))))
1012 (defun conf4 (n a
) ;n_0*a_0+n_2,n_1*a_0+n_3,n_0,n_1
1013 (list (+ (* (car n
) (car a
)) (caddr n
))
1014 (+ (* (cadr n
) (car a
)) (cadddr n
))
1018 (defun conf5 (n a
) ;0,0, n_0*a_0,n_2
1020 (+ (* (car n
) (car a
)) (caddr n
))
1021 (+ (* (cadr n
) (car a
)) (cadddr n
))))
1024 (list (+ (* (car n
) (car b
)) (cadr n
))
1026 (+ (* (caddr n
) (car b
)) (cadddr n
))
1030 (list 0 (+ (* (car n
) (car b
)) (cadr n
))
1031 0 (+ (* (caddr n
) (car b
)) (cadddr n
))))
1034 (cond ((cddr n
) ;A non integer
1035 (merror (intl:gettext
"cf: argument of sqrt must be an integer; found ~M") n
))
1036 ((setq n
(cadr n
))))
1038 (cond ((= $cflength
1)
1039 (cons '(mlist simp
) n
))
1041 (a (copy-tree (cdr n
))))
1042 ((> i $cflength
) (cons '(mlist simp
) n
))
1043 (setq n
(nconc n
(copy-tree a
)))))))
1046 (let ((isqrtn ($isqrt n
)))
1047 (when (or (not (integerp n
))
1049 (= (* isqrtn isqrtn
) n
))
1051 (intl:gettext
"qunit: Argument must be a positive non quadratic integer.")))
1052 (let ((l (sqcont n
)))
1053 (list '(mplus) (pelso1 l
0 1)
1055 (list '(mexpt) n
'((rat) 1 2))
1058 (defun pelso1 (l a b
)
1059 (do ((i l
(cdr i
))) (nil)
1060 (and (null (cdr i
)) (return b
))
1061 (setq b
(+ a
(* (car i
) (setq a b
))))))
1064 (prog (q q1 q2 m m1 a0 a l
)
1065 (setq a0
($isqrt n
) a
(list a0
) q2
1 m1 a0
1066 q1
(- n
(* m1 m1
)) l
(* 2 a0
))
1067 a
(setq a
(cons (truncate (+ m1 a0
) q1
) a
))
1068 (cond ((equal (car a
) l
)
1069 (return (nreverse a
))))
1070 (setq m
(- (* (car a
) q1
) m1
)
1071 q
(+ q2
(* (car a
) (- m1 m
)))
1077 a
(cond ((equal y
1) (return (nreverse (cons x a
))))
1079 (setq b
(+ y
(rem x y
))
1080 a
(cons (1- (truncate x y
)) a
)
1085 ((equal x y
) (return (nreverse (cons 1 a
))))
1087 (setq a
(cons (truncate x y
) a
) x y y b
)))
1090 (defmfun $cfexpand
(x)
1091 (cond ((null ($listp x
)) x
)
1092 ((cons '($matrix
) (cfexpand (cdr x
))))))
1094 (defun cfexpand (ll)
1096 (p2 1 (simplify (list '(mplus) (list '(mtimes) (car l
) p2
) p1
)))
1098 (q2 0 (simplify (list '(mplus) (list '(mtimes) (car l
) q2
) q1
)))
1100 ((null l
) (list (list '(mlist) p2 p1
) (list '(mlist) q2 q1
)))))
1105 (push (simplify e
) sum
))
1108 (push (simplify e
) usum
))
1110 (defun simpsum2 (exp i lo hi
)
1111 (prog (*plus
*times $simpsum u
)
1112 (setq *plus
(list 0) *times
1)
1113 (when (or (and (eq hi
'$inf
) (eq lo
'$minf
))
1114 (equal 0 (m+ hi lo
)))
1115 (setq $simpsum t lo
0)
1116 (setq *plus
(cons (m* -
1 *times
(maxima-substitute 0 i exp
)) *plus
))
1117 (setq exp
(m+ exp
(maxima-substitute (m- i
) i exp
))))
1118 (cond ((eq ($sign
(setq u
(m- hi lo
))) '$neg
)
1121 (merror (intl:gettext
"sum: lower bound ~M greater than upper bound ~M") lo hi
)))
1123 (return (m+l
(cons (freesum exp lo hi
*times
) *plus
))))
1125 ((setq exp
(sumsum exp i lo hi
))
1126 (setq exp
(m* *times
(dosum (cadr exp
) (caddr exp
)
1127 (cadddr exp
) (cadr (cdddr exp
)) t
:evaluate-summand nil
))))
1128 (t (return (m+l
*plus
))))
1129 (return (m+l
(cons exp
*plus
)))))
1131 (defun sumsum (e *var
* lo hi
)
1133 (cond ((eq hi
'$inf
)
1134 (cond (*infsumsimp
(isum e lo
))
1135 ((setq usum
(list e
)))))
1136 ((finite-sum e
1 lo hi
)))
1138 (return-from sumsum
(list '(%sum
) e
*var
* lo hi
))))
1141 #'(lambda (q) (simptimes (list '(mtimes) *times q
) 1 nil
))
1144 (and usum
(setq usum
(list '(%sum
) (simplus (cons '(plus) usum
) 1 t
) *var
* lo hi
)))))
1146 (defun finite-sum (e y lo hi
)
1149 (adsum (m* y e
(m+ hi
1 (m- lo
)))))
1151 (adsum (m* y
(fpolysum e lo hi
))))
1152 ((eq (caar e
) '%binomial
) (fbino e y lo hi
))
1153 ((eq (caar e
) 'mplus
)
1154 (mapc #'(lambda (q) (finite-sum q y lo hi
)) (cdr e
)))
1155 ((and (or (mtimesp e
) (mexptp e
) (mplusp e
))
1161 (defun isum-giveup (e)
1162 (cond ((atom e
) nil
)
1163 ((eq (caar e
) 'mexpt
)
1164 (not (or (free (cadr e
) *var
*)
1165 (ratp (caddr e
) *var
*))))
1166 ((member (caar e
) '(mplus mtimes
) :test
#'eq
)
1167 (some #'identity
(mapcar #'isum-giveup
(cdr e
))))
1171 (cond ((isum-giveup e
)
1172 (setq sum nil usum
(list e
)))
1173 ((eq (catch 'isumout
(isum1 e lo
)) 'divergent
)
1174 (merror (intl:gettext
"sum: sum is divergent.")))))
1177 (cond ((free e
*var
*)
1178 (unless (eq (asksign e
) '$zero
)
1179 (throw 'isumout
'divergent
)))
1181 (adsum (ipolysum e lo
)))
1182 ((eq (caar e
) 'mplus
)
1183 (mapc #'(lambda (x) (isum1 x lo
)) (cdr e
)))
1187 (defun ipolysum (e lo
)
1188 (ipoly1 ($expand e
) lo
))
1190 (defun ipoly1 (e lo
)
1191 (cond ((smono e
*var
*)
1192 (ipoly2 *a
*n lo
(asksign (simplify (list '(mplus) *n
1)))))
1194 (cons '(mplus) (mapcar #'(lambda (x) (ipoly1 x lo
)) (cdr e
))))
1198 (defun ipoly2 (a n lo sign
)
1199 (cond ((member (asksign lo
) '($zero $negative
) :test
#'eq
)
1200 (throw 'isumout
'divergent
)))
1201 (unless (equal lo
1)
1204 ((mtimes) ,a -
1 ((mexpt) ,*var
* ,n
))
1205 ,*var
* 1 ((mplus) -
1 ,lo
)))))
1206 (cond ((eq sign
'$negative
)
1207 (list '(mtimes) a
($zeta
(meval (list '(mtimes) -
1 n
)))))
1208 ((throw 'isumout
'divergent
))))
1210 (defun fsgeo (e y lo hi
)
1211 (let ((r ($ratsimp
(div* (maxima-substitute (list '(mplus) *var
* 1) *var
* e
) e
))))
1215 (list '(mplus) 1 hi
(list '(mtimes) -
1 lo
))
1216 (maxima-substitute lo
*var
* e
))))
1220 (maxima-substitute 0 *var
* e
)
1222 (list '(mexpt) r
(list '(mplus) hi
1))
1223 (list '(mtimes) -
1 (list '(mexpt) r lo
)))
1224 (list '(mexpt) (list '(mplus) r -
1) -
1)))))))
1227 (let ((r ($ratsimp
(div* (maxima-substitute (list '(mplus) *var
* 1) *var
* e
) e
))))
1229 (isgeo1 (maxima-substitute lo
*var
* e
)
1230 r
(asksign (simplify (list '(mplus) (list '(mabs) r
) -
1)))))))
1232 (defun isgeo1 (a r sign
)
1233 (cond ((eq sign
'$positive
)
1234 (throw 'isumout
'divergent
))
1236 (throw 'isumout
'divergent
))
1237 ((eq sign
'$negative
)
1238 (adsum (list '(mtimes) a
1239 (list '(mexpt) (list '(mplus) 1 (list '(mtimes) -
1 r
)) -
1))))))
1242 ;; Sums of polynomials using
1243 ;; bernpoly(x+1, n) - bernpoly(x, n) = n*x^(n-1)
1245 ;; sum(k^n, k, A, B) = 1/(n+1)*(bernpoly(B+1, n+1) - bernpoly(A, n+1))
1247 ;; fpoly1 returns 1/(n+1)*(bernpoly(foo+1, n+1) - bernpoly(0, n+1)) for each power
1248 ;; in the polynomial e
1250 (defun fpolysum (e lo hi
) ;returns *ans*
1251 (let ((a (fpoly1 (setq e
($expand
($ratdisrep
($rat e
*var
*)))) lo
))
1255 (maxima-substitute hi
'foo a
))
1257 (list '(mplus) (maxima-substitute hi
'foo a
)
1258 (list '(mtimes) -
1 (maxima-substitute (list '(mplus) lo -
1) 'foo a
)))))))
1260 (defun fpoly1 (e lo
)
1261 (cond ((smono e
*var
*)
1262 (fpoly2 *a
*n e lo
))
1263 ((eq (caar e
) 'mplus
)
1264 (cons '(mplus) (mapcar #'(lambda (x) (fpoly1 x lo
)) (cdr e
))))
1267 (defun fpoly2 (a n e lo
)
1268 (cond ((null (and (integerp n
) (> n -
1))) (adusum e
) 0)
1270 (m* (cond ((signp e lo
)
1275 (m* a
(list '(rat) 1 (1+ n
))
1276 (m- ($bernpoly
(m+ 'foo
1) (1+ n
))
1277 ($bern
(1+ n
))))))))
1279 ;; fbino can do these sums:
1280 ;; a) sum(binomial(n,k),k,0,n) -> 2^n
1281 ;; b) sum(binomial(n-k,k,k,0,n) -> fib(n+1)
1282 ;; c) sum(binomial(n,2k),k,0,n) -> 2^(n-1)
1283 ;; d) sum(binomial(a+k,b),k,l,h) -> binomial(h+a+1,b+1) - binomial(l+a,b+1)
1284 (defun fbino (e y lo hi
)
1287 ;; check that n and d are linear in *var*
1288 (when (null (setq n
(m2 (cadr e
) (list 'n
'linear
* *var
*))))
1289 (return (adusum e
)))
1290 (setq n
(cdr (assoc 'n n
:test
#'eq
)))
1291 (when (null (setq d
(m2 (caddr e
) (list 'd
'linear
* *var
*))))
1292 (return (adusum e
)))
1293 (setq d
(cdr (assoc 'd d
:test
#'eq
)))
1295 ;; binomial(a+b*k,c+b*k) -> binomial(a+b*k, a-c)
1296 (when (equal (cdr n
) (cdr d
))
1297 (setq d
(cons (m- (car n
) (car d
)) 0)))
1300 ;; substitute k with -k in sum(binomial(a+b*k, c-d*k))
1301 ;; and sum(binomial(a-b*k,c))
1302 ((and (numberp (cdr d
))
1303 (or (minusp (cdr d
))
1304 (and (zerop (cdr d
))
1307 (rplacd d
(- (cdr d
)))
1308 (rplacd n
(- (cdr n
)))
1311 (t (setq l lo h hi
)))
1315 ;; sum(binomial(a+k,c),k,l,h)
1316 ((and (equal 0 (cdr d
)) (equal 1 (cdr n
)))
1317 (adsum (m* y
(m- (list '(%binomial
) (m+ h
(car n
) 1) (m+ (car d
) 1))
1318 (list '(%binomial
) (m+ l
(car n
)) (m+ (car d
) 1))))))
1320 ;; sum(binomial(n,k),k,0,n)=2^n
1321 ((and (equal 1 (cdr d
)) (equal 0 (cdr n
)))
1322 ;; sum(binomial(n,k+c),k,l,h)=sum(binomial(n,k+c+l),k,0,h-l)
1325 (if (and (integerp (m- (car n
) h1
))
1328 (adsum (m* y
(m^
2 (car n
))))
1329 (when (member (asksign (m- (m+ h1 c
) (car n
))) '($zero $negative
) :test
#'eq
)
1330 (adsum (m* -
1 y
(dosum (list '(%binomial
) (car n
) *var
*)
1331 *var
* (m+ h1 c
1) (car n
) t
:evaluate-summand nil
))))
1333 (adsum (m* -
1 y
(dosum (list '(%binomial
) (car n
) *var
*)
1334 *var
* 0 (m- c
1) t
:evaluate-summand nil
)))))
1337 ;; sum(binomial(b-k,k),k,0,floor(b/2))=fib(b+1)
1338 ((and (equal -
1 (cdr n
)) (equal 1 (cdr d
)))
1339 ;; sum(binomial(a-k,b+k),k,l,h)=sum(binomial(a+b-k,k),k,l+b,h+b)
1340 (let ((h1 (m+ h
(car d
)))
1342 (a1 (m+ (car n
) (car d
))))
1343 ;; sum(binomial(a1-k,k),k,0,floor(a1/2))=fib(a1+1)
1344 ;; we only do sums with h>floor(a1/2)
1345 (if (and (integerp l1
)
1346 (member (asksign (m- h1
(m// a1
2))) '($zero $positive
) :test
#'eq
))
1348 (adsum (m* y
($fib
(m+ a1
1))))
1350 (adsum (m* -
1 y
(dosum (list '(%binomial
) (m- a1
*var
*) *var
*)
1351 *var
* 0 (m- l1
1) t
:evaluate-summand nil
)))))
1354 ;; sum(binomial(n,2*k),k,0,floor(n/2))=2^(n-1)
1355 ;; sum(binomial(n,2*k+1),k,0,floor((n-1)/2))=2^(n-1)
1356 ((and (equal 0 (cdr n
)) (equal 2 (cdr d
)))
1357 ;; sum(binomial(a,2*k+b),k,l,h)=sum(binomial(a,2*k),k,l+b/2,h+b/2), b even
1358 ;; sum(binomial(a,2*k+b),k,l,h)=sum(binomial(a,2*k+1),k,l+(b-1)/2,h+(b-1)/2), b odd
1360 (r1 (if (oddp (car d
)) 1 0))
1361 (l1 (if (oddp (car d
))
1362 (m+ l
(truncate (1- (car d
)) 2))
1363 (m+ l
(truncate (car d
) 2)))))
1364 (when (and (integerp l1
)
1365 (member (asksign (m- a hi
)) '($zero $positive
) :test
#'eq
))
1366 (adsum (m* y
(m^
2 (m- a
1))))
1368 (adsum (m* -
1 y
(dosum (list '(%binomial
) a
(m+ *var
* *var
* r1
))
1369 *var
* 0 (m- l1
1) t
:evaluate-summand nil
)))))))
1371 ;; other sums we can't do
1377 (defmspec $product
(l)
1379 (cond ((not (= (length l
) 4)) (merror (intl:gettext
"product: expected exactly four arguments.")))
1380 ((dosum (car l
) (cadr l
) (meval (caddr l
)) (meval (cadddr l
)) nil
:evaluate-summand t
))))
1382 (declare-top (special $ratsimpexpons
))
1384 ;; Is this guy actually looking at the value of its middle arg?
1386 (defun simpprod (x y z
)
1387 (let (($ratsimpexpons t
))
1389 (setq y
(simplifya (cadr x
) z
)))
1390 ((setq y
(simptimes (list '(mexpt) (cadr x
) y
) 1 z
)))))
1391 (simpprod1 y
(caddr x
)
1392 (simplifya (cadddr x
) z
)
1393 (simplifya (cadr (cdddr x
)) z
)))
1395 (defmfun $taytorat
(e)
1396 (cond ((mbagp e
) (cons (car e
) (mapcar #'$taytorat
(cdr e
))))
1397 ((or (atom e
) (not (member 'trunc
(cdar e
) :test
#'eq
))) (ratf e
))
1398 ((catch 'srrat
(srrat e
)))
1399 (t (ratf ($ratdisrep e
)))))
1402 (cons (list 'mrat
'simp
(caddar e
) (cadddr (car e
)))
1406 (if (pscoefp e
) e
(srrat3 (terms e
) (gvar e
))))
1408 (defun srrat3 (l *var
*)
1409 (cond ((null l
) '(0 .
1))
1410 ((null (=1 (cdr (le l
))))
1413 (rattimes (cons (list *var
* (car (le l
)) 1) 1)
1417 (rattimes (cons (list *var
* (car (le l
)) 1) 1)
1420 (srrat3 (n-term l
) *var
*)))))
1423 (declare-top (special $props
*i
))
1425 (defmspec $deftaylor
(l)
1426 (prog (fun series param op ops
)
1427 a
(when (null (setq l
(cdr l
))) (return (cons '(mlist) ops
)))
1428 (setq fun
(meval (car l
)) series
(meval (cadr l
)) l
(cdr l
) param
() )
1429 (when (or (atom fun
)
1430 (if (eq (caar fun
) 'mqapply
)
1431 (or (cdddr fun
) ; must be one parameter
1432 (null (cddr fun
)) ; must have exactly one
1433 (do ((subs (cdadr fun
) (cdr subs
)))
1435 (setq op
(caaadr fun
))
1437 (setq param
(caddr fun
)))
1439 (unless (atom (car subs
)) (return 't
))))
1441 (setq op
(caar fun
))
1442 (when (cdr fun
) (setq param
(cadr fun
)))
1443 (or (and (zl-get op
'op
) (not (eq op
'mfactorial
)))
1444 (not (atom (cadr fun
)))
1445 (not (= (length fun
) 2))))))
1446 (merror (intl:gettext
"deftaylor: don't know how to handle this function: ~M") fun
))
1447 (when (zl-get op
'sp2
)
1448 (mtell (intl:gettext
"deftaylor: redefining ~:M.~%") op
))
1449 (when param
(setq series
(subst 'sp2var param series
)))
1450 (setq series
(subsum '*index series
))
1451 (putprop op series
'sp2
)
1452 (when (eq (caar fun
) 'mqapply
)
1453 (putprop op
(cdadr fun
) 'sp2subs
))
1458 (defun subsum (*i e
) (susum1 e
))
1462 ((eq (caar e
) '%sum
)
1463 (if (null (smonop (cadr e
) 'sp2var
))
1464 (merror (intl:gettext
"deftaylor: argument must be a power series at 0."))
1465 (subst *i
(caddr e
) e
)))
1466 (t (recur-apply #'susum1 e
))))
1468 (declare-top (special varlist genvar $factorflag $ratfac
*p
* *var
* *x
*))
1470 (defmfun $polydecomp
(e v
)
1471 (let ((varlist (list v
))
1473 *var
* p den $factorflag $ratfac
)
1474 (setq p
(cdr (ratf (ratdisrep e
)))
1475 *var
* (cdr (ratf v
)))
1476 (cond ((or (null (cdr *var
*))
1477 (null (equal (cdar *var
*) '(1 1))))
1478 (merror (intl:gettext
"polydecomp: second argument must be an atom; found ~M") v
))
1479 (t (setq *var
* (caar *var
*))))
1480 (cond ((or (pcoefp (cdr p
))
1481 (null (eq (cadr p
) *var
*)))
1484 (t (merror (intl:gettext
"polydecomp: cannot apply 'polydecomp' to a rational function."))))
1486 (cond ((or (pcoefp p
)
1487 (null (eq (car p
) *var
*)))
1488 (list (rdis (cons p den
))))
1489 (t (setq p
(pdecomp p
*var
*))
1491 (setq p
(mapcar #'(lambda (q) (cons q
1)) p
))
1495 (cons (rdis (cons (caar p
)
1496 (ptimes (cdar p
) den
)))
1497 (mapcar #'rdis
(cdr p
))))
1498 (cond ((setq a
(pdecpow (car l
) *var
*))
1505 (cons (ptterm (cdaadr a
) 1)
1509 (ptterm (cdaadr a
) 0)
1513 (cons (list *var
* 1 1) 1)))
1514 (t (rplacd l
(list (cadr a
)))))))))))))
1517 ;;; POLYDECOMP is like $POLYDECOMP except it takes a poly in *POLY* format (as
1518 ;;; defined in SOLVE) (numerator of a RAT form) and returns a list of
1519 ;;; headerless rat forms. In otherwords, it is $POLYDECOMP minus type checking
1520 ;;; and conversions to/from general representation which SOLVE doesn't
1521 ;;; want/need on a general basis.
1522 ;;; It is used in the SOLVE package and as such it should have an autoload
1525 (defun polydecomp (p *var
*)
1526 (let ($factorflag $ratfac
)
1527 (cond ((or (pcoefp p
)
1528 (null (eq (car p
) *var
*)))
1530 (t (setq p
(pdecomp p
*var
*))
1531 (do ((l (setq p
(mapcar #'(lambda (q) (cons q
1)) p
))
1535 (cons (cons (caar p
)
1538 (cond ((setq a
(pdecpow (car l
) *var
*))
1545 (cons (ptterm (cdaadr a
) 1)
1549 (ptterm (cdaadr a
) 0)
1553 (cons (list *var
* 1 1) 1)))
1554 (t (rplacd l
(list (cadr a
))))))))))))
1558 (defun pdecred (f h
*var
*) ;f = g(h(*var*))
1559 (cond ((or (pcoefp h
) (null (eq (car h
) *var
*))
1561 (null (zerop (rem (cadr f
) (cadr h
))))
1562 (and (null (pzerop (caadr (setq f
(pdivide f h
)))))
1563 (equal (cdadr f
) 1)))
1565 (t (do ((q (pdivide (caar f
) h
) (pdivide (caar q
) h
))
1569 (cond ((and (equal (cdadr q
) 1)
1570 (or (pcoefp (caadr q
))
1571 (null (eq (caar (cadr q
)) *var
*))))
1572 (psimp *var
* (cons i
(cons (caadr q
) *ans
*))))))
1573 (cond ((and (equal (cdadr q
) 1)
1574 (or (pcoefp (caadr q
))
1575 (null (eq (caar (cadr q
)) *var
*))))
1576 (and (null (pzerop (caadr q
)))
1577 (setq *ans
* (cons i
(cons (caadr q
) *ans
*)))))
1578 (t (return nil
)))))))
1580 (defun pdecomp (p *var
*)
1581 (let ((c (ptterm (cdr p
) 0))
1582 (a) (*x
* (list *var
* 1 1)))
1583 (cons (pcplus c
(car (setq a
(pdecomp* (pdifference p c
)))))
1586 (defun pdecomp* (*p
*)
1588 (l (pdecgdfrm (pfactor (pquotient *p
* *x
*)))))
1589 (cond ((or (pdecprimep (cadr *p
*))
1590 (null (setq a
(pdecomp1 *x
* l
))))
1592 (t (append (pdecomp* (car a
)) (cdr a
))))))
1594 (defun pdecomp1 (prod l
)
1596 (and (null (equal (cadr prod
) (cadr *p
*)))
1597 (setq l
(pdecred *p
* prod
*var
*))
1599 ((pdecomp1 prod
(cdr l
)))
1600 (t (pdecomp1 (ptimes (car l
) prod
) (cdr l
)))))
1602 (defun pdecgdfrm (l) ;Get list of divisors
1603 (do ((l (copy-list l
))
1607 (rplaca (cdr l
) (1- (cadr l
)))
1608 (cond ((signp e
(cadr l
))
1610 (cond ((null l
) (return ll
)))))
1612 (defun pdecprimep (x)
1613 (setq x
(cfactorw x
))
1614 (and (null (cddr x
)) (equal (cadr x
) 1)))
1616 (defun pdecpow (p *var
*)
1618 (let ((p1 (pderivative p
*var
*))
1619 p2 p1p p1c a lin p2p
)
1620 (setq p1p
(oldcontent p1
)
1621 p1c
(car p1p
) p1p
(cadr p1p
))
1622 (setq p2
(pderivative p1
*var
*))
1623 (setq p2p
(cadr (oldcontent p2
)))
1624 (and (setq lin
(testdivide p1p p2p
))
1626 (eq (car lin
) *var
*)
1628 (rattimes (cons (list *var
* (cadr p
) 1) 1)
1629 (setq a
(ratreduce p1c
1634 (rattimes a
(cons (pexpt lin
(cadr p
)) 1)
1638 (declare-top (unspecial *mfactl
*factlist donel nn
* dn
*
1640 *infsumsimp
*times
*plus sum usum makef
))