- labels: --> Lisp Core
sort([1,2,3,1.0,2.0,3.0,1.0b0,2.0b0,3.0b0,3/2,5/2])
=> [1,1.0,3/2,2,2.0,5/2,3,3.0,1.0B0,2.0B0,3.0B0]
that is, bfloats sort after all other numbers (integers,
floats, and rats) regardless of their magnitude. I realize
that orderlessp does not and cannot in general sort by
magnitude, and I also realize that sort takes a predicate
as a second argument (e.g. "<"), but in the case of
explicit numbers, I think it would be better (principle of
least surprise) if it sorted strictly by magnitude.
Symbolic constants like %E and INF are a harder case.
Currently, they sort after numbers and before variables
and alphabetically among themselves:
sort([1,5,%e,%pi,%phi,%gamma,inf,minf]) =>
[1,5,%E,%GAMMA,%PHI,%PI,INF,MINF]
We could sort them by magnitude, giving
[MINF,%GAMMA,1,%PHI,%E,%PI,5,INF]
But the user can always change the value of a *user-
defined* "constant", if not a system-defined constant.
This might lead to anomalies.
My suggested solution: sort system-defined constants
by magnitude (not %i of course), but not user-defined
constants (by the time a user understands user-defined
constants, he/she is no longer a beginner, and can deal
with the surprise above).
The basic problem here is that "constant" means two
different things: 1) a pseudo-variable such that diff(v)=0;
2) a mathematical constant defined for all time.
Robert Dodier
2006-07-04
Dieter Kaiser
2010-03-13
The following function sorts all constant expressions, e.g. numbers, symbolic constants, or expressions which evaluate to a constant by magnitude.
;; 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.
(defun $order_by_magnitude (a b)
(let (sgn)
(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) (great b a))
(t nil)))
((or (constp a) (member a '($inf $minf))) t)
((or (constp b) (member b '($inf $minf))) nil)
(t (great b a)))))
With this function we get the desired order by magnitude:
(%i10) sort([1,2,3,1.0,2.0,3.0,1.0b0,2.0b0,3.0b0,3/2,5/2],order_by_magnitude);
(%o10) [1,1.0,1.0b0,3/2,2,2.0,2.0b0,5/2,3,3.0,3.0b0]
(%i12) sort([1,5,%e,%pi,%phi,%gamma,inf,minf],order_by_magnitude);
(%o12) [minf,%gamma,1,%phi,%e,%pi,5,inf]
Constant expressions are ordered by magnitude too:
(%i14) sort([0,1,2,3,10,sin(1),%e^2],order_by_magnitude);
(%o14) [0,sin(1),1,2,3,%e^2,10]
Expression which are not constant follow in the order of great:
(%i17) sort([3,10,sin(1),%e^2,x,y,2*x],order_by_magnitude);
(%o17) [sin(1),3,%e^2,10,x,2*x,y]
With this small test function the desired order by magnitude is not the default, but is possible for the user to get it.
Dieter Kaiser
Dieter Kaiser
2010-03-19
Dieter Kaiser
2010-03-19
A predicate function $ordermagnitudep has been added in simp.lisp revision 1.106. $ordermagnitudep gives a total order like $orderlessp and $ordergreatp The user can sort a list by magnitude. This is not the default.
Closing this bug report as fixed.
Dieter Kaiser