math exception handling

Started by nigelbrown, November 16, 2003, 05:21:16 PM

Previous topic - Next topic

nigelbrown

Hi all,

I've been looking into the math side of newlisp (that's my current interest in it) but

I don't see specified how newlisp handles floating point overflow exceptions.

From nl-math.c addition (for example) is done by:

CELL * floatOp(CELL * params, int operand)

{

double number;

double result;

double fltNum;

long intNum;



params = getFloat(params, &result);

if(params == nilCell)

   {

   if(operand == OP_SUBTRACT)

      result = - result;

   }

while(params != nilCell)

   {

   params = getFloat(params, &number);

   switch(operand)

      {

      case OP_ADD:            result += number; break



and early in the file there seems to be a "do nothing" exception handling established (fair enough default) viz:



#ifdef __BORLANDC__

int _matherr(struct _exception *e) {return 0;};

#endif



Now - causing an addition overflow crashes newlisp eg:



C:newlisp>newlisp

newLISP v7.3.3 Copyright (c) 2003 Lutz Mueller. All rights reserved.



> 1.7976931348623157E308

1.797693135e+308

> (add 1.7976931348623157E308 0.1e308)



C:newlisp>



I don't know what happens on linux. Can math exceptions be caught/handled in win32 newlisp? Could it gracefully die with an

error message? I don't have documentation on how

Borlands BCC55 uses matherr.

Regards

Nigel

Lutz

#1
In newLISP math exceptions are best handled on the UNIX compiles (LINUX, FreeBSD) on these platforms you would get:



 (add 1.7976931348623157E308 0.1e308)  => inf



without crashing handled well by the GCC compiler on these platforms.



When compiling with CYGWIN (UNIX simulation on Win32) you get:



 (add 1.7976931348623157E308 0.1e308) => Inf



but BCC on Win32 crashes, on the previous example (seems to be a bug in BCC libraries), but produces +INF on other overflow conditions, i.e 1e1000 = > +INF



 (sqrt -1) => NaN



works well on all platforms and there is a function NaN? in newLISP to test for it.



(/ 123 0) => 'division by zero'



throws a 'division by 0' error on all platforms (trapped by newLISP)



For Math, LINUX or another UNIX compiles using GCC is the preferred way to go. If you want to use Windows, the best way is to compile newLISP for CYGWIN, it also gives you the possibility (like on UNIX) to treat network sockets as filehandles.



Another possibility is, to have newLISP run on a remote UNIX machine and connect to it from a Windows machine via the network. This works with both, the console version of newLISP and the newLISP-tk frontend, which also can connect to a remote running newLISP. Both alternatives are documented in the manuals.



By the way: 5.e-1, 5e-1,  .5e-1 etc. are now all working fine on 7.3.3.



Lutz

nigelbrown

#2
Hi Lutz,

Thanks for the 1.e-1 stuff - I'm using it already.

Its interesting that compiling

int main()

{ double d;

  d = 1e308 + 1e308;

   printf("number:%g",d);

  return 0;

}

with the borland compiler and running gives:

C:newlispNEWLIS~2>c:BorlandBCC55Binmake testmath.c

MAKE Version 5.2  Copyright (c) 1987, 2000 Borland



C:newlispNEWLIS~2>c:BorlandBCC55Binbcc32.exe testmath.c

Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland

testmath.c:

Warning W8065 testmath.c 4: Call to function 'printf' with no prototype in func

ion main

Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland



C:newlispNEWLIS~2>testmath

number:+INF

C:newlispNEWLIS~2>



That is +INF is returned - perhaps the error is in += as the code does:

      case OP_ADD:            result += number; break;



but

I just tested:

int main()

{ double d;

  d = 1e308 ;

  d += 1e308;

   printf("number:%g",d);

  return 0;

}

which throws a floating point overflow error and terminates the program.



That suggests that

case OP_ADD:            result = result + number; break;

should work

but when I make that change (I think) to n-math.c I still get an error -

perhaps somewhere else?

I'm using XP Pro.

Regards

Nigel

nigelbrown

#3
Please excuse some of the oversights in my last post -

a compile would replace = 1e308 + 1e308 with aconstant assignment,

not an addition -

I'll look further at it.

Regards

Nigel