richb@sunaus.oz (Rich Burridge) (02/02/90)
**IMPORTANT NOTE** This patch introduces a (hopefully) portable maths library. Please make sure you read the details listed below carefully. This is to try to make calctool portable to all Unix systems. If you have to make any changes to get it working on your machine, please let me know, and I'll adjust the official source code accordingly. This patch consists of three parts. As well as patch #6, there are two new files; mathlib.c and mathlib.h. ---- Cut Here and unpack ---- #!/bin/sh # shar: Shell Archiver (v1.22) # Packed Fri Feb 2 13:11:50 EST 1990 by stard!richb # from directory /home/tmp # # This is part 1 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # # Run the following text with /bin/sh to create: # patch.6 # mathlib.h # mathlib.c # if test -r s2_seq_.tmp then echo "Must unpack archives in sequence!" next=`cat s2_seq_.tmp`; echo "Please unpack part $next next" exit 1; fi echo "x - extracting patch.6 (Text)" sed 's/^X//' << 'SHAR_EOF' > patch.6 && XThis is official patch #6 for calctool v2.4; please apply it. X X**IMPORTANT NOTE** This patch introduces a (hopefully) portable X maths library. Please make sure you read the X details listed below carefully. X X This is to try to make calctool portable to all X Unix systems. If you have to make any changes to X get it working on your machine, please let me X know, and I'll adjust the official source code X accordingly. X XIt makes the following changes. X X 1/ The Makefile did not include the CHANGES file in the OTHERS X macro definition. X X 2/ If you are not using IEEE floating point format, and you need to X use some of the routines from the portable maths library which is X now included with this distribution, then you need to uncomment X the new NOTIEEE definition in the Makefile. X X 3/ From Tom Friedel <tpf@jdyx.atlanta.ga.us> X In the tty driver, in the drawtext routine, there is a character X array of five elements. There was an invalid assignment to key[5]. X X 4/ From Stephen Frede <stephenf@softway.oz> X The definitions in the Makefile for HELPNAME, NEWSFILE and RCNAME X do not need extra ...GIVEN definitions. X X 5/ Calctool.h defined NEWSNAME, when it should have defined NEWSFILE. X X 6/ With the X11 driver, the function XIconifyWindow is new to R4. X If you are running an X11 release which is not R4, then you need X to uncomment the new definition in the Makefile called NOT_R4. X This nullifys the function of the calctool OFF key, but hey, you X can also you the window manager to iconify calctool (assuming X your window manager can do that!). X X 7/ The factorial function has been adjusted to only work with X positive integers. I couldn't find a public domain or freely X distributable lgamma function written in C. X X 8/ fillbox in graphics.c no longer needs to be passed a window X parameter. X X 9/ From Stephen Frede <stephenf@softway.oz> X Not all linkers have the -L option. The CALCLIB definition in the X Makefile has been adjusted, and moved to the section where X LIBNAME is defined. By default, you shouldn't have to do anything, X but if you are on a Sun and want to use the shared library facility, X then you need to uncomment three definitions. X X 10/ From Stephen Frede <stephenf@softway.oz> X getcwd is not present on all systems. I've replaced it with getwd. X X XIt add the following files: X X mathlib.h X mathlib.c - These are an attempt to provide a portable maths X library for those systems that don't have all the X functions that calctool needs. X X You should look near the end of mathlib.h for a set X of definitions, then set appropriately. X XUse Larry Walls patch program to apply these changes, then recompile. X X------CUT HERE------patch.6------CUT HERE------ X X------- calctool.c ------- X*** /tmp/da5214 Fri Feb 2 13:01:42 1990 X--- calctool.c Tue Jan 30 12:08:45 1990 X*************** X*** 17,22 **** X--- 17,25 ---- X * reported to me then an attempt will be made to fix them. X */ X X+ #include <stdio.h> X+ #include <strings.h> X+ #include <math.h> X #include "patchlevel.h" X #include "color.h" X #include "calctool.h" X*************** X*** 361,372 **** X } X X X! matherr(x) /* Calctools' math library error-handling routine. */ X! struct exception *x ; X { X! SPRINTF(display, "Error in %s", x->name) ; X set_item(DISPLAYITEM, display) ; X error = 1 ; X set_item(OPITEM, "CLR") ; X- return(1) ; X } X--- 364,390 ---- X } X X X! /* Calctools' customised math library error-handling routine. */ X! X! doerr(funcname, etype, eval) X! char *funcname, *etype ; X! int eval ; X { X! SPRINTF(display, "%s: %s error", funcname, etype) ; X set_item(DISPLAYITEM, display) ; X+ error = eval ; X+ set_item(OPITEM, "CLR") ; X+ } X+ X+ X+ /* Default math library exception handling routine. */ X+ X+ /*ARGSUSED*/ X+ matherr(exc) X+ struct exception *exc ; X+ { X+ STRCPY(display, "Error") ; X+ set_item(DISPLAYITEM, display) ; X error = 1 ; X set_item(OPITEM, "CLR") ; X } X X------- functions.c ------- X*** /tmp/da5217 Fri Feb 2 13:01:43 1990 X--- functions.c Fri Feb 2 12:25:38 1990 X*************** X*** 18,27 **** X--- 18,34 ---- X * reported to me then an attempt will be made to fix them. X */ X X+ #include <stdio.h> X+ #include <strings.h> X+ #include <math.h> X #include "calctool.h" X #include "color.h" X #include "extern.h" X X+ extern double acos(), acosh(), asin(), asinh(), atan(), atanh() ; X+ extern double cos(), cosh(), exp(), fabs(), log(), log10(), pow() ; X+ extern double sin(), sinh(), sqrt(), tan(), tanh() ; X+ X BOOLEAN ibool() ; X double setbool() ; X X*************** X*** 185,202 **** X double a ; X int i ; X X! if (val == (int) val) X { X i = val ; X a = 1.0 ; X while ((i > 0) && (a != HUGE)) a *= (float) i-- ; X } X- else X- { X- a = gamma(val+1) ; X- a = exp(a) ; X- if (signgam) a = -a ; X- } X return (a) ; X } X X--- 192,204 ---- X double a ; X int i ; X X! a = val ; X! if (val == (int) val && val > 0.0) /* Only for positive integers. */ X { X i = val ; X a = 1.0 ; X while ((i > 0) && (a != HUGE)) a *= (float) i-- ; X } X return (a) ; X } X X*************** X*** 284,290 **** X break ; X case '{' : disp_val = exp(disp_val) ; /* e^x */ X break ; X! case '}' : disp_val = exp(M_LN10*disp_val) ; /* 10^x */ X break ; X case 'N' : disp_val = log(disp_val) ; /* ln */ X break ; X--- 286,292 ---- X break ; X case '{' : disp_val = exp(disp_val) ; /* e^x */ X break ; X! case '}' : disp_val = exp(LN10*disp_val) ; /* 10^x */ X break ; X case 'N' : disp_val = log(disp_val) ; /* ln */ X break ; X*************** X*** 506,513 **** X X if (!inverse) X { X! if (ttype == DEG) temp = disp_val * M_PI / 180.0 ; X! else if (ttype == GRAD) temp = disp_val * M_PI / 200.0 ; X else temp = disp_val ; X X if (!hyperbolic) X--- 508,515 ---- X X if (!inverse) X { X! if (ttype == DEG) temp = disp_val * PI / 180.0 ; X! else if (ttype == GRAD) temp = disp_val * PI / 200.0 ; X else temp = disp_val ; X X if (!hyperbolic) X*************** X*** 553,560 **** X case CCTRL('t') : disp_val = atanh(disp_val) ; /* atanh */ X } X X! tresults[(int) DEG] = disp_val * 180.0 / M_PI ; X! tresults[(int) GRAD] = disp_val * 200.0 / M_PI ; X tresults[(int) RAD] = disp_val ; X } X X--- 555,562 ---- X case CCTRL('t') : disp_val = atanh(disp_val) ; /* atanh */ X } X X! tresults[(int) DEG] = disp_val * 180.0 / PI ; X! tresults[(int) GRAD] = disp_val * 200.0 / PI ; X tresults[(int) RAD] = disp_val ; X } X X X------- graphics.c ------- X*** /tmp/da5220 Fri Feb 2 13:01:45 1990 X--- graphics.c Tue Jan 30 12:09:19 1990 X*************** X*** 14,19 **** X--- 14,21 ---- X * reported to me then an attempt will be made to fix them. X */ X X+ #include <stdio.h> X+ #include <strings.h> X #include "calctool.h" X #include "color.h" X #include "extern.h" X*************** X*** 73,80 **** X drawbox(column*(BWIDTH+BGAP)+BBORDER, X DISPLAY+row*(BHEIGHT+BGAP)+BBORDER, BWIDTH, BHEIGHT) ; X fillbox(column*(BWIDTH+BGAP)+BBORDER+1, X! DISPLAY+row*(BHEIGHT+BGAP)+BBORDER+1, KEYCANVAS, X! 42, 50, 1, color) ; X } X else X { X--- 75,81 ---- X drawbox(column*(BWIDTH+BGAP)+BBORDER, X DISPLAY+row*(BHEIGHT+BGAP)+BBORDER, BWIDTH, BHEIGHT) ; X fillbox(column*(BWIDTH+BGAP)+BBORDER+1, X! DISPLAY+row*(BHEIGHT+BGAP)+BBORDER+1, 42, 50, 1, color) ; X } X else X { X*************** X*** 82,96 **** X DISPLAY+row*(BHEIGHT+BGAP)+BBORDER+26, 34, 21) ; X color = (iscolor) ? buttons[n].color : BLACK ; X fillbox(column*(BWIDTH+BGAP)+BBORDER+6, X! DISPLAY+row*(BHEIGHT+BGAP)+BBORDER+27, KEYCANVAS, X! 32, 19, 1, color) ; X } X but_text(row, column, portion, state) ; X } X X X! fillbox(x, y, window, width, height, boundry, color) X! enum can_type window ; X int x, y, width, height, boundry, color ; X { X if (boundry) X--- 83,95 ---- X DISPLAY+row*(BHEIGHT+BGAP)+BBORDER+26, 34, 21) ; X color = (iscolor) ? buttons[n].color : BLACK ; X fillbox(column*(BWIDTH+BGAP)+BBORDER+6, X! DISPLAY+row*(BHEIGHT+BGAP)+BBORDER+27, 32, 19, 1, color) ; X } X but_text(row, column, portion, state) ; X } X X X! fillbox(x, y, width, height, boundry, color) X int x, y, width, height, boundry, color ; X { X if (boundry) X*************** X*** 199,205 **** X color = (portion) ? WHITE : BLACK ; X fillbox(column*(BWIDTH+BGAP)+BBORDER+6, X DISPLAY+row*(BHEIGHT+BGAP)+BBORDER+5+(portion*22), X! KEYCANVAS, 32, 19, portion, color) ; X but_text(row, column, portion, state) ; X } X } X--- 198,204 ---- X color = (portion) ? WHITE : BLACK ; X fillbox(column*(BWIDTH+BGAP)+BBORDER+6, X DISPLAY+row*(BHEIGHT+BGAP)+BBORDER+5+(portion*22), X! 32, 19, portion, color) ; X but_text(row, column, portion, state) ; X } X } X X------- news.c ------- X*** /tmp/da5223 Fri Feb 2 13:01:46 1990 X--- news.c Tue Jan 30 12:47:57 1990 X*************** X*** 14,19 **** X--- 14,21 ---- X * reported to me then an attempt will be made to fix them. X */ X X+ #include <stdio.h> X+ #include <strings.h> X #include "calctool.h" X #include "color.h" X #include "extern.h" X X------- sunview.c ------- X*** /tmp/da5226 Fri Feb 2 13:01:47 1990 X--- sunview.c Tue Jan 30 12:30:27 1990 X*************** X*** 14,19 **** X--- 14,21 ---- X * reported to me then an attempt will be made to fix them. X */ X X+ #include <stdio.h> X+ #include <strings.h> X #include "calctool.h" X #include "color.h" X #include "extern.h" X*************** X*** 27,32 **** X--- 29,35 ---- X #define NOTIFY_INTERPOSE_DESTROY_FUNC (void) notify_interpose_destroy_func X #define PW_SETCMSNAME (void) pw_setcmsname X #define PW_PUTCOLORMAP (void) pw_putcolormap X+ #define PW_REVERSEVIDEO (void) pw_reversevideo X #define PW_TTEXT (void) pw_ttext X #define PW_VECTOR (void) pw_vector X #define PW_WRITEBACKGROUND (void) pw_writebackground X*************** X*** 457,463 **** X X calc_colorsetup(red, green, blue) ; X PW_PUTCOLORMAP(cpw, 0, CALC_COLORSIZE, red, green, blue) ; X! if (inv_video) pw_reversevideo(cpw, 0, CALC_COLORSIZE) ; X X if (iscolor) X { X--- 460,466 ---- X X calc_colorsetup(red, green, blue) ; X PW_PUTCOLORMAP(cpw, 0, CALC_COLORSIZE, red, green, blue) ; X! if (inv_video) PW_REVERSEVIDEO(cpw, 0, CALC_COLORSIZE) ; X X if (iscolor) X { X X------- x11.c ------- X*** /tmp/da5229 Fri Feb 2 13:01:48 1990 X--- x11.c Mon Jan 29 23:10:33 1990 X*************** X*** 14,19 **** X--- 14,20 ---- X * reported to me then an attempt will be made to fix them. X */ X X+ #include <stdio.h> X #include "calctool.h" X #include "color.h" X #include "extern.h" X*************** X*** 91,117 **** X X close_frame() X { X! Atom a ; X! XClientMessageEvent ev ; X! X! iconic = 1 ; X! rstate = 0 ; X! X! if (dpy->atoms->wm_change_state == None) X! { X! a = XInternAtom (dpy, "WM_CHANGE_STATE", False) ; X! if (a == None) return ; X! dpy->atoms->wm_change_state = a ; X! } X! X! ev.type = ClientMessage ; X! ev.window = frame ; X! ev.message_type = dpy->atoms->wm_change_state ; X! ev.format = 32 ; X! ev.data.l[0] = IconicState ; X! XSendEvent(dpy, RootWindow(dpy, screen), False, X! SubstructureRedirectMask | SubstructureNotifyMask, X! (XEvent *) &ev) ; X } X X X--- 92,100 ---- X X close_frame() X { X! #ifndef NOT_R4 X! XIconifyWindow(dpy, frame, screen) ; X! #endif /*NOT_R4*/ X } X X X X------- calctool.h ------- X*** /tmp/da5232 Fri Feb 2 13:01:49 1990 X--- calctool.h Fri Feb 2 12:54:28 1990 X*************** X*** 14,31 **** X * reported to me then an attempt will be made to fix them. X */ X X! #include <stdio.h> X! #include <strings.h> X! #include <ctype.h> X! #include <signal.h> X! #include <sys/types.h> X! #include <sys/ioctl.h> X! #include <sys/time.h> X! #include <pwd.h> X! #include <math.h> X X- char *getenv(), *sprintf() ; X- X #define CLOSE (void) close /* To make lint happy. */ X #define FCLOSE (void) fclose X #define FFLUSH (void) fflush X--- 14,21 ---- X * reported to me then an attempt will be made to fix them. X */ X X! char *getenv(), *getwd(), *sprintf() ; X X #define CLOSE (void) close /* To make lint happy. */ X #define FCLOSE (void) fclose X #define FFLUSH (void) fflush X*************** X*** 91,96 **** X--- 81,102 ---- X X enum trig_type { DEG, GRAD, RAD } ; /* Trigonometric types. */ X X+ /* Mathematical constants used by the routines in functions.c X+ * These should be declared in math.h, but just in case.... X+ */ X+ X+ #ifndef HUGE X+ #define HUGE 1.701411733192644270e38 X+ #endif /*HUGE*/ X+ X+ #ifndef LN10 X+ #define LN10 2.30258509299404568402 X+ #endif /*LN10*/ X+ X+ #ifndef PI X+ #define PI 3.14159265358979323846 X+ #endif /*PI*/ X+ X #define BBORDER 10 /* No of pixels in border. */ X #define BCOLS 6 /* No of columns of buttons. */ X #define BGAP 5 /* No of pixels between buttons. */ X*************** X*** 104,112 **** X #define EQUAL !strcmp /* For character comparisons. */ X #define EXTRA 5 /* Extra useful character definitions. */ X X! #ifndef HELPGIVEN X #define HELPNAME "calctool.help" X! #endif /*HELPGIVEN*/ X X #define ICONHEIGHT 64 /* Height of calctool icon. */ X #define ICONWIDTH 42 /* Width of calctool icon. */ X--- 110,118 ---- X #define EQUAL !strcmp /* For character comparisons. */ X #define EXTRA 5 /* Extra useful character definitions. */ X X! #ifndef HELPNAME X #define HELPNAME "calctool.help" X! #endif /*HELPNAME*/ X X #define ICONHEIGHT 64 /* Height of calctool icon. */ X #define ICONWIDTH 42 /* Width of calctool icon. */ X*************** X*** 119,131 **** X #endif /*MAXLINE*/ X X #define MAXMENUS 8 /* Maximum number of popup menus. */ X #define MAXREGS 10 /* Maximum number of memory registers. */ X #define MAXVKEYS 7 /* Number of valid keys after an error. */ X #define MIN(x,y) ((x) < (y) ? (x) : (y)) X X! #ifndef NEWSGIVEN X! #define NEWSNAME "calctool.ps" X! #endif /*NEWSGIVEN*/ X X #define NOBUTTONS BROWS * BCOLS X X--- 125,145 ---- X #endif /*MAXLINE*/ X X #define MAXMENUS 8 /* Maximum number of popup menus. */ X+ X+ #ifndef MAXPATHLEN X+ #define MAXPATHLEN 1024 /* Longest possible path length. */ X+ #endif /*MAXPATHLEN*/ X+ X #define MAXREGS 10 /* Maximum number of memory registers. */ X #define MAXVKEYS 7 /* Number of valid keys after an error. */ X+ X+ #ifndef MIN X #define MIN(x,y) ((x) < (y) ? (x) : (y)) X+ #endif /*MIN*/ X X! #ifndef NEWSFILE X! #define NEWSFILE "calctool.ps" X! #endif /*NEWSFILE*/ X X #define NOBUTTONS BROWS * BCOLS X X*************** X*** 133,141 **** X #define index strchr X #endif /*NOINDEX*/ X X! #ifndef RCGIVEN X #define RCNAME ".calctoolrc" X! #endif /*RCGIVEN*/ X X #ifndef NO_4_3SIGNAL X #define SIGRET void X--- 147,155 ---- X #define index strchr X #endif /*NOINDEX*/ X X! #ifndef RCNAME X #define RCNAME ".calctoolrc" X! #endif /*RCNAME*/ X X #ifndef NO_4_3SIGNAL X #define SIGRET void X X------- Makefile ------- X*** /tmp/da5235 Fri Feb 2 13:01:50 1990 X--- Makefile Fri Feb 2 12:24:19 1990 X*************** X*** 28,35 **** X # It can also be specified here by uncommenting the following X # macro definition and setting appropriately. X # X! #HELPNAME = -DHELPGIVEN -DHELPNAME=\"$(LIBDIR)/calctool.help\" X #----------------------------------------------------------------------- X # Not all machines have the index() string library function. If you X # don't have this function then you should uncomment the NOINDEX X # definition below. X--- 28,44 ---- X # It can also be specified here by uncommenting the following X # macro definition and setting appropriately. X # X! #HELPNAME = -DHELPNAME=\"$(LIBDIR)/calctool.help\" X #----------------------------------------------------------------------- X+ # An attempt is now made at using a portable math library. You should X+ # carefully setup the following three definitions. X+ # X+ # One of the things this is not the same on all machines is the X+ # floating point format. If your machine does *not* use IEEE floating X+ # point format, then the following definition needs to be uncommented. X+ # X+ #NOIEEE = -DIEEE X+ #----------------------------------------------------------------------- X # Not all machines have the index() string library function. If you X # don't have this function then you should uncomment the NOINDEX X # definition below. X*************** X*** 47,53 **** X # should be uncommented and set to the default location for the calctool X # PostScript file, which is downloaded to the NeWS server. X # X! #NEWSFILE = -DNEWSGIVEN -DNEWSFILE=\"$(LIBDIR)/calctool.ps\" X #----------------------------------------------------------------------- X # Calctool loads a run control file when it starts. By default X # this file is called ".calctoolrc", and is taken from the users X--- 56,62 ---- X # should be uncommented and set to the default location for the calctool X # PostScript file, which is downloaded to the NeWS server. X # X! #NEWSFILE = -DNEWSFILE=\"$(LIBDIR)/calctool.ps\" X #----------------------------------------------------------------------- X # Calctool loads a run control file when it starts. By default X # this file is called ".calctoolrc", and is taken from the users X*************** X*** 56,62 **** X # can also be specified here by uncommenting the following macro X # definition and setting appropriately. X # X! #RCNAME = -DRCGIVEN -DRCNAME=\".calctoolrc\" X #----------------------------------------------------------------------- X # If you not running under a BSD4.3 derived system, the parameters X # to the select call are different, and this definition should be X--- 65,71 ---- X # can also be specified here by uncommenting the following macro X # definition and setting appropriately. X # X! #RCNAME = -DRCNAME=\".calctoolrc\" X #----------------------------------------------------------------------- X # If you not running under a BSD4.3 derived system, the parameters X # to the select call are different, and this definition should be X*************** X*** 66,77 **** X #----------------------------------------------------------------------- X # Note that with SunOS v4.x it is possible to create a shared library X # for the calctool routines. If you wish to do this, then you should X! # change LIBNAME below to libcalctool.so.1.1, and uncomment the SHLIB X! # line. X # X LIBNAME = libcalctool.a X # X #LIBNAME = libcalctool.so.1.1 X #SHLIB = -pic X #----------------------------------------------------------------------- X # If you are not running under a BSD4.3 derived system, then the X--- 75,89 ---- X #----------------------------------------------------------------------- X # Note that with SunOS v4.x it is possible to create a shared library X # for the calctool routines. If you wish to do this, then you should X! # uncomment the other three definitions below, commented out the initial X! # two. X # X LIBNAME = libcalctool.a X+ CALCLIB = $(LIBNAME) X # X+ # Shared library definitions. Uncomment if required. X #LIBNAME = libcalctool.so.1.1 X+ #CALCLIB = -L. -lcalctool X #SHLIB = -pic X #----------------------------------------------------------------------- X # If you are not running under a BSD4.3 derived system, then the X*************** X*** 99,104 **** X--- 111,122 ---- X # X #X11INCDIR = -I$(OPENWINHOME)/include X #X11LIBDIR = -L$(OPENWINHOME)/lib X+ # X+ # If you are not running X11R4, then you should uncomment the following X+ # definition. This is needed to disable the call to XIconifyWindow in X+ # the routine close_frame. This routines is new in X11R4. X+ # X+ #NOT_R4 = -DNOT_R4 X #------------------------------------------------------------------------- X # If you are compiling the XView version, then the following two lines X # should be uncommented. X*************** X*** 118,124 **** X # X # Compilation flags and standard macro definitions. X # X! CFLAGS = -g $(HELPNAME) $(NEWSFILE) $(NOINDEX) $(RCNAME) \ X $(SELTYPE) $(SHLIB) $(SIGRET) $(SUN4_KEYBOARD) \ X $(TTEXT) $(MGRPARAM) $(MGRINCDIR) $(X11INCDIR) \ X $(XVIEWINCDIR) X--- 136,142 ---- X # X # Compilation flags and standard macro definitions. X # X! CFLAGS = -g $(HELPNAME) $(NEWSFILE) $(NOIEEE) $(NOINDEX) $(RCNAME) \ X $(SELTYPE) $(SHLIB) $(SIGRET) $(SUN4_KEYBOARD) \ X $(TTEXT) $(MGRPARAM) $(MGRINCDIR) $(X11INCDIR) \ X $(XVIEWINCDIR) X*************** X*** 130,155 **** X X LIBSRCS = graphics.c display.c functions.c get.c X LIBOBJS = graphics.o display.o functions.o get.o X! STDSRCS = calctool.c X! STDOBJS = calctool.o X OBJS = $(STDOBJS) $(LIBNAME) X X GSRCS = mgr.c news.c sunview.c tty.c x11.c xview.c X! HDRS = calctool.h color.h extern.h X IMAGES = calctool.icon calctool.color.icon help.cursor X OTHERS = Makefile README TODO calctool.help calctool.1 \ X! calctool.ps patchlevel.h .calctoolrc X X! SFILES1 = $(LIBSRCS) $(STDSRCS) X! SFILES2 = $(GSRCS) X! SFILES3 = $(HDRS) $(IMAGES) X! SFILES4 = $(OTHERS) X X- CALCLIB = -L. -lcalctool X MGRLIBS = $(CALCLIB) $(MGRHOME)/lib/libmgr.a -lm X! NEWSLIBS = $(CALCLIB) $$NEWSHOME/lib/libcps.a -lm X SVIEWLIBS = $(CALCLIB) -lsuntool -lsunwindow -lpixrect -lm X! TTYLIBS = $(CALCLIB) -ltermcap -lm X X11LIBS = $(CALCLIB) -lX11 -lm X XVIEWLIBS = $(CALCLIB) -lxview -lolgx -lX11 -lm X X--- 148,173 ---- X X LIBSRCS = graphics.c display.c functions.c get.c X LIBOBJS = graphics.o display.o functions.o get.o X! STDSRCS = calctool.c mathlib.c X! STDOBJS = calctool.o mathlib.o X OBJS = $(STDOBJS) $(LIBNAME) X X GSRCS = mgr.c news.c sunview.c tty.c x11.c xview.c X! HDRS = calctool.h color.h extern.h mathlib.h X IMAGES = calctool.icon calctool.color.icon help.cursor X OTHERS = Makefile README TODO calctool.help calctool.1 \ X! CHANGES calctool.ps patchlevel.h .calctoolrc X X! SFILES1 = $(STDSRCS) X! SFILES2 = $(LIBSRCS) X! SFILES3 = $(GSRCS) X! SFILES4 = $(HDRS) $(IMAGES) X! SFILES5 = $(OTHERS) X X MGRLIBS = $(CALCLIB) $(MGRHOME)/lib/libmgr.a -lm X! NEWSLIBS = $(CALCLIB) $$OPENWINHOME/lib/libcps.a -lm X SVIEWLIBS = $(CALCLIB) -lsuntool -lsunwindow -lpixrect -lm X! TTYLIBS = $(CALCLIB) -ltermcap -lm X X11LIBS = $(CALCLIB) -lX11 -lm X XVIEWLIBS = $(CALCLIB) -lxview -lolgx -lX11 -lm X X*************** X*** 230,235 **** X--- 248,254 ---- X shar.script $(SFILES2) > archive.2 X shar.script $(SFILES3) > archive.3 X shar.script $(SFILES4) > archive.4 X+ shar.script $(SFILES5) > archive.5 X X create: SCCS X -sccs create $(STDSRCS) $(GSRCS) $(HDRS) $(IMAGES) $(OTHERS) X*************** X*** 236,238 **** X--- 255,270 ---- X SCCS: X -mkdir SCCS X chmod 755 SCCS X+ X+ calctool.o: calctool.c patchlevel.h color.h calctool.h X+ display.o: display.c calctool.h color.h extern.h X+ functions.o: functions.c calctool.h color.h extern.h X+ get.o: get.c patchlevel.h calctool.h color.h extern.h X+ graphics.o: graphics.c calctool.h color.h extern.h X+ mathlib.o: mathlib.c mathlib.h calctool.h X+ mgr.o: mgr.c calctool.h color.h extern.h X+ news.o: news.c calctool.h color.h extern.h X+ sunview.o: sunview.c calctool.h color.h extern.h X+ tty.o: tty.c calctool.h color.h extern.h X+ x11.o: x11.c calctool.h color.h extern.h X+ xview.o: xview.c calctool.h color.h extern.h X X------- README ------- X*** /tmp/da5238 Fri Feb 2 13:01:51 1990 X--- README Tue Jan 30 00:07:24 1990 X*************** X*** 39,44 **** X--- 39,62 ---- X defined by the Makefile macro definition LIBDIR, so you might need root X permission to successfully do this. X X+ X+ Portable maths routines. X+ ------------------------ X+ X+ It is hoped that your system supplies all the mathematical functions X+ required by calctool. If not then, it is possible to use the needed X+ ones from the portable math library routines that comes with these X+ sources. X+ X+ In mathlib.h, there is one definition for each routine used by calctool. X+ These are commented out by default to signify that this system has that X+ routine in it's maths library. If you are missing any, then uncomment X+ the appropriate definitions. X+ X+ X+ Todo. X+ ----- X+ X There is a TODO file included, which lists the current known bugs, and X a set of possible enhancements, some relatively trivial, others that X are fairly major enhancements which would make interesting future X*************** X*** 46,51 **** X--- 64,70 ---- X X X Acknowledgements. X+ ----------------- X X Thanks to Ed Falk at Sun Microsystems (Mountain View) for most of the X basic arithmetical algorithms used, to Andrew Nicholson for revising the X*************** X*** 55,65 **** X X Thanks go also to James Buster, David Weaver, Steve Damron, Mike Bender, X Charles Tierney, Trevor Watson, Marla Berg, David Hough, Jeff Donsbach, X! Mel Melchner, Peter Allott, Skip Gilbrech and Keith McNeill for bug X! reports and/or bug fixes plus sugggested enhancements. X X Suggestions for furthur improvement would be most welcome, plus bugs, X comments and flames. X X! Rich Burridge, DOMAIN: richb@sunaus.oz.au X! PHONE: +61 2 413 2666 UUCP: {uunet,mcvax,ukc}!munnari!sunaus.oz!richb X--- 74,86 ---- X X Thanks go also to James Buster, David Weaver, Steve Damron, Mike Bender, X Charles Tierney, Trevor Watson, Marla Berg, David Hough, Jeff Donsbach, X! Mel Melchner, Peter Allott, Skip Gilbrech, Tom Friedel, Keith McNeill X! and Stephen Frede for bug reports and/or bug fixes plus sugggested X! enhancements. X X Suggestions for furthur improvement would be most welcome, plus bugs, X comments and flames. X X! Rich Burridge, DOMAIN: richb@Aus.Sun.COM X! PHONE: +61 2 413 2666 ACSNET: richb@sunaus.sun.oz X! UUCP: {uunet,mcvax,ukc}!munnari!sunaus.oz!richb X X------- calctool.1 ------- X*** /tmp/da5241 Fri Feb 2 13:01:52 1990 X--- calctool.1 Mon Jan 29 23:55:44 1990 X*************** X*** 259,265 **** X .IP "\fB1/x [ R ]\fP" 18 X Return the value of 1 divided by the current entry. X .IP "\fBx! [ ! ]\fP" 18 X! Return the factorial of the current entry. X .IP "\fBx^2 [ @ ]\fP" 18 X Return the square of the current entry. X .SS Number Manipulation Operators. X--- 259,266 ---- X .IP "\fB1/x [ R ]\fP" 18 X Return the value of 1 divided by the current entry. X .IP "\fBx! [ ! ]\fP" 18 X! Return the factorial of the current entry. Note that this only works X! for positive integers. X .IP "\fBx^2 [ @ ]\fP" 18 X Return the square of the current entry. X .SS Number Manipulation Operators. X X------- patchlevel.h ------- X*** /tmp/da5244 Fri Feb 2 13:01:53 1990 X--- patchlevel.h Tue Jan 23 10:00:38 1990 X*************** X*** 14,17 **** X * reported to me then an attempt will be made to fix them. X */ X X! #define PATCHLEVEL 5 X--- 14,17 ---- X * reported to me then an attempt will be made to fix them. X */ X X! #define PATCHLEVEL 6 X X------- mgr.c ------- X*** /tmp/da5247 Fri Feb 2 13:01:53 1990 X--- mgr.c Tue Jan 30 00:21:25 1990 X*************** X*** 14,19 **** X--- 14,24 ---- X * reported to me then an attempt will be made to fix them. X */ X X+ #include <stdio.h> X+ #include <signal.h> X+ #include <sys/types.h> X+ #include <sys/ioctl.h> X+ #include <sys/time.h> X #include "dump.h" X #include "term.h" X #include "calctool.h" X X------- tty.c ------- X*** /tmp/da5250 Fri Feb 2 13:01:54 1990 X--- tty.c Tue Jan 30 12:23:19 1990 X*************** X*** 1,3 **** X--- 1,4 ---- X+ /*LINTLIBRARY*/ X X /* %Z%%M% %I% %E% X * X*************** X*** 14,19 **** X--- 15,26 ---- X * reported to me then an attempt will be made to fix them. X */ X X+ #include <stdio.h> X+ #include <strings.h> X+ #include <signal.h> X+ #include <sys/types.h> X+ #include <sys/ioctl.h> X+ #include <sys/time.h> X #include "calctool.h" X #include "color.h" X #include "extern.h" X*************** X*** 105,111 **** X /*ARGSUSED*/ X do_menu(mtype) /* Popup appropriate menu (null routine). */ X enum menu_type mtype ; X! {} X X X do_move(x, y) /* Move to character position (x, y). */ X--- 112,120 ---- X /*ARGSUSED*/ X do_menu(mtype) /* Popup appropriate menu (null routine). */ X enum menu_type mtype ; X! { X! return 0 ; /* To make lint happy. */ X! } X X X do_move(x, y) /* Move to character position (x, y). */ X*************** X*** 234,240 **** X case 3 : key[0] = ' ' ; X STRNCPY(&key[1], str, 3) ; X } X! key[5] = '\0' ; X STRCPY(str, key) ; X if (ty % 3) invert = 1 ; X } X--- 243,249 ---- X case 3 : key[0] = ' ' ; X STRNCPY(&key[1], str, 3) ; X } X! key[4] = '\0' ; X STRCPY(str, key) ; X if (ty % 3) invert = 1 ; X } X X------- xview.c ------- X*** /tmp/da5253 Fri Feb 2 13:01:55 1990 X--- xview.c Mon Jan 29 23:11:47 1990 X*************** X*** 14,19 **** X--- 14,20 ---- X * reported to me then an attempt will be made to fix them. X */ X X+ #include <stdio.h> X #include "calctool.h" X #include "color.h" X #include "extern.h" X X------- get.c ------- X*** /tmp/da5256 Fri Feb 2 13:01:56 1990 X--- get.c Fri Feb 2 12:54:34 1990 X*************** X*** 14,19 **** X--- 14,23 ---- X * reported to me then an attempt will be made to fix them. X */ X X+ #include <stdio.h> X+ #include <strings.h> X+ #include <sys/param.h> X+ #include <pwd.h> X #include "patchlevel.h" X #include "calctool.h" X #include "color.h" X*************** X*** 281,286 **** X--- 285,291 ---- X { X char *home ; /* Pathname for users home directory. */ X char name[MAXLINE] ; /* Full name of users .calctoolrc file. */ X+ char pathname[MAXPATHLEN] ; /* Current working directory. */ X int n ; X struct passwd *entry ; X X*************** X*** 299,305 **** X SPRINTF(name, "%s/%s", home, RCNAME) ; X get_rcfile(name) ; /* Read .calctoolrc from users home directory. */ X X! SPRINTF(name, "%s/%s", getcwd((char *) NULL, MAXLINE), RCNAME) ; X get_rcfile(name) ; /* Read .calctoolrc file from current directory. */ X } X X--- 304,310 ---- X SPRINTF(name, "%s/%s", home, RCNAME) ; X get_rcfile(name) ; /* Read .calctoolrc from users home directory. */ X X! SPRINTF(name, "%s/%s", getwd(pathname), RCNAME) ; X get_rcfile(name) ; /* Read .calctoolrc file from current directory. */ X } X X X------- display.c ------- X*** /tmp/da5259 Fri Feb 2 13:01:57 1990 X--- display.c Tue Jan 30 12:09:53 1990 X*************** X*** 17,22 **** X--- 17,25 ---- X * reported to me then an attempt will be made to fix them. X */ X X+ #include <stdio.h> X+ #include <strings.h> X+ #include <math.h> X #include "calctool.h" X #include "color.h" X #include "extern.h" X X------- CHANGES ------- X*** /tmp/da5262 Fri Feb 2 13:01:58 1990 X--- CHANGES Fri Feb 2 13:01:01 1990 X*************** X*** 93,95 **** X--- 93,152 ---- X X * CHANGES - documented history of the changes made with each new X calctool patch. X+ X+ v2.4 - patchlevel 6. - Posted to comp.sources.bugs (January 1990). X+ X+ Changes: X+ X+ * The Makefile did not include the CHANGES file in the OTHERS X+ macro definition. X+ X+ * If you are not using IEEE floating point format, and you need to X+ use some of the routines from the portable maths library which is X+ now included with this distribution, then you need to uncomment X+ the new NOTIEEE definition in the Makefile. X+ X+ * From Tom Friedel <tpf@jdyx.atlanta.ga.us> X+ In the tty driver, in the drawtext routine, there is a character X+ array of five elements. There was an invalid assignment to key[5]. X+ X+ * From Stephen Frede <stephenf@softway.oz> X+ The definitions in the Makefile for HELPNAME, NEWSFILE and RCNAME X+ do not need extra ...GIVEN definitions. X+ X+ * Calctool.h defined NEWSNAME, when it should have defined NEWSFILE. X+ X+ * With the X11 driver, the function XIconifyWindow is new to R4. X+ If you are running an X11 release which is not R4, then you need X+ to uncomment the new definition in the Makefile called NOT_R4. X+ This nullifys the function of the calctool OFF key, but hey, you X+ can also you the window manager to iconify calctool (assuming X+ your window manager can do that!). X+ X+ * The factorial function has been adjusted to only work with X+ positive integers. I couldn't find a public domain or freely X+ distributable lgamma function written in C. X+ X+ * fillbox in graphics.c no longer needs to be passed a window X+ parameter X+ X+ * From Stephen Frede <stephenf@softway.oz> X+ Not all linkers have the -L option. The CALCLIB definition in the X+ Makefile has been adjusted, and moved to the section where X+ LIBNAME is defined. By default, you shouldn't have to do anything, X+ but if you are on a Sun and want to use the shared library facility, X+ then you need to uncomment three definitions. X+ X+ * From Stephen Frede <stephenf@softway.oz> X+ getcwd is not present on all systems. I've replaced it with getwd. X+ X+ X+ New files: X+ X+ * mathlib.h X+ mathlib.c - These are an attempt to provide a portable maths X+ library for those systems that don't have all the X+ functions that calctool needs. X+ X+ You should look near the end of mathlib.h for a set X+ of definitions, then set appropriately. SHAR_EOF chmod 0644 patch.6 || echo "restore of patch.6 fails" set `wc -c patch.6`;Sum=$1 if test "$Sum" != "35130" then echo original size 35130, current size $Sum;fi echo "x - extracting mathlib.h (Text)" sed 's/^X//' << 'SHAR_EOF' > mathlib.h && X X/* @(#)mathlib.h 1.2 90/02/02 X * X * Definitions used with the portable math library. X * X * This is being done because libm.a doesn't appear to be as portable X * as originally assumed. X * X * These routines are taken from two sources: X * X * 1/ Fred Fishs' portable maths library which was posted to the X * comp.sources.unix newsgroup on April 1987. X * X * acos, acosh, asin, asinh, atan, atanh, cos, cosh, dabss, X * exp, log, log10, mod, poly, sin, sinh, sqrt, tan, tanh. X * X * 2/ The BSD4.3 maths library found on uunet in X * bsd_sources/src/usr.lib/libm. X * X * pow, pow_p, scalb, logb, copysign, finite, drem, exp__E, X * log__L. X * X * Customised and condensed by Rich Burridge, X * Sun Microsystems, Australia. X * X * Permission is given to distribute these sources, as long as the X * copyright messages are not removed, and no monies are exchanged. X * X * No responsibility is taken for any errors or inaccuracies inherent X * either to the comments or the code of this program, but if X * reported to me then an attempt will be made to fix them. X */ X X/************************************************************************ X * * X * N O T I C E * X * * X * Copyright Abandoned, 1987, Fred Fish * X * * X * This previously copyrighted work has been placed into the * X * public domain by the author (Fred Fish) and may be freely used * X * for any purpose, private or commercial. I would appreciate * X * it, as a courtesy, if this notice is left in all copies and * X * derivative works. Thank you, and enjoy... * X * * X * The author makes no warranty of any kind with respect to this * X * product and explicitly disclaims any implied warranties of * X * merchantability or fitness for any particular purpose. * X * * X ************************************************************************ X */ X X/* This file gets included with all of the floating point math X * library routines when they are compiled. Note that X * this is the proper place to put machine dependencies X * whenever possible. X * X * It should be pointed out that for simplicity's sake, the X * environment parameters are defined as floating point constants, X * rather than octal or hexadecimal initializations of allocated SHAR_EOF echo "End of part 1" echo "File mathlib.h is continued in part 2" echo "2" > s2_seq_.tmp exit 0
richb@sunaus.oz (Rich Burridge) (02/02/90)
---- Cut Here and unpack ---- #!/bin/sh # this is part 2 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file mathlib.h continued # CurArch=2 if test ! -r s2_seq_.tmp then echo "Please unpack part 1 first!" exit 1; fi ( read Scheck if test "$Scheck" != $CurArch then echo "Please unpack part $Scheck next!" exit 1; else exit 0; fi ) < s2_seq_.tmp || exit 1 echo "x - Continuing file mathlib.h" sed 's/^X//' << 'SHAR_EOF' >> mathlib.h X * storage areas. This means that the range of allowed numbers X * may not exactly match the hardware's capabilities. For example, X * if the maximum positive double precision floating point number X * is EXACTLY 1.11...E100 and the constant "MAXDOUBLE is X * defined to be 1.11E100 then the numbers between 1.11E100 and X * 1.11...E100 are considered to be undefined. For most X * applications, this will cause no problems. X * X * An alternate method is to allocate a global static "double" variable, X * say "maxdouble", and use a union declaration and initialization X * to initialize it with the proper bits for the EXACT maximum value. X * This was not done because the only compilers available to the X * author did not fully support union initialization features. X */ X Xextern double acos(), acosh(), asin(), asinh(), atan(), atanh() ; Xextern double cos(), cosh(), exp(), fabs(), log(), log10(), pow() ; Xextern double sin(), sinh(), sqrt(), tan(), tanh() ; X X/*START============start of definitions from <values.h>============START X * X * If your system has a /usr/include/values.h, or has another include X * file which defines: X * MAXDOUBLE => Maximum double precision number X * MINDOUBLE => Minimum double precision number X * DMAXEXP => Maximum exponent of a double X * DMINEXP => Minimum exponent of a double X * X * you can comment out these definitions down to the END line below. X */ X X#ifndef BITSPERBYTE X/* These values work with any binary representation of integers X * where the high-order bit contains the sign. */ X X/* a number used normally for size of a shift */ X#if gcos X#define BITSPERBYTE 9 X#else X#define BITSPERBYTE 8 X#endif X#define BITS(type) (BITSPERBYTE * (int)sizeof(type)) X X/* Various values that describe the binary floating-point representation X * MAXDOUBLE - the largest double X * ((_EXPBASE ** DMAXEXP) * (1 - (_EXPBASE ** -DSIGNIF))) X * MINDOUBLE - the smallest double (_EXPBASE ** (DMINEXP - 1)) X * DMAXEXP - the maximum exponent of a double (as returned by frexp()) X * DMINEXP - the minimum exponent of a double (as returned by frexp()) X * DSIGNIF - the number of significant bits in a double X * _IEEE - 1 if IEEE standard representation is used X * _DEXPLEN - the number of bits for the exponent of a double X * _HIDDENBIT - 1 if high-significance bit of mantissa is implicit X */ X X#if u3b || u3b5 || sun X#define MAXDOUBLE 1.79769313486231470e+308 X#define MINDOUBLE 4.94065645841246544e-324 X#define _IEEE 1 X#define _DEXPLEN 11 X#define _HIDDENBIT 1 X#define DMINEXP (-(DMAXEXP + DSIGNIF - _HIDDENBIT - 3)) X#endif X X#if pdp11 || vax X#define MAXDOUBLE 1.701411834604692293e+38 X#define MINDOUBLE (0.01 * 2.938735877055718770e-37) X#define _IEEE 0 X#define _DEXPLEN 8 X#define _HIDDENBIT 1 X#define DMINEXP (-DMAXEXP) X#endif X X#if gcos X#define MAXDOUBLE 1.7014118346046923171e+38 X#define MINDOUBLE 2.9387358770557187699e-39 X#define _IEEE 0 X#define _DEXPLEN 8 X#define _HIDDENBIT 0 X#define DMINEXP (-(DMAXEXP + 1)) X#endif X X#define DSIGNIF (BITS(double) - _DEXPLEN + _HIDDENBIT - 1) X#define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE) X X#endif /*BITSPERBYTE*/ X X/*END==============end of definitions from <values.h>==================END*/ X X X#define LOG2_MAXDOUBLE (DMAXEXP + 1) X#define LOG2_MINDOUBLE (DMINEXP - 1) X#define LOGE_MAXDOUBLE (LOG2_MAXDOUBLE / LOG2E) X#define LOGE_MINDOUBLE (LOG2_MINDOUBLE / LOG2E) X X/* X * The following are hacks which should be fixed when I understand all X * the issues a little better. |tanh(TANH_MAXARG)| = 1.0 X */ X X#define TANH_MAXARG 16 X#define SQRT_MAXDOUBLE 1.304380e19 X X#define TWOPI (2.0 * PI) X#define HALFPI (PI / 2.0) X#define FOURTHPI (PI / 4.0) X#define SIXTHPI (PI / 6.0) X#define LOG2E 1.4426950408889634074 /* Log to base 2 of e */ X#define LOG10E 0.4342944819032518276 X#define SQRT2 1.4142135623730950488 X#define SQRT3 1.7320508075688772935 X#define LN2 0.6931471805599453094 X#define LNSQRT2 0.3465735902799726547 X X/* MC68000 HARDWARE DEPENDENCIES X * X * cc -DIEEE => uses IEEE floating point format X * X * Apologies for the double negative. I want as few definitions X * needed in the default case as possible. X */ X X#ifndef NOIEEE X#define X6_UNDERFLOWS (4.209340e-52) /* X**6 almost underflows */ X#define X16_UNDERFLOWS (5.421010e-20) /* X**16 almost underflows */ X#endif /*NOIEEE*/ X X/* It is hoped that your system supplies all the mathematical functions X * required by calctool. If not then, it is possible to use the needed X * ones from the portable math library routines that comes with these X * sources. X * X * There is one definition for each routine used by calctool. These are X * commented out by default to signify that this system has that routine. X * If you are missing any, then uncomment the appropriate definitions. X */ X X/*#define NEED_ACOS */ X/*#define NEED_ACOSH */ X/*#define NEED_ASIN */ X/*#define NEED_ASINH */ X/*#define NEED_ATAN */ X/*#define NEED_ATANH */ X/*#define NEED_COS */ X/*#define NEED_COSH */ X/*#define NEED_EXP */ X/*#define NEED_LOG */ X/*#define NEED_LOG10 */ X/*#define NEED_POW */ X/*#define NEED_SIN */ X/*#define NEED_SINH */ X/*#define NEED_SQRT */ X/*#define NEED_TAN */ X/*#define NEED_TANH */ SHAR_EOF echo "File mathlib.h is complete" chmod 0444 mathlib.h || echo "restore of mathlib.h fails" set `wc -c mathlib.h`;Sum=$1 if test "$Sum" != "8385" then echo original size 8385, current size $Sum;fi echo "x - extracting mathlib.c (Text)" sed 's/^X//' << 'SHAR_EOF' > mathlib.c && X X/* @(#)mathlib.c 1.2 90/02/02 X * X * These are the mathematical routines used by calctool. X * X * This is being done because libm.a doesn't appear to be as portable X * as originally assumed. X * X * It is hoped that your system supplies all the mathematical functions X * required by calctool. If not then, it is possible to use the needed X * ones from this library. Look in mathlib.h for a set of definitions, X * and uncomment and set appropriately. X * X * These routines are taken from two sources: X * X * 1/ Fred Fishs' portable maths library which was posted to the X * comp.sources.unix newsgroup on April 1987. X * X * acos, acosh, asin, asinh, atan, atanh, cos, cosh, dabs, X * exp, log, log10, mod, poly, sin, sinh, sqrt, tan, tanh. X * X * 2/ The BSD4.3 maths library found on uunet in X * bsd_sources/src/usr.lib/libm. X * X * pow, pow_p, scalb, logb, copysign, finite, drem, exp__E, X * log__L. X * X * Customised and condensed by Rich Burridge, X * Sun Microsystems, Australia. X * X * Permission is given to distribute these sources, as long as the X * copyright messages are not removed, and no monies are exchanged. X * X * No responsibility is taken for any errors or inaccuracies inherent X * either to the comments or the code of this program, but if X * reported to me then an attempt will be made to fix them. X */ X X/************************************************************************ X * * X * N O T I C E * X * * X * Copyright Abandoned, 1987, Fred Fish * X * * X * This previously copyrighted work has been placed into the * X * public domain by the author (Fred Fish) and may be freely used * X * for any purpose, private or commercial. I would appreciate * X * it, as a courtesy, if this notice is left in all copies and * X * derivative works. Thank you, and enjoy... * X * * X * The author makes no warranty of any kind with respect to this * X * product and explicitly disclaims any implied warranties of * X * merchantability or fitness for any particular purpose. * X * * X ************************************************************************ X */ X X#include <stdio.h> X#include <errno.h> X#include "mathlib.h" X#include "calctool.h" X Xdouble atan(), cos(), cosh(), dabs(), exp(), frexp() ; Xdouble ldexp(), log(), mod(), modf(), poly(), sin() ; Xdouble sinh(), sqrt() ; X Xextern double frexp(), ldexp(), modf() ; X X X/* FUNCTION X * X * acos double precision arc cosine X * X * DESCRIPTION X * X * Returns double precision arc cosine of double precision X * floating point argument. X * X * USAGE X * X * double acos(x) X * double x ; X * X * REFERENCES X * X * Fortran IV-plus user's guide, Digital Equipment Corp. pp B-1. X * X * RESTRICTIONS X * X * The maximum relative error for the approximating polynomial X * in atan is 10**(-16.82). However, this assumes exact arithmetic X * in the polynomial evaluation. Additional rounding and X * truncation errors may occur as the argument is reduced X * to the range over which the polynomial approximation X * is valid, and as the polynomial is evaluated using X * finite-precision arithmetic. X * X * INTERNALS X * X * Computes arccosine(x) from: X * X * (1) If x < -1.0 or x > +1.0 then call X * doerr and return 0.0 by default. X * X * (2) If x = 0.0 then acos(x) = PI/2. X * X * (3) If x = 1.0 then acos(x) = 0.0 X * X * (4) If x = -1.0 then acos(x) = PI. X * X * (5) If 0.0 < x < 1.0 then X * acos(x) = atan(Y) X * Y = sqrt[1-(x**2)] / x X * X * (6) If -1.0 < x < 0.0 then X * acos(x) = atan(Y) + PI X * Y = sqrt[1-(x**2)] / x X */ X X#ifdef NEED_ACOS Xdouble Xacos(x) Xdouble x ; X{ X double y ; X auto double retval ; X X if (x > 1.0 || x < -1.0) X { X doerr("acos", "DOMAIN", EDOM) ; X retval = 0.0 ; X } X else if (x == 0.0) retval = HALFPI ; X else if (x == 1.0) retval = 0.0 ; X else if (x == -1.0) retval = PI ; X else X { X y = atan(sqrt(1.0 - (x * x)) / x) ; X if (x > 0.0) retval = y ; X else retval = y + PI ; X } X return(retval) ; X} X#endif /*NEED_ACOS*/ X X X/* FUNCTION X * X * acosh double precision hyperbolic arc cosine X * X * DESCRIPTION X * X * Returns double precision hyperbolic arc cosine of double precision X * floating point number. X * X * USAGE X * X * double acosh(x) X * double x ; X * X * RESTRICTIONS X * X * The range of the ACOSH function is all real numbers greater X * than or equal to 1.0 however large arguments may cause X * overflow in the x squared portion of the function evaluation. X * X * For precision information refer to documentation of the X * floating point library primatives called. X * X * INTERNALS X * X * Computes acosh(x) from: X * X * 1. If x < 1.0 then report illegal X * argument and return zero. X * X * 2. If x > sqrt(MAXDOUBLE) then X * set x = sqrt(MAXDOUBLE and X * continue after reporting overflow. X * X * 3. acosh(x) = log [x+sqrt(x**2 - 1)] X */ X X#ifdef NEED_ACOSH Xdouble Xacosh(x) Xdouble x ; X{ X auto double retval ; X X if (x < 1.0) X { X doerr("acosh", "DOMAIN", ERANGE) ; X retval = 0.0 ; X } X else if (x > SQRT_MAXDOUBLE) X { X doerr("acosh", "OVERFLOW", ERANGE) ; X x = SQRT_MAXDOUBLE ; X retval = log(2* SQRT_MAXDOUBLE) ; X } X else retval = log(x + sqrt(x*x - 1.0)) ; X return(retval) ; X} X#endif /*NEED_ACOSH*/ X X X/* X * FUNCTION X * X * asin double precision arc sine X * X * DESCRIPTION X * X * Returns double precision arc sine of double precision X * floating point argument. X * X * If argument is less than -1.0 or greater than +1.0, calls X * doerr with a DOMAIN error. If doerr does not handle X * the error then prints error message and returns 0. X * X * USAGE X * X * double asin(x) X * double x ; X * X * REFERENCES X * X * Fortran IV-plus user's guide, Digital Equipment Corp. pp B-2. X * X * RESTRICTIONS X * X * For precision information refer to documentation of the floating X * point library primatives called. X * X * INTERNALS X * X * Computes arcsine(x) from: X * X * (1) If x < -1.0 or x > +1.0 then X * call doerr and return 0.0 by default. X * X * (2) If x = 0.0 then asin(x) = 0.0 X * X * (3) If x = 1.0 then asin(x) = PI/2. X * X * (4) If x = -1.0 then asin(x) = -PI/2 X * X * (5) If -1.0 < x < 1.0 then X * asin(x) = atan(y) X * y = x / sqrt[1-(x**2)] X */ X X#ifdef NEED_ASIN Xdouble Xasin(x) Xdouble x ; X{ X auto double retval ; X X if ( x > 1.0 || x < -1.0) X { X doerr("asin", "DOMAIN", EDOM) ; X retval = 0.0 ; X } X else if (x == 0.0) retval = 0.0 ; X else if (x == 1.0) retval = HALFPI ; X else if (x == -1.0) retval = -HALFPI ; X else retval = atan(x / sqrt (1.0 - (x * x))) ; X return(retval) ; X} X#endif /*NEED_ASIN*/ X X X/* FUNCTION X * X * asinh double precision hyperbolic arc sine X * X * DESCRIPTION X * X * Returns double precision hyperbolic arc sine of double precision X * floating point number. X * X * USAGE X * X * double asinh(x) X * double x ; X * X * RESTRICTIONS X * X * The domain of the ASINH function is the entire real axis X * however the evaluation of x squared may cause overflow X * for large magnitudes. X * X * For precision information refer to documentation of the X * floating point library routines called. X * X * INTERNALS X * X * Computes asinh(x) from: X * X * 1. Let xmax = sqrt(MAXDOUBLE - 1) X * X * 2. If x < -xmax or xmax < x then X * let x = xmax and flag overflow. X * X * 3. asinh(x) = log [x+sqrt(x**2 + 1)] X */ X X#ifdef NEED_ASINH Xdouble Xasinh(x) Xdouble x ; X{ X auto double retval ; X X if (x < -SQRT_MAXDOUBLE || x > SQRT_MAXDOUBLE) X { X doerr("asinh", "OVERFLOW", ERANGE) ; X retval = log(2 * SQRT_MAXDOUBLE) ; X } X else retval = log(x + sqrt(x*x + 1.0)) ; X return(retval) ; X} X#endif /*NEED_ASINH*/ X X X/* FUNCTION X * X * atan double precision arc tangent X * X * DESCRIPTION X * X * Returns double precision arc tangent of double precision X * floating point argument. X * X * USAGE X * X * double atan(x) X * double x ; X * X * REFERENCES X * X * Fortran 77 user's guide, Digital Equipment Corp. pp B-3 X * X * Computer Approximations, J.F. Hart et al, John Wiley & Sons, X * 1968, pp. 120-130. X * X * RESTRICTIONS X * X * The maximum relative error for the approximating polynomial X * is 10**(-16.82). However, this assumes exact arithmetic X * in the polynomial evaluation. Additional rounding and X * truncation errors may occur as the argument is reduced X * to the range over which the polynomial approximation X * is valid, and as the polynomial is evaluated using X * finite-precision arithmetic. X * X * INTERNALS X * X * Computes arctangent(x) from: X * X * (1) If x < 0 then negate x, perform steps X * 2, 3, and 4, and negate the returned X * result. This makes use of the identity X * atan(-x) = -atan(x). X * X * (2) If argument x > 1 at this point then X * test to be sure that x can be inverted X * without underflowing. If not, reduce X * x to largest possible number that can X * be inverted, issue warning, and continue. X * Perform steps 3 and 4 with arg = 1/x X * and subtract returned result from X * pi/2. This makes use of the identity X * atan(x) = pi/2 - atan(1/x) for x>0. X * X * (3) At this point 0 <= x <= 1. If X * x > tan(pi/12) then perform step 4 X * with arg = (x*sqrt(3)-1)/(sqrt(3)+x) X * and add pi/6 to returned result. This X * last transformation maps arguments X * greater than tan(pi/12) to arguments X * in range 0...tan(pi/12). X * X * (4) At this point the argument has been X * transformed so that it lies in the X * range -tan(pi/12)...tan(pi/12). X * Since very small arguments may cause X * underflow in the polynomial evaluation, X * a final check is performed. If the X * argument is less than the underflow X * bound, the function returns x, since X * atan(x) approaches asin(x) which X * approaches x, as x goes to zero. X * X * (5) atan(x) is now computed by one of the X * approximations given in the cited X * reference (Hart). That is: X * X * atan(x) = x * SUM [ C[i] * x**(2*i) ] X * over i = {0,1,...8}. X * X * Where: X * X * C[0] = .9999999999999999849899 X * C[1] = -.333333333333299308717 X * C[2] = .1999999999872944792 X * C[3] = -.142857141028255452 X * C[4] = .11111097898051048 X * C[5] = -.0909037114191074 X * C[6] = .0767936869066 X * C[7] = -.06483193510303 X * C[8] = .0443895157187 X * (coefficients from HART table #4945 pg 267) X */ X X#ifdef NEED_ATAN X X#define LAST_BOUND 0.2679491924311227074725 /* tan (PI/12) */ X Xstatic double atan_coeffs[] = { X .9999999999999999849899, /* P0 must be first */ X -.333333333333299308717, X .1999999999872944792, X -.142857141028255452, X .11111097898051048, X -.0909037114191074, X .0767936869066, X -.06483193510303, X .0443895157187 /* Pn must be last */ X} ; X Xdouble Xatan(x) Xdouble x ; X{ X register int order ; X double t1, t2, xt2 ; X auto double retval ; X X if (x < 0.0) retval = -(atan(-x)) ; X else if (x > 1.0) X { X if (x < MAXDOUBLE && x > -MAXDOUBLE) X retval = HALFPI - atan(1.0 / x) ; X else X { X doerr("atan", "UNDERFLOW", EDOM) ; X retval = 0.0 ; X } X } X else if (x > LAST_BOUND) X { X t1 = x * SQRT3 - 1.0 ; X t2 = SQRT3 + x ; X retval = SIXTHPI + atan(t1 / t2) ; X } X else if (x < X16_UNDERFLOWS) X { X doerr("atan", "PLOSS", EDOM) ; X retval = x ; X } X else X { X xt2 = x * x ; X order = sizeof(atan_coeffs) / sizeof(double) ; X order -= 1 ; X retval = x * poly(order, atan_coeffs, xt2) ; X } X return(retval) ; X} X#endif /*NEED_ATAN*/ X X X/* FUNCTION X * X * atanh double precision hyperbolic arc tangent X * X * DESCRIPTION X * X * Returns double precision hyperbolic arc tangent of double precision X * floating point number. X * X * USAGE X * X * double atanh(x) X * double x ; X * X * RESTRICTIONS X * X * The range of the atanh function is -1.0 to +1.0 exclusive. X * Certain pathological cases near 1.0 may cause overflow X * in evaluation of 1+x / 1-x, depending upon machine exponent X * range and mantissa precision. X * X * For precision information refer to documentation of the X * other floating point library routines called. X * X * INTERNALS X * X * Computes atanh(x) from: X * X * 1. If x <= -1.0 or x >= 1.0 X * then report argument out of range and return 0.0 X * X * 2. atanh(x) = 0.5 * log((1+x)/(1-x)) X */ X X#ifdef NEED_ATANH Xdouble Xatanh(x) Xdouble x ; X{ X auto double retval ; X X if (x <= -1.0 || x >= 1.0) X { X doerr("atan", "DOMAIN", ERANGE) ; X retval = 0.0 ; X } X else retval = 0.5 * log((1+x) / (1-x)) ; X return(retval) ; X} X#endif /*NEED_ATANH*/ X X X/* FUNCTION X * X * cos - double precision cosine X * X * DESCRIPTION X * X * Returns double precision cosine of double precision X * floating point argument. X * X * USAGE X * X * double cos(x) X * double x ; X * X * REFERENCES X * X * Computer Approximations, J.F. Hart et al, John Wiley & Sons, X * 1968, pp. 112-120. X * X * RESTRICTIONS X * X * The sin and cos routines are interactive in the sense that X * in the process of reducing the argument to the range -PI/4 X * to PI/4, each may call the other. Ultimately one or the X * other uses a polynomial approximation on the reduced X * argument. The sin approximation has a maximum relative error X * of 10**(-17.59) and the cos approximation has a maximum X * relative error of 10**(-16.18). X * X * These error bounds assume exact arithmetic X * in the polynomial evaluation. Additional rounding and X * truncation errors may occur as the argument is reduced X * to the range over which the polynomial approximation X * is valid, and as the polynomial is evaluated using X * finite-precision arithmetic. X * X * INTERNALS X * X * Computes cos(x) from: X * X * (1) Reduce argument x to range -PI to PI. X * X * (2) If x > PI/2 then call cos recursively X * using relation cos(x) = -cos(x - PI). X * X * (3) If x < -PI/2 then call cos recursively X * using relation cos(x) = -cos(x + PI). X * X * (4) If x > PI/4 then call sin using X * relation cos(x) = sin(PI/2 - x). X * X * (5) If x < -PI/4 then call cos using X * relation cos(x) = sin(PI/2 + x). X * X * (6) If x would cause underflow in approx X * evaluation arithmetic then return X * sqrt(1.0 - x**2). X * X * (7) By now x has been reduced to range X * -PI/4 to PI/4 and the approximation X * from HART pg. 119 can be used: X * X * cos(x) = ( p(y) / q(y) ) X * Where: X * X * y = x * (4/PI) X * X * p(y) = SUM [ Pj * (y**(2*j)) ] X * over j = {0,1,2,3} X * X * q(y) = SUM [ Qj * (y**(2*j)) ] X * over j = {0,1,2,3} X * X * P0 = 0.12905394659037374438571854e+7 X * P1 = -0.3745670391572320471032359e+6 X * P2 = 0.134323009865390842853673e+5 X * P3 = -0.112314508233409330923e+3 X * Q0 = 0.12905394659037373590295914e+7 X * Q1 = 0.234677731072458350524124e+5 X * Q2 = 0.2096951819672630628621e+3 X * Q3 = 1.0000... X * (coefficients from HART table #3843 pg 244) X * X * X * **** NOTE **** The range reduction relations used in X * this routine depend on the final approximation being valid X * over the negative argument range in addition to the positive X * argument range. The particular approximation chosen from X * HART satisfies this requirement, although not explicitly X * stated in the text. This may not be true of other X * approximations given in the reference. X */ X X#ifdef NEED_COS X Xstatic double cos_pcoeffs[] = { X 0.12905394659037374438e7, X -0.37456703915723204710e6, X 0.13432300986539084285e5, X -0.11231450823340933092e3 X} ; X Xstatic double cos_qcoeffs[] = { X 0.12905394659037373590e7, X 0.23467773107245835052e5, X 0.20969518196726306286e3, X 1.0 X} ; X Xdouble Xcos(x) Xdouble x ; X{ X auto double y, yt2 ; X auto double retval ; X X if (x < -PI || x > PI) X { X x = mod(x, TWOPI) ; X if (x > PI) x = x - TWOPI ; X else if (x < -PI) x = x + TWOPI ; X } X if (x > HALFPI) retval = -(cos(x - PI)) ; X else if (x < -HALFPI) retval = -(cos(x + PI)) ; X else if (x > FOURTHPI) retval = sin(HALFPI - x) ; X else if (x < -FOURTHPI) retval = sin(HALFPI + x) ; X else if (x < X6_UNDERFLOWS && x > -X6_UNDERFLOWS) X retval = sqrt(1.0 - (x * x)) ; X else X { X y = x / FOURTHPI ; X yt2 = y * y ; X retval = poly(3, cos_pcoeffs, yt2) / poly(3, cos_qcoeffs, yt2) ; X } X return(retval) ; X} X#endif /*NEED_COS*/ X X X/* FUNCTION X * X * cosh double precision hyperbolic cosine X * X * DESCRIPTION X * X * Returns double precision hyperbolic cosine of double precision X * floating point number. X * X * USAGE X * X * double cosh(x) X * double x ; X * X * REFERENCES X * X * Fortran IV plus user's guide, Digital Equipment Corp. pp B-4 X * X * RESTRICTIONS X * X * Inputs greater than log(MAXDOUBLE) result in overflow. X * Inputs less than log(MINDOUBLE) result in underflow. X * X * For precision information refer to documentation of the X * floating point library routines called. X * X * INTERNALS X * X * Computes hyperbolic cosine from: X * X * cosh(X) = 0.5 * (exp(X) + exp(-X)) X */ X X X#ifdef NEED_COSH Xdouble Xcosh(x) Xdouble x ; X{ X auto double retval ; X X if (x > LOGE_MAXDOUBLE) X { X doerr("cosh", "OVERFLOW", ERANGE) ; X retval = MAXDOUBLE ; X } X else if (x < LOGE_MINDOUBLE) X { X doerr("cosh", "UNDERFLOW", ERANGE) ; X retval = MINDOUBLE ; X } X else X { X x = exp(x) ; X retval = 0.5 * (x + 1.0 / x) ; X } X return(retval) ; X} X#endif /*NEED_COSH*/ X X X/* FUNCTION X * X * dabs double precision absolute value X * X * DESCRIPTION X * X * Returns absolute value of double precision number. X * X * USAGE X * X * double dabs(x) X * double x ; X */ X X#ifdef NEED_EXP Xdouble Xdabs(x) Xdouble x ; X{ X if (x < 0.0) x = -x ; X return(x) ; X} X#endif /*NEED_EXP*/ X X X/* FUNCTION X * X * exp double precision exponential X * X * DESCRIPTION X * X * Returns double precision exponential of double precision X * floating point number. X * X * USAGE X * X * double exp(x) X * double x ; X * X * REFERENCES X * X * Fortran IV plus user's guide, Digital Equipment Corp. pp B-3 X * X * Computer Approximations, J.F. Hart et al, John Wiley & Sons, X * 1968, pp. 96-104. X * X * RESTRICTIONS X * X * Inputs greater than log(MAXDOUBLE) result in overflow. X * Inputs less than log(MINDOUBLE) result in underflow. X * X * The maximum relative error for the approximating polynomial X * is 10**(-16.4). However, this assumes exact arithmetic X * in the polynomial evaluation. Additional rounding and X * truncation errors may occur as the argument is reduced X * to the range over which the polynomial approximation X * is valid, and as the polynomial is evaluated using X * finite precision arithmetic. X * X * X * INTERNALS X * X * Computes exponential from: X * X * exp(x) = 2**y * 2**z * 2**w X * X * Where: X * X * y = int ( x * log2(e) ) X * X * v = 16 * frac ( x * log2(e)) X * X * z = (1/16) * int (v) X * X * w = (1/16) * frac (v) X * X * Note that: X * X * 0 =< v < 16 X * X * z = {0, 1/16, 2/16, ...15/16} X * X * 0 =< w < 1/16 X * X * Then: X * X * 2**z is looked up in a table of 2**0, 2**1/16, ... X * X * 2**w is computed from an approximation: X * X * 2**w = (A + B) / (A - B) X * X * A = C + (D * w * w) X * X * B = w * (E + (F * w * w)) X * X * C = 20.8137711965230361973 X * X * D = 1.0 X * X * E = 7.2135034108448192083 X * X * F = 0.057761135831801928 X * X * Coefficients are from HART, table #1121, pg 206. X * X * Effective multiplication by 2**y is done by a X * floating point scale with y as scale argument. X */ X X#ifdef NEED_EXP X X#define C 20.8137711965230361973 /* Polynomial approx coeff. */ X#define D 1.0 /* Polynomial approx coeff. */ X#define E 7.2135034108448192083 /* Polynomial approx coeff. */ X#define F 0.057761135831801928 /* Polynomial approx coeff. */ X X/************************************************************************ X * * X * This table is fixed in size and reasonably hardware * X * independent. The given constants were generated on a * X * DECSYSTEM 20 using double precision FORTRAN. * X * * X ************************************************************************ X */ X Xstatic double fpof2tbl[] = { X 1.00000000000000000000, /* 2 ** 0/16 */ X 1.04427378242741384020, /* 2 ** 1/16 */ X 1.09050773266525765930, /* 2 ** 2/16 */ X 1.13878863475669165390, /* 2 ** 3/16 */ X 1.18920711500272106640, /* 2 ** 4/16 */ X 1.24185781207348404890, /* 2 ** 5/16 */ X 1.29683955465100966610, /* 2 ** 6/16 */ X 1.35425554693689272850, /* 2 ** 7/16 */ X 1.41421356237309504880, /* 2 ** 8/16 */ X 1.47682614593949931110, /* 2 ** 9/16 */ X 1.54221082540794082350, /* 2 ** 10/16 */ X 1.61049033194925430820, /* 2 ** 11/16 */ X 1.68179283050742908600, /* 2 ** 12/16 */ X 1.75625216037329948340, /* 2 ** 13/16 */ X 1.83400808640934246360, /* 2 ** 14/16 */ X 1.91520656139714729380 /* 2 ** 15/16 */ X} ; X Xdouble Xexp(x) Xdouble x ; X{ X register int ival, y ; X auto double a, b, rtnval, t, temp, v, w, wpof2, zpof2 ; X auto double retval ; X X if (x > LOGE_MAXDOUBLE) X { X doerr("exp", "OVERFLOW", ERANGE) ; X retval = MAXDOUBLE ; X } X else if (x <= LOGE_MINDOUBLE) X { X doerr("exp", "UNDERFLOW", ERANGE) ; X retval = 0.0 ; X } X else X { X t = x * LOG2E ; X (void) modf(t, &temp) ; X y = temp ; X v = 16.0 * modf(t, &temp) ; X (void) modf(dabs(v), &temp) ; X ival = temp ; X if (x < 0.0) zpof2 = 1.0 / fpof2tbl[ival] ; X else zpof2 = fpof2tbl[ival] ; X w = modf(v, &temp) / 16.0 ; X a = C + (D * w * w) ; X b = w * (E + (F * w * w)) ; X wpof2 = (a + b) / (a - b) ; X retval = ldexp((wpof2 * zpof2), y) ; X } X return(retval) ; X} X#endif /*NEED_EXP*/ X X X/* FUNCTION X * X * log double precision natural log X * X * DESCRIPTION X * X * Returns double precision natural log of double precision X * floating point argument. X * X * USAGE X * X * double log(x) X * double x ; X * X * REFERENCES X * X * Computer Approximations, J.F. Hart et al, John Wiley & Sons, X * 1968, pp. 105-111. X * X * RESTRICTIONS X * X * The absolute error in the approximating polynomial is X * 10**(-19.38). Note that contrary to DEC's assertion X * in the F4P user's guide, the error is absolute and not X * relative. X * X * This error bound assumes exact arithmetic X * in the polynomial evaluation. Additional rounding and X * truncation errors may occur as the argument is reduced X * to the range over which the polynomial approximation X * is valid, and as the polynomial is evaluated using X * finite-precision arithmetic. X * X * INTERNALS X * X * Computes log(X) from: X * X * (1) If argument is zero then flag an error X * and return minus infinity (or rather its X * machine representation). X * X * (2) If argument is negative then flag an X * error and return minus infinity. X * X * (3) Given that x = m * 2**k then extract X * mantissa m and exponent k. X * X * (4) Transform m which is in range [0.5,1.0] X * to range [1/sqrt(2), sqrt(2)] by: X * X * s = m * sqrt(2) X * X * (5) Compute z = (s - 1) / (s + 1) X * X * (6) Now use the approximation from HART X * page 111 to find log(s): X * X * log(s) = z * ( P(z**2) / Q(z**2) ) X * X * Where: X * X * P(z**2) = SUM [ Pj * (z**(2*j)) ] X * over j = {0,1,2,3} X * X * Q(z**2) = SUM [ Qj * (z**(2*j)) ] X * over j = {0,1,2,3} X * X * P0 = -0.240139179559210509868484e2 X * P1 = 0.30957292821537650062264e2 X * P2 = -0.96376909336868659324e1 X * P3 = 0.4210873712179797145 X * Q0 = -0.120069589779605254717525e2 X * Q1 = 0.19480966070088973051623e2 X * Q2 = -0.89111090279378312337e1 X * Q3 = 1.0000 X * X * (coefficients from HART table #2705 pg 229) X * X * (7) Finally, compute log(x) from: X * X * log(x) = (k * log(2)) - log(sqrt(2)) + log(s) X */ X X#ifdef NEED_LOG X Xstatic double log_pcoeffs[] = { X -0.24013917955921050986e2, X 0.30957292821537650062e2, X -0.96376909336868659324e1, X 0.4210873712179797145 X} ; X Xstatic double log_qcoeffs[] = { X -0.12006958977960525471e2, X 0.19480966070088973051e2, X -0.89111090279378312337e1, X 1.0000 X} ; X Xdouble Xlog(x) Xdouble x ; X{ X auto int k ; X auto double pqofz, s, z, zt2 ; X auto double retval ; X X if (x == 0.0) X { X doerr("log", "SINGULARITY", EDOM) ; X retval = -MAXDOUBLE ; X } X else if (x < 0.0) X { X doerr("log", "DOMAIN", EDOM) ; X retval = -MAXDOUBLE ; X } X else X { X s = SQRT2 * frexp(x, &k) ; X z = (s - 1.0) / (s + 1.0) ; X zt2 = z * z ; X pqofz = z * (poly(3, log_pcoeffs, zt2) / poly(3, log_qcoeffs, zt2)) ; X x = k * LN2 ; X x -= LNSQRT2 ; X x += pqofz ; X retval = x ; X } X return(retval) ; X} X#endif /*NEED_LOG*/ X X X/* FUNCTION X * X * log10 double precision common log X * X * DESCRIPTION X * X * Returns double precision common log of double precision X * floating point argument. X * X * USAGE X * X * double log10(x) X * double x ; X * X * REFERENCES X * X * PDP-11 Fortran IV-plus users guide, Digital Equip. Corp., X * 1975, pp. B-3. X * X * RESTRICTIONS X * X * For precision information refer to documentation of the X * floating point library routines called. X * X * INTERNALS X * X * Computes log10(x) from: X * X * log10(x) = log10(e) * log(x) X */ X X#ifdef NEED_LOG10 Xdouble Xlog10(x) Xdouble x ; X{ X x = LOG10E * log(x) ; X return(x) ; X} X#endif /*NEED_LOG10*/ X X X/* FUNCTION X * X * mod double precision modulo X * X * DESCRIPTION X * X * Returns double precision modulo of two double X * precision arguments. X * X * USAGE X * X * double mod(value, base) X * double value ; X * double base ; X */ X X#ifdef NEED_COS || NEED_SIN Xdouble mod(value, base) Xdouble value ; Xdouble base ; X{ X auto double intpart ; X X value /= base ; X value = modf(value, &intpart) ; X value *= base ; X return(value) ; X} X#endif /*NEED_COS || NEED_SIN*/ X X X/* FUNCTION X * X * poly double precision polynomial evaluation X * X * DESCRIPTION X * X * Evaluates a polynomial and returns double precision X * result. Is passed a the order of the polynomial, X * a pointer to an array of double precision polynomial X * coefficients (in ascending order), and the independent X * variable. X * X * USAGE X * X * double poly(order, coeffs, x) X * int order ; X * double *coeffs ; X * double x ; X * X * INTERNALS X * X * Evalates the polynomial using recursion and the form: X * X * P(x) = P0 + x(P1 + x(P2 +...x(Pn))) X */ X X#ifdef NEED_ATAN || NEED_COS || NEED_LOG || NEED_SIN Xdouble Xpoly(order, coeffs, x) Xregister int order ; Xdouble *coeffs ; Xdouble x ; X{ X auto double curr_coeff, rtn_value ; X X if (order <= 0) rtn_value = *coeffs ; X else X { X curr_coeff = *coeffs ; /* Bug in Unisoft's compiler. Does not */ X coeffs++ ; /* generate good code for *coeffs++ */ X rtn_value = curr_coeff + x * poly(--order, coeffs, x) ; X } X return(rtn_value) ; X} X#endif /*NEED_ATAN || NEED_COS || NEED_LOG || NEED_SIN*/ SHAR_EOF echo "End of part 2" echo "File mathlib.c is continued in part 3" echo "3" > s2_seq_.tmp exit 0
richb@sunaus.oz (Rich Burridge) (02/02/90)
---- Cut Here and unpack ---- #!/bin/sh # this is part 3 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file mathlib.c continued # CurArch=3 if test ! -r s2_seq_.tmp then echo "Please unpack part 1 first!" exit 1; fi ( read Scheck if test "$Scheck" != $CurArch then echo "Please unpack part $Scheck next!" exit 1; else exit 0; fi ) < s2_seq_.tmp || exit 1 echo "x - Continuing file mathlib.c" sed 's/^X//' << 'SHAR_EOF' >> mathlib.c X X X/* FUNCTION X * X * sin double precision sine X * X * DESCRIPTION X * X * Returns double precision sine of double precision X * floating point argument. X * X * USAGE X * X * double sin(x) X * double x ; X * X * REFERENCES X * X * Computer Approximations, J.F. Hart et al, John Wiley & Sons, X * 1968, pp. 112-120. X * X * RESTRICTIONS X * X * The sin and cos routines are interactive in the sense that X * in the process of reducing the argument to the range -PI/4 X * to PI/4, each may call the other. Ultimately one or the X * other uses a polynomial approximation on the reduced X * argument. The sin approximation has a maximum relative error X * of 10**(-17.59) and the cos approximation has a maximum X * relative error of 10**(-16.18). X * X * These error bounds assume exact arithmetic X * in the polynomial evaluation. Additional rounding and X * truncation errors may occur as the argument is reduced X * to the range over which the polynomial approximation X * is valid, and as the polynomial is evaluated using X * finite-precision arithmetic. X * X * INTERNALS X * X * Computes sin(x) from: X * X * (1) Reduce argument x to range -PI to PI. X * X * (2) If x > PI/2 then call sin recursively X * using relation sin(x) = -sin(x - PI). X * X * (3) If x < -PI/2 then call sin recursively X * using relation sin(x) = -sin(x + PI). X * X * (4) If x > PI/4 then call cos using X * relation sin(x) = cos(PI/2 - x). X * X * (5) If x < -PI/4 then call cos using X * relation sin(x) = -cos(PI/2 + x). X * X * (6) If x is small enough that polynomial X * evaluation would cause underflow X * then return x, since sin(x) X * approaches x as x approaches zero. X * X * (7) By now x has been reduced to range X * -PI/4 to PI/4 and the approximation X * from HART pg. 118 can be used: X * X * sin(x) = y * ( p(y) / q(y) ) X * Where: X * X * y = x * (4/PI) X * X * p(y) = SUM [ Pj * (y**(2*j)) ] X * over j = {0,1,2,3} X * X * q(y) = SUM [ Qj * (y**(2*j)) ] X * over j = {0,1,2,3} X * X * P0 = 0.206643433369958582409167054e+7 X * P1 = -0.18160398797407332550219213e+6 X * P2 = 0.359993069496361883172836e+4 X * P3 = -0.2010748329458861571949e+2 X * Q0 = 0.263106591026476989637710307e+7 X * Q1 = 0.3927024277464900030883986e+5 X * Q2 = 0.27811919481083844087953e+3 X * Q3 = 1.0000... X * (coefficients from HART table #3063 pg 234) X * X * X * **** NOTE **** The range reduction relations used in X * this routine depend on the final approximation being valid X * over the negative argument range in addition to the positive X * argument range. The particular approximation chosen from X * HART satisfies this requirement, although not explicitly X * stated in the text. This may not be true of other X * approximations given in the reference. X */ X X#ifdef NEED_SIN X Xstatic double sin_pcoeffs[] = { X 0.20664343336995858240e7, X -0.18160398797407332550e6, X 0.35999306949636188317e4, X -0.20107483294588615719e2 X} ; X Xstatic double sin_qcoeffs[] = { X 0.26310659102647698963e7, X 0.39270242774649000308e5, X 0.27811919481083844087e3, X 1.0 X} ; X Xdouble Xsin(x) Xdouble x ; X{ X double y, yt2 ; X auto double retval ; X X if (x < -PI || x > PI) X { X x = mod(x, TWOPI) ; X if (x > PI) x = x - TWOPI ; X else if (x < -PI) x = x + TWOPI ; X } X if (x > HALFPI) retval = -(sin(x - PI)) ; X else if (x < -HALFPI) retval = -(sin(x + PI)) ; X else if (x > FOURTHPI) retval = cos(HALFPI - x) ; X else if (x < -FOURTHPI) retval = -(cos(HALFPI + x)) ; X else if (x < X6_UNDERFLOWS && x > -X6_UNDERFLOWS) retval = x ; X else X { X y = x / FOURTHPI ; X yt2 = y * y ; X retval = y * (poly(3, sin_pcoeffs, yt2) / poly(3, sin_qcoeffs, yt2)) ; X } X return(retval) ; X} X#endif /*NEED_SIN*/ X X X/* FUNCTION X * X * sinh double precision hyperbolic sine X * X * DESCRIPTION X * X * Returns double precision hyperbolic sine of double precision X * floating point number. X * X * USAGE X * X * double sinh(x) X * double x ; X * X * REFERENCES X * X * Fortran IV plus user's guide, Digital Equipment Corp. pp B-5 X * X * RESTRICTIONS X * X * Inputs greater than ln(MAXDOUBLE) result in overflow. X * Inputs less than ln(MINDOUBLE) result in underflow. X * X * For precision information refer to documentation of the X * floating point library routines called. X * X * INTERNALS X * X * Computes hyperbolic sine from: X * X * sinh(x) = 0.5 * (exp(x) - 1.0/exp(x)) X */ X X#ifdef NEED_SINH Xdouble Xsinh(x) Xdouble x ; X{ X auto double retval ; X X if (x > LOGE_MAXDOUBLE) X { X doerr("sinh", "OVERFLOW", ERANGE) ; X retval = MAXDOUBLE ; X } X else if (x < LOGE_MINDOUBLE) X { X doerr("sinh", "UNDERFLOW", ERANGE) ; X retval = MINDOUBLE ; X } X else X { X x = exp(x) ; X retval = 0.5 * (x - (1.0 / x)) ; X } X return(retval) ; X} X#endif /*NEED_SINH*/ X X X/* FUNCTION X * X * sqrt double precision square root X * X * DESCRIPTION X * X * Returns double precision square root of double precision X * floating point argument. X * X * USAGE X * X * double sqrt(x) X * double x ; X * X * REFERENCES X * X * Fortran IV-PLUS user's guide, Digital Equipment Corp. pp B-7. X * X * Computer Approximations, J.F. Hart et al, John Wiley & Sons, X * 1968, pp. 89-96. X * X * RESTRICTIONS X * X * The relative error is 10**(-30.1) after three applications X * of Heron's iteration for the square root. X * X * However, this assumes exact arithmetic in the iterations X * and initial approximation. Additional errors may occur X * due to truncation, rounding, or machine precision limits. X * X * INTERNALS X * X * Computes square root by: X * X * (1) Range reduction of argument to [0.5,1.0] X * by application of identity: X * X * sqrt(x) = 2**(k/2) * sqrt(x * 2**(-k)) X * X * k is the exponent when x is written as X * a mantissa times a power of 2 (m * 2**k). X * It is assumed that the mantissa is X * already normalized (0.5 =< m < 1.0). X * X * (2) An approximation to sqrt(m) is obtained X * from: X * X * u = sqrt(m) = (P0 + P1*m) / (Q0 + Q1*m) X * X * P0 = 0.594604482 X * P1 = 2.54164041 X * Q0 = 2.13725758 X * Q1 = 1.0 X * X * (coefficients from HART table #350 pg 193) X * X * (3) Three applications of Heron's iteration are X * performed using: X * X * y[n+1] = 0.5 * (y[n] + (m/y[n])) X * X * where y[0] = u = approx sqrt(m) X * X * (4) If the value of k was odd then y is either X * multiplied by the square root of two or X * divided by the square root of two for k positive X * or negative respectively. This rescales y X * by multiplying by 2**frac(k/2). X * X * (5) Finally, y is rescaled by int(k/2) which X * is equivalent to multiplication by 2**int(k/2). X * X * The result of steps 4 and 5 is that the value X * of y between 0.5 and 1.0 has been rescaled by X * 2**(k/2) which removes the original rescaling X * done prior to finding the mantissa square root. X * X * NOTES X * X * The Convergent Technologies compiler optimizes division X * by powers of two to "arithmetic shift right" instructions. X * This is ok for positive integers but gives different X * results than other C compilers for negative integers. X * For example, (-1)/2 is -1 on the CT box, 0 on every other X * machine I tried. X */ X X#ifdef NEED_SQRT X X#define ITERATIONS 3 /* Number of iterations */ X#define P0 0.594604482 /* Approximation coeff */ X#define P1 2.54164041 /* Approximation coeff */ X#define Q0 2.13725758 /* Approximation coeff */ X#define Q1 1.0 /* Approximation coeff */ X Xdouble Xsqrt(x) Xdouble x ; X{ X register int bugfix, count, kmod2 ; X auto int exponent, k ; X auto double m, u, y ; X auto double retval ; X X if (x == 0.0) retval = 0.0 ; X else if (x < 0.0) X { X doerr("sqrt", "DOMAIN", EDOM) ; X retval = 0.0 ; X } X else X { X m = frexp(x, &k) ; X u = (P0 + (P1 * m)) / (Q0 + (Q1 * m)) ; X for (count = 0, y = u; count < ITERATIONS; count++) X y = 0.5 * (y + (m / y)) ; X if ((kmod2 = (k % 2)) < 0) y /= SQRT2 ; X else if (kmod2 > 0) y *= SQRT2 ; X bugfix = 2 ; X retval = ldexp(y, k / bugfix) ; X } X return(retval) ; X} X#endif /*NEED_SQRT*/ X X X/* FUNCTION X * X * tan Double precision tangent X * X * DESCRIPTION X * X * Returns tangent of double precision floating point number. X * X * USAGE X * X * double tan(x) X * double x ; X * X * INTERNALS X * X * Computes the tangent from tan(x) = sin(x) / cos(x). X * X * If cos(x) = 0 and sin(x) >= 0, then returns largest X * floating point number on host machine. X * X * If cos(x) = 0 and sin(x) < 0, then returns smallest X * floating point number on host machine. X * X * REFERENCES X * X * Fortran IV plus user's guide, Digital Equipment Corp. pp. B-8 X */ X X#ifdef NEED_TAN Xdouble Xtan(x) Xdouble x ; X{ X double cosx, sinx ; X auto double retval ; X X sinx = sin(x) ; X cosx = cos(x) ; X if (cosx == 0.0) X { X doerr("tan", "OVERFLOW", ERANGE) ; X if (sinx >= 0.0) retval = MAXDOUBLE ; X else retval = -MAXDOUBLE ; X } X else retval = sinx / cosx ; X return(retval) ; X} X#endif /*NEED_TAN*/ X X X/* FUNCTION X * X * tanh double precision hyperbolic tangent X * X * DESCRIPTION X * X * Returns double precision hyperbolic tangent of double precision X * floating point number. X * X * USAGE X * X * double tanh(x) X * double x ; X * X * REFERENCES X * X * Fortran IV plus user's guide, Digital Equipment Corp. pp B-5 X * X * RESTRICTIONS X * X * For precision information refer to documentation of the X * floating point library routines called. X * X * INTERNALS X * X * Computes hyperbolic tangent from: X * X * tanh(x) = 1.0 for x > TANH_MAXARG X * = -1.0 for x < -TANH_MAXARG X * = sinh(x) / cosh(x) otherwise X */ X X#ifdef NEED_TANH Xdouble Xtanh(x) Xdouble x ; X{ X auto double retval ; X register int positive ; X X if (x > TANH_MAXARG || x < -TANH_MAXARG) X { X if (x > 0.0) positive = 1 ; X else positive = 0 ; X doerr("tanh", "PLOSS", ERANGE) ; X if (positive) retval = 1.0 ; X else retval = -1.0 ; X } X else retval = sinh(x) / cosh(x) ; X return(retval) ; X} X#endif /*NEED_TANH*/ X X X/* X * Copyright (c) 1985 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that the above copyright notice and this paragraph are X * duplicated in all such forms and that any documentation, X * advertising materials, and other materials related to such X * distribution and use acknowledge that the software was developed X * by the University of California, Berkeley. The name of the X * University may not be used to endorse or promote products derived X * from this software without specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. X * X * All recipients should regard themselves as participants in an ongoing X * research project and hence should feel obligated to report their X * experiences (good or bad) with these elementary function codes, using X * the sendbug(8) program, to the authors. X */ X X#ifdef NEED_POW X/* POW(X,Y) X * RETURN X**Y X * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS) X * CODED IN C BY K.C. NG, 1/8/85; X * REVISED BY K.C. NG on 7/10/85. X * X * Required system supported functions: X * scalb(x,n) X * logb(x) X * copysign(x,y) X * finite(x) X * drem(x,y) X * X * Required kernel functions: X * exp__E(a, c) ...return exp(a+c) - 1 - a*a/2 X * log__L(x) ...return (log(1+x) - 2s)/s, s=x/(2+x) X * pow_p(x, y) ...return +(anything)**(finite non zero) X * X * Method X * 1. Compute and return log(x) in three pieces: X * log(x) = n*ln2 + hi + lo, X * where n is an integer. X * 2. Perform y * log(x) by simulating muti-precision arithmetic and X * return the answer in three pieces: X * y * log(x) = m * ln2 + hi + lo, X * where m is an integer. X * 3. Return x ** y = exp(y * log(x)) X * = 2^m * (exp(hi + lo)). X * X * Special cases: X * (anything) ** 0 is 1 ; X * (anything) ** 1 is itself; X * (anything) ** NaN is NaN; X * NaN ** (anything except 0) is NaN; X * +-(anything > 1) ** +INF is +INF; X * +-(anything > 1) ** -INF is +0; X * +-(anything < 1) ** +INF is +0; X * +-(anything < 1) ** -INF is +INF; X * +-1 ** +-INF is NaN and signal INVALID; X * +0 ** +(anything except 0, NaN) is +0; X * -0 ** +(anything except 0, NaN, odd integer) is +0; X * +0 ** -(anything except 0, NaN) is +INF and signal DIV-BY-ZERO; X * -0 ** -(anything except 0, NaN, odd integer) is +INF with signal; X * -0 ** (odd integer) = -( +0 ** (odd integer) ); X * +INF ** +(anything except 0,NaN) is +INF; X * +INF ** -(anything except 0,NaN) is +0; X * -INF ** (odd integer) = -( +INF ** (odd integer) ); X * -INF ** (even integer) = ( +INF ** (even integer) ); X * -INF ** -(anything except integer,NaN) is NaN with signal; X * -(x=anything) ** (k=integer) is (-1)**k * (x ** k); X * -(anything except 0) ** (non-integer) is NaN with signal; X * X * Accuracy: X * pow(x, y) returns x**y nearly rounded. In particular, on a SUN, a VAX, X * and a Zilog Z8000, X * pow(integer, integer) X * always returns the correct integer provided it is representable. X * In a test run with 100,000 random arguments with 0 < x, y < 20.0 X * on a VAX, the maximum observed error was 1.79 ulps (units in the X * last place). X * X * Constants : X * The hexadecimal values are the intended ones for the following constants. X * The decimal values may be used, provided that the compiler will convert X * from decimal to binary accurately enough to produce the hexadecimal values X * shown. X */ X X#if defined(vax) || defined(tahoe) /* VAX D format */ X#include <errno.h> Xextern double infnan() ; X#ifdef vax X#define _0x(A,B) 0x/**/A/**/B X#else /* vax */ X#define _0x(A,B) 0x/**/B/**/A X#endif /* vax */ X/* static double */ X/* ln2hi = 6.9314718055829871446E-1 , Hex 2^ 0 * .B17217F7D00000 */ X/* ln2lo = 1.6465949582897081279E-12 , Hex 2^-39 * .E7BCD5E4F1D9CC */ X/* invln2 = 1.4426950408889634148E0 , Hex 2^ 1 * .B8AA3B295C17F1 */ X/* sqrt2 = 1.4142135623730950622E0 ; Hex 2^ 1 * .B504F333F9DE65 */ Xstatic long ln2hix[] = { _0x(7217,4031), _0x(0000,f7d0)} ; Xstatic long ln2lox[] = { _0x(bcd5,2ce7), _0x(d9cc,e4f1)} ; Xstatic long invln2x[] = { _0x(aa3b,40b8), _0x(17f1,295c)} ; Xstatic long sqrt2x[] = { _0x(04f3,40b5), _0x(de65,33f9)} ; X#define ln2hi (*(double*) ln2hix) X#define ln2lo (*(double*) ln2lox) X#define invln2 (*(double*) invln2x) X#define sqrt2 (*(double*) sqrt2x) X#else /* defined(vax)||defined(tahoe) */ Xstatic double Xln2hi = 6.9314718036912381649E-1 , /* Hex 2^ -1 * 1.62E42FEE00000 */ Xln2lo = 1.9082149292705877000E-10 , /* Hex 2^-33 * 1.A39EF35793C76 */ Xinvln2 = 1.4426950408889633870E0 , /* Hex 2^ 0 * 1.71547652B82FE */ Xsqrt2 = 1.4142135623730951455E0 ; /* Hex 2^ 0 * 1.6A09E667F3BCD */ X#endif /* defined(vax) || defined(tahoe) */ X Xstatic double zero = 0.0 ; X Xdouble Xpow(x, y) Xdouble x, y ; X{ X double drem(), pow_p(), copysign(), t ; X int finite() ; X X if (y == 0.0) return(1.0) ; X#if !defined(vax) && !defined(tahoe) X else if (y == 1.0 || x != x) return(x) ; /* if x is NaN or y = 1 */ X#else X else if (y == 1.0) return(x) ; /* if y = 1 */ X#endif /* !defined(vax) && !defined(tahoe) */ X X#if !defined(vax) && !defined(tahoe) X else if (y != y) return(y) ; /* if y is NaN */ X#endif /* !defined(vax) && !defined(tahoe) */ X else if (!finite(y)) /* if y is INF */ X if ((t = copysign(x, 1.0)) == 1.0) X return(0.0 / zero) ; X else if (t > 1.0) return((y > 0.0) ? y : 0.0) ; X else return((y < 0.0) ? -y : 0.0) ; X else if (y == 2.0) return(x * x) ; X else if (y == -1.0) return(1.0 / x) ; X X/* sign(x) = 1 */ X X else if (copysign(1.0, x) == 1.0) return(pow_p(x, y)) ; X X/* sign(x)= -1 */ X/* if y is an even integer */ X X else if ((t = drem(y, 2.0)) == 0.0) return(pow_p(-x, y)) ; X X/* if y is an odd integer */ X X else if (copysign(t, 1.0) == 1.0) return(-pow_p(-x, y)) ; X X/* Henceforth y is not an integer */ X X else if (x == 0.0) return((y > 0.0) ? -x : 1.0 / (-x)) ; /* x is -0 */ X else /* return NaN */ X { X#if defined(vax) || defined(tahoe) X return(infnan(EDOM)) ; /* NaN */ X#else /* defined(vax) || defined(tahoe) */ X return(0.0 / zero) ; X#endif /* defined(vax) || defined(tahoe) */ X } X} X X X/* pow_p(x,y) return x**y for x with sign = 1 and finite y */ X Xstatic double Xpow_p(x, y) Xdouble x, y ; X{ X double logb(), scalb(), copysign(), log__L(), exp__E() ; X double c, s, t, z, tx, ty ; X X#ifdef tahoe X double tahoe_tmp ; X#endif /* tahoe */ X float sx, sy ; X long k = 0 ; X int n, m ; X X if (x == 0.0 || !finite(x)) /* if x is +INF or +0 */ X { X X#if defined(vax) || defined(tahoe) X return((y > 0.0) ? x : infnan(ERANGE)) ; /* if y < 0.0, return +INF */ X#else /* defined(vax) || defined(tahoe) */ X return((y > 0.0) ? x : 1.0 / x) ; X#endif /* defined(vax) || defined(tahoe) */ X } X if (x == 1.0) return(x) ; /* if x = 1.0, return 1 since y is finite */ X X/* reduce x to z in [sqrt(1/2)-1, sqrt(2)-1] */ X X z = scalb(x, -(n = logb(x))) ; X X#if !defined(vax) && !defined(tahoe) /* IEEE double; subnormal number */ X if (n <= -1022) X { X n += (m = logb(z)) ; X z = scalb(z, -m) ; X } X#endif /* !defined(vax) && !defined(tahoe) */ X X if (z >= sqrt2) X { X n += 1 ; X z *= 0.5 ; X } X z -= 1.0 ; X X/* log(x) = nlog2 + log(1 + z) ~ nlog2 + t + tx */ X X s = z / (2.0 + z) ; X c = z * z * 0.5 ; X tx = s * (c + log__L(s * s)) ; X t = z - (c - tx) ; X tx += (z - t) - c ; X X/* if y * log(x) is neither too big nor too small */ X X if ((s = logb(y) + logb(n + t)) < 12.0) X if (s > -60.0) X { X X/* compute y * log(x) ~ mlog2 + t + c */ X X s = y * (n + invln2 * t) ; X m = s + copysign(0.5, s) ; /* m := nint(y * log(x)) */ X k = y ; X if ((double) k == y) /* if y is an integer */ X { X k = m - k * n ; X sx = t ; X tx += (t - sx) ; X } X else /* if y is not an integer */ X { X k = m ; X tx += n * ln2lo ; X sx = (c = n * ln2hi) + t ; X tx += (c - sx) + t ; X } X X/* end of checking whether k == y */ X X sy = y ; X ty = y - sy ; /* y ~ sy + ty */ X X#ifdef tahoe X s = (tahoe_tmp = sx) * sy - k * ln2hi ; X#else /* tahoe */ X s = (double) sx * sy - k * ln2hi ; /* (sy + ty) * (sx + tx) - kln2 */ X#endif /* tahoe */ X X z = (tx * ty - k * ln2lo) ; X tx = tx * sy ; ty = sx * ty ; X t = ty + z ; t += tx ; t += s ; X c = -((((t-s)-tx)-ty)-z) ; X X/* return exp(y * log(x)) */ X X t += exp__E(t,c) ; X return(scalb(1.0 + t, m)) ; X } X X/* end of if log(y * log(x)) > -60.0 */ X X else /* exp(+- tiny) = 1 with inexact flag */ X { X ln2hi + ln2lo ; X return(1.0) ; X } X else if (copysign(1.0, y) * (n + invln2 * t) < 0.0) X return(scalb(1.0, -5000)) ; /* exp(-(big#)) underflows to zero */ X else X return(scalb(1.0, 5000)) ; /* exp(+(big#)) overflows to INF */ X} X X X/* Some IEEE standard 754 recommended functions and remainder and sqrt for X * supporting the C elementary functions. X ****************************************************************************** X * WARNING: X * These codes are developed (in double) to support the C elementary X * functions temporarily. They are not universal, and some of them are very X * slow (in particular, drem and sqrt is extremely inefficient). Each X * computer system should have its implementation of these functions using X * its own assembler. X ****************************************************************************** X * X * IEEE 754 required operations: X * drem(x, p) X * returns x REM y = x - [x/y]*y , where [x/y] is the integer X * nearest x/y; in half way case, choose the even one. X * sqrt(x) X * returns the square root of x correctly rounded according to X * the rounding mod. X * X * IEEE 754 recommended functions: X * (a) copysign(x, y) X * returns x with the sign of y. X * (b) scalb(x, N) X * returns x * (2 ** N), for integer values N. X * (c) logb(x) X * returns the unbiased exponent of x, a signed integer in X * double precision, except that logb(0) is -INF, logb(INF) X * is +INF, and logb(NAN) is that NAN. X * (d) finite(x) X * returns the value TRUE if -INF < x < +INF and returns X * FALSE otherwise. X * X * CODED IN C BY K.C. NG, 11/25/84; X * REVISED BY K.C. NG on 1/22/85, 2/13/85, 3/24/85. X */ X X#if defined(vax) || defined(tahoe) /* VAX D format */ X static unsigned short msign = 0x7fff, mexp = 0x7f80 ; X static short prep1 = 57, gap = 7, bias = 129 ; X static double novf = 1.7E38, nunf = 3.0E-39 ; X#else /* defined(vax) || defined(tahoe) */ X static unsigned short msign = 0x7fff, mexp = 0x7ff0 ; X static short prep1 = 54, gap = 4, bias = 1023 ; X static double novf = 1.7E308, nunf = 3.0E-308 ; X#endif /* defined(vax) || defined(tahoe) */ X Xdouble Xscalb(x, N) Xdouble x ; Xint N ; X{ X int k ; X double scalb() ; X X#ifdef national X unsigned short *px = (unsigned short *) &x + 3 ; X#else /* national */ X unsigned short *px = (unsigned short *) &x ; X#endif /* national */ X X if (x == 0.0) return(x) ; X X#if defined(vax) || defined(tahoe) X X if ((k = *px & mexp) != ~msign) X { X if (N < -260) return(nunf * nunf) ; X else if (N > 260) X { X extern double infnan(), copysign() ; X return(copysign(infnan(ERANGE), x)) ; X } X#else /* defined(vax) || defined(tahoe) */ X X if ((k = *px & mexp) != mexp) X { X if (N < -2100) return(nunf * nunf) ; X else if (N > 2100) return(novf + novf) ; X if (k == 0) X { X x *= scalb(1.0, (int) prep1) ; X N -= prep1 ; X return(scalb(x, N)) ; X } X#endif /* defined(vax) || defined(tahoe) */ X X if ((k = (k >> gap) + N) > 0) X if (k < (mexp >> gap)) *px = (*px & ~mexp) | (k << gap) ; X else x = novf + novf ; /* overflow */ X else X if (k > -prep1) X { /* gradual underflow */ X *px = (*px & ~mexp) | (short) (1 << gap) ; X x *= scalb(1.0, k-1) ; X } X else return(nunf * nunf) ; X } X return(x) ; X} X X Xdouble Xcopysign(x, y) Xdouble x, y ; X{ X#ifdef national X unsigned short *px = (unsigned short *) &x + 3, X *py = (unsigned short *) &y + 3 ; X#else /* national */ X unsigned short *px = (unsigned short *) &x, X *py = (unsigned short *) &y ; X#endif /* national */ X X#if defined(vax) || defined(tahoe) X if ((*px & mexp) == 0) return(x) ; X#endif /* defined(vax) || defined(tahoe) */ X X *px = (*px & msign) | (*py & ~msign) ; X return(x) ; X} X X Xdouble Xlogb(x) Xdouble x ; X{ X#ifdef national X short *px = (short *) &x + 3, k ; X#else /* national */ X short *px = (short *) &x, k ; X#endif /* national */ X X#if defined(vax) || defined(tahoe) X return (int) (((*px & mexp) >> gap) - bias) ; X#else /* defined(vax) || defined(tahoe) */ X X if ((k = *px & mexp) != mexp) X if (k != 0) return((k >> gap) - bias) ; X else if (x != 0.0) return(-1022.0) ; X else return(-(1.0 / zero)) ; X else if (x != x) return(x) ; X else X { X *px &= msign ; X return(x) ; X } X#endif /* defined(vax) || defined(tahoe) */ X} X X Xfinite(x) Xdouble x ; X{ X#if defined(vax) || defined(tahoe) X return(1) ; X#else /* defined(vax) || defined(tahoe) */ X#ifdef national X return((*((short *) &x + 3) & mexp) != mexp) ; X#else /* national */ X return((*((short *) &x) & mexp) != mexp) ; X#endif /* national */ X#endif /* defined(vax) || defined(tahoe) */ X} X X Xdouble Xdrem(x, p) Xdouble x, p ; X{ X short sign ; X double hp, dp, tmp, drem(), scalb() ; X unsigned short k ; X X#ifdef national X unsigned short *px = (unsigned short *) &x + 3, X *pp = (unsigned short *) &p + 3, X *pd = (unsigned short *) &dp + 3, X *pt = (unsigned short *) &tmp + 3 ; X#else /* national */ X unsigned short *px = (unsigned short *) &x, X *pp = (unsigned short *) &p , X *pd = (unsigned short *) &dp , X *pt = (unsigned short *) &tmp ; X#endif /* national */ X X *pp &= msign ; X X#if defined(vax) || defined(tahoe) X if ((*px & mexp) == ~msign) /* is x a reserved operand? */ X#else /* defined(vax) || defined(tahoe) */ X if ((*px & mexp) == mexp) X#endif /* defined(vax) || defined(tahoe) */ X return (x-p) - (x-p) ; /* create nan if x is inf */ X X if (p == 0.0) X { X doerr("drem", "SINGULARITY", EDOM) ; X#if defined(vax) || defined(tahoe) X extern double infnan() ; X return(infnan(EDOM)) ; X#else /* defined(vax) || defined(tahoe) */ X return(0.0 / zero) ; X#endif /* defined(vax) || defined(tahoe) */ X } X X#if defined(vax) || defined(tahoe) X if ((*pp & mexp) == ~msign) /* is p a reserved operand? */ X#else /* defined(vax) || defined(tahoe) */ X if ((*pp & mexp) == mexp) X#endif /* defined(vax)||defined(tahoe) */ X { X if (p != p) return p ; X else return x ; X } X else if (((*pp & mexp) >> gap) <= 1) X X/* subnormal p, or almost subnormal p */ X X { X double b ; X b = scalb(1.0, (int) prep1) ; X p *= b ; X x = drem(x, p) ; X x *= b ; X return(drem(x, p) / b) ; X } X else if (p >= novf / 2) X { X p /= 2 ; X x /= 2 ; X return(drem(x, p) * 2) ; X } X else X { X dp = p + p ; X hp = p / 2 ; X sign = *px & ~msign ; X *px &= msign ; X while (x > dp) X { X k = (*px & mexp) - (*pd & mexp) ; X tmp = dp ; X *pt += k ; X X#if defined(vax) || defined(tahoe) X if (x < tmp) *pt -= 128 ; X#else /* defined(vax) || defined(tahoe) */ X if (x < tmp) *pt -= 16 ; X#endif /* defined(vax) || defined(tahoe) */ X X x -= tmp ; X } X if (x > hp) X { X x -= p ; X if (x >= hp) x -= p ; X } X X#if defined(vax) || defined(tahoe) X if (x) X#endif /* defined(vax) || defined(tahoe) */ X *px ^= sign ; X return(x) ; X } X} X X X/* exp__E(x,c) X * ASSUMPTION: c << x SO THAT fl(x+c)=x. X * (c is the correction term for x) X * exp__E RETURNS X * X * / exp(x+c) - 1 - x , 1E-19 < |x| < .3465736 X * exp__E(x,c) = | X * \ 0 , |x| < 1E-19. X * X * DOUBLE PRECISION (IEEE 53 bits, VAX D FORMAT 56 BITS) X * KERNEL FUNCTION OF EXP, EXPM1, POW FUNCTIONS X * CODED IN C BY K.C. NG, 1/31/85; X * REVISED BY K.C. NG on 3/16/85, 4/16/85. X * X * Required system supported function: X * copysign(x,y) X * X * Method: X * 1. Rational approximation. Let r=x+c. X * Based on X * 2 * sinh(r/2) X * exp(r) - 1 = ---------------------- , X * cosh(r/2) - sinh(r/2) X * exp__E(r) is computed using X * x*x (x/2)*W - ( Q - ( 2*P + x*P ) ) X * --- + (c + x*[---------------------------------- + c ]) X * 2 1 - W X * where P := p1*x^2 + p2*x^4, X * Q := q1*x^2 + q2*x^4 (for 56 bits precision, add q3*x^6) X * W := x/2-(Q-x*P), X * X * (See the listing below for the values of p1,p2,q1,q2,q3. The poly- X * nomials P and Q may be regarded as the approximations to sinh X * and cosh : X * sinh(r/2) = r/2 + r * P , cosh(r/2) = 1 + Q . ) X * X * The coefficients were obtained by a special Remez algorithm. X * X * Approximation error: X * X * | exp(x) - 1 | 2**(-57), (IEEE double) X * | ------------ - (exp__E(x,0)+x)/x | <= X * | x | 2**(-69). (VAX D) X * X * Constants: X * The hexadecimal values are the intended ones for the following constants. X * The decimal values may be used, provided that the compiler will convert X * from decimal to binary accurately enough to produce the hexadecimal values X * shown. X */ X X#if defined(vax) || defined(tahoe) /* VAX D format */ X#ifdef vax X#define _0x(A,B) 0x/**/A/**/B X#else /* vax */ X#define _0x(A,B) 0x/**/B/**/A X#endif /* vax */ X X/* static double */ X/* p1 = 1.5150724356786683059E-2 , Hex 2^ -6 * .F83ABE67E1066A */ X/* p2 = 6.3112487873718332688E-5 , Hex 2^-13 * .845B4248CD0173 */ X/* q1 = 1.1363478204690669916E-1 , Hex 2^ -3 * .E8B95A44A2EC45 */ X/* q2 = 1.2624568129896839182E-3 , Hex 2^ -9 * .A5790572E4F5E7 */ X/* q3 = 1.5021856115869022674E-6 ; Hex 2^-19 * .C99EB4604AC395 */ X Xstatic long p1x[] = { _0x(3abe,3d78), _0x(066a,67e1) } ; Xstatic long p2x[] = { _0x(5b42,3984), _0x(0173,48cd) } ; Xstatic long q1x[] = { _0x(b95a,3ee8), _0x(ec45,44a2) } ; Xstatic long q2x[] = { _0x(7905,3ba5), _0x(f5e7,72e4) } ; Xstatic long q3x[] = { _0x(9eb4,36c9), _0x(c395,604a) } ; X#define p1 (*(double*) p1x) X#define p2 (*(double*) p2x) X#define q1 (*(double*) q1x) X#define q2 (*(double*) q2x) X#define q3 (*(double*) q3x) X#else /* defined(vax) || defined(tahoe) */ X Xstatic double Xp1 = 1.3887401997267371720E-2, /* Hex 2^ -7 * 1.C70FF8B3CC2CF */ Xp2 = 3.3044019718331897649E-5, /* Hex 2^-15 * 1.15317DF4526C4 */ Xq1 = 1.1110813732786649355E-1, /* Hex 2^ -4 * 1.C719538248597 */ Xq2 = 9.9176615021572857300E-4 ; /* Hex 2^-10 * 1.03FC4CB8C98E8 */ X#endif /* defined(vax) || defined(tahoe) */ X Xdouble Xexp__E(x, c) Xdouble x, c ; X{ X static double small = 1.0E-19 ; X double copysign(), z, p, q, xp, xh, w ; X X if (copysign(x, 1.0) > small) X { X z = x * x ; X p = z * (p1 + z * p2) ; X X#if defined(vax) || defined(tahoe) X q = z * (q1 + z * (q2 + z * q3)) ; X#else /* defined(vax) || defined(tahoe) */ X q = z * (q1 + z * q2) ; X#endif /* defined(vax) || defined(tahoe) */ X xp = x * p ; X xh = x * 0.5 ; X w = xh - (q - xp) ; X p = p + p ; X c += x * ((xh * w - (q - (p + xp))) / (1.0 - w) + c) ; X return(z * 0.5 + c) ; X } X X/* end of |x| > small */ X X else X { X if (x != 0.0) 1.0 + small ; /* raise the inexact flag */ X return(copysign(0.0, x)) ; X } X} X X X/* log__L(Z) X * LOG(1+X) - 2S X X * RETURN --------------- WHERE Z = S*S, S = ------- , 0 <= Z <= .0294... * S 2 + X X * X * DOUBLE PRECISION (VAX D FORMAT 56 bits or IEEE DOUBLE 53 BITS) X * KERNEL FUNCTION FOR LOG; TO BE USED IN LOG1P, LOG, AND POW FUNCTIONS X * CODED IN C BY K.C. NG, 1/19/85; X * REVISED BY K.C. Ng, 2/3/85, 4/16/85. X * X * Method : X * 1. Polynomial approximation: let s = x/(2+x). X * Based on log(1+x) = log(1+s) - log(1-s) X * = 2s + 2/3 s**3 + 2/5 s**5 + ....., X * X * (log(1+x) - 2s)/s is computed by X * X * z*(L1 + z*(L2 + z*(... (L7 + z*L8)...))) X * X * where z=s*s. (See the listing below for Lk's values.) The X * coefficients are obtained by a special Remez algorithm. X * X * Accuracy: X * Assuming no rounding error, the maximum magnitude of the approximation X * error (absolute) is 2**(-58.49) for IEEE double, and 2**(-63.63) X * for VAX D format. X * X * Constants: X * The hexadecimal values are the intended ones for the following constants. X * The decimal values may be used, provided that the compiler will convert X * from decimal to binary accurately enough to produce the hexadecimal values X * shown. X */ X X#if defined(vax) || defined(tahoe) /* VAX D format (56 bits) */ X#ifdef vax X#define _0x(A,B) 0x/**/A/**/B X#else /* vax */ X#define _0x(A,B) 0x/**/B/**/A X#endif /* vax */ X X/* static double */ X/* L1 = 6.6666666666666703212E-1 , Hex 2^ 0 * .AAAAAAAAAAAAC5 */ X/* L2 = 3.9999999999970461961E-1 , Hex 2^ -1 * .CCCCCCCCCC2684 */ X/* L3 = 2.8571428579395698188E-1 , Hex 2^ -1 * .92492492F85782 */ X/* L4 = 2.2222221233634724402E-1 , Hex 2^ -2 * .E38E3839B7AF2C */ X/* L5 = 1.8181879517064680057E-1 , Hex 2^ -2 * .BA2EB4CC39655E */ X/* L6 = 1.5382888777946145467E-1 , Hex 2^ -2 * .9D8551E8C5781D */ X/* L7 = 1.3338356561139403517E-1 , Hex 2^ -2 * .8895B3907FCD92 */ X/* L8 = 1.2500000000000000000E-1 , Hex 2^ -2 * .80000000000000 */ X Xstatic long L1x[] = { _0x(aaaa,402a), _0x(aac5,aaaa) } ; Xstatic long L2x[] = { _0x(cccc,3fcc), _0x(2684,cccc) } ; Xstatic long L3x[] = { _0x(4924,3f92), _0x(5782,92f8) } ; Xstatic long L4x[] = { _0x(8e38,3f63), _0x(af2c,39b7) } ; Xstatic long L5x[] = { _0x(2eb4,3f3a), _0x(655e,cc39) } ; Xstatic long L6x[] = { _0x(8551,3f1d), _0x(781d,e8c5) } ; Xstatic long L7x[] = { _0x(95b3,3f08), _0x(cd92,907f) } ; Xstatic long L8x[] = { _0x(0000,3f00), _0x(0000,0000) } ; X X#define L1 (*(double*) L1x) X#define L2 (*(double*) L2x) X#define L3 (*(double*) L3x) X#define L4 (*(double*) L4x) X#define L5 (*(double*) L5x) X#define L6 (*(double*) L6x) X#define L7 (*(double*) L7x) X#define L8 (*(double*) L8x) X#else /* defined(vax) || defined(tahoe) */ X Xstatic double XL1 = 6.6666666666667340202E-1, /* Hex 2^ -1 * 1.5555555555592 */ XL2 = 3.9999999999416702146E-1, /* Hex 2^ -2 * 1.999999997FF24 */ XL3 = 2.8571428742008753154E-1, /* Hex 2^ -2 * 1.24924941E07B4 */ XL4 = 2.2222198607186277597E-1, /* Hex 2^ -3 * 1.C71C52150BEA6 */ XL5 = 1.8183562745289935658E-1, /* Hex 2^ -3 * 1.74663CC94342F */ XL6 = 1.5314087275331442206E-1, /* Hex 2^ -3 * 1.39A1EC014045B */ XL7 = 1.4795612545334174692E-1 ; /* Hex 2^ -3 * 1.2F039F0085122 */ X#endif /* defined(vax) || defined(tahoe) */ X Xdouble Xlog__L(z) Xdouble z ; X{ X#if defined(vax) || defined(tahoe) X return(z * (L1 + z * (L2 + z * (L3 + z * (L4 + z * X (L5 + z * (L6 + z * (L7 + z * L8)))))))) ; X#else /* defined(vax) || defined(tahoe) */ X return(z * (L1 + z * (L2 + z * (L3 + z * (L4 + z * X (L5 + z * (L6 + z * L7))))))) ; X#endif /* defined(vax) || defined(tahoe) */ X} X#endif /*NEED_POW*/ SHAR_EOF echo "File mathlib.c is complete" chmod 0444 mathlib.c || echo "restore of mathlib.c fails" set `wc -c mathlib.c`;Sum=$1 if test "$Sum" != "66590" then echo original size 66590, current size $Sum;fi rm -f s2_seq_.tmp echo "You have unpacked the last part" exit 0