From owner-freebsd-questions Wed Feb 18 09:16:15 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id JAA16946 for freebsd-questions-outgoing; Wed, 18 Feb 1998 09:16:15 -0800 (PST) (envelope-from owner-freebsd-questions@FreeBSD.ORG) Received: from penguin.wise.edt.ericsson.se (penguin-ext.wise.edt.ericsson.se [194.237.142.5]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id JAA16845 for ; Wed, 18 Feb 1998 09:15:59 -0800 (PST) (envelope-from kent@erlang.ericsson.se) Received: from erlang (erlang.ericsson.se [147.214.36.16]) by penguin.wise.edt.ericsson.se (8.7.5/8.7.3/glacier-1.12) with SMTP id SAA27724; Wed, 18 Feb 1998 18:15:46 +0100 (MET) Received: from localhost by erlang (SMI-8.6/SMI-SVR4) id SAA21547; Wed, 18 Feb 1998 18:15:42 +0100 To: bartol@salk.edu Cc: freebsd-questions@FreeBSD.ORG Cc: kent@erlang.ericsson.se Subject: Re: IEEE Floating Point question: Inf and NaN (fwd) Reply-To: kent@erlang.ericsson.se In-Reply-To: Your message of "Tue, 3 Feb 1998 09:07:00 -0800 (PST)" References: X-Mailer: Mew version 1.92.4 on Emacs 19.34 X-URL: http://www.ericsson.se/erlang Mime-Version: 1.0 Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-Id: <19980218181739G.kent@erlang.ericsson.se> Date: Wed, 18 Feb 1998 18:17:39 +0100 From: Kent Boortz X-Dispatcher: imput version 971024 Lines: 273 Sender: owner-freebsd-questions@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG > The fpsetmask call is actually a very important thing to know about and > one area where the FreeBSD team should be quite proud. As a programmer, > it's great to have this kind of control over how these exceptions are > handled. After learning about this call I'm convinced that the system > default of trapping the exception and stopping execution is the correct > system-wide policy (it is conducive to the writing of good code in > general). I would prefer the higher level "ieee_handler()" calls used in SunOS4. Using the fpsetmask() calls seem to be *very* hardware dependent. I include a program below that test the floating point trapping on FreeBSD 2.2.2, GCC 2.7.2.1, tested on a 486 machine and Pentium. If I do % gcc -DSTICKY -DALL float.c -lm ; ./a.out it kind of freaks out after a while. If I omit "-DALL" to exclude the FP_X_IMP, "loss of precision", this also seem to disable the overflow and underflow exceptions. This immediately break the next *normal* floating point operation, i.e. gives an exception when it shouldn't. The fpsetmask man page talks about resetting the "sticky bits". I thought I was supposed to write "fpsetsticky(0)" to reset but it seems to be that I should set bits to reset them. What value should I use and *when* do I call this function? Before every floating point aritmetic call? After every call? After an unsuccessful call? Can I call "fpsetsticky()" from inside the signal handler? Is the fpsetmask/SIGFPE handling in FreeBSD 2.2.2 broken or am I doing something wrong? I had even more problem when I tried this on Solaris for Intel, I managed to create panic. If you have any information about how this is supposed to work, please let me know, /kgb ============================================================================ Mask: before set: FP_X_INV FP_X_OFL FP_X_DZ we want : FP_X_INV FP_X_OFL FP_X_UFL FP_X_DZ FP_X_DNML FP_X_IMP new : FP_X_INV FP_X_OFL FP_X_UFL FP_X_DZ FP_X_DNML FP_X_IMP **************************************** **** Exception: overflow **** Sticky : FP_X_OFL **** Exception: underflow **** Sticky : FP_X_UFL **** Exception: divide by zero **** Exception: invalid **** Exception: NaN **************************************** **** Exception: overflow **** Sticky : FP_X_OFL **** Exception: underflow **** Sticky : FP_X_UFL **** Exception: divide by zero **** Exception: invalid **** Exception: NaN **************************************** **** Exception: overflow **** Sticky : FP_X_OFL **** Exception: underflow **** Sticky : FP_X_UFL \\\\ Exception in normal operation **** Exception: divide by zero \\\\ Exception in normal operation **** Exception: invalid \\\\ Exception in normal operation **** Exception: NaN \\\\ Exception in normal operation **************************************** **** Exception: overflow **** Sticky : FP_X_OFL \\\\ Exception in normal operation **** Exception: underflow **** Sticky : FP_X_UFL \\\\ Exception in normal operation **** Exception: divide by zero \\\\ Exception in normal operation **** Exception: invalid **** Sticky : FP_X_OFL \\\\ Exception in normal operation **** Exception: NaN \\\\ Exception in normal operation **************************************** ============================================================================ #include #include #ifdef __FreeBSD__ #include #include #define sigset(__A,__B) signal(__A,__B) #else #include #endif #include #include int got_exception = 0; double dummy = 1.234; int mask; static void report_reset_exception(char*); static void print_mask(char*,int); static void check_normal(void); static void set_exception(int); static void *sys_sigset(int sig, void (*func)()); static void do_test(void); /***************************************************************************/ int main() { mask = FP_X_INV | FP_X_OFL | FP_X_UFL | FP_X_DZ; #ifdef FP_X_DNML mask |= FP_X_DNML; #endif #ifdef ALL mask |= FP_X_IMP; #endif printf("Mask:\n"); print_mask("before set: ",fpgetmask()); print_mask("we want : ",mask); fpsetmask(mask); print_mask("new : ",fpgetmask()); sys_sigset(SIGFPE,set_exception); printf("****************************************\n"); do_test(); do_test(); do_test(); do_test(); return 1; } /***************************************************************************/ static void do_test() { double i, k; k = 3.57e257; i = DBL_MAX * k; report_reset_exception("overflow"); k = 3.57e257; i = DBL_MIN / k; report_reset_exception("underflow"); k = 0.0; i = 3.58 / k; report_reset_exception("divide by zero"); k = 0x7ff0000; i = 3.58 * k; report_reset_exception("invalid"); i = remainder(1.0,0); report_reset_exception("NaN"); printf("****************************************\n"); } /***************************************************************************/ static void report_reset_exception(char *msg) { if (got_exception == 1) { int sticky = fpgetsticky(); got_exception = 0; printf( "**** Exception: %s\n",msg); if (sticky) { print_mask("**** Sticky : ",sticky); #ifdef STICKY fpsetsticky(mask); /* ?????? What value ??????*/ #endif } } else printf("==== No exception: %s\n",msg); check_normal(); } /***************************************************************************/ static void check_normal() { dummy += 1.234; /* Do something with the fpu */ if (got_exception == 1) { got_exception = 0; printf( "\\\\\\\\ Exception in normal operation\n"); } } /***************************************************************************/ #ifdef FP_X_DNML #define PSIZE 6 #else #define PSIZE 5 #endif static void print_mask(char *msg,int mask) { int i; struct { char *name; int value; } ir[] = { {"FP_X_INV",FP_X_INV}, {"FP_X_OFL",FP_X_OFL}, {"FP_X_UFL",FP_X_UFL}, {"FP_X_DZ ",FP_X_DZ}, #ifdef FP_X_DNML {"FP_X_DNML",FP_X_DNML}, #endif {"FP_X_IMP",FP_X_IMP} }; printf("%s",msg); for (i = 0; i < PSIZE; i++) if (mask & ir[i].value) printf("%s ", ir[i].name); printf("\n"); } static void set_exception(int i) { got_exception = 1; if (i != SIGFPE) { printf("Got another signal: %d\n",i); exit(1); } } /***************************************************************************/ #ifdef SIGACTION static void *sys_sigset(int sig, void (*func)()) { struct sigaction act, oact; printf("TRUE POSIX\n"); sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = func; sigaction(sig, &act, &oact); return oact.sa_handler; } #else static void *sys_sigset(int sig, void (*func)()) { return sigset(sig,func); } #endif To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-questions" in the body of the message