v18i064: GL Graphics Library for AT-clone Unix, Part06/07

Rich Salz rsalz at uunet.uu.net
Sat Mar 25 03:58:55 AEST 1989


Submitted-by: umix!m-net!dtlewis!lewis
Posting-number: Volume 18, Issue 64
Archive-name: gl_plot/part06

# To recover, type "sh archive"
echo restoring config.h
sed 's/^X//' > config.h <<XxX--EOF--XxX
X/*	@(#) config.h 5.1 89/02/20	*/
X/*
X *	Copyright (c) David T. Lewis 1987, 1988
X *	All rights reserved.
X *
X *	Permission is granted to use this for any personal noncommercial use.
X *	You may not distribute source or executable code for profit, nor
X *	may you distribute it with a commercial product without the written
X *	consent of the author.  Please send modifications to the author for
X *	inclusion in updates to the program.  Thanks.
X */
X
X/* User modifiable parameters for GL graphics library.			*/
X/* ===> BEGIN USER MODIFIABLE PARAMETERS <===				*/
X
X/* Select one of the following to specify your target system (Xenix	*/
X/* cross compile to MS_DOS should select MS_DOS).			*/
X
X#define SVAT 1
X#define XENIX_286 0
X#define MS_DOS 0
X#define UNIX_386 0	/* (not yet supported) */
X#define XENIX_386 0	/* (not yet supported) */
X
X/* If you defined MS_DOS 1, then specify your compiler here.		*/
X
X#if MS_DOS
X#define XEN2DOS 1	/* Compile on Xenix 286 for DOS target system	*/
X#define USOFT 0		/* Microsoft C under DOS			*/
X#define TCC 0		/* Borland Turbo-C				*/
X#define MIX_C 0		/* The old CP/M derived MIX-C compiler		*/
X#endif /* MS_DOS */
X
X/* The following should be defined if you do NOT have a numeric		*/
X/* coprocessor.  It will cause some trig functions to be done with	*/
X/* integer math (see trig.c).						*/
X
X#define NOFLOAT 1
X
X/* The following should be defined if you want the gl library to handle	*/
X/* interrupt signals.  This will clear the screen and return to text	*/
X/* mode when the interrupt key (or ^C, for MS-DOS) is pressed.  If you	*/
X/* need to do your own signal routine (to close files, for example),	*/
X/* you may prefer not to have this defined.				*/
X
X#define DO_CLEANUP 1
X
X/* VIDEO stuff:								*/
X
X/* Define the name of the program or shell script which will be used	*/
X/* to switch video modes (UNIX only).  This will be made from either	*/
X/* the mode.c program, or the mode.sh shell script, or some equivalent	*/
X/* program that works with your system and video adapter.		*/
X
X#define MODEPROG "mode"
X/* Another possible choice:						*/
X/* #define MODEPROG "/usr/local/bin/mode"				*/
X
X/* Define the name of the environment variable that you wish to use to 	*/
X/* indicate your default graphics mode.  If we call g_init(ENV_MODE),	*/
X/* then we will use this environment variable to set the graphics mode.	*/
X
X#define GL_ENV_MODE "GLMODE"
X
X/* If the environment variable is not set, then fall back to 		*/
X/* DEFAULT_MODE as a last resort.  Mode 4 is CGA color mode, a safe	*/
X/* choice for most systems.						*/
X
X#define DEFAULT_MODE 4
X
X/* PRINTER stuff:							*/
X
X/* Define name of the environment variable that you wish to set to 	*/
X/* indicate your default print device.					*/
X
X#define GL_PLOT_DEV "PLOTDEV"
X
X/* For MS-DOS, define your printer device name (and ignore the rest	*/
X/* of the printer stuff that follows).  Note: Microsoft compilers will	*/
X/* send output to "stdprn" regardless of how you define this; other 	*/
X/* compilers will use the device you define below.  See code in 	*/
X/* g_finish.c if you need to change this.				*/
X
X#define DOSPRINTER "PRN:"
X
X/* Define the standard print spooler program for your system (UNIX).	*/
X
X#define PRINTPROG "/usr/bin/lp"
X#define LP_DEV_FLAG "-d"
X
X/* Define the device to use if GL_PLOT_DEV is not set.			*/
X/* Note:  Use "lp" only if you plan to manually put the printer		*/
X/* driver in transparency mode (see lpset(1M)).				*/
X/* On Microport, your printer devices might look something like the	*/
X/* following, where /dev/lp is the standard printer driver, and		*/
X/* /dev/lpt is the transparency mode printer driver.  See the "Readme"	*/
X/* file for more information.						*/
X/* 									*/
X/* \$ ls -li /dev/lp*							*/
X/*   82 crw-rw-rw-   2 root     sys        7,  0 Oct  9 18:03 /dev/lp	*/
X/*   82 crw-rw-rw-   2 root     sys        7,  0 Oct  9 18:03 /dev/lp0	*/
X/*   83 crw-rw-rw-   1 root     sys        7,  1 Feb 11  1988 /dev/lp1	*/
X/*  295 crw-rw-rw-   2 root     sys        7,128 Oct  9 18:08 /dev/lpt	*/
X/*  295 crw-rw-rw-   2 root     sys        7,128 Oct  9 18:08 /dev/lpt0	*/
X/*  291 crw-rw-rw-   1 root     sys        7,129 May 22 18:42 /dev/lpt1	*/
X
X#define PRINTDEV "lpt"
X
X/* You may need to tweak the following in order to get round circles.	*/
X
X#define HERC_ASPECT_RATIO 0.7
X#define CGA_ASPECT_RATIO 0.85
X#define EGA_ASPECT_RATIO 0.6
X#define IBM_PR_ASPECT_RATIO 0.7
X#define LJ_PR_ASPECT_RATIO 0.81
X
X/* For Xenix System V 286, you must indicate the video adapter you	*/
X/* are using.  Microport users can ignore this (they must, however, 	*/
X/* create a shared memory key with shmcreate(1).  MS-DOS users may	*/
X/* also ignore this.							*/
X
X#define GL_CGA 0
X#define GL_EGA 1
X#define GL_HERC 0
X#define GL_PGA 0	/* (not implemented)				*/
X#define GL_VGA 0	/* (easy to do, but not implemented)		*/
X
X/* The following definitions specify the shared memory key identifiers	*/
X/* which are used by Microport System V/AT.  You are free to use any	*/
X/* identifiers you want to map to video memory with shmcreate(1).	*/
X/* The following are the recommended values.  If you use these, the	*/
X/* key values will be the same as the physical memory addresses.	*/
X/* Change these definitions only if you are using different shared	*/
X/* memory keys for your system.  Xenix users may ignore this.		*/
X
X#define MCA_KEY 0xB0000L
X#define CGA_KEY 0xB8000L
X#define HERC_P0KEY 0xB0000L
X#define HERC_P1KEY 0xB8000L
X#define EGA_KEY 0xA0000L
X
X/* ===> END USER MODIFIABLE PARAMETERS <===				*/
X
X/* The following definitions specify the physical memory locations of	*/
X/* video memory, for use with MS-DOS.					*/
X
X#define DOS_MCA 0xB0000000L
X#define DOS_CGA 0xB8000000L
X#define DOS_H_P0 0xB0000000L
X#define DOS_H_P1 0xB8000000L
X#define DOS_EGA 0xA0000000L
X
X/* Some specific system dependent characteristics.			*/
X
X#if MIX_C
X#define HAS_SIG 0	/* System does not have ^C interrupt handling	*/
X#else
X#if USOFT
X#define HAS_SIG 0	/* System does not have ^C interrupt handling	*/
X#else
X#if XEN2DOS
X#define HAS_SIG 0	/* System does not have ^C interrupt handling	*/
X#else
X#define HAS_SIG 1	/* System has ^C interrupt handling		*/
X#endif /* XEN2DOS */
X#endif /* USOFT */
X#endif /* MIX_C */
X
X#if MIX_C
X#define HAS_ENV 0	/* System does not have getenv() call		*/
X#else
X#define HAS_ENV 1	/* System has getenv() call			*/
X#endif /* MIX_C */
X
X#if MS_DOS
X#define HAS_PIPES 0	/* System does not have popen() call		*/
X#else
X#define HAS_PIPES 1	/* System has popen() call			*/
X#endif /* MS_DOS */
X
X#if USOFT
X#define HAS_SLEEP 0	/* System does not have sleep() call		*/
X#else
X#if XEN2DOS
X#define HAS_SLEEP 0	/* System does not have sleep() call		*/
X#else
X#if MIX_C
X#define HAS_SLEEP 0	/* System does not have sleep() call		*/
X#else
X#define HAS_SLEEP 1	/* System has sleep() call			*/
X#endif /* MIX_C */
X#endif /* XEN2DOS */
X#endif /* USOFT */
X
X#if MIX_C
X#define HAS_FMOD 0	/* System does not have fmod() call		*/
X#else
X#define HAS_FMOD 1	/* System has fmod() call			*/
X#endif /* MIX_C */
X
X#if MIX_C
X#define HAS_ATAN2 0	/* System does not have atan2() call		*/
X#else
X#define HAS_ATAN2 1	/* System has atan2() call			*/
X#endif /* MIX_C */
X
X/* Some MS-DOS compilers have "stdprn" predefined for stream output to	*/
X/* the printer.								*/
X
X#if USOFT
X#define HAS_STDPRN 1
X#else
X#if XEN2DOS
X#define HAS_STDPRN 1
X#else
X#if TCC
X#define HAS_STDPRN 1
X#else /* "stdprn" is not predefined	*/
X#define HAS_STDPRN 0
X#endif /* TCC */
X#endif /* XEN2DOS */
X#endif /* USOFT */
X
X/* The following should be defined for 286 versions, in which an	*/
X/* integer is 16 bits.  Other machines must do extra work to check	*/
X/* for out of range on the normalized 2-D screen space (0 through	*/
X/* 32767).								*/
X
X#if MS_DOS
X#else
X#if XENIX_286
X#else
X#if SVAT
X#define INT16 1
X#else	/* Not a 16 bit integer machine	*/
X#define INT16 0
X#endif /* SVAT */
X#endif /* XENIX_286 */
X#endif /* MS_DOS */
X
X/* Parameter to signal call is system dependent.  Define a macro to 	*/
X/* handle the difference between pointer to void and pointer to int.	*/
X
X#if TCC
X#define SIG_TYPE void
X#else
X#define SIG_TYPE int
X#endif /* TCC */
X
X/* Some compilers can use a macro for the calculation for transform 	*/
X/* from normalized 2-D to screen coordinates.  If yours can't, then	*/
X/* define N_TO_P_MACRO as 0.						*/
X/* (All the compilers I've tried are working now with the macro.  Leave	*/
X/* this here just in case...)						*/
X
X#define N_TO_P_MACRO 1
X
X/* Compiler specific stuff for MS-DOS.					*/
X
X/* For MS-DOS, use the DO_BIOS macro to point to the library routine	*/
X/* that invokes a BIOS call.  Int is the interrupt number, and reg 	*/
X/* is a pointer to a structure representing machine registers.		*/
X/* Define REGISTERS as the name of the data structure for machine	*/
X/* registers (probably declared in <stdlib.h>).				*/
X/* The remaining macros (AL, AH ...) specify individual registers	*/
X/* within the REGISTERS data structure, as they would be referenced	*/
X/* in a	REGISTERS structure (e.g. "inreg.AH").				*/
X
X#if MIX_C
X#define DO_BIOS(int,inreg,outreg) bios(int,inreg) 
X#define REGISTERS REGS
X#define AL byte.al
X#define AH byte.ah
X#define BL byte.bl
X#define BH byte.bh
X#define CL byte.cl
X#define CH byte.ch
X#define DL byte.dl
X#define DH byte.dh
X#endif /* MIX_C */
X
X#if USOFT
X#define DO_BIOS(int,inreg,outreg) int86(int,inreg,outreg)
X#define REGISTERS union REGS
X#define AL h.al
X#define AH h.ah
X#define BL h.bl
X#define BH h.bh
X#define CL h.cl
X#define CH h.ch
X#define DL h.dl
X#define DH h.dh
X#endif /* USOFT */
X
X#if XEN2DOS
X#define DO_BIOS(int,inreg,outreg) int86(int,inreg,outreg)
X#define REGISTERS union REGS
X#define AL h.al
X#define AH h.ah
X#define BL h.bl
X#define BH h.bh
X#define CL h.cl
X#define CH h.ch
X#define DL h.dl
X#define DH h.dh
X#endif /* XEN2DOS */
X
X#if TCC
X#define DO_BIOS(int,inreg,outreg) int86(int,inreg,outreg)
X#define REGISTERS union REGS
X#define AL h.al
X#define AH h.ah
X#define BL h.bl
X#define BH h.bh
X#define CL h.cl
X#define CH h.ch
X#define DL h.dl
X#define DH h.dh
X#endif /* TCC */
X
XxX--EOF--XxX
echo restoring g_fntctl.c
sed 's/^X//' > g_fntctl.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) g_fntctl.c 5.1 89/02/20";
X#endif
X
X/*
X *	Copyright (c) David T. Lewis 1988
X *	All rights reserved.
X *
X *	Permission is granted to use this for any personal noncommercial use.
X *	You may not distribute source or executable code for profit, nor
X *	may you distribute it with a commercial product without the written
X *	consent of the author.  Please send modifications to the author for
X *	inclusion in updates to the program.  Thanks.
X */
X
X/* Control size, aspect ratio, spacing, angle and slant of stroke font.	*/
X/* Size, aspect ratio and spacing control height, relative width and	*/
X/* relative spacing of characters, with 1.0 selecting default values.	*/
X/* Changing size will change the width and spacing appropriately.	*/
X/* Changing width will change the spacing.				*/
X/* Angle is the angle of a text string in radians, with positive	*/
X/* values rotating the text clockwise.  Slant is the character slant	*/
X/* in radians (typically a number on the order of 0.2), with positive	*/
X/* values slanting the text to the "right," as in italics.		*/
X
X#include "config.h"
X#include "bitmaps.h"
X#include "graphics.h"
X
Xextern struct GL_graphics graphics;
X
Xint g_fontctl(size, aspect_ratio, spacing, angle, slant)
Xfloat size, aspect_ratio, spacing, angle, slant;
X
X{
X	graphics.strokefont.xtic
X		= (int)(size * aspect_ratio * spacing *
X		(float)graphics.default_strokefont.xtic);
X	graphics.strokefont.ytic
X		= (int)(size * (float)graphics.default_strokefont.ytic);
X	graphics.strokefont.xsize
X		= (int)(size * aspect_ratio * 
X		(float)graphics.default_strokefont.xsize);
X	graphics.strokefont.ysize
X		= (int)(size * (float)graphics.default_strokefont.ysize);
X	graphics.strokefont.angle = angle;
X	graphics.strokefont.slant = slant;
X
X	if (angle == 0.0) graphics.strokefont.angle_flag = FALSE;
X	else graphics.strokefont.angle_flag = TRUE;
X
X	if (slant == 0.0) graphics.strokefont.slant_flag = FALSE;
X	else graphics.strokefont.slant_flag = TRUE;
X
X	return(0);
X}
X
XxX--EOF--XxX
echo restoring gf_types.h
sed 's/^X//' > gf_types.h <<XxX--EOF--XxX
X/****** Warning! Do not alter this file without updating gl.h! *******/
X
X/*	@(#) gf_types.h 5.1 89/02/20	*/
X/*
X *	Copyright (c) David T. Lewis 1988
X *	All rights reserved.
X *
X *	Permission is granted to use this for any personal noncommercial use.
X *	You may not distribute source or executable code for profit, nor
X *	may you distribute it with a commercial product without the written
X *	consent of the author.  Please send modifications to the author for
X *	inclusion in updates to the program.  Thanks.
X */
X
X/*	Definition(s) required for more than one include file.
X */
X
X/* Define pixel setting modes. 			*/
X
X#define CLEAR 0
X#define AND 1
X#define OR 2
X#define XOR 3
X
X/* Define colors.	 			*/
X
X#define BLACK        0
X#define BLUE         1
X#define GREEN        2
X#define CYAN         3
X#define RED          4
X#define MAGENTA      5
X#define BROWN        6
X#define WHITE        7
X#define GREY         8
X#define LT_BLUE      9
X#define LT_GREEN    10
X#define LT_CYAN     11
X#define LT_RED      12
X#define LT_MAGENTA  13
X#define YELLOW      14
X#define LT_WHITE    15
X
X/* Define line styles (not yet implemented).	*/
X
X#define SOLID 0xffffffffL	/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  */
X#define DOTTED 0x66666666L	/* XX..XX..XX..XX..XX..XX..XX..XX..  */
X#define DASHED 0xffe0ffe0L	/* XXXXXXXXXXX.....XXXXXXXXXXX.....  */
X#define SHORTDASHED 0xf8f8f8f8L	/* XXXXX...XXXXX...XXXXX...XXXXX...  */
X#define LONGDASHED 0xffffff00L	/* XXXXXXXXXXXXXXXXXXXXXXXX........  */
X#define DOTDASHED 0xfc30fc30L	/* XXXXXX....XX....XXXXXX....XX....  */
X
X/* Define line weights (not yet implemented).	*/
X
X#define LIGHT 1
X#define MEDIUM 2
X#define HEAVY 4
X
X
XxX--EOF--XxX
echo restoring gl.h
sed 's/^X//' > gl.h <<XxX--EOF--XxX
X/*	@(#) gl.h 5.1 89/02/20	*/
X/*
X *	Copyright (c) David T. Lewis 1988
X *	All rights reserved.
X *
X *	Permission is granted to use this for any personal noncommercial use.
X *	You may not distribute source or executable code for profit, nor
X *	may you distribute it with a commercial product without the written
X *	consent of the author.  Please send modifications to the author for
X *	inclusion in updates to the program.  Thanks.
X */
X
X/*	This file defines the interface to the graphics library, and should
X *	be included in user programs.
X */
X
X/* Definition of programming interface to gl library.	*/
X
Xextern int g_clear();
Xextern int g_init();
Xextern int g_finish();
Xextern int g_pix_mode();
Xextern int g_pix_color();
Xextern int g_fontctl();
Xextern long g_style();
Xextern int g_weight();
Xextern int p_wr_pix();
Xextern int c_cellchar();
Xextern int c_cellstr();
Xextern int c_cursor();
Xextern int n_movepen();
Xextern int n_box();
Xextern int n_line();
Xextern int n_draw();
Xextern int n_grafchar();
Xextern int n_grafstr();
Xextern int n_arc();
Xextern int n_ellipse();
Xextern int n_point();
X
X/* Everything that follows should be identical to gf_types.h and modes.h. */
X
X/*	@(#) gf_types.h 1.4 88/12/26	*/
X
X/* Define pixel setting modes. 			*/
X
X#define CLEAR 0
X#define AND 1
X#define OR 2
X#define XOR 3
X
X/* Define colors.	 			*/
X
X#define BLACK        0
X#define BLUE         1
X#define GREEN        2
X#define CYAN         3
X#define RED          4
X#define MAGENTA      5
X#define BROWN        6
X#define WHITE        7
X#define GREY         8
X#define LT_BLUE      9
X#define LT_GREEN    10
X#define LT_CYAN     11
X#define LT_RED      12
X#define LT_MAGENTA  13
X#define YELLOW      14
X#define LT_WHITE    15
X
X/* Define line styles.	*/
X
X#define SOLID 0xffffffffL	/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  */
X#define DOTTED 0x66666666L	/* XX..XX..XX..XX..XX..XX..XX..XX..  */
X#define DASHED 0xffe0ffe0L	/* XXXXXXXXXXX.....XXXXXXXXXXX.....  */
X#define SHORTDASHED 0xf8f8f8f8L	/* XXXXX...XXXXX...XXXXX...XXXXX...  */
X#define LONGDASHED 0xffffff00L	/* XXXXXXXXXXXXXXXXXXXXXXXX........  */
X#define DOTDASHED 0xfc30fc30L	/* XXXXXX....XX....XXXXXX....XX....  */
X
X/* Define line weights (not yet implemented).	*/
X
X#define LIGHT 1
X#define MEDIUM 2
X#define HEAVY 4
X
X/*	@(#) modes.h 1.4 89/01/10	*/
X
X/*
X *	Mode definitions.  These will be used by init(), and by the mode
X *	program or shell script.  As much as possible, the numeric mode
X *	values should correspond to those used by the uPort screen driver
X *	and by DOS.  The values given for hercules and for printers are
X *	arbitrary, but should not conflict with other "standard" assignments.
X */
X
X/* ENV_MODE means take the mode setting from an environment variable. */
X#define ENV_MODE 0
X
X/* CGA text modes */
X#define MONO_TEXT 0x02
X#define COLOR_TEXT 0x03
X
X/* CGA modes (for CGA or EGA) */
X#define CGA_COLOR_MODE 0x04
X#define CGA_HI_RES_MODE 0x06
X
X/* Monochrome text mode */
X#define MDA_TEXT 0x07
X
X/* Hercules mono graphics, page 0 and page 1 */
X/* Note:  Modes 8 and 9 were used by the IBM PC Junior.  I trust that 	*/
X/* they will not be found on your machine.				*/
X#define HERC_P0_MODE 0x08
X#define HERC_P1_MODE 0x09
X
X/* EGA 640 x 350 color mode */
X#define EGA_COLOR_MODE 0x010
X
X/* Anything beyond MAXVIDEO is not a video board.  Printers and other	*/
X/* hardcopy would fall in this category.				*/
X
X#define MAXVIDEO 0x0FF
X
X/* Non-video modes follow.						*/
X
X#define IBM_PRINTER 0x100
X
X
XxX--EOF--XxX
echo restoring modes.h
sed 's/^X//' > modes.h <<XxX--EOF--XxX
X/****** Warning! Do not alter this file without updating gl.h! *******/
X
X/*	@(#) modes.h 5.1 89/02/20	*/
X/*
X *	Copyright (c) David T. Lewis 1987, 1988
X *	All rights reserved.
X *
X *	Permission is granted to use this for any personal noncommercial use.
X *	You may not distribute source or executable code for profit, nor
X *	may you distribute it with a commercial product without the written
X *	consent of the author.  Please send modifications to the author for
X *	inclusion in updates to the program.  Thanks.
X */
X
X/*
X *	Mode definitions.  These will be used by init(), and by the mode
X *	program or shell script.  As much as possible, the numeric mode
X *	values should correspond to those used by the uPort screen driver
X *	and by DOS.  The values given for hercules and for printers are
X *	arbitrary, but should not conflict with other "standard" assignments.
X */
X
X/* ENV_MODE means take the mode setting from an environment variable. */
X#define ENV_MODE 0
X
X/* CGA text modes */
X#define MONO_TEXT 0x02
X#define COLOR_TEXT 0x03
X
X/* CGA modes (for CGA or EGA) */
X#define CGA_COLOR_MODE 0x04
X#define CGA_HI_RES_MODE 0x06
X
X/* Monochrome text mode */
X#define MDA_TEXT 0x07
X
X/* Hercules mono graphics, page 0 and page 1 */
X/* Note:  Modes 8 and 9 were used by the IBM PC Junior.  I trust that 	*/
X/* they will not be found on your machine.				*/
X#define HERC_P0_MODE 0x08
X#define HERC_P1_MODE 0x09
X
X/* EGA 640 x 350 color mode */
X#define EGA_COLOR_MODE 0x010
X
X/* Anything beyond MAXVIDEO is not a video board.  Printers and other	*/
X/* hardcopy would fall in this category.				*/
X
X#define MAXVIDEO 0x0FF
X
X/* Non-video modes follow.						*/
X
X#define IBM_PRINTER 0x100
X#define LJ_PRINTER 0x101
X
X
XxX--EOF--XxX
echo restoring n_curves.c
sed 's/^X//' > n_curves.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) n_curves.c 5.1 89/02/20";
X#endif
X
X/*
X *	Copyright (c) David T. Lewis 1988
X *	All rights reserved.
X *
X *	Permission is granted to use this for any personal noncommercial use.
X *	You may not distribute source or executable code for profit, nor
X *	may you distribute it with a commercial product without the written
X *	consent of the author.  Please send modifications to the author for
X *	inclusion in updates to the program.  Thanks.
X */
X
X/*	Sat Aug  6 20:38:14 EDT 1988
X**
X** n_arc():
X**
X** Routine to draw an arc as a partial ellipse.  This routine uses
X** parts of the ellipse() routine to generate the curve.
X** The arc is drawn around an ellipse located at (x,y) with axes a and b.
X** The arc begins at the angle angle1 and traverses counterclockwise to
X** angle2.  "Counterclockwise" is in the sense of the normalized coordinate
X** system, with an inverted Y axis, so the arcs are actually drawn clockwise
X** on the display screen.
X** The values of angle1 and angle2 are given in radians, with 0 being to the
X** right of the center of the ellipse.
X**
X** n_ellipse():
X**
X** Routine to draw an ellipse in normalized 2-d coordinates.  Uses a line
X** segment approximation to the ellipse.  The trig is done with hard coded
X** tables of cos and sin values for speed.  The number of vertices on the
X** ellipse varies according to the size of the ellipse.  The eliminates
X** unnecessary calculations of endpoints for small images.
X** Another method for ellipe drawing would be to do a modified Bresenham
X** type algorithm, but this would be less adaptable for drawing partial arcs.
X**
X** NOTE:  This is an ellipse routine, and not a circle, because the PC display
X** adapters do not generally have square pixels.  A circle routine should be
X** done at a higher level, and should take the screen aspect ration into
X** account (see graphics->aspect_ratio in the graphics.h file).
X**
X** The basic idea is:
X**
X**	Equation of an ellipse:
X**
X**	x^2 / a^2 + y^2 / b^2 = 1
X**
X**	Therefore the X and Y values are:
X**
X**		X = a * cos(theta)
X**		Y = b * sin(theta)
X**
X**		For some angle theta.
X**
X**	By stepping through values of theta, we can generate a list of 
X**	line segment endpoints on the ellipse.  Then call n_movepen() and
X**	n_draw() to display the ellipse.
X**
X**	Note:  The macros PTS_PER_QUADRANT and TRIG_SCALE are defined 
X**	in graphics.h.
X*/
X
X#include "config.h"
X#if MIX_C
X#else
X#include <math.h>
X#endif /* MIX_C */
X#include "bitmaps.h"
X#include "graphics.h"
X
X#ifndef M_PI
X#define M_PI	3.1415926536 
X#endif /* M_PI */
X#ifndef M_PI_2
X#define M_PI_2	1.5707963268 
X#endif /* M_PI_2 */
X
X#define XINDEX 0		/* For specifying array indices.	*/
X#define YINDEX 1
X
X/* The following two arrays are tables of values for cos and sin	*/
X/* for one quadrant of a circle, divided into PTS_PER_QUADRANT slices.	*/
X/* They are found in source file trig.c.				*/
X
Xextern long cos_table[PTS_PER_QUADRANT];
Xextern long sin_table[PTS_PER_QUADRANT];
Xextern long longsin(), longcos();
Xextern int n_movepen(), n_draw();
X
Xstatic void make_endpoints(x,y,a,b,endpoints,step)
Xint x,y,a,b,step;
Xint endpoints[4][PTS_PER_QUADRANT][2];
X{
X	int idx;		/* Loop index.			*/
X	int value;		/* Temporary storage of values	*/
X
X	/* Set the values for points on the ellipse.  While we're	*/
X	/* at it, scale the values back down using TRIG_SCALE, and do	*/
X	/* the x and y translation to the center point of the ellipse.	*/
X	/* Calculations are done with long ints to preserve precision,	*/
X	/* then cast back to short ints in the endpoints array.		*/
X	/* Use the value of step to skip unnecessary points (for small	*/
X	/* ellipes and arcs).						*/
X
X	for(idx=step-1; idx<PTS_PER_QUADRANT; idx+= step)  {
X		value = (cos_table[idx] * (long)a) / TRIG_SCALE;
X		endpoints[0][idx][XINDEX] = value + x;
X		value = -value;
X		endpoints[2][idx][XINDEX] = value + x;
X		value = (sin_table[idx] * (long)a) / TRIG_SCALE;
X		endpoints[3][idx][XINDEX] = value + x;
X		value = -value;
X		endpoints[1][idx][XINDEX] = value + x;
X		value = (cos_table[idx] * (long)b) / TRIG_SCALE;
X		endpoints[1][idx][YINDEX] = value + y;
X		value = -value;
X		endpoints[3][idx][YINDEX] = value + y;
X		value = (sin_table[idx] * (long)b) / TRIG_SCALE;
X		endpoints[0][idx][YINDEX] = value + y;
X		value = -value;
X		endpoints[2][idx][YINDEX] = value + y;
X	}
X	return;
X}
X
Xstatic int make_step(a,b)
Xint a,b;
X{
X	int size;
X	size = a + b;	/* an indication of the "size" of the ellipse.	*/
X	if (size <= 0) return(1);	/* Check for integer overflow.	*/
X	else if (size < 2000) return(16);
X	else if (size < 8000) return(8);
X	else if (size < 16000) return(4);
X	else if (size < 32000) return(2);
X	else return(1);
X}
X
Xint n_arc(x,y,a,b,angle1,angle2)
Xint x,y,a,b;
Xfloat angle1,angle2;
X{
X	int endpoints[4][PTS_PER_QUADRANT][2];
X	int x_1,y_1,x_2,y_2;	/* The start and end points of the arc.	*/
X	int quadrant;		/* Quadrant of first point.		*/
X	int endquadrant;	/* Quadrant of second point.		*/
X	int index;		/* First index into endpoints array.	*/
X	int endindex;		/* Last index into endpoints array.	*/
X	int istat = 0;		/* Function call return status.		*/
X	int step;	/* Amount by which to step through array.	*/
X
X	/* Size of a circle, in radians.				*/
X	float cir_size = M_PI * 2;
X
X	/* Don't feed huge numbers to the trig functions.		*/
X	if (fabs(angle1) > cir_size)
X		angle1 = fmod((double)angle1,(double)cir_size);
X	if (fabs(angle2) > cir_size)
X		angle2 = fmod((double)angle2,(double)cir_size);
X
X	/* Make the angles positive.					*/
X	while (angle1 < 0) angle1 += cir_size;
X	while (angle2 < 0) angle2 += cir_size;
X
X	/* Calculate a value for step, so we can use fewer endpoints	*/
X	/* for small arcs.						*/
X	step = make_step(a,b);
X
X#ifdef DEBUG
X	printf("step is %d\n",step);
X#endif /* DEBUG */
X
X	/* Calculate the end points.	*/
X
X#if NOFLOAT
X	x_1 = x + (int)((longcos(angle1) * a) / TRIG_SCALE); 
X	y_1 = y + (int)((longsin(angle1) * b) / TRIG_SCALE);
X	x_2 = x + (int)((longcos(angle2) * a) / TRIG_SCALE);
X	y_2 = y + (int)((longsin(angle2) * b) / TRIG_SCALE);
X#else
X	x_1 = x + (int)(a * cos((double)angle1));
X	y_1 = y + (int)(b * sin((double)angle1));
X	x_2 = x + (int)(a * cos((double)angle2));
X	y_2 = y + (int)(b * sin((double)angle2));
X#endif /* NOFLOAT */
X
X	/* Generate the array of arc endpoints. */
X	make_endpoints(x,y,a,b,endpoints,step);
X
X	/* Deduce the first and last element of interest in the 	*/
X	/* endpoint array.	*/
X
X	/* First calculate the initial index value.	*/
X	index = (int)(angle1 / M_PI_2 * (float)PTS_PER_QUADRANT);
X	/* Now figure the quadrant.	*/
X	quadrant = (index / PTS_PER_QUADRANT) % 4;
X	/* Wrap around so we point at the array.	*/
X	index = (index % PTS_PER_QUADRANT);
X	index = index + step - (index % step) - 1;
X
X#ifdef DEBUG
X	printf("In n_arc(), index is %d\n",index);
X#endif /* DEBUG */
X
X	/* Calculate the final index value.	*/
X	endindex = (int)(angle2 / M_PI_2 * (float)PTS_PER_QUADRANT);
X	/* Now figure the quadrant.	*/
X	endquadrant = (endindex / PTS_PER_QUADRANT) % 4;
X	/* Wrap around so we point at the array.	*/
X	endindex = (endindex % PTS_PER_QUADRANT);
X	endindex = endindex + step - (endindex % step) - 1;
X
X#ifdef DEBUG
X	printf("In n_arc(), endindex is %d\n",endindex);
X#endif /* DEBUG */
X
X	/* Move pen to start point. */
X
X#ifdef DEBUG
X	printf("Move pen to %d %d\n",x_1,y_1);
X#endif /* DEBUG */
X
X	if(n_movepen(x_1,y_1)) istat = 1;
X
X	/* Start drawing, beginning with the first point of interest. 	*/
X	/* Wrap around the array if needed.				*/
X
X	while ((index != endindex) || (quadrant != endquadrant))  {
X
X#ifdef DEBUG
X	printf("Draw to %d %d -- quadrant %d index %d\n", 
X		endpoints[quadrant][index][XINDEX], 
X		endpoints[quadrant][index][YINDEX],quadrant,index);
X#endif /* DEBUG */
X
X		if(n_draw(endpoints[quadrant][index][XINDEX], 
X			endpoints[quadrant][index][YINDEX]))  {
X			istat = 1;
X			/* This is just for cleaner error recovery: */
X			n_movepen(endpoints[quadrant][index][XINDEX], 
X				endpoints[quadrant][index][YINDEX]); 
X		}
X		/* Increment the indices.	*/
X		if ((index+=step) >= PTS_PER_QUADRANT)  {
X			index = step - 1;
X			if ((++quadrant) >= 4)  {
X				quadrant = 0;
X			}
X		}
X	};
X
X	/* Finish at last point of interest.	*/
X
X#ifdef DEBUG
X	printf("Finish by drawing to %d %d\n",x_2,y_2);
X#endif /* DEBUG */
X
X	if(n_draw(x_2,y_2))  {
X		istat = 1;
X		/* This is just for cleaner error recovery: */
X		n_movepen(x_2,y_2);
X	} 
X	return(istat);
X}
X
Xint n_ellipse(x,y,a,b)
Xint x,y,a,b;
X{
X	/* The endpoints array will hold line segment (x,y) end points.	*/
X	/* There are four quadrants, each with PTS_PER_QUADRANT points,	*/
X	/* with two values (X and Y) each.				*/
X	int endpoints[4][PTS_PER_QUADRANT][2];
X	int pointindex, quadrant;	/* Loop index.			*/
X	int istat = 0;			/* Function call return status.	*/
X	int step;	/* Amount by which to step through array.	*/
X
X	/* Calculate a value for step, so we can use fewer endpoints	*/
X	/* for small ellipses.						*/
X	step = make_step(a,b);
X
X	/* Build the array of endpoints.				*/
X	make_endpoints(x,y,a,b,endpoints,step);
X
X	/* Display the result, drawing all four quadrants.		*/
X
X	/* Start the pen at the location of the last endpoint.  This	*/
X	/* is the point we want to end up on.				*/
X	if(n_movepen(endpoints[3][PTS_PER_QUADRANT-1][XINDEX],
X		endpoints[3][PTS_PER_QUADRANT-1][YINDEX]))
X		istat = 1;
X
X	for (quadrant=0; quadrant<=3; quadrant++)  {
X
X		for (pointindex = step -1; pointindex < PTS_PER_QUADRANT; 
X			pointindex += step)  {
X			if(n_draw(endpoints[quadrant][pointindex][XINDEX],
X				endpoints[quadrant][pointindex][YINDEX]))  {
X				istat = 1;
X				/* This is just for cleaner error recovery: */
X				n_movepen(endpoints[quadrant][pointindex]
X						[XINDEX],
X					endpoints[quadrant][pointindex]
X						[YINDEX]);
X			}
X		}
X	}
X	return(istat);
X}
X
XxX--EOF--XxX
echo restoring plot.c
sed 's/^X//' > plot.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) plot.c 5.1 89/02/20";
X#endif
X
X/*
X *	Copyright (c) David T. Lewis 1988
X *	All rights reserved.
X *
X *	Permission is granted to use this for any personal noncommercial use.
X *	You may not distribute source or executable code for profit, nor
X *	may you distribute it with a commercial product without the written
X *	consent of the author.  Please send modifications to the author for
X *	inclusion in updates to the program.  Thanks.
X */
X
X#include "config.h"
X#include "gf_types.h"
X#include <stdio.h>
X#if MIX_C
X#else
X#include <math.h>
X#endif /* MIX_C */
X#include "modes.h"
X#include "bitmaps.h"
X#include "graphics.h"
X
X/* The following declarations copied from gl.h.	*/
Xextern int g_clear();
Xextern int g_init();
Xextern int g_finish();
Xextern long g_style();
Xextern int c_cellstr();
Xextern int n_movepen();
Xextern int n_line();
Xextern int n_draw();
Xextern int n_arc();
Xextern int n_ellipse();
Xextern int n_point();
X
Xextern struct GL_graphics graphics;
X
X/* These routines emulate the BSD plot(3) library.
X *
X * The arc() routine may vary slightly from the BSD version,
X * in that it calculates start and end angles with trig
X * functions, rather than with simple integer approximations
X * used in the BSD routine.
X *
X * plot:	openpl,	erase, label, line, circle, arc, move, cont,
X * point, linemod, space, closepl - graphics interface
X *
X * Coordinate transformations, using X0, X1, Y0, Y1 set in space(): 
X * X:
X * 	x' = x * (NRM_X_RANGE)/(X1-X0) - (X0*NRM_X_RANGE)/(X1-X0)
X * 	x' = (X0*NRM_X_RANGE + x*NRM_X_RANGE) / (X1-X0)
X * 
X * 	xconst = X0*NRM_X_RANGE;
X * 	xdiv = X1-X0;
X * 	x' = (xconst+x*NRM_X_RANGE)/xdiv;
X * 
X * Y:
X * 	y' = y * (-NRM_Y_RANGE)/(Y1-Y0) + (Y1*NRM_Y_RANGE)/(Y1-Y0)
X * 	y' = (Y1*NRM_Y_RANGE - y*NRM_Y_RANGE) / (Y1-Y0)
X * 
X * 	yconst = Y1*NRM_Y_RANGE;
X * 	ydiv = Y1-Y0;
X * 	y' = (yconst-y*NRM_Y_RANGE)/ydiv;
X */
X
X/* X_TO_NORM(x) and Y_TO_NORM(y) are used to translate from the plot()	*/
X/* coordinate system, as defined by scale(), to the normalized 2-D	*/
X/* coordinate system of the screen.					*/
X
X#define X_TO_NORM(x) ((int)((xconst+x*NRM_X_RANGE)/xdiv))
X#define Y_TO_NORM(y) ((int)((yconst-y*NRM_Y_RANGE)/ydiv))
X
X/* X_SCALE_NORM() and Y_SCALE_NORM() are used for scaling magnitudes.	*/
X
X#define X_SCALE_NORM(x) (((x)*(NRM_X_RANGE))/(xdiv))
X#define Y_SCALE_NORM(y) (((y)*(NRM_Y_RANGE))/(ydiv))
X
Xstatic long xconst,xdiv,yconst,ydiv;	/* Used in space() transforms.	*/
X
Xint openpl()
X{
X	/* Try to get the mode from the environment.		*/
X	/* If no environment variable, use a default.		*/
X	if((g_init(ENV_MODE)) == 0) return(0);
X	else {
X		/* Put warning message to standard error, then	*/
X		/* continue.					*/
X		fprintf(stderr,"Use environment variable %s to control mode.\n",
X			GL_ENV_MODE);
X		fprintf(stderr,"Continuing with default mode %d\n",
X			DEFAULT_MODE);
X		sleep(2);
X		return(g_init(DEFAULT_MODE));
X	}
X}
X
Xint erase()
X{
X	return(g_clear());
X}
X
Xint label(s)
Xchar s[];
X{
X	return(c_cellstr(s));
X}
X
Xint line(x_1, y_1, x_2, y_2)
Xint x_1,y_1,x_2,y_2;
X{
X	return(n_line(
X		X_TO_NORM(x_1),Y_TO_NORM(y_1),X_TO_NORM(x_2),Y_TO_NORM(y_2)));
X}
X
Xint circle(x, y, r)
X{
X	int x_axis=X_SCALE_NORM(r);
X	int y_axis=Y_SCALE_NORM(r);
X	return(n_ellipse(X_TO_NORM(x), Y_TO_NORM(y), x_axis, y_axis));
X}
X
Xint arc(x, y, x_0, y_0, x_1, y_1)
X{
X	int x_axis, y_axis;		/* Major and minor axes.	*/
X	float angle1, angle2;		/* Start and end angles.	*/
X	int radius;	/* Radius, as calculated from sqrt(x**2+y**2).	*/
X	long dx_0 = x_0 - x;
X	long dy_0 = y_0 - y;
X	long dx_1 = x_1 - x;
X	long dy_1 = y_1 - y;
X
X	/* We will draw a section of elliptical arc with major and 	*/
X	/* minor axes such that it appears as a circle on the screen.	*/
X	/* We know the center of the arc (x and y), and the ratio of	*/
X	/* the major and minor axes (b/a equals graphics.aspect_ratio).	*/
X	/* Given the start and end points of the arc, we need to solve	*/
X	/* for the first and second angle, and then for major and minor	*/
X	/* axes.							*/
X	/* These values can be used to call the n_arc() routine.	*/
X
X	/* WARNING:  The value of angle2 is calculated directly as the	*/
X	/* angle of the vector from (x,y) to (x_1,y_1).  The original	*/
X	/* versions of plot(3) from the BSD code apparently use		*/
X	/* a simplistic approximation to this, which may lead to	*/
X	/* different screen displays for arcs drawn with the BSD	*/
X	/* code.  The basic idea for the user, however, should be to	*/
X	/* specify x_1 and y_1 such that they fall very close to the	*/
X	/* intended angle.						*/
X
X	angle1 = (float)(-atan2((double)dy_0,(double)dx_0));
X	angle2 = (float)(-atan2((double)dy_1,(double)dx_1));
X
X	radius = ((int)(sqrt(fabs((double)(dx_0*dx_0+dy_0*dy_0)))));
X	x_axis = X_SCALE_NORM(radius);
X	y_axis = Y_SCALE_NORM(radius);
X
X	return(n_arc(X_TO_NORM(x),Y_TO_NORM(y),x_axis,y_axis,angle2,angle1));
X}
X
Xint move(x, y)
Xint x,y;
X{
X	return(n_movepen(X_TO_NORM(x),Y_TO_NORM(y)));
X}
X
Xint cont(x, y)
Xint x,y;
X{
X	return(n_draw(X_TO_NORM(x),Y_TO_NORM(y)));
X}
X
Xint point(x, y)
Xint x, y;
X{
X	return(n_point(X_TO_NORM(x),Y_TO_NORM(y)));
X}
X
Xint linemod(s)
Xchar s[];
X{
X	if (strncmp(s, "dotted", 6) == 0)  {
X		g_style(DOTTED);
X	}
X	else if (strncmp(s, "dotdashed", 9) == 0)  {
X		g_style(DOTDASHED);
X	}
X	else if (strncmp(s, "longdashed", 10) == 0)  {
X		g_style(LONGDASHED);
X	}
X	else if (strncmp(s, "shortdashed", 11) == 0)  {
X		g_style(SHORTDASHED);
X	}
X	else if (strncmp(s, "solid", 5) == 0)  {
X		g_style(SOLID);
X	}
X	else  {
X		g_style(SOLID);
X	}
X	return(0);
X}
X
Xint space(x_0, y_0, x_1, y_1)
X{
X	/* Set constants for coordinate transformations.		*/
X	/* Adjust x axis for aspect ratio so that output is square.	*/
X
X 	xconst = (long)(x_0) * NRM_X_RANGE; 
X 	xdiv = (long)((float)(x_1-x_0) / graphics.aspect_ratio);
X 	yconst = y_1*NRM_Y_RANGE;
X 	ydiv = y_1-y_0;
X}
X
Xint closepl()
X{
X	return(g_finish());
X}
X
XxX--EOF--XxX
echo restoring trig.c
sed 's/^X//' > trig.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) trig.c 5.1 89/02/20";
X#endif
X
X/*
X *	Copyright (c) David T. Lewis 1988
X *	All rights reserved.
X *
X *	Permission is granted to use this for any personal noncommercial use.
X *	You may not distribute source or executable code for profit, nor
X *	may you distribute it with a commercial product without the written
X *	consent of the author.  Please send modifications to the author for
X *	inclusion in updates to the program.  Thanks.
X */
X
X/* Integer approximations to simple trig functions.  Results are scaled	*/
X/* by a factor of TRIG_SCALE.						*/
X
X/* The macro TRIG_SCALE is defined in graphics.h so that other routines	*/
X/* can use it.  F_TRIG_SCALE is the same value, but in floating point	*/
X/* format.  The defines should look like this:				*/
X/*									*/
X/*	#define TRIG_SCALE 32768					*/
X/*	#define F_TRIG_SCALE 32768.0					*/
X/*									*/
X/* The macro PTS_PER_QUADRANT defines the size of the sin_table and	*/
X/* cos_table arrays.  It is defined in graphics.h and should look	*/
X/* like this:								*/
X/*									*/
X/*	#define PTS_PER_QUADRANT 64					*/
X/*									*/
X
X#include "config.h"
X#if MIX_C
X#else
X#include <math.h>
X#endif /* MIX_C */
X#include "bitmaps.h"
X#include "graphics.h"
X
X#define L_PI 102944L		/* Value of pi times TRIG_SCALE.	*/
X#define L_PI_2 51472L		/* Value of pi/2 times TRIG_SCALE.	*/
X#define L_PI_4 25736L		/* Value of pi/4 times TRIG_SCALE.	*/
X
X#define CIRCLE_SIZE 205887L	/* Value of pi * 2 * TRIG_SCALE.	*/
X
X#define TABLESLICE 804L		/* (L_PI_2 / PTS_PER_QUADRANT)		*/
X
X#define XINDEX 0		/* For specifying array indices.	*/
X#define YINDEX 1
X
X/* The following two arrays are tables of values for cos and sin	*/
X/* for one quadrant of a circle, divided into PTS_PER_QUADRANT slices.	*/
X
Xlong cos_table[PTS_PER_QUADRANT] = {
X	32758L, 32729L, 32679L, 32610L, 32522L, 32413L, 32286L, 32138L, 
X	31972L, 31786L, 31581L, 31357L, 31114L, 30853L, 30572L, 30274L, 
X	29957L, 29622L, 29269L, 28899L, 28511L, 28106L, 27684L, 27246L, 
X	26791L, 26320L, 25833L, 25330L, 24812L, 24279L, 23732L, 23170L, 
X	22595L, 22006L, 21403L, 20788L, 20160L, 19520L, 18868L, 18205L, 
X	17531L, 16846L, 16151L, 15447L, 14733L, 14010L, 13279L, 12540L, 
X	11793L, 11039L, 10279L, 9512L, 8740L, 7962L, 7180L, 6393L, 
X	5602L, 4808L, 4011L, 3212L, 2411L, 1608L, 804L, 0L
X};
X
Xlong sin_table[PTS_PER_QUADRANT] = {
X	804L, 1608L, 2411L, 3212L, 4011L, 4808L, 5602L, 6393L, 
X	7180L, 7962L, 8740L, 9512L, 10279L, 11039L, 11793L, 12540L, 
X	13279L, 14010L, 14733L, 15447L, 16151L, 16846L, 17531L, 18205L, 
X	18868L, 19520L, 20160L, 20788L, 21403L, 22006L, 22595L, 23170L, 
X	23732L, 24279L, 24812L, 25330L, 25833L, 26320L, 26791L, 27246L, 
X	27684L, 28106L, 28511L, 28899L, 29269L, 29622L, 29957L, 30274L, 
X	30572L, 30853L, 31114L, 31357L, 31581L, 31786L, 31972L, 32138L, 
X	32286L, 32413L, 32522L, 32610L, 32679L, 32729L, 32758L, 32768L
X};
X
X/* Estimate sin by interpolation.  Return long integer value.		*/
X
Xlong longsin(theta)
Xfloat theta;
X{
X	long longtheta;
X	int quadrant;
X	long value1, value2;
X	long value;
X	long intpart;
X	long fractionpart;
X
X	/* We have a floating point value for theta.  Put theta 	*/
X	/* into a long integer for the rest of the processing.		*/
X	/* Keep everything scaled by a factor of TRIG_SCALE.		*/
X
X	longtheta = (long)(theta * F_TRIG_SCALE);
X
X	/* Make angle positive.						*/
X
X	while (longtheta < 0) longtheta += CIRCLE_SIZE;
X
X	/* Figure quadrant while making it less than PI/2.		*/
X
X	quadrant = 1;
X
X	while (longtheta > L_PI_2)  {
X		longtheta -= L_PI_2;
X		quadrant++;
X		if (quadrant > 4) quadrant = 1;
X	}
X
X	/* If Quadrant 2 or 4 we need to use the reverse of the		*/
X	/* interpolation table.						*/
X
X	if (quadrant == 2 || quadrant == 4) longtheta = L_PI_2 - longtheta;
X
X	/* Express angle in terms of number of table increments.	*/
X
X	intpart = longtheta / TABLESLICE;
X
X	fractionpart = longtheta % TABLESLICE;
X
X	/* This looks like a kludge, but it isn't.  When TABLESLICE is	*/
X	/* set to TABLESLICE, we have the smallest error in the result.	*/
X	/* This just rounds back down when we overshoot the table.	*/
X
X	if (intpart >= PTS_PER_QUADRANT)  {
X		intpart = PTS_PER_QUADRANT - 1;
X		fractionpart = TABLESLICE;
X	}
X
X	/* Interpolate.							*/
X
X	if (intpart <= 0)  {
X		value1 = 0;
X		value2 = sin_table[0];
X	}
X	else  {
X		value2 = sin_table[(int)(intpart--)];
X		value1 = sin_table[(int)intpart];
X	}
X
X	value = value1 + (fractionpart * (value2 - value1)) / TABLESLICE;
X
X	/* If Quadrant 3 or 4 the result should be negative.		*/
X
X	if (quadrant == 3 || quadrant == 4) return(-value);
X	else return(value);
X}
X
X
X/* Estimate cos by interpolation.  Return long integer value.		*/
X
Xlong longcos(theta)
Xfloat theta;
X{
X	long longtheta;
X	int quadrant;
X	long value1, value2;
X	long value;
X	long intpart;
X	long fractionpart;
X
X	/* We have a floating point value for theta.  Put theta 	*/
X	/* into a long integer for the rest of the processing.		*/
X	/* Keep everything scaled by a factor of TRIG_SCALE.		*/
X
X	longtheta = (long)(theta * F_TRIG_SCALE);
X
X	/* Make angle positive.						*/
X
X	while (longtheta < 0) longtheta += CIRCLE_SIZE;
X
X	/* Figure quadrant while making it less than PI/2.		*/
X
X	quadrant = 1;
X
X	while (longtheta > L_PI_2)  {
X		longtheta -= L_PI_2;
X		quadrant++;
X		if (quadrant > 4) quadrant = 1;
X	}
X
X	/* If Quadrant 2 or 4 we need to use the reverse of the		*/
X	/* interpolation table.						*/
X
X	if (quadrant == 2 || quadrant == 4) longtheta = L_PI_2 - longtheta;
X
X	/* Express angle in terms of number of table increments.	*/
X
X	intpart = longtheta / TABLESLICE;
X
X	fractionpart = longtheta % TABLESLICE;
X
X	/* This looks like a kludge, but it isn't.  When TABLESLICE is	*/
X	/* set to TABLESLICE, we have the smallest error in the result.	*/
X	/* This just rounds back down when we overshoot the table.	*/
X
X	if (intpart >= PTS_PER_QUADRANT)  {
X		intpart = PTS_PER_QUADRANT - 1;
X		fractionpart = TABLESLICE;
X	}
X
X	/* Interpolate.							*/
X
X	if (intpart <= 0)  {
X		value1 = 32768L;
X		value2 = cos_table[0];
X	}
X	else  {
X		value2 = cos_table[(int)(intpart--)];
X		value1 = cos_table[(int)intpart];
X	}
X
X	value = value1 + (fractionpart * (value2 - value1)) / TABLESLICE;
X
X	/* If Quadrant 2 or 3 the result should be negative.		*/
X
X	if (quadrant == 2 || quadrant == 3) return(-value);
X	else return(value);
X}
X
X/* Test program:
Xmain()  {
X	float theta;
X
Xfloat sinval;
Xfloat lsinval;
Xfloat cosval;
Xfloat lcosval;
X
X	for (theta = -8.3; theta < 100.0; theta += 0.1)  {
X
X		sinval = sin((double)theta);
X		lsinval = longsin(theta) / F_TRIG_SCALE;
X		cosval = cos((double)theta);
X		lcosval = longcos(theta) / F_TRIG_SCALE;
X
X		printf("SIN: angle %g	%lg	%g	err %g\n",theta,sinval,
X		lsinval,sinval-lsinval);
X		printf("COS: angle %g	%lg	%g	err %g\n",theta,cosval,
X		lcosval,cosval-lcosval);
X	}
X}
X*/
X
XxX--EOF--XxX


-- 
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.



More information about the Comp.sources.unix mailing list