Page 1 of 1

NAN revisited, a crossover from old to new.

PostPosted: Sun Oct 13, 2002 3:11 pm
by CaveGuy
I posted the following on the old forun last night. Now I have figuring out case sensitivity problem I was haveing with loging in here. I will repeat myself here in the New forum.

Here we go on an adventure in NAN :)

Fresh Start:
newLISP v6.5.23-win32 Copyright (c) 1993-2002 Lutz Mueller. All rights reserved


> (set '+NAN (sqrt -1))

sqrt: DOMAIN error
+NAN
> (NaN? +NAN)
true
> (set 'X +NAN)
+NAN
> (NaN? X)
true
> (save "loadtest.lsp")
true

LoadTest contains:
(set '+NAN +NAN)

(set 'X +NAN)

Fresh Start:
newLISP v6.5.23-win32 Copyright (c) 1993-2002 Lutz Mueller. All rights reserved.


> (load "test")
true
> (symbols)

(! != % & * + +NAN - / < << <= = > >= >> ? MAIN NaN? X ^ abs ...... | ~)
> +NAN
nil
> (NaN? +NAN)

Value expected in function NaN?

> X
nil
> (NaN? X)

Value expected in function NaN?

>



Edit LoadTest file:
;(set '+NAN +NAN) Don't mess with +NAN !

(set 'X +NAN)

Fresh Start:
newLISP v6.5.23-win32 Copyright (c) 1993-2002 Lutz Mueller. All rights reserved


> (set '+NAN (sqrt -1))

sqrt: DOMAIN error
+NAN
> (NaN? +NAN)
true
> (load "loadtest.lsp")
true
> (NaN? X)
true
>

If +NAN was a constant, then its inference
could be carried between states using (save)(load)
without having to force an seemingly untrapable error to generating one.

> (catch (set '+NAN (sqrt -1)) 'result)

sqrt: DOMAIN error
true
>

How can I generate a +NaN that I can test for with NAN?
without fireing off the error handler ?

Why you ask?

I am using the +NAN as a place holding excluder.

The Current Doc states:

syntax: (NaN? number )

Tests if the result of floating point math operation is a NaN.
Certain floating point operations return a special IEE 754 number
format called a NaN for 'Not a Number'.

example:

(set 'x (sqrt -1) => NaN
(add x 123) => NaN
(> x 0) => nil
(<= x 0) => nil
(= x x) => nil
(NaN? x) => true

Note that all floating point arithmetik operations with a NaN will
yield a NaN. All comparisons with NaN will return nil,
even if comparing NaN to itself.

While we are on the subject of the fact that "Certain floating point operations
return a special IEE 754 number format"

How about Pi ? Having access to the constant for Pi would be great !!!
A test (Pi? number ) would be very nice also. Problem is people trying
(Pi? 3.1416)

Final Note: a (div 1 0) should return a +NAN and not return to the OS !


Thanks, now I feel better :)
Keep up the good work.

Thanks
(bob)
bob@bradlee.org

PostPosted: Sun Oct 13, 2002 3:33 pm
by Lutz
there is no symbol for NaN in newLISP (and in any other programming language I know), '+NaN' is just the way the C-library, with which newLISP was compiled, formats NaN results. You can test a coputing result for NaN'nes, but a comparison of two expressions resulting in NaN will always give 'nil'. This last fact is illustrates the reason, that programming languages don't contain a symbol for NaN.

NaN is not a specific value of something, but rather a concept flagging a result as no computable.


+NaN is just a new symbol you created and has the value nil. The parser takes the '+' and ' -' minus characters only as number prefixes when followed by a number, else a space must be present. NaN is "Not a Number".


Lutz

My Last Justification for +NaN

PostPosted: Mon Oct 14, 2002 12:58 am
by CaveGuy
In my example +NAN is in fact just a symbol like any other symbol, only it has been (set) to a NaN, the return value generated by the sqrt: DOMAIN error.

I use '+NAN as a reference symbol to the actual NaN in memory.
I can just as easily refer to it as 'X.

In fact +NAN does in have a value. It is not a string, handle, structure, integer ... it is a non-numeric value whose binary pattern represent the results of an invalid operation some where in the floating point specification.
By ignoring NaNs a stack based numeric processor like the 8087 could ignore intermediate calculations that resulted from previous errors.

I understand that it can only be tested for by using
(NaN?) that is to be expected. The fact that I can
bind a symbol to an NaN once it existence proves the
argument for assignability.

> (set '+NAN (sqrt -1))

sqrt: DOMAIN error ;<---- this is my nemeses
+NAN ; give be a way to catch this error
> (NaN? +NAN) ; and I will go away for a while :)
true
> (set 'X +NAN)
+NAN
> (NaN? X)
true
>

We all use nil as a third state -1 0 1 True False Nil(unknown).
We use (list?) and Nil to represent knowledge or lack of it.
NaNs can be thought of as a mathematical nil.
The reason we have NaNs is to avoid floating point errors when dealing
with unknown values that resulted from previous operations.

We can use +NaN to replace all occurrence of 0.0 in a list to avoid a dreaded divide by zero error.

-0.999 +NAN +0.999 works very nicely in situations where a floating point error or (div x 0.0) will take the system down.

The use of NaN as a data type dates back to the first MASM and PL/M code that accessed the 8087 when Intel introduced it. At the time some said that existence of the NaN would eliminate all divide by zero exceptions in the future, it was the 80's and we had it all figured out, back then :)

Somewhere along the line the NaN became a secret weapon. Most software that exploited NaNs were/are locked deep in NDAs hiding both National and Industrial secrets and the NaN fell from grace. NaN logic is a 900 series topic that is seldom taught because for the most part it's use has been limited to stack based numerical recursion.

Base constants: true false nil NaN and mabe Pi.

Pi is righ next to NaN in the math co-processor and
is at the root of all polar mapping.

Back to my Rat Killen...

PostPosted: Mon Oct 14, 2002 3:00 am
by Lutz
Thanks Bob for your bits about NaN, that was very interesting, I wonder if there is any literature you could point us too, to learn more about how to use NaN etc..

(div 1 0) => Inf ;; hangs the Win32 version

is broken on the Win32 version. When compiled with GCC under Cygwin or Linux is gives you: 'Inf'

This 'Inf' behaves a little bit different than NaN, more like a number :) so:

(set 'x (div 1 0)) => Inf
(set 'y (div 1 0)) => Inf

(= x y) => true

but ?!?:

(+ x 1 ) => 1

But Inf is a total different animal, and at this moment I am just returning to the user, whatever the GCC libraries give me back. And as mentioned, it is broken on the Win32 version and I am not sure at this moment what we can or should do about it. Also just like with NaN 'Inf' is not a newLISP symbol, but unlike NaN, which you have to test using the NaN? newLISP function, you can test for 'Inf' using the equality operator.

But back to NaN. As you describe in your posting all arithmetik operations on NaN result in NaN and all comparisonas in 'nil' (which is also newLISP's false). I modeled this after Java's behavior, which is supposed to be pretty IEEE conformant when comes to floating point crazyness.

The message "sqrt: DOMAIN error", your are observing comes from the BORLAND C++ libraries, and is not present when compiled with GCC under Cygwin or Linux. This is why 'catch' will not work for you, because newLISP didn't observe any error.

There is surfacing all kinds of stuff over time since we have a native Win32 version of newLISP again. I.e. the 'date' function crashes with small values and sockets don't work with functions taking file handles. If you can, compile newLISP under Cygwin when on Windows and you will have more consistent behaviour to newLISP compiled inder UNIXes (UNICES).

About Pi. I just use:

(set 'Pi (mul (acos 0) 2)) => 3.41592564

at the beginning of a program, where I use Pi a lot. Interesting detail, you are mentioning, that Pi is burried in the math coprocessor, I didn't know that and guess it makes a lot of sence to build it into it.

Anyway, very welcome to our group of newLISP fans ...

Lutz

+NAN

PostPosted: Mon Oct 14, 2002 5:11 am
by CaveGuy
Pi is stored as an 80 bit float in the co-processor as a
constant. Your solution returns a 64 bit float If we stay in this solar system then polar error is not too bad :) Just Kidding.

I only need a symbol that has been set to +NAN to still
be a NAN after a save and load.
(save) saves it out as (set 'x +NaN)
(load) (sets 'x nil)

Makeing +NaN a static symbol pointing to a static NaN
would allow it to be restored.

Till later ...
Bob

PostPosted: Mon Oct 14, 2002 3:44 pm
by Lutz
I have it working now on the cygwin/unix versions:

(set '+NaN (sqrt -1))
+NaN => +NaN

(= +NaN (sqrt -1)) => true

but still have problems on the BORLAND C++ compiled Win32, crashing
under certain cirumstances.

Lutz

PostPosted: Mon Oct 14, 2002 6:26 pm
by Lutz
NaN stuff now also working on Win32 see version 6.5.26 in:

http://newlisp.org/download/development/

and the CHANGES file in the distribution

Lutz

+NAN as a constant

PostPosted: Mon Oct 14, 2002 8:15 pm
by CaveGuy
newLISP v6.5.26-win32 Copyright (c) 1993-2002 Lutz Mueller. All rights reserved.

> (symbols) => no observed +NAN on the heap
> +NAN => nil
> (NaN? +NAN) => Value expected in function NaN?

; Now I force one into exsistance

> (set '+NAN (sqrt -1)) => sqrt: DOMAIN error returns: +NAN

(symbols) => wa-la we got +NAN on the heap
; now there will be joy in mudville

> +NAN => +NAN
> (set 'q +NAN) => +NAN
> (NaN? q) => true
>

Like nil there should be only one value for +NAN
and all symbols point to it. If you save a +NAN a maie it constant, then the error does not have to occure to generate the first +NAN value to link to.

Close, real close, once "created" the new +NAN responds nicely.

Other than that, It looks great, thanks for the div by zero fix for winblows. Having forceing a +NaN as 0
in integer operations works for me nicely. I may start using it for Integer Values to be Ignored in a sequence :)

Till later ...

PostPosted: Mon Oct 14, 2002 8:46 pm
by Lutz
At this moment there is no general mechanism in place to protect symbols from beeing changed. The mechanism used for 'nil and 'true wouldn't be suited. So at this moment constants have to be set initially and could be put into 'init.lsp' (in the start up directory of Win32 newLISP or in /usr/share/newlisp on Unix OS's).

Perhaps we will have some protection mechanism in the future or we could simply have a 'constant' primitive:

(constant '+NaN (sqrt -1))
(constant 'Pi (mul 2 (acos 0)))

etc.

Lutz

How about

PostPosted: Mon Oct 14, 2002 9:32 pm
by CaveGuy
How about a new subber (+NaN) that performs a (sqrt -1) function internally and returns +NAN without the error.
The error is the only real problem, now.

I have not tried it as a CGI yet but I am sure it will go boom when I do ... I will give it a test late tonight.

I dont care about Pi it is easily worked around. But the
error is un-trapable.

Got to run...

PostPosted: Mon Oct 14, 2002 10:30 pm
by Lutz
You could put:

(define (+NaN) (sqrt -1)) ;; make new function retruning a NaN

In your initialization file (init.lsp) , or just put:

(set '+NaN (sqrt -1))

in your initialization file.

Then after startup of newLISP +NaN will return +NaN.

Lutz

ps: just finished a new function 'constant' for protecting symbols to define constants, this will go into a new development version by the end of this week.

CGI examples of the problem.

PostPosted: Wed Oct 16, 2002 7:11 pm
by CaveGuy
Been there done that.....

I have set up a CGI test so you can see my problem. "LSP" files are evaluated by your latest greatest, and "LISP" files are processed by the last known stable version before we started messing with it.

<center>
<A ref="http://autocode.com/run/nan-1.lsp">"
http://autocode.com/run/nan-1.lsp"</a>

and

<A ref="http://autocode.com/run/nan-1.lisp">"
http://autocode.com/run/nan-1.lisp"</a>

If you want/need FTP access for testing for your own, please contact me off-list.

Here are links to my first test using both.

<A ref="http://autocode.com/run/nan-test.lsp">"
http://autocode.com/run/nan-test.lsp"</a>

and

<A ref="http://autocode.com/run/nan-test.lisp">"
http://autocode.com/run/nan-test.lisp"</a>

Please believe me, when this works, I will provide you
examples.

Back to my Rat Killen....

PostPosted: Wed Oct 16, 2002 9:43 pm
by Lutz
just to sum up where we are so far with NaN, and what's pending:

(1) we can now create a symbol containing the NaN value:
(set '+NaN (sqrt -1))

when doing this, the error message "sqrt: DOMAIN error" will occur only on the native Win32 version, and I have no way to suppress it (some body knows?). I guess this is a problem for you when doing CGI, where all STDOUT goes back to the client browser. Other than suggesting to use the Cygwin version on Windows, I don't have a solution at the moment. There must be a way to surpress this message. Anybody out there with Borland C++ documentation???

on Cygwin and UNIXs there is no such message.

(2) all integer operations: + 0 / * take NaN as a zero
this seems to work on all versions.

(3) Divisions by zero cause a newLISP "Math exception" on all versions using integer operators and floating operators. This seems to work on all versions.

(4) all floating point ops: div mul add sub produce NaN when one of the arguments is NaN. This works on Cygwin and UNIX's but produces a Math exception error with 'div' on the native Win32 version.

(5) when doing
NaN? => NaN? <407E08>

NaN? is a builtin primitive in newLISP, evaluating a primitive by itself will ebaluate to itself and print its's name and hexadecimal run address. This is intended behaviour for all builtin primitives.

To sum it up: my understanding is, that the only two things to be fixed is the (div 3.14 +NaN) bug in point (4) and surpression of the "DOMAIN error" message in Win32 in point (1), everything else is fine.

I think (4) I can do pretty quickly, for (1) I wouldn't know, how to do it, at the moment.

Lutz

PS: no rats or any other animals will be killed sqashing this bug.

Yet One more thought :)

PostPosted: Wed Oct 16, 2002 10:01 pm
by CaveGuy
Simple Answer: Yes and Yes :)

Please Understand the last "C" project I personaly coded was many years ago. What version of Borland
are you using I WILL locate a copy. One workaround
that comes to mind is to force the error early.

In NewLISP internal init code. redirtect stdio to null,
do a (sqrt -1), store the return value, and put stdio
back. Now by the time it gets to me at the application level, the NAN value has already been forced and the
output suppressed :)

I have a "C" programmer in Chicago I work with, If you do not mind I will have him take a hack at the problem.

Till later
Bob

PostPosted: Wed Oct 16, 2002 10:30 pm
by Lutz
I am using the BCC32 version 5.5.1 from Borland. It is a free compiler available on their website. I used to work with Borland C++ a long time ago, and I remember there was a way to redirect math exceptions to your own exception handler (sort of like signals in UNIX). That would be the 'right' way to do it. But any other 'hack' is welcome as long as it works :)

Lutz

PostPosted: Thu Oct 17, 2002 1:39 am
by Lutz
Found docs at borland.com. Problem is fixed, see announcement in News section and new files at:

http://nuevatec.com/download/development/

Lutz

There is Joy in Mudville Tonight

PostPosted: Thu Oct 17, 2002 2:24 am
by CaveGuy
Thanks !!! I updated online test and it passed with flying colors :) ATABoy ......

Spoke a bit too soon :(

PostPosted: Thu Oct 17, 2002 3:28 pm
by CaveGuy
One more little problem with NaN :(

> (set 'X nil)
nil
> (NaN? 'X)

Value expected in function NaN?

>

I would have expected a return of nil, I will add it to the
previous online test.

PostPosted: Thu Oct 17, 2002 5:02 pm
by Lutz
Their shouldn't be a quote before the X, you would check the symbol not the contents. But also without the qote it will give the error message because NaN? at this moment is only taking float type arguments, but this is easy to change, look for 6.5.28 in a short moment.

Lutz

PostPosted: Thu Oct 17, 2002 5:23 pm
by Lutz
turns out that, NaN? in other languages i.e. Java, C only takes floats, which kind of makes sense, because NaN is rather a subtype of float, than a type by itself. It's like you have a function 'biggerTen?' which checks numbers for beeing bigger than 10. You also would expect this function to error when given arguments, which are not numbers.

So I feel reluctant to change this.

Lutz

+NAN the noun Vs. NaN? the Verb

PostPosted: Thu Oct 17, 2002 10:33 pm
by CaveGuy
Promoting +NAN to the state of being a noun in NewLISP
was truely a big leep in logic :)

Fixing the verb NaN? to be consistent with the other XXX?
functions completes the puzzle.

NaN? should return True or False based exclusively on NaNness and nothing else.

All the other (xxxx? tests operate this way.

The fact that NaNness is the numeric anti-nil. IT no longer
wishes to be confused with it and it's evil twin the all logical nil.

The fact that the birth of a new AI is in your hands,
should not affect your decision in any way :)

And if you are asking. WHY ME ?
You started it with NaN? I have wanted a numeric nil for years.

I appreciate the numerous leeps of logic involved in evolution of newLISP as a language. LISP, Scheme, and TK.

I know nothing about TK, which will make codeing the user interface, a real adventure. and the start of a new thread and a new example or three :)

Thanks again, it has been fun ...
Bob

PostPosted: Fri Oct 18, 2002 12:06 am
by Lutz
How about a new +NaN? function pronounced: "improved NaN?"

(define (+NaN? x) (if (float? x) (NaN? x) nil)) ;;-)

but seriously, I wonder what everybody else thinks about this topic?

Anybody out there with an opinion about NaN? !?!

About TK, I am not an expert here, just supplied a workable interface to use a very popular and platformindependent way to do GUI's.

What is missing here would be a layer in newLISP providing a more LISPier way of doing GUI stuff. Personally I am more into Web GUIs and haven't thought of providing it myself.


Lutz

PostPosted: Wed Oct 23, 2002 2:27 pm
by eddier
While we are at it what about infinity (both the + and the -). Although I admit, in Complex Analysis +inf and -inf are the same thing.

The rules for using inf are in every college calculus book.

About GUIs.

I had to write a database front-end for NSLDS (financial aid stuff). I gave up on newlisp-tk, java, and wxPython and just used the newlisp httpd server and wrote a cgi in newlisp to enter data. The cgi verifys data entry and exports it to fixed record format for the Government and took half of the work required to do a full blown GUI.

Eddie

PostPosted: Wed Oct 23, 2002 4:41 pm
by Lutz
'Inf' is still part of the game on Linux and Cygwin and is returned from the GCC libraries and passed to newLISP. But on the next released version division by zero will cause a newLISP Math error in all versions and will not return Inf anymore. But in other cases Inf is still returned.

I think the NaN situation is pretty much hashed out with CaveGuy's help, but on Inf I just rely on the smartness of the underlying 'C' libraries until further notice.

That application you are describing pretty much sums up what I think about todays GUI app. writing: 99% of GUIs can be written for a Web Browser. When hosting locally just use the newLISP httpd as a very slim webserver.

I think GUIs fabricated outside of Browsers only have a very special niche today, like mouse intense graphics stuff and certain realtime stuff. The nice thing about doing Browser/CGI GUIs is, that

(1) at the same time you make an application which can be distributed/run over the Internet.

(2) parts of your application can be replaced, redesigned, because of open standards, i.e. throw in a different webserver, or interface with other web/CGI system, which may/or not be written in newLISP.

(3) If well designed, big parts of the system can be maintained without or very little newLISP knowledge.

I think the time will come where we will see new intents to bring real-time stuff and interactive graphics to the browser. Java was pretty good at that but didn't caught on, other solutions out there are propietary.

Lutz