#274 orderlessp of bfloat, %e, and inf

closed
nobody
Lisp Core (471)
5
2010-03-19
2003-03-26
Stavros Macrakis
No

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.

Discussion

  • Robert Dodier
    Robert Dodier
    2006-07-04

    • labels: --> Lisp Core
     
  • Dieter Kaiser
    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
    Dieter Kaiser
    2010-03-19

    • status: open --> closed
     
  • Dieter Kaiser
    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