Re: +-Inf and NaN
Henry Baker <[email protected]> Fri, 23 Feb 2024 16:16:04 +0000
| Newsgroups | gmane.comp.mathematics.maxima.general,gmane.lisp.gcl.devel |
|---|---|
| Message-ID | <[email protected]> |
Re: Lisp arithmetic should be compatible with IEEE float arithmeticFor various interpretations of 'float' and/or 'arithmetic' ?There was a reason why Maclisp used a separate function namefor float arithmetic functions, and it wasn't just to speedup float arithmetic.The real reason is that *floats don't adhere to standard algebraic axioms*.1. Float addition isn't associative.2. Float addition isn't necessarily commutative -- e.g., when utilizingaccumulation HW.3. All the weirdnesses of NaN's.When President Abraham Lincoln was asked "How many legs does a dog have,if you assume that its tail is a leg?", he answered: "Four. Calling atail a leg doesn't make it one."I'd like to propose "Lincoln's Criterion" for naming (generic/overloaded)functions:"+" has to be commutative and associative."*" has to be commutative and associative and distribute over "+".I.e., we're talking about a commutative ring with identities at thevery least, if nota field.Etc., etc.Float arithmetic needs to utilize a *different* symbol, since we're notcalling tails legs.In particular, standard "=" needs to be an *equivalence relation*, whichmeanstransitivity, among other things, so floating point needs its ownbrain-damaged 'equality' predicate -- perhaps IEEE-= ?BTW, many other languages are far worse that Common Lisp in this regard:somelanguages use "+" for string concatenation.Languages like Rust with heavy duty higher order typing are often forcedto be more Lincoln-like, due to their relatively deep knowledge of algebrain their optimization routines.P.S. The log function 'ln' requires a complex field in order to be a"Lincoln log". :-)(Sorry; couldn't resist!) -----Original Message----- From: Raymond Toy <[email protected]> Sent: Feb 21, 2024 10:26 AM To: Stavros Macrakis <[email protected]> Cc: <[email protected]>, Richard Fateman <[email protected]>, Robert Dodier <[email protected]>, <[email protected]> Subject: Re: [Maxima-discuss] +-Inf and NaN On Wed, Feb 21, 2024 at 8:57 AM Stavros Macrakis <[email protected] (mailto:[email protected])> wrote: Lisp arithmetic should be compatible with IEEE float arithmetic. I wholeheartedly agree with this. This is what the hardware does and we shouldn't needlessly deviate from that. NaN is an important part of preventing numeric calculations from giving incorrect results. Not quite sure what you mean by this because NaN is, in a sense, an incorrect result because we couldn't represent what was asked, like 0d0/0d0 or inf-inf. Optimizing away (= x x) where x are of undeclared type seems like an extremely minor gain. As for most-positive-long-float, I am fine with interpreting that as most-positive-long-finite-float. Same. On Wed, Feb 21, 2024 at 10:54 AM Camm Maguire <[email protected] (mailto:[email protected])> wrote: Greetings, and thanks for your feedback! Raymond Toy <[email protected] (mailto:[email protected])> writes: > When a is a floating-point number (= a a) should not be optimized to > T. Likewise (/= a a) should not be optimized to NIL. I'm pretty sure > IEEE754 says that NaN is never = to itself or another NaN or any other > number. Why not? I agree the 'C' IEEE operator of similar name ('==') should be left untouched, but the spec for common-lisp::= clearly implies that the *same* NaN should be '= to itself, and even that different boxed versions of the same bit patterns should be. I am suggesting that (/= a a) not be a NaN detector, but to provide some other means (described below). I agree on 'staying close to the hardware', and one could just as well say who cares on a practical violation of the spec. In general I am sympathetic to such a point of view, but here it seems unnecessary. Lisp after all is just a bunch of hardware instructions with optional type checking layered on top :-). #'car on a long-float should trigger an error, and does at certain safety levels, but compile at safety 0, and one gets the 'hardware' car which will return a value however dubious it may be. The same could be the case for '=. Say NaN was boxed with identical layout to a long-float, but with a different type-word denoting something orthogonal to 'number, say 'ieee-special-64 or some such. '= will then signal an error on nan input, except when compiled at safety 0, in which case the NaN can be read as before in boxed or unboxed form. The compiler would then simplify '= to t on equivalent bindings, and we could use #'si::isnan or even (typep nan 'ieee-special-64) as a detector. > > We also have the following charming behavior: > > (typep nan 'long-float) ->t > (typep nan '(long-float 0) ->nil > (typep nan '(long-float * 0)) ->nil > (typep nan '(or (long-float 0) (long-float * 0))) ->nil > > but the first and last types are of course identical. > > Isn't the last one a bug? Should the compiler convert (or (long-float > 0) (long-float * 0)) to just long-float? > I don't think so. (typep a '(or b c)) == (or (typep a b) (typep a c)) > I'm not sure what the second and third cases returning nil really > means in practice. I think even if you declare a function as only > taking and returning (long-float 0), you can have operations return > NaN, even if the inputs are non-negative floats. > It means that NaN does not fit into a total ordering scheme of say long-floats, and the type explicitly recognizes and denotes ordered subsets. > If NaN was truly 'not a number', the numerical functions would trigger > an error on input only when compiled with safety, and might be arranged > > I think I would defer to whatever the HW does and the floating point > traps that are enabled. If the invalid trap is enabled, then we get > errors. If the invalid trap is disabled, NaN gets returned. > I think we can have our cacke and eat it too. We can still compile at safety 0 and proceed with errors optionally triggered only when setting FPE traps. But when interpreted or compiled with safety, standard type errors would be triggered. > The subject also mentions +/= inf. Did you forget to mention issues > with infinities? > I am much less bothered by these, though they do make most-positive-long-float meaningless. They are in fact quite useful in bounds checking arithmetic in the compiler. Maybe most-positive-long-float == +inf? Can anyone without too much effort summarize how other lisps handle this? Can one access/manipulate nan at the lisp prompt level? Take care, > Take care, > -- > Camm Maguire [email protected] (mailto:[email protected]) > ========================================================================== > "The earth is but one country, and mankind its citizens." -- Baha'u'llah -- Camm Maguire [email protected] (mailto:[email protected]) ========================================================================== "The earth is but one country, and mankind its citizens." -- Baha'u'llah -- Ray _______________________________________________ Maxima-discuss mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/maxima-discuss