1 //===========================================================================
5 // Support sign of the gamma*() functions in Math library
7 //===========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //===========================================================================
41 //#####DESCRIPTIONBEGIN####
43 // Author(s): jlarmour
44 // Contributors: jlarmour
47 // Description: Contains the accessor functions to get and set the stored sign
48 // of the gamma*() functions in the math library
51 //####DESCRIPTIONEND####
53 //===========================================================================
55 /* @(#)k_standard.c 1.3 95/01/18 */
57 * ====================================================
58 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
60 * Developed at SunSoft, a Sun Microsystems, Inc. business.
61 * Permission to use, copy, modify, and distribute this
62 * software is freely granted, provided that this notice
64 * ====================================================
70 #include <pkgconf/libm.h> // Configuration header
72 // Include the Math library?
77 #include <cyg/infra/cyg_type.h> // Common type definitions and support
78 #include <cyg/infra/cyg_trac.h> // Tracing macros
80 #include <math.h> // Main header for math library
81 #include "mathincl/fdlibm.h" // Internal header for math library
83 #include <cyg/error/codes.h> // standard error codes
85 #ifndef CYGSEM_LIBM_COMPAT_IEEE_ONLY
88 static int errno; // this whole file won't be used if we're IEEE only, but
89 // doing this keeps the compiler happy
92 #ifdef CYGSEM_LIBM_USE_STDERR
95 #define WRITE2(u,v) fputs(u, stderr)
101 #endif // ifdef CYGSEM_LIBM_USE_STDERR
106 static const double zero = 0.0;
111 * Standard conformance (non-IEEE) on exception cases.
115 * 3 -- atan2(+-0,+-0)
116 * 4 -- hypot overflow
126 * 14-- lgamma(finite) overflow
127 * 15-- lgamma(-integer)
133 * 21-- pow(x,y) overflow
134 * 22-- pow(x,y) underflow
135 * 23-- pow(0,negative)
136 * 24-- pow(neg,non-integral)
137 * 25-- sinh(finite) overflow
138 * 26-- sqrt(negative)
140 * 28-- remainder(x,0)
144 * 32-- scalb overflow
145 * 33-- scalb underflow
146 * 34-- j0(|x|>X_TLOSS)
148 * 36-- j1(|x|>X_TLOSS)
150 * 38-- jn(|x|>X_TLOSS, n)
151 * 39-- yn(x>X_TLOSS, n)
152 * 40-- gamma(finite) overflow
153 * 41-- gamma(-integer)
155 * 43-- ldexp overflow
156 * 44-- ldexp underflow
161 __kernel_standard(double x, double y, int type)
163 struct exception exc;
165 #ifdef CYGSEM_LIBM_USE_STDERR
166 (void) fflush(stdout);
176 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
178 else if (!matherr(&exc)) {
179 if(cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
180 (void) WRITE2("acos: DOMAIN error\n", 19);
190 if(cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
192 else if (!matherr(&exc)) {
193 if(cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
194 (void) WRITE2("asin: DOMAIN error\n", 19);
206 if(cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
208 else if (!matherr(&exc)) {
209 if(cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
210 (void) WRITE2("atan2: DOMAIN error\n", 20);
216 /* hypot(finite,finite) overflow */
219 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
222 exc.retval = HUGE_VAL;
223 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
225 else if (!matherr(&exc)) {
230 /* cosh(finite) overflow */
233 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
236 exc.retval = HUGE_VAL;
237 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
239 else if (!matherr(&exc)) {
244 /* exp(finite) overflow */
247 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
250 exc.retval = HUGE_VAL;
251 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
253 else if (!matherr(&exc)) {
258 /* exp(finite) underflow */
259 exc.type = UNDERFLOW;
262 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
264 else if (!matherr(&exc)) {
270 exc.type = DOMAIN; /* should be SING for IEEE */
272 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
275 exc.retval = -HUGE_VAL;
276 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
278 else if (!matherr(&exc)) {
279 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
280 (void) WRITE2("y0: DOMAIN error\n", 17);
289 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
292 exc.retval = -HUGE_VAL;
293 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
295 else if (!matherr(&exc)) {
296 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
297 (void) WRITE2("y0: DOMAIN error\n", 17);
304 exc.type = DOMAIN; /* should be SING for IEEE */
306 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
309 exc.retval = -HUGE_VAL;
310 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
312 else if (!matherr(&exc)) {
313 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
314 (void) WRITE2("y1: DOMAIN error\n", 17);
323 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
326 exc.retval = -HUGE_VAL;
327 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
329 else if (!matherr(&exc)) {
330 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
331 (void) WRITE2("y1: DOMAIN error\n", 17);
338 exc.type = DOMAIN; /* should be SING for IEEE */
340 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
343 exc.retval = -HUGE_VAL;
344 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
346 else if (!matherr(&exc)) {
347 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
348 (void) WRITE2("yn: DOMAIN error\n", 17);
357 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
360 exc.retval = -HUGE_VAL;
361 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
363 else if (!matherr(&exc)) {
364 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
365 (void) WRITE2("yn: DOMAIN error\n", 17);
371 /* lgamma(finite) overflow */
374 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
377 exc.retval = HUGE_VAL;
378 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
380 else if (!matherr(&exc)) {
385 /* lgamma(-integer) or lgamma(0) */
388 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
391 exc.retval = HUGE_VAL;
392 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
394 else if (!matherr(&exc)) {
395 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
396 (void) WRITE2("lgamma: SING error\n", 19);
405 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
408 exc.retval = -HUGE_VAL;
409 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
411 else if (!matherr(&exc)) {
412 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
413 (void) WRITE2("log: SING error\n", 16);
422 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
425 exc.retval = -HUGE_VAL;
426 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
428 else if (!matherr(&exc)) {
429 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
430 (void) WRITE2("log: DOMAIN error\n", 18);
439 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
442 exc.retval = -HUGE_VAL;
443 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
445 else if (!matherr(&exc)) {
446 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
447 (void) WRITE2("log10: SING error\n", 18);
456 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
459 exc.retval = -HUGE_VAL;
460 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
462 else if (!matherr(&exc)) {
463 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
464 (void) WRITE2("log10: DOMAIN error\n", 20);
471 /* error only if cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID */
475 if (cyg_libm_get_compat_mode() != CYGNUM_LIBM_COMPAT_SVID) exc.retval = 1.0;
476 else if (!matherr(&exc)) {
477 (void) WRITE2("pow(0,0): DOMAIN error\n", 23);
482 /* pow(x,y) overflow */
485 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
488 if(x<zero&&rint(y)!=y) exc.retval = -HUGE;
490 exc.retval = HUGE_VAL;
492 if(x<zero&&rint(y)!=y) exc.retval = -HUGE_VAL;
494 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
496 else if (!matherr(&exc)) {
501 /* pow(x,y) underflow */
502 exc.type = UNDERFLOW;
505 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
507 else if (!matherr(&exc)) {
515 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
518 exc.retval = -HUGE_VAL;
519 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
521 else if (!matherr(&exc)) {
522 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
523 (void) WRITE2("pow(0,neg): DOMAIN error\n", 25);
529 /* neg**non-integral */
532 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
535 exc.retval = zero/zero; /* X/Open allow NaN */
536 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
538 else if (!matherr(&exc)) {
539 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
540 (void) WRITE2("neg**non-integral: DOMAIN error\n", 32);
546 /* sinh(finite) overflow */
549 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
550 exc.retval = ( (x>zero) ? HUGE : -HUGE);
552 exc.retval = ( (x>zero) ? HUGE_VAL : -HUGE_VAL);
553 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
555 else if (!matherr(&exc)) {
563 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
566 exc.retval = zero/zero;
567 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
569 else if (!matherr(&exc)) {
570 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
571 (void) WRITE2("sqrt: DOMAIN error\n", 19);
580 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
583 exc.retval = zero/zero;
584 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
586 else if (!matherr(&exc)) {
587 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
588 (void) WRITE2("fmod: DOMAIN error\n", 20);
596 exc.name = "remainder";
597 exc.retval = zero/zero;
598 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
600 else if (!matherr(&exc)) {
601 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
602 (void) WRITE2("remainder: DOMAIN error\n", 24);
611 exc.retval = zero/zero;
612 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
614 else if (!matherr(&exc)) {
615 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
616 (void) WRITE2("acosh: DOMAIN error\n", 20);
625 exc.retval = zero/zero;
626 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
628 else if (!matherr(&exc)) {
629 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
630 (void) WRITE2("atanh: DOMAIN error\n", 20);
639 exc.retval = x/zero; /* sign(x)*inf */
640 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
642 else if (!matherr(&exc)) {
643 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
644 (void) WRITE2("atanh: SING error\n", 18);
650 /* scalb overflow; SVID also returns +-HUGE_VAL */
653 exc.retval = x > zero ? HUGE_VAL : -HUGE_VAL;
654 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
656 else if (!matherr(&exc)) {
661 /* scalb underflow */
662 exc.type = UNDERFLOW;
664 exc.retval = copysign(zero,x);
665 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
667 else if (!matherr(&exc)) {
672 /* j0(|x|>X_TLOSS) */
676 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
678 else if (!matherr(&exc)) {
679 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
680 (void) WRITE2(exc.name, 2);
681 (void) WRITE2(": TLOSS error\n", 14);
691 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
693 else if (!matherr(&exc)) {
694 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
695 (void) WRITE2(exc.name, 2);
696 (void) WRITE2(": TLOSS error\n", 14);
702 /* j1(|x|>X_TLOSS) */
706 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
708 else if (!matherr(&exc)) {
709 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
710 (void) WRITE2(exc.name, 2);
711 (void) WRITE2(": TLOSS error\n", 14);
721 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
723 else if (!matherr(&exc)) {
724 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
725 (void) WRITE2(exc.name, 2);
726 (void) WRITE2(": TLOSS error\n", 14);
732 /* jn(|x|>X_TLOSS) */
736 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
738 else if (!matherr(&exc)) {
739 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
740 (void) WRITE2(exc.name, 2);
741 (void) WRITE2(": TLOSS error\n", 14);
751 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
753 else if (!matherr(&exc)) {
754 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
755 (void) WRITE2(exc.name, 2);
756 (void) WRITE2(": TLOSS error\n", 14);
762 /* gamma(finite) overflow */
765 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
768 exc.retval = HUGE_VAL;
769 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
771 else if (!matherr(&exc)) {
776 /* gamma(-integer) or gamma(0) */
779 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID)
782 exc.retval = HUGE_VAL;
783 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
785 else if (!matherr(&exc)) {
786 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID) {
787 (void) WRITE2("gamma: SING error\n", 18);
794 /* error only if cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_SVID & CYGNUM_LIBM_COMPAT_XOPEN */
798 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_IEEE ||
799 cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX) exc.retval = 1.0;
800 else if (!matherr(&exc)) {
805 /* ldexp overflow; SVID also returns +-HUGE_VAL */
808 exc.retval = x > zero ? HUGE_VAL : -HUGE_VAL;
809 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
811 else if (!matherr(&exc)) {
816 /* ldexp underflow */
817 exc.type = UNDERFLOW;
819 exc.retval = copysign(zero,x);
820 if (cyg_libm_get_compat_mode() == CYGNUM_LIBM_COMPAT_POSIX)
822 else if (!matherr(&exc)) {
830 #endif // ifdef CYGPKG_LIBM