You can subscribe to this list here.
| 2001 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(20) |
Dec
(17) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2002 |
Jan
(39) |
Feb
(21) |
Mar
(33) |
Apr
(135) |
May
(53) |
Jun
(88) |
Jul
(47) |
Aug
(59) |
Sep
(207) |
Oct
(40) |
Nov
(7) |
Dec
(26) |
| 2003 |
Jan
(49) |
Feb
(39) |
Mar
(117) |
Apr
(50) |
May
(62) |
Jun
(6) |
Jul
(19) |
Aug
(24) |
Sep
(11) |
Oct
(11) |
Nov
(49) |
Dec
(9) |
| 2004 |
Jan
(29) |
Feb
(123) |
Mar
(32) |
Apr
(53) |
May
(52) |
Jun
(19) |
Jul
(33) |
Aug
(10) |
Sep
(76) |
Oct
(86) |
Nov
(171) |
Dec
(163) |
| 2005 |
Jan
(147) |
Feb
(121) |
Mar
(120) |
Apr
(126) |
May
(120) |
Jun
(213) |
Jul
(76) |
Aug
(79) |
Sep
(140) |
Oct
(83) |
Nov
(156) |
Dec
(202) |
| 2006 |
Jan
(181) |
Feb
(171) |
Mar
(157) |
Apr
(98) |
May
(96) |
Jun
(97) |
Jul
(193) |
Aug
(76) |
Sep
(130) |
Oct
(63) |
Nov
(196) |
Dec
(253) |
| 2007 |
Jan
(256) |
Feb
(293) |
Mar
(276) |
Apr
(258) |
May
(181) |
Jun
(91) |
Jul
(108) |
Aug
(69) |
Sep
(107) |
Oct
(179) |
Nov
(137) |
Dec
(121) |
| 2008 |
Jan
(124) |
Feb
(129) |
Mar
(192) |
Apr
(201) |
May
(90) |
Jun
(86) |
Jul
(115) |
Aug
(142) |
Sep
(49) |
Oct
(91) |
Nov
(95) |
Dec
(218) |
| 2009 |
Jan
(230) |
Feb
(149) |
Mar
(118) |
Apr
(72) |
May
(77) |
Jun
(68) |
Jul
(102) |
Aug
(72) |
Sep
(89) |
Oct
(76) |
Nov
(125) |
Dec
(86) |
| 2010 |
Jan
(75) |
Feb
(90) |
Mar
(89) |
Apr
(121) |
May
(111) |
Jun
(66) |
Jul
(75) |
Aug
(66) |
Sep
(66) |
Oct
(166) |
Nov
(121) |
Dec
(73) |
| 2011 |
Jan
(74) |
Feb
|
Mar
|
Apr
(14) |
May
(22) |
Jun
(31) |
Jul
(53) |
Aug
(37) |
Sep
(23) |
Oct
(25) |
Nov
(31) |
Dec
(28) |
| 2012 |
Jan
(18) |
Feb
(11) |
Mar
(32) |
Apr
(17) |
May
(48) |
Jun
(37) |
Jul
(23) |
Aug
(54) |
Sep
(15) |
Oct
(11) |
Nov
(19) |
Dec
(22) |
| 2013 |
Jan
(11) |
Feb
(32) |
Mar
(24) |
Apr
(37) |
May
(31) |
Jun
(14) |
Jul
(26) |
Aug
(33) |
Sep
(40) |
Oct
(21) |
Nov
(36) |
Dec
(84) |
| 2014 |
Jan
(23) |
Feb
(20) |
Mar
(27) |
Apr
(24) |
May
(31) |
Jun
(27) |
Jul
(34) |
Aug
(26) |
Sep
(21) |
Oct
(45) |
Nov
(23) |
Dec
(73) |
| 2015 |
Jan
(33) |
Feb
(8) |
Mar
(24) |
Apr
(45) |
May
(27) |
Jun
(19) |
Jul
(21) |
Aug
(51) |
Sep
(43) |
Oct
(29) |
Nov
(61) |
Dec
(86) |
| 2016 |
Jan
(99) |
Feb
(52) |
Mar
(80) |
Apr
(61) |
May
(24) |
Jun
(23) |
Jul
(36) |
Aug
(30) |
Sep
(41) |
Oct
(43) |
Nov
(27) |
Dec
(46) |
| 2017 |
Jan
(57) |
Feb
(34) |
Mar
(40) |
Apr
(31) |
May
(78) |
Jun
(49) |
Jul
(72) |
Aug
(33) |
Sep
(26) |
Oct
(82) |
Nov
(69) |
Dec
(29) |
| 2018 |
Jan
(43) |
Feb
(9) |
Mar
|
Apr
(40) |
May
(34) |
Jun
(49) |
Jul
(45) |
Aug
(8) |
Sep
(51) |
Oct
(75) |
Nov
(103) |
Dec
(80) |
| 2019 |
Jan
(153) |
Feb
(78) |
Mar
(47) |
Apr
(48) |
May
(63) |
Jun
(54) |
Jul
(10) |
Aug
(7) |
Sep
(17) |
Oct
(24) |
Nov
(29) |
Dec
(17) |
| 2020 |
Jan
(22) |
Feb
(74) |
Mar
(47) |
Apr
(48) |
May
(12) |
Jun
(44) |
Jul
(13) |
Aug
(18) |
Sep
(26) |
Oct
(36) |
Nov
(25) |
Dec
(23) |
| 2021 |
Jan
(28) |
Feb
(25) |
Mar
(58) |
Apr
(76) |
May
(72) |
Jun
(70) |
Jul
(25) |
Aug
(67) |
Sep
(17) |
Oct
(24) |
Nov
(30) |
Dec
(30) |
| 2022 |
Jan
(51) |
Feb
(39) |
Mar
(72) |
Apr
(65) |
May
(30) |
Jun
(72) |
Jul
(129) |
Aug
(44) |
Sep
(45) |
Oct
(30) |
Nov
(48) |
Dec
(275) |
| 2023 |
Jan
(235) |
Feb
(232) |
Mar
(68) |
Apr
(16) |
May
(52) |
Jun
(87) |
Jul
(143) |
Aug
(32) |
Sep
(26) |
Oct
(15) |
Nov
(20) |
Dec
(74) |
| 2024 |
Jan
(119) |
Feb
(32) |
Mar
(64) |
Apr
(68) |
May
(30) |
Jun
(50) |
Jul
(37) |
Aug
(32) |
Sep
(10) |
Oct
(27) |
Nov
(47) |
Dec
(36) |
| 2025 |
Jan
(94) |
Feb
(68) |
Mar
(79) |
Apr
(66) |
May
(46) |
Jun
(21) |
Jul
(134) |
Aug
(134) |
Sep
(53) |
Oct
(24) |
Nov
(69) |
Dec
(68) |
| 2026 |
Jan
(48) |
Feb
(49) |
Mar
(56) |
Apr
(107) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: tomasriker <tom...@us...> - 2026-04-23 06:35:46
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, master has been updated
via 162a6093a8ed1eb17e1446f33757701b6ea57816 (commit)
from 5ed3b159c792c2626a1b41cb2d2e860a723b6b2d (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 162a6093a8ed1eb17e1446f33757701b6ea57816
Author: David Scherfgen <d.s...@go...>
Date: Thu Apr 23 08:35:18 2026 +0200
APPARENTLY-A-DIRECTORY-P: support Allegro CL via EXCL:FILE-DIRECTORY-P
Allegro CL puts a directory's name into :NAME, unlike other Lisps,
so we need a different test. Allegro CL provides an internal function for this.
diff --git a/src/mload.lisp b/src/mload.lisp
index 0ba8f6138..a220814e1 100644
--- a/src/mload.lisp
+++ b/src/mload.lisp
@@ -640,7 +640,8 @@
(if foo (not (apparently-a-directory-p foo)))))
(defun apparently-a-directory-p (path)
- (member (pathname-name path) '(nil :unspecific) :test #'eq))
+ #+allegro (excl:file-directory-p path)
+ #-allegro (member (pathname-name path) '(nil :unspecific) :test #'eq))
;; We keep these here in case we want to optimize the search. To
;; speed things up, we might want to support search lists like
-----------------------------------------------------------------------
Summary of changes:
src/mload.lisp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
hooks/post-receive
--
Maxima CAS
|
|
From: tomasriker <tom...@us...> - 2026-04-23 06:10:06
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, master has been updated
via 5ed3b159c792c2626a1b41cb2d2e860a723b6b2d (commit)
from dee5760083240743043639aece795d3fcaaa94c3 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 5ed3b159c792c2626a1b41cb2d2e860a723b6b2d
Author: David Scherfgen <d.s...@go...>
Date: Thu Apr 23 08:09:20 2026 +0200
APPARENTLY-A-DIRECTORY-P: also check for :UNSPECIFIC to support LispWorks
In LispWorks, PATHNAME-NAME of a directory listed by DIRECTORY is :UNSPECIFIC,
not NIL.
diff --git a/src/mload.lisp b/src/mload.lisp
index 2bcc6a5a4..0ba8f6138 100644
--- a/src/mload.lisp
+++ b/src/mload.lisp
@@ -640,7 +640,7 @@
(if foo (not (apparently-a-directory-p foo)))))
(defun apparently-a-directory-p (path)
- (eq (pathname-name path) nil))
+ (member (pathname-name path) '(nil :unspecific) :test #'eq))
;; We keep these here in case we want to optimize the search. To
;; speed things up, we might want to support search lists like
-----------------------------------------------------------------------
Summary of changes:
src/mload.lisp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
hooks/post-receive
--
Maxima CAS
|
|
From: rtoy <rt...@us...> - 2026-04-23 02:33:51
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, rtoy-break-dependency-cycles has been updated
via 4ab582f71781666618165c25b0ab821328f94371 (commit)
via 860e9733581bb6fc86ae227372d50aa50806560d (commit)
from 00ddbe5b5dbf5db2de48caadc8bf590c3771392b (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 4ab582f71781666618165c25b0ab821328f94371
Author: Raymond Toy <toy...@gm...>
Date: Wed Apr 22 19:32:19 2026 -0700
Update dependencies for variable-predicates
The module hypergeometric (hyp.lisp) needs functions from
variable-predicates so add the dependency.
diff --git a/src/maxima.system b/src/maxima.system
index 1914d4c14..d109b0230 100644
--- a/src/maxima.system
+++ b/src/maxima.system
@@ -758,7 +758,8 @@
;; Simplification and evaluation of hypergeometric functions.
:depends-on ("compatibility-macros1" "declarations" "defmfun" "errset" "globals"
"miscellaneous" "other-macros" "prerequisites" "utility-macros"
- "m2-pattern-matcher")
+ "m2-pattern-matcher"
+ "variable-predicates")
:components
((:file "hyp")
(:file "hypergeometric")
commit 860e9733581bb6fc86ae227372d50aa50806560d
Author: Raymond Toy <toy...@gm...>
Date: Wed Apr 22 19:25:29 2026 -0700
Break circular dependency between irinte and sin
First, all the variable predicate stuff like `freevar` and `varp` to
the new file var-predicates that is in the new module
variable-predicates. This removes a lot of the dependency between
irinte and sin. (These predicates are also used in other files.)
Second, irinte was using a few functions from sin like `integerp2`,
`integerp1`, `zerp`, and `nonzerp`. Moved to a new file sin-util.
Now sin depends on irinte but not vice versa. And sin and irinte both
depend on sin-util.
Third, laplac and hypgeo are definite integration routines so they can
be movedto the definite-integetion module.
Dependencies updated.
diff --git a/src/irinte.lisp b/src/irinte.lisp
index 06d454516..14d48d6ea 100644
--- a/src/irinte.lisp
+++ b/src/irinte.lisp
@@ -14,12 +14,8 @@
(load-macsyma-macros rzmac)
-(defun zerp (a) (equal a 0))
-
(defun integerpfr (a) (if (not (maxima-integerp a)) (integerp1 a)))
-(defun nonzerp (a) (not (equal a 0)))
-
(defun hasvar2 (exp var2)
(not (freevar2 exp var2)))
diff --git a/src/maxima.system b/src/maxima.system
index ed37d7663..1914d4c14 100644
--- a/src/maxima.system
+++ b/src/maxima.system
@@ -749,6 +749,11 @@
(:file "compar")
(:file "askp")) ;does this belong here?
)
+ (:module variable-predicates :source-pathname ""
+ ;; Variable predicates like FREEVAR, VARP.
+ :depends-on ("simp-utilities")
+ :components
+ ((:file "var-predicate")))
(:module hypergeometric :source-pathname ""
;; Simplification and evaluation of hypergeometric functions.
:depends-on ("compatibility-macros1" "declarations" "defmfun" "errset" "globals"
@@ -766,15 +771,16 @@
"compatibility-macros" "declarations"
"destructuring-let" "errset" "fundamental-macros"
"prerequisites" "rat-macros" "utility-macros"
- "hypergeometric"
- "m2-pattern-matcher")
+ "m2-pattern-matcher"
+ "variable-predicates")
:components
- ((:file "sinint")
- (:file "sin")
+ ((:file "sin-util")
+ (:file "sinint")
(:file "risch")
- (:file "irinte")
- (:file "laplac")
- (:file "hypgeo")))
+ (:file "irinte"
+ :depends-on ("sin-util"))
+ (:file "sin"
+ :depends-on ("sin-util" "irinte"))))
(:module taylor-series :source-pathname ""
:depends-on ("globals" "defmfun" "compatibility-macros"
"compatibility-macros1" "declarations"
@@ -786,10 +792,14 @@
:depends-on ("globals" "defmfun" "declarations" "destructuring-let"
"fundamental-macros" "other-macros"
"prerequisites"
- "m2-pattern-matcher")
+ "hypergeometric"
+ "m2-pattern-matcher"
+ "variable-predicates")
:components
((:file "defint")
- (:file "residu")))
+ (:file "residu")
+ (:file "laplac")
+ (:file "hypgeo")))
(:module trigonometry :source-pathname ""
:depends-on ("globals" "defmfun"
"compatibility-macros" "declarations"
diff --git a/src/sin-util.lisp b/src/sin-util.lisp
new file mode 100644
index 000000000..330141a7d
--- /dev/null
+++ b/src/sin-util.lisp
@@ -0,0 +1,23 @@
+;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
+
+(in-package :maxima)
+
+;;; Predicate functions
+
+(defun integerp2 (x)
+ "Returns x if x is an integer, else false"
+ (let (u)
+ (cond ((not (numberp x)) nil)
+ ((not (floatp x)) x)
+ ((prog2 (setq u (maxima-rationalize x))
+ (equal (cdr u) 1))
+ (car u)))))
+
+(defun integerp1 (x)
+ "Returns 2*x if 2*x is an integer, else nil"
+ (integerp2 (mul2* 2 x)))
+
+(defun zerp (a) (equal a 0))
+
+(defun nonzerp (a) (not (equal a 0)))
+
diff --git a/src/sin.lisp b/src/sin.lisp
index f1e3c1b20..5f3e262e1 100644
--- a/src/sin.lisp
+++ b/src/sin.lisp
@@ -31,53 +31,6 @@
;;; Predicate functions
-;; Note: varp and freevarp are not used in this file anymore. But
-;; they are used in other files. Someday, varp and freevarp should be
-;; moved elsewhere.
-(declaim (inline varp))
-(defun varp (x)
- (declare (special var))
- (alike1 x var))
-
-(defun freevar (a)
- (declare (special var))
- (cond ((atom a) (not (eq a var)))
- ((varp a) nil)
- ((and (not (atom (car a)))
- (member 'array (cdar a) :test #'eq))
- (cond ((freevar (cdr a)) t)
- (t (merror "~&FREEVAR: variable of integration appeared in subscript."))))
- (t (and (freevar (car a)) (freevar (cdr a))))))
-
-;; Same as varp, but the second arg specifies the variable to be
-;; tested instead of using the special variable VAR.
-(defun varp2 (x var2)
- (alike1 x var2))
-
-;; Like freevar but the second arg specifies the variable to be tested
-;; instead of using the special variable VAR.
-(defun freevar2 (a var2)
- (cond ((atom a) (not (eq a var2)))
- ((varp2 a var2) nil)
- ((and (not (atom (car a)))
- (member 'array (cdar a) :test #'eq))
- (cond ((freevar2 (cdr a) var2) t)
- (t (merror "~&FREEVAR: variable of integration appeared in subscript."))))
- (t (and (freevar2 (car a) var2) (freevar2 (cdr a) var2)))))
-
-(defun integerp1 (x)
- "Returns 2*x if 2*x is an integer, else nil"
- (integerp2 (mul2* 2 x)))
-
-(defun integerp2 (x)
- "Returns x if x is an integer, else false"
- (let (u)
- (cond ((not (numberp x)) nil)
- ((not (floatp x)) x)
- ((prog2 (setq u (maxima-rationalize x))
- (equal (cdr u) 1))
- (car u)))))
-
;; This predicate is used with m2 pattern matcher.
;; A rational expression in var2.
(defun rat8 (ex var2)
diff --git a/src/var-predicate.lisp b/src/var-predicate.lisp
new file mode 100644
index 000000000..20666184a
--- /dev/null
+++ b/src/var-predicate.lisp
@@ -0,0 +1,42 @@
+;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
+
+(in-package :maxima)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Predicate functions
+
+;; Note: varp and freevarp are not used in this file anymore. But
+;; they are used in other files. Someday, varp and freevarp should be
+;; moved elsewhere.
+(declaim (inline varp))
+(defun varp (x)
+ (declare (special var))
+ (alike1 x var))
+
+(defun freevar (a)
+ (declare (special var))
+ (cond ((atom a) (not (eq a var)))
+ ((varp a) nil)
+ ((and (not (atom (car a)))
+ (member 'array (cdar a) :test #'eq))
+ (cond ((freevar (cdr a)) t)
+ (t (merror "~&FREEVAR: variable of integration appeared in subscript."))))
+ (t (and (freevar (car a)) (freevar (cdr a))))))
+
+;; Same as varp, but the second arg specifies the variable to be
+;; tested instead of using the special variable VAR.
+(defun varp2 (x var2)
+ (alike1 x var2))
+
+;; Like freevar but the second arg specifies the variable to be tested
+;; instead of using the special variable VAR.
+(defun freevar2 (a var2)
+ (cond ((atom a) (not (eq a var2)))
+ ((varp2 a var2) nil)
+ ((and (not (atom (car a)))
+ (member 'array (cdar a) :test #'eq))
+ (cond ((freevar2 (cdr a) var2) t)
+ (t (merror "~&FREEVAR: variable of integration appeared in subscript."))))
+ (t (and (freevar2 (car a) var2) (freevar2 (cdr a) var2)))))
+
-----------------------------------------------------------------------
Summary of changes:
src/irinte.lisp | 4 ----
src/maxima.system | 31 +++++++++++++++++++++----------
src/sin-util.lisp | 23 +++++++++++++++++++++++
src/sin.lisp | 47 -----------------------------------------------
src/var-predicate.lisp | 42 ++++++++++++++++++++++++++++++++++++++++++
5 files changed, 86 insertions(+), 61 deletions(-)
create mode 100644 src/sin-util.lisp
create mode 100644 src/var-predicate.lisp
hooks/post-receive
--
Maxima CAS
|
|
From: rtoy <rt...@us...> - 2026-04-22 19:45:37
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, rtoy-break-dependency-cycles has been updated
via 00ddbe5b5dbf5db2de48caadc8bf590c3771392b (commit)
from a2060858c4b91934c04275436f8aa6b0d0eb5021 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 00ddbe5b5dbf5db2de48caadc8bf590c3771392b
Author: Raymond Toy <toy...@gm...>
Date: Wed Apr 22 12:42:21 2026 -0700
Move cdras from irinte to new file schatc-util
cdras caused a circular dependency between irinte and defint and other
integration routines. Moving it to schatc-util breaks at least that
dependency. Plus cdras is intimately related to schatc.
diff --git a/src/irinte.lisp b/src/irinte.lisp
index 27eba22a6..06d454516 100644
--- a/src/irinte.lisp
+++ b/src/irinte.lisp
@@ -219,9 +219,6 @@
(declare (ignore xx ee fff gg dd pp r0 e0))
nil)
-(defun cdras (a b)
- (cdr (assoc a b :test #'equal)))
-
(defun intir (funct x)
(inti funct x (jmaug (specrepcheck funct) x)))
diff --git a/src/maxima.system b/src/maxima.system
index f95a29876..ed37d7663 100644
--- a/src/maxima.system
+++ b/src/maxima.system
@@ -263,7 +263,8 @@
(:module m2-pattern-matcher :source-pathname ""
:depends-on ("simp-utilities")
:components
- ((:file "schatc")))
+ ((:file "schatc")
+ (:file "schatc-util")))
;; This contains the reader macro #$...$ so we want io compile this
;; as early as possible before anything uses it.
(:module reader :source-pathname ""
diff --git a/src/schatc-util.lisp b/src/schatc-util.lisp
new file mode 100644
index 000000000..e9e194d95
--- /dev/null
+++ b/src/schatc-util.lisp
@@ -0,0 +1,10 @@
+;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
+
+(in-package :maxima)
+
+;; Utility functions for working with M2 pattern matching results
+
+(defun cdras (a b)
+ "Extract the value associated with key A from association list B.
+ This is commonly used to extract matched variables from M2 pattern matching results."
+ (cdr (assoc a b :test #'equal)))
-----------------------------------------------------------------------
Summary of changes:
src/irinte.lisp | 3 ---
src/maxima.system | 3 ++-
src/schatc-util.lisp | 10 ++++++++++
3 files changed, 12 insertions(+), 4 deletions(-)
create mode 100644 src/schatc-util.lisp
hooks/post-receive
--
Maxima CAS
|
|
From: rtoy <rt...@us...> - 2026-04-22 19:34:16
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, rtoy-break-dependency-cycles has been updated
via a2060858c4b91934c04275436f8aa6b0d0eb5021 (commit)
via 424e55b3d4ba49c2337a85e6d76bb955005b837c (commit)
from 777848aa6455934fca7f46c88aa7f3d8c584abb0 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit a2060858c4b91934c04275436f8aa6b0d0eb5021
Author: Raymond Toy <toy...@gm...>
Date: Wed Apr 22 12:32:28 2026 -0700
Remove pattern-matching dependency
The integration, trigonometry, and miscellaneous modules don't depend
on the pattern-matching module. They only need m2-pattern-matcher.
diff --git a/src/maxima.system b/src/maxima.system
index 6f7bbe279..f95a29876 100644
--- a/src/maxima.system
+++ b/src/maxima.system
@@ -761,7 +761,7 @@
;; be loaded first.
:depends-on ("hypergeometric"))))
(:module integration :source-pathname ""
- :depends-on ("globals" "defmfun" "pattern-matching"
+ :depends-on ("globals" "defmfun"
"compatibility-macros" "declarations"
"destructuring-let" "errset" "fundamental-macros"
"prerequisites" "rat-macros" "utility-macros"
@@ -790,7 +790,7 @@
((:file "defint")
(:file "residu")))
(:module trigonometry :source-pathname ""
- :depends-on ("globals" "pattern-matching" "defmfun"
+ :depends-on ("globals" "defmfun"
"compatibility-macros" "declarations"
"errset" "fundamental-macros" "other-macros"
"prerequisites" "utility-macros"
@@ -868,7 +868,7 @@
((:file "expintegral")
(:file "gamma")))
(:module miscellaneous :source-pathname ""
- :depends-on ("globals" "defmfun" "pattern-matching" "compatibility-macros1"
+ :depends-on ("globals" "defmfun" "compatibility-macros1"
"reader" "utility-macros" "commands"
"destructuring-let" "errset" "other-macros"
"rat-macros" "declarations" "fundamental-macros"
commit 424e55b3d4ba49c2337a85e6d76bb955005b837c
Author: Raymond Toy <toy...@gm...>
Date: Wed Apr 22 12:28:17 2026 -0700
Move schatc to new module m2-pattern-matcher
This doesn't break any cycles but should make changes easier to
manage. Update other modules that now depend on schatc.
diff --git a/src/maxima.system b/src/maxima.system
index 02d5acd4f..6f7bbe279 100644
--- a/src/maxima.system
+++ b/src/maxima.system
@@ -260,6 +260,10 @@
:depends-on ("simp-utils"))
(:file "simp"
:depends-on ("simp-utils" "opers" "mopers" "mutils"))))
+ (:module m2-pattern-matcher :source-pathname ""
+ :depends-on ("simp-utilities")
+ :components
+ ((:file "schatc")))
;; This contains the reader macro #$...$ so we want io compile this
;; as early as possible before anything uses it.
(:module reader :source-pathname ""
@@ -747,7 +751,8 @@
(:module hypergeometric :source-pathname ""
;; Simplification and evaluation of hypergeometric functions.
:depends-on ("compatibility-macros1" "declarations" "defmfun" "errset" "globals"
- "miscellaneous" "other-macros" "prerequisites" "utility-macros")
+ "miscellaneous" "other-macros" "prerequisites" "utility-macros"
+ "m2-pattern-matcher")
:components
((:file "hyp")
(:file "hypergeometric")
@@ -760,7 +765,8 @@
"compatibility-macros" "declarations"
"destructuring-let" "errset" "fundamental-macros"
"prerequisites" "rat-macros" "utility-macros"
- "hypergeometric")
+ "hypergeometric"
+ "m2-pattern-matcher")
:components
((:file "sinint")
(:file "sin")
@@ -778,7 +784,8 @@
(:module definite-integration :source-pathname ""
:depends-on ("globals" "defmfun" "declarations" "destructuring-let"
"fundamental-macros" "other-macros"
- "prerequisites")
+ "prerequisites"
+ "m2-pattern-matcher")
:components
((:file "defint")
(:file "residu")))
@@ -787,7 +794,8 @@
"compatibility-macros" "declarations"
"errset" "fundamental-macros" "other-macros"
"prerequisites" "utility-macros"
- "taylor-series")
+ "taylor-series"
+ "m2-pattern-matcher")
:components
((:file "trigi")
(:file "trigo")
@@ -824,8 +832,7 @@
"rat-macros"
"simp-utilities")
:components
- ((:file "schatc")
- (:file "matcom")
+ ((:file "matcom")
(:file "matrun")
(:file "nisimp")))
(:module limits :source-pathname ""
@@ -856,7 +863,7 @@
((:file "mtrace")
(:file "mdebug")))
(:module gamma-expint :source-pathname ""
- :depends-on ("numerical-utilities")
+ :depends-on ("numerical-utilities" "m2-pattern-matcher")
:components
((:file "expintegral")
(:file "gamma")))
@@ -865,7 +872,8 @@
"reader" "utility-macros" "commands"
"destructuring-let" "errset" "other-macros"
"rat-macros" "declarations" "fundamental-macros"
- "numerical-utilities")
+ "numerical-utilities"
+ "m2-pattern-matcher")
:components
((:file "scs")
(:file "asum")
-----------------------------------------------------------------------
Summary of changes:
src/maxima.system | 30 +++++++++++++++++++-----------
1 file changed, 19 insertions(+), 11 deletions(-)
hooks/post-receive
--
Maxima CAS
|
|
From: rtoy <rt...@us...> - 2026-04-22 18:47:05
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, master has been updated
via dee5760083240743043639aece795d3fcaaa94c3 (commit)
via 0a57cfb13b91ba1bef7fe3c1e26d402a0fc63807 (commit)
via f36e38d8992cac971f50a80074fae4072def7f2d (commit)
from b123029a18cb75e53d48d7be968f99a78ba688bb (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit dee5760083240743043639aece795d3fcaaa94c3
Merge: b123029a1 0a57cfb13
Author: Raymond Toy <toy...@gm...>
Date: Wed Apr 22 11:46:44 2026 -0700
Merge branch 'bug-4720-part1-move-atan2-to-trigi'
-----------------------------------------------------------------------
Summary of changes:
src/comm2.lisp | 212 ------------------------------------------------------
src/limit.lisp | 3 -
src/maxima.system | 3 +-
src/mutils.lisp | 9 +++
src/trigi.lisp | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 219 insertions(+), 216 deletions(-)
hooks/post-receive
--
Maxima CAS
|
|
From: rtoy <rt...@us...> - 2026-04-22 18:13:43
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, rtoy-break-dependency-cycles has been updated
via 777848aa6455934fca7f46c88aa7f3d8c584abb0 (commit)
via 2313b77146f9e596450957bf5442c918465d204b (commit)
via 292dd91d1c6da8e1755b306f892f84147a3cad86 (commit)
from 1afa87ef875f87e688702cb365b0ba1b204853b0 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 777848aa6455934fca7f46c88aa7f3d8c584abb0
Author: Raymond Toy <toy...@gm...>
Date: Wed Apr 22 11:11:08 2026 -0700
Update dependencies for hayat and trigi
hayat.lisp needs multiplep, so taylor-series module depends on
simp-utilities module.
And since the circular dependency between hayat and trigi has been
broken, the trigonometry module can depend on taylor-series because
trigi uses $taylorinfo.
diff --git a/src/maxima.system b/src/maxima.system
index 45f7ea1d9..02d5acd4f 100644
--- a/src/maxima.system
+++ b/src/maxima.system
@@ -772,7 +772,8 @@
:depends-on ("globals" "defmfun" "compatibility-macros"
"compatibility-macros1" "declarations"
"destructuring-let" "fundamental-macros"
- "other-macros" "prerequisites" "rat-macros" "errset")
+ "other-macros" "prerequisites" "rat-macros" "errset"
+ "simp-utilities")
:components ((:file "hayat")))
(:module definite-integration :source-pathname ""
:depends-on ("globals" "defmfun" "declarations" "destructuring-let"
@@ -785,7 +786,8 @@
:depends-on ("globals" "pattern-matching" "defmfun"
"compatibility-macros" "declarations"
"errset" "fundamental-macros" "other-macros"
- "prerequisites" "utility-macros")
+ "prerequisites" "utility-macros"
+ "taylor-series")
:components
((:file "trigi")
(:file "trigo")
commit 2313b77146f9e596450957bf5442c918465d204b
Author: Raymond Toy <toy...@gm...>
Date: Wed Apr 22 11:00:51 2026 -0700
Move multiplep from trigi to simp-util
This breaks the circular dependency between trigi (which defined it)
and hayat which used it. But trigi calls $taylorinfo from hayat.
Hence, the circular dependency.
By moving multiplep out of trigi, hayat no longer depends on trigi.
diff --git a/src/simp-utils.lisp b/src/simp-utils.lisp
index b61e3dacb..a40ed0d5e 100644
--- a/src/simp-utils.lisp
+++ b/src/simp-utils.lisp
@@ -125,3 +125,9 @@
(return nil)))))
+;; Check if EXP is a multiple of VAR.
+(defun multiplep (exp var)
+ (and (not (zerop1 exp))
+ (zerop1 (sub exp
+ (mul var (coeff exp var 1))))))
+
diff --git a/src/trigi.lisp b/src/trigi.lisp
index b4d81f7c0..ea65bf54e 100644
--- a/src/trigi.lisp
+++ b/src/trigi.lisp
@@ -903,9 +903,6 @@
(div (mod x mod) d)))
(t nil)))
-(defun multiplep (exp var)
- (and (not (zerop1 exp)) (zerop1 (sub exp (mul var (coeff exp var 1))))))
-
(defun linearp (exp var)
(and (setq exp (islinear exp var)) (not (equal (car exp) 0))))
commit 292dd91d1c6da8e1755b306f892f84147a3cad86
Author: Raymond Toy <toy...@gm...>
Date: Wed Apr 22 10:49:10 2026 -0700
simp-utilities depends on defmfun
There are a few defmfun's in this module.
diff --git a/src/maxima.system b/src/maxima.system
index 5c9ea7a57..45f7ea1d9 100644
--- a/src/maxima.system
+++ b/src/maxima.system
@@ -250,7 +250,7 @@
;; function calls. Can't really do anything about that.
;; and can't depend on those modules because that causes a
;; circular dependency.
- :depends-on ("prerequisites")
+ :depends-on ("prerequisites" "defmfun")
:components
((:file "simp-utils")
(:file "mopers")
-----------------------------------------------------------------------
Summary of changes:
src/maxima.system | 8 +++++---
src/simp-utils.lisp | 6 ++++++
src/trigi.lisp | 3 ---
3 files changed, 11 insertions(+), 6 deletions(-)
hooks/post-receive
--
Maxima CAS
|
|
From: rtoy <rt...@us...> - 2026-04-22 17:43:39
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, rtoy-break-dependency-cycles has been updated
via 1afa87ef875f87e688702cb365b0ba1b204853b0 (commit)
from 5cb2f3ca9dbfd0621e38e3de9ed452a750abc9ee (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 1afa87ef875f87e688702cb365b0ba1b204853b0
Author: Raymond Toy <toy...@gm...>
Date: Wed Apr 22 10:36:59 2026 -0700
More fixes for circular dependencies
Moved more items to simp-utils:
* ratdisrep from simp.lisp
* like from compar.lisp
* alike from simp.lisp
I believe this breaks any circular dependency between the files in
simp-utilities.
There are still dependencies to other functions like $ratdisrep and
$outofpois in other modules. Can't really do anything about that
right now. Those functions naturally should stay where they are.
Maxima builds and testsuite passes.
diff --git a/src/compar.lisp b/src/compar.lisp
index 31adb47a9..a63cbf2ba 100644
--- a/src/compar.lisp
+++ b/src/compar.lisp
@@ -975,9 +975,6 @@ TDNEG TDZERO TDPN) to store it, and also sets SIGN."
((eq '$nz sgn) (daddgq nil (neg x))))))
(setf *local-signs* nil)))
-(defun like (x y)
- (alike1 (specrepcheck x) (specrepcheck y)))
-
(setf (get '$und 'sysconst) t)
(setf (get '$ind 'sysconst) t)
(setf (get '$zeroa 'sysconst) t)
diff --git a/src/maxima.system b/src/maxima.system
index 9efde8b83..5c9ea7a57 100644
--- a/src/maxima.system
+++ b/src/maxima.system
@@ -245,6 +245,11 @@
(:file "mopers")
(:file "mforma")))
(:module simp-utilities :source-pathname ""
+ ;; There are other dependencies. We call $ratdisrep,
+ ;; $outofpois, $ratsimp and others. These are all
+ ;; function calls. Can't really do anything about that.
+ ;; and can't depend on those modules because that causes a
+ ;; circular dependency.
:depends-on ("prerequisites")
:components
((:file "simp-utils")
@@ -252,7 +257,7 @@
(:file "opers"
:depends-on ("mopers"))
(:file "mutils"
- :depends-on "simp-utils")
+ :depends-on ("simp-utils"))
(:file "simp"
:depends-on ("simp-utils" "opers" "mopers" "mutils"))))
;; This contains the reader macro #$...$ so we want io compile this
diff --git a/src/simp-utils.lisp b/src/simp-utils.lisp
index 5b446311a..b61e3dacb 100644
--- a/src/simp-utils.lisp
+++ b/src/simp-utils.lisp
@@ -21,9 +21,32 @@
((numberp x) (zerop x))
(($bfloatp x) (= 0 (cadr x)))))
+(defun ratdisrep (e)
+ (simplifya (locally
+ (declare (notinline $ratdisrep))
+ ($ratdisrep e))
+ nil))
+
+(defun specdisrep (e)
+ (cond ((eq (caar e) 'mrat)
+ (ratdisrep e))
+ (t
+ (locally
+ (declare (notinline $outofpois))
+ ($outofpois e)))))
+
+(defun specrepcheck (e)
+ (if (specrepp e)
+ (specdisrep e)
+ e))
+
+
;; Compares two Macsyma expressions ignoring SIMP flags and all other
;; items in the header except for the ARRAY flag.
+(defun like (x y)
+ (alike1 (specrepcheck x) (specrepcheck y)))
+
;; Trivial function used only in ALIKE1.
;; Should be defined as an open-codable subr.
@@ -94,9 +117,11 @@
(t nil)
))
-(defun specrepcheck (e) (if (specrepp e) (specdisrep e) e))
+;; Maps ALIKE1 down two lists.
+
+(defun alike (x y)
+ (do ((x x (cdr x)) (y y (cdr y))) ((atom x) (equal x y))
+ (cond ((or (atom y) (not (alike1 (car x) (car y))))
+ (return nil)))))
-(defun specdisrep (e)
- (cond ((eq (caar e) 'mrat) (ratdisrep e))
- (t ($outofpois e))))
diff --git a/src/simp.lisp b/src/simp.lisp
index 42daa02e6..2a8415eb4 100644
--- a/src/simp.lisp
+++ b/src/simp.lisp
@@ -102,8 +102,6 @@
(defprop $equal t binary)
(defprop $notequal t binary)
-(defun ratdisrep (e) (simplifya ($ratdisrep e) nil))
-
(defun sratsimp (e) (simplifya ($ratsimp e) nil))
(defun simpcheck (e flag)
@@ -2817,13 +2815,6 @@
(alike1 (mfuncall '$arrayinfo x) (mfuncall '$arrayinfo y))
(alike1 ($listarray x) ($listarray y))))
-;; Maps ALIKE1 down two lists.
-
-(defun alike (x y)
- (do ((x x (cdr x)) (y y (cdr y))) ((atom x) (equal x y))
- (cond ((or (atom y) (not (alike1 (car x) (car y))))
- (return nil)))))
-
(defun ordfna (e a) ; A is an atom
(cond ((numberp a)
(or (not (eq (caar e) 'rat))
-----------------------------------------------------------------------
Summary of changes:
src/compar.lisp | 3 ---
src/maxima.system | 7 ++++++-
src/simp-utils.lisp | 33 +++++++++++++++++++++++++++++----
src/simp.lisp | 9 ---------
4 files changed, 35 insertions(+), 17 deletions(-)
hooks/post-receive
--
Maxima CAS
|
|
From: rtoy <rt...@us...> - 2026-04-22 17:02:15
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, rtoy-break-dependency-cycles has been updated
via 5cb2f3ca9dbfd0621e38e3de9ed452a750abc9ee (commit)
from a4b6ce46dd8df13abdafd0b467535a18ef5c6704 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 5cb2f3ca9dbfd0621e38e3de9ed452a750abc9ee
Author: Raymond Toy <toy...@gm...>
Date: Wed Apr 22 09:57:43 2026 -0700
Break circular dependency between simp and mutils
The functions that were causing a circular dependency between simp and
mutils have been moved to simp-utils.lisp. This includes zerop1,
memqarr, alike1 and support functions, specrepcheck, and specdisrep.
Also moved $bfloatp from mutils-fn to simp-utils because zerop1 uses
$bfloatp.
Update dependencies in maxima.system and remove comment about circular
dependency. (I think all the circular dependencies are gone.)
diff --git a/src/maxima.system b/src/maxima.system
index 07d3382cc..9efde8b83 100644
--- a/src/maxima.system
+++ b/src/maxima.system
@@ -251,14 +251,10 @@
(:file "mopers")
(:file "opers"
:depends-on ("mopers"))
- ;; NOTE: There is a circular dependency between mutils
- ;; and simp. mutils calls ALIKE1 from simp, and simp
- ;; calls AMONG, ZEROP1 from mutils. These should be
- ;; fixed, but since this is all in this module, it
- ;; doesn't matter too much right now.
- (:file "mutils")
+ (:file "mutils"
+ :depends-on "simp-utils")
(:file "simp"
- :depends-on ("opers" "mopers" "mutils"))))
+ :depends-on ("simp-utils" "opers" "mopers" "mutils"))))
;; This contains the reader macro #$...$ so we want io compile this
;; as early as possible before anything uses it.
(:module reader :source-pathname ""
diff --git a/src/mutils-fn.lisp b/src/mutils-fn.lisp
index 4cd375efe..acc8badbc 100644
--- a/src/mutils-fn.lisp
+++ b/src/mutils-fn.lisp
@@ -66,12 +66,6 @@
(integerp (cadr x))
(integerp (cddr x)))))
-(defmfun ($bfloatp :inline-impl t) (x)
- "Returns true if X is a bigfloat"
- (and (consp x)
- (consp (car x))
- (eq (caar x) 'bigfloat)))
-
(defmfun $floatnump (x)
(or (floatp x)
(and ($ratp x) (floatp (cadr x)) (onep1 (cddr x)))))
diff --git a/src/mutils.lisp b/src/mutils.lisp
index c0e1badff..2a11c50ba 100644
--- a/src/mutils.lisp
+++ b/src/mutils.lisp
@@ -190,13 +190,6 @@
(and (not (atom x)) (not (atom (car x)))
(member (caar x) '(rat bigfloat)) t)))
-(declaim (inline zerop1))
-(defun zerop1 (x)
- "Returns non-NIL if X is Lisp number or bfloat that is equal to 0"
- (cond
- ((numberp x) (zerop x))
- (($bfloatp x) (= 0 (cadr x)))))
-
(defun bigfloat-one-p (x)
"Returns T if X, assumed to be a bigfloat, represents the value 1."
;; Binary bigfloat ones are of the form '((BIGFLOAT [SIMP] <P>) 2^(<P>-1) 1).
diff --git a/src/simp-utils.lisp b/src/simp-utils.lisp
index b4d6dcdc8..5b446311a 100644
--- a/src/simp-utils.lisp
+++ b/src/simp-utils.lisp
@@ -3,6 +3,100 @@
(in-package :maxima)
+;; These are common utililites needed by both simp.lisp and mutils.lisp.
+
(defun delsimp (e)
(remove 'simp e))
+(defmfun ($bfloatp :inline-impl t) (x)
+ "Returns true if X is a bigfloat"
+ (and (consp x)
+ (consp (car x))
+ (eq (caar x) 'bigfloat)))
+
+(declaim (inline zerop1))
+(defun zerop1 (x)
+ "Returns non-NIL if X is Lisp number or bfloat that is equal to 0"
+ (cond
+ ((numberp x) (zerop x))
+ (($bfloatp x) (= 0 (cadr x)))))
+
+;; Compares two Macsyma expressions ignoring SIMP flags and all other
+;; items in the header except for the ARRAY flag.
+
+;; Trivial function used only in ALIKE1.
+;; Should be defined as an open-codable subr.
+
+(defmacro memqarr (l)
+ `(if (member-eq 'array ,l) t))
+
+(defun lisp-vector-alike1 (x y)
+ (let ((lx (length x)))
+ (when (eql lx (length y))
+ (lisp-array-elements-alike1 x y lx))))
+
+(defun lisp-array-alike1 (x y)
+ (when (equal (array-dimensions x) (array-dimensions y))
+ (lisp-array-elements-alike1 x y (array-total-size x))))
+
+(defun lisp-array-elements-alike1 (x y n)
+ (dotimes (i n t)
+ (unless (alike1 (row-major-aref x i) (row-major-aref y i))
+ (return-from lisp-array-elements-alike1 nil))))
+
+(defun alike1 (x y)
+ ;; Clauses are ordered based on frequency of the case
+ ;; cons, integer, and symbol are very common
+ ;; everything else is rare
+ (cond ((eq x y) t)
+ ((consp x)
+ (let (car-x car-y op)
+ (if (and (consp y)
+ (not (atom (setq car-x (car x))))
+ (not (atom (setq car-y (car y))))
+ (eq (setq op (car car-x)) (car car-y)))
+ (cond
+ ((eq op 'mrat) (like x y))
+ ((eq op 'mpois) (equal (cdr x) (cdr y)))
+ ((eq op 'bigfloat)
+ ;; Bigfloats need special treatment because their precision
+ ;; and an optional DECIMAL flag are stored in the CAR,
+ ;; which would otherwise be ignored.
+ ;; A bigfloat looks like this, [...] means optional:
+ ;; ((BIGFLOAT [SIMP] <PRECISION> [DECIMAL]) <MANTISSA> <EXPONENT>)
+ ;; Compare mantissas and exponents first.
+ (when (and (= (cadr x) (cadr y)) (= (caddr x) (caddr y)))
+ ;; Mantissas and exponents are the same.
+ ;; If the CARs are EQ (see BCONS), we're done. Otherwise, we
+ ;; still need to compare precision and maybe radix (binary/decimal).
+ ;; If there's a SIMP flag, it must be ignored.
+ (if (eq car-x car-y)
+ t
+ (let ((rest-x (if (eq 'simp (cadar x)) (cddar x) (cdar x)))
+ (rest-y (if (eq 'simp (cadar y)) (cddar y) (cdar y))))
+ (and (= (car rest-x) (car rest-y))
+ (eq (cadr rest-x) (cadr rest-y)))))))
+ ;; General case: First check for CARs being EQ (see EQTEST).
+ ;; If not, just check whether both have or don't have the ARRAY flag.
+ ((or (eq car-x car-y) (eq (memqarr (cdar x)) (memqarr (cdar y))))
+ (alike (cdr x) (cdr y)))
+ (t nil))
+ ;; (foo) and (foo) test non-alike because the car's aren't standard
+ nil)))
+ ((consp y) nil)
+ ((or (symbolp x) (symbolp y)) nil)
+ ((integerp x) (and (integerp y) (= x y)))
+ ;; uncommon cases from here down
+ ((floatp x) (and (floatp y) (= x y)))
+ ((stringp x) (and (stringp y) (string= x y)))
+ ((vectorp x) (and (vectorp y) (lisp-vector-alike1 x y)))
+ ((arrayp x) (and (arrayp y) (lisp-array-alike1 x y)))
+ (t nil)
+ ))
+
+(defun specrepcheck (e) (if (specrepp e) (specdisrep e) e))
+
+(defun specdisrep (e)
+ (cond ((eq (caar e) 'mrat) (ratdisrep e))
+ (t ($outofpois e))))
+
diff --git a/src/simp.lisp b/src/simp.lisp
index 08863ffdd..42daa02e6 100644
--- a/src/simp.lisp
+++ b/src/simp.lisp
@@ -116,18 +116,12 @@
(defun mratcheck (e) (if ($ratp e) (ratdisrep e) e))
-(defun specrepcheck (e) (if (specrepp e) (specdisrep e) e))
-
;; Note that the following two functions are carefully coupled.
(defun specrepp (e)
(and (not (atom e))
(member (caar e) '(mrat mpois)) t))
-(defun specdisrep (e)
- (cond ((eq (caar e) 'mrat) (ratdisrep e))
- (t ($outofpois e))))
-
(defun constant (x)
(cond ((symbolp x) (kindp x '$constant))
(($subvarp x)
@@ -2806,79 +2800,6 @@
((not (alike1 (car x1) (car y1)))
(return (great (car x1) (car y1)))))))))
-;; Trivial function used only in ALIKE1.
-;; Should be defined as an open-codable subr.
-
-(defmacro memqarr (l)
- `(if (member-eq 'array ,l) t))
-
-;; Compares two Macsyma expressions ignoring SIMP flags and all other
-;; items in the header except for the ARRAY flag.
-
-(defun alike1 (x y)
- ;; Clauses are ordered based on frequency of the case
- ;; cons, integer, and symbol are very common
- ;; everything else is rare
- (cond ((eq x y) t)
- ((consp x)
- (let (car-x car-y op)
- (if (and (consp y)
- (not (atom (setq car-x (car x))))
- (not (atom (setq car-y (car y))))
- (eq (setq op (car car-x)) (car car-y)))
- (cond
- ((eq op 'mrat) (like x y))
- ((eq op 'mpois) (equal (cdr x) (cdr y)))
- ((eq op 'bigfloat)
- ;; Bigfloats need special treatment because their precision
- ;; and an optional DECIMAL flag are stored in the CAR,
- ;; which would otherwise be ignored.
- ;; A bigfloat looks like this, [...] means optional:
- ;; ((BIGFLOAT [SIMP] <PRECISION> [DECIMAL]) <MANTISSA> <EXPONENT>)
- ;; Compare mantissas and exponents first.
- (when (and (= (cadr x) (cadr y)) (= (caddr x) (caddr y)))
- ;; Mantissas and exponents are the same.
- ;; If the CARs are EQ (see BCONS), we're done. Otherwise, we
- ;; still need to compare precision and maybe radix (binary/decimal).
- ;; If there's a SIMP flag, it must be ignored.
- (if (eq car-x car-y)
- t
- (let ((rest-x (if (eq 'simp (cadar x)) (cddar x) (cdar x)))
- (rest-y (if (eq 'simp (cadar y)) (cddar y) (cdar y))))
- (and (= (car rest-x) (car rest-y))
- (eq (cadr rest-x) (cadr rest-y)))))))
- ;; General case: First check for CARs being EQ (see EQTEST).
- ;; If not, just check whether both have or don't have the ARRAY flag.
- ((or (eq car-x car-y) (eq (memqarr (cdar x)) (memqarr (cdar y))))
- (alike (cdr x) (cdr y)))
- (t nil))
- ;; (foo) and (foo) test non-alike because the car's aren't standard
- nil)))
- ((consp y) nil)
- ((or (symbolp x) (symbolp y)) nil)
- ((integerp x) (and (integerp y) (= x y)))
- ;; uncommon cases from here down
- ((floatp x) (and (floatp y) (= x y)))
- ((stringp x) (and (stringp y) (string= x y)))
- ((vectorp x) (and (vectorp y) (lisp-vector-alike1 x y)))
- ((arrayp x) (and (arrayp y) (lisp-array-alike1 x y)))
- (t nil)
- ))
-
-(defun lisp-vector-alike1 (x y)
- (let ((lx (length x)))
- (when (eql lx (length y))
- (lisp-array-elements-alike1 x y lx))))
-
-(defun lisp-array-alike1 (x y)
- (when (equal (array-dimensions x) (array-dimensions y))
- (lisp-array-elements-alike1 x y (array-total-size x))))
-
-(defun lisp-array-elements-alike1 (x y n)
- (dotimes (i n t)
- (unless (alike1 (row-major-aref x i) (row-major-aref y i))
- (return-from lisp-array-elements-alike1 nil))))
-
;; Not sure if we want to enable comparison of maxima arrays.
;; Aside from that, add2lnc calls alike1 (via memalike) and that causes trouble.
;; Possible code for ALIKE1 to enable such comparisons should we choose to do so:
-----------------------------------------------------------------------
Summary of changes:
src/maxima.system | 10 ++----
src/mutils-fn.lisp | 6 ----
src/mutils.lisp | 7 ----
src/simp-utils.lisp | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/simp.lisp | 79 --------------------------------------------
5 files changed, 97 insertions(+), 99 deletions(-)
hooks/post-receive
--
Maxima CAS
|
|
From: rtoy <rt...@us...> - 2026-04-22 16:38:40
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, rtoy-break-dependency-cycles has been updated
via a4b6ce46dd8df13abdafd0b467535a18ef5c6704 (commit)
via 0f0ec31b52b863d211e119d66e8539c0117c97a2 (commit)
from f10fe1f89564e15a990bae3c39b447da51c0633e (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit a4b6ce46dd8df13abdafd0b467535a18ef5c6704
Author: Raymond Toy <toy...@gm...>
Date: Wed Apr 22 09:37:30 2026 -0700
Comment about circular dependency between mutils and simp
Maxima builds from scratch fine.
diff --git a/src/maxima.system b/src/maxima.system
index b7bdc4777..07d3382cc 100644
--- a/src/maxima.system
+++ b/src/maxima.system
@@ -251,6 +251,11 @@
(:file "mopers")
(:file "opers"
:depends-on ("mopers"))
+ ;; NOTE: There is a circular dependency between mutils
+ ;; and simp. mutils calls ALIKE1 from simp, and simp
+ ;; calls AMONG, ZEROP1 from mutils. These should be
+ ;; fixed, but since this is all in this module, it
+ ;; doesn't matter too much right now.
(:file "mutils")
(:file "simp"
:depends-on ("opers" "mopers" "mutils"))))
commit 0f0ec31b52b863d211e119d66e8539c0117c97a2
Author: Raymond Toy <toy...@gm...>
Date: Wed Apr 22 09:23:56 2026 -0700
Move more things into simp-utilities module
We move files into the simp-utilities module to get them defined early
because we need them. This means opers, mopers, and mutils.
However, simp and mutils have defmfun's in them. That makes things
even more circular, so move all the defmfuns from simp and mutils to
simp-fn and mutils-fn. These files are in the original modules that
previously had simp and mutils.
But that's not enough to get a working build.
* simp uses member-eq so move that from mutils to simp.
* Move while from utils to simp because member-eq needs the while
macro.
* simp also uses coeff so move that from comm.lisp.
* simp also uses among so put that in mutils which seems like the
natural place assol and assolike live ther. Since simp depends on
mutils this works out.
Update maxima.system for the new files and dependencies.
There are still circular dependencies between simp and mutils
including
* simp uses zerop1, among, while from mutils.lisp
* mutils uses alike1 from simp.
We're leaving this for now since these are all self-contained in the
module. These should be fixed someday.
diff --git a/src/comm.lisp b/src/comm.lisp
index d1955d7de..61d526a71 100644
--- a/src/comm.lisp
+++ b/src/comm.lisp
@@ -1294,6 +1294,7 @@
(coeff e x 0)
(coeff e (power x n) 1)))
+#+nil
(defun coeff (e var pow)
(simplify
(cond ((alike1 e var) (if (equal pow 1) 1 0))
diff --git a/src/maxima.system b/src/maxima.system
index 63189d2e6..b7bdc4777 100644
--- a/src/maxima.system
+++ b/src/maxima.system
@@ -241,14 +241,26 @@
:depends-on ("defmfun" "compatibility-macros" "compatibility-macros1"
"prerequisites" "errset")
:components
- ((:file "mopers")
+ (#+nil
+ (:file "mopers")
(:file "mforma")))
+ (:module simp-utilities :source-pathname ""
+ :depends-on ("prerequisites")
+ :components
+ ((:file "simp-utils")
+ (:file "mopers")
+ (:file "opers"
+ :depends-on ("mopers"))
+ (:file "mutils")
+ (:file "simp"
+ :depends-on ("opers" "mopers" "mutils"))))
;; This contains the reader macro #$...$ so we want io compile this
;; as early as possible before anything uses it.
(:module reader :source-pathname ""
:depends-on ("globals" "defmfun" "compatibility-macros" "compatibility-macros1"
"declarations" "fundamental-macros" "prerequisites"
- "utility-macros")
+ "utility-macros"
+ "simp-utilities")
:components
((:file "nparse")))
(:module other-macros :source-pathname ""
@@ -272,18 +284,18 @@
"compatibility-macros1" "declarations" "fundamental-macros"
"prerequisites")
:components
- ((:file "opers")
- (:file "utils")
+ (#+nil
+ (:file "opers")
+ (:file "utils")
(:file "sumcon")
(:file "sublis")
(:file "merror")
(:file "mformt")
- (:file "mutils")
+ #+nil
+ (:file "mutils")
+ (:file "mutils-fn")
(:file "outmis")
(:file "ar")))
- (:module simp-utilities :source-pathname ""
- :components
- ((:file "simp-utils")))
(:module commands :source-pathname ""
:depends-on ("globals" "defmfun" "compatibility-macros" "compatibility-macros1"
"declarations" "fundamental-macros" "prerequisites"
@@ -590,7 +602,9 @@
"numerical-utilities"
"simp-utilities")
:components
- ((:file "simp")
+ (#+nil
+ (:file "simp")
+ (:file "simp-fn")
(:file "float")
(:file "csimp")
(:file "csimp2")
diff --git a/src/mutils-fn.lisp b/src/mutils-fn.lisp
new file mode 100644
index 000000000..4cd375efe
--- /dev/null
+++ b/src/mutils-fn.lisp
@@ -0,0 +1,107 @@
+;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(in-package :maxima)
+
+;;; This function searches for the key in the left hand side of the input list
+;;; of the form [x,y,z...] where each of the list elements is a expression of
+;;; a binary operand and 2 elements. For example x=1, 2^3, [a,b] etc.
+;;; The key checked against the first operand and and returns the second
+;;; operand if the key is found.
+;;; If the key is not found it either returns the default value if supplied or
+;;; false.
+;;; Author Dan Stanger 12/1/02
+
+(defmfun $assoc (key ielist &optional default)
+ (let ((elist (if (listp ielist)
+ (margs ielist)
+ (merror
+ (intl:gettext "assoc: second argument must be a nonatomic expression; found: ~:M")
+ ielist)))
+ found)
+ (dolist (i elist)
+ (unless (and (listp i) (= 3 (length i)))
+ (merror (intl:gettext "assoc: elements of the second argument must be an expression of two parts; found: ~:M") i))
+ (when (alike1 key (second i))
+ (setq found i)
+ (return)))
+ (if found (third found) default)))
+
+;;; Return a Maxima gensym.
+;;;
+;;; N.B. Maxima gensyms are interned, so they are not Lisp gensyms.
+;;; This function can return the same symbol multiple times, it can
+;;; return a symbol that was created and used elsewhere, etc. I (kjak)
+;;; do not think any of this is correct for a function named gensym.
+;;;
+;;; Maxima produces some expressions that contain Maxima gensyms, so
+;;; the use of uninterned symbols instead can cause confusion since
+;;; these print like any other symbol when lispdisp=false (the default).
+(defmfun $gensym (&optional x)
+ (typecase x
+ (null
+ (intern (symbol-name (gensym "$G")) :maxima))
+ (string
+ (intern
+ (symbol-name (gensym (format nil "$~a" (maybe-invert-string-case x))))
+ :maxima))
+ ((integer 0)
+ (let ((*gensym-counter* x))
+ (intern (symbol-name (gensym "$G")) :maxima)))
+ (t
+ (merror
+ (intl:gettext
+ "gensym: Argument must be a nonnegative integer or a string. Found: ~M") x))))
+
+(defmfun ($ratp :inline-impl t) (x)
+ (and (not (atom x))
+ (consp (car x))
+ (eq (caar x) 'mrat)))
+
+(defmfun $ratnump (x)
+ (or (integerp x)
+ (ratnump x)
+ (and ($ratp x)
+ (not (member-eq 'trunc (car x)))
+ (integerp (cadr x))
+ (integerp (cddr x)))))
+
+(defmfun ($bfloatp :inline-impl t) (x)
+ "Returns true if X is a bigfloat"
+ (and (consp x)
+ (consp (car x))
+ (eq (caar x) 'bigfloat)))
+
+(defmfun $floatnump (x)
+ (or (floatp x)
+ (and ($ratp x) (floatp (cadr x)) (onep1 (cddr x)))))
+
+(defmfun $numberp (x)
+ "Returns true if X is a Maxima rational, a float, or a bigfloat number"
+ (or ($ratnump x) ($floatnump x) ($bfloatp x)))
+
+(defmfun $integerp (x)
+ (or (integerp x)
+ (and ($ratp x)
+ (not (member-eq 'trunc (car x)))
+ (integerp (cadr x))
+ (equal (cddr x) 1))))
+
+;; The call to $INTEGERP in the following two functions checks for a CRE
+;; rational number with an integral numerator and a unity denominator.
+
+(defmfun ($oddp :inline-impl t) (x)
+ (cond ((integerp x) (oddp x))
+ ((atom x) nil)
+ (($integerp x) (oddp (cadr x)))))
+
+(defmfun ($evenp :inline-impl t) (x)
+ (cond ((integerp x) (evenp x))
+ ((atom x) nil)
+ (($integerp x) (not (oddp (cadr x))))))
+
+(defmfun $taylorp (x)
+ (and (not (atom x))
+ (eq (caar x) 'mrat)
+ (member-eq 'trunc (cdar x)) t))
+
diff --git a/src/mutils.lisp b/src/mutils.lisp
index edb03c0ce..c0e1badff 100644
--- a/src/mutils.lisp
+++ b/src/mutils.lisp
@@ -18,29 +18,16 @@
;;;
;;; Every function in this file is known about externally.
-;;; This function searches for the key in the left hand side of the input list
-;;; of the form [x,y,z...] where each of the list elements is a expression of
-;;; a binary operand and 2 elements. For example x=1, 2^3, [a,b] etc.
-;;; The key checked against the first operand and and returns the second
-;;; operand if the key is found.
-;;; If the key is not found it either returns the default value if supplied or
-;;; false.
-;;; Author Dan Stanger 12/1/02
-
-(defmfun $assoc (key ielist &optional default)
- (let ((elist (if (listp ielist)
- (margs ielist)
- (merror
- (intl:gettext "assoc: second argument must be a nonatomic expression; found: ~:M")
- ielist)))
- found)
- (dolist (i elist)
- (unless (and (listp i) (= 3 (length i)))
- (merror (intl:gettext "assoc: elements of the second argument must be an expression of two parts; found: ~:M") i))
- (when (alike1 key (second i))
- (setq found i)
- (return)))
- (if found (third found) default)))
+;;; A MEMQ which works at all levels of a piece of list structure.
+;;;
+;;; Note that (AMONG NIL '(A B C)) is T, however. This could cause bugs.
+;;; > This is false. (AMONG NIL anything) returns NIL always. -kmp
+
+(defun among (x l)
+ (cond ((null l) nil)
+ ((atom l) (eq x l))
+ (t (or (among x (car l)) (among x (cdr l))))))
+
;;; (ASSOL item A-list)
;;;
@@ -78,17 +65,6 @@
((null l))
(when (alike1 x (car l)) (return l)))))
-(declaim (inline member-eq))
-(defun member-eq (m l)
- "This function behaves like (MEMBER M L :TEST #'EQ).
- When inlined, this function is so small that there is almost no code size
- overhead compared to a MEMBER call, but it is faster because no CALL
- instruction is required."
- (while l
- (when (eq m (car l))
- (return l))
- (setq l (cdr l))))
-
;;; Return the first duplicate element of the list LIST, or NIL if there
;;; are no duplicates present in LIST. The function KEY is applied to
;;; each element of the list before comparison (or uses the element itself
@@ -107,32 +83,6 @@
(return-from find-duplicate e))
(push i seen)))))
-;;; Return a Maxima gensym.
-;;;
-;;; N.B. Maxima gensyms are interned, so they are not Lisp gensyms.
-;;; This function can return the same symbol multiple times, it can
-;;; return a symbol that was created and used elsewhere, etc. I (kjak)
-;;; do not think any of this is correct for a function named gensym.
-;;;
-;;; Maxima produces some expressions that contain Maxima gensyms, so
-;;; the use of uninterned symbols instead can cause confusion since
-;;; these print like any other symbol when lispdisp=false (the default).
-(defmfun $gensym (&optional x)
- (typecase x
- (null
- (intern (symbol-name (gensym "$G")) :maxima))
- (string
- (intern
- (symbol-name (gensym (format nil "$~a" (maybe-invert-string-case x))))
- :maxima))
- ((integer 0)
- (let ((*gensym-counter* x))
- (intern (symbol-name (gensym "$G")) :maxima)))
- (t
- (merror
- (intl:gettext
- "gensym: Argument must be a nonnegative integer or a string. Found: ~M") x))))
-
;; Does X or a subexpression match PREDICATE?
;;
;; If X is a tree then we recurse depth-first down its arguments. The specrep
@@ -240,25 +190,6 @@
(and (not (atom x)) (not (atom (car x)))
(member (caar x) '(rat bigfloat)) t)))
-(defmfun ($ratp :inline-impl t) (x)
- (and (not (atom x))
- (consp (car x))
- (eq (caar x) 'mrat)))
-
-(defmfun $ratnump (x)
- (or (integerp x)
- (ratnump x)
- (and ($ratp x)
- (not (member-eq 'trunc (car x)))
- (integerp (cadr x))
- (integerp (cddr x)))))
-
-(defmfun ($bfloatp :inline-impl t) (x)
- "Returns true if X is a bigfloat"
- (and (consp x)
- (consp (car x))
- (eq (caar x) 'bigfloat)))
-
(declaim (inline zerop1))
(defun zerop1 (x)
"Returns non-NIL if X is Lisp number or bfloat that is equal to 0"
@@ -283,34 +214,6 @@
((numberp x) (= 1 x))
(($bfloatp x) (bigfloat-one-p x))))
-(defmfun $floatnump (x)
- (or (floatp x)
- (and ($ratp x) (floatp (cadr x)) (onep1 (cddr x)))))
-
-(defmfun $numberp (x)
- "Returns true if X is a Maxima rational, a float, or a bigfloat number"
- (or ($ratnump x) ($floatnump x) ($bfloatp x)))
-
-(defmfun $integerp (x)
- (or (integerp x)
- (and ($ratp x)
- (not (member-eq 'trunc (car x)))
- (integerp (cadr x))
- (equal (cddr x) 1))))
-
-;; The call to $INTEGERP in the following two functions checks for a CRE
-;; rational number with an integral numerator and a unity denominator.
-
-(defmfun ($oddp :inline-impl t) (x)
- (cond ((integerp x) (oddp x))
- ((atom x) nil)
- (($integerp x) (oddp (cadr x)))))
-
-(defmfun ($evenp :inline-impl t) (x)
- (cond ((integerp x) (evenp x))
- ((atom x) nil)
- (($integerp x) (not (oddp (cadr x))))))
-
;; EVEN works for any arbitrary lisp object since it does an integer
;; check first. In other cases, you may want the Lisp EVENP function
;; which only works for integers.
@@ -319,11 +222,6 @@
(defun even (x)
(and (integerp x) (not (oddp x))))
-(defmfun $taylorp (x)
- (and (not (atom x))
- (eq (caar x) 'mrat)
- (member-eq 'trunc (cdar x)) t))
-
;; Is there a bfloat anywhere in X?
(defun some-bfloatp (x)
(subexpression-matches-p '$bfloatp x))
diff --git a/src/simp-fn.lisp b/src/simp-fn.lisp
new file mode 100644
index 000000000..b16ec5711
--- /dev/null
+++ b/src/simp-fn.lisp
@@ -0,0 +1,139 @@
+;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
+
+(in-package :maxima)
+
+(defmfun $polysign (x)
+ (setq x (cadr (ratf x)))
+ (cond ((equal x 0) 0) ((pminusp x) -1) (t 1)))
+
+(defmfun $numfactor (x)
+ (setq x (specrepcheck x))
+ (cond ((mnump x) x)
+ ((atom x) 1)
+ ((not (eq (caar x) 'mtimes)) 1)
+ ((mnump (cadr x)) (cadr x))
+ (t 1)))
+
+(defmfun $constantp (x)
+ (cond ((atom x) (or ($numberp x) (kindp x '$constant)))
+ ((member (caar x) '(rat bigfloat)) t)
+ ((specrepp x) ($constantp (specdisrep x)))
+ ((or (mopp (caar x)) (kindp (caar x) '$constant))
+ (do ((x (cdr x) (cdr x))) ((null x) t)
+ (if (not ($constantp (car x))) (return nil))))))
+
+
+(defmfun $scalarp (x) (or (consttermp x) (eq (scalarclass x) '$scalar)))
+
+(defmfun $nonscalarp (x) (eq (scalarclass x) '$nonscalar))
+
+(defmfun ($resimplify :inline-impl t) (expr)
+ "Resimplifies the expression EXPR based on the current environment.
+ This function is useful when the fact database, option variables,
+ or tellsimp rules have changed since the expression was last simplified."
+ (resimplify expr))
+
+(defmfun $sqrt (z)
+ (simplify (list '(%sqrt) z)))
+
+;; Define a verb function $abs
+(defmfun $abs (x)
+ (simplify (list '(mabs) x)))
+
+(defmfun $exp (z)
+ (simplify (list '(%exp) z)))
+
+;; Support a function for code,
+;; which depends on an unsimplified noun form.
+(defmfun $exp-form (z)
+ (list '(mexpt) '$%e z))
+
+(defmfun $orderlessp (a b)
+ (setq a ($totaldisrep (specrepcheck a))
+ b ($totaldisrep (specrepcheck b)))
+ (and (not (alike1 a b)) (great b a) t))
+
+(defmfun $ordergreatp (a b)
+ (setq a ($totaldisrep (specrepcheck a))
+ b ($totaldisrep (specrepcheck b)))
+ (and (not (alike1 a b)) (great a b) t))
+
+;; Test function to order a and b by magnitude. If it is not possible to
+;; order a and b by magnitude they are ordered by great. This function
+;; can be used by sort, e.g. sort([3,1,7,x,sin(1),minf],ordermagnitudep)
+(defmfun $ordermagnitudep (a b)
+ (let (sgn)
+ (setq a ($totaldisrep (specrepcheck a))
+ b ($totaldisrep (specrepcheck b)))
+ (cond ((and (or (constp a) (member a '($inf $minf)))
+ (or (constp b) (member b '($inf $minf)))
+ (member (setq sgn ($csign (sub b a))) '($pos $neg $zero)))
+ (cond ((eq sgn '$pos) t)
+ ((eq sgn '$zero) (and (not (alike1 a b)) (great b a)))
+ (t nil)))
+ ((or (constp a) (member a '($inf $minf))) t)
+ ((or (constp b) (member b '($inf $minf))) nil)
+ (t (and (not (alike1 a b)) (great b a))))))
+
+(defmfun $multthru (e1 &optional e2)
+ (let (arg1 arg2)
+ (cond (e2 ;called with two args
+ (setq arg1 (specrepcheck e1)
+ arg2 (specrepcheck e2))
+ (cond ((or (atom arg2)
+ (not (member (caar arg2) '(mplus mequal))))
+ (mul2 arg1 arg2))
+ ((eq (caar arg2) 'mequal)
+ (list (car arg2) ($multthru arg1 (cadr arg2))
+ ($multthru arg1 (caddr arg2))))
+ (t (expandterms arg1 (cdr arg2)))))
+ (t ;called with only one arg
+ (prog (l1)
+ (setq arg1 (setq arg2 (specrepcheck e1)))
+ (cond ((atom arg1) (return arg1))
+ ((eq (caar arg1) 'mnctimes)
+ (setq arg1 (cdr arg1)) (go nct))
+ ((not (eq (caar arg1) 'mtimes)) (return arg1)))
+ (setq arg1 (reverse (cdr arg1)))
+ times (when (mplusp (car arg1))
+ (setq l1 (nconc l1 (cdr arg1)))
+ (return (expandterms (muln l1 t) (cdar arg1))))
+ (setq l1 (cons (car arg1) l1))
+ (setq arg1 (cdr arg1))
+ (if (null arg1) (return arg2))
+ (go times)
+ nct (when (mplusp (car arg1))
+ (setq l1 (nreverse l1))
+ (return (addn (mapcar
+ #'(lambda (u)
+ (simplifya
+ (cons '(mnctimes)
+ (append l1 (ncons u) (cdr arg1)))
+ t))
+ (cdar arg1))
+ t)))
+ (setq l1 (cons (car arg1) l1))
+ (setq arg1 (cdr arg1))
+ (if (null arg1) (return arg2))
+ (go nct))))))
+
+(defmfun $expand (exp &optional (expop $maxposex) (expon $maxnegex))
+ (expand1 exp expop expon))
+
+;; The following was formerly in SININT. This code was placed here because
+;; SININT is now an out-of-core file on MC, and this code is needed in-core
+;; because of the various calls to it. - BMT & JPG
+
+(defmfun $integrate (expr x &optional lo hi)
+ (declare (special *in-risch-p* context))
+ (let ($ratfac)
+ (if (not hi)
+ (with-new-context (context)
+ (if (member '%risch *nounl*)
+ (if *in-risch-p*
+ ;; Give up; we're being called from RISCHINT by some path.
+ (list '(%integrate) expr x)
+ (rischint expr x))
+ (sinint expr x)))
+ ($defint expr x lo hi))))
+
diff --git a/src/simp.lisp b/src/simp.lisp
index 760e8f679..08863ffdd 100644
--- a/src/simp.lisp
+++ b/src/simp.lisp
@@ -50,6 +50,22 @@
(defvar *exptrlsw* nil)
(defvar *expandflag* nil)
+(defmacro while (cond &rest body)
+ `(do ()
+ ((not ,cond))
+ ,@body))
+
+(declaim (inline member-eq))
+(defun member-eq (m l)
+ "This function behaves like (MEMBER M L :TEST #'EQ).
+ When inlined, this function is so small that there is almost no code size
+ overhead compared to a MEMBER call, but it is faster because no CALL
+ instruction is required."
+ (while l
+ (when (eq m (car l))
+ (return l))
+ (setq l (cdr l))))
+
(defprop mnctimes t associative)
(defprop lambda t lisp-no-simp)
@@ -112,26 +128,6 @@
(cond ((eq (caar e) 'mrat) (ratdisrep e))
(t ($outofpois e))))
-(defmfun $polysign (x)
- (setq x (cadr (ratf x)))
- (cond ((equal x 0) 0) ((pminusp x) -1) (t 1)))
-
-(defmfun $numfactor (x)
- (setq x (specrepcheck x))
- (cond ((mnump x) x)
- ((atom x) 1)
- ((not (eq (caar x) 'mtimes)) 1)
- ((mnump (cadr x)) (cadr x))
- (t 1)))
-
-(defmfun $constantp (x)
- (cond ((atom x) (or ($numberp x) (kindp x '$constant)))
- ((member (caar x) '(rat bigfloat)) t)
- ((specrepp x) ($constantp (specdisrep x)))
- ((or (mopp (caar x)) (kindp (caar x) '$constant))
- (do ((x (cdr x) (cdr x))) ((null x) t)
- (if (not ($constantp (car x))) (return nil))))))
-
(defun constant (x)
(cond ((symbolp x) (kindp x '$constant))
(($subvarp x)
@@ -143,10 +139,6 @@
(or (numberp x)
(and (symbolp x) (kindp x '$constant))))
-(defmfun $scalarp (x) (or (consttermp x) (eq (scalarclass x) '$scalar)))
-
-(defmfun $nonscalarp (x) (eq (scalarclass x) '$nonscalar))
-
(defun scalar-or-constant-p (x flag)
(if flag (not ($nonscalarp x)) ($scalarp x)))
@@ -388,12 +380,6 @@
(defun resimplify (x) (let ((dosimp t)) (simplifya x nil)))
-(defmfun ($resimplify :inline-impl t) (expr)
- "Resimplifies the expression EXPR based on the current environment.
- This function is useful when the fact database, option variables,
- or tellsimp rules have changed since the expression was last simplified."
- (resimplify expr))
-
(defun unsimplify (x)
(if (or (atom x) (specrepp x))
x
@@ -1249,9 +1235,6 @@
(defprop %sqrt simp-sqrt operators)
-(defmfun $sqrt (z)
- (simplify (list '(%sqrt) z)))
-
(defun simp-sqrt (x y z)
(oneargcheck x)
(setq y (list '(mexpt) (cadr x) '((rat simp) 1 2)))
@@ -1290,10 +1273,6 @@
;; The abs function distributes over bags.
(defprop mabs (mlist $matrix mequal) distribute_over)
-;; Define a verb function $abs
-(defmfun $abs (x)
- (simplify (list '(mabs) x)))
-
;; The abs function is a simplifying function.
(defprop mabs simpabs operators)
@@ -1664,14 +1643,6 @@
(defprop %exp simp-exp operators)
-(defmfun $exp (z)
- (simplify (list '(%exp) z)))
-
-;; Support a function for code,
-;; which depends on an unsimplified noun form.
-(defmfun $exp-form (z)
- (list '(mexpt) '$%e z))
-
(defun simp-exp (x y z)
(oneargcheck x)
(setq y (list '(mexpt) '$%e (cadr x)))
@@ -2746,33 +2717,6 @@
((or (floatp r1) (floatp r2)) 0.0)
(t 0)))
-(defmfun $orderlessp (a b)
- (setq a ($totaldisrep (specrepcheck a))
- b ($totaldisrep (specrepcheck b)))
- (and (not (alike1 a b)) (great b a) t))
-
-(defmfun $ordergreatp (a b)
- (setq a ($totaldisrep (specrepcheck a))
- b ($totaldisrep (specrepcheck b)))
- (and (not (alike1 a b)) (great a b) t))
-
-;; Test function to order a and b by magnitude. If it is not possible to
-;; order a and b by magnitude they are ordered by great. This function
-;; can be used by sort, e.g. sort([3,1,7,x,sin(1),minf],ordermagnitudep)
-(defmfun $ordermagnitudep (a b)
- (let (sgn)
- (setq a ($totaldisrep (specrepcheck a))
- b ($totaldisrep (specrepcheck b)))
- (cond ((and (or (constp a) (member a '($inf $minf)))
- (or (constp b) (member b '($inf $minf)))
- (member (setq sgn ($csign (sub b a))) '($pos $neg $zero)))
- (cond ((eq sgn '$pos) t)
- ((eq sgn '$zero) (and (not (alike1 a b)) (great b a)))
- (t nil)))
- ((or (constp a) (member a '($inf $minf))) t)
- ((or (constp b) (member b '($inf $minf))) nil)
- (t (and (not (alike1 a b)) (great b a))))))
-
(defun evnump (n) (or (even n) (and (ratnump n) (even (cadr n)))))
(defun odnump (n) (or (and (integerp n) (oddp n))
(and (ratnump n) (oddp (cadr n)))))
@@ -3097,48 +3041,6 @@
;; Different mantissa signs, directly compare.
(> sgn-mant-x sgn-mant-y)))))
-(defmfun $multthru (e1 &optional e2)
- (let (arg1 arg2)
- (cond (e2 ;called with two args
- (setq arg1 (specrepcheck e1)
- arg2 (specrepcheck e2))
- (cond ((or (atom arg2)
- (not (member (caar arg2) '(mplus mequal))))
- (mul2 arg1 arg2))
- ((eq (caar arg2) 'mequal)
- (list (car arg2) ($multthru arg1 (cadr arg2))
- ($multthru arg1 (caddr arg2))))
- (t (expandterms arg1 (cdr arg2)))))
- (t ;called with only one arg
- (prog (l1)
- (setq arg1 (setq arg2 (specrepcheck e1)))
- (cond ((atom arg1) (return arg1))
- ((eq (caar arg1) 'mnctimes)
- (setq arg1 (cdr arg1)) (go nct))
- ((not (eq (caar arg1) 'mtimes)) (return arg1)))
- (setq arg1 (reverse (cdr arg1)))
- times (when (mplusp (car arg1))
- (setq l1 (nconc l1 (cdr arg1)))
- (return (expandterms (muln l1 t) (cdar arg1))))
- (setq l1 (cons (car arg1) l1))
- (setq arg1 (cdr arg1))
- (if (null arg1) (return arg2))
- (go times)
- nct (when (mplusp (car arg1))
- (setq l1 (nreverse l1))
- (return (addn (mapcar
- #'(lambda (u)
- (simplifya
- (cons '(mnctimes)
- (append l1 (ncons u) (cdr arg1)))
- t))
- (cdar arg1))
- t)))
- (setq l1 (cons (car arg1) l1))
- (setq arg1 (cdr arg1))
- (if (null arg1) (return arg2))
- (go nct))))))
-
;; EXPANDEXPT computes the expansion of (x1 + x2 + ... + xm)^n
;; taking a sum and integer power as arguments.
;; Its theory is to recurse down the binomial expansion of
@@ -3290,9 +3192,6 @@
(merror (intl:gettext "expand: expon must be a nonnegative integer; found: ~M") $expon))
(resimplify (specrepcheck exp)))
-(defmfun $expand (exp &optional (expop $maxposex) (expon $maxnegex))
- (expand1 exp expop expon))
-
(defun fixexpand (a)
(if (not (mplusp a))
(ncons a)
@@ -3364,23 +3263,6 @@
(atom (cadr simp-in))
(member (caaadr simp-in) '(mplus mtimes rat))))))))))
-;; The following was formerly in SININT. This code was placed here because
-;; SININT is now an out-of-core file on MC, and this code is needed in-core
-;; because of the various calls to it. - BMT & JPG
-
-(defmfun $integrate (expr x &optional lo hi)
- (declare (special *in-risch-p* context))
- (let ($ratfac)
- (if (not hi)
- (with-new-context (context)
- (if (member '%risch *nounl*)
- (if *in-risch-p*
- ;; Give up; we're being called from RISCHINT by some path.
- (list '(%integrate) expr x)
- (rischint expr x))
- (sinint expr x)))
- ($defint expr x lo hi))))
-
(defun ratp (a ratp-var)
(cond ((atom a) t)
((member (caar a) '(mplus mtimes))
@@ -3497,3 +3379,21 @@
(cons '(mlist simp)
(mapcar #'(lambda (z) (list '(mequal simp) z (meval z))) l)))
+(defun coeff (e var pow)
+ (simplify
+ (cond ((alike1 e var) (if (equal pow 1) 1 0))
+ ((atom e) (if (equal pow 0) e 0))
+ ((eq (caar e) 'mexpt)
+ (cond ((alike1 (cadr e) var)
+ (if (or (equal pow 0) (not (alike1 (caddr e) pow))) 0 1))
+ ((equal pow 0) e)
+ (t 0)))
+ ((or (eq (caar e) 'mplus) (mbagp e))
+ (cons (if (eq (caar e) 'mplus) '(mplus) (car e))
+ (mapcar #'(lambda (e) (coeff e var pow)) (cdr e))))
+ ((eq (caar e) 'mrat) (ratcoeff e var pow))
+ ((equal pow 0) (if (coeff-contains-powers e var) 0 e))
+ ((eq (caar e) 'mtimes)
+ (let ((term (if (equal pow 1) var (power var pow))))
+ (if (memalike term (cdr e)) ($delete term e 1) 0)))
+ (t 0))))
diff --git a/src/utils.lisp b/src/utils.lisp
index 742632355..46ef11a69 100644
--- a/src/utils.lisp
+++ b/src/utils.lisp
@@ -20,11 +20,6 @@
;;;
;;; Every function in this file is known about externally.
-(defmacro while (cond &rest body)
- `(do ()
- ((not ,cond))
- ,@body))
-
(defun maxima-getenv (envvar)
#+gcl (si::getenv envvar)
#+ecl (si::getenv envvar)
@@ -83,16 +78,6 @@
(defun xor (a b)
(or (and (not a) b) (and (not b) a)))
-;;; A MEMQ which works at all levels of a piece of list structure.
-;;;
-;;; Note that (AMONG NIL '(A B C)) is T, however. This could cause bugs.
-;;; > This is false. (AMONG NIL anything) returns NIL always. -kmp
-
-(defun among (x l)
- (cond ((null l) nil)
- ((atom l) (eq x l))
- (t (or (among x (car l)) (among x (cdr l))))))
-
;;; Similar to AMONG, but takes a list of objects to look for. If any
;;; are found in L, returns T.
-----------------------------------------------------------------------
Summary of changes:
src/comm.lisp | 1 +
src/maxima.system | 37 +++++++++---
src/mutils-fn.lisp | 107 ++++++++++++++++++++++++++++++++++
src/mutils.lisp | 122 ++++----------------------------------
src/simp-fn.lisp | 139 ++++++++++++++++++++++++++++++++++++++++++++
src/simp.lisp | 168 +++++++++++------------------------------------------
src/utils.lisp | 15 -----
7 files changed, 319 insertions(+), 270 deletions(-)
create mode 100644 src/mutils-fn.lisp
create mode 100644 src/simp-fn.lisp
hooks/post-receive
--
Maxima CAS
|
|
From: rtoy <rt...@us...> - 2026-04-21 21:35:48
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, rtoy-break-dependency-cycles has been updated
via f10fe1f89564e15a990bae3c39b447da51c0633e (commit)
from 6cb9305041dc6fb7f14e2cd064ab4e467c3101d4 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit f10fe1f89564e15a990bae3c39b447da51c0633e
Author: Raymond Toy <toy...@gm...>
Date: Tue Apr 21 14:32:54 2026 -0700
Move delsimp from comm.lisp to simp-utils.lisp
This breaks the circular dependency between nforma.lisp and comm.lisp.
comm.lisp used nformat-all (via nformat) and that uses delsimp.
A new file simp-utils.lisp holds this function now. It's placed in
the new module simp-utilities. Updated dependencies for all modules
that used delsimp.
diff --git a/src/comm.lisp b/src/comm.lisp
index 392a2891a..d1955d7de 100644
--- a/src/comm.lisp
+++ b/src/comm.lisp
@@ -726,8 +726,6 @@
(defun nthelem (n e)
(car (nthcdr (1- n) e)))
-(defun delsimp (e) (remove 'simp e))
-
(defun remsimp (e)
(if (atom e) e (cons (delsimp (car e)) (mapcar #'remsimp (cdr e)))))
diff --git a/src/maxima.system b/src/maxima.system
index 5e6915042..63189d2e6 100644
--- a/src/maxima.system
+++ b/src/maxima.system
@@ -281,17 +281,22 @@
(:file "mutils")
(:file "outmis")
(:file "ar")))
+ (:module simp-utilities :source-pathname ""
+ :components
+ ((:file "simp-utils")))
(:module commands :source-pathname ""
:depends-on ("globals" "defmfun" "compatibility-macros" "compatibility-macros1"
"declarations" "fundamental-macros" "prerequisites"
- "utility-macros")
+ "utility-macros"
+ "simp-utilities")
:components
((:file "comm")
(:file "comm2")))
(:module evaluator :source-pathname ""
:depends-on ("globals" "defmfun" "utility-macros" "compatibility-macros"
"compatibility-macros1" "declarations" "destructuring-let"
- "fundamental-macros" "prerequisites" "utilities" "commands")
+ "fundamental-macros" "prerequisites" "utilities" "commands"
+ "simp-utilities")
:components
((:file "mlisp")
(:file "mmacro")
@@ -582,7 +587,8 @@
:depends-on ("globals" "defmfun" "reader" "utility-macros" "compatibility-macros"
"compatibility-macros1" "declarations" "destructuring-let"
"fundamental-macros" "i-o" "other-macros" "prerequisites"
- "numerical-utilities")
+ "numerical-utilities"
+ "simp-utilities")
:components
((:file "simp")
(:file "float")
@@ -630,7 +636,8 @@
:depends-on ("globals" "defmfun" "rat-macros" "other-macros"
"compatibility-macros1" "ifactor" "factoring"
"compatibility-macros" "declarations" "destructuring-let"
- "fundamental-macros" "prerequisites" "utilities")
+ "fundamental-macros" "prerequisites" "utilities"
+ "simp-utilities")
:components
((:file "rat3a")
(:file "rat3b")
@@ -689,7 +696,8 @@
(:file "intpol")))
(:module display :source-pathname ""
:depends-on ("globals" "defmfun" "compatibility-macros1" "declarations"
- "fundamental-macros" "prerequisites")
+ "fundamental-macros" "prerequisites"
+ "simp-utilities")
:components
((:file "displa")
(:file "nforma")
@@ -791,7 +799,8 @@
:depends-on ("globals" "defmfun" "compatibility-macros1"
"declarations" "evaluator"
"fundamental-macros" "prerequisites"
- "rat-macros")
+ "rat-macros"
+ "simp-utilities")
:components
((:file "schatc")
(:file "matcom")
diff --git a/src/simp-utils.lisp b/src/simp-utils.lisp
new file mode 100644
index 000000000..b4d6dcdc8
--- /dev/null
+++ b/src/simp-utils.lisp
@@ -0,0 +1,8 @@
+;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(in-package :maxima)
+
+(defun delsimp (e)
+ (remove 'simp e))
+
-----------------------------------------------------------------------
Summary of changes:
src/comm.lisp | 2 --
src/maxima.system | 21 +++++++++++++++------
src/simp-utils.lisp | 8 ++++++++
3 files changed, 23 insertions(+), 8 deletions(-)
create mode 100644 src/simp-utils.lisp
hooks/post-receive
--
Maxima CAS
|
|
From: rtoy <rt...@us...> - 2026-04-21 21:12:54
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, rtoy-break-dependency-cycles has been updated
via 6cb9305041dc6fb7f14e2cd064ab4e467c3101d4 (commit)
via 93c79c8d11b4531b5553133e415745cbc59fc6c5 (commit)
from 529be2a2bc43fde31d809999ddd3611bee6fffad (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 6cb9305041dc6fb7f14e2cd064ab4e467c3101d4
Author: Raymond Toy <toy...@gm...>
Date: Tue Apr 21 14:12:02 2026 -0700
Update dependency: bessel.lisp needs numeric-utilities
diff --git a/src/maxima.system b/src/maxima.system
index 3fe221eda..5e6915042 100644
--- a/src/maxima.system
+++ b/src/maxima.system
@@ -678,7 +678,8 @@
(:module numerical-functions :source-pathname ""
:depends-on ("globals" "defmfun" "trigonometry" "algebraic-database"
"utility-macros" "reader"
- "fundamental-macros" "other-macros" "prerequisites")
+ "fundamental-macros" "other-macros" "prerequisites"
+ "numerical-utilities")
:components
((:file "bessel")
(:file "ellipt")
commit 93c79c8d11b4531b5553133e415745cbc59fc6c5
Author: Raymond Toy <toy...@gm...>
Date: Tue Apr 21 14:08:31 2026 -0700
Move simp-domain-error to numerical-utilities
That's used all over so numerical-utilities seems to be a good place
for it. Also changed how $erf and $erfc are called in
expintegral.lisp. We used `ftake` instead.
diff --git a/src/expintegral.lisp b/src/expintegral.lisp
index aa5d80225..aae55b342 100644
--- a/src/expintegral.lisp
+++ b/src/expintegral.lisp
@@ -124,15 +124,6 @@
*expintflag*)))))))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Global to this file
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun simp-domain-error (&rest args)
- (if errorsw
- (throw 'errorsw t)
- (apply #'merror args)))
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Part 1: The implementation of the Exponential Integral En
@@ -363,9 +354,9 @@
;; We have a half integral order and $expintexpand is not NIL.
;; We expand in a series in terms of the Erfc or Erf function.
(let ((func (cond ((eq $expintexpand '%erf)
- (sub 1 ($erf (power arg '((rat simp) 1 2)))))
+ (sub 1 (ftake '%erf (power arg '((rat simp) 1 2)))))
(t
- ($erfc (power arg '((rat simp) 1 2)))))))
+ (ftake '%erfc (power arg '((rat simp) 1 2)))))))
(cond
((= ratorder 1/2)
(mul (power '$%pi '((rat simp) 1 2))
diff --git a/src/numerical-utils.lisp b/src/numerical-utils.lisp
index af136ee31..80594b1e9 100644
--- a/src/numerical-utils.lisp
+++ b/src/numerical-utils.lisp
@@ -118,4 +118,13 @@
(defun cpower (x y) ($rectform (power x y)))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Utilitye function to signal an error denoting a domain error for
+;; the special functions. ARGS should be appropriate for MERROR.
+(defun simp-domain-error (&rest args)
+ (if errorsw
+ (throw 'errorsw t)
+ (apply #'merror args)))
+
-----------------------------------------------------------------------
Summary of changes:
src/expintegral.lisp | 13 ++-----------
src/maxima.system | 3 ++-
src/numerical-utils.lisp | 9 +++++++++
3 files changed, 13 insertions(+), 12 deletions(-)
hooks/post-receive
--
Maxima CAS
|
|
From: rtoy <rt...@us...> - 2026-04-21 19:56:42
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, rtoy-break-dependency-cycles has been created
at 529be2a2bc43fde31d809999ddd3611bee6fffad (commit)
- Log -----------------------------------------------------------------
commit 529be2a2bc43fde31d809999ddd3611bee6fffad
Author: Raymond Toy <toy...@gm...>
Date: Tue Apr 21 12:50:16 2026 -0700
Move numerical-eval stuff to new file numerical-utils.lisp.
The numerical-eval-p functions from gamma.lisp along with the cmul
functions from expintegral.lisp have been moved to the new file
numerical-utils.lisp in the new module numerical-utilities. This
breaks the cycle of dependency between gamma.lisp and
expintegral.lisp.
With the new module, we also move gamma.lisp and expintegral.lisp to a
new module gamma-expint. A quick grep for numerical-eval-p shows what
modules now depend on numerical-utilities so update those dependencies
too.
diff --git a/src/expintegral.lisp b/src/expintegral.lisp
index 491e49bb3..aa5d80225 100644
--- a/src/expintegral.lisp
+++ b/src/expintegral.lisp
@@ -656,16 +656,6 @@
(setq *debug-expint-fracmaxit* (max *debug-expint-fracmaxit* i)))
(return r))))))))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Helper functions for Bigfloat numerical evaluation.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun cmul (x y) ($rectform (mul x y)))
-
-(defun cdiv (x y) ($rectform (div x y)))
-
-(defun cpower (x y) ($rectform (power x y)))
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; We have not changed the above algorithm, but generalized it to handle
;;; complex and real Bigfloat numbers. By carefully examination of the
diff --git a/src/gamma.lisp b/src/gamma.lisp
index 68aba8c28..680fc5f4b 100644
--- a/src/gamma.lisp
+++ b/src/gamma.lisp
@@ -84,106 +84,6 @@
(defmvar $erf_%iargs nil
"When T erf and erfi simplifies for an imaginary argument.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; The following functions test if numerical evaluation has to be done.
-;;; The functions should help to test for numerical evaluation more consistent
-;;; and without complicated conditional tests including more than one or two
-;;; arguments.
-;;;
-;;; The functions take a list of arguments. All arguments have to be a CL or
-;;; Maxima number. If all arguments are numbers we have two cases:
-;;; 1. $numer is T we return T. The function has to be evaluated numerically.
-;;; 2. One of the args is a float or a bigfloat. Evaluate numerically.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;;; Test for numerically evaluation in float precision
-
-(defun float-numerical-eval-p (&rest args)
- (let ((flag nil))
- (dolist (ll args)
- (when (not (float-or-rational-p ll))
- (return-from float-numerical-eval-p nil))
- (when (floatp ll) (setq flag t)))
- (if (or $numer flag) t nil)))
-
-;;; Test for numerically evaluation in complex float precision
-
-(defun complex-float-numerical-eval-p (&rest args)
- "Determine if ARGS consists of numerical values by determining if
- the real and imaginary parts of each arg are nuemrical (but not
- bigfloats). A non-NIL result is returned if at least one of args is
- a floating-point value or if numer is true. If the result is
- non-NIL, it is a list of the arguments reduced via COMPLEX-NUMBER-P"
- (let (flag values)
- (dolist (ll args)
- (multiple-value-bind (bool rll ill)
- (complex-number-p ll 'float-or-rational-p)
- (unless bool
- (return-from complex-float-numerical-eval-p nil))
- ;; Always save the result from complex-number-p. But for backward
- ;; compatibility, only set the flag if any item is a float.
- (push (add rll (mul ill '$%i)) values)
- (setf flag (or flag (or (floatp rll) (floatp ill))))))
- (when (or $numer flag)
- ;; Return the values in the same order as the args!
- (nreverse values))))
-
-;;; Test for numerically evaluation in bigfloat precision
-
-(defun bigfloat-numerical-eval-p (&rest args)
- (let ((flag nil))
- (dolist (ll args)
- (when (not (bigfloat-or-number-p ll))
- (return-from bigfloat-numerical-eval-p nil))
- (when ($bfloatp ll)
- (setq flag t)))
- (if (or $numer flag) t nil)))
-
-;;; Test for numerically evaluation in complex bigfloat precision
-
-(defun complex-bigfloat-numerical-eval-p (&rest args)
- "Determine if ARGS consists of numerical values by determining if
- the real and imaginary parts of each arg are nuemrical (including
- bigfloats). A non-NIL result is returned if at least one of args is
- a floating-point value or if numer is true. If the result is
- non-NIL, it is a list of the arguments reduced via COMPLEX-NUMBER-P."
-
- (let (flag values)
- (dolist (ll args)
- (multiple-value-bind (bool rll ill)
- (complex-number-p ll 'bigfloat-or-number-p)
- (unless bool
- (return-from complex-bigfloat-numerical-eval-p nil))
- ;; Always save the result from complex-number-p. But for backward
- ;; compatibility, only set the flag if any item is a bfloat.
- (push (add rll (mul ill '$%i)) values)
- (when (or ($bfloatp rll) ($bfloatp ill))
- (setf flag t))))
- (when (or $numer flag)
- ;; Return the values in the same order as the args!
- (nreverse values))))
-
-;;; Test for numerical evaluation in any precision, real or complex.
-(defun numerical-eval-p (&rest args)
- (or (apply 'float-numerical-eval-p args)
- (apply 'complex-float-numerical-eval-p args)
- (apply 'bigfloat-numerical-eval-p args)
- (apply 'complex-bigfloat-numerical-eval-p args)))
-
-;;; Check for an integer or a float or bigfloat representation. When we
-;;; have a float or bigfloat representation return the integer value.
-
-(defun integer-representation-p (x)
- (let ((val nil))
- (cond ((integerp x) x)
- ((and (floatp x) (= 0 (nth-value 1 (truncate x))))
- (nth-value 0 (truncate x)))
- ((and ($bfloatp x)
- (eq ($sign (sub (setq val ($truncate x)) x)) '$zero))
- val)
- (t nil))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; The changes to the parser to connect the operator !! to double_factorial(z)
diff --git a/src/hyp.lisp b/src/hyp.lisp
index 2d3103383..73fae974e 100644
--- a/src/hyp.lisp
+++ b/src/hyp.lisp
@@ -1,6 +1,5 @@
;;; -*- LISP -*-
;;; ** (c) Copyright 1979 Massachusetts Institute of Technology **
-
(in-package :maxima)
;;; References:
diff --git a/src/maxima.system b/src/maxima.system
index a7228b244..3fe221eda 100644
--- a/src/maxima.system
+++ b/src/maxima.system
@@ -581,7 +581,8 @@
(:module simplification :source-pathname ""
:depends-on ("globals" "defmfun" "reader" "utility-macros" "compatibility-macros"
"compatibility-macros1" "declarations" "destructuring-let"
- "fundamental-macros" "i-o" "other-macros" "prerequisites")
+ "fundamental-macros" "i-o" "other-macros" "prerequisites"
+ "numerical-utilities")
:components
((:file "simp")
(:file "float")
@@ -671,6 +672,9 @@
(:file "evalw")
(:file "trprop")
(:file "mdefun")))
+ (:module numerical-utilities :source-pathname ""
+ :components
+ ((:file "numerical-utils")))
(:module numerical-functions :source-pathname ""
:depends-on ("globals" "defmfun" "trigonometry" "algebraic-database"
"utility-macros" "reader"
@@ -759,7 +763,8 @@
(:file "trgred")))
(:module special-functions :source-pathname ""
:depends-on ("globals" "defmfun" "reader" "utility-macros"
- "other-macros" "rat-macros")
+ "other-macros" "rat-macros"
+ "numerical-utilities")
:components
((:file "specfn")))
(:module matrix-algebra :source-pathname ""
@@ -818,11 +823,17 @@
:components
((:file "mtrace")
(:file "mdebug")))
+ (:module gamma-expint :source-pathname ""
+ :depends-on ("numerical-utilities")
+ :components
+ ((:file "expintegral")
+ (:file "gamma")))
(:module miscellaneous :source-pathname ""
:depends-on ("globals" "defmfun" "pattern-matching" "compatibility-macros1"
"reader" "utility-macros" "commands"
"destructuring-let" "errset" "other-macros"
- "rat-macros" "declarations" "fundamental-macros")
+ "rat-macros" "declarations" "fundamental-macros"
+ "numerical-utilities")
:components
((:file "scs")
(:file "asum")
@@ -840,10 +851,8 @@
(:file "maxmin")
(:file "nummod")
(:file "conjugate")
- (:file "expintegral")
- (:file "gamma")
- (:file "hstep")
- (:file "sinc")
+ (:file "hstep")
+ (:file "sinc")
(:file "mstuff")))
(:module polynomial :source-pathname ""
:depends-on ("defmfun")
diff --git a/src/numerical-utils.lisp b/src/numerical-utils.lisp
new file mode 100644
index 000000000..af136ee31
--- /dev/null
+++ b/src/numerical-utils.lisp
@@ -0,0 +1,121 @@
+;;;; -*- LISP -*-
+
+;;;; This software has NO WARRANTY, not even the implied warranty of
+;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+(in-package :maxima)
+
+;;; Utilities for determining if numerical evaluation should be done.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; The following functions test if numerical evaluation has to be done.
+;;; The functions should help to test for numerical evaluation more consistent
+;;; and without complicated conditional tests including more than one or two
+;;; arguments.
+;;;
+;;; The functions take a list of arguments. All arguments have to be a CL or
+;;; Maxima number. If all arguments are numbers we have two cases:
+;;; 1. $numer is T we return T. The function has to be evaluated numerically.
+;;; 2. One of the args is a float or a bigfloat. Evaluate numerically.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Test for numerically evaluation in float precision
+
+(defun float-numerical-eval-p (&rest args)
+ (let ((flag nil))
+ (dolist (ll args)
+ (when (not (float-or-rational-p ll))
+ (return-from float-numerical-eval-p nil))
+ (when (floatp ll) (setq flag t)))
+ (if (or $numer flag) t nil)))
+
+;;; Test for numerically evaluation in complex float precision
+
+(defun complex-float-numerical-eval-p (&rest args)
+ "Determine if ARGS consists of numerical values by determining if
+ the real and imaginary parts of each arg are nuemrical (but not
+ bigfloats). A non-NIL result is returned if at least one of args is
+ a floating-point value or if numer is true. If the result is
+ non-NIL, it is a list of the arguments reduced via COMPLEX-NUMBER-P"
+ (let (flag values)
+ (dolist (ll args)
+ (multiple-value-bind (bool rll ill)
+ (complex-number-p ll 'float-or-rational-p)
+ (unless bool
+ (return-from complex-float-numerical-eval-p nil))
+ ;; Always save the result from complex-number-p. But for backward
+ ;; compatibility, only set the flag if any item is a float.
+ (push (add rll (mul ill '$%i)) values)
+ (setf flag (or flag (or (floatp rll) (floatp ill))))))
+ (when (or $numer flag)
+ ;; Return the values in the same order as the args!
+ (nreverse values))))
+
+;;; Test for numerically evaluation in bigfloat precision
+
+(defun bigfloat-numerical-eval-p (&rest args)
+ (let ((flag nil))
+ (dolist (ll args)
+ (when (not (bigfloat-or-number-p ll))
+ (return-from bigfloat-numerical-eval-p nil))
+ (when ($bfloatp ll)
+ (setq flag t)))
+ (if (or $numer flag) t nil)))
+
+;;; Test for numerically evaluation in complex bigfloat precision
+
+(defun complex-bigfloat-numerical-eval-p (&rest args)
+ "Determine if ARGS consists of numerical values by determining if
+ the real and imaginary parts of each arg are nuemrical (including
+ bigfloats). A non-NIL result is returned if at least one of args is
+ a floating-point value or if numer is true. If the result is
+ non-NIL, it is a list of the arguments reduced via COMPLEX-NUMBER-P."
+
+ (let (flag values)
+ (dolist (ll args)
+ (multiple-value-bind (bool rll ill)
+ (complex-number-p ll 'bigfloat-or-number-p)
+ (unless bool
+ (return-from complex-bigfloat-numerical-eval-p nil))
+ ;; Always save the result from complex-number-p. But for backward
+ ;; compatibility, only set the flag if any item is a bfloat.
+ (push (add rll (mul ill '$%i)) values)
+ (when (or ($bfloatp rll) ($bfloatp ill))
+ (setf flag t))))
+ (when (or $numer flag)
+ ;; Return the values in the same order as the args!
+ (nreverse values))))
+
+;;; Test for numerical evaluation in any precision, real or complex.
+(defun numerical-eval-p (&rest args)
+ (or (apply 'float-numerical-eval-p args)
+ (apply 'complex-float-numerical-eval-p args)
+ (apply 'bigfloat-numerical-eval-p args)
+ (apply 'complex-bigfloat-numerical-eval-p args)))
+
+;;; Check for an integer or a float or bigfloat representation. When we
+;;; have a float or bigfloat representation return the integer value.
+
+(defun integer-representation-p (x)
+ (let ((val nil))
+ (cond ((integerp x) x)
+ ((and (floatp x) (= 0 (nth-value 1 (truncate x))))
+ (nth-value 0 (truncate x)))
+ ((and ($bfloatp x)
+ (eq ($sign (sub (setq val ($truncate x)) x)) '$zero))
+ val)
+ (t nil))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Helper functions for Bigfloat numerical evaluation.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun cmul (x y) ($rectform (mul x y)))
+
+(defun cdiv (x y) ($rectform (div x y)))
+
+(defun cpower (x y) ($rectform (power x y)))
+
+
-----------------------------------------------------------------------
hooks/post-receive
--
Maxima CAS
|
|
From: dauti <da...@us...> - 2026-04-21 17:06:35
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, master has been updated
via b123029a18cb75e53d48d7be968f99a78ba688bb (commit)
from bf60af06a6798e0f416d49836407fa667697eb8b (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit b123029a18cb75e53d48d7be968f99a78ba688bb
Author: Wolfgang Dautermann <da...@us...>
Date: Tue Apr 21 19:04:01 2026 +0200
Fixes for Maxima/ECL/Windows.
ECL is installed in %maxima_prefix%/ecl, set the
path to ecl correctly.
diff --git a/crosscompile-windows/CMakeLists.txt b/crosscompile-windows/CMakeLists.txt
index df14c7add..f67fe7815 100644
--- a/crosscompile-windows/CMakeLists.txt
+++ b/crosscompile-windows/CMakeLists.txt
@@ -313,7 +313,7 @@ externalproject_add(maxima
COMMAND sed -i s+^.*wine-clisp.sh+clisp.exe+g src/maxima.bat
COMMAND sed -i s+^.*wine-sbcl.sh+sbcl.exe+g src/maxima.bat
COMMAND sed -i s+^.*wine-ccl.sh+wx86cl64.exe+g src/maxima.bat
- COMMAND sed -i s+^.*wine-ecl.sh+ecl/ecl.exe+g src/maxima.bat
+ COMMAND sed -i s+^.*wine-ecl.sh+ecl.exe+g src/maxima.bat
INSTALL_COMMAND PATH=${CMAKE_BINARY_DIR}/texinfo-installroot/bin:$ENV{PATH} LANG=C $(MAKE) install DESTDIR=${CMAKE_BINARY_DIR}/maxima-installroot/
COMMAND PATH=${CMAKE_BINARY_DIR}/texinfo-installroot/bin:$ENV{PATH} LANG=C $(MAKE) extradocinstall DESTDIR=${CMAKE_BINARY_DIR}/maxima-installroot/
)
diff --git a/crosscompile-windows/ecl/CMakeLists.txt b/crosscompile-windows/ecl/CMakeLists.txt
index df4fdf3a9..da804edb6 100644
--- a/crosscompile-windows/ecl/CMakeLists.txt
+++ b/crosscompile-windows/ecl/CMakeLists.txt
@@ -32,4 +32,4 @@ ExternalProject_Add(ecl
COMMAND ${CMAKE_COMMAND} -E copy "${MINGW_LIBGCC}" "${CMAKE_BINARY_DIR}/ecl-cross-root"
COMMAND ${CMAKE_COMMAND} -E copy "${MINGW_LIBWINPTHREAD}" "${CMAKE_BINARY_DIR}/ecl-cross-root"
)
-install(DIRECTORY ${CMAKE_BINARY_DIR}/ecl-cross-root/ DESTINATION bin/ecl COMPONENT ECL)
+install(DIRECTORY ${CMAKE_BINARY_DIR}/ecl-cross-root/ DESTINATION ecl COMPONENT ECL)
diff --git a/src/maxima.bat.in b/src/maxima.bat.in
index fd535039f..d37527e1f 100755
--- a/src/maxima.bat.in
+++ b/src/maxima.bat.in
@@ -184,7 +184,7 @@ goto :EOF
:doecl
chcp 65001 >nul
-set "path=%maxima_prefix%/winlibs/bin;%path%"
+set "path=%maxima_prefix%/ecl;%maxima_prefix%/winlibs/bin;%path%"
set "MAXIMA_IMAGESDIR_BIN=%maxima_imagesdir%/binary-%lisp%"
@ECL_NAME@ --eval "(load \"%MAXIMA_IMAGESDIR_BIN%/defsystem.lisp\")" --eval "(mk:add-registry-location \"%MAXIMA_IMAGESDIR_BIN%\")" --eval "(funcall (intern (symbol-name :operate-on-system) :mk) \"maxima\" :load :verbose nil)" --eval "(cl-user::run)" -- %*
goto :EOF
-----------------------------------------------------------------------
Summary of changes:
crosscompile-windows/CMakeLists.txt | 2 +-
crosscompile-windows/ecl/CMakeLists.txt | 2 +-
src/maxima.bat.in | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
hooks/post-receive
--
Maxima CAS
|
|
From: rtoy <rt...@us...> - 2026-04-20 20:43:13
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, bug-4720-part1-move-atan2-to-trigi has been created
at 0a57cfb13b91ba1bef7fe3c1e26d402a0fc63807 (commit)
- Log -----------------------------------------------------------------
commit 0a57cfb13b91ba1bef7fe3c1e26d402a0fc63807
Author: Raymond Toy <toy...@gm...>
Date: Mon Apr 20 10:56:08 2026 -0700
Update dependencies for trigonometry module
Moving atan2 from comm2 to trigi means some dependencies need
updating. Add the following to the trigonometry module:
* "simplification"
* `alike1` and `free` from simp.lisp
* "algebraic-database"
* `mnqp` and `mgrp` from compar.lisp
diff --git a/src/maxima.system b/src/maxima.system
index a7228b244..98f6547e1 100644
--- a/src/maxima.system
+++ b/src/maxima.system
@@ -752,7 +752,8 @@
:depends-on ("globals" "pattern-matching" "defmfun"
"compatibility-macros" "declarations"
"errset" "fundamental-macros" "other-macros"
- "prerequisites" "utility-macros")
+ "prerequisites" "utility-macros"
+ "simplification" "algebraic-database")
:components
((:file "trigi")
(:file "trigo")
commit f36e38d8992cac971f50a80074fae4072def7f2d
Author: Raymond Toy <toy...@gm...>
Date: Mon Apr 20 10:52:25 2026 -0700
Move atan2 simplifier from comm2 to trigi
For some reason comm2.lisp had the simplifier for atan2. It makes a
lot more sense to have it in trigi where all the other inverse trig
functions live. Now comm2 has no def-simplifier in it.
Since cosp is used by atan2 and sinp from limits is very simple, we're
moving them to mutils where other simple predicates live.
diff --git a/src/comm2.lisp b/src/comm2.lisp
index e1da8ba48..51701f33f 100644
--- a/src/comm2.lisp
+++ b/src/comm2.lisp
@@ -485,218 +485,6 @@
((specrepp e) ($nterms (specdisrep e)))
(t 1)))
-;;;; ATAN2
-
-;; The function sinp is defined in `limit.lisp'. Here we define `cosp`.
-(defun cosp (e)
-"Return true iff the expression `e` is in general form and its operator is `%cos`."
- (and (consp e) (eq '%cos (caar e))))
-
-;; Checks:
-;; (i) pi - 2 pi ceiling((pi - pi)/(2 pi)) = pi - 0 = pi, and
-;; (ii) -pi - 2 pi ceiling((-pi - pi)/(2 pi)) = -pi - 2 pi ceiling(-1) = -pi + 2pi = pi, as required.
-(defun reduce-angle-mod-2pi (theta)
- "Reduce the input `mod 2 pi` to a value in the interval `(-pi, pi]`.
- Thus -pi reduces to pi, and pi reduces to pi."
- (cond
- ;; The range of both atan2 and carg is `(-pi,pi]`, so give a free pass for such expressions.
- ((and (consp theta) (or (eq (caar theta) '%atan2) (eq (caar theta) '%carg)))
- theta)
- (t
- (let ((n (ftake '$ceiling (div (sub theta '$%pi) (mul 2 '$%pi)))))
- ;; If you want to do the reduction only when `n` is an explicit integer,
- ;; put in a conditional and return nil when `n` is not an explicit integer.
- (sub theta (mul 2 '$%pi n))))))
-
-(defun nonvanishing-common-factor (p q)
- "Return the product of the absolute values of the nonvanishing factors that are common to p and q. This code
- doesn't factor p or q, so it only considers factors that are explict. When there are no
- such factors, return one, that is, the empty product."
- (let* ((pp (fapply '$set (if (mtimesp p) (cdr p) (list p))))
- (qq (fapply '$set (if (mtimesp q) (cdr q) (list q))))
- (ss (cdr ($intersection pp qq)))
- (ll nil))
- (dolist (sx ss)
- (when (eq t (mnqp sx 0))
- (push (ftake 'mabs sx) ll)))
- (fapply 'mtimes ll)))
-
-;; Outside the one call to this function in the atan2 simplifier, this code likely isn't particulary useful.
-(defun polar-angle-if-sinusoids (x y)
- "When both `x` and `y` have the form `(+/-) sin(X)` or `(+/-) cos(X)` and the point (x,y) is on the unit circle,
- return the principal polar angle of the point `(x,y)`. Otherwise, return nil. The principal polar angle is a
- member of the interval `(-pi,pi]`."
- (flet ((sinusoid-p (x)
- (or (cosp x) (cosp (neg x)) (sinp x) (sinp (neg x)))))
- (when (and (sinusoid-p x) (sinusoid-p y))
- (let ((z ($expand ($exponentialize (add x (mul '$%i y))))))
- (flet ((fn (x)
- (cond ((eql x -1) '$%pi)
- ((eq x '$%i) (div '$%pi 2))
- ((and (mexptp x) (eq (cadr x) '$%e)) (div (caddr x) '$%i))
- (t nil))))
- ;; When `(x,y)` isn't on the unit circle (say `x = sin(p)` and `y = cos(q)`) `z` will not
- ;; be a product of terms that are on the unit circle, and the `every` check will fail.
- (let ((theta (mapcar #'fn (if (mtimesp z) (cdr z) (list z)))))
- (if (every #'identity theta)
- (reduce-angle-mod-2pi (fapply 'mplus theta))
- nil)))))))
-
-(defvar *atan2-extended-real-hashtable* (make-hash-table :test #'equal)
-"Hashtable giving the value of atan2(extended real, extended real) when the value
-is unambiguous. Ambiguous cases, for example atan2(inf,inf), are not included in
-the hashtable.")
-
-;; At compile time, the functions `div` and `mul` are not available, so we
-;; cannot build `atan2-extended-real-hashtable*` here. To workaround this, we define
-;; a function `initialize-atan2-hashtable` that hash table *atan2-extended-real-hashtable*,
-;; we and call this function in `init-cl.lisp`.
-(defun initialize-atan2-hashtable ()
- (let ((pi-over-two (div '$%pi 2)) (neg-pi-over-two (div '$%pi -2)) (minus-pi (mul -1 '$%pi)))
- (mapcar #'(lambda (z) (setf (gethash (list (first z) (second z)) *atan2-extended-real-hashtable*) (third z)))
- (list
- (list '$minf '$zerob neg-pi-over-two)
- (list '$minf '$zeroa neg-pi-over-two)
- (list '$minf '$ind neg-pi-over-two)
-
- (list '$zerob '$minf minus-pi)
- (list '$zerob '$inf 0)
-
- (list '$zeroa '$minf '$%pi)
- (list '$zeroa '$inf 0)
-
- (list '$ind '$inf 0)
-
- (list '$inf '$zerob pi-over-two)
- (list '$inf '$zeroa pi-over-two)
- (list '$inf '$ind pi-over-two)))))
-
-(defvar *extended-reals* '($minf $zerob $zeroa $ind $und $inf $infinity)
-"Common Lisp list of all of Maxima's extended real numbers")
-
-;; atan2 distributes over lists, matrices, and equations
-(defprop %atan2 (mlist $matrix mequal) distribute_over)
-
-;; I have locally set `limitp` to `nil` in two calls to `$sign`. This change
-;; resolves bug #4529: `atan2` limit issue with `radexpand: false`.
-;; Specifically, it resolves the bug when computing the limit:
-;; `block([radexpand: false], limit(atan2(x^2 - 2, x^3 - 3*x), x, sqrt(2), minus))`.
-;; Arguably, this fix is inelegant and should be revisited. (Barton Willis, April 2025)
-(def-simplifier atan2 (y x)
- ;; for both x & y, convert -inf to minf.
- (when (alike1 y (mul -1 '$inf))
- (setq y '$minf))
- (when (alike1 x (mul -1 '$inf))
- (setq x '$minf))
- ;; for both x & y, convert -minf to inf.
- (when (alike1 y (mul -1 '$minf))
- (setq y '$inf))
- (when (alike1 x (mul -1 '$minf))
- (setq x '$inf))
-
- ;; Divide both x & y by the absolute value of common factors that are
- ;; nonvanishing. Skip this when either x or y depend on an extended real.
- (when (and (freeofl y *extended-reals*) (freeofl x *extended-reals*))
- (let ((w (nonvanishing-common-factor y x)))
- (setq y (div y w))
- (setq x (div x w))))
-
- (let ((signy) (signx))
-
- (cond ((and (zerop1 y) (zerop1 x))
- (merror (intl:gettext "atan2: atan2(0,0) is undefined.")))
- (;; float contagion
- (and (or (numberp x) (ratnump x)) ; both numbers
- (or (numberp y) (ratnump y)) ; ... but not bigfloats
- (or $numer (floatp x) (floatp y))) ; at least one float
- (atan ($float y) ($float x)))
- (;; bfloat contagion
- (and (mnump x)
- (mnump y)
- (or ($bfloatp x) ($bfloatp y))) ; at least one bfloat
- (setq x ($bfloat x)
- y ($bfloat y))
- (*fpatan y (list x)))
- ;; Look up atan(extended real, extended real) in a hashtable. When the value
- ;; isn't found in the hashtable, return a nounform.
- ((and (member x *extended-reals*) (member y *extended-reals*))
- (gethash (list y x) *atan2-extended-real-hashtable* (give-up)))
-
- ;;When either `x` or `y` is in ($und infinity $ind), give up
- ((or (member x '($und $infinity $ind)) (member y '($und $infinity $ind)))
- (give-up))
-
- ;; Simplify infinities--the hashtable lookup catches atan2(inf,inf),atan2(minf,inf), ..., so
- ;; we should be able to safely do atan2(y,inf) = 0 here.
- ((eq x '$inf)
- ;; Simplify atan2(y,inf) -> 0
- 0)
- ((eq x '$minf)
- ;; Simplify atan2(y,minf) -> %pi for realpart(y)>=0 or -%pi
- ;; for realpart(y)<0. When sign of y unknown, return noun
- ;; form. We are basically making atan2 on the branch cut
- ;; be continuous with quadrant II.
- (let ((sgn ($sign ($realpart y))))
- (cond ((member sgn '($pos $pz $zero))
- '$%pi)
- ((eq sgn '$neg) (mul -1 '$%pi))
- (t (give-up)))))
- ;; We have already taken care of atan2(extended real, extended real), so we can
- ;; safely simplify atan2(inf, X) to %pi/2 and atan2(minf, X) to -%pi/2. The case
- ;; atan2(inf, %i) = %pi/2 is likely OK.
- ((eq y '$inf)
- (div '$%pi 2))
- ((eq y '$minf)
- (div '$%pi -2))
- ((and (free x '$%i) (setq signx (let ((limitp nil)) ($sign x)))
- (free y '$%i) (setq signy (let ((limitp nil)) ($sign y)))
- (cond ((eq signy '$zero)
- ;; Handle atan2(0, x) which is %pi or -%pi
- ;; depending on the sign of x. We assume that
- ;; x is never actually zero since atan2(0,0) is
- ;; undefined.
- (cond ((member signx '($neg $nz)) '$%pi)
- ((member signx '($pos $pz)) 0)
- ((eq signx '$zero) (merror (intl:gettext "atan2: atan2(0,0) is undefined.")))))
-
- ((eq signx '$zero)
- ;; Handle atan2(y, 0) which is %pi/2 or -%pi/2,
- ;; depending on the sign of y.
- (cond ((eq signy '$neg) (div '$%pi -2))
- ((member signy '($pos $pz)) (div '$%pi 2))))
- ((alike1 y x)
- ;; Handle atan2(x,x) which is %pi/4 or -3*%pi/4
- ;; depending on the sign of x.
- (cond ((eq signx '$neg) (mul -3 (div '$%pi 4)))
- ((member signx '($pos $pz)) (div '$%pi 4))))
- ((alike1 y (mul -1 x))
- ;; Handle atan2(-x,x) which is 3*%pi/4 or
- ;; -%pi/4 depending on the sign of x.
- (cond ((eq signx '$neg) (mul 3 (div '$%pi 4)))
- ((member signx '($pos $pz)) (div '$%pi -4)))))))
-
- ;; atan2((+/-)sin(angle),(+/-)cos(angle)) = angle reduced to (-pi,pi] mod 2 pi.
- ;; and similarly for atan2((+/-)cos(angle),(+/-)sin(angle))
- ((polar-angle-if-sinusoids x y))
- ($logarc
- (logarc '%atan2 (list ($logarc y) ($logarc x))))
- ;; atan2(-y,x) = -atan2(y,x) provided (a) trigsign is true, (b) (great (neg y) y), and
- ;; (c) (x,y) is off the negative real axis.
- ((and $trigsign
- (eq t (mminusp y))
- (or (eq t (mnqp y 0)) (eq t (mgrp x 0))))
- (neg (ftake '%atan2 (neg y) x)))
- ((eq signx '$pos)
- ;; atan2(y,x) = atan(y/x) when x is positive.
- (take '(%atan) (div y x)))
-
- ((and (eq signx '$neg) (member signy '($pos $neg $pz $zero) :test #'eq))
- (cond ((eq signy '$neg) (sub (ftake '%atan (div y x)) '$%pi))
- ((member signy '($pos $pz $zero)) (add (ftake '%atan (div y x)) '$%pi))
- (t (give-up))))
-
- (t (give-up)))))
-
;;;; ARITHF
(defmfun $fibtophi (e &optional (lnorecurse nil))
diff --git a/src/limit.lisp b/src/limit.lisp
index d1468fedc..bb1d44e7a 100644
--- a/src/limit.lisp
+++ b/src/limit.lisp
@@ -4322,9 +4322,6 @@ ignoring dummy variables and array indices."
((or (eql 2 sgn) (eql 1 sgn)) 1) ; atan(> 0) = 1
(t (throw 'taylor-catch nil)))))
-(defun sinp (e)
- (and (consp e) (eq '%sin (caar e))))
-
(defun mrv-sign-sin (e x)
(let ((sgn (mrv-sign-helper (div 1 (cadr e)) x)))
(cond ((eql sgn 2) 1) ;sin(zeroa) = 1
diff --git a/src/mutils.lisp b/src/mutils.lisp
index edb03c0ce..da3aa21a1 100644
--- a/src/mutils.lisp
+++ b/src/mutils.lisp
@@ -398,3 +398,12 @@
(and (not (atom x))
(or (eq (caar x) '$matrix)
(and $listarith (eq (caar x) 'mlist)))))
+
+(defun sinp (e)
+ (and (consp e) (eq '%sin (caar e))))
+
+(defun cosp (e)
+ "Return true iff the expression `e` is in general form and its operator is `%cos`."
+ (and (consp e) (eq '%cos (caar e))))
+
+
diff --git a/src/trigi.lisp b/src/trigi.lisp
index b4d81f7c0..901cb28b1 100644
--- a/src/trigi.lisp
+++ b/src/trigi.lisp
@@ -927,3 +927,211 @@
(defun dbz-err1 (func)
(cond ((not errorsw) (merror (intl:gettext "~A: division by zero attempted.") func))
(t (throw 'errorsw t))))
+
+;;;; ATAN2
+
+;; Checks:
+;; (i) pi - 2 pi ceiling((pi - pi)/(2 pi)) = pi - 0 = pi, and
+;; (ii) -pi - 2 pi ceiling((-pi - pi)/(2 pi)) = -pi - 2 pi ceiling(-1) = -pi + 2pi = pi, as required.
+(defun reduce-angle-mod-2pi (theta)
+ "Reduce the input `mod 2 pi` to a value in the interval `(-pi, pi]`.
+ Thus -pi reduces to pi, and pi reduces to pi."
+ (cond
+ ;; The range of both atan2 and carg is `(-pi,pi]`, so give a free pass for such expressions.
+ ((and (consp theta) (or (eq (caar theta) '%atan2) (eq (caar theta) '%carg)))
+ theta)
+ (t
+ (let ((n (ftake '$ceiling (div (sub theta '$%pi) (mul 2 '$%pi)))))
+ ;; If you want to do the reduction only when `n` is an explicit integer,
+ ;; put in a conditional and return nil when `n` is not an explicit integer.
+ (sub theta (mul 2 '$%pi n))))))
+
+(defun nonvanishing-common-factor (p q)
+ "Return the product of the absolute values of the nonvanishing factors that are common to p and q. This code
+ doesn't factor p or q, so it only considers factors that are explict. When there are no
+ such factors, return one, that is, the empty product."
+ (let* ((pp (fapply '$set (if (mtimesp p) (cdr p) (list p))))
+ (qq (fapply '$set (if (mtimesp q) (cdr q) (list q))))
+ (ss (cdr ($intersection pp qq)))
+ (ll nil))
+ (dolist (sx ss)
+ (when (eq t (mnqp sx 0))
+ (push (ftake 'mabs sx) ll)))
+ (fapply 'mtimes ll)))
+
+;; Outside the one call to this function in the atan2 simplifier, this code likely isn't particulary useful.
+(defun polar-angle-if-sinusoids (x y)
+ "When both `x` and `y` have the form `(+/-) sin(X)` or `(+/-) cos(X)` and the point (x,y) is on the unit circle,
+ return the principal polar angle of the point `(x,y)`. Otherwise, return nil. The principal polar angle is a
+ member of the interval `(-pi,pi]`."
+ (flet ((sinusoid-p (x)
+ (or (cosp x) (cosp (neg x)) (sinp x) (sinp (neg x)))))
+ (when (and (sinusoid-p x) (sinusoid-p y))
+ (let ((z ($expand ($exponentialize (add x (mul '$%i y))))))
+ (flet ((fn (x)
+ (cond ((eql x -1) '$%pi)
+ ((eq x '$%i) (div '$%pi 2))
+ ((and (mexptp x) (eq (cadr x) '$%e)) (div (caddr x) '$%i))
+ (t nil))))
+ ;; When `(x,y)` isn't on the unit circle (say `x = sin(p)` and `y = cos(q)`) `z` will not
+ ;; be a product of terms that are on the unit circle, and the `every` check will fail.
+ (let ((theta (mapcar #'fn (if (mtimesp z) (cdr z) (list z)))))
+ (if (every #'identity theta)
+ (reduce-angle-mod-2pi (fapply 'mplus theta))
+ nil)))))))
+
+(defvar *atan2-extended-real-hashtable* (make-hash-table :test #'equal)
+"Hashtable giving the value of atan2(extended real, extended real) when the value
+is unambiguous. Ambiguous cases, for example atan2(inf,inf), are not included in
+the hashtable.")
+
+;; At compile time, the functions `div` and `mul` are not available, so we
+;; cannot build `atan2-extended-real-hashtable*` here. To workaround this, we define
+;; a function `initialize-atan2-hashtable` that hash table *atan2-extended-real-hashtable*,
+;; we and call this function in `init-cl.lisp`.
+(defun initialize-atan2-hashtable ()
+ (let ((pi-over-two (div '$%pi 2)) (neg-pi-over-two (div '$%pi -2)) (minus-pi (mul -1 '$%pi)))
+ (mapcar #'(lambda (z) (setf (gethash (list (first z) (second z)) *atan2-extended-real-hashtable*) (third z)))
+ (list
+ (list '$minf '$zerob neg-pi-over-two)
+ (list '$minf '$zeroa neg-pi-over-two)
+ (list '$minf '$ind neg-pi-over-two)
+
+ (list '$zerob '$minf minus-pi)
+ (list '$zerob '$inf 0)
+
+ (list '$zeroa '$minf '$%pi)
+ (list '$zeroa '$inf 0)
+
+ (list '$ind '$inf 0)
+
+ (list '$inf '$zerob pi-over-two)
+ (list '$inf '$zeroa pi-over-two)
+ (list '$inf '$ind pi-over-two)))))
+
+(defvar *extended-reals* '($minf $zerob $zeroa $ind $und $inf $infinity)
+"Common Lisp list of all of Maxima's extended real numbers")
+
+;; atan2 distributes over lists, matrices, and equations
+(defprop %atan2 (mlist $matrix mequal) distribute_over)
+
+;; I have locally set `limitp` to `nil` in two calls to `$sign`. This change
+;; resolves bug #4529: `atan2` limit issue with `radexpand: false`.
+;; Specifically, it resolves the bug when computing the limit:
+;; `block([radexpand: false], limit(atan2(x^2 - 2, x^3 - 3*x), x, sqrt(2), minus))`.
+;; Arguably, this fix is inelegant and should be revisited. (Barton Willis, April 2025)
+(def-simplifier atan2 (y x)
+ ;; for both x & y, convert -inf to minf.
+ (when (alike1 y (mul -1 '$inf))
+ (setq y '$minf))
+ (when (alike1 x (mul -1 '$inf))
+ (setq x '$minf))
+ ;; for both x & y, convert -minf to inf.
+ (when (alike1 y (mul -1 '$minf))
+ (setq y '$inf))
+ (when (alike1 x (mul -1 '$minf))
+ (setq x '$inf))
+
+ ;; Divide both x & y by the absolute value of common factors that are
+ ;; nonvanishing. Skip this when either x or y depend on an extended real.
+ (when (and (freeofl y *extended-reals*) (freeofl x *extended-reals*))
+ (let ((w (nonvanishing-common-factor y x)))
+ (setq y (div y w))
+ (setq x (div x w))))
+
+ (let ((signy) (signx))
+
+ (cond ((and (zerop1 y) (zerop1 x))
+ (merror (intl:gettext "atan2: atan2(0,0) is undefined.")))
+ (;; float contagion
+ (and (or (numberp x) (ratnump x)) ; both numbers
+ (or (numberp y) (ratnump y)) ; ... but not bigfloats
+ (or $numer (floatp x) (floatp y))) ; at least one float
+ (atan ($float y) ($float x)))
+ (;; bfloat contagion
+ (and (mnump x)
+ (mnump y)
+ (or ($bfloatp x) ($bfloatp y))) ; at least one bfloat
+ (setq x ($bfloat x)
+ y ($bfloat y))
+ (*fpatan y (list x)))
+ ;; Look up atan(extended real, extended real) in a hashtable. When the value
+ ;; isn't found in the hashtable, return a nounform.
+ ((and (member x *extended-reals*) (member y *extended-reals*))
+ (gethash (list y x) *atan2-extended-real-hashtable* (give-up)))
+
+ ;;When either `x` or `y` is in ($und infinity $ind), give up
+ ((or (member x '($und $infinity $ind)) (member y '($und $infinity $ind)))
+ (give-up))
+
+ ;; Simplify infinities--the hashtable lookup catches atan2(inf,inf),atan2(minf,inf), ..., so
+ ;; we should be able to safely do atan2(y,inf) = 0 here.
+ ((eq x '$inf)
+ ;; Simplify atan2(y,inf) -> 0
+ 0)
+ ((eq x '$minf)
+ ;; Simplify atan2(y,minf) -> %pi for realpart(y)>=0 or -%pi
+ ;; for realpart(y)<0. When sign of y unknown, return noun
+ ;; form. We are basically making atan2 on the branch cut
+ ;; be continuous with quadrant II.
+ (let ((sgn ($sign ($realpart y))))
+ (cond ((member sgn '($pos $pz $zero))
+ '$%pi)
+ ((eq sgn '$neg) (mul -1 '$%pi))
+ (t (give-up)))))
+ ;; We have already taken care of atan2(extended real, extended real), so we can
+ ;; safely simplify atan2(inf, X) to %pi/2 and atan2(minf, X) to -%pi/2. The case
+ ;; atan2(inf, %i) = %pi/2 is likely OK.
+ ((eq y '$inf)
+ (div '$%pi 2))
+ ((eq y '$minf)
+ (div '$%pi -2))
+ ((and (free x '$%i) (setq signx (let ((limitp nil)) ($sign x)))
+ (free y '$%i) (setq signy (let ((limitp nil)) ($sign y)))
+ (cond ((eq signy '$zero)
+ ;; Handle atan2(0, x) which is %pi or -%pi
+ ;; depending on the sign of x. We assume that
+ ;; x is never actually zero since atan2(0,0) is
+ ;; undefined.
+ (cond ((member signx '($neg $nz)) '$%pi)
+ ((member signx '($pos $pz)) 0)
+ ((eq signx '$zero) (merror (intl:gettext "atan2: atan2(0,0) is undefined.")))))
+
+ ((eq signx '$zero)
+ ;; Handle atan2(y, 0) which is %pi/2 or -%pi/2,
+ ;; depending on the sign of y.
+ (cond ((eq signy '$neg) (div '$%pi -2))
+ ((member signy '($pos $pz)) (div '$%pi 2))))
+ ((alike1 y x)
+ ;; Handle atan2(x,x) which is %pi/4 or -3*%pi/4
+ ;; depending on the sign of x.
+ (cond ((eq signx '$neg) (mul -3 (div '$%pi 4)))
+ ((member signx '($pos $pz)) (div '$%pi 4))))
+ ((alike1 y (mul -1 x))
+ ;; Handle atan2(-x,x) which is 3*%pi/4 or
+ ;; -%pi/4 depending on the sign of x.
+ (cond ((eq signx '$neg) (mul 3 (div '$%pi 4)))
+ ((member signx '($pos $pz)) (div '$%pi -4)))))))
+
+ ;; atan2((+/-)sin(angle),(+/-)cos(angle)) = angle reduced to (-pi,pi] mod 2 pi.
+ ;; and similarly for atan2((+/-)cos(angle),(+/-)sin(angle))
+ ((polar-angle-if-sinusoids x y))
+ ($logarc
+ (logarc '%atan2 (list ($logarc y) ($logarc x))))
+ ;; atan2(-y,x) = -atan2(y,x) provided (a) trigsign is true, (b) (great (neg y) y), and
+ ;; (c) (x,y) is off the negative real axis.
+ ((and $trigsign
+ (eq t (mminusp y))
+ (or (eq t (mnqp y 0)) (eq t (mgrp x 0))))
+ (neg (ftake '%atan2 (neg y) x)))
+ ((eq signx '$pos)
+ ;; atan2(y,x) = atan(y/x) when x is positive.
+ (take '(%atan) (div y x)))
+
+ ((and (eq signx '$neg) (member signy '($pos $neg $pz $zero) :test #'eq))
+ (cond ((eq signy '$neg) (sub (ftake '%atan (div y x)) '$%pi))
+ ((member signy '($pos $pz $zero)) (add (ftake '%atan (div y x)) '$%pi))
+ (t (give-up))))
+
+ (t (give-up)))))
+
-----------------------------------------------------------------------
hooks/post-receive
--
Maxima CAS
|
|
From: willisbl <wil...@us...> - 2026-04-20 18:56:01
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, master has been updated
via bf60af06a6798e0f416d49836407fa667697eb8b (commit)
from afa88b539ca88b9748701824e7c7b44601e8f174 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit bf60af06a6798e0f416d49836407fa667697eb8b
Author: Barton Willis <wi...@un...>
Date: Mon Apr 20 13:55:50 2026 -0500
Declare `preserve-direction` at top of nummod.lisp
This eliminates one SBCL compiler message.
No unexpected testsuite or share testsuite failures.
diff --git a/src/nummod.lisp b/src/nummod.lisp
index 46affc85a..197009563 100644
--- a/src/nummod.lisp
+++ b/src/nummod.lisp
@@ -26,6 +26,8 @@
(in-package :maxima)
+(declare-top (special preserve-direction))
+
(macsyma-module nummod)
;; Let's have version numbers 1,2,3,...
-----------------------------------------------------------------------
Summary of changes:
src/nummod.lisp | 2 ++
1 file changed, 2 insertions(+)
hooks/post-receive
--
Maxima CAS
|
|
From: willisbl <wil...@us...> - 2026-04-20 17:54:57
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, master has been updated
via afa88b539ca88b9748701824e7c7b44601e8f174 (commit)
from 5b7282e42965cc12351323d2c900745f0f133b23 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit afa88b539ca88b9748701824e7c7b44601e8f174
Author: Barton Willis <wi...@un...>
Date: Mon Apr 20 12:54:43 2026 -0500
Fixes #4085, #4717, #3826, and several unnumbered testsuite failures.
Summary of changes:
- Introduce `limit-by-methods` (in tlimit) to forlimit method dispatch.
- Rename `limit-assumptions` to `*limit-assumptions*`.
- Revise `coef-sign` (in hayat) so that it updates `*limit-assumptions*`.
- Adjust `simplim%signum` so that `limit(signum(und))` returns `und`.
- Remove one line of dead code in `simplimplus1`.
- Update testsuite files and correct several expected results.
The fix for #3826 is a better fix (no longer a limit nounform).
No unexpected testsuite or share testsuite failures with either SBCL 2.4.7 or Clozure CL 1.13.1.
diff --git a/src/hayat.lisp b/src/hayat.lisp
index 5f76aa3ac..ca8b1be87 100644
--- a/src/hayat.lisp
+++ b/src/hayat.lisp
@@ -139,6 +139,7 @@
trunclist ;
*within-srf?* ;flag for in srf
mainvar-datum ;
+ *limit-assumptions*
least_term? ; If non-null then the addition routines
; are adding or subtracting coeff's of the
; least term of a sum so they should do
@@ -1401,9 +1402,24 @@
lim)))))
(defun coef-sign (coef)
- (if (not ($freeof '$%i ($rectform coef)))
- '$im
- ($asksign coef)))
+ "Determine the sign of `coef`.
+
+ First, find the sign using `$csign`. If `$csign` returns `$complex` or `$imaginary`,
+ return `$im`; if the sign is`$neg` or `$pos`, return those values.
+
+ Second, call `asksign`. If `$asksign` returns `$zero` and `*limit-assumptions*`
+ is non-nil, push `coef = 0` onto `*limit-assumptions*` before returning the sign
+ determined by asksign."
+ (let ((sgn ($csign coef)))
+ (cond ((or (eq sgn '$complex) (eq sgn '$imaginary)) '$im)
+ ((member sgn '($neg $zero $pos)) sgn)
+ (t
+ (let ((asgn ($asksign coef)))
+ ;; When sgn is zero and limit is active, record this fact as a noun equality
+ ;; in *limit-assumptions*.
+ (when (and *limit-assumptions* (eq asgn '$zero))
+ (push (ftake '$equal coef 0) *limit-assumptions*))
+ asgn)))))
(defun gvar-lim (gvar)
(or (cdr (assoc gvar tvar-limits :test #'eq))
diff --git a/src/limit.lisp b/src/limit.lisp
index d1468fedc..c64c60c40 100644
--- a/src/limit.lisp
+++ b/src/limit.lisp
@@ -31,13 +31,14 @@
*indicator numer denom exp var val
taylored logcombed
$exponentialize lhp? lhcount
- loginprod? context limit-assumptions
+ loginprod? context *limit-assumptions*
limit-top))
(defconstant +behavior-count+ 4)
(defvar *behavior-count-now*)
(defvar *getsignl-asksign-ok* nil)
(defvar *old-integer-info* nil)
+(defvar *limit-assumptions* nil)
(load-macsyma-macros rzmac)
@@ -117,7 +118,7 @@
(some #'(lambda (q) (indefinite-integral-p q x)) (cdr e)))))
(defun toplevel-$limit (&rest args)
- (let ((limit-assumptions ())
+ (let ((*limit-assumptions* ())
(*old-integer-info* ())
($keepfloat t)
($numer nil)
@@ -125,7 +126,7 @@
($%emode t)
($%e_to_numlog nil)
(limit-top t))
- (declare (special limit-assumptions limit-top))
+ (declare (special *limit-assumptions* limit-top))
(unless limitp
(setq *old-integer-info* *integer-info*)
(setq *integer-info* ()))
@@ -279,10 +280,10 @@
(cond (limit-top
(assume '((mgreaterp) lim-epsilon 0))
(assume '((mgreaterp) prin-inf 100000000))
- (setq limit-assumptions (make-limit-assumptions var val direction))
+ (setq *limit-assumptions* (make-limit-assumptions var val direction))
(setq limit-top ()))
(t ()))
- limit-assumptions)
+ *limit-assumptions*)
(defun make-limit-assumptions (var val direction)
(let ((new-assumptions))
@@ -304,7 +305,7 @@
(defun restore-assumptions ()
;;;Hackery until assume and forget take reliable args. Nov. 9 1979.
;;;JIM.
- (do ((assumption-list limit-assumptions (cdr assumption-list)))
+ (do ((assumption-list *limit-assumptions* (cdr assumption-list)))
((null assumption-list) t)
(forget (car assumption-list)))
(forget '((mgreaterp) lim-epsilon 0))
@@ -1332,7 +1333,7 @@ ignoring dummy variables and array indices."
(let ((lim (limit (cadr e) x pt 'think)))
(cond ((or (eq lim '$zeroa) (eql lim 0) (eq lim '$ind)) lim)
((eq lim '$zerob) '$zeroa)
- ((eq lim '$und) (throw 'limit nil))
+ ((eq lim '$und) '$und)
((or (eq lim '$minf) (eq lim '$inf) (eq lim '$infinity)) '$inf)
(t (ftake 'mabs lim)))))
(setf (get 'mabs 'simplim%function) 'simplim%mabs)
@@ -2461,7 +2462,6 @@ ignoring dummy variables and array indices."
(push ans undl))
((or (eq r '$minf) (eq r '$inf) (eq r '$infinity))
(throw 'limit t))
- ((eq r nil))
(t (push r sum))))
;; Add the members of the list sum.
(setq sum (fapply 'mplus sum))
@@ -3833,7 +3833,7 @@ ignoring dummy variables and array indices."
(let ((e (limit (cadr e) x pt 'think)) (sgn))
(cond ((eq '$minf e) -1)
((eq '$inf e) 1)
- ((eq '$infinity e) '$und)
+ ((eq '$infinity e) '$ind)
((eq '$ind e) '$ind)
((eq '$und e) e)
((eq '$zerob e) -1)
diff --git a/src/testsuite.lisp b/src/testsuite.lisp
index 84f971b1e..d4102c990 100644
--- a/src/testsuite.lisp
+++ b/src/testsuite.lisp
@@ -138,12 +138,12 @@
((mlist simp) 42 59 61 82 83 84 89
96 104
124 125 126 127 132 133 135 136 137
- 224 238
- 239 240 241 242 243 244 245 246 249
- 261 262 267 268 269 270 272
+ 224
+ 240 243 244 245 246 249
+ 262 267 268 269 270 272
281 282 357 358))
((mlist simp) "rtest_limit_gruntz"
- ((mlist simp) 20 25 28 29 30 36 37 39 86 96))
+ ((mlist simp) 20 25 28 29 30 37 39 86 96))
((mlist simp) "rtest_limit_wester"
((mlist simp) 12 13))
diff --git a/src/tlimit.lisp b/src/tlimit.lisp
index 1c5bf916c..1be08976e 100644
--- a/src/tlimit.lisp
+++ b/src/tlimit.lisp
@@ -10,19 +10,48 @@
(in-package :maxima)
-(declare-top (special taylored *getsignl-asksign-ok*))
+(declare-top (special taylored *limit-assumptions* preserve-direction *getsignl-asksign-ok*))
+
+(declaim (special *limit-method-depth* *already-processed-limits*))
(macsyma-module tlimit)
(load-macsyma-macros rzmac)
+;; The function `limit-by-methods` iterates over a list of limit methods and stops when a
+;; method is successful. A method is considered successful when it returns a value that is
+;; neither a boolean (often produced by a non‑local exit) nor a limit nounform.
+
+;; To prevent unbounded recursion or repeated evaluation, `limit-by-methods`
+;; uses two safeguards:
+
+;; (a) The special variable `*limit-method-depth*` tracks the current recursion
+;; depth. The depth is incremented upon entry to each method and compared
+;; against `*max-limit-depth*` (default 16). If the limit computation exceeds
+;; this bound, processing stops.
+
+;; (b) Each attempted limit produces a "fingerprint." The fingerprint is a list of
+;; the method and the limit data (function, limit variable, and limit point).
+;; These fingerprints are stored in the special variable `*already-processed-limits*`.
+;; If a newly generated fingerprint matches one already present, the computation ends.
+
+;; To ensure alikeness of each fingerprint, the limit variable is normalized to
+;; `*universal-limit-variable*`. This allows expressions such as limit(f(x), x, a)
+;; and limit(f(y), y, a) to test as `alike1`, preventing redundant evaluation.
+
+(defvar *limit-method-depth* 0)
+(defvar *universal-limit-variable* (gensym))
+(defvar *already-processed-limits* nil)
+(defmvar *max-limit-depth* 8) ; magic number = 8 for no particular reason
+
;; For limits toward `inf`, assume that the limit variable exceeds `*large-positive-number*`
(defmvar *large-positive-number* 4398046511104) ; 2^42 for no particular reason
;; TOP LEVEL FUNCTION(S): $TLIMIT $TLDEFINT
+(declaim (special limit-using-taylor))
+
(defmfun $tlimit (&rest args)
(let ((limit-using-taylor t))
- (declare (special limit-using-taylor))
(apply #'$limit args)))
(defmfun $tldefint (exp var ll ul)
@@ -35,7 +64,7 @@
;; expressions containing $ind.
;; We have subst([h=0,x=0], taylor(asin(x+h)-asin(x),h,0,1)) = %pi (see
-;; bug #4416 limit of Newton quotient involving asin). This bug causes
+;; bug \#4416 limit of Newton quotient involving asin). This bug causes
;; trouble for tlimit((asin(x+h) - asin(x))/h,h,0). Until such bugs are
;; sorted, we will disallow tlimit from attempting limits involving
;; acos and asin.
@@ -111,15 +140,16 @@
(let ((ee)
(silent-taylor-flag t)
($taylordepth 8)
- ($radexpand nil)
- ($taylor_logexpand t)
- ($logexpand nil))
+ ($radexpand nil)
+ ($taylor_logexpand t)
+ ($logexpand nil))
(cond
- ((eq pt '$infinity) nil)
+ ((eq pt '$infinity) nil) ; infinity is an illegitimate limit point
(t
(setq e (atan2-to-atan e))
- (setq ee (catch 'taylor-catch ($totaldisrep ($taylor e x pt n))))
+ (setq ee ($totaldisrep (catch 'taylor-catch ($taylor e x pt n))))
+
(cond
((and ee (not (eql ee 0))) ee)
;; Retry if Taylor returns zero and depth is less than 16
@@ -130,22 +160,143 @@
;; Previously, when the Taylor series failed, there was code to decide
;; whether to call limit1 or simplimit. The choice depended on the last
;; argument to taylim (previously named *i*) and the main operator of the
-;; expression. This updated code eliminates that logic and always dispatches
-;; limit1 when Maxima is unable to find the Taylor polynomial. As a result,
-;; the last argument of taylim is now unused (orphaned).
-(defun taylim (e var val flag)
- "Attempt to compute the limit of `e` as `var` approaches `val` using a Taylor expansion.
- When the Taylor expansion fails, fall back to using `limit1`. The `flag` argument is unused."
+;; expression. This updated code eliminates that logic and now uses the
+;; new limit-by-methods scheme. As a result, the last argument of taylim
+;; is now unused (orphaned).
+
+;; Occasionally, the taylor code does an asksign (see function coef-sign). When
+;; that happens and asksign determines that the sign is zero, the taylor code
+;; appends this fact to *limit-assumptions*. Often this fact is rather crucial, so after
+;; the first effort to determine the taylor series, the code loops through
+;; *limit-assumptions* and looks for facts of the form equal(XXX,0); when it
+;; finds such a fact, it substitutes 0 for XXX in the expression and tries again
+;; to find the taylor series.
+
+(defun taylim (e var val &optional (flag nil))
+ "Attempt to compute the limit of `e` as `var` approaches `val` using a
+ Taylor expansion. If the Taylor expansion succeeds, apply limit
+ methods to the resulting series. If it fails—or if Taylor-based
+ assumptions require rewriting the expression—fall back to `limit1`
+ and related methods."
(declare (ignore flag))
- (let ((et nil))
+
+ ;; Establish recursion‑protection for limit-by-methods. If these specials
+ ;; are already dynamically bound, preserve their bindings; otherwise start
+ ;; with the default values. The function taylim is currently the only entry point that
+ ;; invokes limit-by-methods, so we set up the guard context here.
+ (let ((*already-processed-limits* *already-processed-limits*)
+ (*limit-method-depth* *limit-method-depth*)
+ (*getsignl-asksign-ok* nil)
+ (et nil))
+
(when (tlimp e var)
- (setq e (stirling0 e))
- (setq et (tlimit-taylor e var (ridofab val) $lhospitallim 0)))
+ (let* ((e1 (stirling0 e))
+ (pt (ridofab val))
+ (redo nil))
+
+ ;; First Taylor attempt
+ (setq et (tlimit-taylor e1 var pt $lhospitallim 0))
+
+ ;; Examine any assumptions recorded during Taylor
+ (dolist (fct *limit-assumptions*)
+ (when (and (consp fct) (eq '$equal (caar fct)))
+ (setq redo t)
+ (setq e1 (maxima-substitute (third fct) (second fct) e1))))
+
+ ;; Retry Taylor after rewriting, if needed
+ (when redo
+ (setq et (tlimit-taylor e1 var pt $lhospitallim 0)))))
+
+ ;; If Taylor succeeded, set taylored to true and dispatch methods on et; otherwise
+ ;; dispatch methods on e.
(if et
- (let ((taylored t)) ; the special variable `taylored` prevents infinite looping
- (or (limit-sum-of-powers et var val)
- (limit et var val 'think)))
- (limit1 e var val))))
+ (let ((taylored t))
+ (limit-by-methods et var val
+ (list 'limit-sum-of-powers
+ 'limit-method-think
+ 'limit1
+ 'limit-method-reciprocal-limit-point)))
+ (limit-by-methods e var val
+ (list
+ 'limit-method-think
+ 'limit1
+ 'limit-method-reciprocal-limit-point)))))
+
+(defun limit-method-think (e x pt)
+ (limit e x pt 'think))
+
+(defun liminv-new-val (val)
+ (cond ((eq val '$zeroa) '$inf)
+ ((eq val '$zerob) '$minf)
+ ((eq val '$inf) '$zeroa)
+ ((eq val '$minf) '$zerob)
+ (t nil)))
+
+(defun limit-method-reciprocal-limit-point (e var val)
+ "Attempt to compute the limit of E as VAR approaches VAL by transforming the
+ limit point via reciprocal substitution."
+ (let* ((ee (maxima-substitute (div 1 var) var e))
+ (new-val (liminv-new-val val)))
+ (cond
+ (new-val
+ (let ((preserve-direction t))
+ (taylim ee var new-val nil)))
+ (t
+ (throw 'limit t)))))
+
+(defun successful-limit-result-p (ans)
+ ;; A limit method result is successful only if it is:
+ ;; - non-nil
+ ;; - not the special inconclusive marker T
+ ;; - not a %limit nounform
+ (and ans
+ (not (eq ans t))
+ (not (among '%limit ans))))
+
+;; To call this function, the callee must intialize *limit-method-depth* and *already-processed-limits*. The
+;; function taylim shows an expample of how to do this.
+
+;; Although `limit-by-methods` is defined in the file `tlimit`, it is not specific to the tlimit code.
+(defun limit-by-methods (e x pt methods)
+ "Apply a sequence of limit methods to compute limit(e, x, pt).
+
+Each method FN is called as (FN e x pt) and may return a value,
+NIL, or signal (throw 'limit <value>). The first value satisfying
+successful-limit-result-p is returned.
+
+Recursion guards:
+ (a) *limit-method-depth* is incremented and compared with
+ *max-limit-depth*; exceeding this bound aborts with (throw 'limit NIL).
+
+ (b) A fingerprint of (FN, e, x, pt) is recorded in
+ *already-processed-limits*; repeating a fingerprint aborts the
+ computation to prevent recursive cycles.
+
+Returns the first valid limit result found, or NIL if no method succeeds."
+ ;; Initialize guards if not already bound
+ (let ((*already-processed-limits* (or *already-processed-limits* nil))
+ (*limit-method-depth* (or *limit-method-depth* 0)))
+
+ (when (> *limit-method-depth* *max-limit-depth*)
+ (throw 'limit nil))
+
+ (let ((*limit-method-depth* (1+ *limit-method-depth*)))
+ (catch 'limit-found
+ (dolist (fn methods)
+ ;; recursion guard
+ (let ((fingerprint (ftake 'mlist
+ (position fn methods)
+ (maxima-substitute *universal-limit-variable* x e)
+ *universal-limit-variable*
+ pt)))
+ (when (member fingerprint *already-processed-limits* :test #'alike1)
+ (throw 'limit nil))
+ (push fingerprint *already-processed-limits*))
+
+ ;; run method
+ (let ((ans (catch 'limit (funcall fn e x pt))))
+ (when (successful-limit-result-p ans)
+ (throw 'limit-found ans))))))))
(defun power-of-x-p (e x)
"Return true if `e` is a monomial of the form `x^q`, where `q` is a rational number. Also returns true if `e` is `x`.
diff --git a/tests/rtest3.mac b/tests/rtest3.mac
index b786b2871..9837009be 100644
--- a/tests/rtest3.mac
+++ b/tests/rtest3.mac
@@ -385,7 +385,11 @@ trigsimp (integrate (%e^((-log(x)^2)-1)*log(x),x));
/(4*abs(2*log(x)-1))$
/* throw away results of integrate, just make sure it runs without crashing */
-block ([foo, bar, ctxt, domain : 'complex],
+
+/* The assignment facsum_combine : 'facsum_combine, prevents some calls to asksign & askinteger. Without
+ this assignment in a fresh Maxima, this test runs with no calls to either asksign or askinteger. */
+
+block ([foo, bar, ctxt, domain : 'complex, facsum_combine : 'facsum_combine],
foo : exp(-(log(x) - MU)*(log(x) - MU)/(2*SIGMA*SIGMA))/(x*SIGMA*sqrt(2*%pi)),
bar : (log(B) - log(x*SIGMA) + ((x-A)*(x-A)/(2*B*B) - (log(x) -MU)*(log(x) -MU)/(2*SIGMA*SIGMA))),
[foo, bar] : subst ([A=2, MU=3], [foo, bar]),
@@ -1074,3 +1078,9 @@ print_string_2d ("
\"'My Novel' not found.\"
";
+
+contexts;
+[initial, global]$
+
+kill(values);
+done$
\ No newline at end of file
diff --git a/tests/rtest_limit.mac b/tests/rtest_limit.mac
index 9656b8ff8..d04881b93 100644
--- a/tests/rtest_limit.mac
+++ b/tests/rtest_limit.mac
@@ -923,10 +923,10 @@ true;
ctxt: newcontext (),
assume (q > 0),
limit(x^q/(a*x^q- 1),x,inf));
-'limit(x^q/(a*x^q- 1),x,inf);
+1/a;
tlimit(x^q/(a*x^q- 1),x,inf);
-'limit(x^q/(a*x^q- 1),x,inf);
+1/a;
(assume (a > 0),
declare (q, integer),
diff --git a/tests/rtest_limit_extra.mac b/tests/rtest_limit_extra.mac
index 32fe765cb..37d54d1e3 100644
--- a/tests/rtest_limit_extra.mac
+++ b/tests/rtest_limit_extra.mac
@@ -911,8 +911,8 @@ limit(li[3](x)/log(-x)^3,x,inf);
ind$
/* #4085 limit((2-%i)^a/a!,a,inf) */
- errcatch(limit((2-%i)^a/a!,a,inf));
- [0]$
+ limit((2-%i)^a/a!,a,inf);
+ 0$
/* #4081 limit((2+sin(x))^(-2),x,inf) --> und */
limit((2+sin(x))^(-2),x,inf);
@@ -1470,6 +1470,13 @@ the other test mentioned in ticket 4634. */
limit(((-1)^N*(2*N+1))/4-1/4,N,inf);
und$
+/* \#4717 limit(signum(exp(%i*x)*exp(x)),x,inf);*/
+limit(signum(exp(%i*x)*exp(x)),x,inf);
+ind$
+
+limit(signum(exp(%i*x)*exp(x))/x,x,inf);
+0$
+
/* clean up*/
(kill(values),0);
0$
-----------------------------------------------------------------------
Summary of changes:
src/hayat.lisp | 22 ++++-
src/limit.lisp | 18 ++---
src/testsuite.lisp | 8 +-
src/tlimit.lisp | 193 +++++++++++++++++++++++++++++++++++++++-----
tests/rtest3.mac | 12 ++-
tests/rtest_limit.mac | 4 +-
tests/rtest_limit_extra.mac | 11 ++-
7 files changed, 226 insertions(+), 42 deletions(-)
hooks/post-receive
--
Maxima CAS
|
|
From: <ap...@us...> - 2026-04-20 15:03:50
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, master has been updated
via 5b7282e42965cc12351323d2c900745f0f133b23 (commit)
from 895081d576bd6b73757b98bea3bb7e470b432379 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 5b7282e42965cc12351323d2c900745f0f133b23
Author: Robert Dodier <rob...@so...>
Date: Mon Apr 20 08:03:14 2026 -0700
Revert 895081 (changes to pretty printer display for product(...) expressions).
Need to complete the changes before committing again.
diff --git a/src/displa.lisp b/src/displa.lisp
index 390c3401e..97c9d4fac 100644
--- a/src/displa.lisp
+++ b/src/displa.lisp
@@ -531,7 +531,7 @@
(update-heights height depth)
(return result)))))
-(defun dsumprod (form result d-form sw sh sd)
+(defun dsumprod (form result d-form symbol-w symbol-h symbol-d)
(prog (str to dummy (w 0) (h 0) (d 0) dummy2 (lsum (eq (caar form) '%lsum)))
(setq dummy2 (dimension (caddr form) nil 'mparen 'mequal nil 0)
w width
@@ -548,16 +548,16 @@
(setq dummy (dimension to nil 'mparen 'mparen nil 0))
(unless (checkfit (max w width))
(return (dimension-function form result)))
- (setq dummy2 (cons (cons (- sw) (cons (- (+ sd h)) dummy2)) (cons d-form result)))
- (cond ((> width sw)
- (setq sw 0))
+ (setq dummy2 (cons (cons (- symbol-w) (cons (- (+ symbol-d h)) dummy2)) (cons d-form result)))
+ (cond ((> width symbol-w)
+ (setq symbol-w 0))
(t
- (setq sw (truncate (- sw width) 2)
- width (+ sw width))))
- (setq dummy (cons (cons (- sw w) (cons (+ sh depth) dummy)) dummy2)
+ (setq symbol-w (truncate (- symbol-w width) 2)
+ width (+ symbol-w width))))
+ (setq dummy (cons (cons (- symbol-w w) (cons (+ symbol-h depth) dummy)) dummy2)
w (max w width)
- d (+ sd h d)
- h (+ sh height depth))
+ d (+ symbol-d h d)
+ h (+ symbol-h height depth))
(update-heights h d)
(setq dummy (dimension (cadr form) (cons (list (1+ (- w width)) 0) dummy)
(caar form) rop w right)
@@ -604,7 +604,7 @@
(displa-def %product dim-%product 115.)
(defun dim-%product (form result)
- (dsumprod form result '(d-prodsign) 6 3 1))
+ (dsumprod form result '(d-prodsign) 5 3 1))
(displa-def rat dim-rat "/")
(displa-def %rat dim-rat "/")
-----------------------------------------------------------------------
Summary of changes:
src/displa.lisp | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
hooks/post-receive
--
Maxima CAS
|
|
From: <ap...@us...> - 2026-04-20 04:26:34
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, master has been updated
via 895081d576bd6b73757b98bea3bb7e470b432379 (commit)
from a60464454e29c0276c27de8b5e640553dcad5c33 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 895081d576bd6b73757b98bea3bb7e470b432379
Author: Robert Dodier <rob...@so...>
Date: Sun Apr 19 15:19:23 2026 -0700
Adjust 2d pretty printer Unicode output for 'product(...) expressions.
This is an improvement, in that box('product(...)) is now correct,
but placement of the index bounds and the expression ...
(the "productand", I guess) could still be improved.
Work in progress for SF bug report #4711: "Pretty-printer slightly incorrect output for 'product(...)"
diff --git a/src/displa.lisp b/src/displa.lisp
index 8137e4b5e..390c3401e 100644
--- a/src/displa.lisp
+++ b/src/displa.lisp
@@ -604,7 +604,7 @@
(displa-def %product dim-%product 115.)
(defun dim-%product (form result)
- (dsumprod form result '(d-prodsign) 5 3 1))
+ (dsumprod form result '(d-prodsign) 6 3 1))
(displa-def rat dim-rat "/")
(displa-def %rat dim-rat "/")
-----------------------------------------------------------------------
Summary of changes:
src/displa.lisp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
hooks/post-receive
--
Maxima CAS
|
|
From: rtoy <rt...@us...> - 2026-04-19 14:55:46
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, master has been updated
via a60464454e29c0276c27de8b5e640553dcad5c33 (commit)
via dcbaae4051654ec77364e140a13ddee0ac0cf8da (commit)
from cd4f49448088e330891d1f9103a8ec5c486d3bd6 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
-----------------------------------------------------------------------
Summary of changes:
src/maxima.system | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
hooks/post-receive
--
Maxima CAS
|
|
From: rtoy <rt...@us...> - 2026-04-19 14:51:34
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, bug-4718-simplify-translated-packages has been updated
via a60464454e29c0276c27de8b5e640553dcad5c33 (commit)
from dcbaae4051654ec77364e140a13ddee0ac0cf8da (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit a60464454e29c0276c27de8b5e640553dcad5c33
Author: Raymond Toy <toy...@gm...>
Date: Sun Apr 19 07:50:42 2026 -0700
Add dependencies and move hypergeometric module before integration
diff --git a/src/maxima.system b/src/maxima.system
index 4398c7b74..a7228b244 100644
--- a/src/maxima.system
+++ b/src/maxima.system
@@ -711,11 +711,23 @@
(:file "compar")
(:file "askp")) ;does this belong here?
)
+ (:module hypergeometric :source-pathname ""
+ ;; Simplification and evaluation of hypergeometric functions.
+ :depends-on ("compatibility-macros1" "declarations" "defmfun" "errset" "globals"
+ "miscellaneous" "other-macros" "prerequisites" "utility-macros")
+ :components
+ ((:file "hyp")
+ (:file "hypergeometric")
+ (:file "nfloat"
+ ;; Comment in nfloat says hypergeometric needs to
+ ;; be loaded first.
+ :depends-on ("hypergeometric"))))
(:module integration :source-pathname ""
:depends-on ("globals" "defmfun" "pattern-matching"
"compatibility-macros" "declarations"
"destructuring-let" "errset" "fundamental-macros"
- "prerequisites" "rat-macros" "utility-macros")
+ "prerequisites" "rat-macros" "utility-macros"
+ "hypergeometric")
:components
((:file "sinint")
(:file "sin")
@@ -843,14 +855,6 @@
:components
((:file "pois2")
(:file "pois3")))
- (:module hypergeometric :source-pathname ""
- :components
- ((:file "hyp")
- (:file "hypergeometric")
- (:file "nfloat"
- ;; Comment in nfloat says hypergeometric needs to
- ;; be loaded first.
- :depends-on ("hypergeometric"))))
(:module translated-packages :source-pathname ""
:depends-on ("globals" "maxima-language-compiler-macros"
"compatibility-macros1"
-----------------------------------------------------------------------
Summary of changes:
src/maxima.system | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)
hooks/post-receive
--
Maxima CAS
|
|
From: rtoy <rt...@us...> - 2026-04-19 14:39:34
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, bug-4718-simplify-translated-packages has been created
at dcbaae4051654ec77364e140a13ddee0ac0cf8da (commit)
- Log -----------------------------------------------------------------
commit dcbaae4051654ec77364e140a13ddee0ac0cf8da
Author: Raymond Toy <toy...@gm...>
Date: Sun Apr 19 07:36:57 2026 -0700
Fix #4718: Restructure translated-packages module
Move hypeo.lisp (containing $specint) to the integration module since
specint compute Laplace transforms and the integration module already
contains laplac.lisp for Laplace transforms.
Create a new module hypergeometric that contains hyp.lisp,
hypergeometric.lisp, and nfloat.lisp that are all related to
simplification and evaluation of hypergeometric functions.
diff --git a/src/maxima.system b/src/maxima.system
index 4185402ee..4398c7b74 100644
--- a/src/maxima.system
+++ b/src/maxima.system
@@ -721,7 +721,8 @@
(:file "sin")
(:file "risch")
(:file "irinte")
- (:file "laplac")))
+ (:file "laplac")
+ (:file "hypgeo")))
(:module taylor-series :source-pathname ""
:depends-on ("globals" "defmfun" "compatibility-macros"
"compatibility-macros1" "declarations"
@@ -842,6 +843,14 @@
:components
((:file "pois2")
(:file "pois3")))
+ (:module hypergeometric :source-pathname ""
+ :components
+ ((:file "hyp")
+ (:file "hypergeometric")
+ (:file "nfloat"
+ ;; Comment in nfloat says hypergeometric needs to
+ ;; be loaded first.
+ :depends-on ("hypergeometric"))))
(:module translated-packages :source-pathname ""
:depends-on ("globals" "maxima-language-compiler-macros"
"compatibility-macros1"
@@ -852,13 +861,6 @@
((:file "desoln")
(:file "elim")
(:file "invert")
- (:file "hypgeo")
- (:file "hyp")
- (:file "hypergeometric")
- (:file "nfloat"
- ;; Comment in nfloat says hypergeometric needs to
- ;; be loaded first.
- :depends-on ("hypergeometric"))
(:file "todd-coxeter")
(:file "plot")))
(:module graphics-drivers :source-pathname ""
-----------------------------------------------------------------------
hooks/post-receive
--
Maxima CAS
|
|
From: tomasriker <tom...@us...> - 2026-04-19 13:10:11
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, master has been updated
via cd4f49448088e330891d1f9103a8ec5c486d3bd6 (commit)
from 1c8ff707d81759301ef2c6e89559615393b11285 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit cd4f49448088e330891d1f9103a8ec5c486d3bd6
Author: David Scherfgen <d.s...@go...>
Date: Sun Apr 19 15:09:40 2026 +0200
ARRSTORE: don't allocate more buckets beyond the modulus used by HASHER (32768)
The modulus 32768 has been extracted into a constant +HASHER-MOD+.
This fixes bug #4663.
diff --git a/src/mlisp.lisp b/src/mlisp.lisp
index a63ac34bd..9eb84b2bc 100644
--- a/src/mlisp.lisp
+++ b/src/mlisp.lisp
@@ -1890,8 +1890,12 @@ wrapper for this."
(setf (aref (symbol-array ary) lispsub)
(delete (car hashl1) hashl :count 1 :test #'equal))
(return nil))))
- (if (> (aref (symbol-array ary) 1) (aref (symbol-array ary) 0))
- (arraysize fun (* 2 (aref (symbol-array ary) 0))))
+ (let* ((s-ary (symbol-array ary))
+ (num-buckets (aref s-ary 0))
+ (num-elements (aref s-ary 1)))
+ (when (and (> num-elements num-buckets)
+ (< num-buckets +hasher-mod+))
+ (arraysize fun (min +hasher-mod+ (* 2 num-buckets)))))
r)
((and (eq fun 'mqapply) (or (mxorlistp (setq ary (meval (cadr l)))) (arrayp ary))
(prog2
@@ -1949,10 +1953,13 @@ wrapper for this."
(aexpr (mapply1 (cadr arrfun) subs (cadr arrfun) form))
(a-subr (apply (cadr arrfun) subs)))))
+(defconstant +hasher-mod+ 32768
+ "Modulus used by the HASHER function - must be a power of 2.")
+
(defun hasher (l) ; This is not the best way to write a hasher. But,
(if (null l) ; please don't change this code or you're liable to
0 ; break SAVE files.
- (logand #o77777
+ (logand (1- +hasher-mod+) ; NOTE: Assumes that +hasher-mod+ is 2^n.
(let ((x (car l)))
(cond ((specrepp x)
(merror (intl:gettext "hash function: cannot hash a special expression (CRE, Taylor or Poisson).")))
-----------------------------------------------------------------------
Summary of changes:
src/mlisp.lisp | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
hooks/post-receive
--
Maxima CAS
|
|
From: tomasriker <tom...@us...> - 2026-04-19 09:54:00
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, master has been updated
via 1c8ff707d81759301ef2c6e89559615393b11285 (commit)
from c1946f333903873e05d0bdfc0773af1038511bd9 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 1c8ff707d81759301ef2c6e89559615393b11285
Author: David Scherfgen <d.s...@go...>
Date: Sun Apr 19 11:53:48 2026 +0200
DIRECTORY-CACHED debugging: print every path probed
This facilitates debugging because one can see exactly which directories are
searched by DIRECTORY-CACHED.
diff --git a/src/mload.lisp b/src/mload.lisp
index 22599bdb2..2bcc6a5a4 100644
--- a/src/mload.lisp
+++ b/src/mload.lisp
@@ -1056,6 +1056,7 @@
(not (prefixp *maxima-objdir* dir-ns)))
do
(let ((merged (merge-pathnames query-file dir-path)))
+ (dbg "probe \"~A\"" merged)
(when (file-exists-p merged)
(dbg "found in \"~A\"" dir-path)
(push (truename merged) result))))
-----------------------------------------------------------------------
Summary of changes:
src/mload.lisp | 1 +
1 file changed, 1 insertion(+)
hooks/post-receive
--
Maxima CAS
|
|
From: tomasriker <tom...@us...> - 2026-04-19 09:52:17
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Maxima CAS".
The branch, master has been updated
via c1946f333903873e05d0bdfc0773af1038511bd9 (commit)
via 7151a4678c4f936243734c4b4962d1138b28de1e (commit)
via 8c2a847d514aa88911270451fd622b58bce8e596 (commit)
via b2d3343219ae16fc6e363d96ddd60c5132f21c4c (commit)
from 577daf4284cd5abd8553a650a9cde4e8a2f60965 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit c1946f333903873e05d0bdfc0773af1038511bd9
Author: David Scherfgen <d.s...@go...>
Date: Sun Apr 19 11:51:22 2026 +0200
Prevent foreign binary and internal files from being found by file_search
This commit makes changes to DIRECTORY-CACHED and NEW-FILE-SEARCH that prevent
files within foreign binary directories and within the "test_directory_cache"
directory from being found by file_search.
Previously, left-over binary files (e.g. .fasl files) from previous/incompatible
Maxima/Lisp versions could accidentally be loaded.
For example, an earlier Maxima version could have created the file:
/home/user/.maxima/binary/5_46/sbcl/2_5_3/share/draw/gnuplot.fasl
After upgrading to a new Maxima and SBCL, a new directory is created:
/home/user/.maxima/binary/5_47/sbcl/2_6_3/
But due to the file search logic, Maxima would still try to load the old file,
which isn't compatible any more, leading to an error.
diff --git a/src/mload.lisp b/src/mload.lisp
index f7b078c47..22599bdb2 100644
--- a/src/mload.lisp
+++ b/src/mload.lisp
@@ -732,10 +732,14 @@
:if-does-not-exist :create)
(declare (ignorable stream))))
+(defun test-directory-cached-dir-base ()
+ "Returns the base path of the directory that will be used for tests,
+ which does not depend on the Maxima and Lisp version."
+ (combine-path *maxima-userdir* "test-directory-cached" ""))
+
(defun test-directory-cached-dir ()
"Returns the path of the directory that will be used for tests."
- (combine-path *maxima-userdir*
- "test-directory-cached"
+ (combine-path (test-directory-cached-dir-base)
(maxima-version1)
*maxima-lispname*
(lisp-implementation-version1)))
@@ -1035,11 +1039,23 @@
;; Cache miss! Perform the file search by looping over all
;; directories and testing whether a file with the given name
;; exists in there. Build a list of all files found.
+ ;; Ignore any directories that were created for testing the cache
+ ;; and foreign binary directories (those for other Maxima/Lisp versions).
(dbg "result miss")
- (let (result)
- (dolist (dir dirs)
- (let* ((dir-path (car dir))
- (merged (merge-pathnames query-file dir-path)))
+ (let (result
+ (test-dir-base (test-directory-cached-dir-base))
+ (obj-dir-base (maxima-objdir-base)))
+ (loop
+ for dir in dirs
+ for dir-path = (car dir)
+ for dir-ns = (namestring dir-path)
+ ;; Skip any cache test directories.
+ unless (prefixp test-dir-base dir-ns)
+ ;; Skip foreign binary directories.
+ unless (and (prefixp obj-dir-base dir-ns)
+ (not (prefixp *maxima-objdir* dir-ns)))
+ do
+ (let ((merged (merge-pathnames query-file dir-path)))
(when (file-exists-p merged)
(dbg "found in \"~A\"" dir-path)
(push (truename merged) result))))
@@ -1081,8 +1097,19 @@
(let ((pathnames (directory-cached path mtime-cache)))
(when *debug-new-file-search*
(format *debug-io* "wildpath ~S~%" path))
+ ;; Remove files inside directory cache test directories and
+ ;; foreign binary directories (those for other Maxima/Lisp versions).
+ (let ((test-dir-base (test-directory-cached-dir-base))
+ (obj-dir-base (maxima-objdir-base)))
+ (setf pathnames
+ (remove-if #'(lambda (path)
+ (let ((ns (namestring path)))
+ (or (prefixp test-dir-base ns)
+ (and (prefixp obj-dir-base ns)
+ (not (prefixp *maxima-objdir* ns))))))
+ pathnames)))
(when pathnames
- ;; We MUST sort the results in alphabetical order
+ ;; We MUST sort the results in alphabetical order
;; because that's how the old search paths were
;; sorted.
(setf pathnames (sort pathnames #'string< :key #'namestring))
commit 7151a4678c4f936243734c4b4962d1138b28de1e
Author: David Scherfgen <d.s...@go...>
Date: Sun Apr 19 11:40:50 2026 +0200
PREFIXP utility function checking if a sequence is a prefix of another one
diff --git a/src/utils.lisp b/src/utils.lisp
index db5e585a3..742632355 100644
--- a/src/utils.lisp
+++ b/src/utils.lisp
@@ -135,3 +135,11 @@
nil)
(t
(putprop base val sel))))
+
+(defun prefixp (prefix sequence &key (test #'eql))
+ "Returns T if PREFIX is a prefix of SEQUENCE.
+ Accepts any sequence type and an optional :TEST function (defaults to EQL).
+ E.g. '(1 2) is a prefix of '(1 2 3), and \"hell\" is a prefix of \"hello\".
+ Any sequence is a prefix of itself."
+ (let ((m (mismatch sequence prefix :test test)))
+ (or (not m) (>= m (length prefix)))))
commit 8c2a847d514aa88911270451fd622b58bce8e596
Merge: b2d334321 577daf428
Author: David Scherfgen <d.s...@go...>
Date: Sun Apr 19 10:45:48 2026 +0200
Merge branch 'master' of https://git.code.sf.net/p/maxima/code
commit b2d3343219ae16fc6e363d96ddd60c5132f21c4c
Author: David Scherfgen <d.s...@go...>
Date: Sun Apr 19 10:45:16 2026 +0200
Add MAXIMA-OBJDIR-BASE function to identify the binary storage base directory
Introduce the MAXIMA-OBJDIR-BASE function to calculate the common base
directory where compiled Lisp files (e.g. .fasl) are stored. This is intended
for use in NEW-FILE-SEARCH to filter out binaries from incompatible Maxima or
Lisp versions.
Example for default path: "/home/user/.maxima/binary/5_47post/sbcl/2_6_3"
-> "/home/user/.maxima/binary/"
The function detects whether the user has manually modified $maxima_objdir,
in which case it returns the directory unmodified (with a trailing slash added,
if necessary).
diff --git a/src/init-cl.lisp b/src/init-cl.lisp
index e4eb3a107..5c707884a 100644
--- a/src/init-cl.lisp
+++ b/src/init-cl.lisp
@@ -295,6 +295,9 @@ maxima [options] --batch-string='batch_answers_from_file:false; ...'
(maxima-parse-dirstring maxima-objdir-env)
(concatenate 'string *maxima-userdir* "/binary"))
"/" (maxima-version1) "/" *maxima-lispname* "/" (lisp-implementation-version1)))
+ ;; NOTE: If this format is changed (e.g. by adding more subdirectories),
+ ;; the function MAXIMA-OBJDIR-BASE may have to be adapted,
+ ;; because its job is to strip these subdirectories.
(when maxima-htmldir-env
(setq *maxima-htmldir* (combine-path (maxima-parse-dirstring maxima-htmldir-env) "doc" "info")))
@@ -908,6 +911,21 @@ maxima [options] --batch-string='batch_answers_from_file:false; ...'
"Return a pathname string such that subdirs is a subdirectory of maxima_objdir"
(apply #'combine-path *maxima-objdir* subdirs))
+(defun maxima-objdir-base ()
+ "Return the Maxima object directory stripped of the subdirectories
+ that are specific to the Maxima version, Lisp implementation and Lisp version.
+ If the user has overridden $maxima_objdir manually, return the directory itself.
+ A trailing slash is always added, if necessary.
+ Example for default path: '/home/user/.maxima/binary/5_47post/sbcl/2_6_3'
+ -> '/home/user/.maxima/binary/'"
+ (let ((path (pathname (combine-path *maxima-objdir* "")))) ; ensure trailing slash
+ (if (string= *maxima-objdir* (gethash '$maxima_objdir *variable-initial-values*))
+ ;; *MAXIMA-OBJDIR* has its default value: strip the last 3 subdirectories
+ (namestring (make-pathname :directory (butlast (pathname-directory path) 3)
+ :defaults path))
+ ;; User override: return the path as-is (with ensured trailing slash)
+ (namestring path))))
+
(defun maxima-load-pathname-directory ()
"Return the directory part of *load-pathname*."
(let ((path *load-pathname*))
-----------------------------------------------------------------------
Summary of changes:
src/init-cl.lisp | 18 ++++++++++++++++++
src/mload.lisp | 41 ++++++++++++++++++++++++++++++++++-------
src/utils.lisp | 8 ++++++++
3 files changed, 60 insertions(+), 7 deletions(-)
hooks/post-receive
--
Maxima CAS
|