mirror of
https://github.com/lcn2/calc.git
synced 2025-08-16 01:03:29 +03:00
Release calc version 2.10.2t30
This commit is contained in:
95
BUGS
Normal file
95
BUGS
Normal file
@@ -0,0 +1,95 @@
|
||||
If you notice something wrong, strange or broken, try rereading:
|
||||
|
||||
README.FIRST
|
||||
README
|
||||
BUGS (in particular the bottom problems or mis-features section)
|
||||
|
||||
If that does not help, cd to the calc source directory and try:
|
||||
|
||||
make check
|
||||
|
||||
Look at the end of the output, it should say something like:
|
||||
|
||||
9999: passed all tests /\../\
|
||||
|
||||
If it does not, then something is really broken!
|
||||
|
||||
If you made and modifications to calc beyond the simple Makefile
|
||||
configuration, try backing them out and see if things get better.
|
||||
|
||||
Check to see if the version of calc you are using is current. Calc
|
||||
distributions may be obtained from the official calc repository:
|
||||
|
||||
ftp://ftp.uu.net/pub/calc
|
||||
|
||||
If you are an alpha or beta tester, you may have a special pre-released
|
||||
version that is more advanced than what is in the ftp archive.
|
||||
|
||||
=-=
|
||||
|
||||
If you have tried all of the above and things still are not right,
|
||||
then it may be time to send in a bug report. You can send bug reports to:
|
||||
|
||||
calc-tester@postofc.corp.sgi.com
|
||||
|
||||
When you send your report, please include the following information:
|
||||
|
||||
* a description of the problem
|
||||
|
||||
* the version of calc you are using (if you cannot get calc
|
||||
it to run, then send us the 4 #define lines from version.c)
|
||||
|
||||
* if you modified calc from an official patch, send me the mods you made
|
||||
|
||||
* the type of system you were using
|
||||
|
||||
* the type of compiler you were using
|
||||
|
||||
* cd to the calc source directory, and type:
|
||||
|
||||
make debug > debug.out 2>&1 (sh, ksh, bash users)
|
||||
make debug >& debug.out (csh, tcsh users)
|
||||
|
||||
and send the contents of the 'debug.out' file.
|
||||
|
||||
Stack traces from core dumps are useful to send as well.
|
||||
|
||||
=-=
|
||||
|
||||
The official calc repository is located in:
|
||||
|
||||
ftp://ftp.uu.net/pub/calc
|
||||
|
||||
If you don't have ftp access to that site, or if your version is more
|
||||
recent than what has been released to the ftp archive, you may, as a
|
||||
last resort, send EMail to:
|
||||
|
||||
chongo@toad.com
|
||||
|
||||
Indicate the version you have and that you would like a more up to date version.
|
||||
|
||||
=-=
|
||||
|
||||
Send any comments, suggestions and most importantly, fixes (in the form
|
||||
of a context diff patch) to:
|
||||
|
||||
calc-tester@postofc.corp.sgi.com
|
||||
|
||||
=-=
|
||||
|
||||
Known problems or mis-features:
|
||||
|
||||
* In calc2.10.2t3, when scan() reads characters from stdin, they
|
||||
are not echoed. This also happens with fgets(files(0)) and
|
||||
fgetline(files(0)). Reports indicate that this did not happen in
|
||||
calc.2.10.1t20 but did in 2.10.2t0.
|
||||
|
||||
* Many of LIBRARY, LIMITS and SEE ALSO sections of help files
|
||||
for builtins are either inconsistent or missing information.
|
||||
|
||||
* The functions filepos2z() and z2filepos() do not work (or
|
||||
worse do not compile) when FILEPOS is 64 bits long.
|
||||
|
||||
* There is some places in the source with obscure variable names
|
||||
and not much in the way of comments. We need some major cleanup
|
||||
and documentation.
|
436
LIBRARY
Normal file
436
LIBRARY
Normal file
@@ -0,0 +1,436 @@
|
||||
USING THE ARBITRARY PRECISION ROUTINES IN A C PROGRAM
|
||||
|
||||
Part of the calc release consists of an arbitrary precision math library.
|
||||
This library is used by the calc program to perform its own calculations.
|
||||
If you wish, you can ignore the calc program entirely and call the arbitrary
|
||||
precision math routines from your own C programs.
|
||||
|
||||
The library is called libcalc.a, and provides routines to handle arbitrary
|
||||
precision arithmetic with integers, rational numbers, or complex numbers.
|
||||
There are also many numeric functions such as factorial and gcd, along
|
||||
with some transcendental functions such as sin and exp.
|
||||
|
||||
------------------
|
||||
FIRST THINGS FIRST
|
||||
------------------
|
||||
|
||||
*******************************************************************************
|
||||
* You MUST call libcalc_call_me_first() prior to using libcalc lib functions! *
|
||||
*******************************************************************************
|
||||
|
||||
The function libcalc_call_me_first() takes no args and returns void. You
|
||||
need call libcalc_call_me_first() only once.
|
||||
|
||||
-------------
|
||||
INCLUDE FILES
|
||||
-------------
|
||||
|
||||
To use any of these routines in your own programs, you need to include the
|
||||
appropriate include file. These include files are:
|
||||
|
||||
zmath.h (for integer arithmetic)
|
||||
qmath.h (for rational arithmetic)
|
||||
cmath.h (for complex number arithmetic)
|
||||
|
||||
You never need to include more than one of the above files, even if you wish
|
||||
to use more than one type of arithmetic, since qmath.h automatically includes
|
||||
zmath.h, and cmath.h automatically includes qmath.h.
|
||||
|
||||
The prototypes for the available routines are listed in the above include
|
||||
files. Some of these routines are meant for internal use, and so aren't
|
||||
convenient for outside use. So you should read the source for a routine
|
||||
to see if it really does what you think it does. I won't guarantee that
|
||||
obscure internal routines won't change or disappear in future releases!
|
||||
|
||||
When calc is installed, all of the include files needed to build
|
||||
libcalc.a along with the library itself (and the lint library
|
||||
llib-lcalc.ln, if made) are installed into ${LIBDIR}.
|
||||
|
||||
External programs may want to compile with:
|
||||
|
||||
-I${LIBDIR} -L${LIBDIR} -lcalc
|
||||
|
||||
--------------
|
||||
ERROR HANDLING
|
||||
--------------
|
||||
|
||||
Your program MUST provide a function called math_error. This is called by
|
||||
the math routines on an error condition, such as malloc failures or a
|
||||
division by zero. The routine is called in the manner of printf, with a
|
||||
format string and optional arguments. (However, none of the low level math
|
||||
routines currently uses formatting, so if you are lazy you can simply use
|
||||
the first argument as a simple error string.) For example, one of the
|
||||
error calls you might expect to receive is:
|
||||
|
||||
math_error("Division by zero");
|
||||
|
||||
Your program can handle errors in basically one of two ways. Firstly, it
|
||||
can simply print the error message and then exit. Secondly, you can make
|
||||
use of setjmp and longjmp in your program. Use setjmp at some appropriate
|
||||
level in your program, and use longjmp in the math_error routine to return
|
||||
to that level and so recover from the error. This is what the calc program
|
||||
does.
|
||||
|
||||
For convenience, the library libcalc.a contains a math_error routine.
|
||||
By default, this routine simply prints a message to stderr and then exits.
|
||||
By simply linking in this library, any calc errors will result in a
|
||||
error message on stderr followed by an exit.
|
||||
|
||||
External programs that wish to use this math_error may want to compile with:
|
||||
|
||||
-I${LIBDIR} -L${LIBDIR} -lcalc
|
||||
|
||||
If one sets up calc_jmp_buf, and then sets calc_jmp to non-zero then
|
||||
this routine will longjmp back (with the value of calc_jmp) instead.
|
||||
In addition, the last calc error message will be found in calc_error;
|
||||
this error is not printed to stderr. The calc error message will
|
||||
not have a trailing newline.
|
||||
|
||||
For example:
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
extern jmp_buf calc_jmp_buf;
|
||||
extern int calc_jmp;
|
||||
extern char *calc_error;
|
||||
int error;
|
||||
|
||||
...
|
||||
|
||||
if ((error = setjmp(calc_jmp_buf)) != 0) {
|
||||
/* handle error */
|
||||
printf("Ouch: %s\n", calc_error);
|
||||
}
|
||||
calc_jmp = 1;
|
||||
|
||||
---------------
|
||||
OUTPUT ROUTINES
|
||||
---------------
|
||||
|
||||
The output from the routines in the library normally goes to stdout. You
|
||||
can divert that output to either another FILE handle, or else to a string.
|
||||
Read the routines in zio.c to see what is available. Diversions can be
|
||||
nested.
|
||||
|
||||
You use math_setfp to divert output to another FILE handle. Calling
|
||||
math_setfp with stdout restores output to stdout.
|
||||
|
||||
Use math_divertio to begin diverting output into a string. Calling
|
||||
math_getdivertedio will then return a string containing the output, and
|
||||
clears the diversion. The string is reallocated as necessary, but since
|
||||
it is in memory, there are obviously limits on the amount of data that can
|
||||
be diverted into it. The string needs freeing when you are done with it.
|
||||
|
||||
Calling math_cleardiversions will clear all the diversions to strings, and
|
||||
is useful on an error condition to restore output to a known state. You
|
||||
should also call math_setfp on errors if you had changed that.
|
||||
|
||||
If you wish to mix your own output with numeric output from the math routines,
|
||||
then you can call math_chr, math_str, math_fill, math_fmt, or math_flush.
|
||||
These routines output single characters, output null-terminated strings,
|
||||
output strings with space filling, output formatted strings like printf, and
|
||||
flush the output. Output from these routines is diverted as described above.
|
||||
|
||||
You can change the default output mode by calling math_setmode, and you can
|
||||
change the default number of digits printed by calling math_setdigits. These
|
||||
routines return the previous values. The possible modes are described in
|
||||
zmath.h.
|
||||
|
||||
--------------
|
||||
USING INTEGERS
|
||||
--------------
|
||||
|
||||
The arbitrary precision integer routines define a structure called a ZVALUE.
|
||||
This is defined in zmath.h. A ZVALUE contains a pointer to an array of
|
||||
integers, the length of the array, and a sign flag. The array is allocated
|
||||
using malloc, so you need to free this array when you are done with a
|
||||
ZVALUE. To do this, you should call zfree with the ZVALUE as an argument
|
||||
(or call freeh with the pointer as an argument) and never try to free the
|
||||
array yourself using free. The reason for this is that sometimes the pointer
|
||||
points to one of two statically allocated arrays which should NOT be freed.
|
||||
|
||||
The ZVALUE structures are passed to routines by value, and are returned
|
||||
through pointers. For example, to multiply two small integers together,
|
||||
you could do the following:
|
||||
|
||||
ZVALUE z1, z2, z3;
|
||||
|
||||
itoz(3L, &z1);
|
||||
itoz(4L, &z2);
|
||||
zmul(z1, z2, &z3);
|
||||
|
||||
Use zcopy to copy one ZVALUE to another. There is no sharing of arrays
|
||||
between different ZVALUEs even if they have the same value, so you MUST
|
||||
use this routine. Simply assigning one value into another will cause
|
||||
problems when one of the copies is freed. However, the special ZVALUE
|
||||
values _zero_ and _one_ CAN be assigned to variables directly, since their
|
||||
values of 0 and 1 are so common that special checks are made for them.
|
||||
|
||||
For initial values besides 0 or 1, you need to call itoz to convert a long
|
||||
value into a ZVALUE, as shown in the above example. Or alternatively,
|
||||
for larger numbers you can use the atoz routine to convert a string which
|
||||
represents a number into a ZVALUE. The string can be in decimal, octal,
|
||||
hex, or binary according to the leading digits.
|
||||
|
||||
Always make sure you free a ZVALUE when you are done with it or when you
|
||||
are about to overwrite an old ZVALUE with another value by passing its
|
||||
address to a routine as a destination value, otherwise memory will be
|
||||
lost. The following shows an example of the correct way to free memory
|
||||
over a long sequence of operations.
|
||||
|
||||
ZVALUE z1, z2, z3;
|
||||
|
||||
z1 = _one_;
|
||||
atoz("12345678987654321", &z2);
|
||||
zadd(z1, z2, &z3);
|
||||
zfree(z1);
|
||||
zfree(z2);
|
||||
zsquare(z3, &z1);
|
||||
zfree(z3);
|
||||
itoz(17L, &z2);
|
||||
zsub(z1, z2, &z3);
|
||||
zfree(z1);
|
||||
zfree(z2);
|
||||
zfree(z3);
|
||||
|
||||
There are some quick checks you can make on integers. For example, whether
|
||||
or not they are zero, negative, even, and so on. These are all macros
|
||||
defined in zmath.h, and should be used instead of checking the parts of the
|
||||
ZVALUE yourself. Examples of such checks are:
|
||||
|
||||
ziseven(z) (number is even)
|
||||
zisodd(z) (number is odd)
|
||||
ziszero(z) (number is zero)
|
||||
zisneg(z) (number is negative)
|
||||
zispos(z) (number is positive)
|
||||
zisunit(z) (number is 1 or -1)
|
||||
zisone(z) (number is 1)
|
||||
zisnegone(z) (number is -1)
|
||||
zistwo(z) (number is 2)
|
||||
zisabstwo(z) (number is 2 or -2)
|
||||
zisabsleone(z) (number is -1, 0 or 1)
|
||||
zislezero(z) (number is <= 0)
|
||||
zisleone(z) (number is <= 1)
|
||||
zge16b(z) (number is >= 2^16)
|
||||
zge24b(z) (number is >= 2^24)
|
||||
zge31b(z) (number is >= 2^31)
|
||||
zge32b(z) (number is >= 2^32)
|
||||
zge64b(z) (number is >= 2^64)
|
||||
|
||||
Typically the largest unsigned long is typedefed to FULL. The following
|
||||
macros are useful in dealing with this data type:
|
||||
|
||||
MAXFULL (largest positive FULL value)
|
||||
MAXUFULL (largest unsigned FULL value)
|
||||
zgtmaxfull(z) (number is > MAXFULL)
|
||||
zgtmaxufull(z) (number is > MAXUFULL)
|
||||
zgtmaxlong(z) (number is > MAXLONG, largest long value)
|
||||
zgtmaxulong(z) (number is > MAXULONG, largest unsigned long value)
|
||||
|
||||
If zgtmaxufull(z) is false, then one may quickly convert the absolute
|
||||
value of number into a full with the macro:
|
||||
|
||||
ztofull(z) (convert abs(number) to FULL)
|
||||
ztoulong(z) (convert abs(number) to an unsigned long)
|
||||
ztolong(z) (convert abs(number) to a long)
|
||||
|
||||
If the value is too large for ztofull(), ztoulong() or ztolong(), only
|
||||
the low order bits converted.
|
||||
|
||||
There are two types of comparisons you can make on ZVALUEs. This is whether
|
||||
or not they are equal, or the ordering on size of the numbers. The zcmp
|
||||
function tests whether two ZVALUEs are equal, returning TRUE if they differ.
|
||||
The zrel function tests the relative sizes of two ZVALUEs, returning -1 if
|
||||
the first one is smaller, 0 if they are the same, and 1 if the first one
|
||||
is larger.
|
||||
|
||||
---------------
|
||||
USING FRACTIONS
|
||||
---------------
|
||||
|
||||
The arbitrary precision fractional routines define a structure called NUMBER.
|
||||
This is defined in qmath.h. A NUMBER contains two ZVALUEs for the numerator
|
||||
and denominator of a fraction, and a count of the number of uses there are
|
||||
for this NUMBER. The numerator and denominator are always in lowest terms,
|
||||
and the sign of the number is contained in the numerator. The denominator
|
||||
is always positive. If the NUMBER is an integer, the denominator has the
|
||||
value 1.
|
||||
|
||||
Unlike ZVALUEs, NUMBERs are passed using pointers, and pointers to them are
|
||||
returned by functions. So the basic type for using fractions is not really
|
||||
(NUMBER), but is (NUMBER *). NUMBERs are allocated using the qalloc routine.
|
||||
This returns a pointer to a number which has the value 1. Because of the
|
||||
special property of a ZVALUE of 1, the numerator and denominator of this
|
||||
returned value can simply be overwritten with new ZVALUEs without needing
|
||||
to free them first. The following illustrates this:
|
||||
|
||||
NUMBER *q;
|
||||
|
||||
q = qalloc();
|
||||
itoz(55L, &q->num);
|
||||
|
||||
A better way to create NUMBERs with particular values is to use the itoq,
|
||||
iitoq, or atoq functions. Using itoq makes a long value into a NUMBER,
|
||||
using iitoq makes a pair of longs into the numerator and denominator of a
|
||||
NUMBER (reducing them first if needed), and atoq converts a string representing
|
||||
a number into the corresponding NUMBER. The atoq function accepts input in
|
||||
integral, fractional, real, or exponential formats. Examples of allocating
|
||||
numbers are:
|
||||
|
||||
NUMBER *q1, *q2, *q3;
|
||||
|
||||
q1 = itoq(66L);
|
||||
q2 = iitoq(2L, 3L);
|
||||
q3 = atoq("456.78");
|
||||
|
||||
Also unlike ZVALUEs, NUMBERs are quickly copied. This is because they contain
|
||||
a link count, which is the number of pointers there are to the NUMBER. The
|
||||
qlink macro is used to copy a pointer to a NUMBER, and simply increments
|
||||
the link count and returns the same pointer. Since it is a macro, the
|
||||
argument should not be a function call, but a real pointer variable. The
|
||||
qcopy routine will actually make a new copy of a NUMBER, with a new link
|
||||
count of 1. This is not usually needed.
|
||||
|
||||
NUMBERs are deleted using the qfree routine. This decrements the link count
|
||||
in the NUMBER, and if it reaches zero, then it will deallocate both of
|
||||
the ZVALUEs contained within the NUMBER, and then puts the NUMBER structure
|
||||
onto a free list for quick reuse. The following is an example of allocating
|
||||
NUMBERs, copying them, adding them, and finally deleting them again.
|
||||
|
||||
NUMBER *q1, *q2, *q3;
|
||||
|
||||
q1 = itoq(111L);
|
||||
q2 = qlink(q1);
|
||||
q3 = qqadd(q1, q2);
|
||||
qfree(q1);
|
||||
qfree(q2);
|
||||
qfree(q3);
|
||||
|
||||
Because of the passing of pointers and the ability to copy numbers easily,
|
||||
you might wish to use the rational number routines even for integral
|
||||
calculations. They might be slightly slower than the raw integral routines,
|
||||
but are more convenient to program with.
|
||||
|
||||
The prototypes for the fractional routines are defined in qmath.h.
|
||||
Many of the definitions for integer functions parallel the ones defined
|
||||
in zmath.h. But there are also functions used only for fractions.
|
||||
Examples of these are qnum to return the numerator, qden to return the
|
||||
denominator, qint to return the integer part of, qfrac to return the
|
||||
fractional part of, and qinv to invert a fraction.
|
||||
|
||||
There are some transcendental functions in the library, such as sin and cos.
|
||||
These cannot be evaluated exactly as fractions. Therefore, they accept
|
||||
another argument which tells how accurate you want the result. This is an
|
||||
"epsilon" value, and the returned value will be within that quantity of
|
||||
the correct value. This is usually an absolute difference, but for some
|
||||
functions (such as exp), this is a relative difference. For example, to
|
||||
calculate sin(0.5) to 100 decimal places, you could do:
|
||||
|
||||
NUMBER *q, *ans, *epsilon;
|
||||
|
||||
q = atoq("0.5");
|
||||
epsilon = atoq("1e-100");
|
||||
ans = qsin(q, epsilon);
|
||||
|
||||
There are many convenience macros similar to the ones for ZVALUEs which can
|
||||
give quick information about NUMBERs. In addition, there are some new ones
|
||||
applicable to fractions. These are all defined in qmath.h. Some of these
|
||||
macros are:
|
||||
|
||||
qiszero(q) (number is zero)
|
||||
qisneg(q) (number is negative)
|
||||
qispos(q) (number is positive)
|
||||
qisint(q) (number is an integer)
|
||||
qisfrac(q) (number is fractional)
|
||||
qisunit(q) (number is 1 or -1)
|
||||
qisone(q) (number is 1)
|
||||
qisnegone(q) (number is -1)
|
||||
qistwo(q) (number is 2)
|
||||
qiseven(q) (number is an even integer)
|
||||
qisodd(q) (number is an odd integer)
|
||||
qistwopower(q) (number is a power of 2 >= 1)
|
||||
|
||||
The comparisons for NUMBERs are similar to the ones for ZVALUEs. You use the
|
||||
qcmp and qrel functions.
|
||||
|
||||
There are four predefined values for fractions. You should qlink them when
|
||||
you want to use them. These are _qzero_, _qone_, _qnegone_, and _qonehalf_.
|
||||
These have the values 0, 1, -1, and 1/2. An example of using them is:
|
||||
|
||||
NUMBER *q1, *q2;
|
||||
|
||||
q1 = qlink(&_qonehalf_);
|
||||
q2 = qlink(&_qone_);
|
||||
|
||||
---------------------
|
||||
USING COMPLEX NUMBERS
|
||||
---------------------
|
||||
|
||||
The arbitrary precision complex arithmetic routines define a structure
|
||||
called COMPLEX. This is defined in cmath.h. This contains two NUMBERs
|
||||
for the real and imaginary parts of a complex number, and a count of the
|
||||
number of links there are to this COMPLEX number.
|
||||
|
||||
The complex number routines work similarly to the fractional routines.
|
||||
You can allocate a COMPLEX structure using comalloc (NOT calloc!).
|
||||
You can construct a COMPLEX number with desired real and imaginary
|
||||
fractional parts using qqtoc. You can copy COMPLEX values using clink
|
||||
which increments the link count. And you free a COMPLEX value using cfree.
|
||||
The following example illustrates this:
|
||||
|
||||
NUMBER *q1, *q2;
|
||||
COMPLEX *c1, *c2, *c3;
|
||||
|
||||
q1 = itoq(3L);
|
||||
q2 = itoq(4L);
|
||||
c1 = qqtoc(q1, q2);
|
||||
qfree(q1);
|
||||
qfree(q2);
|
||||
c2 = clink(c1);
|
||||
c3 = cmul(c1, c2);
|
||||
cfree(c1);
|
||||
cfree(c2);
|
||||
cfree(c3);
|
||||
|
||||
As a shortcut, when you want to manipulate a COMPLEX value by a real value,
|
||||
you can use the caddq, csubq, cmulq, and cdivq routines. These accept one
|
||||
COMPLEX value and one NUMBER value, and produce a COMPLEX value.
|
||||
|
||||
There is no direct routine to convert a string value into a COMPLEX value.
|
||||
But you can do this yourself by converting two strings into two NUMBERS,
|
||||
and then using the qqtoc routine.
|
||||
|
||||
COMPLEX values are always returned from these routines. To split out the
|
||||
real and imaginary parts into normal NUMBERs, you can simply qlink the
|
||||
two components, as shown in the following example:
|
||||
|
||||
COMPLEX *c;
|
||||
NUMBER *rp, *ip;
|
||||
|
||||
c = calloc();
|
||||
rp = qlink(c->real);
|
||||
ip = qlink(c->imag);
|
||||
|
||||
There are many macros for checking quick things about complex numbers,
|
||||
similar to the ZVALUE and NUMBER macros. In addition, there are some
|
||||
only used for complex numbers. Examples of macros are:
|
||||
|
||||
cisreal(c) (number is real)
|
||||
cisimag(c) (number is pure imaginary)
|
||||
ciszero(c) (number is zero)
|
||||
cisnegone(c) (number is -1)
|
||||
cisone(c) (number is 1)
|
||||
cisrunit(c) (number is 1 or -1)
|
||||
cisiunit(c) (number is i or -i)
|
||||
cisunit(c) (number is 1, -1, i, or -i)
|
||||
cistwo(c) (number is 2)
|
||||
cisint(c) (number is has integer real and imaginary parts)
|
||||
ciseven(c) (number is has even real and imaginary parts)
|
||||
cisodd(c) (number is has odd real and imaginary parts)
|
||||
|
||||
There is only one comparison you can make for COMPLEX values, and that is
|
||||
for equality. The ccmp function returns TRUE if two complex numbers differ.
|
||||
|
||||
There are three predefined values for complex numbers. You should clink
|
||||
them when you want to use them. They are _czero_, _cone_, and _conei_.
|
||||
These have the values 0, 1, and i.
|
68
README
Normal file
68
README
Normal file
@@ -0,0 +1,68 @@
|
||||
# Copyright (c) 1994 David I. Bell
|
||||
# Permission is granted to use, distribute, or modify this source,
|
||||
# provided that this copyright notice remains intact.
|
||||
#
|
||||
# Arbitrary precision calculator.
|
||||
|
||||
I am allowing this calculator to be freely distributed for personal uses.
|
||||
Like all multi-precision programs, you should not depend absolutely on
|
||||
its results, since bugs in such programs can be insidious and only rarely
|
||||
show up.
|
||||
|
||||
-dbell-
|
||||
|
||||
p.s. By Landon Curt Noll:
|
||||
|
||||
Building calc in 3 easy steps:
|
||||
|
||||
1) Look at the makefile, and adjust it to suit your needs.
|
||||
|
||||
Here are some Makefile hints:
|
||||
|
||||
In the past, some people have had to adjust the VARARG or
|
||||
TERMCONTROL because the Makefile cannot always guess
|
||||
correctly for certain systems. You may need to play with
|
||||
these values if you experience problems.
|
||||
|
||||
The default compiler used is 'cc'. The default compiler flag
|
||||
is '-O'. If you have gcc, or gcc v2 (or better) you should use
|
||||
that instead. Some compilers allow for optimization beyond
|
||||
just -O (gcc v2 has -O2, mips cc has -O3). You should select
|
||||
the best flag for speed optimization. Calc can be cpu intensive
|
||||
so selecting a quality compiler and good optimization level can
|
||||
really pay off.
|
||||
|
||||
2) build calc:
|
||||
|
||||
make all
|
||||
|
||||
3) test calc:
|
||||
|
||||
make check
|
||||
|
||||
==>>>If you run into problems, follow the instructions in the BUGS file<<<==
|
||||
|
||||
=-=
|
||||
|
||||
For further reading:
|
||||
|
||||
LIBRARY
|
||||
explains how programs can use libcalc.a to take advantage
|
||||
of the calc multi-precision routines.
|
||||
|
||||
help/todo
|
||||
current wish list for calc
|
||||
|
||||
CHANGES
|
||||
recent changes to calc
|
||||
|
||||
BUGS
|
||||
known bugs, mis-features and how to report problems
|
||||
|
||||
help/full
|
||||
full set of calc documentation
|
||||
|
||||
=-=
|
||||
|
||||
David I. Bell dbell@auug.org.au
|
||||
chongo@toad.com <Landon Curt Noll -- chongo@toad.com> /\../\
|
52
README.FIRST
Normal file
52
README.FIRST
Normal file
@@ -0,0 +1,52 @@
|
||||
Dear alpha tester,
|
||||
|
||||
Thanks for taking the time to try out this alpha version of calc! We are
|
||||
interested in any/all feedback that you may have on this version. In
|
||||
particular we would like to hear about:
|
||||
|
||||
* compile problems
|
||||
* regression test problems (try: make check)
|
||||
* compiler warnings
|
||||
* special compile flags/options that you needed
|
||||
* Makefile problems
|
||||
* help file problems
|
||||
* misc nits and typos
|
||||
|
||||
We would like to offer a clean compile across a wide verity of platforms,
|
||||
so if you can test on several, so much the better!
|
||||
|
||||
Calc distributions may be obtained from:
|
||||
|
||||
ftp://ftp.uu.net/pub/calc
|
||||
|
||||
If you don't have ftp access to that site, or if you do not find a more
|
||||
recent version (you may have a special pre-released version that is
|
||||
more advanced than what is in the ftp archive) send EMail to:
|
||||
|
||||
chongo@toad.com
|
||||
|
||||
Indicate the version you have and that you would like a more up
|
||||
to date version.
|
||||
|
||||
=-=
|
||||
|
||||
Misc items TODO before Beta release:
|
||||
|
||||
* improve the coverage in the 'SEE ALSO' help file lists
|
||||
|
||||
* where reasonable, be sure that regress.cal tests builtin functions
|
||||
|
||||
* add the Blum-Blum-Shub random() generator code
|
||||
|
||||
* add code to allow of the reading, writing and processing of binary data
|
||||
|
||||
* add shs, shs-1 and md5 hashing functions. Use align32.h.
|
||||
|
||||
* add mod h*2^n+/-1 function for integers
|
||||
|
||||
* be sure that CHANGES is up to date,
|
||||
look over the help/todo file and update as needed,
|
||||
revisit issues in the BUGS file and
|
||||
change this file :-)
|
||||
|
||||
* clean the source code and document it better
|
448
addop.c
Normal file
448
addop.c
Normal file
@@ -0,0 +1,448 @@
|
||||
/*
|
||||
* Copyright (c) 1995 David I. Bell
|
||||
* Permission is granted to use, distribute, or modify this source,
|
||||
* provided that this copyright notice remains intact.
|
||||
*
|
||||
* Add opcodes to a function being compiled.
|
||||
*/
|
||||
|
||||
#include "calc.h"
|
||||
#include "opcodes.h"
|
||||
#include "string.h"
|
||||
#include "func.h"
|
||||
#include "token.h"
|
||||
#include "label.h"
|
||||
#include "symbol.h"
|
||||
|
||||
|
||||
#define FUNCALLOCSIZE 20 /* reallocate size for functions */
|
||||
#define OPCODEALLOCSIZE 100 /* reallocate size for opcodes in functions */
|
||||
|
||||
|
||||
static long maxopcodes; /* number of opcodes available */
|
||||
static long newindex; /* index of new function */
|
||||
static long oldop; /* previous opcode */
|
||||
static long debugline; /* line number of latest debug opcode */
|
||||
static long funccount; /* number of functions */
|
||||
static long funcavail; /* available number of functions */
|
||||
static FUNC *functemplate; /* function definition template */
|
||||
static FUNC **functions; /* table of functions */
|
||||
static STRINGHEAD funcnames; /* function names */
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the table of user defined functions.
|
||||
*/
|
||||
void
|
||||
initfunctions(void)
|
||||
{
|
||||
initstr(&funcnames);
|
||||
maxopcodes = OPCODEALLOCSIZE;
|
||||
functemplate = (FUNC *) malloc(funcsize(maxopcodes));
|
||||
if (functemplate == NULL) {
|
||||
math_error("Cannot allocate function template");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
functions = (FUNC **) malloc(sizeof(FUNC *) * FUNCALLOCSIZE);
|
||||
if (functions == NULL) {
|
||||
math_error("Cannot allocate function table");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
funccount = 0;
|
||||
funcavail = FUNCALLOCSIZE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Show the list of user defined functions.
|
||||
*/
|
||||
void
|
||||
showfunctions(void)
|
||||
{
|
||||
FUNC **fpp; /* pointer into function table */
|
||||
FUNC *fp; /* current function */
|
||||
|
||||
if (funccount == 0) {
|
||||
printf("No user functions defined.\n");
|
||||
return;
|
||||
}
|
||||
printf("Name Arguments\n");
|
||||
printf("---- ---------\n");
|
||||
for (fpp = &functions[funccount - 1]; fpp >= functions; fpp--) {
|
||||
fp = *fpp;
|
||||
if (fp == NULL)
|
||||
continue;
|
||||
printf("%-12s %-2d\n", fp->f_name, fp->f_paramcount);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize a function for definition.
|
||||
* Newflag is TRUE if we should allocate a new function structure,
|
||||
* instead of the usual overwriting of the template function structure.
|
||||
* The new structure is returned in the global curfunc variable.
|
||||
*
|
||||
* given:
|
||||
* name name of function
|
||||
* newflag TRUE if need new structure
|
||||
*/
|
||||
void
|
||||
beginfunc(char *name, BOOL newflag)
|
||||
{
|
||||
register FUNC *fp; /* current function */
|
||||
|
||||
newindex = adduserfunc(name);
|
||||
maxopcodes = OPCODEALLOCSIZE;
|
||||
fp = functemplate;
|
||||
if (newflag) {
|
||||
fp = (FUNC *) malloc(funcsize(maxopcodes));
|
||||
if (fp == NULL) {
|
||||
math_error("Cannot allocate temporary function");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
}
|
||||
fp->f_next = NULL;
|
||||
fp->f_localcount = 0;
|
||||
fp->f_opcodecount = 0;
|
||||
fp->f_savedvalue.v_type = V_NULL;
|
||||
fp->f_name = namestr(&funcnames, newindex);
|
||||
curfunc = fp;
|
||||
initlocals();
|
||||
initlabels();
|
||||
oldop = OP_NOP;
|
||||
debugline = 0;
|
||||
errorcount = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Commit the just defined function for use.
|
||||
* This replaces any existing definition for the function.
|
||||
* This should only be called for normal user-defined functions.
|
||||
*/
|
||||
void
|
||||
endfunc(void)
|
||||
{
|
||||
register FUNC *fp; /* function just finished */
|
||||
unsigned long size; /* size of just created function */
|
||||
|
||||
checklabels();
|
||||
if (errorcount) {
|
||||
printf("\"%s\": %ld error%s\n", curfunc->f_name, errorcount,
|
||||
((errorcount == 1) ? "" : "s"));
|
||||
return;
|
||||
}
|
||||
size = funcsize(curfunc->f_opcodecount);
|
||||
fp = (FUNC *) malloc(size);
|
||||
if (fp == NULL) {
|
||||
math_error("Cannot commit function");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
memcpy((char *) fp, (char *) curfunc, size);
|
||||
if (curfunc != functemplate)
|
||||
free(curfunc);
|
||||
if (conf->traceflags & TRACE_FNCODES) {
|
||||
dumpnames = TRUE;
|
||||
for (size = 0; size < fp->f_opcodecount; ) {
|
||||
printf("%ld: ", (long)size);
|
||||
size += dumpop(&fp->f_opcodes[size]);
|
||||
}
|
||||
}
|
||||
if (functions[newindex]) {
|
||||
free(functions[newindex]);
|
||||
fprintf(stderr, "**** %s() has been redefined\n", fp->f_name);
|
||||
}
|
||||
functions[newindex] = fp;
|
||||
objuncache();
|
||||
if (inputisterminal())
|
||||
printf("\"%s\" defined\n", fp->f_name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Find the user function with the specified name, and return its index.
|
||||
* If the function does not exist, its name is added to the function table
|
||||
* and an error will be generated when it is called if it is still undefined.
|
||||
*
|
||||
* given:
|
||||
* name name of function
|
||||
*/
|
||||
long
|
||||
adduserfunc(char *name)
|
||||
{
|
||||
long index; /* index of function */
|
||||
|
||||
index = findstr(&funcnames, name);
|
||||
if (index >= 0)
|
||||
return index;
|
||||
if (funccount >= funcavail) {
|
||||
functions = (FUNC **) realloc(functions,
|
||||
sizeof(FUNC *) * (funcavail + FUNCALLOCSIZE));
|
||||
if (functions == NULL) {
|
||||
math_error("Failed to reallocate function table");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
funcavail += FUNCALLOCSIZE;
|
||||
}
|
||||
if (addstr(&funcnames, name) == NULL) {
|
||||
math_error("Cannot save function name");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
index = funccount++;
|
||||
functions[index] = NULL;
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Clear any optimization that may be done for the next opcode.
|
||||
* This is used when defining a label.
|
||||
*/
|
||||
void
|
||||
clearopt(void)
|
||||
{
|
||||
oldop = OP_NOP;
|
||||
debugline = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Find a function structure given its index.
|
||||
*/
|
||||
FUNC *
|
||||
findfunc(long index)
|
||||
{
|
||||
if ((unsigned long) index >= funccount) {
|
||||
math_error("Undefined function");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
return functions[index];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the name of a function given its index.
|
||||
*/
|
||||
char *
|
||||
namefunc(long index)
|
||||
{
|
||||
return namestr(&funcnames, index);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Let a matrix indexing operation know that it will be treated as a write
|
||||
* reference instead of just as a read reference.
|
||||
*/
|
||||
void
|
||||
writeindexop(void)
|
||||
{
|
||||
if (oldop == OP_INDEXADDR)
|
||||
curfunc->f_opcodes[curfunc->f_opcodecount - 1] = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add an opcode to the current function being compiled.
|
||||
* Note: This can change the curfunc global variable when the
|
||||
* function needs expanding.
|
||||
*/
|
||||
void
|
||||
addop(long op)
|
||||
{
|
||||
register FUNC *fp; /* current function */
|
||||
NUMBER *q;
|
||||
|
||||
fp = curfunc;
|
||||
if ((fp->f_opcodecount + 5) >= maxopcodes) {
|
||||
maxopcodes += OPCODEALLOCSIZE;
|
||||
fp = (FUNC *) malloc(funcsize(maxopcodes));
|
||||
if (fp == NULL) {
|
||||
math_error("cannot malloc function");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
memcpy((char *) fp, (char *) curfunc,
|
||||
funcsize(curfunc->f_opcodecount));
|
||||
if (curfunc != functemplate)
|
||||
free(curfunc);
|
||||
curfunc = fp;
|
||||
}
|
||||
/*
|
||||
* Check the current opcode against the previous opcode and try to
|
||||
* slightly optimize the code depending on the various combinations.
|
||||
*/
|
||||
if (op == OP_GETVALUE) {
|
||||
switch (oldop) {
|
||||
|
||||
case OP_NUMBER: case OP_ZERO: case OP_ONE: case OP_IMAGINARY:
|
||||
case OP_GETEPSILON: case OP_SETEPSILON: case OP_STRING:
|
||||
case OP_UNDEF: case OP_GETCONFIG: case OP_SETCONFIG:
|
||||
return;
|
||||
case OP_DUPLICATE:
|
||||
fp->f_opcodes[fp->f_opcodecount - 1] = OP_DUPVALUE;
|
||||
oldop = OP_DUPVALUE;
|
||||
return;
|
||||
case OP_FIADDR:
|
||||
fp->f_opcodes[fp->f_opcodecount - 1] = OP_FIVALUE;
|
||||
oldop = OP_FIVALUE;
|
||||
return;
|
||||
case OP_GLOBALADDR:
|
||||
fp->f_opcodes[fp->f_opcodecount - 2] = OP_GLOBALVALUE;
|
||||
oldop = OP_GLOBALVALUE;
|
||||
return;
|
||||
case OP_LOCALADDR:
|
||||
fp->f_opcodes[fp->f_opcodecount - 2] = OP_LOCALVALUE;
|
||||
oldop = OP_LOCALVALUE;
|
||||
return;
|
||||
case OP_PARAMADDR:
|
||||
fp->f_opcodes[fp->f_opcodecount - 2] = OP_PARAMVALUE;
|
||||
oldop = OP_PARAMVALUE;
|
||||
return;
|
||||
case OP_ELEMADDR:
|
||||
fp->f_opcodes[fp->f_opcodecount - 2] = OP_ELEMVALUE;
|
||||
oldop = OP_ELEMVALUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ((op == OP_NEGATE) && (oldop == OP_NUMBER)) {
|
||||
q = constvalue(fp->f_opcodes[fp->f_opcodecount - 1]);
|
||||
fp->f_opcodes[fp->f_opcodecount - 1] = addqconstant(qneg(q));
|
||||
oldop = OP_NUMBER;
|
||||
return;
|
||||
}
|
||||
if ((op == OP_POWER) && (oldop == OP_NUMBER)) {
|
||||
if (qcmpi(constvalue(fp->f_opcodes[fp->f_opcodecount - 1]), 2L) == 0) {
|
||||
fp->f_opcodecount--;
|
||||
fp->f_opcodes[fp->f_opcodecount - 1] = OP_SQUARE;
|
||||
oldop = OP_SQUARE;
|
||||
return;
|
||||
}
|
||||
if (qcmpi(constvalue(fp->f_opcodes[fp->f_opcodecount - 1]), 4L) == 0) {
|
||||
fp->f_opcodes[fp->f_opcodecount - 2] = OP_SQUARE;
|
||||
fp->f_opcodes[fp->f_opcodecount - 1] = OP_SQUARE;
|
||||
oldop = OP_SQUARE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ((op == OP_POP) && (oldop == OP_ASSIGN)) { /* optimize */
|
||||
fp->f_opcodes[fp->f_opcodecount - 1] = OP_ASSIGNPOP;
|
||||
oldop = OP_ASSIGNPOP;
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* No optimization possible, so store the opcode.
|
||||
*/
|
||||
fp->f_opcodes[fp->f_opcodecount] = op;
|
||||
fp->f_opcodecount++;
|
||||
oldop = op;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add an opcode and and one integer argument to the current function
|
||||
* being compiled.
|
||||
*/
|
||||
void
|
||||
addopone(long op, long arg)
|
||||
{
|
||||
NUMBER *q;
|
||||
|
||||
switch (op) {
|
||||
case OP_NUMBER:
|
||||
q = constvalue(arg);
|
||||
if (q == NULL)
|
||||
break;
|
||||
if (qiszero(q)) {
|
||||
addop(OP_ZERO);
|
||||
return;
|
||||
}
|
||||
if (qisone(q)) {
|
||||
addop(OP_ONE);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_DEBUG:
|
||||
if ((conf->traceflags & TRACE_NODEBUG) || (arg == debugline))
|
||||
return;
|
||||
debugline = arg;
|
||||
if (oldop == OP_DEBUG) {
|
||||
curfunc->f_opcodes[curfunc->f_opcodecount - 1] = arg;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
addop(op);
|
||||
curfunc->f_opcodes[curfunc->f_opcodecount] = arg;
|
||||
curfunc->f_opcodecount++;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add an opcode and and two integer arguments to the current function
|
||||
* being compiled.
|
||||
*/
|
||||
void
|
||||
addoptwo(long op, long arg1, long arg2)
|
||||
{
|
||||
addop(op);
|
||||
curfunc->f_opcodes[curfunc->f_opcodecount++] = arg1;
|
||||
curfunc->f_opcodes[curfunc->f_opcodecount++] = arg2;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add an opcode and a character pointer to the function being compiled.
|
||||
*/
|
||||
void
|
||||
addopptr(long op, char *ptr)
|
||||
{
|
||||
char **ptraddr;
|
||||
|
||||
addop(op);
|
||||
ptraddr = (char **) &curfunc->f_opcodes[curfunc->f_opcodecount];
|
||||
*ptraddr = ptr;
|
||||
curfunc->f_opcodecount += PTR_SIZE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add an opcode and an index and an argument count for a function call.
|
||||
*/
|
||||
void
|
||||
addopfunction(long op, long index, int count)
|
||||
{
|
||||
long newop;
|
||||
|
||||
if ((op == OP_CALL) && ((newop = builtinopcode(index)) != OP_NOP)) {
|
||||
if ((newop == OP_SETCONFIG) && (count == 1))
|
||||
newop = OP_GETCONFIG;
|
||||
if ((newop == OP_SETEPSILON) && (count == 0))
|
||||
newop = OP_GETEPSILON;
|
||||
if ((newop == OP_ABS) && (count == 1))
|
||||
addop(OP_GETEPSILON);
|
||||
addop(newop);
|
||||
return;
|
||||
}
|
||||
addop(op);
|
||||
curfunc->f_opcodes[curfunc->f_opcodecount++] = index;
|
||||
curfunc->f_opcodes[curfunc->f_opcodecount++] = count;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add a jump-type opcode and a label to the function being compiled.
|
||||
*
|
||||
* given:
|
||||
* label label to be added
|
||||
*/
|
||||
void
|
||||
addoplabel(long op, LABEL *label)
|
||||
{
|
||||
addop(op);
|
||||
uselabel(label);
|
||||
}
|
||||
|
||||
/* END CODE */
|
79
align32.c
Normal file
79
align32.c
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* align32 - determine if 32 bit accesses must be aligned
|
||||
*
|
||||
* This file was written by:
|
||||
*
|
||||
* Landon Curt Noll (chongo@toad.com) chongo <was here> /\../\
|
||||
*
|
||||
* This code has been placed in the public domain. Please do not
|
||||
* copyright this code.
|
||||
*
|
||||
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO
|
||||
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MER-
|
||||
* CHANTABILITY AND FITNESS. IN NO EVENT SHALL LANDON CURT
|
||||
* NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include "longbits.h"
|
||||
|
||||
#include "have_unistd.h"
|
||||
#if defined(HAVE_UNISTD_H)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
static void buserr(void); /* catch alignment errors */
|
||||
|
||||
|
||||
MAIN
|
||||
main(void)
|
||||
{
|
||||
char byte[2*sizeof(USB32)]; /* mis-alignment buffer */
|
||||
USB32 *p; /* mis-alignment pointer */
|
||||
int i;
|
||||
|
||||
#if defined(MUST_ALIGN32)
|
||||
/* force alignment */
|
||||
printf("#define MUST_ALIGN32\t%c* forced to align 32 bit values *%c\n",
|
||||
'/', '/');
|
||||
#else
|
||||
/* setup to catch alignment bus errors */
|
||||
signal(SIGBUS, buserr);
|
||||
signal(SIGSEGV, buserr); /* some systems will generate SEGV instead! */
|
||||
|
||||
/* mis-align our long fetches */
|
||||
for (i=0; i < sizeof(USB32); ++i) {
|
||||
p = (USB32 *)(byte+i);
|
||||
*p = i;
|
||||
*p += 1;
|
||||
}
|
||||
|
||||
/* if we got here, then we can mis-align longs */
|
||||
printf("#undef MUST_ALIGN32\t%c* can mis-align 32 bit values *%c\n",
|
||||
'/', '/');
|
||||
|
||||
#endif
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* buserr - catch an alignment error
|
||||
*
|
||||
* given:
|
||||
* arg to keep ANSI C happy
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
static void
|
||||
buserr(int arg)
|
||||
{
|
||||
/* alignment is required */
|
||||
printf("#define MUST_ALIGN32\t%c* must align 32 bit values *%c\n",
|
||||
'/', '/');
|
||||
exit(0);
|
||||
}
|
64
alloc.h
Normal file
64
alloc.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 1995 David I. Bell
|
||||
* Permission is granted to use, distribute, or modify this source,
|
||||
* provided that this copyright notice remains intact.
|
||||
*/
|
||||
|
||||
|
||||
#if !defined(ALLOC_H)
|
||||
#define ALLOC_H
|
||||
|
||||
#include "have_malloc.h"
|
||||
#include "have_newstr.h"
|
||||
#include "have_string.h"
|
||||
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#else
|
||||
# if defined(__STDC__) && __STDC__ != 0
|
||||
extern void *malloc();
|
||||
extern void *realloc();
|
||||
extern void free();
|
||||
# else
|
||||
extern char *malloc();
|
||||
extern char *realloc();
|
||||
extern void free();
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
|
||||
#else
|
||||
|
||||
# if defined(HAVE_NEWSTR)
|
||||
extern void *memcpy();
|
||||
extern void *memset();
|
||||
# if defined(__STDC__) && __STDC__ != 0
|
||||
extern size_t strlen();
|
||||
# else
|
||||
extern long strlen(); /* should be size_t, but old systems don't have it */
|
||||
# endif
|
||||
# else /* HAVE_NEWSTR */
|
||||
extern void bcopy();
|
||||
extern void bfill();
|
||||
extern char *index();
|
||||
# endif /* HAVE_NEWSTR */
|
||||
extern char *strchr();
|
||||
extern char *strcpy();
|
||||
extern char *strncpy();
|
||||
extern char *strcat();
|
||||
extern int strcmp();
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_NEWSTR)
|
||||
#undef memcpy
|
||||
#define memcpy(s1, s2, n) bcopy(s2, s1, n)
|
||||
#undef memset
|
||||
#define memset(s, c, n) bfill(s, n, c)
|
||||
#undef strchr
|
||||
#define strchr(s, c) index(s, c)
|
||||
#endif /* HAVE_NEWSTR */
|
||||
|
||||
#endif /* !ALLOC_H */
|
477
assocfunc.c
Normal file
477
assocfunc.c
Normal file
@@ -0,0 +1,477 @@
|
||||
/*
|
||||
* Copyright (c) 1995 David I. Bell
|
||||
* Permission is granted to use, distribute, or modify this source,
|
||||
* provided that this copyright notice remains intact.
|
||||
*
|
||||
* Association table routines.
|
||||
* An association table is a type of value which can be "indexed" by
|
||||
* one or more arbitrary values. Each element in the table is thus an
|
||||
* association between a particular set of index values and a result value.
|
||||
* The elements in an association table are stored in a hash table for
|
||||
* quick access.
|
||||
*/
|
||||
|
||||
#include "value.h"
|
||||
|
||||
|
||||
#define MINHASHSIZE 31 /* minimum size of hash tables */
|
||||
#define GROWHASHSIZE 50 /* approximate growth for hash tables */
|
||||
#define CHAINLENGTH 10 /* desired number of elements on a hash chain */
|
||||
#define ELEMSIZE(n) (sizeof(ASSOCELEM) + (sizeof(VALUE) * ((n) - 1)))
|
||||
|
||||
|
||||
static ASSOCELEM *elemindex(ASSOC *ap, long index);
|
||||
static BOOL compareindices(VALUE *v1, VALUE *v2, long dim);
|
||||
static void resize(ASSOC *ap, long newsize);
|
||||
static void assoc_elemfree(ASSOCELEM *ep);
|
||||
|
||||
|
||||
/*
|
||||
* Return the address of the value specified by normal indexing of
|
||||
* an association. The create flag is TRUE if a value is going to be
|
||||
* assigned into the specified indexing location. If create is FALSE and
|
||||
* the index value doesn't exist, a pointer to a NULL value is returned.
|
||||
*
|
||||
* given:
|
||||
* ap association to index into
|
||||
* create whether to create the index value
|
||||
* dim dimension of the indexing
|
||||
* indices table of values being indexed by
|
||||
*/
|
||||
VALUE *
|
||||
associndex(ASSOC *ap, BOOL create, long dim, VALUE *indices)
|
||||
{
|
||||
ASSOCELEM **listhead;
|
||||
ASSOCELEM *ep;
|
||||
static VALUE val;
|
||||
QCKHASH hash;
|
||||
int i;
|
||||
|
||||
if (dim <= 0) {
|
||||
math_error("No dimensions for indexing association");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the hash value to use for this set of indices
|
||||
* so that we can first select the correct hash chain, and
|
||||
* also so we can quickly compare each element for a match.
|
||||
*/
|
||||
hash = (QCKHASH)0;
|
||||
for (i = 0; i < dim; i++)
|
||||
hash = hashvalue(&indices[i], hash);
|
||||
|
||||
/*
|
||||
* Search the correct hash chain for the specified set of indices.
|
||||
* If found, return the address of the found element's value.
|
||||
*/
|
||||
listhead = &ap->a_table[hash % ap->a_size];
|
||||
for (ep = *listhead; ep; ep = ep->e_next) {
|
||||
if ((ep->e_hash != hash) || (ep->e_dim != dim))
|
||||
continue;
|
||||
if (compareindices(ep->e_indices, indices, dim))
|
||||
return &ep->e_value;
|
||||
}
|
||||
|
||||
/*
|
||||
* The set of indices was not found.
|
||||
* Either return a pointer to a NULL value for a read reference,
|
||||
* or allocate a new element in the list for a write reference.
|
||||
*/
|
||||
if (!create) {
|
||||
val.v_type = V_NULL;
|
||||
return &val;
|
||||
}
|
||||
|
||||
ep = (ASSOCELEM *) malloc(ELEMSIZE(dim));
|
||||
if (ep == NULL) {
|
||||
math_error("Cannot allocate association element");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
ep->e_dim = dim;
|
||||
ep->e_hash = hash;
|
||||
ep->e_value.v_type = V_NULL;
|
||||
for (i = 0; i < dim; i++)
|
||||
copyvalue(&indices[i], &ep->e_indices[i]);
|
||||
ep->e_next = *listhead;
|
||||
*listhead = ep;
|
||||
ap->a_count++;
|
||||
|
||||
resize(ap, ap->a_count / CHAINLENGTH);
|
||||
|
||||
return &ep->e_value;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Search an association for the specified value starting at the
|
||||
* specified index. Returns the element number (zero based) of the
|
||||
* found value, or -1 if the value was not found.
|
||||
*/
|
||||
long
|
||||
assocsearch(ASSOC *ap, VALUE *vp, long index)
|
||||
{
|
||||
ASSOCELEM *ep;
|
||||
|
||||
if (index < 0)
|
||||
index = 0;
|
||||
while (TRUE) {
|
||||
ep = elemindex(ap, index);
|
||||
if (ep == NULL)
|
||||
return -1;
|
||||
if (!comparevalue(&ep->e_value, vp))
|
||||
return index;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Search an association backwards for the specified value starting at the
|
||||
* specified index. Returns the element number (zero based) of the
|
||||
* found value, or -1 if the value was not found.
|
||||
*/
|
||||
long
|
||||
assocrsearch(ASSOC *ap, VALUE *vp, long index)
|
||||
{
|
||||
ASSOCELEM *ep;
|
||||
|
||||
if (index >= ap->a_count)
|
||||
index = ap->a_count - 1;
|
||||
while (TRUE) {
|
||||
ep = elemindex(ap, index);
|
||||
if (ep == NULL)
|
||||
return -1;
|
||||
if (!comparevalue(&ep->e_value, vp))
|
||||
return index;
|
||||
index--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the address of an element of an association indexed by the
|
||||
* double-bracket operation.
|
||||
*
|
||||
* given:
|
||||
* ap association to index into
|
||||
* index index of desired element
|
||||
*/
|
||||
static ASSOCELEM *
|
||||
elemindex(ASSOC *ap, long index)
|
||||
{
|
||||
ASSOCELEM *ep;
|
||||
int i;
|
||||
|
||||
if ((index < 0) || (index > ap->a_count))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* This loop should be made more efficient by remembering
|
||||
* previously requested locations within the association.
|
||||
*/
|
||||
for (i = 0; i < ap->a_size; i++) {
|
||||
for (ep = ap->a_table[i]; ep; ep = ep->e_next) {
|
||||
if (index-- == 0)
|
||||
return ep;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the address of the value specified by double-bracket indexing
|
||||
* of an association. Returns NULL if there is no such element.
|
||||
*
|
||||
* given:
|
||||
* ap association to index into
|
||||
* index index of desired element
|
||||
*/
|
||||
VALUE *
|
||||
assocfindex(ASSOC *ap, long index)
|
||||
{
|
||||
ASSOCELEM *ep;
|
||||
|
||||
ep = elemindex(ap, index);
|
||||
if (ep == NULL)
|
||||
return NULL;
|
||||
return &ep->e_value;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Compare two associations to see if they are identical.
|
||||
* Returns TRUE if they are different.
|
||||
*/
|
||||
BOOL
|
||||
assoccmp(ASSOC *ap1, ASSOC *ap2)
|
||||
{
|
||||
ASSOCELEM **table1;
|
||||
ASSOCELEM *ep1;
|
||||
ASSOCELEM *ep2;
|
||||
long size1;
|
||||
long size2;
|
||||
QCKHASH hash;
|
||||
long dim;
|
||||
|
||||
if (ap1 == ap2)
|
||||
return FALSE;
|
||||
if (ap1->a_count != ap2->a_count)
|
||||
return TRUE;
|
||||
|
||||
table1 = ap1->a_table;
|
||||
size1 = ap1->a_size;
|
||||
size2 = ap2->a_size;
|
||||
while (size1-- > 0) {
|
||||
for (ep1 = *table1++; ep1; ep1 = ep1->e_next) {
|
||||
hash = ep1->e_hash;
|
||||
dim = ep1->e_dim;
|
||||
for (ep2 = ap2->a_table[hash % size2]; ;
|
||||
ep2 = ep2->e_next)
|
||||
{
|
||||
if (ep2 == NULL)
|
||||
return TRUE;
|
||||
if (ep2->e_hash != hash)
|
||||
continue;
|
||||
if (ep2->e_dim != dim)
|
||||
continue;
|
||||
if (compareindices(ep1->e_indices,
|
||||
ep2->e_indices, dim))
|
||||
break;
|
||||
}
|
||||
if (comparevalue(&ep1->e_value, &ep2->e_value))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Copy an association value.
|
||||
*/
|
||||
ASSOC *
|
||||
assoccopy(ASSOC *oldap)
|
||||
{
|
||||
ASSOC *ap;
|
||||
ASSOCELEM *oldep;
|
||||
ASSOCELEM *ep;
|
||||
ASSOCELEM **listhead;
|
||||
int oldhi;
|
||||
int i;
|
||||
|
||||
ap = assocalloc(oldap->a_count / CHAINLENGTH);
|
||||
ap->a_count = oldap->a_count;
|
||||
|
||||
for (oldhi = 0; oldhi < oldap->a_size; oldhi++) {
|
||||
for (oldep = oldap->a_table[oldhi]; oldep;
|
||||
oldep = oldep->e_next)
|
||||
{
|
||||
ep = (ASSOCELEM *) malloc(ELEMSIZE(oldep->e_dim));
|
||||
if (ep == NULL) {
|
||||
math_error("Cannot allocate association element");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
ep->e_dim = oldep->e_dim;
|
||||
ep->e_hash = oldep->e_hash;
|
||||
ep->e_value.v_type = V_NULL;
|
||||
for (i = 0; i < ep->e_dim; i++)
|
||||
copyvalue(&oldep->e_indices[i], &ep->e_indices[i]);
|
||||
copyvalue(&oldep->e_value, &ep->e_value);
|
||||
listhead = &ap->a_table[ep->e_hash % ap->a_size];
|
||||
ep->e_next = *listhead;
|
||||
*listhead = ep;
|
||||
}
|
||||
}
|
||||
return ap;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Resize the hash table for an association to be the specified size.
|
||||
* This is only actually done if the growth from the previous size is
|
||||
* enough to make this worthwhile.
|
||||
*/
|
||||
static void
|
||||
resize(ASSOC *ap, long newsize)
|
||||
{
|
||||
ASSOCELEM **oldtable;
|
||||
ASSOCELEM **newtable;
|
||||
ASSOCELEM **oldlist;
|
||||
ASSOCELEM **newlist;
|
||||
ASSOCELEM *ep;
|
||||
int i;
|
||||
|
||||
if (newsize < ap->a_size + GROWHASHSIZE)
|
||||
return;
|
||||
|
||||
newsize = (long) next_prime((FULL)newsize);
|
||||
newtable = (ASSOCELEM **) malloc(sizeof(ASSOCELEM *) * newsize);
|
||||
if (newtable == NULL) {
|
||||
math_error("No memory to grow association");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
for (i = 0; i < newsize; i++)
|
||||
newtable[i] = NULL;
|
||||
|
||||
oldtable = ap->a_table;
|
||||
oldlist = oldtable;
|
||||
for (i = 0; i < ap->a_size; i++) {
|
||||
while (*oldlist) {
|
||||
ep = *oldlist;
|
||||
*oldlist = ep->e_next;
|
||||
newlist = &newtable[ep->e_hash % newsize];
|
||||
ep->e_next = *newlist;
|
||||
*newlist = ep;
|
||||
}
|
||||
oldlist++;
|
||||
}
|
||||
|
||||
ap->a_table = newtable;
|
||||
ap->a_size = newsize;
|
||||
free((char *) oldtable);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Free an association element, along with any contained values.
|
||||
*/
|
||||
static void
|
||||
assoc_elemfree(ASSOCELEM *ep)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ep->e_dim; i++)
|
||||
freevalue(&ep->e_indices[i]);
|
||||
freevalue(&ep->e_value);
|
||||
ep->e_dim = 0;
|
||||
ep->e_next = NULL;
|
||||
free((char *) ep);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Allocate a new association value with an initial hash table.
|
||||
* The hash table size is set at specified (but at least a minimum size).
|
||||
*/
|
||||
ASSOC *
|
||||
assocalloc(long initsize)
|
||||
{
|
||||
register ASSOC *ap;
|
||||
int i;
|
||||
|
||||
if (initsize < MINHASHSIZE)
|
||||
initsize = MINHASHSIZE;
|
||||
ap = (ASSOC *) malloc(sizeof(ASSOC));
|
||||
if (ap == NULL) {
|
||||
math_error("No memory for association");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
ap->a_count = 0;
|
||||
ap->a_size = initsize;
|
||||
ap->a_table = (ASSOCELEM **) malloc(sizeof(ASSOCELEM *) * initsize);
|
||||
if (ap->a_table == NULL) {
|
||||
free((char *) ap);
|
||||
math_error("No memory for association");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
for (i = 0; i < initsize; i++)
|
||||
ap->a_table[i] = NULL;
|
||||
return ap;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Free an association value, along with all of its elements.
|
||||
*/
|
||||
void
|
||||
assocfree(ASSOC *ap)
|
||||
{
|
||||
ASSOCELEM **listhead;
|
||||
ASSOCELEM *ep;
|
||||
ASSOCELEM *nextep;
|
||||
int i;
|
||||
|
||||
listhead = ap->a_table;
|
||||
for (i = 0; i < ap->a_size; i++) {
|
||||
nextep = *listhead;
|
||||
*listhead = NULL;
|
||||
while (nextep) {
|
||||
ep = nextep;
|
||||
nextep = ep->e_next;
|
||||
assoc_elemfree(ep);
|
||||
}
|
||||
listhead++;
|
||||
}
|
||||
free((char *) ap->a_table);
|
||||
ap->a_table = NULL;
|
||||
free((char *) ap);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Print out an association along with the specified number of
|
||||
* its elements. The elements are printed out in shortened form.
|
||||
*/
|
||||
void
|
||||
assocprint(ASSOC *ap, long max_print)
|
||||
{
|
||||
ASSOCELEM *ep;
|
||||
long index;
|
||||
long i;
|
||||
int savemode;
|
||||
|
||||
if (max_print <= 0) {
|
||||
math_fmt("assoc (%ld element%s)", ap->a_count,
|
||||
((ap->a_count == 1) ? "" : "s"));
|
||||
return;
|
||||
}
|
||||
math_fmt("\n assoc (%ld element%s):\n", ap->a_count,
|
||||
((ap->a_count == 1) ? "" : "s"));
|
||||
|
||||
for (index = 0; ((index < max_print) && (index < ap->a_count));
|
||||
index++)
|
||||
{
|
||||
ep = elemindex(ap, index);
|
||||
if (ep == NULL)
|
||||
continue;
|
||||
math_str(" [");
|
||||
for (i = 0; i < ep->e_dim; i++) {
|
||||
if (i)
|
||||
math_chr(',');
|
||||
savemode = math_setmode(MODE_FRAC);
|
||||
printvalue(&ep->e_indices[i],
|
||||
(PRINT_SHORT | PRINT_UNAMBIG));
|
||||
math_setmode(savemode);
|
||||
}
|
||||
math_str("] = ");
|
||||
printvalue(&ep->e_value, PRINT_SHORT | PRINT_UNAMBIG);
|
||||
math_chr('\n');
|
||||
}
|
||||
if (max_print < ap->a_count)
|
||||
math_str(" ...\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Compare two lists of index values to see if they are identical.
|
||||
* Returns TRUE if they are the same.
|
||||
*/
|
||||
static BOOL
|
||||
compareindices(VALUE *v1, VALUE *v2, long dim)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dim; i++)
|
||||
if (v1[i].v_type != v2[i].v_type)
|
||||
return FALSE;
|
||||
|
||||
while (dim-- > 0)
|
||||
if (comparevalue(v1++, v2++))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* END CODE */
|
686
byteswap.c
Normal file
686
byteswap.c
Normal file
@@ -0,0 +1,686 @@
|
||||
/*
|
||||
* Copyright (c) 1995 by Landon Curt Noll. All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright, this permission notice and text
|
||||
* this comment, and the disclaimer below appear in all of the following:
|
||||
*
|
||||
* supporting documentation
|
||||
* source copies
|
||||
* source works derived from this source
|
||||
* binaries derived from this source or from derived source
|
||||
*
|
||||
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
||||
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "cmath.h"
|
||||
#include "byteswap.h"
|
||||
|
||||
|
||||
/*
|
||||
* swap_b8_in_HALFs - swap 8 and if needed, 16 bits in an array of HALFs
|
||||
*
|
||||
* given:
|
||||
* dest - pointer to where the swapped src wil be put or
|
||||
* NULL to allocate the storage
|
||||
* src - pointer to a HALF array to swap
|
||||
* len - length of the src HALF array
|
||||
*
|
||||
* returns:
|
||||
* pointer to where the swapped src has been put
|
||||
*/
|
||||
HALF *
|
||||
swap_b8_in_HALFs(HALF *dest, HALF *src, LEN len)
|
||||
{
|
||||
LEN i;
|
||||
|
||||
/*
|
||||
* allocate storage if needed
|
||||
*/
|
||||
if (dest == NULL) {
|
||||
dest = alloc(len);
|
||||
}
|
||||
|
||||
/*
|
||||
* swap the array
|
||||
*/
|
||||
for (i=0; i < len; ++i, ++dest, ++src) {
|
||||
SWAP_B8_IN_HALF(dest, src);
|
||||
}
|
||||
|
||||
/*
|
||||
* return the result
|
||||
*/
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* swap_b8_in_ZVALUE - swap 8 and if needed, 16 bits in a ZVALUE
|
||||
*
|
||||
* given:
|
||||
* dest - pointer to where the swapped src wil be put or
|
||||
* NULL to allocate the storage
|
||||
* src - pointer to a ZVALUE to swap
|
||||
* all - TRUE => swap every element, FALSE => swap only the
|
||||
* multiprecision storage
|
||||
*
|
||||
* returns:
|
||||
* pointer to where the swapped src has been put
|
||||
*
|
||||
* This macro will either switch to the opposite byte sex (Big Endian vs.
|
||||
* Little Endian) the elements of a ZVALUE.
|
||||
*/
|
||||
ZVALUE *
|
||||
swap_b8_in_ZVALUE(ZVALUE *dest, ZVALUE *src, BOOL all)
|
||||
{
|
||||
/*
|
||||
* allocate storage if needed
|
||||
*/
|
||||
if (dest == NULL) {
|
||||
|
||||
/*
|
||||
* allocate the storage
|
||||
*/
|
||||
dest = malloc(sizeof(ZVALUE));
|
||||
if (dest == NULL) {
|
||||
math_error("swap_b8_in_ZVALUE: swap_b8_in_ZVALUE: Not enough memory");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate (by forcing swap_b8_in_ZVALUE) and swap storage
|
||||
*/
|
||||
dest->v = swap_b8_in_HALFs(NULL, src->v, src->len);
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* swap storage
|
||||
*/
|
||||
if (dest->v != NULL) {
|
||||
zfree(*dest);
|
||||
}
|
||||
dest->v = swap_b8_in_HALFs(NULL, src->v, src->len);
|
||||
}
|
||||
|
||||
/*
|
||||
* swap or copy the rest of the ZVALUE elements
|
||||
*/
|
||||
if (all) {
|
||||
dest->len = (LEN)SWAP_B8_IN_LEN(&dest->len, &src->len);
|
||||
dest->sign = (BOOL)SWAP_B8_IN_BOOL(&dest->sign, &src->sign);
|
||||
} else {
|
||||
dest->len = src->len;
|
||||
dest->sign = src->sign;
|
||||
}
|
||||
|
||||
/*
|
||||
* return the result
|
||||
*/
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* swap_b8_in_NUMBER - swap 8 and if needed, 16 bits in a NUMBER
|
||||
*
|
||||
* given:
|
||||
* dest - pointer to where the swapped src wil be put or
|
||||
* NULL to allocate the storage
|
||||
* src - pointer to a NUMBER to swap
|
||||
* all - TRUE => swap every element, FALSE => swap only the
|
||||
* multiprecision storage
|
||||
*
|
||||
* returns:
|
||||
* pointer to where the swapped src has been put
|
||||
*
|
||||
* This macro will either switch to the opposite byte sex (Big Endian vs.
|
||||
* Little Endian) the elements of a NUMBER.
|
||||
*/
|
||||
NUMBER *
|
||||
swap_b8_in_NUMBER(NUMBER *dest, NUMBER *src, BOOL all)
|
||||
{
|
||||
/*
|
||||
* allocate storage if needed
|
||||
*/
|
||||
if (dest == NULL) {
|
||||
|
||||
/*
|
||||
* allocate the storage
|
||||
*/
|
||||
dest = malloc(sizeof(NUMBER));
|
||||
if (dest == NULL) {
|
||||
math_error("swap_b8_in_NUMBER: Not enough memory");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate (by forcing swap_b8_in_ZVALUE) and swap storage
|
||||
*/
|
||||
dest->num = *swap_b8_in_ZVALUE(NULL, &src->num, all);
|
||||
dest->den = *swap_b8_in_ZVALUE(NULL, &src->den, all);
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* swap storage
|
||||
*/
|
||||
dest->num = *swap_b8_in_ZVALUE(&dest->num, &src->num, all);
|
||||
dest->den = *swap_b8_in_ZVALUE(&dest->den, &src->den, all);
|
||||
}
|
||||
|
||||
/*
|
||||
* swap or copy the rest of the NUMBER elements
|
||||
*/
|
||||
if (all) {
|
||||
dest->links = (long)SWAP_B8_IN_LONG(&dest->links, &src->links);
|
||||
} else {
|
||||
dest->links = src->links;
|
||||
}
|
||||
|
||||
/*
|
||||
* return the result
|
||||
*/
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* swap_b8_in_COMPLEX - swap 8 and if needed, 16 bits in a COMPLEX
|
||||
*
|
||||
* given:
|
||||
* dest - pointer to where the swapped src wil be put or
|
||||
* NULL to allocate the storage
|
||||
* src - pointer to a COMPLEX to swap
|
||||
* all - TRUE => swap every element, FALSE => swap only the
|
||||
* multiprecision storage
|
||||
*
|
||||
* returns:
|
||||
* pointer to where the swapped src has been put
|
||||
*
|
||||
* This macro will either switch to the opposite byte sex (Big Endian vs.
|
||||
* Little Endian) the elements of a COMPLEX.
|
||||
*/
|
||||
COMPLEX *
|
||||
swap_b8_in_COMPLEX(COMPLEX *dest, COMPLEX *src, BOOL all)
|
||||
{
|
||||
/*
|
||||
* allocate storage if needed
|
||||
*/
|
||||
if (dest == NULL) {
|
||||
|
||||
/*
|
||||
* allocate the storage
|
||||
*/
|
||||
dest = malloc(sizeof(COMPLEX));
|
||||
if (dest == NULL) {
|
||||
math_error("swap_b8_in_COMPLEX: Not enough memory");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate (by forcing swap_b8_in_ZVALUE) and swap storage
|
||||
*/
|
||||
dest->real = swap_b8_in_NUMBER(NULL, src->real, all);
|
||||
dest->imag = swap_b8_in_NUMBER(NULL, src->imag, all);
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* swap storage
|
||||
*/
|
||||
dest->real = swap_b8_in_NUMBER(dest->real, src->real, all);
|
||||
dest->imag = swap_b8_in_NUMBER(dest->imag, src->imag, all);
|
||||
}
|
||||
|
||||
/*
|
||||
* swap or copy the rest of the NUMBER elements
|
||||
*/
|
||||
if (all) {
|
||||
dest->links = (long)SWAP_B8_IN_LONG(&dest->links, &src->links);
|
||||
} else {
|
||||
dest->links = src->links;
|
||||
}
|
||||
|
||||
/*
|
||||
* return the result
|
||||
*/
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* swap_b16_in_HALFs - swap 16 bits in an array of HALFs
|
||||
*
|
||||
* given:
|
||||
* dest - pointer to where the swapped src wil be put or
|
||||
* NULL to allocate the storage
|
||||
* src - pointer to a HALF array to swap
|
||||
* len - length of the src HALF array
|
||||
*
|
||||
* returns:
|
||||
* pointer to where the swapped src has been put
|
||||
*/
|
||||
HALF *
|
||||
swap_b16_in_HALFs(HALF *dest, HALF *src, LEN len)
|
||||
{
|
||||
LEN i;
|
||||
|
||||
/*
|
||||
* allocate storage if needed
|
||||
*/
|
||||
if (dest == NULL) {
|
||||
dest = alloc(len);
|
||||
}
|
||||
|
||||
/*
|
||||
* swap the array
|
||||
*/
|
||||
for (i=0; i < len; ++i, ++dest, ++src) {
|
||||
SWAP_B16_IN_HALF(dest, src);
|
||||
}
|
||||
|
||||
/*
|
||||
* return the result
|
||||
*/
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* swap_b16_in_ZVALUE - swap 16 bits in a ZVALUE
|
||||
*
|
||||
* given:
|
||||
* dest - pointer to where the swapped src wil be put or
|
||||
* NULL to allocate the storage
|
||||
* src - pointer to a ZVALUE to swap
|
||||
* all - TRUE => swap every element, FALSE => swap only the
|
||||
* multiprecision storage
|
||||
*
|
||||
* returns:
|
||||
* pointer to where the swapped src has been put
|
||||
*
|
||||
* This macro will either switch to the opposite byte sex (Big Endian vs.
|
||||
* Little Endian) the elements of a ZVALUE.
|
||||
*/
|
||||
ZVALUE *
|
||||
swap_b16_in_ZVALUE(ZVALUE *dest, ZVALUE *src, BOOL all)
|
||||
{
|
||||
/*
|
||||
* allocate storage if needed
|
||||
*/
|
||||
if (dest == NULL) {
|
||||
|
||||
/*
|
||||
* allocate the storage
|
||||
*/
|
||||
dest = malloc(sizeof(ZVALUE));
|
||||
if (dest == NULL) {
|
||||
math_error("swap_b16_in_ZVALUE: Not enough memory");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate (by forcing swap_b16_in_ZVALUE) and swap storage
|
||||
*/
|
||||
dest->v = swap_b16_in_HALFs(NULL, src->v, src->len);
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* swap storage
|
||||
*/
|
||||
if (dest->v != NULL) {
|
||||
zfree(*dest);
|
||||
}
|
||||
dest->v = swap_b16_in_HALFs(NULL, src->v, src->len);
|
||||
}
|
||||
|
||||
/*
|
||||
* swap or copy the rest of the ZVALUE elements
|
||||
*/
|
||||
if (all) {
|
||||
dest->len = (LEN)SWAP_B16_IN_LEN(&dest->len, &src->len);
|
||||
dest->sign = (BOOL)SWAP_B16_IN_BOOL(&dest->sign, &src->sign);
|
||||
} else {
|
||||
dest->len = src->len;
|
||||
dest->sign = src->sign;
|
||||
}
|
||||
|
||||
/*
|
||||
* return the result
|
||||
*/
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* swap_b16_in_NUMBER - swap 16 bits in a NUMBER
|
||||
*
|
||||
* given:
|
||||
* dest - pointer to where the swapped src wil be put or
|
||||
* NULL to allocate the storage
|
||||
* src - pointer to a NUMBER to swap
|
||||
* all - TRUE => swap every element, FALSE => swap only the
|
||||
* multiprecision storage
|
||||
*
|
||||
* returns:
|
||||
* pointer to where the swapped src has been put
|
||||
*
|
||||
* This macro will either switch to the opposite byte sex (Big Endian vs.
|
||||
* Little Endian) the elements of a NUMBER.
|
||||
*/
|
||||
NUMBER *
|
||||
swap_b16_in_NUMBER(NUMBER *dest, NUMBER *src, BOOL all)
|
||||
{
|
||||
/*
|
||||
* allocate storage if needed
|
||||
*/
|
||||
if (dest == NULL) {
|
||||
|
||||
/*
|
||||
* allocate the storage
|
||||
*/
|
||||
dest = malloc(sizeof(NUMBER));
|
||||
if (dest == NULL) {
|
||||
math_error("swap_b16_in_NUMBER: Not enough memory");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate (by forcing swap_b16_in_ZVALUE) and swap storage
|
||||
*/
|
||||
dest->num = *swap_b16_in_ZVALUE(NULL, &src->num, all);
|
||||
dest->den = *swap_b16_in_ZVALUE(NULL, &src->den, all);
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* swap storage
|
||||
*/
|
||||
dest->num = *swap_b16_in_ZVALUE(&dest->num, &src->num, all);
|
||||
dest->den = *swap_b16_in_ZVALUE(&dest->den, &src->den, all);
|
||||
}
|
||||
|
||||
/*
|
||||
* swap or copy the rest of the NUMBER elements
|
||||
*/
|
||||
if (all) {
|
||||
dest->links = (long)SWAP_B16_IN_LONG(&dest->links, &src->links);
|
||||
} else {
|
||||
dest->links = src->links;
|
||||
}
|
||||
|
||||
/*
|
||||
* return the result
|
||||
*/
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* swap_b16_in_COMPLEX - swap 16 bits in a COMPLEX
|
||||
*
|
||||
* given:
|
||||
* dest - pointer to where the swapped src wil be put or
|
||||
* NULL to allocate the storage
|
||||
* src - pointer to a COMPLEX to swap
|
||||
* all - TRUE => swap every element, FALSE => swap only the
|
||||
* multiprecision storage
|
||||
*
|
||||
* returns:
|
||||
* pointer to where the swapped src has been put
|
||||
*
|
||||
* This macro will either switch to the opposite byte sex (Big Endian vs.
|
||||
* Little Endian) the elements of a COMPLEX.
|
||||
*/
|
||||
COMPLEX *
|
||||
swap_b16_in_COMPLEX(COMPLEX *dest, COMPLEX *src, BOOL all)
|
||||
{
|
||||
/*
|
||||
* allocate storage if needed
|
||||
*/
|
||||
if (dest == NULL) {
|
||||
|
||||
/*
|
||||
* allocate the storage
|
||||
*/
|
||||
dest = malloc(sizeof(COMPLEX));
|
||||
if (dest == NULL) {
|
||||
math_error("swap_b16_in_COMPLEX: Not enough memory");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate (by forcing swap_b16_in_ZVALUE) and swap storage
|
||||
*/
|
||||
dest->real = swap_b16_in_NUMBER(NULL, src->real, all);
|
||||
dest->imag = swap_b16_in_NUMBER(NULL, src->imag, all);
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* swap storage
|
||||
*/
|
||||
dest->real = swap_b16_in_NUMBER(dest->real, src->real, all);
|
||||
dest->imag = swap_b16_in_NUMBER(dest->imag, src->imag, all);
|
||||
}
|
||||
|
||||
/*
|
||||
* swap or copy the rest of the NUMBER elements
|
||||
*/
|
||||
if (all) {
|
||||
dest->links = (long)SWAP_B16_IN_LONG(&dest->links, &src->links);
|
||||
} else {
|
||||
dest->links = src->links;
|
||||
}
|
||||
|
||||
/*
|
||||
* return the result
|
||||
*/
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* swap_HALF_in_ZVALUE - swap HALFs in a ZVALUE
|
||||
*
|
||||
* given:
|
||||
* dest - pointer to where the swapped src wil be put or
|
||||
* NULL to allocate the storage
|
||||
* src - pointer to a ZVALUE to swap
|
||||
* all - TRUE => swap every element, FALSE => swap only the
|
||||
* multiprecision storage
|
||||
*
|
||||
* returns:
|
||||
* pointer to where the swapped src has been put
|
||||
*
|
||||
* This macro will either switch to the opposite byte sex (Big Endian vs.
|
||||
* Little Endian) the elements of a ZVALUE.
|
||||
*/
|
||||
ZVALUE *
|
||||
swap_HALF_in_ZVALUE(ZVALUE *dest, ZVALUE *src, BOOL all)
|
||||
{
|
||||
/*
|
||||
* allocate storage if needed
|
||||
*/
|
||||
if (dest == NULL) {
|
||||
|
||||
/*
|
||||
* allocate the storage
|
||||
*/
|
||||
dest = malloc(sizeof(ZVALUE));
|
||||
if (dest == NULL) {
|
||||
math_error("swap_HALF_in_ZVALUE: Not enough memory");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* copy storage because we are dealing with HALFs
|
||||
*/
|
||||
dest->v = (HALF *) zcopyval(*src, *dest);
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* copy storage because we are dealing with HALFs
|
||||
*/
|
||||
if (dest->v != NULL) {
|
||||
zfree(*dest);
|
||||
dest->v = alloc(src->len);
|
||||
}
|
||||
zcopyval(*src, *dest);
|
||||
}
|
||||
|
||||
/*
|
||||
* swap or copy the rest of the ZVALUE elements
|
||||
*/
|
||||
if (all) {
|
||||
dest->len = (LEN)SWAP_HALF_IN_LEN(&dest->len, &src->len);
|
||||
dest->sign = (BOOL)SWAP_HALF_IN_BOOL(&dest->sign, &src->sign);
|
||||
} else {
|
||||
dest->len = src->len;
|
||||
dest->sign = src->sign;
|
||||
}
|
||||
|
||||
/*
|
||||
* return the result
|
||||
*/
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* swap_HALF_in_NUMBER - swap HALFs in a NUMBER
|
||||
*
|
||||
* given:
|
||||
* dest - pointer to where the swapped src wil be put or
|
||||
* NULL to allocate the storage
|
||||
* src - pointer to a NUMBER to swap
|
||||
* all - TRUE => swap every element, FALSE => swap only the
|
||||
* multiprecision storage
|
||||
*
|
||||
* returns:
|
||||
* pointer to where the swapped src has been put
|
||||
*
|
||||
* This macro will either switch to the opposite byte sex (Big Endian vs.
|
||||
* Little Endian) the elements of a NUMBER.
|
||||
*/
|
||||
NUMBER *
|
||||
swap_HALF_in_NUMBER(NUMBER *dest, NUMBER *src, BOOL all)
|
||||
{
|
||||
/*
|
||||
* allocate storage if needed
|
||||
*/
|
||||
if (dest == NULL) {
|
||||
|
||||
/*
|
||||
* allocate the storage
|
||||
*/
|
||||
dest = malloc(sizeof(NUMBER));
|
||||
if (dest == NULL) {
|
||||
math_error("swap_HALF_in_NUMBER: Not enough memory");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate (by forcing swap_HALF_in_ZVALUE) and swap storage
|
||||
*/
|
||||
dest->num = *swap_HALF_in_ZVALUE(NULL, &src->num, all);
|
||||
dest->den = *swap_HALF_in_ZVALUE(NULL, &src->den, all);
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* swap storage
|
||||
*/
|
||||
dest->num = *swap_HALF_in_ZVALUE(&dest->num, &src->num, all);
|
||||
dest->den = *swap_HALF_in_ZVALUE(&dest->den, &src->den, all);
|
||||
}
|
||||
|
||||
/*
|
||||
* swap or copy the rest of the NUMBER elements
|
||||
*/
|
||||
if (all) {
|
||||
dest->links = (long)SWAP_HALF_IN_LONG(&dest->links,&src->links);
|
||||
} else {
|
||||
dest->links = src->links;
|
||||
}
|
||||
|
||||
/*
|
||||
* return the result
|
||||
*/
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* swap_HALF_in_COMPLEX - swap HALFs in a COMPLEX
|
||||
*
|
||||
* given:
|
||||
* dest - pointer to where the swapped src wil be put or
|
||||
* NULL to allocate the storage
|
||||
* src - pointer to a COMPLEX to swap
|
||||
* all - TRUE => swap every element, FALSE => swap only the
|
||||
* multiprecision storage
|
||||
*
|
||||
* returns:
|
||||
* pointer to where the swapped src has been put
|
||||
*
|
||||
* This macro will either switch to the opposite byte sex (Big Endian vs.
|
||||
* Little Endian) the elements of a COMPLEX.
|
||||
*/
|
||||
COMPLEX *
|
||||
swap_HALF_in_COMPLEX(COMPLEX *dest, COMPLEX *src, BOOL all)
|
||||
{
|
||||
/*
|
||||
* allocate storage if needed
|
||||
*/
|
||||
if (dest == NULL) {
|
||||
|
||||
/*
|
||||
* allocate the storage
|
||||
*/
|
||||
dest = malloc(sizeof(COMPLEX));
|
||||
if (dest == NULL) {
|
||||
math_error("swap_HALF_in_COMPLEX: Not enough memory");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate (by forcing swap_HALF_in_ZVALUE) and swap storage
|
||||
*/
|
||||
dest->real = swap_HALF_in_NUMBER(NULL, src->real, all);
|
||||
dest->imag = swap_HALF_in_NUMBER(NULL, src->imag, all);
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* swap storage
|
||||
*/
|
||||
dest->real = swap_HALF_in_NUMBER(dest->real, src->real, all);
|
||||
dest->imag = swap_HALF_in_NUMBER(dest->imag, src->imag, all);
|
||||
}
|
||||
|
||||
/*
|
||||
* swap or copy the rest of the NUMBER elements
|
||||
*/
|
||||
if (all) {
|
||||
dest->links = (long)SWAP_HALF_IN_LONG(&dest->links,&src->links);
|
||||
} else {
|
||||
dest->links = src->links;
|
||||
}
|
||||
|
||||
/*
|
||||
* return the result
|
||||
*/
|
||||
return dest;
|
||||
}
|
166
byteswap.h
Normal file
166
byteswap.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (c) 1995 by Landon Curt Noll. All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright, this permission notice and text
|
||||
* this comment, and the disclaimer below appear in all of the following:
|
||||
*
|
||||
* supporting documentation
|
||||
* source copies
|
||||
* source works derived from this source
|
||||
* binaries derived from this source or from derived source
|
||||
*
|
||||
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
||||
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(BYTESWAP_H)
|
||||
#define BYTESWAP_H
|
||||
|
||||
#include "longbits.h"
|
||||
|
||||
|
||||
/*
|
||||
* SWAP_B8_IN_B16 - swap 8 bits in 16 bits
|
||||
*
|
||||
* dest - pointer to where the swapped src wil be put
|
||||
* src - pointer to a 16 bit value to swap
|
||||
*
|
||||
* This macro will either switch to the opposite byte sex (Big Endian vs.
|
||||
* Little Endian) a 16 bit value.
|
||||
*/
|
||||
#define SWAP_B8_IN_B16(dest, src) ( \
|
||||
*((USB16*)(dest)) = \
|
||||
(((*((USB16*)(src))) << 8) | ((*((USB16*)(src))) >> 8)) \
|
||||
)
|
||||
|
||||
/*
|
||||
* SWAP_B16_IN_B32 - swap 16 bits in 32 bits
|
||||
*
|
||||
* dest - pointer to where the swapped src wil be put
|
||||
* src - pointer to a 32 bit value to swap
|
||||
*/
|
||||
#define SWAP_B16_IN_B32(dest, src) ( \
|
||||
*((USB32*)(dest)) = \
|
||||
(((*((USB32*)(src))) << 16) | ((*((USB32*)(src))) >> 16)) \
|
||||
)
|
||||
|
||||
/*
|
||||
* SWAP_B8_IN_B32 - swap 8 & 16 bits in 32 bits
|
||||
*
|
||||
* dest - pointer to where the swapped src wil be put
|
||||
* src - pointer to a 32 bit value to swap
|
||||
*
|
||||
* This macro will either switch to the opposite byte sex (Big Endian vs.
|
||||
* Little Endian) a 32 bit value.
|
||||
*/
|
||||
#define SWAP_B8_IN_B32(dest, src) ( \
|
||||
SWAP_B16_IN_B32(dest, src), \
|
||||
(*((USB32*)(dest)) = \
|
||||
((((*((USB32*)(dest))) & (USB32)0xff00ff00) >> 8) | \
|
||||
(((*((USB32*)(dest))) & (USB32)0x00ff00ff) << 8))) \
|
||||
)
|
||||
|
||||
#if defined(HAVE_B64)
|
||||
|
||||
/*
|
||||
* SWAP_B32_IN_B64 - swap 32 bits in 64 bits
|
||||
*
|
||||
* dest - pointer to where the swapped src wil be put
|
||||
* src - pointer to a 64 bit value to swap
|
||||
*/
|
||||
#define SWAP_B32_IN_B64(dest, src) ( \
|
||||
*((USB64*)(dest)) = \
|
||||
(((*((USB64*)(src))) << 32) | ((*((USB64*)(src))) >> 32)) \
|
||||
)
|
||||
|
||||
/*
|
||||
* SWAP_B16_IN_B64 - swap 16 & 32 bits in 64 bits
|
||||
*
|
||||
* dest - pointer to where the swapped src wil be put
|
||||
* src - pointer to a 64 bit value to swap
|
||||
*/
|
||||
#define SWAP_B16_IN_B64(dest, src) ( \
|
||||
SWAP_B32_IN_B64(dest, src), \
|
||||
(*((USB64*)(dest)) = \
|
||||
((((*((USB64*)(dest))) & (USB64)0xffff0000ffff0000) >> 16) | \
|
||||
(((*((USB64*)(dest))) & (USB64)0x0000ffff0000ffff) << 16))) \
|
||||
)
|
||||
|
||||
/*
|
||||
* SWAP_B8_IN_B64 - swap 16 & 32 bits in 64 bits
|
||||
*
|
||||
* dest - pointer to where the swapped src wil be put
|
||||
* src - pointer to a 64 bit value to swap
|
||||
*
|
||||
* This macro will either switch to the opposite byte sex (Big Endian vs.
|
||||
* Little Endian) a 64 bit value.
|
||||
*/
|
||||
#define SWAP_B8_IN_B64(dest, src) ( \
|
||||
SWAP_B16_IN_B64(dest, src), \
|
||||
(*((USB64*)(dest)) = \
|
||||
((((*((USB64*)(dest))) & (USB64)0xff00ff00ff00ff00) >> 8) | \
|
||||
(((*((USB64*)(dest))) & (USB64)0x00ff00ff00ff00ff) << 8))) \
|
||||
)
|
||||
|
||||
#else /* HAVE_B64 */
|
||||
|
||||
/*
|
||||
* SWAP_B32_IN_B64 - swap 32 bits in 64 bits (simulated by 2 32 bit values)
|
||||
*
|
||||
* dest - pointer to where the swapped src wil be put
|
||||
* src - pointer to a 64 bit value to swap
|
||||
*/
|
||||
#define SWAP_B32_IN_B64(dest, src) ( \
|
||||
((USB32*)(dest))[1] = ((USB32*)(dest))[0], \
|
||||
((USB32*)(dest))[0] = ((USB32*)(dest))[1] \
|
||||
)
|
||||
|
||||
/*
|
||||
* SWAP_B16_IN_B64 - swap 16 & 32 bits in 64 bits (simulated by 2 32 bit vals)
|
||||
*
|
||||
* dest - pointer to where the swapped src wil be put
|
||||
* src - pointer to a 64 bit value to swap
|
||||
*/
|
||||
#define SWAP_B16_IN_B64(dest, src) ( \
|
||||
SWAP_B16_IN_B32(((USB32*)dest)+1, ((USB32*)src)), \
|
||||
SWAP_B16_IN_B32(((USB32*)dest), ((USB32*)src)+1) \
|
||||
)
|
||||
|
||||
/*
|
||||
* SWAP_B8_IN_B64 - swap 16 & 32 bits in 64 bits (simulated by 2 32 bit vals)
|
||||
*
|
||||
* dest - pointer to where the swapped src wil be put
|
||||
* src - pointer to a 64 bit value to swap
|
||||
*
|
||||
* This macro will either switch to the opposite byte sex (Big Endian vs.
|
||||
* Little Endian) a 64 bit value.
|
||||
*/
|
||||
#define SWAP_B8_IN_B64(dest, src) ( \
|
||||
SWAP_B8_IN_B32(((USB32*)dest)+1, ((USB32*)src)), \
|
||||
SWAP_B8_IN_B32(((USB32*)dest), ((USB32*)src)+1) \
|
||||
)
|
||||
|
||||
#endif /* HAVE_B64 */
|
||||
|
||||
#if LONG_BITS == 64
|
||||
|
||||
#define SWAP_B32_IN_LONG(dest, src) SWAP_B32_IN_B64(dest, src)
|
||||
#define SWAP_B16_IN_LONG(dest, src) SWAP_B16_IN_B64(dest, src)
|
||||
#define SWAP_B8_IN_LONG(dest, src) SWAP_B8_IN_B64(dest, src)
|
||||
|
||||
#else /* LONG_BITS == 64 */
|
||||
|
||||
#define SWAP_B32_IN_LONG(dest, src) SWAP_B32_IN_B32(dest, src)
|
||||
#define SWAP_B16_IN_LONG(dest, src) SWAP_B16_IN_B32(dest, src)
|
||||
#define SWAP_B8_IN_LONG(dest, src) SWAP_B8_IN_B32(dest, src)
|
||||
|
||||
#endif /* LONG_BITS == 64 */
|
||||
|
||||
#endif /* !BYTESWAP_H */
|
441
calc.c
Normal file
441
calc.c
Normal file
@@ -0,0 +1,441 @@
|
||||
/*
|
||||
* Copyright (c) 1995 David I. Bell
|
||||
* Permission is granted to use, distribute, or modify this source,
|
||||
* provided that this copyright notice remains intact.
|
||||
*
|
||||
* Arbitrary precision calculator.
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define CALC_C
|
||||
#include "calc.h"
|
||||
#include "hist.h"
|
||||
#include "func.h"
|
||||
#include "opcodes.h"
|
||||
#include "conf.h"
|
||||
#include "token.h"
|
||||
#include "symbol.h"
|
||||
#include "have_uid_t.h"
|
||||
|
||||
#include "have_unistd.h"
|
||||
#if defined(HAVE_UNISTD_H)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "have_stdlib.h"
|
||||
#if defined(HAVE_STDLIB_H)
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* in case we do not have certain .h files
|
||||
*/
|
||||
#if !defined(HAVE_STDLIB_H) && !defined(HAVE_UNISTD_H)
|
||||
#if !defined(HAVE_UID_T) && !defined(_UID_T)
|
||||
typedef unsigned short uid_t;
|
||||
#endif
|
||||
extern char *getenv();
|
||||
extern uid_t geteuid();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Common definitions
|
||||
*/
|
||||
int abortlevel; /* current level of aborts */
|
||||
BOOL inputwait; /* TRUE if in a terminal input wait */
|
||||
jmp_buf jmpbuf; /* for errors */
|
||||
int start_done = FALSE; /* TRUE => start up processing finished */
|
||||
|
||||
extern int isatty(int tty); /* TRUE if fd is a tty */
|
||||
|
||||
static int p_flag = FALSE; /* TRUE => pipe mode */
|
||||
static int q_flag = FALSE; /* TRUE => don't execute rc files */
|
||||
static int u_flag = FALSE; /* TRUE => unbuffer stdin and stdout */
|
||||
|
||||
/*
|
||||
* global permissions
|
||||
*/
|
||||
int allow_read = TRUE; /* FALSE => may not open any files for reading */
|
||||
int allow_write = TRUE; /* FALSE => may not open any files for writing */
|
||||
int allow_exec = TRUE; /* FALSE => may not execute any commands */
|
||||
|
||||
char *calcpath; /* $CALCPATH or default */
|
||||
char *calcrc; /* $CALCRC or default */
|
||||
char *calcbindings; /* $CALCBINDINGS or default */
|
||||
char *home; /* $HOME or default */
|
||||
static char *pager; /* $PAGER or default */
|
||||
char *shell; /* $SHELL or default */
|
||||
int stdin_tty = TRUE; /* TRUE if stdin is a tty */
|
||||
int post_init = FALSE; /* TRUE setjmp for math_error is readready */
|
||||
|
||||
/*
|
||||
* some help topics are symbols, so we alias them to nice filenames
|
||||
*/
|
||||
static struct help_alias {
|
||||
char *topic;
|
||||
char *filename;
|
||||
} halias[] = {
|
||||
{"=", "assign"},
|
||||
{"%", "mod"},
|
||||
{"//", "quo"},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
NUMBER *epsilon_default; /* default allowed error for float calcs */
|
||||
|
||||
static void intint(int arg); /* interrupt routine */
|
||||
static void initenv(void); /* initialize environment vars */
|
||||
|
||||
extern void file_init(void);
|
||||
extern void zio_init(void);
|
||||
|
||||
char cmdbuf[MAXCMD+1]; /* command line expression */
|
||||
|
||||
/*
|
||||
* Top level calculator routine.
|
||||
*/
|
||||
MAIN
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
static char *str; /* current option string or expression */
|
||||
int want_defhelp = 0; /* 1=> we only want the default help */
|
||||
long i;
|
||||
char *p;
|
||||
|
||||
/*
|
||||
* parse args
|
||||
*/
|
||||
argc--;
|
||||
argv++;
|
||||
while ((argc > 0) && (**argv == '-')) {
|
||||
for (str = &argv[0][1]; *str; str++) switch (*str) {
|
||||
case 'h':
|
||||
want_defhelp = 1;
|
||||
break;
|
||||
case 'm':
|
||||
if (argv[0][2]) {
|
||||
p = &argv[0][2];
|
||||
} else if (argc > 1) {
|
||||
p = argv[1];
|
||||
argc--;
|
||||
argv++;
|
||||
} else {
|
||||
fprintf(stderr, "-m requires an arg\n");
|
||||
exit(1);
|
||||
}
|
||||
if (p[1] != '\0' || *p < '0' || *p > '7') {
|
||||
fprintf(stderr, "unknown -m arg\n");
|
||||
exit(1);
|
||||
}
|
||||
allow_read = (((*p-'0') & 04) > 0);
|
||||
allow_write = (((*p-'0') & 02) > 0);
|
||||
allow_exec = (((*p-'0') & 01) > 0);
|
||||
break;
|
||||
case 'p':
|
||||
p_flag = TRUE;
|
||||
break;
|
||||
case 'q':
|
||||
q_flag = TRUE;
|
||||
break;
|
||||
case 'u':
|
||||
u_flag = TRUE;
|
||||
break;
|
||||
case 'v':
|
||||
version(stdout);
|
||||
exit(0);
|
||||
default:
|
||||
fprintf(stderr, "Unknown option\n");
|
||||
exit(1);
|
||||
}
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
str = cmdbuf;
|
||||
*str = '\0';
|
||||
while (--argc >= 0) {
|
||||
i = (long)strlen(*argv);
|
||||
if (str+1+i+2 >= cmdbuf+MAXCMD) {
|
||||
fprintf(stderr, "command in arg list too long\n");
|
||||
exit(1);
|
||||
}
|
||||
*str++ = ' ';
|
||||
strcpy(str, *argv++);
|
||||
str += i;
|
||||
str[0] = '\n';
|
||||
str[1] = '\0';
|
||||
}
|
||||
str = cmdbuf;
|
||||
|
||||
/*
|
||||
* unbuffered mode
|
||||
*/
|
||||
if (u_flag) {
|
||||
setbuf(stdin, NULL);
|
||||
setbuf(stdout, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* initialize
|
||||
*/
|
||||
libcalc_call_me_first();
|
||||
hash_init();
|
||||
file_init();
|
||||
initenv();
|
||||
resetinput();
|
||||
if (want_defhelp) {
|
||||
givehelp(DEFAULTCALCHELP);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* if allowed or needed, print version and setup bindings
|
||||
*/
|
||||
if (*str == '\0') {
|
||||
/*
|
||||
* check for pipe mode and/or non-tty stdin
|
||||
*/
|
||||
if (p_flag) {
|
||||
stdin_tty = FALSE; /* stdin not a tty in pipe mode */
|
||||
conf->tab_ok = FALSE; /* config("tab",0) if pipe mode */
|
||||
} else {
|
||||
stdin_tty = isatty(0); /* assume stdin is on fd 0 */
|
||||
}
|
||||
|
||||
/*
|
||||
* empty string arg is no string
|
||||
*/
|
||||
str = NULL;
|
||||
|
||||
/*
|
||||
* if tty, setup bindings
|
||||
*/
|
||||
if (stdin_tty) {
|
||||
version(stdout);
|
||||
printf("[%s]\n\n",
|
||||
"Type \"exit\" to exit, or \"help\" for help.");
|
||||
}
|
||||
if (stdin_tty) {
|
||||
switch (hist_init(calcbindings)) {
|
||||
case HIST_NOFILE:
|
||||
fprintf(stderr,
|
||||
"Cannot open bindings file \"%s\", %s.\n",
|
||||
calcbindings, "fancy editing disabled");
|
||||
break;
|
||||
|
||||
case HIST_NOTTY:
|
||||
fprintf(stderr,
|
||||
"Cannot set terminal modes, %s.\n",
|
||||
"fancy editing disabled");
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
/*
|
||||
* process args, not stdin
|
||||
*/
|
||||
stdin_tty = FALSE; /* stdin not a tty in arg mode */
|
||||
conf->tab_ok = FALSE; /* config("tab",0) if pipe mode */
|
||||
}
|
||||
|
||||
/*
|
||||
* establish error longjump point with initial conditions
|
||||
*/
|
||||
if (setjmp(jmpbuf) == 0) {
|
||||
|
||||
/*
|
||||
* reset/initialize the computing environment
|
||||
*/
|
||||
post_init = TRUE; /* jmpbuf is ready for math_error() */
|
||||
inittokens();
|
||||
initglobals();
|
||||
initfunctions();
|
||||
initstack();
|
||||
resetinput();
|
||||
math_cleardiversions();
|
||||
math_setfp(stdout);
|
||||
math_setmode(MODE_INITIAL);
|
||||
math_setdigits((long)DISPLAY_DEFAULT);
|
||||
conf->maxprint = MAXPRINT_DEFAULT;
|
||||
|
||||
/*
|
||||
* if arg mode or non-tty mode, just do the work and be gone
|
||||
*/
|
||||
if (str || !stdin_tty) {
|
||||
if (q_flag == FALSE && allow_read) {
|
||||
runrcfiles();
|
||||
q_flag = TRUE;
|
||||
}
|
||||
if (str)
|
||||
(void) openstring(str);
|
||||
else
|
||||
(void) openterminal();
|
||||
start_done = TRUE;
|
||||
getcommands(FALSE);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
start_done = TRUE;
|
||||
|
||||
/*
|
||||
* if in arg mode, we should not get here
|
||||
*/
|
||||
if (str)
|
||||
exit(1);
|
||||
|
||||
/*
|
||||
* process commands (from stdin, not the command line)
|
||||
*/
|
||||
abortlevel = 0;
|
||||
_math_abort_ = FALSE;
|
||||
inputwait = FALSE;
|
||||
(void) signal(SIGINT, intint);
|
||||
math_cleardiversions();
|
||||
math_setfp(stdout);
|
||||
resetscopes();
|
||||
resetinput();
|
||||
if (q_flag == FALSE && allow_read) {
|
||||
q_flag = TRUE;
|
||||
runrcfiles();
|
||||
}
|
||||
(void) openterminal();
|
||||
getcommands(TRUE);
|
||||
|
||||
/*
|
||||
* all done
|
||||
*/
|
||||
exit(0);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* initenv - obtain $CALCPATH, $CALCRC, $CALCBINDINGS, $HOME, $PAGER
|
||||
* and $SHELL values
|
||||
*
|
||||
* If $CALCPATH, $CALCRC, $CALCBINDINGS, $PAGER or $SHELL do not exist,
|
||||
* use the default values. If $PAGER or $SHELL is an empty string, also
|
||||
* use a default value. If $HOME does not exist, or is empty, use the home
|
||||
* directory information from the password file.
|
||||
*/
|
||||
static void
|
||||
initenv(void)
|
||||
{
|
||||
struct passwd *ent; /* our password entry */
|
||||
|
||||
/* determine the $CALCPATH value */
|
||||
calcpath = getenv(CALCPATH);
|
||||
if (calcpath == NULL)
|
||||
calcpath = DEFAULTCALCPATH;
|
||||
|
||||
/* determine the $CALCRC value */
|
||||
calcrc = getenv(CALCRC);
|
||||
if (calcrc == NULL) {
|
||||
calcrc = DEFAULTCALCRC;
|
||||
}
|
||||
|
||||
/* determine the $CALCBINDINGS value */
|
||||
calcbindings = getenv(CALCBINDINGS);
|
||||
if (calcbindings == NULL) {
|
||||
calcbindings = DEFAULTCALCBINDINGS;
|
||||
}
|
||||
|
||||
/* determine the $HOME value */
|
||||
home = getenv(HOME);
|
||||
if (home == NULL || home[0] == '\0') {
|
||||
ent = (struct passwd *)getpwuid(geteuid());
|
||||
if (ent == NULL) {
|
||||
/* just assume . is home if all else fails */
|
||||
home = ".";
|
||||
}
|
||||
home = (char *)malloc(strlen(ent->pw_dir)+1);
|
||||
strcpy(home, ent->pw_dir);
|
||||
}
|
||||
|
||||
/* determine the $PAGER value */
|
||||
pager = getenv(PAGER);
|
||||
if (pager == NULL || *pager == '\0') {
|
||||
pager = DEFAULTCALCPAGER;
|
||||
}
|
||||
|
||||
/* determine the $SHELL value */
|
||||
shell = getenv(SHELL);
|
||||
if (shell == NULL)
|
||||
shell = DEFAULTSHELL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* givehelp - display a help file
|
||||
*
|
||||
* given:
|
||||
* type the type of help to give, NULL => index
|
||||
*/
|
||||
void
|
||||
givehelp(char *type)
|
||||
{
|
||||
struct help_alias *p; /* help alias being considered */
|
||||
char *helpcmd; /* what to execute to print help */
|
||||
|
||||
/*
|
||||
* check permissions to see if we are allowed to help
|
||||
*/
|
||||
if (!allow_exec || !allow_read) {
|
||||
fprintf(stderr,
|
||||
"sorry, help is only allowed with -m mode 5 or 7\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* catch the case where we just print the index */
|
||||
if (type == NULL) {
|
||||
type = DEFAULTCALCHELP; /* the help index file */
|
||||
}
|
||||
|
||||
/* alias the type of help, if needed */
|
||||
for (p=halias; p->topic; ++p) {
|
||||
if (strcmp(type, p->topic) == 0) {
|
||||
type = p->filename;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* form the help command name */
|
||||
helpcmd = (char *)malloc(
|
||||
sizeof("if [ ! -d \"")+sizeof(HELPDIR)+1+strlen(type)+
|
||||
sizeof("\" ];then ")+
|
||||
strlen(pager)+1+1+sizeof(HELPDIR)+1+strlen(type)+1+1+
|
||||
sizeof(";else echo no such help;fi"));
|
||||
sprintf(helpcmd,
|
||||
"if [ -r \"%s/%s\" ];then %s \"%s/%s\";else echo no such help;fi",
|
||||
HELPDIR, type, pager, HELPDIR, type);
|
||||
|
||||
/* execute the help command */
|
||||
system(helpcmd);
|
||||
free(helpcmd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Interrupt routine.
|
||||
*
|
||||
* given:
|
||||
* arg to keep ANSI C happy
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
static void
|
||||
intint(int arg)
|
||||
{
|
||||
(void) signal(SIGINT, intint);
|
||||
if (inputwait || (++abortlevel >= ABORT_NOW)) {
|
||||
math_error("\nABORT");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (abortlevel >= ABORT_MATH)
|
||||
_math_abort_ = TRUE;
|
||||
printf("\n[Abort level %d]\n", abortlevel);
|
||||
}
|
||||
|
||||
/* END CODE */
|
165
calc.h
Normal file
165
calc.h
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (c) 1995 David I. Bell
|
||||
* Permission is granted to use, distribute, or modify this source,
|
||||
* provided that this copyright notice remains intact.
|
||||
*
|
||||
* Definitions for calculator program.
|
||||
*/
|
||||
|
||||
#ifndef CALC_H
|
||||
#define CALC_H
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include "value.h"
|
||||
|
||||
|
||||
/*
|
||||
* Configuration definitions
|
||||
*/
|
||||
#define CALCPATH "CALCPATH" /* environment variable for files */
|
||||
#define CALCRC "CALCRC" /* environment variable for startup */
|
||||
#define CALCBINDINGS "CALCBINDINGS" /* environment variable for hist bindings */
|
||||
#define HOME "HOME" /* environment variable for home dir */
|
||||
#define PAGER "PAGER" /* environment variable for help */
|
||||
#define SHELL "SHELL" /* environment variable for shell */
|
||||
#define DEFAULTCALCHELP "help" /* help file that -h prints */
|
||||
#define DEFAULTSHELL "sh" /* default shell to use */
|
||||
#define CALCEXT ".cal" /* extension for files read in */
|
||||
#define PATHSIZE 1024 /* maximum length of path name */
|
||||
#define HOMECHAR '~' /* char which indicates home directory */
|
||||
#define DOTCHAR '.' /* char which indicates current directory */
|
||||
#define PATHCHAR '/' /* char which separates path components */
|
||||
#define LISTCHAR ':' /* char which separates paths in a list */
|
||||
#define MAXCMD 16384 /* maximum length of command invocation */
|
||||
#define MAXERROR 512 /* maximum length of error message string */
|
||||
|
||||
#define SYMBOLSIZE 256 /* maximum symbol name size */
|
||||
#define MAXINDICES 20 /* maximum number of indices for objects */
|
||||
#define MAXLABELS 100 /* maximum number of user labels in function */
|
||||
#define MAXOBJECTS 10 /* maximum number of object types */
|
||||
#define MAXSTRING 1024 /* maximum size of string constant */
|
||||
#define MAXSTACK 1000 /* maximum depth of evaluation stack */
|
||||
#define MAXFILES 20 /* maximum number of opened files */
|
||||
#define PROMPT1 "> " /* default normal prompt*/
|
||||
#define PROMPT2 ">> " /* default prompt inside multi-line input */
|
||||
|
||||
|
||||
#define TRACE_NORMAL 0x00 /* normal trace flags */
|
||||
#define TRACE_OPCODES 0x01 /* trace every opcode */
|
||||
#define TRACE_NODEBUG 0x02 /* suppress debugging opcodes */
|
||||
#define TRACE_LINKS 0x04 /* display links for real and complex numbers */
|
||||
#define TRACE_FNCODES 0x08 /* display code for newly defined function */
|
||||
#define TRACE_MAX 0x0f /* maximum value for trace flag */
|
||||
|
||||
#define ABORT_NONE 0 /* abort not needed yet */
|
||||
#define ABORT_STATEMENT 1 /* abort on statement boundary */
|
||||
#define ABORT_OPCODE 2 /* abort on any opcode boundary */
|
||||
#define ABORT_MATH 3 /* abort on any math operation */
|
||||
#define ABORT_NOW 4 /* abort right away */
|
||||
|
||||
/*
|
||||
* File ids corresponding to standard in, out, error, and when not in use.
|
||||
*/
|
||||
#define FILEID_STDIN ((FILEID) 0)
|
||||
#define FILEID_STDOUT ((FILEID) 1)
|
||||
#define FILEID_STDERR ((FILEID) 2)
|
||||
#define FILEID_NONE ((FILEID) -1)
|
||||
|
||||
/*
|
||||
* File I/O routines.
|
||||
*/
|
||||
extern FILEID openid(char *name, char *mode);
|
||||
extern FILEID indexid(long index);
|
||||
extern BOOL validid(FILEID id);
|
||||
extern BOOL errorid(FILEID id);
|
||||
extern BOOL eofid(FILEID id);
|
||||
extern int closeid(FILEID id);
|
||||
extern int getcharid(FILEID id);
|
||||
extern int idprintf(FILEID id, char *fmt, int count, VALUE **vals);
|
||||
extern int idfputc(FILEID id, int ch);
|
||||
extern int idfputs(FILEID id, char *str);
|
||||
extern int printid(FILEID id, int flags);
|
||||
extern int flushid(FILEID id);
|
||||
extern int readid(FILEID id, int flags, char **retptr);
|
||||
extern int getloc(FILEID id, ZVALUE *loc);
|
||||
extern int setloc(FILEID id, ZVALUE zpos);
|
||||
extern int getsize(FILEID id, ZVALUE *size);
|
||||
extern int get_device(FILEID id, ZVALUE *dev);
|
||||
extern int get_inode(FILEID id, ZVALUE *ino);
|
||||
extern FILEID reopenid(FILEID id, char *mode, char *name);
|
||||
extern int closeall(void);
|
||||
extern int flushall(void);
|
||||
extern int idfputstr(FILEID id, char *str);
|
||||
extern int rewindid(FILEID id);
|
||||
extern void rewindall(void);
|
||||
extern long filesize(FILEID id);
|
||||
extern void showfiles(void);
|
||||
extern int fscanfid(FILEID id, char *fmt, int count, VALUE **vals);
|
||||
extern int scanfstr(char *str, char *fmt, int count, VALUE **vals);
|
||||
extern long ftellid(FILEID id);
|
||||
extern long fseekid(FILEID id, long offset, int whence);
|
||||
extern int isattyid(FILEID id);
|
||||
long fsearch(FILEID id, char *str, long pos);
|
||||
long frsearch(FILEID id, char *str, long pos);
|
||||
|
||||
/*
|
||||
* Input routines.
|
||||
*/
|
||||
extern FILE *f_open(char *name, char *mode);
|
||||
extern int openstring(char *str);
|
||||
extern int openterminal(void);
|
||||
extern int opensearchfile(char *name, char *pathlist, char *exten, int reopen_ok);
|
||||
extern char *nextline(void);
|
||||
extern int nextchar(void);
|
||||
extern void reread(void);
|
||||
extern void resetinput(void);
|
||||
extern void setprompt(char *);
|
||||
extern BOOL inputisterminal(void);
|
||||
extern char *inputname(void);
|
||||
extern long linenumber(void);
|
||||
extern void runrcfiles(void);
|
||||
extern void closeinput(void);
|
||||
extern FILE *curstream(void);
|
||||
|
||||
|
||||
/*
|
||||
* Other routines.
|
||||
*/
|
||||
extern NUMBER *constvalue(unsigned long index);
|
||||
extern long addnumber(char *str);
|
||||
extern long addqconstant(NUMBER *q);
|
||||
extern void initstack(void);
|
||||
extern void version(FILE *stream);
|
||||
extern void getcommands(BOOL toplevel);
|
||||
extern void givehelp(char *type);
|
||||
extern void hash_init(void);
|
||||
extern void libcalc_call_me_first(void);
|
||||
|
||||
|
||||
/*
|
||||
* Global data definitions.
|
||||
*/
|
||||
extern int abortlevel; /* current level of aborts */
|
||||
extern BOOL inputwait; /* TRUE if in a terminal input wait */
|
||||
extern VALUE *stack; /* execution stack */
|
||||
extern jmp_buf jmpbuf; /* for errors */
|
||||
extern int start_done; /* TRUE => start up processing finished */
|
||||
extern int dumpnames; /* TRUE => dump names rather than indices */
|
||||
|
||||
extern char *calcpath; /* $CALCPATH or default */
|
||||
extern char *calcrc; /* $CALCRC or default */
|
||||
extern char *calcbindings; /* $CALCBINDINGS or default */
|
||||
extern char *home; /* $HOME or default */
|
||||
extern char *shell; /* $SHELL or default */
|
||||
|
||||
extern int allow_read; /* FALSE => may not open any files for reading */
|
||||
extern int allow_write; /* FALSE => may not open any files for writing */
|
||||
extern int allow_exec; /* FALSE => may not execute any commands */
|
||||
|
||||
extern int post_init; /* TRUE => setjmp for math_error is ready */
|
||||
|
||||
#endif
|
||||
|
||||
/* END CODE */
|
423
calc.man
Normal file
423
calc.man
Normal file
@@ -0,0 +1,423 @@
|
||||
.\"
|
||||
.\" Copyright (c) 1994 David I. Bell and Landon Curt Noll
|
||||
.\" Permission is granted to use, distribute, or modify this source,
|
||||
.\" provided that this copyright notice remains intact.
|
||||
.\"
|
||||
.\" calculator by David I. Bell
|
||||
.\" man page by Landon Noll
|
||||
.TH calc 1 "^..^" "15nov93"
|
||||
.SH NAME
|
||||
calc \- arbitrary precision calculator
|
||||
.SH SYNOPSIS
|
||||
\fIcalc\fP
|
||||
[\fI\-h\fP]
|
||||
[\fI\-m mode\fP]
|
||||
[\fI\-p\fP]
|
||||
[\fI\-q\fP]
|
||||
[\fI\-u\fP]
|
||||
[\fI\-v\fP]
|
||||
[\fIcalc_cmd \&.\|.\|.\fp]
|
||||
.SH DESCRIPTION
|
||||
\&
|
||||
.br
|
||||
CALC COMMAND LINE
|
||||
.PP
|
||||
.TP
|
||||
\fI\-h\fP
|
||||
Print a help message.
|
||||
This option implies \fI \-q\fP.
|
||||
This is equivalent to the calc command \fIhelp help\fP.
|
||||
The help facility is disabled unless the \fImode\fP is 5 or 7.
|
||||
See \fI\-m\fP below.
|
||||
.sp
|
||||
.TP
|
||||
\fI\-m mode\fP
|
||||
This flag sets the permission mode of calc.
|
||||
It controls the ability for \fIcalc\fP to open files
|
||||
and execute programs.
|
||||
\fIMode\fP may be a number from 0 to 7.
|
||||
.sp
|
||||
The \fImode\fP value is interpreted in a way similar
|
||||
to that of the \fRchmod(1)\fP octal mode:
|
||||
.sp
|
||||
.in +0.5i
|
||||
.nf
|
||||
0 do not open any file, do not execute progs
|
||||
1 do not open any file
|
||||
2 do not open files for reading, do not execute progs
|
||||
3 do not open files for reading
|
||||
4 do not open files for writing, do not execute progs
|
||||
5 do not open files for writing
|
||||
6 do not execute any program
|
||||
7 allow everything (default mode)
|
||||
.fi
|
||||
.in -0.5i
|
||||
.sp
|
||||
If one wished to run calc from a privledged user, one might
|
||||
want to use \fI\-m 0\fP in an effort to make calc more secure.
|
||||
.sp
|
||||
\fIMode\fP bits for reading and writing apply only on an open.
|
||||
Files already open are not effected.
|
||||
Thus if one wanted to use the \fI\-m 0\fP in an effort to make
|
||||
\fIcalc\fP more secure, but still wanted to read and write a specific
|
||||
file, one might want to do:
|
||||
.sp
|
||||
.in +0.5i
|
||||
.nf
|
||||
\fRcalc \-m 0 3<a.file\fP
|
||||
.fi
|
||||
.in -0.5i
|
||||
.sp
|
||||
Files presented to \fIcalc\fP in this way are opened in an unknown mode.
|
||||
\fICalc\fP will attempt to read or write them if directed.
|
||||
.sp
|
||||
If the \fImode\fP disables opening of files for reading, then
|
||||
the startup library scripts are disabled as of \fI\-q\fP was given.
|
||||
The reading of key bindings is also disabled when the \fImode\fP
|
||||
disables opening of files for reading.
|
||||
.TP
|
||||
\fI \-p\fP
|
||||
Pipe processing is enabled by use of \-p. For example:
|
||||
.sp
|
||||
.in +0.5i
|
||||
.nf
|
||||
\fRecho "print 2^21701\-1, 2^23209\-1" | calc \-p | fizzbin\fP
|
||||
.fi
|
||||
.in -0.5i
|
||||
.sp
|
||||
In pipe mode, \fIcalc\fP does not prompt, does not print leading tabs
|
||||
and does not print the initial header.
|
||||
.TP
|
||||
\fI \-q\fP
|
||||
Disable the use of the \fI$CALCRC\fP startup scripts.
|
||||
.TP
|
||||
\fI \-u\fP
|
||||
Disable buffering of stdin and stdout.
|
||||
.TP
|
||||
\fI \-v\fP
|
||||
Print the version and exit.
|
||||
.PP
|
||||
Without \fIcalc_cmd\fPs, \fIcalc\fP operates interactively.
|
||||
If one or more \fIcalc_cmd\fPs are given on the command line,
|
||||
\fIcalc\fP will execute them and exit.
|
||||
The printing of leading tabs on output is disabled
|
||||
as if \fIconfig("tab",0)\fP had been executed.
|
||||
.PP
|
||||
Normally on startup, \fIcalc\fP attempts to execute a collection
|
||||
of library scripts.
|
||||
The environment variable \fI$CALCRC\fP (if non-existent then
|
||||
a compiled in value) contains a \fI:\fP separated list of
|
||||
startup library scripts.
|
||||
No error conditions are produced if these startup library scripts
|
||||
are not found.
|
||||
.PP
|
||||
If the \fImode\fP disables opening of files for reading, then
|
||||
the startup library scripts are disabled as of \fI\-q\fP was given
|
||||
and \fI$CALCRC\fP as well as the default compiled in value are ignored.
|
||||
.PP
|
||||
Filenames are subject to ``~'' expansion (see below).
|
||||
The environment variable \fI$CALCPATH\fP (if non-existent then
|
||||
a compiled in value) contains a \fI:\fP separated list of search
|
||||
directories.
|
||||
If a file does not begin with \fI/\fP, \fI~\fP or \fI./\fP,
|
||||
then it is searched for under each directory listed in the \fI$CALCPATH\fP.
|
||||
It is an error if no such readable file is found.
|
||||
.PP
|
||||
Calc treats all open files, other than stdin, stdout and stderr
|
||||
as files available for reading and writing.
|
||||
One may present calc with an already open file in the following way:
|
||||
.sp
|
||||
.in +0.5i
|
||||
.nf
|
||||
\fRcalc 3<open_file 4<open_file2\fP
|
||||
.fi
|
||||
.in -0.5i
|
||||
.PP
|
||||
For more information use the following calc commands:
|
||||
.PP
|
||||
.in 1.0i
|
||||
help usage
|
||||
.br
|
||||
help help
|
||||
.br
|
||||
help environment
|
||||
.in -1.0i
|
||||
.PP
|
||||
OVERVIEW
|
||||
.PP
|
||||
\fICalc\fP is arbitrary precision arithmetic system that uses
|
||||
a C-like language.
|
||||
\fICalc\fP is useful as a calculator, an algorithm prototyped
|
||||
and as a mathematical research tool.
|
||||
More importantly, \fIcalc\fP provides one with a machine
|
||||
independent means of computation.
|
||||
.PP
|
||||
\fICalc\fP comes with a rich set of builtin mathematical
|
||||
and programmatic functions.
|
||||
.PP
|
||||
\fICalc\fP is distributed with library of scripts.
|
||||
Written in the same C-like language, library scripts may be
|
||||
read in and executed during a \fIcalc\fP session.
|
||||
These library scripts are also provided because they are
|
||||
useful and to serve as examples of the \fIcalc\fP language.
|
||||
One may further extend \fIcalc\fP thru the
|
||||
use of user defined scripts.
|
||||
.PP
|
||||
Internally calc represents numeric values as fractions reduced to their
|
||||
lowest terms.
|
||||
The numerators and denominators of these factions may grow to
|
||||
arbitrarily large values.
|
||||
Numeric values read in are automatically converted into rationals.
|
||||
The user need not be aware of this internal representation.
|
||||
.PP
|
||||
For more information use the following calc commands:
|
||||
.PP
|
||||
.in 1.0i
|
||||
help intro
|
||||
.br
|
||||
help builtin
|
||||
.br
|
||||
help stdlib
|
||||
.br
|
||||
help define
|
||||
.br
|
||||
show builtins
|
||||
.br
|
||||
show functions
|
||||
.in -1.0i
|
||||
.PP
|
||||
DATA TYPES
|
||||
.PP
|
||||
Fundamental builtin data types include integers, real numbers,
|
||||
rational numbers, complex numbers and strings.
|
||||
.PP
|
||||
By use of an object, one may define an arbitrarily complex
|
||||
data types.
|
||||
One may define how such objects behave a wide range of
|
||||
operations such as addition, subtraction,
|
||||
multiplication, division, negation, squaring, modulus,
|
||||
rounding, exponentiation, equality, comparison, printing
|
||||
and so on.
|
||||
.PP
|
||||
For more information use the following calc commands:
|
||||
.PP
|
||||
.in 1.0i
|
||||
help types
|
||||
.br
|
||||
help obj
|
||||
.br
|
||||
show objfuncs
|
||||
.in -1.0i
|
||||
.PP
|
||||
VARIABLES
|
||||
.PP
|
||||
Variables in \fIcalc\fP are typeless.
|
||||
In other words, the fundamental type of a variable is determined by its content.
|
||||
Before a variable is assigned a value it has the value of zero.
|
||||
.PP
|
||||
The scope of a variable may be global, local to a file, or local to a
|
||||
procedure.
|
||||
Values may be grouped together in a matrix, or into a
|
||||
a list that permits stack and queue style operations.
|
||||
.PP
|
||||
For more information use the following calc commands:
|
||||
.PP
|
||||
.in 1.0i
|
||||
help variable
|
||||
.br
|
||||
help mat
|
||||
.br
|
||||
help list
|
||||
.br
|
||||
show globals
|
||||
.in -1.0i
|
||||
.PP
|
||||
INPUT/OUTPUT
|
||||
.PP
|
||||
A leading ``0x'' implies a hexadecimal value,
|
||||
a leading ``0b'' implies a binary value,
|
||||
and a ``0'' followed by a digit implies an octal value.
|
||||
Complex numbers are indicated by a trailing ``i'' such as in ``3+4i''.
|
||||
Strings may be delimited by either a pair of single or double quotes.
|
||||
By default, \fIcalc\fP prints values as if they were floating point numbers.
|
||||
One may change the default to print values in a number of modes
|
||||
including fractions, integers and exponentials.
|
||||
.PP
|
||||
A number of stdio-like file I/O operations are provided.
|
||||
One may open, read, write, seek and close files.
|
||||
Filenames are subject to ``\~'' expansion to home directories
|
||||
in a way similar to that of the Korn or C-Shell.
|
||||
.PP
|
||||
For example:
|
||||
.PP
|
||||
.in 1.0i
|
||||
~/.calcrc
|
||||
.br
|
||||
~chongo/lib/fft_multiply.cal
|
||||
.in -1.0i
|
||||
.PP
|
||||
For more information use the following calc command:
|
||||
.PP
|
||||
.in 1.0i
|
||||
help file
|
||||
.in -1.0i
|
||||
.PP
|
||||
CALC LANGUAGE
|
||||
.PP
|
||||
The \fIcalc\fP language is a C-like language.
|
||||
The language includes commands such as variable declarations,
|
||||
expressions, tests, labels, loops, file operations, function calls.
|
||||
These commands are very similar to their counterparts in C.
|
||||
.PP
|
||||
The language also include a number of commands particular
|
||||
to \fIcalc\fP itself.
|
||||
These include commands such as function definition, help,
|
||||
reading in library scripts, dump files to a file, error notification,
|
||||
configuration control and status.
|
||||
.PP
|
||||
For more information use the following calc command:
|
||||
.PP
|
||||
.in 1.0i
|
||||
help command
|
||||
.br
|
||||
help statement
|
||||
.br
|
||||
help expression
|
||||
.br
|
||||
help operator
|
||||
.br
|
||||
help config
|
||||
.in -1.0i
|
||||
.PP
|
||||
.SH FILES
|
||||
\&
|
||||
.br
|
||||
.PD 0
|
||||
.TP 20
|
||||
${LIBDIR}/*.cal
|
||||
library scripts shipped with calc
|
||||
.br
|
||||
.sp
|
||||
.TP 20
|
||||
${LIBDIR}/help/*
|
||||
help files
|
||||
.br
|
||||
.sp
|
||||
.TP 20
|
||||
${LIBDIR}/bindings
|
||||
command line editor bindings
|
||||
.sp
|
||||
.SH ENVIRONMENT
|
||||
\&
|
||||
.br
|
||||
.PD 0
|
||||
.TP 5
|
||||
CALCPATH
|
||||
A :-separated list of directories used to search for
|
||||
scripts filenames that do not begin with /, ./ or ~.
|
||||
.br
|
||||
.sp
|
||||
Default value: .:./lib:~/lib:${LIBDIR}
|
||||
.br
|
||||
.sp
|
||||
.TP 5
|
||||
CALCRC
|
||||
On startup (unless \-h or \-q was given on the command
|
||||
line), calc searches for files along this :-separated
|
||||
environment variable.
|
||||
.br
|
||||
.sp
|
||||
Default value: ${LIBDIR}/startup:~/.calcrc
|
||||
.br
|
||||
.sp
|
||||
.TP 5
|
||||
CALCBINDINGS
|
||||
On startup (unless \fI\-h\fP or \fI\-q\fP was given on the command
|
||||
line, or \fI\-m\fP disallows opening files for reading), calc reads
|
||||
key bindings from the filename specified
|
||||
by this environment variable.
|
||||
.br
|
||||
.sp
|
||||
Default value: ${LIBDIR}/bindings
|
||||
.sp
|
||||
.SH CREDIT
|
||||
\&
|
||||
.br
|
||||
The majority of calc was written by David I. Bell.
|
||||
.sp
|
||||
Calc archives and calc-tester mailing list maintained by Landon Curt Noll.
|
||||
.sp
|
||||
Thanks for suggestions and encouragement from Peter Miller,
|
||||
Neil Justusson, and Landon Noll.
|
||||
.sp
|
||||
Thanks to Stephen Rothwell for writing the original version of
|
||||
hist.c which is used to do the command line editing.
|
||||
.sp
|
||||
Thanks to Ernest W. Bowen for supplying many improvements in
|
||||
accuracy and generality for some numeric functions. Much of
|
||||
this was in terms of actual code which I gratefully accepted.
|
||||
Ernest also supplied the original text for many of the help files.
|
||||
.sp
|
||||
Portions of this program are derived from an earlier set of
|
||||
public domain arbitrarily precision routines which was posted
|
||||
to the net around 1984. By now, there is almost no recognizable
|
||||
code left from that original source.
|
||||
.sp
|
||||
Most of this source and binary has one of the following copyrights:
|
||||
.sp
|
||||
.in +0.5i
|
||||
Copyright (c) 19xx David I. Bell
|
||||
.br
|
||||
Copyright (c) 19xx David I. Bell and Landon Curt Noll
|
||||
.br
|
||||
Copyright (c) 19xx Landon Curt Noll
|
||||
.br
|
||||
Copyright (c) 19xx Ernest Bowen and Landon Curt Noll
|
||||
.in -0.5i
|
||||
.sp
|
||||
Permission is granted to use, distribute, or modify this source,
|
||||
provided that this copyright notice remains intact.
|
||||
.sp
|
||||
Send calc comments, suggestions, bug fixes, enhancements
|
||||
and interesting calc scripts that you would like you see included
|
||||
in future distributions to:
|
||||
.sp
|
||||
.in +0.5i
|
||||
dbell@auug.org.au
|
||||
.br
|
||||
chongo@toad.com
|
||||
.in -0.5i
|
||||
.sp
|
||||
Landon Noll maintains the official calc ftp archive at:
|
||||
.sp
|
||||
.in +0.5i
|
||||
ftp://ftp.uu.net/pub/calc
|
||||
.in -0.5i
|
||||
.sp
|
||||
Alpha test versions, complete with bugs, untested code and
|
||||
experimental features may be fetched (if you are brave) under:
|
||||
.sp
|
||||
.in +0.5i
|
||||
http://reality.sgi.com/chongo/calc/
|
||||
.in -0.5i
|
||||
.sp
|
||||
One may join the calc testing group by sending a request to:
|
||||
.sp
|
||||
.in +0.5i
|
||||
calc-tester-request@postofc.corp.sgi.com
|
||||
.in -0.5i
|
||||
.sp
|
||||
Your message body (not the subject) should consist of:
|
||||
.sp
|
||||
.in +0.5i
|
||||
subscribe calc-tester address
|
||||
.br
|
||||
end
|
||||
.br
|
||||
name your_full_name
|
||||
.sp
|
||||
where "address" is your EMail address and "your_full_name"
|
||||
is your full name.
|
||||
.in -0.5i
|
||||
.sp
|
||||
Enjoy!
|
193
calcerr.tbl
Normal file
193
calcerr.tbl
Normal file
@@ -0,0 +1,193 @@
|
||||
# This file is used to build calcerr.h include file.
|
||||
#
|
||||
# Lines should be of the form:
|
||||
#
|
||||
# SYMBOL meaning
|
||||
|
||||
E_1OVER0 Division by zero
|
||||
E_0OVER0 Indeterminate (0/0)
|
||||
E_ADD Bad arguments for +
|
||||
E_SUB Bad arguments for binary -
|
||||
E_MUL Bad arguments for *
|
||||
E_DIV Bad arguments for /
|
||||
E_NEG Bad argument for unary -
|
||||
E_SQUARE Bad argument for squaring
|
||||
E_INV Bad argument for inverse
|
||||
E_INCV Bad argument for ++
|
||||
E_DECV Bad argument for --
|
||||
E_INT Bad argument for int
|
||||
E_FRAC Bad argument for frac
|
||||
E_CONJ Bad argument for conj
|
||||
E_APPR Bad first argument for appr
|
||||
E_APPR2 Bad second argument for appr
|
||||
E_APPR3 Bad third argument for appr
|
||||
E_ROUND Bad first argument for round
|
||||
E_ROUND2 Bad second argument for round
|
||||
E_ROUND3 Bad third argument for round
|
||||
E_BROUND Bad first argument for bround
|
||||
E_BROUND2 Bad second argument for bround
|
||||
E_BROUND3 Bad third argument for bround
|
||||
E_SQRT Bad first argument for sqrt
|
||||
E_SQRT2 Bad second argument for sqrt
|
||||
E_SQRT3 Bad third argument for sqrt
|
||||
E_ROOT Bad first argument for root
|
||||
E_ROOT2 Bad second argument for root
|
||||
E_ROOT3 Bad third argument for root
|
||||
E_NORM Bad argument for norm
|
||||
E_SHIFT Bad first argument for << or >>
|
||||
E_SHIFT2 Bad second argument for << or >>
|
||||
E_SCALE Bad first argument for scale
|
||||
E_SCALE2 Bad second argument for scale
|
||||
E_POWI Bad first argument for ^
|
||||
E_POWI2 Bad second argument for ^
|
||||
E_POWER Bad first argument for power
|
||||
E_POWER2 Bad second argument for power
|
||||
E_POWER3 Bad third argument for power
|
||||
E_QUO Bad first argument for quo or //
|
||||
E_QUO2 Bad second argument for quo or //
|
||||
E_QUO3 Bad third argument for quo
|
||||
E_MOD Bad first argument for mod or %
|
||||
E_MOD2 Bad second argument for mod or %
|
||||
E_MOD3 Bad third argument for mod
|
||||
E_SGN Bad argument for sgn
|
||||
E_ABS Bad first argument for abs
|
||||
E_ABS2 Bad second argument for abs
|
||||
E_EVAL Scan error in argument for eval
|
||||
E_STR Non-simple type for str
|
||||
E_EXP1 Non-real epsilon for exp
|
||||
E_EXP2 Bad first argument for exp
|
||||
E_FPUTC1 Non-file first argument for fputc
|
||||
E_FPUTC2 Bad second argument for fputc
|
||||
E_FPUTC3 File not open for writing for fputc
|
||||
E_FGETC1 Non-file first argument for fgetc
|
||||
E_FGETC2 File not open for reading for fgetc
|
||||
E_FOPEN1 Non-string arguments for fopen
|
||||
E_FOPEN2 Unrecognized mode for fopen
|
||||
E_FREOPEN1 Non-file first argument for freopen
|
||||
E_FREOPEN2 Non-string or unrecognized mode for freopen
|
||||
E_FREOPEN3 Non-string third argument for freopen
|
||||
E_FCLOSE1 Non-file argument for fclose
|
||||
E_FFLUSH Non-file argument for fflush
|
||||
E_FPUTS1 Non-file first argument for fputs
|
||||
E_FPUTS2 Non-string argument after first for fputs
|
||||
E_FPUTS3 File not open for writing for fputs
|
||||
E_FGETS1 Non-file argument for fgets
|
||||
E_FGETS2 File not open for reading for fgets
|
||||
E_FPUTSTR1 Non-file first argument for fputstr
|
||||
E_FPUTSTR2 Non-string argument after first for fputstr
|
||||
E_FPUTSTR3 File not open for writing for fputstr
|
||||
E_FGETSTR1 Non-file first argument for fgetstr
|
||||
E_FGETSTR2 File not open for reading for fgetstr
|
||||
E_FGETLINE1 Non-file argument for fgetline
|
||||
E_FGETLINE2 File not open for reading for fgetline
|
||||
E_FGETWORD1 Non-file argument for fgetword
|
||||
E_FGETWORD2 File not open for reading for fgetword
|
||||
E_REWIND1 Non-file argument for rewind
|
||||
E_FILES Non-integer argument for files
|
||||
E_PRINTF1 Non-string fmt argument for fprint
|
||||
E_PRINTF2 Stdout not open for writing to ???
|
||||
E_FPRINTF1 Non-file first argument for fprintf
|
||||
E_FPRINTF2 Non-string second (fmt) argument for fprintf
|
||||
E_FPRINTF3 File not open for writing for fprintf
|
||||
E_STRPRINTF1 Non-string first (fmt) argument for strprintf
|
||||
E_STRPRINTF2 Error in attempting strprintf ???
|
||||
E_FSCAN1 Non-file first argument for fscan
|
||||
E_FSCAN2 File not open for reading for fscan
|
||||
E_STRSCAN Non-string first argument for strscan
|
||||
E_FSCANF1 Non-file first argument for fscanf
|
||||
E_FSCANF2 Non-string second (fmt) argument for fscanf
|
||||
E_FSCANF3 Non-lvalue argument after second for fscanf
|
||||
E_FSCANF4 File not open for reading or other error for fscanf
|
||||
E_STRSCANF1 Non-string first argument for strscanf
|
||||
E_STRSCANF2 Non-string second (fmt) argument for strscanf
|
||||
E_STRSCANF3 Non-lvalue argument after second for strscanf
|
||||
E_STRSCANF4 Some error in attempting strscanf ???
|
||||
E_SCANF1 Non-string first (fmt) argument for scanf
|
||||
E_SCANF2 Non-lvalue argument after first for scanf
|
||||
E_SCANF3 Some error in attempting scanf ???
|
||||
E_FTELL1 Non-file argument for ftell
|
||||
E_FTELL2 File not open or other error for ftell
|
||||
E_FSEEK1 Non-file first argument for fseek
|
||||
E_FSEEK2 Non-integer or negative second argument for fseek
|
||||
E_FSEEK3 File not open or other error for fseek
|
||||
E_FSIZE1 Non-file argument for fsize
|
||||
E_FSIZE2 File not open or other error for fsize
|
||||
E_FEOF1 Non-file argument for feof
|
||||
E_FEOF2 File not open or other error for feof
|
||||
E_FERROR1 Non-file argument for ferror
|
||||
E_FERROR2 File not open or other error for ferror
|
||||
E_UNGETC1 Non-file argument for ungetc
|
||||
E_UNGETC2 File not open for reading for ungetc
|
||||
E_UNGETC3 Bad second argument or other error for ungetc
|
||||
E_BIGEXP Exponent too big in scanning
|
||||
E_ISATTY1 Non-file argument for isatty
|
||||
E_ISATTY2 File not open for isatty
|
||||
E_ACCESS1 Non-string first argument for access
|
||||
E_ACCESS2 Bad second argument for access
|
||||
E_SEARCH1 Bad first argument for search
|
||||
E_SEARCH2 Bad second argument for search
|
||||
E_SEARCH3 Bad third argument for search
|
||||
E_RSEARCH1 Bad first argument for rsearch
|
||||
E_RSEARCH2 Bad second argument for rsearch
|
||||
E_RSEARCH3 Bad third argument for rsearch
|
||||
E_FOPEN3 Too many open files
|
||||
E_REWIND2 Attempt to rewind a file that is not open
|
||||
E_STRERROR1 Bad argument type for strerror
|
||||
E_STRERROR2 Index out of range for strerror
|
||||
E_COS1 Bad epsilon for cos
|
||||
E_COS2 Bad first argument for cos
|
||||
E_SIN1 Bad epsilon for sin
|
||||
E_SIN2 Bad first argument for sin
|
||||
E_EVAL2 Non-string argument for eval
|
||||
E_ARG1 Bad epsilon for arg
|
||||
E_ARG2 Bad first argument for arg
|
||||
E_POLAR1 Non-real argument for polar
|
||||
E_POLAR2 Bad epsilon for polar
|
||||
E_FCNT Non-integral argument for fcnt
|
||||
E_MATFILL1 Non-variable first argument for matfill
|
||||
E_MATFILL2 Non-matrix first argument-value for matfill
|
||||
E_MATDIM Non-matrix argument for matdim
|
||||
E_MATSUM Non-matrix argument for matsum
|
||||
E_ISIDENT Non-matrix argument for isident
|
||||
E_MATTRANS1 Non-matrix argument for mattrans
|
||||
E_MATTRANS2 Non-two-dimensional matrix for mattrans
|
||||
E_DET1 Non-matrix argument for det
|
||||
E_DET2 Matrix for det not of dimension 2
|
||||
E_DET3 Non-square matrix for det
|
||||
E_MATMIN1 Non-matrix first argument for matmin
|
||||
E_MATMIN2 Non-positive-integer second argument for matmin
|
||||
E_MATMIN3 Second argument for matmin exceeds dimension
|
||||
E_MATMAX1 Non-matrix first argument for matmin
|
||||
E_MATMAX2 Second argument for matmax not positive integer
|
||||
E_MATMAX3 Second argument for matmax exceeds dimension
|
||||
E_CP1 Non-matrix argument for cp
|
||||
E_CP2 Non-one-dimensional matrix for cp
|
||||
E_CP3 Matrix size not 3 for cp
|
||||
E_DP1 Non-matrix argument for dp
|
||||
E_DP2 Non-one-dimensional matrix for dp
|
||||
E_DP3 Different-size matrices for dp
|
||||
E_STRLEN Non-string argument for strlen
|
||||
E_STRCAT Non-string argument for strcat
|
||||
E_SUBSTR1 Non-string first argument for strcat
|
||||
E_SUBSTR2 Non-non-negative integer second argument for strcat
|
||||
E_CHAR Bad argument for char
|
||||
E_ORD Non-string argument for ord
|
||||
E_INSERT1 Non-list-variable first argument for insert
|
||||
E_INSERT2 Non-integral second argument for insert
|
||||
E_PUSH Non-list-variable first argument for push
|
||||
E_APPEND Non-list-variable first argument for append
|
||||
E_DELETE1 Non-list-variable first argument for delete
|
||||
E_DELETE2 Non-integral second argument for delete
|
||||
E_POP Non-list-variable argument for pop
|
||||
E_REMOVE Non-list-variable argument for remove
|
||||
E_LN1 Bad epsilon argument for ln
|
||||
E_LN2 Non-numeric first argument for ln
|
||||
E_ERROR1 Non-integer argument for error
|
||||
E_ERROR2 Argument outside range for error
|
||||
E_EVAL3 Attempt to eval at maximum input depth
|
||||
E_EVAL4 Unable to open string for reading
|
||||
E_RM1 First argument for rm is not a non-empty string
|
||||
E_RM2 Unable to remove a file
|
||||
E_RDPERM Operation allowed because calc mode disallows read operations
|
||||
E_WRPERM Operation allowed because calc mode disallows write operations
|
||||
E_EXPERM Operation allowed because calc mode disallows exec operations
|
17
calcerr_c.awk
Normal file
17
calcerr_c.awk
Normal file
@@ -0,0 +1,17 @@
|
||||
BEGIN {
|
||||
printf("#include <stdio.h>\n");
|
||||
printf("#include \"calcerr.h\"\n\n");
|
||||
printf("#include \"have_const.h\"\n\n");
|
||||
printf("/*\n");
|
||||
printf(" * names of calc error values\n");
|
||||
printf(" */\n");
|
||||
printf("CONST char *error_table[E__COUNT+2] = {\n");
|
||||
printf(" \"No error\",\n");
|
||||
}
|
||||
{
|
||||
print $0;
|
||||
}
|
||||
END {
|
||||
printf(" NULL\n");
|
||||
printf("};\n");
|
||||
}
|
4
calcerr_c.sed
Normal file
4
calcerr_c.sed
Normal file
@@ -0,0 +1,4 @@
|
||||
s/#.*//
|
||||
s/[ ][ ]*$//
|
||||
/^$/d
|
||||
s/[^ ][^ ]*[ ][ ]*\(.*\)$/ "\1",/
|
22
calcerr_h.awk
Normal file
22
calcerr_h.awk
Normal file
@@ -0,0 +1,22 @@
|
||||
BEGIN {
|
||||
ebase = 10000;
|
||||
printf("#define E__BASE %d\t/* calc errors start above here */\n\n", ebase);
|
||||
}
|
||||
NF > 1 {
|
||||
if (length($1) > 7) {
|
||||
printf("#define %s\t", $1, NR);
|
||||
} else {
|
||||
printf("#define %s\t\t", $1, NR);
|
||||
}
|
||||
printf("%d\t/* ", ebase+NR);
|
||||
for (i=2; i < NF; ++i) {
|
||||
printf("%s ", $i);
|
||||
}
|
||||
printf("%s */\n", $NF);
|
||||
}
|
||||
END {
|
||||
printf("\n#define E__HIGHEST\t%d\t/* highest calc error */\n", NR+ebase);
|
||||
printf("#define E__COUNT\t\t%d\t/* number of calc errors */\n", NR);
|
||||
printf("#define E_USERDEF\t20000\t/* base of user defined errors */\n\n");
|
||||
printf("/* names of calc error values */\n");
|
||||
}
|
4
calcerr_h.sed
Normal file
4
calcerr_h.sed
Normal file
@@ -0,0 +1,4 @@
|
||||
s/#.*//
|
||||
s/[ ][ ]*$//
|
||||
/^$/d
|
||||
s/\([^ ][^ ]*\)[ ][ ]*\(.*\)$/\1 \2/
|
74
check.awk
Normal file
74
check.awk
Normal file
@@ -0,0 +1,74 @@
|
||||
# This awk script will print 3 lines before and after any non-blank line that
|
||||
# does not begin with a number. This allows the 'make debug' rule to remove
|
||||
# all non-interest lines the the 'make check' regression output while providing
|
||||
# 3 lines of context around unexpected output.
|
||||
#
|
||||
BEGIN {
|
||||
havebuf0=0;
|
||||
buf0=0;
|
||||
havebuf1=0;
|
||||
buf1=0;
|
||||
havebuf2=0;
|
||||
buf2=0;
|
||||
error = 0;
|
||||
}
|
||||
|
||||
NF == 0 {
|
||||
if (error > 0) {
|
||||
if (havebuf2) {
|
||||
print buf2;
|
||||
}
|
||||
--error;
|
||||
}
|
||||
buf2 = buf1;
|
||||
havebuf2 = havebuf1;
|
||||
buf1 = buf0;
|
||||
havebuf1 = havebuf0;
|
||||
buf0 = $0;
|
||||
havebuf0 = 1;
|
||||
next;
|
||||
}
|
||||
|
||||
$1 ~ /^[0-9]/ {
|
||||
if (error > 0) {
|
||||
if (havebuf2) {
|
||||
print buf2;
|
||||
}
|
||||
--error;
|
||||
}
|
||||
buf2 = buf1;
|
||||
havebuf2 = havebuf1;
|
||||
buf1 = buf0;
|
||||
havebuf1 = havebuf0;
|
||||
buf0 = $0;
|
||||
havebuf0 = 1;
|
||||
next;
|
||||
}
|
||||
|
||||
{
|
||||
error = 6;
|
||||
if (havebuf2) {
|
||||
print buf2;
|
||||
}
|
||||
buf2 = buf1;
|
||||
havebuf2 = havebuf1;
|
||||
buf1 = buf0;
|
||||
havebuf1 = havebuf0;
|
||||
buf0 = $0;
|
||||
havebuf0 = 1;
|
||||
next;
|
||||
}
|
||||
|
||||
END {
|
||||
if (error > 0 && havebuf2) {
|
||||
print buf2;
|
||||
--error;
|
||||
}
|
||||
if (error > 0 && havebuf1) {
|
||||
print buf1;
|
||||
--error;
|
||||
}
|
||||
if (error > 0 && havebuf0) {
|
||||
print buf0;
|
||||
}
|
||||
}
|
113
cmath.h
Normal file
113
cmath.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 1993 David I. Bell
|
||||
* Permission is granted to use, distribute, or modify this source,
|
||||
* provided that this copyright notice remains intact.
|
||||
*
|
||||
* Data structure declarations for extended precision complex arithmetic.
|
||||
*/
|
||||
|
||||
#ifndef CMATH_H
|
||||
#define CMATH_H
|
||||
|
||||
#include "qmath.h"
|
||||
|
||||
|
||||
/*
|
||||
* Complex arithmetic definitions.
|
||||
*/
|
||||
typedef struct {
|
||||
NUMBER *real; /* real part of number */
|
||||
NUMBER *imag; /* imaginary part of number */
|
||||
long links; /* link count */
|
||||
} COMPLEX;
|
||||
|
||||
|
||||
/*
|
||||
* Input, output, and conversion routines.
|
||||
*/
|
||||
extern COMPLEX *comalloc(void);
|
||||
extern COMPLEX *qqtoc(NUMBER *q1, NUMBER *q2);
|
||||
extern void comfree(COMPLEX *c);
|
||||
extern void comprint(COMPLEX *c);
|
||||
extern void cprintfr(COMPLEX *c);
|
||||
|
||||
|
||||
/*
|
||||
* Basic numeric routines.
|
||||
*/
|
||||
extern COMPLEX *cadd(COMPLEX *c1, COMPLEX *c2);
|
||||
extern COMPLEX *csub(COMPLEX *c1, COMPLEX *c2);
|
||||
extern COMPLEX *cmul(COMPLEX *c1, COMPLEX *c2);
|
||||
extern COMPLEX *cdiv(COMPLEX *c1, COMPLEX *c2);
|
||||
extern COMPLEX *caddq(COMPLEX *c, NUMBER *q);
|
||||
extern COMPLEX *csubq(COMPLEX *c, NUMBER *q);
|
||||
extern COMPLEX *cmulq(COMPLEX *c, NUMBER *q);
|
||||
extern COMPLEX *cdivq(COMPLEX *c, NUMBER *q);
|
||||
extern COMPLEX *cscale(COMPLEX *c, long i);
|
||||
extern COMPLEX *cshift(COMPLEX *c, long i);
|
||||
extern COMPLEX *csquare(COMPLEX *c);
|
||||
extern COMPLEX *cconj(COMPLEX *c);
|
||||
extern COMPLEX *creal(COMPLEX *c);
|
||||
extern COMPLEX *cimag(COMPLEX *c);
|
||||
extern COMPLEX *cneg(COMPLEX *c);
|
||||
extern COMPLEX *cinv(COMPLEX *c);
|
||||
extern COMPLEX *cint(COMPLEX *c);
|
||||
extern COMPLEX *cfrac(COMPLEX *c);
|
||||
extern BOOL ccmp(COMPLEX *c1, COMPLEX *c2);
|
||||
|
||||
|
||||
/*
|
||||
* More complicated functions.
|
||||
*/
|
||||
extern COMPLEX *cpowi(COMPLEX *c, NUMBER *q);
|
||||
|
||||
|
||||
/*
|
||||
* Transcendental routines. These all take an epsilon argument to
|
||||
* specify how accurately these are to be calculated.
|
||||
*/
|
||||
extern COMPLEX *cpower(COMPLEX *c1, COMPLEX *c2, NUMBER *epsilon);
|
||||
extern COMPLEX *csqrt(COMPLEX *c, NUMBER *epsilon, long R);
|
||||
extern COMPLEX *croot(COMPLEX *c, NUMBER *q, NUMBER *epsilon);
|
||||
extern COMPLEX *cexp(COMPLEX *c, NUMBER *epsilon);
|
||||
extern COMPLEX *cln(COMPLEX *c, NUMBER *epsilon);
|
||||
extern COMPLEX *ccos(COMPLEX *c, NUMBER *epsilon);
|
||||
extern COMPLEX *csin(COMPLEX *c, NUMBER *epsilon);
|
||||
extern COMPLEX *cpolar(NUMBER *q1, NUMBER *q2, NUMBER *epsilon);
|
||||
extern COMPLEX *crel(COMPLEX *c1, COMPLEX *c2);
|
||||
|
||||
|
||||
/*
|
||||
* external functions
|
||||
*/
|
||||
extern COMPLEX *swap_b8_in_COMPLEX(COMPLEX *dest, COMPLEX *src, BOOL all);
|
||||
extern COMPLEX *swap_b16_in_COMPLEX(COMPLEX *dest, COMPLEX *src, BOOL all);
|
||||
extern COMPLEX *swap_HALF_in_COMPLEX(COMPLEX *dest, COMPLEX *src, BOOL all);
|
||||
|
||||
|
||||
/*
|
||||
* macro expansions to speed this thing up
|
||||
*/
|
||||
#define cisreal(c) (qiszero((c)->imag))
|
||||
#define cisimag(c) (qiszero((c)->real) && !cisreal(c))
|
||||
#define ciszero(c) (cisreal(c) && qiszero((c)->real))
|
||||
#define cisone(c) (cisreal(c) && qisone((c)->real))
|
||||
#define cisnegone(c) (cisreal(c) && qisnegone((c)->real))
|
||||
#define cisrunit(c) (cisreal(c) && qisunit((c)->real))
|
||||
#define cisiunit(c) (qiszero((c)->real) && qisunit((c)->imag))
|
||||
#define cisunit(c) (cisrunit(c) || cisiunit(c))
|
||||
#define cistwo(c) (cisreal(c) && qistwo((c)->real))
|
||||
#define cisint(c) (qisint((c)->real) && qisint((c)->imag))
|
||||
#define ciseven(c) (qiseven((c)->real) && qiseven((c)->imag))
|
||||
#define cisodd(c) (qisodd((c)->real) || qisodd((c)->imag))
|
||||
#define clink(c) ((c)->links++, (c))
|
||||
|
||||
|
||||
/*
|
||||
* Pre-defined values.
|
||||
*/
|
||||
extern COMPLEX _czero_, _cone_, _conei_;
|
||||
|
||||
#endif
|
||||
|
||||
/* END CODE */
|
770
comfunc.c
Normal file
770
comfunc.c
Normal file
@@ -0,0 +1,770 @@
|
||||
/*
|
||||
* Copyright (c) 1993 David I. Bell
|
||||
* Permission is granted to use, distribute, or modify this source,
|
||||
* provided that this copyright notice remains intact.
|
||||
*
|
||||
* Extended precision complex arithmetic non-primitive routines
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "cmath.h"
|
||||
|
||||
/*
|
||||
* Compute the result of raising a complex number to an integer power.
|
||||
*
|
||||
* given:
|
||||
* c complex number to be raised
|
||||
* q power to raise it to
|
||||
*/
|
||||
COMPLEX *
|
||||
cpowi(COMPLEX *c, NUMBER *q)
|
||||
{
|
||||
COMPLEX *tmp, *res; /* temporary values */
|
||||
long power; /* power to raise to */
|
||||
FULL bit; /* current bit value */
|
||||
int sign;
|
||||
|
||||
if (qisfrac(q)) {
|
||||
math_error("Raising number to non-integral power");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (zge31b(q->num)) {
|
||||
math_error("Raising number to very large power");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
power = ztolong(q->num);
|
||||
if (ciszero(c) && (power == 0)) {
|
||||
math_error("Raising zero to zeroth power");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
sign = 1;
|
||||
if (qisneg(q))
|
||||
sign = -1;
|
||||
/*
|
||||
* Handle some low powers specially
|
||||
*/
|
||||
if (power <= 4) {
|
||||
switch ((int) (power * sign)) {
|
||||
case 0:
|
||||
return clink(&_cone_);
|
||||
case 1:
|
||||
return clink(c);
|
||||
case -1:
|
||||
return cinv(c);
|
||||
case 2:
|
||||
return csquare(c);
|
||||
case -2:
|
||||
tmp = csquare(c);
|
||||
res = cinv(tmp);
|
||||
comfree(tmp);
|
||||
return res;
|
||||
case 3:
|
||||
tmp = csquare(c);
|
||||
res = cmul(c, tmp);
|
||||
comfree(tmp);
|
||||
return res;
|
||||
case 4:
|
||||
tmp = csquare(c);
|
||||
res = csquare(tmp);
|
||||
comfree(tmp);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Compute the power by squaring and multiplying.
|
||||
* This uses the left to right method of power raising.
|
||||
*/
|
||||
bit = TOPFULL;
|
||||
while ((bit & power) == 0)
|
||||
bit >>= 1L;
|
||||
bit >>= 1L;
|
||||
res = csquare(c);
|
||||
if (bit & power) {
|
||||
tmp = cmul(res, c);
|
||||
comfree(res);
|
||||
res = tmp;
|
||||
}
|
||||
bit >>= 1L;
|
||||
while (bit) {
|
||||
tmp = csquare(res);
|
||||
comfree(res);
|
||||
res = tmp;
|
||||
if (bit & power) {
|
||||
tmp = cmul(res, c);
|
||||
comfree(res);
|
||||
res = tmp;
|
||||
}
|
||||
bit >>= 1L;
|
||||
}
|
||||
if (sign < 0) {
|
||||
tmp = cinv(res);
|
||||
comfree(res);
|
||||
res = tmp;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Calculate the square root of a complex number to specified accuracy.
|
||||
* Type of rounding of each component specified by R as for qsqrt().
|
||||
*/
|
||||
COMPLEX *
|
||||
csqrt(COMPLEX *c, NUMBER *epsilon, long R)
|
||||
{
|
||||
COMPLEX *r;
|
||||
NUMBER *es, *aes, *bes, *u, *v, qtemp;
|
||||
NUMBER *ntmp;
|
||||
ZVALUE g, a, b, d, aa, cc;
|
||||
ZVALUE tmp1, tmp2, tmp3, mul1, mul2;
|
||||
long s1, s2, s3, up1, up2;
|
||||
int imsign, sign;
|
||||
|
||||
if (ciszero(c))
|
||||
return clink(c);
|
||||
if (cisreal(c)) {
|
||||
r = comalloc();
|
||||
if (!qisneg(c->real)) {
|
||||
r->real = qsqrt(c->real, epsilon, R);
|
||||
return r;
|
||||
}
|
||||
ntmp = qneg(c->real);
|
||||
r->imag = qsqrt(ntmp, epsilon, R);
|
||||
qfree(ntmp);
|
||||
return r;
|
||||
}
|
||||
|
||||
up1 = up2 = 0;
|
||||
sign = (R & 64) != 0;
|
||||
#if 0
|
||||
if (qiszero(epsilon)) {
|
||||
aes = qsquare(c->real);
|
||||
bes = qsquare(c->imag);
|
||||
v = qqadd(aes, bes);
|
||||
qfree(aes);
|
||||
qfree(bes);
|
||||
u = qsqrt(v, epsilon, 0);
|
||||
qfree(v);
|
||||
if (qiszero(u)) {
|
||||
qfree(u);
|
||||
return clink(&_czero_);
|
||||
}
|
||||
aes = qqadd(u, c->real);
|
||||
qfree(u);
|
||||
bes = qscale(aes, -1);
|
||||
qfree(aes);
|
||||
u = qsqrt(bes, epsilon, R);
|
||||
qfree(bes);
|
||||
if (qiszero(u)) {
|
||||
qfree(u);
|
||||
return clink(&_czero_);
|
||||
}
|
||||
aes = qscale(c->imag, -1);
|
||||
v = qdiv(aes, u);
|
||||
qfree(aes);
|
||||
r = comalloc();
|
||||
r->real = u;
|
||||
r->imag = v;
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
imsign = c->imag->num.sign;
|
||||
es = qsquare(epsilon);
|
||||
aes = qdiv(c->real, es);
|
||||
bes = qdiv(c->imag, es);
|
||||
qfree(es);
|
||||
zgcd(aes->den, bes->den, &g);
|
||||
zequo(bes->den, g, &tmp1);
|
||||
zmul(aes->num, tmp1, &a);
|
||||
zmul(aes->den, tmp1, &tmp2);
|
||||
zshift(tmp2, 1, &d);
|
||||
zfree(tmp1);
|
||||
zfree(tmp2);
|
||||
zequo(aes->den, g, &tmp1);
|
||||
zmul(bes->num, tmp1, &b);
|
||||
zfree(tmp1);
|
||||
zfree(g);
|
||||
qfree(aes);
|
||||
qfree(bes);
|
||||
zsquare(a, &tmp1);
|
||||
zsquare(b, &tmp2);
|
||||
zfree(b);
|
||||
zadd(tmp1, tmp2, &tmp3);
|
||||
zfree(tmp1);
|
||||
zfree(tmp2);
|
||||
if (R & 16) {
|
||||
zshift(tmp3, 4, &tmp1);
|
||||
zfree(tmp3);
|
||||
zshift(a, 2, &aa);
|
||||
zfree(a);
|
||||
s1 = zsqrt(tmp1, &cc, 16);
|
||||
zfree(tmp1);
|
||||
zadd(cc, aa, &tmp1);
|
||||
if (s1 == 0 && R & 32) {
|
||||
zmul(tmp1, d, &tmp2);
|
||||
zfree(tmp1);
|
||||
s2 = zsqrt(tmp2, &tmp3, 16);
|
||||
zfree(tmp2);
|
||||
if (s2 == 0) {
|
||||
aes = qalloc();
|
||||
zshift(d, 1, &tmp1);
|
||||
zreduce(tmp3, tmp1, &aes->num, &aes->den);
|
||||
zfree(tmp1);
|
||||
zfree(tmp3);
|
||||
zfree(aa);
|
||||
zfree(cc);
|
||||
zfree(d);
|
||||
r = comalloc();
|
||||
qtemp = *aes;
|
||||
qtemp.num.sign = sign;
|
||||
r->real = qmul(&qtemp, epsilon);
|
||||
qfree(aes);
|
||||
bes = qscale(r->real, 1);
|
||||
qtemp = *bes;
|
||||
qtemp.num.sign = sign ^ imsign;
|
||||
r->imag = qdiv(c->imag, &qtemp);
|
||||
qfree(bes);
|
||||
return r;
|
||||
}
|
||||
s3 = zquo(tmp3, d, &tmp1, s2 < 0);
|
||||
}
|
||||
else {
|
||||
s2 = zquo(tmp1, d, &tmp3, s1 ? (s1 < 0) : 16);
|
||||
zfree(tmp1);
|
||||
s3 = zsqrt(tmp3,&tmp1,(s1||s2) ? (s1<0 || s2<0) : 16);
|
||||
}
|
||||
zfree(tmp3);
|
||||
zshift(tmp1, -1, &mul1);
|
||||
if (*tmp1.v & 1)
|
||||
up1 = s1 + s2 + s3;
|
||||
else
|
||||
up1 = -1;
|
||||
zfree(tmp1);
|
||||
zsub(cc, aa, &tmp1);
|
||||
s2 = zquo(tmp1, d, &tmp2, s1 ? (s1 < 0) : 16);
|
||||
zfree(tmp1);
|
||||
s3 = zsqrt(tmp2, &tmp1, (s1 || s2) ? (s1 < 0 || s2 < 0) : 16);
|
||||
zfree(tmp2);
|
||||
zshift(tmp1, -1, &mul2);
|
||||
if (*tmp1.v & 1)
|
||||
up2 = s1 + s2 + s3;
|
||||
else
|
||||
up2 = -1;
|
||||
zfree(tmp1);
|
||||
zfree(aa);
|
||||
}
|
||||
else {
|
||||
s1 = zsqrt(tmp3, &cc, 0);
|
||||
zfree(tmp3);
|
||||
zadd(cc, a, &tmp1);
|
||||
if (s1 == 0 && R & 32) {
|
||||
zmul(tmp1, d, &tmp2);
|
||||
zfree(tmp1);
|
||||
s2 = zsqrt(tmp2, &tmp3, 0);
|
||||
zfree(tmp2);
|
||||
if (s2 == 0) {
|
||||
aes = qalloc();
|
||||
zreduce(tmp3, d, &aes->num, &aes->den);
|
||||
zfree(tmp3);
|
||||
zfree(a);
|
||||
zfree(cc);
|
||||
zfree(d);
|
||||
r = comalloc();
|
||||
qtemp = *aes;
|
||||
qtemp.num.sign = sign;
|
||||
r->real = qmul(&qtemp, epsilon);
|
||||
qfree(aes);
|
||||
bes = qscale(r->real, 1);
|
||||
qtemp = *bes;
|
||||
qtemp.num.sign = sign ^ imsign;
|
||||
r->imag = qdiv(c->imag, &qtemp);
|
||||
qfree(bes);
|
||||
return r;
|
||||
}
|
||||
s3 = zquo(tmp3, d, &mul1, 0);
|
||||
}
|
||||
else {
|
||||
s2 = zquo(tmp1, d, &tmp3, 0);
|
||||
zfree(tmp1);
|
||||
s3 = zsqrt(tmp3, &mul1, 0);
|
||||
}
|
||||
up1 = (s1 + s2 + s3) ? 0 : -1;
|
||||
zfree(tmp3);
|
||||
zsub(cc, a, &tmp1);
|
||||
s2 = zquo(tmp1, d, &tmp2, 0);
|
||||
zfree(tmp1);
|
||||
s3 = zsqrt(tmp2, &mul2, 0);
|
||||
up2 = (s1 + s2 + s3) ? 0 : -1;
|
||||
zfree(tmp2);
|
||||
zfree(a);
|
||||
}
|
||||
zfree(cc); zfree(d);
|
||||
if (up1 == 0) {
|
||||
if (R & 8)
|
||||
up1 = (long)((R ^ *mul1.v) & 1);
|
||||
else
|
||||
up1 = (R ^ epsilon->num.sign ^ sign) & 1;
|
||||
if (R & 2)
|
||||
up1 ^= epsilon->num.sign ^ sign;
|
||||
if (R & 4)
|
||||
up1 ^= epsilon->num.sign;
|
||||
}
|
||||
if (up2 == 0) {
|
||||
if (R & 8)
|
||||
up2 = (long)((R ^ *mul2.v) & 1);
|
||||
else
|
||||
up2 = (R ^ epsilon->num.sign ^ sign ^ imsign) & 1;
|
||||
if (R & 2)
|
||||
up2 ^= epsilon->num.sign ^ imsign ^ sign;
|
||||
if (R & 4)
|
||||
up2 ^= epsilon->num.sign;
|
||||
}
|
||||
if (up1 > 0) {
|
||||
zadd(mul1, _one_, &tmp1);
|
||||
zfree(mul1);
|
||||
mul1 = tmp1;
|
||||
}
|
||||
if (up2 > 0) {
|
||||
zadd(mul2, _one_, &tmp2);
|
||||
zfree(mul2);
|
||||
mul2 = tmp2;
|
||||
}
|
||||
if (ziszero(mul1))
|
||||
u = qlink(&_qzero_);
|
||||
else {
|
||||
mul1.sign = sign ^ epsilon->num.sign;
|
||||
u = qalloc();
|
||||
zreduce(mul1, epsilon->den, &tmp2, &u->den);
|
||||
zmul(tmp2, epsilon->num, &u->num);
|
||||
zfree(tmp2);
|
||||
}
|
||||
zfree(mul1);
|
||||
if (ziszero(mul2))
|
||||
v = qlink(&_qzero_);
|
||||
else {
|
||||
mul2.sign = imsign ^ sign ^ epsilon->num.sign;
|
||||
v = qalloc();
|
||||
zreduce(mul2, epsilon->den, &tmp2, &v->den);
|
||||
zmul(tmp2, epsilon->num, &v->num);
|
||||
zfree(tmp2);
|
||||
}
|
||||
zfree(mul2);
|
||||
if (qiszero(u) && qiszero(v)) {
|
||||
qfree(u);
|
||||
qfree(v);
|
||||
return clink(&_czero_);
|
||||
}
|
||||
r = comalloc();
|
||||
if (!qiszero(u))
|
||||
r->real = u;
|
||||
if (!qiszero(v))
|
||||
r->imag = v;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Take the Nth root of a complex number, where N is a positive integer.
|
||||
* Each component of the result is within the specified error.
|
||||
*/
|
||||
COMPLEX *
|
||||
croot(COMPLEX *c, NUMBER *q, NUMBER *epsilon)
|
||||
{
|
||||
COMPLEX *r;
|
||||
NUMBER *a2pb2, *root, *tmp1, *tmp2, *epsilon2;
|
||||
long n, m;
|
||||
|
||||
if (qisneg(q) || qiszero(q) || qisfrac(q)) {
|
||||
math_error("Taking bad root of complex number");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (cisone(c) || qisone(q))
|
||||
return clink(c);
|
||||
if (qistwo(q))
|
||||
return csqrt(c, epsilon, 24L);
|
||||
if (cisreal(c) && !qisneg(c->real)) {
|
||||
r = comalloc();
|
||||
r->real = qroot(c->real, q, epsilon);
|
||||
return r;
|
||||
}
|
||||
/*
|
||||
* Calculate the root using the formula:
|
||||
* croot(a + bi, n) =
|
||||
* cpolar(qroot(a^2 + b^2, 2 * n), qatan2(b, a) / n).
|
||||
*/
|
||||
n = qilog2(epsilon);
|
||||
epsilon2 = qbitvalue(n - 4);
|
||||
tmp1 = qsquare(c->real);
|
||||
tmp2 = qsquare(c->imag);
|
||||
a2pb2 = qqadd(tmp1, tmp2);
|
||||
qfree(tmp1);
|
||||
qfree(tmp2);
|
||||
tmp1 = qscale(q, 1L);
|
||||
root = qroot(a2pb2, tmp1, epsilon2);
|
||||
qfree(a2pb2);
|
||||
qfree(tmp1);
|
||||
m = qilog2(root);
|
||||
if (m < n) {
|
||||
qfree(root);
|
||||
return clink(&_czero_);
|
||||
}
|
||||
qfree(epsilon2);
|
||||
epsilon2 = qbitvalue(n - m - 4);
|
||||
tmp1 = qatan2(c->imag, c->real, epsilon2);
|
||||
qfree(epsilon2);
|
||||
tmp2 = qdiv(tmp1, q);
|
||||
qfree(tmp1);
|
||||
r = cpolar(root, tmp2, epsilon);
|
||||
qfree(root);
|
||||
qfree(tmp2);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Calculate the complex exponential function to the desired accuracy.
|
||||
* We use the formula:
|
||||
* exp(a + bi) = exp(a) * (cos(b) + i * sin(b)).
|
||||
*/
|
||||
COMPLEX *
|
||||
cexp(COMPLEX *c, NUMBER *epsilon)
|
||||
{
|
||||
COMPLEX *r;
|
||||
NUMBER *sin, *cos, *tmp1, *tmp2, *epsilon1;
|
||||
long k, n;
|
||||
|
||||
if (qiszero(epsilon)) {
|
||||
math_error("Zero epsilon for cexp");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
r = comalloc();
|
||||
if (cisreal(c)) {
|
||||
r->real = qexp(c->real, epsilon);
|
||||
return r;
|
||||
}
|
||||
n = qilog2(epsilon);
|
||||
epsilon1 = qbitvalue(n - 2);
|
||||
tmp1 = qexp(c->real, epsilon1);
|
||||
qfree(epsilon1);
|
||||
if (qiszero(tmp1)) {
|
||||
qfree(tmp1);
|
||||
return clink(&_czero_);
|
||||
}
|
||||
k = qilog2(tmp1) + 1;
|
||||
if (k < n) {
|
||||
qfree(tmp1);
|
||||
return clink(&_czero_);
|
||||
}
|
||||
qsincos(c->imag, k - n + 2, &sin, &cos);
|
||||
tmp2 = qmul(tmp1, cos);
|
||||
qfree(cos);
|
||||
r->real = qmappr(tmp2, epsilon, 24L);
|
||||
qfree(tmp2);
|
||||
tmp2 = qmul(tmp1, sin);
|
||||
qfree(tmp1);
|
||||
qfree(sin);
|
||||
r->imag = qmappr(tmp2, epsilon, 24L);
|
||||
qfree(tmp2);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Calculate the natural logarithm of a complex number within the specified
|
||||
* error. We use the formula:
|
||||
* ln(a + bi) = ln(a^2 + b^2) / 2 + i * atan2(b, a).
|
||||
*/
|
||||
COMPLEX *
|
||||
cln(COMPLEX *c, NUMBER *epsilon)
|
||||
{
|
||||
COMPLEX *r;
|
||||
NUMBER *a2b2, *tmp1, *tmp2, *epsilon1;
|
||||
|
||||
if (ciszero(c)) {
|
||||
math_error("Logarithm of zero");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (cisone(c))
|
||||
return clink(&_czero_);
|
||||
r = comalloc();
|
||||
if (cisreal(c) && !qisneg(c->real)) {
|
||||
r->real = qln(c->real, epsilon);
|
||||
return r;
|
||||
}
|
||||
tmp1 = qsquare(c->real);
|
||||
tmp2 = qsquare(c->imag);
|
||||
a2b2 = qqadd(tmp1, tmp2);
|
||||
qfree(tmp1);
|
||||
qfree(tmp2);
|
||||
epsilon1 = qscale(epsilon, 1L);
|
||||
tmp1 = qln(a2b2, epsilon1);
|
||||
qfree(a2b2);
|
||||
qfree(epsilon1);
|
||||
r->real = qscale(tmp1, -1L);
|
||||
qfree(tmp1);
|
||||
r->imag = qatan2(c->imag, c->real, epsilon);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Calculate the complex cosine within the specified accuracy.
|
||||
* This uses the formula:
|
||||
* cos(x) = (exp(1i * x) + exp(-1i * x))/2;
|
||||
*/
|
||||
COMPLEX *
|
||||
ccos(COMPLEX *c, NUMBER *epsilon)
|
||||
{
|
||||
COMPLEX *r, *ctmp1, *ctmp2, *ctmp3;
|
||||
NUMBER *epsilon1;
|
||||
long n;
|
||||
BOOL neg;
|
||||
|
||||
if (qiszero(epsilon)) {
|
||||
math_error("Zero epsilon for ccos");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
n = qilog2(epsilon);
|
||||
ctmp1 = comalloc();
|
||||
neg = qisneg(c->imag);
|
||||
ctmp1->real = neg ? qneg(c->imag) : qlink(c->imag);
|
||||
ctmp1->imag = neg ? qlink(c->real) : qneg(c->real);
|
||||
epsilon1 = qbitvalue(n - 2);
|
||||
ctmp2 = cexp(ctmp1, epsilon1);
|
||||
comfree(ctmp1);
|
||||
qfree(epsilon1);
|
||||
if (ciszero(ctmp2)) {
|
||||
comfree(ctmp2);
|
||||
return clink(&_czero_);
|
||||
}
|
||||
ctmp1 = cinv(ctmp2);
|
||||
ctmp3 = cadd(ctmp2, ctmp1);
|
||||
comfree(ctmp1);
|
||||
comfree(ctmp2);
|
||||
ctmp1 = cscale(ctmp3, -1);
|
||||
comfree(ctmp3);
|
||||
r = comalloc();
|
||||
r->real = qmappr(ctmp1->real, epsilon, 24L);
|
||||
r->imag = qmappr(ctmp1->imag, epsilon, 24L);
|
||||
comfree(ctmp1);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Calculate the complex sine within the specified accuracy.
|
||||
* This uses the formula:
|
||||
* sin(x) = (exp(1i * x) - exp(-i1*x))/(2i).
|
||||
*/
|
||||
COMPLEX *
|
||||
csin(COMPLEX *c, NUMBER *epsilon)
|
||||
{
|
||||
COMPLEX *r, *ctmp1, *ctmp2, *ctmp3;
|
||||
NUMBER *qtmp, *epsilon1;
|
||||
long n;
|
||||
BOOL neg;
|
||||
|
||||
if (qiszero(epsilon)) {
|
||||
math_error("Zero epsilon for csin");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (ciszero(c))
|
||||
return clink(&_czero_);
|
||||
n = qilog2(epsilon);
|
||||
ctmp1 = comalloc();
|
||||
neg = qisneg(c->imag);
|
||||
ctmp1->real = neg ? qneg(c->imag) : qlink(c->imag);
|
||||
ctmp1->imag = neg ? qlink(c->real) : qneg(c->real);
|
||||
epsilon1 = qbitvalue(n - 2);
|
||||
ctmp2 = cexp(ctmp1, epsilon1);
|
||||
comfree(ctmp1);
|
||||
qfree(epsilon1);
|
||||
if (ciszero(ctmp2)) {
|
||||
comfree(ctmp2);
|
||||
return clink(&_czero_);
|
||||
}
|
||||
ctmp1 = cinv(ctmp2);
|
||||
ctmp3 = csub(ctmp2, ctmp1);
|
||||
comfree(ctmp1);
|
||||
comfree(ctmp2);
|
||||
ctmp1 = cscale(ctmp3, -1);
|
||||
comfree(ctmp3);
|
||||
r = comalloc();
|
||||
qtmp = neg ? qlink(ctmp1->imag) : qneg(ctmp1->imag);
|
||||
r->real = qmappr(qtmp, epsilon, 24L);
|
||||
qfree(qtmp);
|
||||
qtmp = neg ? qneg(ctmp1->real) : qlink(ctmp1->real);
|
||||
r->imag = qmappr(qtmp, epsilon, 24L);
|
||||
qfree(qtmp);
|
||||
comfree(ctmp1);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert a number from polar coordinates to normal complex number form
|
||||
* within the specified accuracy. This produces the value:
|
||||
* q1 * cos(q2) + q1 * sin(q2) * i.
|
||||
*/
|
||||
COMPLEX *
|
||||
cpolar(NUMBER *q1, NUMBER *q2, NUMBER *epsilon)
|
||||
{
|
||||
COMPLEX *r;
|
||||
NUMBER *tmp, *cos, *sin;
|
||||
long m, n;
|
||||
|
||||
if (qiszero(epsilon)) {
|
||||
math_error("Zero epsilson for cpolar");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (qiszero(q1))
|
||||
return qlink(&_czero_);
|
||||
m = qilog2(q1) + 1;
|
||||
n = qilog2(epsilon);
|
||||
if (m < n)
|
||||
return qlink(&_czero_);
|
||||
r = comalloc();
|
||||
if (qiszero(q2)) {
|
||||
r->real = qlink(q1);
|
||||
return r;
|
||||
}
|
||||
qsincos(q2, m - n + 2, &sin, &cos);
|
||||
tmp = qmul(q1, cos);
|
||||
qfree(cos);
|
||||
r->real = qmappr(tmp, epsilon, 24L);
|
||||
qfree(tmp);
|
||||
tmp = qmul(q1, sin);
|
||||
qfree(sin);
|
||||
r->imag = qmappr(tmp, epsilon, 24L);
|
||||
qfree(tmp);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Raise one complex number to the power of another one to within the
|
||||
* specified error.
|
||||
*/
|
||||
COMPLEX *
|
||||
cpower(COMPLEX *c1, COMPLEX *c2, NUMBER *epsilon)
|
||||
{
|
||||
COMPLEX *ctmp1, *ctmp2;
|
||||
long k1, k2, k, m1, m2, m, n;
|
||||
NUMBER *a2b2, *qtmp1, *qtmp2, *epsilon1;
|
||||
|
||||
if (qiszero(epsilon)) {
|
||||
math_error("Zero epsilon for cpower");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (ciszero(c1)) {
|
||||
if (qisneg(c2->real) || qiszero(c2->real)) {
|
||||
math_error ("Non-positive exponent of zero");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
return clink(&_czero_);
|
||||
}
|
||||
n = qilog2(epsilon);
|
||||
m1 = m2 = -1000000;
|
||||
k1 = k2 = 0;
|
||||
qtmp1 = qsquare(c1->real);
|
||||
qtmp2 = qsquare(c1->imag);
|
||||
a2b2 = qqadd(qtmp1, qtmp2);
|
||||
qfree(qtmp1);
|
||||
qfree(qtmp2);
|
||||
if (!qiszero(c2->real)) {
|
||||
m1 = qilog2(c2->real);
|
||||
epsilon1 = qbitvalue(-m1 - 1);
|
||||
qtmp1 = qln(a2b2, epsilon1);
|
||||
qfree(epsilon1);
|
||||
qfree(a2b2);
|
||||
qtmp2 = qmul(qtmp1, c2->real);
|
||||
qfree(qtmp1);
|
||||
qtmp1 = qmul(qtmp2, &_qlge_);
|
||||
qfree(qtmp2);
|
||||
k1 = qtoi(qtmp1);
|
||||
qfree(qtmp1);
|
||||
}
|
||||
if (!qiszero(c2->imag)) {
|
||||
m2 = qilog2(c2->imag);
|
||||
epsilon1 = qbitvalue(-m2 - 1);
|
||||
qtmp1 = qatan2(c1->imag, c1->real, epsilon1);
|
||||
qfree(epsilon1);
|
||||
qtmp2 = qmul(qtmp1, c2->imag);
|
||||
qfree(qtmp1);
|
||||
qtmp1 = qscale(qtmp2, -1);
|
||||
qfree(qtmp2);
|
||||
qtmp2 = qmul(qtmp1, &_qlge_);
|
||||
qfree(qtmp1);
|
||||
k2 = qtoi(qtmp2);
|
||||
qfree(qtmp2);
|
||||
}
|
||||
m = (m2 > m1) ? m2 : m1;
|
||||
k = k1 - k2 + 1;
|
||||
if (k < n)
|
||||
return clink(&_czero_);
|
||||
epsilon1 = qbitvalue(n - k - m - 2);
|
||||
ctmp1 = cln(c1, epsilon1);
|
||||
qfree(epsilon1);
|
||||
ctmp2 = cmul(ctmp1, c2);
|
||||
comfree(ctmp1);
|
||||
ctmp1 = cexp(ctmp2, epsilon);
|
||||
comfree(ctmp2);
|
||||
return ctmp1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Print a complex number in the current output mode.
|
||||
*/
|
||||
void
|
||||
comprint(COMPLEX *c)
|
||||
{
|
||||
NUMBER qtmp;
|
||||
|
||||
if (conf->outmode == MODE_FRAC) {
|
||||
cprintfr(c);
|
||||
return;
|
||||
}
|
||||
if (!qiszero(c->real) || qiszero(c->imag))
|
||||
qprintnum(c->real, MODE_DEFAULT);
|
||||
qtmp = c->imag[0];
|
||||
if (qiszero(&qtmp))
|
||||
return;
|
||||
if (!qiszero(c->real) && !qisneg(&qtmp))
|
||||
math_chr('+');
|
||||
if (qisneg(&qtmp)) {
|
||||
math_chr('-');
|
||||
qtmp.num.sign = 0;
|
||||
}
|
||||
qprintnum(&qtmp, MODE_DEFAULT);
|
||||
math_chr('i');
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Print a complex number in rational representation.
|
||||
* Example: 2/3-4i/5
|
||||
*/
|
||||
void
|
||||
cprintfr(COMPLEX *c)
|
||||
{
|
||||
NUMBER *r;
|
||||
NUMBER *i;
|
||||
|
||||
r = c->real;
|
||||
i = c->imag;
|
||||
if (!qiszero(r) || qiszero(i))
|
||||
qprintfr(r, 0L, FALSE);
|
||||
if (qiszero(i))
|
||||
return;
|
||||
if (!qiszero(r) && !qisneg(i))
|
||||
math_chr('+');
|
||||
zprintval(i->num, 0L, 0L);
|
||||
math_chr('i');
|
||||
if (qisfrac(i)) {
|
||||
math_chr('/');
|
||||
zprintval(i->den, 0L, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
/* END CODE */
|
555
commath.c
Normal file
555
commath.c
Normal file
@@ -0,0 +1,555 @@
|
||||
/*
|
||||
* Copyright (c) 1993 David I. Bell
|
||||
* Permission is granted to use, distribute, or modify this source,
|
||||
* provided that this copyright notice remains intact.
|
||||
*
|
||||
* Extended precision complex arithmetic primitive routines
|
||||
*/
|
||||
|
||||
#include "cmath.h"
|
||||
|
||||
|
||||
COMPLEX _czero_ = { &_qzero_, &_qzero_, 1 };
|
||||
COMPLEX _cone_ = { &_qone_, &_qzero_, 1 };
|
||||
COMPLEX _conei_ = { &_qzero_, &_qone_, 1 };
|
||||
|
||||
static COMPLEX _cnegone_ = { &_qnegone_, &_qzero_, 1 };
|
||||
|
||||
|
||||
/*
|
||||
* Add two complex numbers.
|
||||
*/
|
||||
COMPLEX *
|
||||
cadd(COMPLEX *c1, COMPLEX *c2)
|
||||
{
|
||||
COMPLEX *r;
|
||||
|
||||
if (ciszero(c1))
|
||||
return clink(c2);
|
||||
if (ciszero(c2))
|
||||
return clink(c1);
|
||||
r = comalloc();
|
||||
if (!qiszero(c1->real) || !qiszero(c2->real))
|
||||
r->real = qqadd(c1->real, c2->real);
|
||||
if (!qiszero(c1->imag) || !qiszero(c2->imag))
|
||||
r->imag = qqadd(c1->imag, c2->imag);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Subtract two complex numbers.
|
||||
*/
|
||||
COMPLEX *
|
||||
csub(COMPLEX *c1, COMPLEX *c2)
|
||||
{
|
||||
COMPLEX *r;
|
||||
|
||||
if ((c1->real == c2->real) && (c1->imag == c2->imag))
|
||||
return clink(&_czero_);
|
||||
if (ciszero(c2))
|
||||
return clink(c1);
|
||||
r = comalloc();
|
||||
if (!qiszero(c1->real) || !qiszero(c2->real))
|
||||
r->real = qsub(c1->real, c2->real);
|
||||
if (!qiszero(c1->imag) || !qiszero(c2->imag))
|
||||
r->imag = qsub(c1->imag, c2->imag);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Multiply two complex numbers.
|
||||
* This saves one multiplication over the obvious algorithm by
|
||||
* trading it for several extra additions, as follows. Let
|
||||
* q1 = (a + b) * (c + d)
|
||||
* q2 = a * c
|
||||
* q3 = b * d
|
||||
* Then (a+bi) * (c+di) = (q2 - q3) + (q1 - q2 - q3)i.
|
||||
*/
|
||||
COMPLEX *
|
||||
cmul(COMPLEX *c1, COMPLEX *c2)
|
||||
{
|
||||
COMPLEX *r;
|
||||
NUMBER *q1, *q2, *q3, *q4;
|
||||
|
||||
if (ciszero(c1) || ciszero(c2))
|
||||
return clink(&_czero_);
|
||||
if (cisone(c1))
|
||||
return clink(c2);
|
||||
if (cisone(c2))
|
||||
return clink(c1);
|
||||
if (cisreal(c2))
|
||||
return cmulq(c1, c2->real);
|
||||
if (cisreal(c1))
|
||||
return cmulq(c2, c1->real);
|
||||
/*
|
||||
* Need to do the full calculation.
|
||||
*/
|
||||
r = comalloc();
|
||||
q2 = qqadd(c1->real, c1->imag);
|
||||
q3 = qqadd(c2->real, c2->imag);
|
||||
q1 = qmul(q2, q3);
|
||||
qfree(q2);
|
||||
qfree(q3);
|
||||
q2 = qmul(c1->real, c2->real);
|
||||
q3 = qmul(c1->imag, c2->imag);
|
||||
q4 = qqadd(q2, q3);
|
||||
r->real = qsub(q2, q3);
|
||||
r->imag = qsub(q1, q4);
|
||||
qfree(q1);
|
||||
qfree(q2);
|
||||
qfree(q3);
|
||||
qfree(q4);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Square a complex number.
|
||||
*/
|
||||
COMPLEX *
|
||||
csquare(COMPLEX *c)
|
||||
{
|
||||
COMPLEX *r;
|
||||
NUMBER *q1, *q2;
|
||||
|
||||
if (ciszero(c))
|
||||
return clink(&_czero_);
|
||||
if (cisrunit(c))
|
||||
return clink(&_cone_);
|
||||
if (cisiunit(c))
|
||||
return clink(&_cnegone_);
|
||||
r = comalloc();
|
||||
if (cisreal(c)) {
|
||||
r->real = qsquare(c->real);
|
||||
return r;
|
||||
}
|
||||
if (cisimag(c)) {
|
||||
q1 = qsquare(c->imag);
|
||||
r->real = qneg(q1);
|
||||
qfree(q1);
|
||||
return r;
|
||||
}
|
||||
q1 = qsquare(c->real);
|
||||
q2 = qsquare(c->imag);
|
||||
r->real = qsub(q1, q2);
|
||||
qfree(q1);
|
||||
qfree(q2);
|
||||
q1 = qmul(c->real, c->imag);
|
||||
r->imag = qscale(q1, 1L);
|
||||
qfree(q1);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Divide two complex numbers.
|
||||
*/
|
||||
COMPLEX *
|
||||
cdiv(COMPLEX *c1, COMPLEX *c2)
|
||||
{
|
||||
COMPLEX *r;
|
||||
NUMBER *q1, *q2, *q3, *den;
|
||||
|
||||
if (ciszero(c2)) {
|
||||
math_error("Division by zero");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if ((c1->real == c2->real) && (c1->imag == c2->imag))
|
||||
return clink(&_cone_);
|
||||
r = comalloc();
|
||||
if (cisreal(c1) && cisreal(c2)) {
|
||||
r->real = qdiv(c1->real, c2->real);
|
||||
return r;
|
||||
}
|
||||
if (cisimag(c1) && cisimag(c2)) {
|
||||
r->real = qdiv(c1->imag, c2->imag);
|
||||
return r;
|
||||
}
|
||||
if (cisimag(c1) && cisreal(c2)) {
|
||||
r->imag = qdiv(c1->imag, c2->real);
|
||||
return r;
|
||||
}
|
||||
if (cisreal(c1) && cisimag(c2)) {
|
||||
q1 = qdiv(c1->real, c2->imag);
|
||||
r->imag = qneg(q1);
|
||||
qfree(q1);
|
||||
return r;
|
||||
}
|
||||
if (cisreal(c2)) {
|
||||
r->real = qdiv(c1->real, c2->real);
|
||||
r->imag = qdiv(c1->imag, c2->real);
|
||||
return r;
|
||||
}
|
||||
q1 = qsquare(c2->real);
|
||||
q2 = qsquare(c2->imag);
|
||||
den = qqadd(q1, q2);
|
||||
qfree(q1);
|
||||
qfree(q2);
|
||||
q1 = qmul(c1->real, c2->real);
|
||||
q2 = qmul(c1->imag, c2->imag);
|
||||
q3 = qqadd(q1, q2);
|
||||
qfree(q1);
|
||||
qfree(q2);
|
||||
r->real = qdiv(q3, den);
|
||||
qfree(q3);
|
||||
q1 = qmul(c1->real, c2->imag);
|
||||
q2 = qmul(c1->imag, c2->real);
|
||||
q3 = qsub(q2, q1);
|
||||
qfree(q1);
|
||||
qfree(q2);
|
||||
r->imag = qdiv(q3, den);
|
||||
qfree(q3);
|
||||
qfree(den);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Invert a complex number.
|
||||
*/
|
||||
COMPLEX *
|
||||
cinv(COMPLEX *c)
|
||||
{
|
||||
COMPLEX *r;
|
||||
NUMBER *q1, *q2, *den;
|
||||
|
||||
if (ciszero(c)) {
|
||||
math_error("Inverting zero");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
r = comalloc();
|
||||
if (cisreal(c)) {
|
||||
r->real = qinv(c->real);
|
||||
return r;
|
||||
}
|
||||
if (cisimag(c)) {
|
||||
q1 = qinv(c->imag);
|
||||
r->imag = qneg(q1);
|
||||
qfree(q1);
|
||||
return r;
|
||||
}
|
||||
q1 = qsquare(c->real);
|
||||
q2 = qsquare(c->imag);
|
||||
den = qqadd(q1, q2);
|
||||
qfree(q1);
|
||||
qfree(q2);
|
||||
r->real = qdiv(c->real, den);
|
||||
q1 = qdiv(c->imag, den);
|
||||
r->imag = qneg(q1);
|
||||
qfree(q1);
|
||||
qfree(den);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Negate a complex number.
|
||||
*/
|
||||
COMPLEX *
|
||||
cneg(COMPLEX *c)
|
||||
{
|
||||
COMPLEX *r;
|
||||
|
||||
if (ciszero(c))
|
||||
return clink(&_czero_);
|
||||
r = comalloc();
|
||||
if (!qiszero(c->real))
|
||||
r->real = qneg(c->real);
|
||||
if (!qiszero(c->imag))
|
||||
r->imag = qneg(c->imag);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Take the integer part of a complex number.
|
||||
* This means take the integer part of both components.
|
||||
*/
|
||||
COMPLEX *
|
||||
cint(COMPLEX *c)
|
||||
{
|
||||
COMPLEX *r;
|
||||
|
||||
if (cisint(c))
|
||||
return clink(c);
|
||||
r = comalloc();
|
||||
r->real = qint(c->real);
|
||||
r->imag = qint(c->imag);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Take the fractional part of a complex number.
|
||||
* This means take the fractional part of both components.
|
||||
*/
|
||||
COMPLEX *
|
||||
cfrac(COMPLEX *c)
|
||||
{
|
||||
COMPLEX *r;
|
||||
|
||||
if (cisint(c))
|
||||
return clink(&_czero_);
|
||||
r = comalloc();
|
||||
r->real = qfrac(c->real);
|
||||
r->imag = qfrac(c->imag);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Take the conjugate of a complex number.
|
||||
* This negates the complex part.
|
||||
*/
|
||||
COMPLEX *
|
||||
cconj(COMPLEX *c)
|
||||
{
|
||||
COMPLEX *r;
|
||||
|
||||
if (cisreal(c))
|
||||
return clink(c);
|
||||
r = comalloc();
|
||||
if (!qiszero(c->real))
|
||||
r->real = qlink(c->real);
|
||||
r->imag = qneg(c->imag);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the real part of a complex number.
|
||||
*/
|
||||
COMPLEX *
|
||||
creal(COMPLEX *c)
|
||||
{
|
||||
COMPLEX *r;
|
||||
|
||||
if (cisreal(c))
|
||||
return clink(c);
|
||||
r = comalloc();
|
||||
if (!qiszero(c->real))
|
||||
r->real = qlink(c->real);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the imaginary part of a complex number as a real.
|
||||
*/
|
||||
COMPLEX *
|
||||
cimag(COMPLEX *c)
|
||||
{
|
||||
COMPLEX *r;
|
||||
|
||||
if (cisreal(c))
|
||||
return clink(&_czero_);
|
||||
r = comalloc();
|
||||
r->real = qlink(c->imag);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add a real number to a complex number.
|
||||
*/
|
||||
COMPLEX *
|
||||
caddq(COMPLEX *c, NUMBER *q)
|
||||
{
|
||||
COMPLEX *r;
|
||||
|
||||
if (qiszero(q))
|
||||
return clink(c);
|
||||
r = comalloc();
|
||||
r->real = qqadd(c->real, q);
|
||||
r->imag = qlink(c->imag);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Subtract a real number from a complex number.
|
||||
*/
|
||||
COMPLEX *
|
||||
csubq(COMPLEX *c, NUMBER *q)
|
||||
{
|
||||
COMPLEX *r;
|
||||
|
||||
if (qiszero(q))
|
||||
return clink(c);
|
||||
r = comalloc();
|
||||
r->real = qsub(c->real, q);
|
||||
r->imag = qlink(c->imag);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Shift the components of a complex number left by the specified
|
||||
* number of bits. Negative values shift to the right.
|
||||
*/
|
||||
COMPLEX *
|
||||
cshift(COMPLEX *c, long n)
|
||||
{
|
||||
COMPLEX *r;
|
||||
|
||||
if (ciszero(c) || (n == 0))
|
||||
return clink(c);
|
||||
r = comalloc();
|
||||
r->real = qshift(c->real, n);
|
||||
r->imag = qshift(c->imag, n);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Scale a complex number by a power of two.
|
||||
*/
|
||||
COMPLEX *
|
||||
cscale(COMPLEX *c, long n)
|
||||
{
|
||||
COMPLEX *r;
|
||||
|
||||
if (ciszero(c) || (n == 0))
|
||||
return clink(c);
|
||||
r = comalloc();
|
||||
r->real = qscale(c->real, n);
|
||||
r->imag = qscale(c->imag, n);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Multiply a complex number by a real number.
|
||||
*/
|
||||
COMPLEX *
|
||||
cmulq(COMPLEX *c, NUMBER *q)
|
||||
{
|
||||
COMPLEX *r;
|
||||
|
||||
if (qiszero(q))
|
||||
return clink(&_czero_);
|
||||
if (qisone(q))
|
||||
return clink(c);
|
||||
if (qisnegone(q))
|
||||
return cneg(c);
|
||||
r = comalloc();
|
||||
r->real = qmul(c->real, q);
|
||||
r->imag = qmul(c->imag, q);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Divide a complex number by a real number.
|
||||
*/
|
||||
COMPLEX *
|
||||
cdivq(COMPLEX *c, NUMBER *q)
|
||||
{
|
||||
COMPLEX *r;
|
||||
|
||||
if (qiszero(q)) {
|
||||
math_error("Division by zero");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (qisone(q))
|
||||
return clink(c);
|
||||
if (qisnegone(q))
|
||||
return cneg(c);
|
||||
r = comalloc();
|
||||
r->real = qdiv(c->real, q);
|
||||
r->imag = qdiv(c->imag, q);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Construct a complex number given the real and imaginary components.
|
||||
*/
|
||||
COMPLEX *
|
||||
qqtoc(NUMBER *q1, NUMBER *q2)
|
||||
{
|
||||
COMPLEX *r;
|
||||
|
||||
if (qiszero(q1) && qiszero(q2))
|
||||
return clink(&_czero_);
|
||||
r = comalloc();
|
||||
if (!qiszero(q1))
|
||||
r->real = qlink(q1);
|
||||
if (!qiszero(q2))
|
||||
r->imag = qlink(q2);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Compare two complex numbers for equality, returning FALSE if they are equal,
|
||||
* and TRUE if they differ.
|
||||
*/
|
||||
BOOL
|
||||
ccmp(COMPLEX *c1, COMPLEX *c2)
|
||||
{
|
||||
BOOL i;
|
||||
|
||||
i = qcmp(c1->real, c2->real);
|
||||
if (!i)
|
||||
i = qcmp(c1->imag, c2->imag);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Compare two complex numbers and return a complex number with real and
|
||||
* imaginary parts -1, 0 or 1 indicating relative values of the real and
|
||||
* imaginary parts of the two numbers.
|
||||
*/
|
||||
COMPLEX *
|
||||
crel(COMPLEX *c1, COMPLEX *c2)
|
||||
{
|
||||
COMPLEX *c;
|
||||
|
||||
c = comalloc();
|
||||
c->real = itoq((long) qrel(c1->real, c2->real));
|
||||
c->imag = itoq((long) qrel(c1->imag, c2->imag));
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Allocate a new complex number.
|
||||
*/
|
||||
COMPLEX *
|
||||
comalloc(void)
|
||||
{
|
||||
COMPLEX *r;
|
||||
|
||||
r = (COMPLEX *) malloc(sizeof(COMPLEX));
|
||||
if (r == NULL) {
|
||||
math_error("Cannot allocate complex number");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
r->links = 1;
|
||||
r->real = qlink(&_qzero_);
|
||||
r->imag = qlink(&_qzero_);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Free a complex number.
|
||||
*/
|
||||
void
|
||||
comfree(COMPLEX *c)
|
||||
{
|
||||
if (--(c->links) > 0)
|
||||
return;
|
||||
qfree(c->real);
|
||||
qfree(c->imag);
|
||||
free(c);
|
||||
}
|
||||
|
||||
/* END CODE */
|
985
config.c
Normal file
985
config.c
Normal file
@@ -0,0 +1,985 @@
|
||||
/*
|
||||
* Copyright (c) 1995 David I. Bell
|
||||
* Permission is granted to use, distribute, or modify this source,
|
||||
* provided that this copyright notice remains intact.
|
||||
*
|
||||
* Configuration routines.
|
||||
*/
|
||||
|
||||
#include "calc.h"
|
||||
#include "token.h"
|
||||
#include "zrand.h"
|
||||
|
||||
|
||||
/*
|
||||
* Table of configuration types that can be set or read.
|
||||
*/
|
||||
NAMETYPE configs[] = {
|
||||
{"all", CONFIG_ALL},
|
||||
{"mode", CONFIG_MODE},
|
||||
{"display", CONFIG_DISPLAY},
|
||||
{"epsilon", CONFIG_EPSILON},
|
||||
/*epsilonprec -- tied to epsilon not a configuration type*/
|
||||
{"trace", CONFIG_TRACE},
|
||||
{"maxprint", CONFIG_MAXPRINT},
|
||||
{"mul2", CONFIG_MUL2},
|
||||
{"sq2", CONFIG_SQ2},
|
||||
{"pow2", CONFIG_POW2},
|
||||
{"redc2", CONFIG_REDC2},
|
||||
{"tilde", CONFIG_TILDE},
|
||||
{"tab", CONFIG_TAB},
|
||||
{"quomod", CONFIG_QUOMOD},
|
||||
{"quo", CONFIG_QUO},
|
||||
{"mod", CONFIG_MOD},
|
||||
{"sqrt", CONFIG_SQRT},
|
||||
{"appr", CONFIG_APPR},
|
||||
{"cfappr", CONFIG_CFAPPR},
|
||||
{"cfsim", CONFIG_CFSIM},
|
||||
{"outround", CONFIG_OUTROUND},
|
||||
{"round", CONFIG_ROUND},
|
||||
{"leadzero", CONFIG_LEADZERO},
|
||||
{"fullzero", CONFIG_FULLZERO},
|
||||
{"maxerr", CONFIG_MAXERR},
|
||||
{"prompt", CONFIG_PROMPT},
|
||||
{"more", CONFIG_MORE},
|
||||
{"random", CONFIG_RANDOM},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* configurations
|
||||
*/
|
||||
CONFIG oldstd = { /* backward compatible standard configuration */
|
||||
MODE_INITIAL, /* current output mode */
|
||||
20, /* current output digits for float or exp */
|
||||
NULL, /* loaded in at startup - default error for real functions */
|
||||
EPSILONPREC_DEFAULT, /* binary precision of epsilon */
|
||||
FALSE, /* tracing flags */
|
||||
MAXPRINT_DEFAULT, /* number of elements to print */
|
||||
MUL_ALG2, /* size of number to use multiply alg 2 */
|
||||
SQ_ALG2, /* size of number to use square alg 2 */
|
||||
POW_ALG2, /* size of modulus to use REDC for powers */
|
||||
REDC_ALG2, /* size of modulus to use REDC algorithm 2 */
|
||||
TRUE, /* ok to print a tilde on aproximations */
|
||||
TRUE, /* ok to print tab before numeric values */
|
||||
0, /* quomod() default rounding mode */
|
||||
2, /* quotent // default rounding mode */
|
||||
0, /* mod % default rounding mode */
|
||||
24, /* sqrt() default rounding mode */
|
||||
24, /* appr() default rounding mode */
|
||||
0, /* cfappr() default rounding mode */
|
||||
8, /* cfsim() default rounding mode */
|
||||
2, /* output default rounding mode */
|
||||
24, /* round()/bround() default rounding mode */
|
||||
FALSE, /* ok to print leading 0 before decimal pt */
|
||||
0, /* ok to print trailing 0's */
|
||||
MAXERRORCOUNT, /* max errors before abort */
|
||||
PROMPT1, /* normal prompt */
|
||||
PROMPT2, /* prompt when inside multi-line input */
|
||||
3 /* require 1 mod 4 and to pass ptest(newn,1) */
|
||||
};
|
||||
CONFIG newstd = { /* new non-backward compatible configuration */
|
||||
MODE_INITIAL, /* current output mode */
|
||||
10, /* current output digits for float or exp */
|
||||
NULL, /* loaded in at startup - default error for real functions */
|
||||
NEW_EPSILONPREC_DEFAULT, /* binary precision of epsilon */
|
||||
FALSE, /* tracing flags */
|
||||
MAXPRINT_DEFAULT, /* number of elements to print */
|
||||
MUL_ALG2, /* size of number to use multiply alg 2 */
|
||||
SQ_ALG2, /* size of number to use square alg 2 */
|
||||
POW_ALG2, /* size of modulus to use REDC for powers */
|
||||
REDC_ALG2, /* size of modulus to use REDC algorithm 2 */
|
||||
TRUE, /* ok to print a tilde on aproximations */
|
||||
TRUE, /* ok to print tab before numeric values */
|
||||
0, /* quomod() default rounding mode */
|
||||
0, /* quotent // default rounding mode */
|
||||
0, /* mod % default rounding mode */
|
||||
24, /* sqrt() default rounding mode */
|
||||
24, /* appr() default rounding mode */
|
||||
0, /* cfappr() default rounding mode */
|
||||
8, /* cfsim() default rounding mode */
|
||||
24, /* output default rounding mode */
|
||||
24, /* round()/bround() default rounding mode */
|
||||
TRUE, /* ok to print leading 0 before decimal pt */
|
||||
1, /* ok to print trailing 0's */
|
||||
MAXERRORCOUNT, /* max errors before abort */
|
||||
"; ", /* normal prompt */
|
||||
";; ", /* prompt when inside multi-line input */
|
||||
3 /* require 1 mod 4 and to pass ptest(newn,1) */
|
||||
};
|
||||
CONFIG *conf = NULL; /* loaded in at startup - current configuration */
|
||||
|
||||
|
||||
/*
|
||||
* Possible output modes.
|
||||
*/
|
||||
static NAMETYPE modes[] = {
|
||||
{"frac", MODE_FRAC},
|
||||
{"decimal", MODE_FRAC},
|
||||
{"dec", MODE_FRAC},
|
||||
{"int", MODE_INT},
|
||||
{"real", MODE_REAL},
|
||||
{"exp", MODE_EXP},
|
||||
{"hexadecimal", MODE_HEX},
|
||||
{"hex", MODE_HEX},
|
||||
{"octal", MODE_OCTAL},
|
||||
{"oct", MODE_OCTAL},
|
||||
{"binary", MODE_BINARY},
|
||||
{"bin", MODE_BINARY},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Possible binary config state values
|
||||
*/
|
||||
static NAMETYPE truth[] = {
|
||||
{"y", TRUE},
|
||||
{"n", FALSE},
|
||||
{"yes", TRUE},
|
||||
{"no", FALSE},
|
||||
{"set", TRUE},
|
||||
{"unset", FALSE},
|
||||
{"on", TRUE},
|
||||
{"off", FALSE},
|
||||
{"true", TRUE},
|
||||
{"false", FALSE},
|
||||
{"t", TRUE},
|
||||
{"f", FALSE},
|
||||
{"1", TRUE},
|
||||
{"0", FALSE},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* declate static functions
|
||||
*/
|
||||
static int modetype(char *name);
|
||||
static int truthtype(char *name);
|
||||
static char *modename(int type);
|
||||
|
||||
|
||||
/*
|
||||
* Given a string value which represents a configuration name, return
|
||||
* the configuration type for that string. Returns negative type if
|
||||
* the string is unknown.
|
||||
*
|
||||
* given:
|
||||
* name configuration name
|
||||
*/
|
||||
int
|
||||
configtype(char *name)
|
||||
{
|
||||
NAMETYPE *cp; /* current config pointer */
|
||||
|
||||
for (cp = configs; cp->name; cp++) {
|
||||
if (strcmp(cp->name, name) == 0)
|
||||
return cp->type;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Given the name of a mode, convert it to the internal format.
|
||||
* Returns -1 if the string is unknown.
|
||||
*
|
||||
* given:
|
||||
* name mode name
|
||||
*/
|
||||
static int
|
||||
modetype(char *name)
|
||||
{
|
||||
NAMETYPE *cp; /* current config pointer */
|
||||
|
||||
for (cp = modes; cp->name; cp++) {
|
||||
if (strcmp(cp->name, name) == 0)
|
||||
return cp->type;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Given the name of a truth value, convert it to a BOOL or -1.
|
||||
* Returns -1 if the string is unknown.
|
||||
*
|
||||
* given:
|
||||
* name mode name
|
||||
*/
|
||||
static int
|
||||
truthtype(char *name)
|
||||
{
|
||||
NAMETYPE *cp; /* current config pointer */
|
||||
|
||||
for (cp = truth; cp->name; cp++) {
|
||||
if (strcmp(cp->name, name) == 0)
|
||||
return cp->type;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Given the mode type, convert it to a string representing that mode.
|
||||
* Where there are multiple strings representing the same mode, the first
|
||||
* one in the table is used. Returns NULL if the node type is unknown.
|
||||
* The returned string cannot be modified.
|
||||
*/
|
||||
static char *
|
||||
modename(int type)
|
||||
{
|
||||
NAMETYPE *cp; /* current config pointer */
|
||||
|
||||
for (cp = modes; cp->name; cp++) {
|
||||
if (type == cp->type)
|
||||
return cp->name;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the specified configuration type to the specified value.
|
||||
* An error is generated if the type number or value is illegal.
|
||||
*/
|
||||
void
|
||||
setconfig(int type, VALUE *vp)
|
||||
{
|
||||
NUMBER *q;
|
||||
CONFIG *newconf; /* new configuration to set */
|
||||
long temp;
|
||||
char *p;
|
||||
|
||||
switch (type) {
|
||||
case CONFIG_ALL:
|
||||
newconf = NULL; /* firewall */
|
||||
if (vp->v_type == V_STR) {
|
||||
if (strcmp(vp->v_str, "oldstd") == 0) {
|
||||
newconf = &oldstd;
|
||||
} else if (strcmp(vp->v_str, "newstd") == 0) {
|
||||
newconf = &newstd;
|
||||
} else {
|
||||
math_error("CONFIG alias not oldstd or newstd");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
} else if (vp->v_type != V_CONFIG) {
|
||||
math_error("non-CONFIG for all");
|
||||
/*NOTREACHED*/
|
||||
} else {
|
||||
newconf = vp->v_config;
|
||||
}
|
||||
|
||||
/* free the current configuration */
|
||||
config_free(conf);
|
||||
|
||||
/* set the new configuration */
|
||||
conf = config_copy(newconf);
|
||||
break;
|
||||
|
||||
case CONFIG_TRACE:
|
||||
if (vp->v_type != V_NUM) {
|
||||
math_error("Non-numeric for trace");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
q = vp->v_num;
|
||||
temp = qtoi(q);
|
||||
if (qisfrac(q) || !zistiny(q->num) ||
|
||||
((unsigned long) temp > TRACE_MAX)) {
|
||||
math_error("Bad trace value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
conf->traceflags = (FLAG)temp;
|
||||
break;
|
||||
|
||||
case CONFIG_DISPLAY:
|
||||
if (vp->v_type != V_NUM) {
|
||||
math_error("Non-numeric for display");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
q = vp->v_num;
|
||||
temp = qtoi(q);
|
||||
if (qisfrac(q) || qisneg(q) || !zistiny(q->num))
|
||||
temp = -1;
|
||||
math_setdigits(temp);
|
||||
break;
|
||||
|
||||
case CONFIG_MODE:
|
||||
if (vp->v_type != V_STR) {
|
||||
math_error("Non-string for mode");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
temp = modetype(vp->v_str);
|
||||
if (temp < 0) {
|
||||
math_error("Unknown mode \"%s\"", vp->v_str);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
math_setmode((int) temp);
|
||||
break;
|
||||
|
||||
case CONFIG_EPSILON:
|
||||
if (vp->v_type != V_NUM) {
|
||||
math_error("Non-numeric for epsilon");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
setepsilon(vp->v_num);
|
||||
break;
|
||||
|
||||
case CONFIG_MAXPRINT:
|
||||
if (vp->v_type != V_NUM) {
|
||||
math_error("Non-numeric for maxprint");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
q = vp->v_num;
|
||||
temp = qtoi(q);
|
||||
if (qisfrac(q) || qisneg(q) || !zistiny(q->num))
|
||||
temp = -1;
|
||||
if (temp < 0) {
|
||||
math_error("Maxprint value is out of range");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
conf->maxprint = temp;
|
||||
break;
|
||||
|
||||
case CONFIG_MUL2:
|
||||
if (vp->v_type != V_NUM) {
|
||||
math_error("Non-numeric for mul2");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
q = vp->v_num;
|
||||
temp = qtoi(q);
|
||||
if (qisfrac(q) || qisneg(q))
|
||||
temp = -1;
|
||||
if (temp == 0)
|
||||
temp = MUL_ALG2;
|
||||
if (temp < 2) {
|
||||
math_error("Illegal mul2 value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
conf->mul2 = (int)temp;
|
||||
break;
|
||||
|
||||
case CONFIG_SQ2:
|
||||
if (vp->v_type != V_NUM) {
|
||||
math_error("Non-numeric for sq2");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
q = vp->v_num;
|
||||
temp = qtoi(q);
|
||||
if (qisfrac(q) || qisneg(q))
|
||||
temp = -1;
|
||||
if (temp == 0)
|
||||
temp = SQ_ALG2;
|
||||
if (temp < 2) {
|
||||
math_error("Illegal sq2 value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
conf->sq2 = (int)temp;
|
||||
break;
|
||||
|
||||
case CONFIG_POW2:
|
||||
if (vp->v_type != V_NUM) {
|
||||
math_error("Non-numeric for pow2");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
q = vp->v_num;
|
||||
temp = qtoi(q);
|
||||
if (qisfrac(q) || qisneg(q))
|
||||
temp = -1;
|
||||
if (temp == 0)
|
||||
temp = POW_ALG2;
|
||||
if (temp < 1) {
|
||||
math_error("Illegal pow2 value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
conf->pow2 = (int)temp;
|
||||
break;
|
||||
|
||||
case CONFIG_REDC2:
|
||||
if (vp->v_type != V_NUM) {
|
||||
math_error("Non-numeric for redc2");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
q = vp->v_num;
|
||||
temp = qtoi(q);
|
||||
if (qisfrac(q) || qisneg(q))
|
||||
temp = -1;
|
||||
if (temp == 0)
|
||||
temp = REDC_ALG2;
|
||||
if (temp < 1) {
|
||||
math_error("Illegal redc2 value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
conf->redc2 = (int)temp;
|
||||
break;
|
||||
|
||||
|
||||
case CONFIG_TILDE:
|
||||
if (vp->v_type == V_NUM) {
|
||||
q = vp->v_num;
|
||||
conf->tilde_ok = !qiszero(q);
|
||||
} else if (vp->v_type == V_STR) {
|
||||
temp = truthtype(vp->v_str);
|
||||
if (temp < 0) {
|
||||
math_error("Illegal truth value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
conf->tilde_ok = (int)temp;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONFIG_TAB:
|
||||
if (vp->v_type == V_NUM) {
|
||||
q = vp->v_num;
|
||||
conf->tab_ok = !qiszero(q);
|
||||
} else if (vp->v_type == V_STR) {
|
||||
temp = truthtype(vp->v_str);
|
||||
if (temp < 0) {
|
||||
math_error("Illegal truth value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
conf->tab_ok = (int)temp;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONFIG_QUOMOD:
|
||||
if (vp->v_type != V_NUM) {
|
||||
math_error("Non numeric for quomod");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
q = vp->v_num;
|
||||
temp = qtoi(q);
|
||||
if (qisfrac(q) || qisneg(q) || !zistiny(q->num)) {
|
||||
math_error("Illegal quomod parameter value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
conf->quomod = temp;
|
||||
break;
|
||||
|
||||
case CONFIG_QUO:
|
||||
if (vp->v_type != V_NUM) {
|
||||
math_error("Non numeric for quo");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
q = vp->v_num;
|
||||
temp = qtoi(q);
|
||||
if (qisfrac(q) || qisneg(q) || !zistiny(q->num)) {
|
||||
math_error("Illegal quo parameter value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
conf->quo = temp;
|
||||
break;
|
||||
|
||||
case CONFIG_MOD:
|
||||
if (vp->v_type != V_NUM) {
|
||||
math_error("Non numeric for mod");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
q = vp->v_num;
|
||||
temp = qtoi(q);
|
||||
if (qisfrac(q) || qisneg(q) || !zistiny(q->num)) {
|
||||
math_error("Illegal mod parameter value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
conf->mod = temp;
|
||||
break;
|
||||
|
||||
case CONFIG_SQRT:
|
||||
if (vp->v_type != V_NUM) {
|
||||
math_error("Non numeric for sqrt");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
q = vp->v_num;
|
||||
temp = qtoi(q);
|
||||
if (qisfrac(q) || qisneg(q) || !zistiny(q->num)) {
|
||||
math_error("Illegal sqrt parameter value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
conf->sqrt = temp;
|
||||
break;
|
||||
|
||||
case CONFIG_APPR:
|
||||
if (vp->v_type != V_NUM) {
|
||||
math_error("Non numeric for appr");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
q = vp->v_num;
|
||||
temp = qtoi(q);
|
||||
if (qisfrac(q) || qisneg(q) || !zistiny(q->num)) {
|
||||
math_error("Illegal appr parameter value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
conf->appr = temp;
|
||||
break;
|
||||
|
||||
case CONFIG_CFAPPR:
|
||||
if (vp->v_type != V_NUM) {
|
||||
math_error("Non numeric for cfappr");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
q = vp->v_num;
|
||||
temp = qtoi(q);
|
||||
if (qisfrac(q) || qisneg(q) || !zistiny(q->num)) {
|
||||
math_error("Illegal cfappr parameter value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
conf->cfappr = temp;
|
||||
break;
|
||||
|
||||
case CONFIG_CFSIM:
|
||||
if (vp->v_type != V_NUM) {
|
||||
math_error("Non numeric for cfsim");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
q = vp->v_num;
|
||||
temp = qtoi(q);
|
||||
if (qisfrac(q) || qisneg(q) || !zistiny(q->num)) {
|
||||
math_error("Illegal cfsim parameter value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
conf->cfsim = temp;
|
||||
break;
|
||||
|
||||
case CONFIG_OUTROUND:
|
||||
if (vp->v_type != V_NUM) {
|
||||
math_error("Non numeric for outround");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
q = vp->v_num;
|
||||
temp = qtoi(q);
|
||||
if (qisfrac(q) || qisneg(q) || !zistiny(q->num)) {
|
||||
math_error("Illegal output parameter value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
conf->outround = temp;
|
||||
break;
|
||||
|
||||
case CONFIG_ROUND:
|
||||
if (vp->v_type != V_NUM) {
|
||||
math_error("Non numeric for round");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
q = vp->v_num;
|
||||
temp = qtoi(q);
|
||||
if (qisfrac(q) || qisneg(q) || !zistiny(q->num)) {
|
||||
math_error("Illegal output parameter value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
conf->round = temp;
|
||||
break;
|
||||
|
||||
case CONFIG_LEADZERO:
|
||||
if (vp->v_type == V_NUM) {
|
||||
q = vp->v_num;
|
||||
conf->leadzero = !qiszero(q);
|
||||
} else if (vp->v_type == V_STR) {
|
||||
temp = truthtype(vp->v_str);
|
||||
if (temp < 0) { {
|
||||
math_error("Illegal truth value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
}
|
||||
conf->leadzero = (int)temp;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONFIG_FULLZERO:
|
||||
if (vp->v_type == V_NUM) {
|
||||
q = vp->v_num;
|
||||
conf->fullzero = !qiszero(q);
|
||||
} else if (vp->v_type == V_STR) {
|
||||
temp = truthtype(vp->v_str);
|
||||
if (temp < 0) { {
|
||||
math_error("Illegal truth value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
}
|
||||
conf->fullzero = (int)temp;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONFIG_MAXERR:
|
||||
if (vp->v_type != V_NUM) {
|
||||
math_error("Non-numeric for maxerr");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
q = vp->v_num;
|
||||
temp = qtoi(q);
|
||||
if (qisfrac(q) || qisneg(q) || !zistiny(q->num))
|
||||
temp = -1;
|
||||
if (temp < 0) {
|
||||
math_error("Maxerr value is out of range");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
conf->maxerrorcount = temp;
|
||||
break;
|
||||
|
||||
case CONFIG_PROMPT:
|
||||
if (vp->v_type != V_STR) {
|
||||
math_error("Non-string for prompt");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
p = (char *)malloc(strlen(vp->v_str) + 1);
|
||||
if (p == NULL) {
|
||||
math_error("Cannot duplicate new prompt");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
strcpy(p, vp->v_str);
|
||||
free(conf->prompt1);
|
||||
conf->prompt1 = p;
|
||||
break;
|
||||
|
||||
case CONFIG_MORE:
|
||||
if (vp->v_type != V_STR) {
|
||||
math_error("Non-string for more prompt");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
p = (char *)malloc(strlen(vp->v_str) + 1);
|
||||
if (p == NULL) {
|
||||
math_error("Cannot duplicate new more prompt");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
strcpy(p, vp->v_str);
|
||||
free(conf->prompt2);
|
||||
conf->prompt2 = p;
|
||||
break;
|
||||
|
||||
case CONFIG_RANDOM:
|
||||
if (vp->v_type != V_NUM) {
|
||||
math_error("Non-numeric for random config value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
q = vp->v_num;
|
||||
temp = qtoi(q);
|
||||
if (qisfrac(q) || qisneg(q) || !zistiny(q->num))
|
||||
temp = -1;
|
||||
if (temp < BLUM_CFG_MIN || temp > BLUM_CFG_MAX) {
|
||||
math_error("Random config value is out of range");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
conf->random = temp;
|
||||
break;
|
||||
|
||||
default:
|
||||
math_error("Setting illegal config parameter");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* config_copy - copy the configuration from one value to another
|
||||
*
|
||||
* given:
|
||||
* src copy this configuration
|
||||
*
|
||||
* returns:
|
||||
* prointer to the configuration copy
|
||||
*/
|
||||
CONFIG *
|
||||
config_copy(CONFIG *src)
|
||||
{
|
||||
CONFIG *dest; /* the new CONFIG to return */
|
||||
|
||||
/*
|
||||
* firewall
|
||||
*/
|
||||
if (src == NULL || src->epsilon == NULL || src->prompt1 == NULL ||
|
||||
src->prompt2 == NULL) {
|
||||
math_error("bad CONFIG value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* malloc the storage
|
||||
*/
|
||||
dest = (CONFIG *)malloc(sizeof(CONFIG));
|
||||
if (dest == NULL) {
|
||||
math_error("malloc of CONFIG failed");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* copy over the values
|
||||
*/
|
||||
*dest = *src;
|
||||
|
||||
/*
|
||||
* clone the pointer values
|
||||
*/
|
||||
dest->epsilon = qlink(src->epsilon);
|
||||
dest->prompt1 = (char *)malloc(strlen(src->prompt1)+1);
|
||||
if (dest->prompt1 == NULL) {
|
||||
math_error("cannot dup prompt1 for new CONFIG value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
strcpy(dest->prompt1, src->prompt1);
|
||||
dest->prompt2 = (char *)malloc(strlen(src->prompt2)+1);
|
||||
if (dest->prompt2 == NULL) {
|
||||
math_error("cannot dup prompt2 for new CONFIG value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
strcpy(dest->prompt2, src->prompt2);
|
||||
|
||||
/*
|
||||
* return the new value
|
||||
*/
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* config_free - free a CONFIG value
|
||||
*
|
||||
* given:
|
||||
* cfg the CONFIG value to free
|
||||
*/
|
||||
void
|
||||
config_free(CONFIG *cfg)
|
||||
{
|
||||
/*
|
||||
* firewall
|
||||
*/
|
||||
if (cfg == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* free prointer values
|
||||
*/
|
||||
if (cfg->epsilon != NULL) {
|
||||
qfree(cfg->epsilon);
|
||||
}
|
||||
if (cfg->prompt1 != NULL) {
|
||||
free(cfg->prompt1);
|
||||
}
|
||||
if (cfg->prompt2 != NULL) {
|
||||
free(cfg->prompt2);
|
||||
}
|
||||
|
||||
/*
|
||||
* free the CONFIG value itself
|
||||
*/
|
||||
free(cfg);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* config_value - return a CONFIG element as a value
|
||||
*
|
||||
* given:
|
||||
* cfg CONFIG from which an element will be returned
|
||||
* type the type of CONFIG element to print
|
||||
* ret where to return the value
|
||||
*
|
||||
* returns:
|
||||
* ret points to the VALUE returned
|
||||
*/
|
||||
void
|
||||
config_value(CONFIG *cfg, int type, VALUE *vp)
|
||||
{
|
||||
long i=0;
|
||||
|
||||
/*
|
||||
* firewall
|
||||
*/
|
||||
if (cfg == NULL || cfg->epsilon == NULL || cfg->prompt1 == NULL ||
|
||||
cfg->prompt2 == NULL) {
|
||||
math_error("bad CONFIG value");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* convert element to value
|
||||
*/
|
||||
vp->v_type = V_NUM;
|
||||
switch (type) {
|
||||
case CONFIG_ALL:
|
||||
vp->v_type = V_CONFIG;
|
||||
vp->v_config = config_copy(conf);
|
||||
return;
|
||||
|
||||
case CONFIG_TRACE:
|
||||
i = cfg->traceflags;
|
||||
break;
|
||||
|
||||
case CONFIG_DISPLAY:
|
||||
i = cfg->outdigits;
|
||||
break;
|
||||
|
||||
case CONFIG_MODE:
|
||||
vp->v_type = V_STR;
|
||||
vp->v_subtype = V_STRLITERAL;
|
||||
vp->v_str = modename(cfg->outmode);
|
||||
return;
|
||||
|
||||
case CONFIG_EPSILON:
|
||||
vp->v_num = qlink(cfg->epsilon);
|
||||
return;
|
||||
|
||||
case CONFIG_MAXPRINT:
|
||||
i = cfg->maxprint;
|
||||
break;
|
||||
|
||||
case CONFIG_MUL2:
|
||||
i = cfg->mul2;
|
||||
break;
|
||||
|
||||
case CONFIG_SQ2:
|
||||
i = cfg->sq2;
|
||||
break;
|
||||
|
||||
case CONFIG_POW2:
|
||||
i = cfg->pow2;
|
||||
break;
|
||||
|
||||
case CONFIG_REDC2:
|
||||
i = cfg->redc2;
|
||||
break;
|
||||
|
||||
case CONFIG_TILDE:
|
||||
i = cfg->tilde_ok;
|
||||
break;
|
||||
|
||||
case CONFIG_TAB:
|
||||
i = cfg->tab_ok;
|
||||
break;
|
||||
|
||||
case CONFIG_QUOMOD:
|
||||
i = cfg->quomod;
|
||||
break;
|
||||
|
||||
case CONFIG_QUO:
|
||||
i = cfg->quo;
|
||||
break;
|
||||
|
||||
case CONFIG_MOD:
|
||||
i = cfg->mod;
|
||||
break;
|
||||
|
||||
case CONFIG_SQRT:
|
||||
i = cfg->sqrt;
|
||||
break;
|
||||
|
||||
case CONFIG_APPR:
|
||||
i = cfg->appr;
|
||||
break;
|
||||
|
||||
case CONFIG_CFAPPR:
|
||||
i = cfg->cfappr;
|
||||
break;
|
||||
|
||||
case CONFIG_CFSIM:
|
||||
i = cfg->cfsim;
|
||||
break;
|
||||
|
||||
case CONFIG_OUTROUND:
|
||||
i = cfg->outround;
|
||||
break;
|
||||
|
||||
case CONFIG_ROUND:
|
||||
i = cfg->round;
|
||||
break;
|
||||
|
||||
case CONFIG_LEADZERO:
|
||||
i = cfg->leadzero;
|
||||
break;
|
||||
|
||||
case CONFIG_FULLZERO:
|
||||
i = cfg->fullzero;
|
||||
break;
|
||||
|
||||
case CONFIG_MAXERR:
|
||||
i = cfg->maxerrorcount;
|
||||
break;
|
||||
|
||||
case CONFIG_PROMPT:
|
||||
vp->v_type = V_STR;
|
||||
vp->v_subtype = V_STRLITERAL;
|
||||
vp->v_str = cfg->prompt1;
|
||||
return;
|
||||
|
||||
case CONFIG_MORE:
|
||||
vp->v_type = V_STR;
|
||||
vp->v_subtype = V_STRLITERAL;
|
||||
vp->v_str = cfg->prompt2;
|
||||
return;
|
||||
|
||||
case CONFIG_RANDOM:
|
||||
i = cfg->random;
|
||||
break;
|
||||
|
||||
default:
|
||||
math_error("Getting illegal CONFIG element");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* if we got this far, we have a V_NUM in i
|
||||
*/
|
||||
vp->v_num = itoq(i);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* config_cmp - compare two CONFIG states
|
||||
*
|
||||
* given:
|
||||
* cfg1 - 1st CONFIG to compare
|
||||
* cfg2 - 2nd CONFIG to compare
|
||||
*
|
||||
* return:
|
||||
* TRUE if configurations differ
|
||||
*/
|
||||
BOOL
|
||||
config_cmp(CONFIG *cfg1, CONFIG *cfg2)
|
||||
{
|
||||
/*
|
||||
* firewall
|
||||
*/
|
||||
if (cfg1 == NULL || cfg1->epsilon == NULL || cfg1->prompt1 == NULL ||
|
||||
cfg1->prompt2 == NULL) {
|
||||
math_error("CONFIG #1 value is invaid");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (cfg2 == NULL || cfg2->epsilon == NULL || cfg2->prompt1 == NULL ||
|
||||
cfg2->prompt2 == NULL) {
|
||||
math_error("CONFIG #2 value is invaid");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* compare
|
||||
*/
|
||||
return cfg1->traceflags != cfg2->traceflags ||
|
||||
cfg1->outdigits != cfg2->outdigits ||
|
||||
cfg1->outmode != cfg2->outmode ||
|
||||
qcmp(cfg1->epsilon, cfg2->epsilon) ||
|
||||
cfg1->epsilonprec != cfg2->epsilonprec ||
|
||||
cfg1->maxprint != cfg2->maxprint ||
|
||||
cfg1->mul2 != cfg2->mul2 ||
|
||||
cfg1->sq2 != cfg2->sq2 ||
|
||||
cfg1->pow2 != cfg2->pow2 ||
|
||||
cfg1->redc2 != cfg2->redc2 ||
|
||||
cfg1->tilde_ok != cfg2->tilde_ok ||
|
||||
cfg1->tab_ok != cfg2->tab_ok ||
|
||||
cfg1->quomod != cfg2->quomod ||
|
||||
cfg1->quo != cfg2->quo ||
|
||||
cfg1->mod != cfg2->mod ||
|
||||
cfg1->sqrt != cfg2->sqrt ||
|
||||
cfg1->appr != cfg2->appr ||
|
||||
cfg1->cfappr != cfg2->cfappr ||
|
||||
cfg1->cfsim != cfg2->cfsim ||
|
||||
cfg1->outround != cfg2->outround ||
|
||||
cfg1->round != cfg2->round ||
|
||||
cfg1->leadzero != cfg2->leadzero ||
|
||||
cfg1->fullzero != cfg2->fullzero ||
|
||||
cfg1->maxerrorcount != cfg2->maxerrorcount ||
|
||||
strcmp(cfg1->prompt1, cfg2->prompt1) != 0 ||
|
||||
strcmp(cfg1->prompt2, cfg2->prompt2) != 0 ||
|
||||
cfg1->random != cfg2->random;
|
||||
}
|
143
config.h
Normal file
143
config.h
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (c) 1995 by Landon Curt Noll. All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright, this permission notice and text
|
||||
* this comment, and the disclaimer below appear in all of the following:
|
||||
*
|
||||
* supporting documentation
|
||||
* source copies
|
||||
* source works derived from this source
|
||||
* binaries derived from this source or from derived source
|
||||
*
|
||||
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
||||
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Prior to calc 2.9.3t9, these routines existed as a calc library called
|
||||
* cryrand.cal. They have been rewritten in C for performance as well
|
||||
* as to make them available directly from libcalc.a.
|
||||
*
|
||||
* Comments, suggestions, bug fixes and questions about these routines
|
||||
* are welcome. Send EMail to the address given below.
|
||||
*
|
||||
* Happy bit twiddling,
|
||||
*
|
||||
* Landon Curt Noll
|
||||
*
|
||||
* chongo@toad.com
|
||||
* ...!{pyramid,sun,uunet}!hoptoad!chongo
|
||||
*
|
||||
* chongo was here /\../\
|
||||
*/
|
||||
|
||||
#if !defined(CONFIG_H)
|
||||
#define CONFIG_H
|
||||
|
||||
#include "qmath.h"
|
||||
|
||||
|
||||
/*
|
||||
* configuration element types
|
||||
*/
|
||||
#define CONFIG_ALL 0 /* not a real configuration parameter */
|
||||
#define CONFIG_MODE 1 /* types of configuration parameters */
|
||||
#define CONFIG_DISPLAY 2
|
||||
#define CONFIG_EPSILON 3
|
||||
#define CONFIG_EPSILONPREC 3 /* not a real type -- tied to CONFIG_EPSILON */
|
||||
#define CONFIG_TRACE 4
|
||||
#define CONFIG_MAXPRINT 5
|
||||
#define CONFIG_MUL2 6
|
||||
#define CONFIG_SQ2 7
|
||||
#define CONFIG_POW2 8
|
||||
#define CONFIG_REDC2 9
|
||||
#define CONFIG_TILDE 10
|
||||
#define CONFIG_TAB 11
|
||||
#define CONFIG_QUOMOD 12
|
||||
#define CONFIG_QUO 13
|
||||
#define CONFIG_MOD 14
|
||||
#define CONFIG_SQRT 15
|
||||
#define CONFIG_APPR 16
|
||||
#define CONFIG_CFAPPR 17
|
||||
#define CONFIG_CFSIM 18
|
||||
#define CONFIG_OUTROUND 19
|
||||
#define CONFIG_ROUND 20
|
||||
#define CONFIG_LEADZERO 21
|
||||
#define CONFIG_FULLZERO 22
|
||||
#define CONFIG_MAXERR 23
|
||||
#define CONFIG_PROMPT 24
|
||||
#define CONFIG_MORE 25
|
||||
#define CONFIG_RANDOM 26
|
||||
|
||||
|
||||
/*
|
||||
* config defult symbols
|
||||
*/
|
||||
#define DISPLAY_DEFAULT 20 /* default digits for float display */
|
||||
#define EPSILON_DEFAULT "1e-20" /* allowed error for float calculations */
|
||||
#define EPSILONPREC_DEFAULT 67 /* 67 ==> 2^-67 <= EPSILON_DEFAULT < 2^-66 */
|
||||
#define NEW_EPSILON_DEFAULT "1e-10" /* newstd EPSILON_DEFAULT */
|
||||
#define NEW_EPSILONPREC_DEFAULT 34 /* 34 ==> 2^-34 <= 1e-10 < 2^-33 */
|
||||
#define MAXPRINT_DEFAULT 16 /* default number of elements printed */
|
||||
#define MAXERRORCOUNT 20 /* default max errors before an abort */
|
||||
|
||||
|
||||
/*
|
||||
* configuration object
|
||||
*/
|
||||
struct config {
|
||||
int outmode; /* current output mode */
|
||||
long outdigits; /* current output digits for float or exp */
|
||||
NUMBER *epsilon; /* default error for real functions */
|
||||
long epsilonprec; /* epsilon binary precision (tied to epsilon) */
|
||||
FLAG traceflags; /* tracing flags */
|
||||
long maxprint; /* number of elements to print */
|
||||
LEN mul2; /* size of number to use multiply algorithm 2 */
|
||||
LEN sq2; /* size of number to use square algorithm 2 */
|
||||
LEN pow2; /* size of modulus to use REDC for powers */
|
||||
LEN redc2; /* size of modulus to use REDC algorithm 2 */
|
||||
int tilde_ok; /* ok to print a tilde on aproximations */
|
||||
int tab_ok; /* ok to print tab before numeric values */
|
||||
long quomod; /* quomod() default rounding mode */
|
||||
long quo; /* quotent // default rounding mode */
|
||||
long mod; /* mod % default rounding mode */
|
||||
long sqrt; /* sqrt() default rounding mode */
|
||||
long appr; /* appr() default rounding mode */
|
||||
long cfappr; /* cfappr() default rounding mode */
|
||||
long cfsim; /* cfsim() default rounding mode */
|
||||
long outround; /* output default rounding mode */
|
||||
long round; /* round()/bround() default rounding mode */
|
||||
int leadzero; /* ok to print leading 0 before decimal pt */
|
||||
int fullzero; /* ok to print trailing 0's -- XXX ??? */
|
||||
long maxerrorcount; /* max errors before abort */
|
||||
char *prompt1; /* normal prompt */
|
||||
char *prompt2; /* prompt when inside multi-line input */
|
||||
int random; /* random mode */
|
||||
};
|
||||
typedef struct config CONFIG;
|
||||
|
||||
|
||||
/*
|
||||
* global configuration states and aliases
|
||||
*/
|
||||
extern CONFIG *conf; /* current configuration */
|
||||
extern CONFIG oldstd; /* backward compatible standard configuration */
|
||||
extern CONFIG newstd; /* new non-backward compatible configuration */
|
||||
|
||||
|
||||
/*
|
||||
* configuration functions
|
||||
*/
|
||||
extern CONFIG *config_copy(CONFIG *src);
|
||||
extern void config_free(CONFIG *cfg);
|
||||
extern void config_print(CONFIG *cfg);
|
||||
extern BOOL config_cmp(CONFIG *cfg1, CONFIG *cfg2);
|
||||
extern int configtype(char *name);
|
||||
|
||||
|
||||
#endif
|
113
const.c
Normal file
113
const.c
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 1993 David I. Bell
|
||||
* Permission is granted to use, distribute, or modify this source,
|
||||
* provided that this copyright notice remains intact.
|
||||
*
|
||||
* Constant number storage module.
|
||||
*/
|
||||
|
||||
#include "calc.h"
|
||||
|
||||
#define CONSTALLOCSIZE 400 /* number of constants to allocate */
|
||||
|
||||
|
||||
static long constcount; /* number of constants defined */
|
||||
static long constavail; /* number of constants available */
|
||||
static NUMBER **consttable; /* table of constants */
|
||||
|
||||
|
||||
/*
|
||||
* Read in a constant number and add it to the table of constant numbers,
|
||||
* creating a new entry if necessary. The incoming number is a string
|
||||
* value which must have a correct format, otherwise an undefined number
|
||||
* will result. Returns the index of the number in the constant table.
|
||||
* Returns zero if the number could not be saved.
|
||||
*
|
||||
* given:
|
||||
* str string representation of number
|
||||
*/
|
||||
long
|
||||
addnumber(char *str)
|
||||
{
|
||||
NUMBER *q;
|
||||
|
||||
q = str2q(str);
|
||||
if (q == NULL)
|
||||
return 0;
|
||||
return addqconstant(q);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add a particular number to the constant table.
|
||||
* Returns the index of the number in the constant table, or zero
|
||||
* if the number could not be saved. The incoming number if freed
|
||||
* if it is already in the table.
|
||||
*
|
||||
* XXX - we should hash the constant table
|
||||
*
|
||||
* given:
|
||||
* q number to be added
|
||||
*/
|
||||
long
|
||||
addqconstant(NUMBER *q)
|
||||
{
|
||||
register NUMBER **tp; /* pointer to current number */
|
||||
register NUMBER *t; /* number being tested */
|
||||
long index; /* index into constant table */
|
||||
long numlen; /* numerator length */
|
||||
long denlen; /* denominator length */
|
||||
HALF numlow; /* bottom value of numerator */
|
||||
HALF denlow; /* bottom value of denominator */
|
||||
|
||||
numlen = q->num.len;
|
||||
denlen = q->den.len;
|
||||
numlow = q->num.v[0];
|
||||
denlow = q->den.v[0];
|
||||
tp = &consttable[1];
|
||||
for (index = 1; index <= constcount; index++) {
|
||||
t = *tp++;
|
||||
if ((numlen != t->num.len) || (numlow != t->num.v[0]))
|
||||
continue;
|
||||
if ((denlen != t->den.len) || (denlow != t->den.v[0]))
|
||||
continue;
|
||||
if (q->num.sign != t->num.sign)
|
||||
continue;
|
||||
if (qcmp(q, t) == 0) {
|
||||
qfree(q);
|
||||
return index;
|
||||
}
|
||||
}
|
||||
if (constavail <= 0) {
|
||||
if (consttable == NULL) {
|
||||
tp = (NUMBER **)
|
||||
malloc(sizeof(NUMBER *) * (CONSTALLOCSIZE + 1));
|
||||
*tp = NULL;
|
||||
} else
|
||||
tp = (NUMBER **) realloc((char *) consttable,
|
||||
sizeof(NUMBER *) * (constcount+CONSTALLOCSIZE + 1));
|
||||
if (tp == NULL)
|
||||
return 0;
|
||||
consttable = tp;
|
||||
constavail = CONSTALLOCSIZE;
|
||||
}
|
||||
constavail--;
|
||||
constcount++;
|
||||
consttable[constcount] = q;
|
||||
return constcount;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the value of a constant number given its index.
|
||||
* Returns address of the number, or NULL if the index is illegal.
|
||||
*/
|
||||
NUMBER *
|
||||
constvalue(unsigned long index)
|
||||
{
|
||||
if ((index <= 0) || (index > constcount))
|
||||
return NULL;
|
||||
return consttable[index];
|
||||
}
|
||||
|
||||
/* END CODE */
|
78
endian.c
Normal file
78
endian.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* endian - Determine the byte order of a long on your machine.
|
||||
*
|
||||
* Big Endian: Amdahl, 68k, Pyramid, Mips, Sparc, ...
|
||||
* Little Endian: Vax, 32k, Spim (Dec Mips), i386, i486, ...
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1993 by Landon Curt Noll. All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright, this permission notice and text
|
||||
* this comment, and the disclaimer below appear in all of the following:
|
||||
*
|
||||
* supporting documentation
|
||||
* source copies
|
||||
* source works derived from this source
|
||||
* binaries derived from this source or from derived source
|
||||
*
|
||||
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
||||
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* chongo was here /\../\
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "have_unistd.h"
|
||||
#if defined(HAVE_UNISTD_H)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/* byte order array */
|
||||
char byte[8] = { (char)0x12, (char)0x36, (char)0x48, (char)0x59,
|
||||
(char)0x01, (char)0x23, (char)0x45, (char)0x67 };
|
||||
|
||||
MAIN
|
||||
main(void)
|
||||
{
|
||||
/* pointers into the byte order array */
|
||||
int *intp = (int *)byte;
|
||||
#if defined(DEBUG)
|
||||
short *shortp = (short *)byte;
|
||||
long *longp = (long *)byte;
|
||||
|
||||
printf("byte: %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
byte[0], byte[1], byte[2], byte[3],
|
||||
byte[4], byte[5], byte[6], byte[7]);
|
||||
printf("short: %04x %04x %04x %04x\n",
|
||||
shortp[0], shortp[1], shortp[2], shortp[3]);
|
||||
printf("int: %08x %08x\n",
|
||||
intp[0], intp[1]);
|
||||
printf("long: %08x %08x\n",
|
||||
longp[0], longp[1]);
|
||||
#endif
|
||||
|
||||
/* Print the standard <machine/endian.h> defines */
|
||||
printf("#define BIG_ENDIAN\t4321\n");
|
||||
printf("#define LITTLE_ENDIAN\t1234\n");
|
||||
|
||||
/* Determine byte order */
|
||||
if (intp[0] == 0x12364859) {
|
||||
/* Most Significant Byte first */
|
||||
printf("#define BYTE_ORDER\tBIG_ENDIAN\n");
|
||||
} else if (intp[0] == 0x59483612) {
|
||||
/* Least Significant Byte first */
|
||||
printf("#define BYTE_ORDER\tLITTLE_ENDIAN\n");
|
||||
} else {
|
||||
fprintf(stderr, "Unknown int Byte Order, set BYTE_ORDER in Makefile\n");
|
||||
exit(1);
|
||||
}
|
||||
exit(0);
|
||||
}
|
60
file.h
Normal file
60
file.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 1996 David I. Bell
|
||||
* Permission is granted to use, distribute, or modify this source,
|
||||
* provided that this copyright notice remains intact.
|
||||
*
|
||||
* File I/O routines callable by users.
|
||||
*/
|
||||
|
||||
#include "have_fpos.h"
|
||||
|
||||
|
||||
/*
|
||||
* Definition of opened files.
|
||||
*/
|
||||
typedef struct {
|
||||
FILEID id; /* id to identify this file */
|
||||
FILE *fp; /* real file structure for I/O */
|
||||
dev_t dev; /* file device */
|
||||
ino_t inode; /* file inode */
|
||||
char *name; /* file name */
|
||||
BOOL reading; /* TRUE if opened for reading */
|
||||
BOOL writing; /* TRUE if opened for writing */
|
||||
char action; /* most recent use for 'r', 'w' or 0 */
|
||||
char mode[3]; /* open mode */
|
||||
} FILEIO;
|
||||
|
||||
|
||||
/*
|
||||
* fgetpos/fsetpos vs fseek/ftell interface
|
||||
*
|
||||
* f_seek_set(FILE *stream, FILEPOS *loc)
|
||||
* Seek loc bytes from the beginning of the open file, stream.
|
||||
*
|
||||
* f_tell(FILE *stream, FILEPOS *loc)
|
||||
* Set loc to bytes from the beinning of the open file, stream.
|
||||
*
|
||||
* We assume that if your system does not have fgetpos/fsetpos,
|
||||
* then it will have a FILEPOS that is a scalar type (e.g., long).
|
||||
* Some obscure systems without fgetpos/fsetpos may not have a simple
|
||||
* scalar type. In these cases the f_tell macro below will fail.
|
||||
*/
|
||||
#if defined(HAVE_FPOS)
|
||||
|
||||
#define f_seek_set(stream, loc) fsetpos((FILE*)(stream), (FILEPOS*)(loc))
|
||||
#define f_tell(stream, loc) fgetpos((FILE*)(stream), (FILEPOS*)(loc))
|
||||
|
||||
#else
|
||||
|
||||
#define f_seek_set(stream, loc) \
|
||||
fseek((FILE*)(stream), *(FILEPOS*)(loc), SEEK_SET)
|
||||
#define f_tell(stream, loc) (*((FILEPOS*)(loc)) = ftell((FILE*)(stream)))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* external functions
|
||||
*/
|
||||
extern int fgetposid(FILEID id, FILEPOS *ptr);
|
||||
extern int fsetposid(FILEID id, FILEPOS *ptr);
|
212
fposval.c
Normal file
212
fposval.c
Normal file
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* fposval - Determine information about the file position type
|
||||
*
|
||||
* The include file have_pos.h, as built during the make process will
|
||||
* define the type FILEPOS as the type used to describe file positions.
|
||||
* We will print information regarding the size and byte order
|
||||
* of this definition.
|
||||
*
|
||||
* The stat system call returns a stat structure. One of the elements
|
||||
* of the stat structure is the st_size element. We will print information
|
||||
* regarding the size and byte order of st_size.
|
||||
*
|
||||
* We will #define of 8 symbols:
|
||||
*
|
||||
* FILEPOS_BITS length in bits of the type FILEPOS
|
||||
* SWAP_HALF_IN_FILEPOS will copy/swap FILEPOS into an HALF array
|
||||
* STSIZE_BITS length in bits of the st_size stat element
|
||||
* SWAP_HALF_IN_STSIZE will copy/swap st_size into an HALF array
|
||||
* DEV_BITS length in bits of the st_dev stat element
|
||||
* SWAP_HALF_IN_DEV will copy/swap st_dev into an HALF array
|
||||
* INODE_BITS length in bits of the st_ino stat element
|
||||
* SWAP_HALF_IN_INODE will copy/swap st_ino into an HALF array
|
||||
*
|
||||
* With regards to 'will copy/swap ... into an HALF array'. Such macros
|
||||
* will either be a copy or a copy with HALFs swapped depending on the
|
||||
* Endian order of the hardware.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1996 by Landon Curt Noll. All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright, this permission notice and text
|
||||
* this comment, and the disclaimer below appear in all of the following:
|
||||
*
|
||||
* supporting documentation
|
||||
* source copies
|
||||
* source works derived from this source
|
||||
* binaries derived from this source or from derived source
|
||||
*
|
||||
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
||||
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* chongo was here /\../\
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "have_fpos.h"
|
||||
#include "endian_calc.h"
|
||||
|
||||
char *program; /* our name */
|
||||
|
||||
MAIN
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int stsizelen; /* bit length of st_size in buf */
|
||||
int fileposlen; /* bit length of FILEPOS */
|
||||
int devlen; /* bit length of st_dev in buf */
|
||||
int inodelen; /* bit length of st_ino in buf */
|
||||
struct stat buf; /* file status */
|
||||
|
||||
/*
|
||||
* parse args
|
||||
*/
|
||||
program = argv[0];
|
||||
|
||||
/*
|
||||
* print the file position information
|
||||
*/
|
||||
fileposlen = sizeof(FILEPOS)*8;
|
||||
printf("#undef FILEPOS_BITS\n");
|
||||
printf("#define FILEPOS_BITS %d\n", fileposlen);
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
/*
|
||||
* Big Endian
|
||||
*/
|
||||
if (fileposlen == 64) {
|
||||
printf("#define SWAP_HALF_IN_FILEPOS(dest, src)\t\t%s\n",
|
||||
"SWAP_HALF_IN_B64(dest, src)");
|
||||
} else if (fileposlen == 32) {
|
||||
printf("#define SWAP_HALF_IN_FILEPOS(dest, src)\t\t%s\n",
|
||||
"SWAP_HALF_IN_B32(dest, src)");
|
||||
} else {
|
||||
fprintf(stderr, "%s: unexpected FILEPOS bit size: %d\n",
|
||||
program, fileposlen);
|
||||
exit(1);
|
||||
}
|
||||
#else /* BYTE_ORDER == BIG_ENDIAN */
|
||||
/*
|
||||
* Little Endian
|
||||
*
|
||||
* Normally a "(*(dest) = *(src))" would do, but on some
|
||||
* systems, a FILEPOS is not a scalar hince we must memcpy.
|
||||
*/
|
||||
printf("#define SWAP_HALF_IN_FILEPOS(dest, src)\t%s%d%s\n",
|
||||
"memcpy((void *)(dest), (void *)(src), sizeof(",fileposlen,"))");
|
||||
#endif /* BYTE_ORDER == BIG_ENDIAN */
|
||||
putchar('\n');
|
||||
|
||||
/*
|
||||
* print the stat file size information
|
||||
*/
|
||||
stsizelen = sizeof(buf.st_size)*8;
|
||||
printf("#undef STSIZE_BITS\n");
|
||||
printf("#define STSIZE_BITS %d\n", stsizelen);
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
/*
|
||||
* Big Endian
|
||||
*/
|
||||
if (stsizelen == 64) {
|
||||
printf("#define SWAP_HALF_IN_STSIZE(dest, src)\t\t%s\n",
|
||||
"SWAP_HALF_IN_B64(dest, src)");
|
||||
} else if (stsizelen == 32) {
|
||||
printf("#define SWAP_HALF_IN_STSIZE(dest, src)\t\t%s\n",
|
||||
"SWAP_HALF_IN_B32(dest, src)");
|
||||
} else {
|
||||
fprintf(stderr, "%s: unexpected st_size bit size: %d\n",
|
||||
program, stsizelen);
|
||||
exit(2);
|
||||
}
|
||||
#else /* BYTE_ORDER == BIG_ENDIAN */
|
||||
/*
|
||||
* Little Endian
|
||||
*
|
||||
* Normally a "(*(dest) = *(src))" would do, but on some
|
||||
* systems, a STSIZE is not a scalar hince we must memcpy.
|
||||
*/
|
||||
printf("#define SWAP_HALF_IN_STSIZE(dest, src)\t%s%d%s\n",
|
||||
"memcpy((void *)(dest), (void *)(src), sizeof(",stsizelen,"))");
|
||||
#endif /* BYTE_ORDER == BIG_ENDIAN */
|
||||
putchar('\n');
|
||||
|
||||
/*
|
||||
* print the dev_t size
|
||||
*/
|
||||
devlen = sizeof(buf.st_dev)*8;
|
||||
printf("#undef DEV_BITS\n");
|
||||
printf("#define DEV_BITS %d\n", devlen);
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
/*
|
||||
* Big Endian
|
||||
*/
|
||||
if (devlen == 64) {
|
||||
printf("#define SWAP_HALF_IN_DEV(dest, src)\t\t%s\n",
|
||||
"SWAP_HALF_IN_B64(dest, src)");
|
||||
} else if (devlen == 32) {
|
||||
printf("#define SWAP_HALF_IN_DEV(dest, src)\t\t%s\n",
|
||||
"SWAP_HALF_IN_B32(dest, src)");
|
||||
} else if (devlen == 16) {
|
||||
printf("#define SWAP_HALF_IN_DEV(dest, src)\t\t%s\n",
|
||||
"(*(dest) = *(src))");
|
||||
} else {
|
||||
fprintf(stderr, "%s: unexpected st_dev bit size: %d\n",
|
||||
program, devlen);
|
||||
exit(3);
|
||||
}
|
||||
#else /* BYTE_ORDER == BIG_ENDIAN */
|
||||
/*
|
||||
* Little Endian
|
||||
*
|
||||
* Normally a "(*(dest) = *(src))" would do, but on some
|
||||
* systems, a DEV is not a scalar hince we must memcpy.
|
||||
*/
|
||||
printf("#define SWAP_HALF_IN_DEV(dest, src)\t%s%d%s\n",
|
||||
"memcpy((void *)(dest), (void *)(src), sizeof(",devlen,"))");
|
||||
#endif /* BYTE_ORDER == BIG_ENDIAN */
|
||||
putchar('\n');
|
||||
|
||||
/*
|
||||
* print the ino_t size
|
||||
*/
|
||||
inodelen = sizeof(buf.st_ino)*8;
|
||||
printf("#undef INODE_BITS\n");
|
||||
printf("#define INODE_BITS %d\n", inodelen);
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
/*
|
||||
* Big Endian
|
||||
*/
|
||||
if (inodelen == 64) {
|
||||
printf("#define SWAP_HALF_IN_INODE(dest, src)\t\t%s\n",
|
||||
"SWAP_HALF_IN_B64(dest, src)");
|
||||
} else if (inodelen == 32) {
|
||||
printf("#define SWAP_HALF_IN_INODE(dest, src)\t\t%s\n",
|
||||
"SWAP_HALF_IN_B32(dest, src)");
|
||||
} else if (inodelen == 16) {
|
||||
printf("#define SWAP_HALF_IN_INODE(dest, src)\t\t%s\n",
|
||||
"(*(dest) = *(src))");
|
||||
} else {
|
||||
fprintf(stderr, "%s: unexpected st_ino bit size: %d\n",
|
||||
program, inodelen);
|
||||
exit(4);
|
||||
}
|
||||
#else /* BYTE_ORDER == BIG_ENDIAN */
|
||||
/*
|
||||
* Little Endian
|
||||
*
|
||||
* Normally a "(*(dest) = *(src))" would do, but on some
|
||||
* systems, a INODE is not a scalar hince we must memcpy.
|
||||
*/
|
||||
printf("#define SWAP_HALF_IN_INODE(dest, src)\t%s%d%s\n",
|
||||
"memcpy((void *)(dest), (void *)(src), sizeof(",inodelen,"))");
|
||||
#endif /* BYTE_ORDER == BIG_ENDIAN */
|
||||
exit(0);
|
||||
}
|
80
func.h
Normal file
80
func.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 1993 David I. Bell
|
||||
* Permission is granted to use, distribute, or modify this source,
|
||||
* provided that this copyright notice remains intact.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FUNC_H
|
||||
#define FUNC_H
|
||||
|
||||
#include "calc.h"
|
||||
#include "label.h"
|
||||
|
||||
|
||||
/*
|
||||
* Structure of a function.
|
||||
* The f_opcodes array is actually of variable size.
|
||||
*/
|
||||
typedef struct func FUNC;
|
||||
struct func {
|
||||
FUNC *f_next; /* next function in list */
|
||||
unsigned long f_opcodecount; /* size of opcode array */
|
||||
unsigned int f_localcount; /* number of local variables */
|
||||
unsigned int f_paramcount; /* max number of parameters */
|
||||
char *f_name; /* function name */
|
||||
VALUE f_savedvalue; /* saved value of last expression */
|
||||
unsigned long f_opcodes[1]; /* array of opcodes (variable length) */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Amount of space needed to allocate a function of n opcodes.
|
||||
*/
|
||||
#define funcsize(n) (sizeof(FUNC) + (n) * sizeof(long))
|
||||
|
||||
|
||||
/*
|
||||
* Size of a character pointer rounded up to a number of opcodes.
|
||||
*/
|
||||
#define PTR_SIZE ((sizeof(char *) + sizeof(long) - 1) / sizeof(long))
|
||||
|
||||
|
||||
/*
|
||||
* The current function being compiled.
|
||||
*/
|
||||
extern FUNC *curfunc;
|
||||
|
||||
|
||||
/*
|
||||
* Functions to handle functions.
|
||||
*/
|
||||
extern FUNC *findfunc(long index);
|
||||
extern char *namefunc(long index);
|
||||
extern BOOL evaluate(BOOL nestflag);
|
||||
extern long adduserfunc(char *name);
|
||||
extern void beginfunc(char *name, BOOL newflag);
|
||||
extern int builtinopcode(long index);
|
||||
extern char *builtinname(long index);
|
||||
extern int dumpop(unsigned long *pc);
|
||||
extern void addop(long op);
|
||||
extern void endfunc(void);
|
||||
extern void addopone(long op, long arg);
|
||||
extern void addoptwo(long op, long arg1, long arg2);
|
||||
extern void addoplabel(long op, LABEL *label);
|
||||
extern void addopptr(long op, char *ptr);
|
||||
extern void writeindexop(void);
|
||||
extern void showbuiltins(void);
|
||||
extern int getbuiltinfunc(char *name);
|
||||
extern void builtincheck(long index, int count);
|
||||
extern void addopfunction(long op, long index, int count);
|
||||
extern void showfunctions(void);
|
||||
extern void initfunctions(void);
|
||||
extern void clearopt(void);
|
||||
extern void updateoldvalue(FUNC *fp);
|
||||
extern void calculate(FUNC *fp, int argcount);
|
||||
extern VALUE builtinfunc(long index, int argcount, VALUE *stck);
|
||||
|
||||
#endif
|
||||
|
||||
/* END CODE */
|
117
hash.c
Normal file
117
hash.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/* XXX - this code is currently not really used, but it will be soon */
|
||||
/*
|
||||
* Copyright (c) 1995 by Landon Curt Noll. All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright, this permission notice and text
|
||||
* this comment, and the disclaimer below appear in all of the following:
|
||||
*
|
||||
* supporting documentation
|
||||
* source copies
|
||||
* source works derived from this source
|
||||
* binaries derived from this source or from derived source
|
||||
*
|
||||
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
||||
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "value.h"
|
||||
|
||||
|
||||
/*
|
||||
* hash function interface table
|
||||
*
|
||||
* htbl[i] is the interface for hash algorithm i
|
||||
*/
|
||||
static HASHFUNC htbl[HASH_TYPE_MAX+1];
|
||||
|
||||
|
||||
/*
|
||||
* static functions
|
||||
*/
|
||||
static void load_htbl(void (*h_func)(HASHFUNC*), HASHFUNC*);
|
||||
|
||||
|
||||
/*
|
||||
* hash_init - initialize hash function interface table
|
||||
*
|
||||
* We will load the hash function interface table and ensure that it is
|
||||
* completely filled.
|
||||
*
|
||||
* This function does not return if an error is encountered.
|
||||
*/
|
||||
void
|
||||
hash_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* setup
|
||||
*/
|
||||
for (i=0; i <= HASH_TYPE_MAX; ++i) {
|
||||
htbl[i].type = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* setup the hash function interface for all hashes
|
||||
*/
|
||||
load_htbl(shs_hashfunc, htbl);
|
||||
|
||||
/*
|
||||
* verify that our interface table is fully populated
|
||||
*/
|
||||
for (i=0; i <= HASH_TYPE_MAX; ++i) {
|
||||
if (htbl[i].type != i) {
|
||||
fprintf(stderr, "htbl[%d] is bad\n", i);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* load_htbl - load a hash function interface table slot
|
||||
*
|
||||
* We will call the h_func function, sanity check the function type
|
||||
* and check to be sure that the slot is unused.
|
||||
*
|
||||
* given:
|
||||
* h_func - a function that returns a HASHFUNC entry
|
||||
* h - a array of hash function interfaces
|
||||
*
|
||||
* This function does not return if an error is encountered.
|
||||
*/
|
||||
static void
|
||||
load_htbl(void (*h_func)(HASHFUNC*), HASHFUNC *h)
|
||||
{
|
||||
HASHFUNC hent; /* hash function interface entry */
|
||||
|
||||
/*
|
||||
* call the HASHFUNC interface function
|
||||
*/
|
||||
h_func(&hent);
|
||||
|
||||
/*
|
||||
* sanity check the type
|
||||
*/
|
||||
if (hent.type < 0 || hent.type > HASH_TYPE_MAX) {
|
||||
fprintf(stderr, "bad HASHFUNC type: %d\n", hent.type);
|
||||
exit(1);
|
||||
}
|
||||
if (h[hent.type].type >= 0) {
|
||||
fprintf(stderr, "h[%d].type: %d already in use\n",
|
||||
hent.type, h[hent.type].type);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* load the entry
|
||||
*/
|
||||
h[hent.type] = hent;
|
||||
}
|
50
hash.h
Normal file
50
hash.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* XXX - this code is currently not really used, but it will be soon */
|
||||
/*
|
||||
* Copyright (c) 1995 by Landon Curt Noll. All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright, this permission notice and text
|
||||
* this comment, and the disclaimer below appear in all of the following:
|
||||
*
|
||||
* supporting documentation
|
||||
* source copies
|
||||
* source works derived from this source
|
||||
* binaries derived from this source or from derived source
|
||||
*
|
||||
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
||||
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(HASH_H)
|
||||
#define HASH_H
|
||||
|
||||
/*
|
||||
* hashstate - state of a hash system
|
||||
*/
|
||||
struct hashstate {
|
||||
int type; /* hash type (see XYZ_HASH_TYPE below) */
|
||||
BOOL prevstr; /* TRUE=>previous value hashed was a string */
|
||||
union {
|
||||
SHS_INFO hh_shs; /* old Secure Hash Standard */
|
||||
} h_union;
|
||||
};
|
||||
typedef struct hashstate HASH;
|
||||
/* For ease in referencing */
|
||||
#define h_shs h_union.hh_shs
|
||||
|
||||
|
||||
/*
|
||||
* XYZ_HASH_TYPE - hash types
|
||||
*
|
||||
* we support these hash types - must start with 0
|
||||
*/
|
||||
#define SHS_HASH_TYPE 0
|
||||
#define HASH_TYPE_MAX 0 /* must be number of XYZ_HASH_TYPE values */
|
||||
|
||||
#endif /* !HASH_H */
|
58
have_const.c
Normal file
58
have_const.c
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* have_const - Determine if we want or can support ansi const
|
||||
*
|
||||
* usage:
|
||||
* have_const
|
||||
*
|
||||
* Not all compilers support const, so this may not compile on your system.
|
||||
*
|
||||
* This prog outputs several defines:
|
||||
*
|
||||
* HAVE_CONST
|
||||
* defined ==> ok to use const
|
||||
* undefined ==> do not use const
|
||||
*
|
||||
* CONST
|
||||
* const ==> use const
|
||||
* (nothing) ==> const not used
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1995 by Landon Curt Noll. All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright, this permission notice and text
|
||||
* this comment, and the disclaimer below appear in all of the following:
|
||||
*
|
||||
* supporting documentation
|
||||
* source copies
|
||||
* source works derived from this source
|
||||
* binaries derived from this source or from derived source
|
||||
*
|
||||
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
||||
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* chongo was here /\../\
|
||||
*/
|
||||
|
||||
MAIN
|
||||
main(void)
|
||||
{
|
||||
#if defined(HAVE_NO_CONST)
|
||||
printf("#undef HAVE_CONST /* no */\n");
|
||||
printf("#undef CONST\n");
|
||||
printf("#define CONST /* no */\n");
|
||||
#else /* HAVE_NO_CONST */
|
||||
const char * const str = "const";
|
||||
|
||||
printf("#define HAVE_CONST /* yes */\n");
|
||||
printf("#undef CONST\n");
|
||||
printf("#define CONST %s /* yes */\n", str);
|
||||
#endif /* HAVE_NO_CONST */
|
||||
exit(0);
|
||||
}
|
53
have_fpos.c
Normal file
53
have_fpos.c
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* have_fpos - Determine if have fgetpos and fsetpos functions
|
||||
*
|
||||
* If the symbol HAVE_NO_FPOS is defined, we will output nothing.
|
||||
* If we are able to compile this program, then we must have the
|
||||
* fgetpos and fsetpos functions and we will output the
|
||||
* appropriate have_fpos.h file body.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1995 by Landon Curt Noll. All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright, this permission notice and text
|
||||
* this comment, and the disclaimer below appear in all of the following:
|
||||
*
|
||||
* supporting documentation
|
||||
* source copies
|
||||
* source works derived from this source
|
||||
* binaries derived from this source or from derived source
|
||||
*
|
||||
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
||||
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* chongo was here /\../\
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
MAIN
|
||||
main(void)
|
||||
{
|
||||
#if !defined(HAVE_NO_FPOS)
|
||||
fpos_t pos; /* file position */
|
||||
|
||||
/* get the current position */
|
||||
(void) fgetpos(stdin, &pos);
|
||||
|
||||
/* set the current position */
|
||||
(void) fsetpos(stdin, &pos);
|
||||
|
||||
/* print a have_fpos.h body that says we have the functions */
|
||||
printf("#undef HAVE_FPOS\n");
|
||||
printf("#define HAVE_FPOS 1 /* yes */\n\n");
|
||||
printf("typedef fpos_t FILEPOS;\n");
|
||||
#endif
|
||||
exit(0);
|
||||
}
|
60
have_newstr.c
Normal file
60
have_newstr.c
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* have_newstr - Determine if we have a system without ANSI C string functions
|
||||
*
|
||||
* usage:
|
||||
* have_newstr
|
||||
*
|
||||
* Not all systems support all ANSI C string functions, so this may not
|
||||
* compile on your system.
|
||||
*
|
||||
* This prog outputs several defines:
|
||||
*
|
||||
* HAVE_NEWSTR
|
||||
* defined ==> use memcpy(), memset(), strchr()
|
||||
* undefined ==> use bcopy() instead of memcpy(),
|
||||
* use bfill() instead of memset(),
|
||||
* use index() instead of strchr()
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1995 by Landon Curt Noll. All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright, this permission notice and text
|
||||
* this comment, and the disclaimer below appear in all of the following:
|
||||
*
|
||||
* supporting documentation
|
||||
* source copies
|
||||
* source works derived from this source
|
||||
* binaries derived from this source or from derived source
|
||||
*
|
||||
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
||||
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* chongo was here /\../\
|
||||
*/
|
||||
|
||||
#define MOVELEN 3
|
||||
|
||||
char src[] = "chongo was here";
|
||||
char dest[MOVELEN+1];
|
||||
|
||||
MAIN
|
||||
main(void)
|
||||
{
|
||||
#if defined(HAVE_NO_NEWSTR)
|
||||
printf("#undef HAVE_NEWSTR /* no */\n");
|
||||
#else /* HAVE_NO_NEWSTR */
|
||||
(void) memcpy(dest, src, MOVELEN);
|
||||
(void) memset(dest, 0, MOVELEN);
|
||||
(void) strchr(src, 'e');
|
||||
|
||||
printf("#define HAVE_NEWSTR /* yes */\n");
|
||||
#endif /* HAVE_NO_NEWSTR */
|
||||
exit(0);
|
||||
}
|
139
have_stdvs.c
Normal file
139
have_stdvs.c
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* have_stdvs - try <stdarg.h> to see if it really works with vsprintf()
|
||||
*
|
||||
* On some systems that have both <stdarg.h> and <varargs.h>, vsprintf()
|
||||
* does not work well under one type of include file.
|
||||
*
|
||||
* Some systems (such as UMIPS) have bugs in the <stdarg.h> implementation
|
||||
* that show up in vsprintf(), so we may have to try to use sprintf()
|
||||
* as if it were vsprintf() and hope for the best.
|
||||
*
|
||||
* This program will output #defines and exits 0 if vsprintf() (or sprintf())
|
||||
* produces the results that we expect. This program exits 1 if vsprintf()
|
||||
* (or sprintf()) produces unexpected results while using the <stdarg.h>
|
||||
* include file.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1995 by Landon Curt Noll. All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright, this permission notice and text
|
||||
* this comment, and the disclaimer below appear in all of the following:
|
||||
*
|
||||
* supporting documentation
|
||||
* source copies
|
||||
* source works derived from this source
|
||||
* binaries derived from this source or from derived source
|
||||
*
|
||||
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
||||
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* chongo was here /\../\
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "have_unistd.h"
|
||||
#if defined(HAVE_UNISTD_H)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "have_string.h"
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
|
||||
char buf[BUFSIZ];
|
||||
|
||||
|
||||
void
|
||||
try(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
#if !defined(DONT_HAVE_VSPRINTF)
|
||||
vsprintf(buf, fmt, ap);
|
||||
#else
|
||||
sprintf(buf, fmt, ap);
|
||||
#endif
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
MAIN
|
||||
main(void)
|
||||
{
|
||||
/*
|
||||
* setup
|
||||
*/
|
||||
buf[0] = '\0';
|
||||
|
||||
/*
|
||||
* test variable args and vsprintf/sprintf
|
||||
*/
|
||||
try("@%d:%s:%d@", 1, "hi", 2);
|
||||
if (strcmp(buf, "@1:hi:2@") != 0) {
|
||||
#if !defined(DONT_HAVE_VSPRINTF)
|
||||
/* <stdarg.h> with vsprintf() didn't work */
|
||||
#else
|
||||
/* <stdarg.h> with sprintf() simulating vsprintf() didn't work */
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
try("%s %d%s%d%d %s",
|
||||
"Landon Noll 1st proved that", 2, "^", 23209, -1, "was prime");
|
||||
if (strcmp(buf, "Landon Noll 1st proved that 2^23209-1 was prime") != 0) {
|
||||
#if !defined(DONT_HAVE_VSPRINTF)
|
||||
/* <stdarg.h> with vsprintf() didn't work */
|
||||
#else
|
||||
/* <stdarg.h> with sprintf() simulating vsprintf() didn't work */
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* report the result
|
||||
*/
|
||||
puts("/* what type of variable args do we have? */");
|
||||
#if defined(DONT_HAVE_VSPRINTF)
|
||||
puts("/*");
|
||||
puts(" * SIMULATE_STDARG");
|
||||
puts(" *");
|
||||
puts(" * WARNING: This type of stdarg makes assumptions about the stack");
|
||||
puts(" * that may not be true on your system. You may want to");
|
||||
puts(" * define STDARG (if using ANSI C) or VARARGS.");
|
||||
puts(" */");
|
||||
puts("typedef char *va_list;");
|
||||
puts("#define va_start(ap,parmn) (void)((ap) = (char*)(&(parmn) + 1))");
|
||||
puts("#define va_end(ap) (void)((ap) = 0)");
|
||||
puts("#define va_arg(ap, type) \\");
|
||||
puts(" (((type*)((ap) = ((ap) + sizeof(type))))[-1])");
|
||||
puts("#define SIMULATE_STDARG /* use std_arg.h to simulate <stdarg.h> */");
|
||||
#else
|
||||
puts("#define STDARG /* use <stdarg.h> */");
|
||||
puts("#include <stdarg.h>");
|
||||
#endif
|
||||
puts("\n/* should we use vsprintf()? */");
|
||||
#if !defined(DONT_HAVE_VSPRINTF)
|
||||
puts("#define HAVE_VS /* yes */");
|
||||
#else
|
||||
puts("/*");
|
||||
puts(" * Hack aleart!!!");
|
||||
puts(" *");
|
||||
puts(" * Systems that do not have vsprintf() need something. In some");
|
||||
puts(" * cases the sprintf function will deal correctly with the");
|
||||
puts(" * va_alist 3rd arg. Hope for the best!");
|
||||
puts(" */");
|
||||
puts("#define vsprintf sprintf");
|
||||
puts("#undef HAVE_VS");
|
||||
#endif
|
||||
exit(0);
|
||||
}
|
62
have_uid_t.c
Normal file
62
have_uid_t.c
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* have_uid_t - Determine if we want or can support uid_t
|
||||
*
|
||||
* usage:
|
||||
* have_uid_t
|
||||
*
|
||||
* Not all compilers support uid_t, so this may not compile on your system.
|
||||
*
|
||||
* This prog outputs several defines:
|
||||
*
|
||||
* HAVE_UID_T
|
||||
* defined ==> ok to use uid_t
|
||||
* undefined ==> do not use uid_t
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1995 by Landon Curt Noll. All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright, this permission notice and text
|
||||
* this comment, and the disclaimer below appear in all of the following:
|
||||
*
|
||||
* supporting documentation
|
||||
* source copies
|
||||
* source works derived from this source
|
||||
* binaries derived from this source or from derived source
|
||||
*
|
||||
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
||||
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* chongo was here /\../\
|
||||
*/
|
||||
|
||||
#if !defined(HAVE_NO_UID_T)
|
||||
#include "have_unistd.h"
|
||||
#if defined(HAVE_UNISTD_H)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <pwd.h>
|
||||
#include <sys/types.h>
|
||||
#endif /* ! HAVE_NO_UID_T */
|
||||
|
||||
MAIN
|
||||
main(void)
|
||||
{
|
||||
#if defined(HAVE_NO_UID_T)
|
||||
printf("#undef HAVE_UID_T /* no */\n");
|
||||
#else /* HAVE_NO_UID_T */
|
||||
uid_t curds;
|
||||
extern uid_t geteuid();
|
||||
|
||||
curds = geteuid();
|
||||
|
||||
printf("#define HAVE_UID_T /* yes */\n");
|
||||
#endif /* HAVE_NO_UID_T */
|
||||
exit(0);
|
||||
}
|
131
have_varvs.c
Normal file
131
have_varvs.c
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* have_varvs - try <varargs.h> to see if it really works with vsprintf()
|
||||
*
|
||||
* Some systems have bugs in the <varargs.h> implementation that show up in
|
||||
* vsprintf(), so we may have to try to use sprintf() as if it were vsprintf()
|
||||
* and hope for the best.
|
||||
*
|
||||
* This program will output #defines and exits 0 if vsprintf() (or sprintf())
|
||||
* produces the results that we expect. This program exits 1 if vsprintf()
|
||||
* (or sprintf()) produces unexpected results while using the <stdarg.h>
|
||||
* include file.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1995 by Landon Curt Noll. All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright, this permission notice and text
|
||||
* this comment, and the disclaimer below appear in all of the following:
|
||||
*
|
||||
* supporting documentation
|
||||
* source copies
|
||||
* source works derived from this source
|
||||
* binaries derived from this source or from derived source
|
||||
*
|
||||
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
||||
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* chongo was here /\../\
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "have_unistd.h"
|
||||
#if defined(HAVE_UNISTD_H)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "have_string.h"
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
|
||||
char buf[BUFSIZ];
|
||||
|
||||
#if !defined(STDARG) && !defined(SIMULATE_STDARG)
|
||||
#include <varargs.h>
|
||||
|
||||
void
|
||||
try(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap);
|
||||
#if !defined(DONT_HAVE_VSPRINTF)
|
||||
vsprintf(buf, fmt, ap);
|
||||
#else
|
||||
sprintf(buf, fmt, ap);
|
||||
#endif
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void
|
||||
try(char *a, int b, char *c, int d)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
MAIN
|
||||
main(void)
|
||||
{
|
||||
/*
|
||||
* setup
|
||||
*/
|
||||
buf[0] = '\0';
|
||||
|
||||
/*
|
||||
* test variable args and vsprintf/sprintf
|
||||
*/
|
||||
try("@%d:%s:%d@", 1, "hi", 2);
|
||||
if (strcmp(buf, "@1:hi:2@") != 0) {
|
||||
#if !defined(DONT_HAVE_VSPRINTF)
|
||||
/* <varargs.h> with vsprintf() didn't work */
|
||||
#else
|
||||
/* <varargs.h> with sprintf() simulating vsprintf() didn't work */
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
try("%s %d%s%d%d %s",
|
||||
"Landon Noll 1st proved that", 2, "^", 23209, -1, "was prime");
|
||||
if (strcmp(buf, "Landon Noll 1st proved that 2^23209-1 was prime") != 0) {
|
||||
#if !defined(DONT_HAVE_VSPRINTF)
|
||||
/* <stdarg.h> with vsprintf() didn't work */
|
||||
#else
|
||||
/* <stdarg.h> with sprintf() simulating vsprintf() didn't work */
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* report the result
|
||||
*/
|
||||
puts("/* what type of variable args do we have? */");
|
||||
puts("#define VARARGS /* use <varargs.h> */");
|
||||
puts("#include <varargs.h>");
|
||||
puts("\n/* should we use vsprintf()? */");
|
||||
#if !defined(DONT_HAVE_VSPRINTF)
|
||||
puts("#define HAVE_VS /* yes */");
|
||||
#else
|
||||
puts("/*");
|
||||
puts(" * Hack aleart!!!");
|
||||
puts(" *");
|
||||
puts(" * Systems that do not have vsprintf() need something. In some");
|
||||
puts(" * cases the sprintf function will deal correctly with the");
|
||||
puts(" * va_alist 3rd arg. Hope for the best!");
|
||||
puts(" */");
|
||||
puts("#define vsprintf sprintf");
|
||||
puts("#undef HAVE_VS");
|
||||
#endif
|
||||
exit(0);
|
||||
}
|
369
help/Makefile
Normal file
369
help/Makefile
Normal file
@@ -0,0 +1,369 @@
|
||||
#
|
||||
# help - makefile for calc help files
|
||||
#
|
||||
# Copyright (c) 1994 David I. Bell and Landon Curt Noll
|
||||
# Permission is granted to use, distribute, or modify this source,
|
||||
# provided that this copyright notice remains intact.
|
||||
#
|
||||
# Arbitrary precision calculator.
|
||||
#
|
||||
# calculator by David I. Bell
|
||||
# makefile by Landon Curt Noll
|
||||
|
||||
# required vars
|
||||
#
|
||||
SHELL= /bin/sh
|
||||
MAKE_FILE = Makefile
|
||||
|
||||
# Normally, the upper level makefile will set these values. We provide
|
||||
# a default here just in case you want to build from this directory.
|
||||
#
|
||||
TOPDIR= /usr/local/lib
|
||||
#TOPDIR= /usr/lib
|
||||
#TOPDIR= /usr/libdata
|
||||
|
||||
LIBDIR= ${TOPDIR}/calc
|
||||
HELPDIR= ${LIBDIR}/help
|
||||
|
||||
# Makefile debug
|
||||
#
|
||||
# Q=@ do not echo internal makefile actions (quiet mode)
|
||||
# Q= echo internal makefile actions (debug / verbose mode)
|
||||
#
|
||||
#Q=
|
||||
Q=@
|
||||
|
||||
# standard tools
|
||||
#
|
||||
NATIVE_CC= cc
|
||||
NATIVE_CFLAGS=
|
||||
SED= sed
|
||||
SORT= sort
|
||||
FMT= fmt
|
||||
CMP= cmp
|
||||
CAT= cat
|
||||
|
||||
# Standard help files
|
||||
#
|
||||
# The obj.file is special and is not listed here.
|
||||
#
|
||||
STD_HELP_FILES1= intro overview help command config \
|
||||
define environment expression file history interrupt mat
|
||||
STD_HELP_FILES2= operator statement types usage variable
|
||||
STD_HELP_FILES3= todo credit
|
||||
STD_HELP_FILES= ${STD_HELP_FILES1} ${STD_HELP_FILES2} ${STD_HELP_FILES3}
|
||||
SYMBOL_HELP= assign
|
||||
|
||||
# These two lists are prodiced by the detaillist and missinglist rules
|
||||
# when no WARNINGS are detected.
|
||||
#
|
||||
DETAIL_HELP= abs access acos acosh acot acoth acsc acsch append appr archive \
|
||||
arg asec asech asin asinh assoc atan atan2 atanh avg base bround \
|
||||
btrunc ceil cfappr cfsim char cmdbuf cmp comb conj cos cosh cot coth \
|
||||
count cp csc csch ctime delete den det digit digits dp epsilon errno \
|
||||
error eval exp fact factor fclose fcnt feof ferror fflush fgetc \
|
||||
fgetfield fgetline fgets fgetstr fib files floor fopen forall fprintf \
|
||||
fputc fputs fputstr frac frem freopen fscan fscanf fseek fsize ftell \
|
||||
gcd gcdrem getenv hash head highbit hmean hypot ilog ilog10 ilog2 im \
|
||||
insert int inverse iroot isassoc isatty isconfig iserror iseven \
|
||||
isfile ishash isident isint islist ismat ismult isnull isnum isobj \
|
||||
isodd isprime isqrt isrand israndom isreal isrel isset issimple issq \
|
||||
isstr istype jacobi join lcm lcmfact lfactor list ln lowbit ltol \
|
||||
makelist matdim matfill matmax matmin matsum mattrans max meq min \
|
||||
minv mmin mne mod modify near newerror nextcand nextprime norm null \
|
||||
num ord param perm pfact pi pix places pmod polar poly pop power \
|
||||
prevcand prevprime printf prompt ptest push putenv quo quomod rand \
|
||||
randbit randperm rcin rcmul rcout rcpow rcsq re rm remove reverse \
|
||||
rewind root round rsearch runtime scale scan scanf search sec sech \
|
||||
segment select sgn sin sinh size sizeof sort sqrt srand ssq str \
|
||||
strcat strerror strlen strpos strprintf strscan strscanf substr swap \
|
||||
system tail tan tanh time trunc xor
|
||||
|
||||
# Help files that are constructed from other sources
|
||||
#
|
||||
# The obj.file is special and is not listed here.
|
||||
#
|
||||
BUILT_HELP_FILES= bindings altbind changes libcalc stdlib bugs errorcodes
|
||||
|
||||
# Singular files
|
||||
#
|
||||
# These files are copies of their plural form.
|
||||
#
|
||||
PLURAL_FILES= bindings bugs changes errorcodes types
|
||||
SINGULAR_FILES= binding bug change errorcode type
|
||||
|
||||
# These files are found (but not built) in the distribution
|
||||
#
|
||||
DISTLIST= ${STD_HELP_FILES} ${DETAIL_HELP} ${SYMBOL_HELP} ${MAKE_FILE} \
|
||||
obj.file builtin.top builtin.end funclist.sed \
|
||||
errorcodes.hdr errorcodes.sed
|
||||
|
||||
all: ${STD_HELP_FILES} obj.file ${BUILT_HELP_FILES} full \
|
||||
${DETAIL_HELP} ${SINGULAR_FILES} builtin .all
|
||||
|
||||
# used by the upper level Makefile to determine of we have done all
|
||||
#
|
||||
# NOTE: Due to bogus shells found on one common system we must have
|
||||
# an non-emoty else clause for every if condition. *sigh*
|
||||
#
|
||||
.all:
|
||||
rm -f .all
|
||||
touch .all
|
||||
|
||||
bindings: ../lib/bindings
|
||||
rm -f bindings
|
||||
cp ../lib/bindings bindings
|
||||
chmod 0444 bindings
|
||||
-@if [ -z "${Q}" ]; then \
|
||||
echo ''; \
|
||||
echo '=-=-= skipping the cat of help/$@ =-=-='; \
|
||||
echo ''; \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
|
||||
altbind: ../lib/altbind
|
||||
rm -f altbind
|
||||
cp ../lib/altbind altbind
|
||||
chmod 0444 altbind
|
||||
-@if [ -z "${Q}" ]; then \
|
||||
echo ''; \
|
||||
echo '=-=-= skipping the cat of help/$@ =-=-='; \
|
||||
echo ''; \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
|
||||
stdlib: ../lib/README
|
||||
rm -f stdlib
|
||||
cp ../lib/README stdlib
|
||||
chmod 0444 stdlib
|
||||
-@if [ -z "${Q}" ]; then \
|
||||
echo ''; \
|
||||
echo '=-=-= skipping the cat of help/$@ =-=-='; \
|
||||
echo ''; \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
|
||||
changes: ../CHANGES
|
||||
rm -f changes
|
||||
cp ../CHANGES changes
|
||||
chmod 0444 changes
|
||||
-@if [ -z "${Q}" ]; then \
|
||||
echo ''; \
|
||||
echo '=-=-= skipping the cat of help/$@ =-=-='; \
|
||||
echo ''; \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
|
||||
libcalc: ../LIBRARY
|
||||
rm -f libcalc
|
||||
${SED} -e 's:$${LIBDIR}:${LIBDIR}:g' < ../LIBRARY > libcalc
|
||||
chmod 0444 libcalc
|
||||
-@if [ -z "${Q}" ]; then \
|
||||
echo ''; \
|
||||
echo '=-=-= skipping the cat of help/$@ =-=-='; \
|
||||
echo ''; \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
|
||||
bugs: ../BUGS
|
||||
rm -f bugs
|
||||
cp ../BUGS bugs
|
||||
chmod 0444 bugs
|
||||
-@if [ -z "${Q}" ]; then \
|
||||
echo ''; \
|
||||
echo '=-=-= skipping the cat of help/$@ =-=-='; \
|
||||
echo ''; \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
|
||||
errorcodes: ../calcerr.h errorcodes.hdr errorcodes.sed
|
||||
rm -f errorcodes
|
||||
${CAT} errorcodes.hdr > errorcodes
|
||||
${SED} -n -f errorcodes.sed < ../calcerr.h >> errorcodes
|
||||
chmod 0444 errorcodes
|
||||
-@if [ -z "${Q}" ]; then \
|
||||
echo ''; \
|
||||
echo '=-=-= skipping the cat of help/$@ =-=-='; \
|
||||
echo ''; \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
|
||||
full: ${STD_HELP_FILES} ${BUILT_HELP_FILES} ${MAKE_FILE}
|
||||
${Q}echo "forming full"
|
||||
-${Q}rm -f full
|
||||
-${Q}for i in ${STD_HELP_FILES1} obj.file ${STD_HELP_FILES2} \
|
||||
${BUILT_HELP_FILES} ${STD_HELP_FILES3}; do \
|
||||
if [ Xintro != X"$$i" ]; then \
|
||||
echo ""; \
|
||||
else \
|
||||
true; \
|
||||
fi; \
|
||||
if [ Xobj.file = X"$$i" ]; then \
|
||||
j=obj; \
|
||||
else \
|
||||
j=$$i; \
|
||||
fi; \
|
||||
echo "*************"; \
|
||||
echo "* $$j"; \
|
||||
echo "*************"; \
|
||||
echo ""; \
|
||||
cat $$i; \
|
||||
done > full
|
||||
${Q}echo "full formed"
|
||||
-@if [ -z "${Q}" ]; then \
|
||||
echo ''; \
|
||||
echo '=-=-= skipping the cat of help/$@ =-=-='; \
|
||||
echo ''; \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
|
||||
# Singular files are the same files as their plural form.
|
||||
#
|
||||
${SINGULAR_FILES}: ${PLURAL_FILES}
|
||||
${Q}for i in ${SINGULAR_FILES}; do \
|
||||
echo "rm -f $${i}"; \
|
||||
rm -f $${i}; \
|
||||
echo "cp $${i}s $${i}"; \
|
||||
cp $${i}s $${i}; \
|
||||
done
|
||||
-@if [ -z "${Q}" ]; then \
|
||||
echo ''; \
|
||||
echo '=-=-= skipping the cat of help/SINGULAR_FILES =-=-='; \
|
||||
echo ''; \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
|
||||
# Form the builtin file
|
||||
#
|
||||
# We ave a "chicken-and-egg" problem. We want the builtn help file to
|
||||
# accurately reflect the function list. It would be nice if we could
|
||||
# just execute calc show builtin, but calc may not have been built or
|
||||
# buildable at this point. The hack-a-round used is to convert ../func.c
|
||||
# into a standalone program that generates a suitable function list
|
||||
# that is standwiched between the top and bottom builtin help text.
|
||||
#
|
||||
# We form funclist.c by sedding out unwanted stuff from builtins table,
|
||||
# converting NUMBER* and VALUE into harmless types and converting
|
||||
# the showbuiltins() function into main(). Combined with the -DFUNCLIST
|
||||
# we will avoid all of the complex calc types, macros and defines and
|
||||
# be left with just main() and a mininal builtins table.
|
||||
#
|
||||
# Building funclist.o a portable fashion is ugly because some systems
|
||||
# do not treat -I.. correctly!
|
||||
#
|
||||
builtin: builtin.top builtin.end ../func.c funclist.sed
|
||||
${Q}echo "forming builtin help file"
|
||||
-${Q}rm -f builtin
|
||||
${Q}cat builtin.top > builtin
|
||||
-${Q}rm -f funclist.c
|
||||
${Q}${SED} -n -f funclist.sed ../func.c > funclist.c
|
||||
|
||||
-${Q}rm -f ../funclist.c ../funclist.o ../funclist funclist
|
||||
${Q}cp funclist.c ..
|
||||
-${Q}(cd ..; \
|
||||
${NATIVE_CC} ${NATIVE_CFLAGS} -DFUNCLIST funclist.c -o funclist; \
|
||||
mv funclist help; \
|
||||
rm -f funclist.c funclist.o funclist)
|
||||
${Q}./funclist | \
|
||||
${SED} -e 's/^/ /' -e 's/[ ][ ]*$$//' >> builtin
|
||||
${Q}cat builtin.end >> builtin
|
||||
${Q}echo "builtin help file formed"
|
||||
-@if [ -z "${Q}" ]; then \
|
||||
echo ''; \
|
||||
echo '=-=-= skipping the cat of help/$@ =-=-='; \
|
||||
echo ''; \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
|
||||
##
|
||||
#
|
||||
# File list generation. You can ignore this section.
|
||||
#
|
||||
#
|
||||
# We will form the names of source files as if they were in a
|
||||
# sub-directory called calc/help.
|
||||
#
|
||||
##
|
||||
|
||||
distlist: ${DISTLIST}
|
||||
${Q}for i in ${DISTLIST}; do \
|
||||
echo calc/help/$$i; \
|
||||
done | ${SORT}
|
||||
|
||||
# The bsdi distribution has generated files as well as distributed files.
|
||||
#
|
||||
bsdilist: ${DISTLIST} ${BUILT_HELP_FILES}
|
||||
${Q}for i in ${DISTLIST} ${BUILT_HELP_FILES}; do \
|
||||
echo calc/help/$$i; \
|
||||
done | ${SORT}
|
||||
|
||||
# The BSDI cdrom makefile expects all help files to be pre-built. This rule
|
||||
# creats these fils so that the release can be shipped off to BSDI. You can
|
||||
# ignore this rule.
|
||||
#
|
||||
bsdi: all
|
||||
rm -f obj
|
||||
cp obj.file obj
|
||||
|
||||
# These next rule help me form the ${DETAIL_HELP} makefile variables above.
|
||||
#
|
||||
detaillist:
|
||||
${Q}-(echo "xxxxx"; \
|
||||
for i in ${DETAIL_HELP}; do \
|
||||
if [ ! -f SCCS/s.$$i ]; then \
|
||||
echo "WARNING: $$i not under SCCS control" 1>&2; \
|
||||
else \
|
||||
echo $$i; \
|
||||
fi; \
|
||||
done | ${SORT}) | ${FMT} -70 | \
|
||||
${SED} -e '1s/xxxxx/DETAIL_HELP=/' -e '2,$$s/^/ /' \
|
||||
-e 's/$$/ \\/' -e '$$s/ \\$$//'
|
||||
|
||||
clean:
|
||||
rm -f obj mkbuiltin funclist.c funclist.o funclist
|
||||
|
||||
clobber:
|
||||
rm -f ${BUILT_HELP_FILES} full builtin .all
|
||||
rm -f obj mkbuiltin funclist.c funclist.o funclist ${SINGULAR_FILES}
|
||||
|
||||
install: all
|
||||
-${Q}if [ ! -d ${TOPDIR} ]; then \
|
||||
echo mkdir ${TOPDIR}; \
|
||||
mkdir ${TOPDIR}; \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
-${Q}if [ ! -d ${LIBDIR} ]; then \
|
||||
echo mkdir ${LIBDIR}; \
|
||||
mkdir ${LIBDIR}; \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
-${Q}if [ ! -d ${HELPDIR} ]; then \
|
||||
echo mkdir ${HELPDIR}; \
|
||||
mkdir ${HELPDIR}; \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
${Q}for i in ${STD_HELP_FILES} ${BUILT_HELP_FILES} builtin \
|
||||
full ${DETAIL_HELP} ${SINGULAR_FILES} ${SYMBOL_HELP}; do \
|
||||
echo rm -f ${HELPDIR}/$$i; \
|
||||
rm -f ${HELPDIR}/$$i; \
|
||||
echo cp $$i ${HELPDIR}; \
|
||||
cp $$i ${HELPDIR}; \
|
||||
echo chmod 0444 ${HELPDIR}/$$i; \
|
||||
chmod 0444 ${HELPDIR}/$$i; \
|
||||
done
|
||||
rm -f ${HELPDIR}/obj
|
||||
cp obj.file ${HELPDIR}/obj
|
||||
chmod 0444 ${HELPDIR}/obj
|
41
help/abs
Normal file
41
help/abs
Normal file
@@ -0,0 +1,41 @@
|
||||
NAME
|
||||
abs - absolute value
|
||||
|
||||
SYNOPSIS
|
||||
abs(x [,eps])
|
||||
|
||||
TYPES
|
||||
If x is an object of type xx, the function xx_abs has to have
|
||||
been defined; this will determine the types for x, eps and
|
||||
the returned value.
|
||||
|
||||
For non-object x and eps:
|
||||
|
||||
x number (real or complex)
|
||||
eps ignored if x is real, nonzero real for complex x,
|
||||
defaults to epsilon().
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
If x is real, returns x if x is positive or zero, -x if x is negative.
|
||||
|
||||
For complex x, returns the multiple of eps nearest or next to nearest
|
||||
to the absolute value of x. The result usually has error less in
|
||||
absolute value than abs(eps), but should not exceed 0.75 * abs(eps).
|
||||
|
||||
EXAMPLE
|
||||
> print abs(3.4), abs(-3.4)
|
||||
3.4 3.4
|
||||
|
||||
> print abs(3+4i, 1e-5), abs(4+5i, 1e-5), abs(4+5i, 1e-10)
|
||||
5 6.40312 6.4031242374
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
none
|
||||
|
||||
SEE ALSO
|
||||
cmp, epsilon, hypot, norm, near, obj
|
46
help/access
Normal file
46
help/access
Normal file
@@ -0,0 +1,46 @@
|
||||
NAME
|
||||
access - determine existence or accessibility of named file
|
||||
|
||||
SYNOPSIS
|
||||
access(name [, mode])
|
||||
|
||||
TYPES
|
||||
name string
|
||||
mode integer or string containing only 'r', 'w', 'x' characters
|
||||
|
||||
return null value or error
|
||||
|
||||
DESCRIPTION
|
||||
access(name) or access(name, 0) or access(name, "") returns the null
|
||||
value if a file with this name exists.
|
||||
|
||||
If non-null mode is specified, the null value is returned if there
|
||||
is a file with the specified name and accessibility indicated by the
|
||||
bits or characters of the mode argument: 'r' or bit 2 for reading,
|
||||
'w' or bit 1 for writing, 'x' or bit 0 for execution.
|
||||
|
||||
EXAMPLE
|
||||
> !rm -f junk
|
||||
> access("junk")
|
||||
Error 10002 XXX This number will probably be changed
|
||||
> f = fopen("junk", "w")
|
||||
> access("junk")
|
||||
> fputs(f, "Now is the time");
|
||||
> freopen(f, "r");
|
||||
> !chmod u-w junk
|
||||
> fgets(f)
|
||||
"Now is the time"
|
||||
> access("junk", "w")
|
||||
Error 10013 XXX
|
||||
> freopen(f, "w")
|
||||
Error 10013 XXX
|
||||
|
||||
LIMITS
|
||||
none - XXX - is this correct?
|
||||
|
||||
LIBRARY
|
||||
none - XXX - is this correct?
|
||||
|
||||
SEE ALSO
|
||||
errno, fclose, feof, ferror, fflush, fgetc, fgetline, fgets, files, fopen,
|
||||
fprintf, fputc, fputs, fseek, fsize, ftell, isfile, printf, prompt
|
32
help/acos
Normal file
32
help/acos
Normal file
@@ -0,0 +1,32 @@
|
||||
NAME
|
||||
acos - inverse trigonometric cosine
|
||||
|
||||
SYNOPSIS
|
||||
acos(x [,eps])
|
||||
|
||||
TYPES
|
||||
x real, -1 <= x <= 1
|
||||
eps nonzero real, defaults to epsilon()
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
Returns the acos of x to a multiple of eps with error less in
|
||||
absolute value than .75 * eps.
|
||||
|
||||
v = acos(x) is the number in [0, pi] for which cos(v) = x.
|
||||
|
||||
EXAMPLE
|
||||
> print acos(.5, 1e-5), acos(.5, 1e-10), acos(.5, 1e-15), acos(.5, 1e-20)
|
||||
1.0472 1.0471975512 1.047197551196598 1.04719755119659774615
|
||||
|
||||
LIMITS
|
||||
unlike sin and cos, x must be real
|
||||
abs(x) <= 1
|
||||
eps > 0
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qacos(NUMBER *x, NUMBER *eps)
|
||||
|
||||
SEE ALSO
|
||||
asin, atan, asec, acsc, acot, epsilon
|
32
help/acosh
Normal file
32
help/acosh
Normal file
@@ -0,0 +1,32 @@
|
||||
NAME
|
||||
acosh - inverse hyperbolic cosine
|
||||
|
||||
SYNOPSIS
|
||||
acosh(x [,eps])
|
||||
|
||||
TYPES
|
||||
x real, x >= 1
|
||||
eps nonzero real, defaults to epsilon()
|
||||
|
||||
return nonnegative real
|
||||
|
||||
DESCRIPTION
|
||||
Returns the cosh of x to a multiple of eps with error less in
|
||||
absolute value than .75 * eps.
|
||||
|
||||
acosh(x) = ln(x + sqrt(x^2 - 1)) is the nonnegative real number v
|
||||
for which cosh(v) = x.
|
||||
|
||||
EXAMPLE
|
||||
> print acosh(2, 1e-5), acosh(2, 1e-10), acosh(2, 1e-15), acosh(2, 1e-20)
|
||||
1.31696 1.3169578969 1.316957896924817 1.31695789692481670862
|
||||
|
||||
LIMITS
|
||||
unlike sin and cos, x must be real
|
||||
eps > 0
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qacosh(NUMBER *x, NUMBER *eps)
|
||||
|
||||
SEE ALSO
|
||||
asinh, atanh, asech, acsch, acoth, epsilon
|
31
help/acot
Normal file
31
help/acot
Normal file
@@ -0,0 +1,31 @@
|
||||
NAME
|
||||
acot - inverse trigonometric cotangent
|
||||
|
||||
SYNOPSIS
|
||||
acot(x [,eps])
|
||||
|
||||
TYPES
|
||||
x real
|
||||
eps nonzero real, defaults to epsilon()
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
Returns the acot of x to a multiple of eps with error less in
|
||||
absolute value than .75 * eps.
|
||||
|
||||
v = acot(x) is the number in (0, pi) for which cot(v) = x.
|
||||
|
||||
EXAMPLE
|
||||
> print acot(2, 1e-5), acot(2, 1e-10), acot(2, 1e-15), acot(2, 1e-20)
|
||||
.46365 .463647609 .463647609000806 .46364760900080611621
|
||||
|
||||
LIMITS
|
||||
unlike sin and cos, x must be real
|
||||
eps > 0
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qacot(NUMBER *x, NUMBER *eps)
|
||||
|
||||
SEE ALSO
|
||||
asin, acos, atan, asec, acsc, epsilon
|
33
help/acoth
Normal file
33
help/acoth
Normal file
@@ -0,0 +1,33 @@
|
||||
NAME
|
||||
acoth - inverse hyperbolic cotangent
|
||||
|
||||
SYNOPSIS
|
||||
acoth(x [,eps])
|
||||
|
||||
TYPES
|
||||
x real, with abs(x) > 1
|
||||
eps nonzero real, defaults to epsilon()
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
Returns the acoth of x to a multiple of eps with error less in
|
||||
absolute value than .75 * eps.
|
||||
|
||||
acoth(x) = ln((x + 1)/(x - 1))/2 is the real number v for which
|
||||
coth(v) = x.
|
||||
|
||||
EXAMPLE
|
||||
> print acoth(2, 1e-5), acoth(2, 1e-10), acoth(2, 1e-15), acoth(2, 1e-20)
|
||||
.54931 .5493061443 .549306144334055 .5493061443340548457
|
||||
|
||||
LIMITS
|
||||
unlike sin and cos, x must be real
|
||||
abs(x) > 1
|
||||
eps > 0
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qacoth(NUMBER *x, NUMBER *eps)
|
||||
|
||||
SEE ALSO
|
||||
asinh, acosh, atanh, asech, acsch, epsilon
|
32
help/acsc
Normal file
32
help/acsc
Normal file
@@ -0,0 +1,32 @@
|
||||
NAME
|
||||
acsc - inverse trigonometric cosecant
|
||||
|
||||
SYNOPSIS
|
||||
acsc(x [,eps])
|
||||
|
||||
TYPES
|
||||
x real, with absolute value >= 1
|
||||
eps nonzero real, defaults to epsilon()
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
Returns the acsc of x to a multiple of eps with error less in
|
||||
absolute value than .75 * eps.
|
||||
|
||||
v = acsc(x) is the number in [-pi/2, pi/2] for which csc(v) = x.
|
||||
|
||||
EXAMPLE
|
||||
> print acsc(2, 1e-5), acsc(2, 1e-10), acsc(2, 1e-15), acsc(2, 1e-20)
|
||||
.5236 .5235987756 .523598775598299 .52359877559829887308
|
||||
|
||||
LIMITS
|
||||
unlike sin and cos, x must be real
|
||||
abs(x) >= 1
|
||||
eps > 0
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qacsc(NUMBER *x, NUMBER *eps)
|
||||
|
||||
SEE ALSO
|
||||
asin, acos, atan, asec, acot, epsilon
|
33
help/acsch
Normal file
33
help/acsch
Normal file
@@ -0,0 +1,33 @@
|
||||
NAME
|
||||
acsch - inverse hyperbolic cosecant
|
||||
|
||||
SYNOPSIS
|
||||
acsch(x [,eps])
|
||||
|
||||
TYPES
|
||||
x nonzero real
|
||||
eps nonzero real, defaults to epsilon()
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
Returns the acsch of x to a multiple of eps with error less in
|
||||
absolute value than .75 * eps.
|
||||
|
||||
acsch(x) = ln((1 + sqrt(1 + x^2))/x) is the real number v for
|
||||
which csch(v) = x.
|
||||
|
||||
EXAMPLE
|
||||
> print acsch(2, 1e-5), acsch(2, 1e-10), acsch(2, 1e-15), acsch(2, 1e-20)
|
||||
.48121 .4812118251 .481211825059603 .4812118250596034475
|
||||
|
||||
LIMITS
|
||||
unlike sin and cos, x must be real
|
||||
x != 0
|
||||
eps > 0
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qacsch(NUMBER *x, NUMBER *eps)
|
||||
|
||||
SEE ALSO
|
||||
asinh, acosh, atanh, asech, acoth, epsilon
|
60
help/append
Normal file
60
help/append
Normal file
@@ -0,0 +1,60 @@
|
||||
NAME
|
||||
append - append one or more values to end of list
|
||||
|
||||
SYNOPSIS
|
||||
append(x, y_0, y_1, ...)
|
||||
|
||||
TYPES
|
||||
x lvalue whose value is a list
|
||||
y_0, ... any
|
||||
|
||||
return null value
|
||||
|
||||
DESCRIPTION
|
||||
If after evaluation of y_0, y_1, ..., x is a list with contents
|
||||
(x_0, x_1, ...), then after append(x, y_0, y_1, ...), x has
|
||||
contents (x_0, x_1, ..., y_0, y_1, ...).
|
||||
|
||||
If after evaluation of y_0, y_1, ..., x has size n,
|
||||
append(x, y_0, y_1, ...) is equivalent to insert(x, n, y_0, y_1, ...).
|
||||
|
||||
EXAMPLE
|
||||
> x = list(2,3,4)
|
||||
> append(x, 5, 6)
|
||||
> print x
|
||||
|
||||
list (5 elements, 5 nonzero):
|
||||
[[0]] = 2
|
||||
[[1]] = 3
|
||||
[[2]] = 4
|
||||
[[3]] = 5
|
||||
[[4]] = 6
|
||||
|
||||
> append(x, pop(x), pop(x))
|
||||
> print x
|
||||
|
||||
list (5 elements, 5 nonzero):
|
||||
[[0]] = 4
|
||||
[[1]] = 5
|
||||
[[2]] = 6
|
||||
[[3]] = 2
|
||||
[[4]] = 3
|
||||
|
||||
> append(x, (remove(x), 7))
|
||||
> print x
|
||||
|
||||
list (5 elements, 5 nonzero):
|
||||
[[0]] = 4
|
||||
[[1]] = 5
|
||||
[[2]] = 6
|
||||
[[3]] = 2
|
||||
[[4]] = 7
|
||||
|
||||
LIMITS
|
||||
append() can have at most 100 arguments
|
||||
|
||||
LIBRARY
|
||||
none
|
||||
|
||||
SEE ALSO
|
||||
delete, insert, islist, list, pop, push, remove, rsearch, search, size
|
146
help/appr
Normal file
146
help/appr
Normal file
@@ -0,0 +1,146 @@
|
||||
NAME
|
||||
appr - approximate numbers by multiples of a specified number
|
||||
|
||||
SYNOPSIS
|
||||
appr(x [,y [,z]])
|
||||
|
||||
TYPES
|
||||
x real, complex, matrix, list
|
||||
y real
|
||||
z integer
|
||||
|
||||
return same type as x except that complex x may return a real number
|
||||
|
||||
DESCRIPTION
|
||||
Return the approximate value of x as specified by a specific error
|
||||
(epsilon) and config ("appr") value.
|
||||
|
||||
The default value for y is epsilon(). The default value for z is
|
||||
the current value of the "appr" configuration parameter.
|
||||
|
||||
If y is zero or x is a multiple of y, appr(x,y,z) returns x. I.e.,
|
||||
there is no "approximation" - the result represents x exactly.
|
||||
|
||||
In the following it is assumed y is nonzero and x is not a multiple of y.
|
||||
For Real x:
|
||||
|
||||
appr(x,y,z) is either the nearest multiple of y greater
|
||||
than x or the nearest multiple of y less than x. Thus, if
|
||||
we write a = appr(x,y,z) and r = x - a, then a/y is an integer
|
||||
and abs(r) < abs(y). If r > 0, we say x has been "rounded down"
|
||||
to a; if r < 0, the rounding is "up". For particular x and y,
|
||||
whether the rounding is down or up is determined by z.
|
||||
|
||||
Only the 5 lowest bits of z are used, so we may assume z has been
|
||||
replaced by its value modulo 32. The type of rounding depends on
|
||||
z as follows:
|
||||
|
||||
z = 0 round down or up according as y is positive or negative,
|
||||
sgn(r) = sgn(y)
|
||||
|
||||
z = 1 round up or down according as y is positive or negative,
|
||||
sgn(r) = -sgn(y)
|
||||
|
||||
z = 2 round towards zero, sgn(r) = sgn(x)
|
||||
|
||||
z = 3 round away from zero, sgn(r) = -sgn(x)
|
||||
|
||||
z = 4 round down
|
||||
|
||||
z = 5 round up
|
||||
|
||||
z = 6 round towards or from zero according as y is positive or
|
||||
negative, sgn(r) = sgn(x/y)
|
||||
|
||||
z = 7 round from or towards zero according as y is positive or
|
||||
negative, sgn(r) = -sgn(x/y)
|
||||
|
||||
z = 8 a/y is even
|
||||
|
||||
z = 9 a/y is odd
|
||||
|
||||
z = 10 a/y is even or odd according as x/y is positive or negative
|
||||
|
||||
z = 11 a/y is odd or even according as x/y is positive or negative
|
||||
|
||||
z = 12 a/y is even or odd according as y is positive or negative
|
||||
|
||||
z = 13 a/y is odd or even according as y is positive or negative
|
||||
|
||||
z = 14 a/y is even or odd according as x is positive or negative
|
||||
|
||||
z = 15 a/y is odd or even according as x is positive or negative
|
||||
|
||||
z = 16 to 31 abs(r) <= abs(y)/2; if there is a unique multiple
|
||||
of y that is nearest x, appr(x,y,z) is that multiple of y
|
||||
and then abs(r) < abs(y)/2. If x is midway between
|
||||
successive multiples of y, then abs(r) = abs(y)/2 and
|
||||
the value of a is as given by appr(x, y, z-16).
|
||||
|
||||
Matrix or List x:
|
||||
|
||||
appr(x,y,z) returns the matrix or list indexed in the same way as x,
|
||||
in which each element t has been replaced by appr(t,y,z).
|
||||
|
||||
XXX - complex x needs to be documented
|
||||
|
||||
PROPERTIES
|
||||
If appr(x,y,z) != x, then abs(x - appr(x,y,z)) < abs(y).
|
||||
|
||||
If appr(x,y,z) != x and 16 <= z <= 31, abs(x - appr(x,y,z)) <= abs(y)/2.
|
||||
|
||||
For z = 0, 1, 4, 5, 16, 17, 20 or 21, and any integer n,
|
||||
appr(x + n*y, y, z) = appr(x, y, z) + n * y.
|
||||
|
||||
If y is nonzero, appr(x,y,8)/y = an odd integer n only if x = n * y.
|
||||
|
||||
EXAMPLES
|
||||
> print appr(-5.44,0.1,0), appr(5.44,0.1,0), appr(5.7,1,0), appr(-5.7,1,0)
|
||||
-5.5 5.4 5 -6
|
||||
|
||||
> print appr(-5.44,-.1,0), appr(5.44,-.1,0), appr(5.7,-1,0), appr(-5.7,-1,0)
|
||||
-5.4 5.5 6 -5
|
||||
|
||||
> print appr(-5.44,0.1,3), appr(5.44,0.1,3), appr(5.7,1,3), appr(-5.7,1,3)
|
||||
-5.5 5.5 6 -6
|
||||
|
||||
> print appr(-5.44,0.1,4), appr(5.44,0.1,4), appr(5.7,1,4), appr(-5.7,1,4)
|
||||
-5.5 5.4 5 -6
|
||||
|
||||
> print appr(-5.44,0.1,6), appr(5.44,0.1,6), appr(5.7,1,6), appr(-5.7,1,6)
|
||||
-5.4 5.4 6 -5
|
||||
|
||||
> print appr(-5.44,-.1,6), appr(5.44,-.1,6), appr(5.7,-1,6), appr(-5.7,-1,6)
|
||||
-5.5 5.5 6 -6
|
||||
|
||||
> print appr(-5.44,0.1,9), appr(5.44,0.1,9), appr(5.7,1,9), appr(-5.7,1,9)
|
||||
-5.5 5.5 5 -5
|
||||
|
||||
> print appr(-.44,0.1,11), appr(.44,0.1,11), appr(5.7,1,11), appr(-5.7,1,11)
|
||||
-.4 .5 5 -6
|
||||
|
||||
> print appr(-.44,-.1,11),appr(.44,-.1,11),appr(5.7,-1,11),appr(-5.7,-1,11)
|
||||
-.5 .4 6 -5
|
||||
|
||||
> print appr(-.44,0.1,12), appr(.44,0.1,12), appr(5.7,1,12), appr(-5.7,1,12)
|
||||
-.4 .5 5 -6
|
||||
|
||||
> print appr(-.44,-.1,12),appr(.44,-.1,12),appr(5.7,-1,12),appr(-5.7,-1,12)
|
||||
-.5 .4 6 -5
|
||||
|
||||
> print appr(-.44,0.1,15), appr(.44,0.1,15), appr(5.7,1,15), appr(-5.7,1,15)
|
||||
-.4 .5 5 -6
|
||||
|
||||
> print appr(-.44,-.1,15),appr(.44,-.1,15),appr(5.7,-1,15),appr(-5.7,-1,15)
|
||||
-.4 .5 5 -6
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qmappr(NUMBER *q, NUMBER *e, long R);
|
||||
LIST *listappr(LIST *oldlp, VALUE *v2, VALUE *v3);
|
||||
MATRIX *matappr(MATRIX *m, VALUE *v2, VALUE *v3);
|
||||
|
||||
SEE ALSO
|
||||
round, bround, cfappr, cfsim
|
25
help/archive
Normal file
25
help/archive
Normal file
@@ -0,0 +1,25 @@
|
||||
Where to get the the latest versions of calc
|
||||
|
||||
Landon Noll maintains the official calc ftp archive at:
|
||||
|
||||
ftp://ftp.uu.net/pub/calc
|
||||
|
||||
Alpha test versions, complete with bugs, untested code and
|
||||
experimental features may be fetched (if you are brave) under:
|
||||
|
||||
http://reality.sgi.com/chongo/calc/
|
||||
|
||||
One may join the calc testing group by sending a request to:
|
||||
|
||||
calc-tester-request@postofc.corp.sgi.com
|
||||
|
||||
Your message body (not the subject) should consist of:
|
||||
|
||||
subscribe calc-tester address
|
||||
end
|
||||
name your_full_name
|
||||
|
||||
where "address" is your EMail address and "your_full_name"
|
||||
is your full name.
|
||||
|
||||
Landon Curt Noll <chongo@toad.com> /\oo/\
|
33
help/arg
Normal file
33
help/arg
Normal file
@@ -0,0 +1,33 @@
|
||||
NAME
|
||||
arg - argument (the angle or phase) of a complex number
|
||||
|
||||
SYNOPSIS
|
||||
arg(x [,eps])
|
||||
|
||||
TYPES
|
||||
x number
|
||||
eps nonzero real, defaults to epsilon()
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
Returns the argument of x to the nearest or next to nearest multiple of
|
||||
eps; the error will be less in absolute value than 0.75 * abs(eps),
|
||||
but usually less than 0.5 * abs(eps). By default, acc is epsilon().
|
||||
|
||||
EXAMPLE
|
||||
> print arg(2), arg(2+3i, 1e-5), arg(2+3i, 1e-10), arg(2+3i, 1e-20)
|
||||
0 .98279 .9827937232 .98279372324732906799
|
||||
|
||||
> pi = pi(1e-10); deg = pi/180; eps = deg/10000
|
||||
> print arg(2+3i, eps)/deg, arg(-1 +1i, eps)/deg, arg(-1 - 1i,eps)/deg
|
||||
56.3099 135 -135
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
none
|
||||
|
||||
SEE ALSO
|
||||
conj, im, polar, re
|
32
help/asec
Normal file
32
help/asec
Normal file
@@ -0,0 +1,32 @@
|
||||
NAME
|
||||
asec - inverse trigonometric secant
|
||||
|
||||
SYNOPSIS
|
||||
asec(x [,eps])
|
||||
|
||||
TYPES
|
||||
x real, with absolute value >= 1
|
||||
eps nonzero real, defaults to epsilon()
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
Returns the asec of x to a multiple of eps with error less in
|
||||
absolute value than .75 * eps.
|
||||
|
||||
v = asec(x) is the number in [0, pi] for which sec(v) = x.
|
||||
|
||||
EXAMPLE
|
||||
> print asec(2, 1e-5), asec(2, 1e-10), asec(2, 1e-15), asec(2, 1e-20)
|
||||
1.0472 1.0471975512 1.047197551196598 1.04719755119659774615
|
||||
|
||||
LIMITS
|
||||
unlike sin and cos, x must be real
|
||||
abs(x) >= 1
|
||||
eps > 0
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qasec(NUMBER *x, NUMBER *eps)
|
||||
|
||||
SEE ALSO
|
||||
asin, acos, atan, acsc, acot, epsilon
|
33
help/asech
Normal file
33
help/asech
Normal file
@@ -0,0 +1,33 @@
|
||||
NAME
|
||||
asech - inverse hyperbolic secant
|
||||
|
||||
SYNOPSIS
|
||||
asech(x [,eps])
|
||||
|
||||
TYPES
|
||||
x real, 0 < x <= 1
|
||||
eps nonzero real, defaults to epsilon()
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
Returns the asech of x to a multiple of eps with error less in
|
||||
absolute value than .75 * eps.
|
||||
|
||||
asech(x) = ln((1 + sqrt(1 - x^2))/x) is the real number v for which
|
||||
sech(v) = x.
|
||||
|
||||
EXAMPLE
|
||||
> print asech(.5,1e-5), asech(.5,1e-10), asech(.5,1e-15), asech(.5,1e-20)
|
||||
1.31696 1.3169578969 1.316957896924817 1.31695789692481670862
|
||||
|
||||
LIMITS
|
||||
unlike sin and cos, x must be real
|
||||
0 < x <= 1
|
||||
eps > 0
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qasech(NUMBER *x, NUMBER *eps)
|
||||
|
||||
SEE ALSO
|
||||
asinh, acosh, atanh, acsch, acoth, epsilon
|
32
help/asin
Normal file
32
help/asin
Normal file
@@ -0,0 +1,32 @@
|
||||
NAME
|
||||
asin - inverse trigonometric sine
|
||||
|
||||
SYNOPSIS
|
||||
asin(x [,eps])
|
||||
|
||||
TYPES
|
||||
x real, -1 <= x <= 1
|
||||
eps nonzero real, defaults to epsilon()
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
Returns the asin of x to a multiple of eps with error less in
|
||||
absolute value than .75 * eps.
|
||||
|
||||
v = asin(x) is the number in [-p1/2, pi/2] for which sin(v) = x.
|
||||
|
||||
EXAMPLE
|
||||
> print asin(.5, 1e-5), asin(.5, 1e-10), asin(.5, 1e-15), asin(.5, 1e-20)
|
||||
.5236 .5235987756 .523598775598299 .52359877559829887308
|
||||
|
||||
LIMITS
|
||||
unlike sin and cos, x must be real
|
||||
abs(x) <= 1
|
||||
eps > 0
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qasin(NUMBER *q, NUMBER *epsilon)
|
||||
|
||||
SEE ALSO
|
||||
acos, atan, asec, acsc, acot, epsilon
|
32
help/asinh
Normal file
32
help/asinh
Normal file
@@ -0,0 +1,32 @@
|
||||
NAME
|
||||
asinh - inverse hyperbolic sine
|
||||
|
||||
SYNOPSIS
|
||||
asinh(x [,eps])
|
||||
|
||||
TYPES
|
||||
x real
|
||||
eps nonzero real, defaults to epsilon()
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
Returns the asinh of x to a multiple of eps with error less in
|
||||
absolute value than .75 * eps.
|
||||
|
||||
asinh(x) = ln(x + sqrt(1 + x^2)) is the real number v for which
|
||||
sinh(v) = x.
|
||||
|
||||
EXAMPLE
|
||||
> print asinh(2, 1e-5), asinh(2, 1e-10), asinh(2, 1e-15), asinh(2, 1e-20)
|
||||
1.44363 1.4436354752 1.44363547517881 1.44363547517881034249
|
||||
|
||||
LIMITS
|
||||
unlike sin and cos, x must be real
|
||||
eps > 0
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qasinh(NUMBER *x, NUMBER *eps)
|
||||
|
||||
SEE ALSO
|
||||
acosh, atanh, asech, acsch, acoth, epsilon
|
29
help/assign
Normal file
29
help/assign
Normal file
@@ -0,0 +1,29 @@
|
||||
NAME
|
||||
=
|
||||
|
||||
SYNOPSIS
|
||||
a = b
|
||||
|
||||
TYPES
|
||||
a lvalue
|
||||
b expression
|
||||
|
||||
return lvalue
|
||||
|
||||
DESCRIPTION
|
||||
a = b evaluates b, assigns its value to a, and returns a.
|
||||
|
||||
EXAMPLE
|
||||
> b = 3+1
|
||||
> a = b
|
||||
> print a, b
|
||||
4 4
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
none
|
||||
|
||||
SEE ALSO
|
||||
XXX - fill in
|
79
help/assoc
Normal file
79
help/assoc
Normal file
@@ -0,0 +1,79 @@
|
||||
NAME
|
||||
assoc - create a new association array
|
||||
|
||||
SYNOPSIS
|
||||
assoc()
|
||||
|
||||
TYPES
|
||||
return association
|
||||
|
||||
DESCRIPTION
|
||||
This functions returns an empty association array.
|
||||
|
||||
Associations are special values that act like matrices, except
|
||||
that they are more general (and slower) than normal matrices.
|
||||
Unlike matrices, associations can be indexed by arbitrary values.
|
||||
For example, if 'val' was an association, you could do the following:
|
||||
|
||||
val['hello'] = 11;
|
||||
val[4.5] = val['hello'];
|
||||
print val[9/2];
|
||||
|
||||
and 11 would be printed.
|
||||
|
||||
Associations are created by the 'assoc' function. It takes no
|
||||
arguments, and simply returns an empty association. You can then
|
||||
insert elements into the association by indexing the returned value
|
||||
as shown above.
|
||||
|
||||
Associations are multi-dimensional. You can index them using one to
|
||||
four dimensions as desired, and the elements with different numbers
|
||||
of dimensions will remain separated. For example, 'val[3]' and
|
||||
'val[3,0]' can both be used in the same association and will be
|
||||
distinct elements.
|
||||
|
||||
When references are made to undefined elements of an association,
|
||||
a null value is simply returned. Therefore no bounds errors can
|
||||
occur when indexing an association. Assignments of a null value
|
||||
to an element of an association does not delete the element, but
|
||||
a later reference to that element will return the null value as if
|
||||
the element was undefined. Elements with null values are implicitly
|
||||
created on certain other operations which require an address to be
|
||||
taken, such as the += operator and using & in a function call.
|
||||
|
||||
The elements of an association are stored in a hash table for
|
||||
quick access. The index values are hashed to select the correct
|
||||
hash chain for a small sequential search for the element. The hash
|
||||
table will be resized as necessary as the number of entries in
|
||||
the association becomes larger.
|
||||
|
||||
The size function returns the number of elements in an association.
|
||||
This size will include elements with null values.
|
||||
|
||||
Double bracket indexing can be used for associations to walk through
|
||||
the elements of the association. The order that the elements are
|
||||
returned in as the index increases is essentially random. Any
|
||||
change made to the association can reorder the elements, this making
|
||||
a sequential scan through the elements difficult.
|
||||
|
||||
The search and rsearch functions can search for an element in an
|
||||
association which has the specified value. They return the index
|
||||
of the found element, or a NULL value if the value was not found.
|
||||
|
||||
Associations can be copied by an assignment, and can be compared
|
||||
for equality. But no other operations on associations have meaning,
|
||||
and are illegal.
|
||||
|
||||
EXAMPLE
|
||||
> print assoc()
|
||||
|
||||
assoc (0 elements):
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
none
|
||||
|
||||
SEE ALSO
|
||||
isassoc, rsearch, search, size
|
31
help/atan
Normal file
31
help/atan
Normal file
@@ -0,0 +1,31 @@
|
||||
NAME
|
||||
atan - inverse trigonometric tangent
|
||||
|
||||
SYNOPSIS
|
||||
atan(x [,eps])
|
||||
|
||||
TYPES
|
||||
x real
|
||||
eps nonzero real, defaults to epsilon()
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
Returns the atan of x to a multiple of eps with error less in
|
||||
absolute value than .75 * eps.
|
||||
|
||||
v = atan(x) is the number in (-p1/2, pi/2) for which tan(v) = x.
|
||||
|
||||
EXAMPLE
|
||||
> print atan(2, 1e-5), atan(2, 1e-10), atan(2, 1e-15), atan(2, 1e-20)
|
||||
1.10715 1.1071487178 1.107148717794091 1.10714871779409050302
|
||||
|
||||
LIMITS
|
||||
unlike sin and cos, x must be real
|
||||
eps > 0
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qatan(NUMBER *x, NUMBER *eps)
|
||||
|
||||
SEE ALSO
|
||||
asin, acos, asec, acsc, acot, epsilon
|
36
help/atan2
Normal file
36
help/atan2
Normal file
@@ -0,0 +1,36 @@
|
||||
NAME
|
||||
atan2 - angle to point
|
||||
|
||||
SYNOPSIS
|
||||
atan2(y, x, [,acc])
|
||||
|
||||
TYPES
|
||||
y real
|
||||
x real
|
||||
acc real
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
Return the angle which is determined by the point (x,y). This
|
||||
function computes the arctangent of y/x in the range [-pi, pi].
|
||||
The value acc specifies the accuracy of the result. By default, acc
|
||||
is epsilon().
|
||||
|
||||
Note that by convention, y is the first argument.
|
||||
|
||||
To conform to the 4.3BSD ANSI/IEEE 754-1985 math lib, atan2(0,0) is
|
||||
defined to return 0.
|
||||
|
||||
EXAMPLE
|
||||
> print atan2(0,0), atan2(1,sqrt(3)), atan2(17,53,1e-100)
|
||||
0 ~.52359877559829887307 ~.31038740713235146535
|
||||
|
||||
LIMITS
|
||||
acc > 0
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qatan2(NUMBER *y, *x, *acc)
|
||||
|
||||
SEE ALSO
|
||||
acos, asin, atan, cos, epsilon, sin, tan
|
32
help/atanh
Normal file
32
help/atanh
Normal file
@@ -0,0 +1,32 @@
|
||||
NAME
|
||||
atanh - inverse hyperbolic tangent
|
||||
|
||||
SYNOPSIS
|
||||
atanh(x [,eps])
|
||||
|
||||
TYPES
|
||||
x real
|
||||
eps nonzero real, defaults to epsilon()
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
Returns the atanh of x to a multiple of eps with error less in
|
||||
absolute value than .75 * eps.
|
||||
|
||||
atanh(x) = ln((1 + x)/(1 - x))/2 is the real number v for whichi
|
||||
tanh(v) = x.
|
||||
|
||||
EXAMPLE
|
||||
> print atanh(.5,1e-5), atanh(.5,1e-10), atanh(.5,1e-15), atanh(.5,1e-20)
|
||||
.54931 .5493061443 .549306144334055 .5493061443340548457
|
||||
|
||||
LIMITS
|
||||
unlike sin and cos, x must be real
|
||||
eps > 0
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qatanh(NUMBER *x, NUMBER *eps)
|
||||
|
||||
SEE ALSO
|
||||
asinh, acosh, asech, acsch, acoth, epsilon
|
50
help/avg
Normal file
50
help/avg
Normal file
@@ -0,0 +1,50 @@
|
||||
NAME
|
||||
avg - average (arithmetic) mean of values
|
||||
|
||||
SYNOPSIS
|
||||
avg(x_1, x_2, ...)
|
||||
|
||||
TYPES
|
||||
x_1, ... arithmetic or list
|
||||
|
||||
return as determined by types of items averaged
|
||||
|
||||
DESCRIPTION
|
||||
If there are n non-list arguments x_1, x_2, ..., x_n,
|
||||
for which the required additions and division by n are defined,
|
||||
avg(x_1, x_2, ..., x_n) returns the value of:
|
||||
|
||||
(x_1 + x_2 + ... + x_n)/n.
|
||||
|
||||
If the x_i are real, the result will be a real number; if the
|
||||
x_i are real or complex numbers, the result will be a real or complex
|
||||
number. If the x_i are summable matrices the result will be a matrix
|
||||
of the same size (e.g. if the x_i are all 3 x 4 matrices with real
|
||||
entries, the result will be a 3 x 4 matrix with real entries).
|
||||
|
||||
If an argument x_i is list-valued, e.g. list(y_1, y_2, ...), this
|
||||
is treated as contributing y_1, y_2, ... to the list of items to
|
||||
be averaged.
|
||||
|
||||
EXAMPLE
|
||||
> print avg(1,2,3,4,5), avg(list(1,2,3,4,5)), avg(1,2,list(3,4,5))
|
||||
3 3 3
|
||||
|
||||
> mat x[2,2] = {1,2,3,4}
|
||||
> mat y[2,2] = {1,2,4,8}
|
||||
> avg(x,y)
|
||||
|
||||
mat [2,2] (4 elements, 4 nonzero):
|
||||
[0,0] = 1
|
||||
[0,1] = 2
|
||||
[1,0] = 3.5
|
||||
[1,1] = 6
|
||||
|
||||
LIMITS
|
||||
The number of arguments is not to exceed 100.
|
||||
|
||||
LIBRARY
|
||||
none
|
||||
|
||||
SEE ALSO
|
||||
hmean
|
55
help/base
Normal file
55
help/base
Normal file
@@ -0,0 +1,55 @@
|
||||
NAME
|
||||
base - set default output base
|
||||
|
||||
SYNOPSIS
|
||||
base([mode])
|
||||
|
||||
TYPES
|
||||
mode real
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
The base function allows one to specify how numbers should be
|
||||
printer. The base function provides a numeric shorthand to the
|
||||
config("mode") interface. With no args, base() will return the
|
||||
current mode. With 1 arg, base(val) will set the mode according to
|
||||
the arg and return the previous mode.
|
||||
|
||||
The following convention is used to declare modes:
|
||||
|
||||
base config
|
||||
value string
|
||||
|
||||
2 "binary" binary fractions
|
||||
8 "octal" octal fractions
|
||||
10 "real" decimal floating point
|
||||
16 "hex" hexadecimal fractions
|
||||
-10 "int" decimal integer
|
||||
1/3 "frac" decimal fractions
|
||||
1e20 "exp" decimal exponential
|
||||
|
||||
For convenience, any non-integer value is assumed to mean "frac",
|
||||
and any integer >= 2^64 is assumed to mean "exp".
|
||||
|
||||
EXAMPLE
|
||||
> base()
|
||||
10
|
||||
|
||||
> base(8)
|
||||
012
|
||||
|
||||
> print 10
|
||||
012
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
int math_setmode(int newmode)
|
||||
|
||||
NOTE: newmode must be one of MODE_DEFAULT, MODE_FRAC, MODE_INT,
|
||||
MODE_REAL, MODE_EXP, MODE_HEX, MODE_OCTAL, MODE_BINARY
|
||||
|
||||
SEE ALSO
|
||||
config
|
123
help/bround
Normal file
123
help/bround
Normal file
@@ -0,0 +1,123 @@
|
||||
NAME
|
||||
bround - round numbers to a specified number of binary digits
|
||||
|
||||
SYNOPSIS
|
||||
bround(x [,plcs [, rnd]])
|
||||
|
||||
TYPES
|
||||
If x is a matrix or a list, bround(x[[i]], ...) is to return
|
||||
a value for each element x[[i]] of x; the value returned will be
|
||||
a matrix or list with the same structure as x.
|
||||
|
||||
Otherwise, if x is an object of type tt, or if x is not an object or
|
||||
number but y is an object of type tt, and the function tt_bround has
|
||||
to be defined; the types for x, plcs, rnd, and the returned value,
|
||||
if any, are as required for specified in tt_bround. For the object
|
||||
case, plcs and rnd default to the null value.
|
||||
|
||||
For other cases:
|
||||
|
||||
x number (real or complex)
|
||||
plcs integer, defaults to zero
|
||||
rnd integer, defaults to config("round")
|
||||
|
||||
return number
|
||||
|
||||
DESCRIPTION
|
||||
For real x, bround(x, plcs, rnd) returns x rounded to either
|
||||
plcs significant binary digits (if rnd & 32 is nonzero) or to plcs
|
||||
binary places (if rnd & 32 is zero). In the significant-figure
|
||||
case the rounding is to plcs - ilog10(x) - 1 binary places.
|
||||
If the number of binary places is n and eps = 10^-n, the
|
||||
result is the same as for appr(x, eps, rnd). This will be
|
||||
exactly x if x is a multiple of eps; otherwise rounding occurs
|
||||
to one of the nearest multiples of eps on either side of x. Which
|
||||
of these multiples is returned is determined by z = rnd & 31, i.e.
|
||||
the five low order bits of rnd, as follows:
|
||||
|
||||
z = 0 or 4: round down, i.e. towards minus infinity
|
||||
z = 1 or 5: round up, i.e. towards plus infinity
|
||||
z = 2 or 6: round towards zero
|
||||
z = 3 or 7: round away from zero
|
||||
z = 8 or 12: round to the nearest even multiple of eps
|
||||
z = 9 or 13: round to the nearest odd multiple of eps
|
||||
z = 10 or 14: round to nearest even or odd multiple of eps
|
||||
according as x > or < 0
|
||||
z = 11 or 15: round to nearest odd or even multiple of eps
|
||||
according as x > or < 0
|
||||
z = 16 to 31: round to the nearest multiple of eps when
|
||||
this is uniquely determined. Otherwise
|
||||
rounding is as if z is replaced by z - 16
|
||||
|
||||
For complex x:
|
||||
|
||||
The real and imaginary parts are rounded as for real x; if the
|
||||
imaginary part rounds to zero, the result is real.
|
||||
|
||||
For matrix or list x:
|
||||
|
||||
The returned values has element bround(x[[i]], plcs, rnd) in
|
||||
the same position as x[[i]] in x.
|
||||
|
||||
For object x or plcs:
|
||||
|
||||
When bround(x, plcs, rnd) is called, x is passed by address so may be
|
||||
changed by assignments; plcs and rnd are copied to temporary
|
||||
variables, so their values are not changed by the call.
|
||||
|
||||
EXAMPLES
|
||||
> a = 7/32, b = -7/32
|
||||
|
||||
> print a, b
|
||||
.21875 -.21875
|
||||
|
||||
> print round(a,3,0), round(a,3,1), round(a,3,2), print round(a,3,3)
|
||||
.218, .219, .218, .219
|
||||
|
||||
> print round(b,3,0), round(b,3,1), round(b,3,2), print round(b,3,3)
|
||||
-.219, -.218, -.218, -.219
|
||||
|
||||
> print round(a,3,16), round(a,3,17), round(a,3,18), print round(a,3,19)
|
||||
.2188 .2188 .2188 .2188
|
||||
|
||||
> print round(a,4,16), round(a,4,17), round(a,4,18), print round(a,4,19)
|
||||
.2187 .2188 .2187 .2188
|
||||
|
||||
> print round(a,2,8), round(a,3,8), round(a,4,8), round(a,5,8)
|
||||
.22 .218 .2188 .21875
|
||||
|
||||
> print round(a,2,24), round(a,3,24), round(a,4,24), round(a,5,24)
|
||||
.22 .219 .2188 .21875
|
||||
|
||||
> c = 21875
|
||||
> print round(c,-2,0), round(c,-2,1), round(c,-3,0), round(c,-3,16)
|
||||
21800 21900 21000 22000
|
||||
|
||||
> print round(c,2,32), round(c,2,33), round(c,2,56), round(c,4,56)
|
||||
21000 22000 22000 21880
|
||||
|
||||
> A = list(1/8, 2/8, 3/8, 4/8, 5/8, 6/8, 7/8)
|
||||
> print round(A,2,24)
|
||||
|
||||
list(7 elements, 7 nonzero):
|
||||
[[0]] = .12
|
||||
[[1]] = .25
|
||||
[[3]] = .38
|
||||
[[4]] = .5
|
||||
[[5]] = .62
|
||||
[[6]] = .75
|
||||
[[7]] = .88
|
||||
|
||||
LIMITS
|
||||
For non-object case:
|
||||
0 <= abs(plcs) < 2^31
|
||||
0 <= abs(rnd) < 2^31
|
||||
|
||||
LIBRARY
|
||||
void broundvalue(VALUE *x, VALUE *plcs, VALUE *rnd, VALUE *result)
|
||||
MATRIX *matbround(MATRIX *m, VALUE *plcs, VALUE *rnd);
|
||||
LIST *listbround(LIST *m, VALUE *plcs, VALUE *rnd);
|
||||
NUMBER *qbround(NUMBER *m, long plcs, long rnd);
|
||||
|
||||
SEE ALSO
|
||||
round, trunc, btrunc, int, appr
|
36
help/btrunc
Normal file
36
help/btrunc
Normal file
@@ -0,0 +1,36 @@
|
||||
NAME
|
||||
btrunc - truncate a value to a number of binary places
|
||||
|
||||
SYNOPSIS
|
||||
btrunc(x [,j])
|
||||
|
||||
TYPES
|
||||
x real
|
||||
j int
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
Truncate x to j binary places. If j is omitted, 0 places is assumed.
|
||||
Specifying zero places makes the result identical to int().
|
||||
|
||||
Truncation of a non-integer prodcues values nearer to zero.
|
||||
|
||||
EXAMPLE
|
||||
> print btrunc(pi()), btrunc(pi(), 10)
|
||||
3 3.140625
|
||||
|
||||
> print btrunc(3.3), btrunc(3.7), btrunc(3.3, 2), btrunc(3.7, 2)
|
||||
3 3 3.25 3.5
|
||||
|
||||
> print btrunc(-3.3), btrunc(-3.7), btrunc(-3.3, 2), btrunc(-3.7, 2)
|
||||
-3 -3 -3.25 -3.5
|
||||
|
||||
LIMITS
|
||||
0 <= j < 2^31
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qbtrunc(NUMBER *x, *j)
|
||||
|
||||
SEE ALSO
|
||||
bround, int, round, trunc
|
200
help/builtin.end
Normal file
200
help/builtin.end
Normal file
@@ -0,0 +1,200 @@
|
||||
|
||||
The config function sets or reads the value of a configuration
|
||||
parameter. The first argument is a string which names the parameter
|
||||
to be set or read. If only one argument is given, then the current
|
||||
value of the named parameter is returned. If two arguments are given,
|
||||
then the named parameter is set to the value of the second argument,
|
||||
and the old value of the parameter is returned. Therefore you can
|
||||
change a parameter and restore its old value later. The possible
|
||||
parameters are explained in the next section.
|
||||
|
||||
The scale function multiplies or divides a number by a power of 2.
|
||||
This is used for fractional calculations, unlike the << and >>
|
||||
operators, which are only defined for integers. For example,
|
||||
scale(6, -3) is 3/4.
|
||||
|
||||
The quomod function is used to obtain both the quotient and remainder
|
||||
of a division in one operation. The first two arguments a and b are
|
||||
the numbers to be divided. The last two arguments c and d are two
|
||||
variables which will be assigned the quotient and remainder. For
|
||||
nonnegative arguments, the results are equivalent to computing a//b
|
||||
and a%b. If a is negative and the remainder is nonzero, then the
|
||||
quotient will be one less than a//b. This makes the following three
|
||||
properties always hold: The quotient c is always an integer. The
|
||||
remainder d is always 0 <= d < b. The equation a = b * c + d always
|
||||
holds. This function returns 0 if there is no remainder, and 1 if
|
||||
there is a remainder. For examples, quomod(10, 3, x, y) sets x to 3,
|
||||
y to 1, and returns the value 1, and quomod(-4, 3.14159, x, y) sets x
|
||||
to -2, y to 2.28318, and returns the value 1.
|
||||
|
||||
The eval function accepts a string argument and evaluates the
|
||||
expression represented by the string and returns its value.
|
||||
The expression can include function calls and variable references.
|
||||
For example, eval("fact(3) + 7") returns 13. When combined with
|
||||
the prompt function, this allows the calculator to read values from
|
||||
the user. For example, x=eval(prompt("Number: ")) sets x to the
|
||||
value input by the user.
|
||||
|
||||
The digit and isset functions return individual digits of a number,
|
||||
either in base 10 or in base 2, where the lowest digit of a number
|
||||
is at digit position 0. For example, digit(5678, 3) is 5, and
|
||||
isset(0b1000100, 2) is 1. Negative digit positions indicate places
|
||||
to the right of the decimal or binary point, so that for example,
|
||||
digit(3.456, -1) is 4.
|
||||
|
||||
The ptest builtin is a primality testing function. The
|
||||
1st argument is the suspected prime to be tested. The
|
||||
absolute value of the 2nd argument is an iteration count.
|
||||
|
||||
If ptest is called with only 2 args, the 3rd argument is
|
||||
assumed to be 0. If ptest is called with only 1 arg, the
|
||||
2nd argument is assumed to be 1. Thus, the following
|
||||
calls are equivalent:
|
||||
|
||||
ptest(a)
|
||||
ptest(a,1)
|
||||
ptest(a,1,0)
|
||||
|
||||
Normally ptest performs a some checks to determine if the
|
||||
value is divisable by some trivial prime. If the 2nd
|
||||
argument is < 0, then the trivial check is omitted.
|
||||
|
||||
For example, ptest(a,10) performs the same work as:
|
||||
|
||||
ptest(a,-3) (7 tests without trivial check)
|
||||
ptest(a,-7,3) (3 more tests without the trivial check)
|
||||
|
||||
The ptest function returns 0 if the number is definitely not
|
||||
prime, and 1 is the number is probably prime. The chance
|
||||
of a number which is probably prime being actually composite
|
||||
is less than 1/4 raised to the power of the iteration count.
|
||||
For example, for a random number p, ptest(p, 10) incorrectly
|
||||
returns 1 less than once in every million numbers, and you
|
||||
will probably never find a number where ptest(p, 20) gives
|
||||
the wrong answer.
|
||||
|
||||
The first 3 args of nextcand and prevcand functions are the same
|
||||
arguments as ptest. But unlike ptest, nextcand and prevcand return
|
||||
the next and previous values for which ptest is true.
|
||||
|
||||
For example, nextcand(2^1000) returns 2^1000+297 because
|
||||
2^1000+297 is the smallest value x > 2^1000 for which
|
||||
ptest(x,1) is true. And for example, prevcand(2^31-1,10,5)
|
||||
returns 2147483629 (2^31-19) because 2^31-19 is the largest
|
||||
value y < 2^31-1 for which ptest(y,10,5) is true.
|
||||
|
||||
The nextcand and prevcand functions also have a 5 argument form:
|
||||
|
||||
nextcand(num, count, skip, modval, modulus)
|
||||
prevcand(num, count, skip, modval, modulus)
|
||||
|
||||
return the smallest (or largest) value ans > num (or < num) that
|
||||
is also == modval % modulus for which ptest(ans,count,skip) is true.
|
||||
|
||||
The builtins nextprime(x) and prevprime(x) return the
|
||||
next and previous primes with respect to x respectively.
|
||||
As of this release, x must be < 2^32. With one argument, they
|
||||
will return an error if x is out of range. With two arguments,
|
||||
they will not generate an error but instead will return y.
|
||||
|
||||
The builtin function pix(x) returns the number of primes <= x.
|
||||
As of this release, x must be < 2^32. With one argument, pix(x)
|
||||
will return an error if x is out of range. With two arguments,
|
||||
pix(x,y) will not generate an error but instead will return y.
|
||||
|
||||
The builtin function factor may be used to search for the
|
||||
smallest factor of a given number. The call factor(x,y)
|
||||
will attempt to find the smallest factor of x < min(x,y).
|
||||
As of this release, y must be < 2^32. If y is omitted, y
|
||||
is assumed to be 2^32-1.
|
||||
|
||||
If x < 0, factor(x,y) will return -1. If no factor <
|
||||
min(x,y) is found, factor(x,y) will return 1. In all other
|
||||
cases, factor(x,y) will return the smallest prime factor
|
||||
of x. Note except for the case when abs(x) == 1, factor(x,y)
|
||||
will not return x.
|
||||
|
||||
If factor is called with y that is too large, or if x or y
|
||||
is not an integer, calc will report an error. If a 3rd argument
|
||||
is given, factor will return that value instead. For example,
|
||||
factor(1/2,b,c) will return c instead of issuing an error.
|
||||
|
||||
The builtin lfactor(x,y) searches a number of primes instead
|
||||
of below a limit. As of this release, y must be <= 203280221
|
||||
(y <= pix(2^32-1)). In all other cases, lfactor is operates
|
||||
in the same way as factor.
|
||||
|
||||
If lfactor is called with y that is too large, or if x or y
|
||||
is not an integer, calc will report an error. If a 3rd argument
|
||||
is given, lfactor will return that value instead. For example,
|
||||
lfactor(1/2,b,c) will return c instead of issuing an error.
|
||||
|
||||
The lfactor function is slower than factor. If possible factor
|
||||
should be used instead of lfactor.
|
||||
|
||||
The builtin isprime(x) will attempt to determine if x is prime.
|
||||
As of this release, x must be < 2^32. With one argument, isprime(x)
|
||||
will return an error if x is out of range. With two arguments,
|
||||
isprime(x,y) will not generate an error but instead will return y.
|
||||
|
||||
The functions rcin, rcmul, rcout, rcpow, and rcsq are used to
|
||||
perform modular arithmetic calculations for large odd numbers
|
||||
faster than the usual methods. To do this, you first use the
|
||||
rcin function to convert all input values into numbers which are
|
||||
in a format called REDC format. Then you use rcmul, rcsq, and
|
||||
rcpow to multiply such numbers together to produce results also
|
||||
in REDC format. Finally, you use rcout to convert a number in
|
||||
REDC format back to a normal number. The addition, subtraction,
|
||||
negation, and equality comparison between REDC numbers are done
|
||||
using the normal modular methods. For example, to calculate the
|
||||
value 13 * 17 + 1 (mod 11), you could use:
|
||||
|
||||
p = 11;
|
||||
t1 = rcin(13, p);
|
||||
t2 = rcin(17, p);
|
||||
t3 = rcin(1, p);
|
||||
t4 = rcmul(t1, t2, p);
|
||||
t5 = (t4 + t3) % p;
|
||||
answer = rcout(t5, p);
|
||||
|
||||
The swap function exchanges the values of two variables without
|
||||
performing copies. For example, after:
|
||||
|
||||
x = 17;
|
||||
y = 19;
|
||||
swap(x, y);
|
||||
|
||||
then x is 19 and y is 17. This function should not be used to
|
||||
swap a value which is contained within another one. If this is
|
||||
done, then some memory will be lost. For example, the following
|
||||
should not be done:
|
||||
|
||||
mat x[5];
|
||||
swap(x, x[0]);
|
||||
|
||||
The hash function returns a relatively small non-negative integer
|
||||
for one or more input values. The hash values should not be used
|
||||
across runs of the calculator, since the algorithms used to generate
|
||||
the hash value may change with different versions of the calculator.
|
||||
|
||||
The base function allows one to specify how numbers should be
|
||||
printer. The base function provides a numeric shorthand to the
|
||||
config("mode") interface. With no args, base() will return the
|
||||
current mode. With 1 arg, base(val) will set the mode according to
|
||||
the arg and return the previous mode.
|
||||
|
||||
The following convention is used to declare modes:
|
||||
|
||||
base config
|
||||
value string
|
||||
|
||||
2 "binary" binary fractions
|
||||
8 "octal" octal fractions
|
||||
10 "real" decimal floating point
|
||||
16 "hex" hexadecimal fractions
|
||||
-10 "int" decimal integer
|
||||
1/3 "frac" decimal fractions
|
||||
1e20 "exp" decimal exponential
|
||||
|
||||
For convenience, any non-integer value is assumed to mean "frac",
|
||||
and any integer >= 2^64 is assumed to mean "exp".
|
9
help/builtin.top
Normal file
9
help/builtin.top
Normal file
@@ -0,0 +1,9 @@
|
||||
Builtin functions
|
||||
|
||||
There is a large number of built-in functions. Many of the
|
||||
functions work on several types of arguments, whereas some only
|
||||
work for the correct types (e.g., numbers or strings). In the
|
||||
following description, this is indicated by whether or not the
|
||||
description refers to values or numbers. This display is generated
|
||||
by the 'show builtin' command.
|
||||
|
33
help/ceil
Normal file
33
help/ceil
Normal file
@@ -0,0 +1,33 @@
|
||||
NAME
|
||||
ceil - ceiling
|
||||
|
||||
SYNOPSIS
|
||||
ceil(x)
|
||||
|
||||
TYPES
|
||||
x real, complex, list, matrix
|
||||
|
||||
return real or complex, list, matrix
|
||||
|
||||
DESCRIPTION
|
||||
For real x, ceil(x) is the least integer not less than x.
|
||||
|
||||
For complex, ceil(x) returns the real or complex number v for
|
||||
which re(v) = ceil(re(x)), im(v) = ceil(im(x)).
|
||||
|
||||
For list or matrix x, ceil(x) returns the list or matrix of the
|
||||
same structure as x for which each element t of x has been replaced
|
||||
by ceil(t).
|
||||
|
||||
EXAMPLE
|
||||
> print ceil(27), ceil(1.23), ceil(-4.56), ceil(7.8 - 9.1i)
|
||||
27 2 -4 8-9i
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
none
|
||||
|
||||
SEE ALSO
|
||||
floor, int
|
89
help/cfappr
Normal file
89
help/cfappr
Normal file
@@ -0,0 +1,89 @@
|
||||
NAME
|
||||
cfappr - approximate a real number using continued fractions
|
||||
|
||||
SYNOPSIS
|
||||
cfappr(x [,eps [,rnd]]) or cfappr(x, n [,rnd])
|
||||
|
||||
TYPES
|
||||
x real
|
||||
eps real with abs(eps) < 1, defaults to epsilon()
|
||||
n real with n >= 1
|
||||
rnd integer, defaults to config("cfappr")
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
If x is an integer or eps is zero, either form returns x.
|
||||
|
||||
If abs(eps) < 1, cfappr(x, eps) returns the smallest-denominator
|
||||
number in one of the three intervals, [x, x + abs(eps)],
|
||||
[x - abs(eps], x], [x - abs(eps)/2, x + abs(eps)/2].
|
||||
|
||||
If n >= 1 and den(x) > n, cfappr(x, n) returns the nearest above,
|
||||
nearest below, or nearest, approximation to x with denominator less
|
||||
than or equal to n. If den(x) <= n, cfappr(x,n) returns x.
|
||||
|
||||
In either case when the result v is not x, how v relates to x is
|
||||
determined by bits 0, 1, 2 and 4 of the argument rnd in the same way as
|
||||
these bits are used in the functions round() and appr(). In the
|
||||
following y is either eps or n.
|
||||
|
||||
rnd sign of remainder x - v
|
||||
|
||||
0 sgn(y)
|
||||
1 -sgn(y
|
||||
2 sgn(x), "rounding to zero"
|
||||
3 -sgn(x), "rounding from zero"
|
||||
4 +, "rounding down"
|
||||
5 -, "rounding up"
|
||||
6 sgn(x/y)
|
||||
7 -sgn(x/y)
|
||||
|
||||
If bit 4 of rnd is set, the other bits are irrelevant for the eps case;
|
||||
thus for 16 <= rnd < 24, cfappr(x, eps, rnd) is the smallest-denominator
|
||||
number differing from x by at most abs(eps)/2.
|
||||
|
||||
If bit 4 of rnd is set and den(x) > 2, the other bits are irrelevant for
|
||||
the bounded denominator case; in the case of two equally near nearest
|
||||
approximations with denominator less than n, cfappr(x, n, rnd)
|
||||
returns the number with smaller denominator. If den(x) = 2, bits
|
||||
0, 1 and 2 of rnd are used as described above.
|
||||
|
||||
If -1 < eps < 1, cfappr(x, eps, 0) may be described as the smallest
|
||||
denominator number in the closed interval with end-points x and x - eps.
|
||||
It follows that if abs(a - b) < 1, cfappr(a, a - b, 0) gives the smallest
|
||||
denominator number in the interval with end-points a and b; the same
|
||||
result is returned by cfappr(b, b - a, 0) or cfappr(a, b - a, 1).
|
||||
|
||||
If abs(eps) < 1 and v = cfappr(x, eps, rnd), then
|
||||
cfappr(x, sgn(eps) * den(v), rnd) = v.
|
||||
|
||||
If 1 <= n < den(x), u = cfappr(x, n, 0) and v = cfappr(x, n, 1), then
|
||||
u < x < v, den(u) <= n, den(v) <= n, den(u) + den(v) > n, and
|
||||
v - u = 1/(den(u) * den(v)).
|
||||
|
||||
If x is not zero, the nearest approximation with numerator not
|
||||
exceeding n is 1/cfappr(1/x, n, 16).
|
||||
|
||||
EXAMPLE
|
||||
> c = config("mode", "frac")
|
||||
> x = 43/30; u = cfappr(x, 10, 0); v = cfappr(x, 10, 1);
|
||||
> print u, v, x - u, v - x, v - u, cfappr(x, 10, 16)
|
||||
10/7 13/9 1/210 1/90 1/63 10/7
|
||||
|
||||
> pi = pi(1e-10)
|
||||
> print cfappr(pi, 100, 16), cfappr(pi, .01, 16), cfappr(pi, 1e-6, 16)
|
||||
311/99 22/7 355/113
|
||||
|
||||
> x = 17/12; u = cfappr(x,4,0); v = cfappr(x,4,1);
|
||||
> print u, v, x - u, v - x, cfappr(x,4,16)
|
||||
4/3 3/2 1/12 1/12 3/2
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qcfappr(NUMBER *q, NUMBER *epsilon, long R)
|
||||
|
||||
SEE ALSO
|
||||
appr, cfsim
|
114
help/cfsim
Normal file
114
help/cfsim
Normal file
@@ -0,0 +1,114 @@
|
||||
NAME
|
||||
cfsim - simplify a value using continued fractions
|
||||
|
||||
SYNOPSIS
|
||||
cfsim(x [,rnd])
|
||||
|
||||
TYPES
|
||||
x real
|
||||
rnd integer, defaults to config("cfsim")
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
If x is not an integer, cfsim(x, rnd) returns either the nearest
|
||||
above x, or the nearest below x, number with denominator less than
|
||||
den(x). If x is an integer, cfsim(x, rnd) returns x + 1, x - 1, or 0.
|
||||
Which of the possible results is returned is controlled
|
||||
by bits 0, 1, 3 and 4 of the parameter rnd.
|
||||
|
||||
For 0 <= rnd < 4, the sign of the remainder x - cfsim(x, rnd) is
|
||||
as follows:
|
||||
|
||||
rnd sign of x - cfsim(x, rnd)
|
||||
|
||||
0 +, as if rounding down
|
||||
1 -. as if rounding up
|
||||
2 sgn(x), as if rounding to zero
|
||||
3 -sgn(x), as if rounding from zero
|
||||
|
||||
This corresponds to the use of rnd for functions like round(x, n, rnd).
|
||||
|
||||
If bit 3 or 4 of rnd is set, the lower order bits are ignored; bit 3
|
||||
is ignored if bit 4 is set. Thusi, for rnd > 3, it sufficient to
|
||||
consider the two cases rnd = 8 and rnd = 16.
|
||||
|
||||
If den(x) > 2, cfsim(x, 8) returns the value of the penultimate simple
|
||||
continued-fraction approximant to x, i.e. if:
|
||||
|
||||
x = a_0 + 1/(a_1 + 1/(a_2 + ... + 1/a_n) ...)),
|
||||
|
||||
where a_0 is an integer, a_1, ..., a_n are positive integers,
|
||||
and a_n >= 2, the value returned is that of the continued fraction
|
||||
obtained by dropping the last quotient 1/a_n.
|
||||
|
||||
If den(x) > 2, cfsim(x, 16) returns the nearest number to x with
|
||||
denominator less than den(x). In the continued-fraction representation
|
||||
of x described above, this is given by replacing a_n by a_n - 1.
|
||||
|
||||
If den(x) = 2, the definition adopted is to round towards zero for the
|
||||
approximant case (rnd = 8) and from zero for the "nearest" case (rnd = 16).
|
||||
|
||||
For integral x, cfsim(x, 8) returns zero, cfsim(x,16) returns x - sgn(x).
|
||||
|
||||
In summary, for cfsim(x, rnd) when rnd = 8 or 16, the results are:
|
||||
|
||||
rnd integer x half-integer x den(x) > 2
|
||||
|
||||
8 0 x - sgn(x)/2 approximant
|
||||
16 x - sgn(x) x + sgn(x)/2 nearest
|
||||
|
||||
From either cfsim(x, 0) and cfsim(x, 1), the other is easily
|
||||
determined: if one of them has value w, the other has value
|
||||
(num(x) - num(w))/(den(x) - den(w)). From x and w one may find
|
||||
other optimal rational numbers near x; for example, the smallest-
|
||||
denominator number between x and w is (num(x) + num(w))/(den(x) + den(w)).
|
||||
|
||||
If x = n/d and cfsim(x, 8) = u/v, then for k * v < d, the k-th member of
|
||||
the sequence of nearest approximations to x with decreasing denominators
|
||||
on the other side of x is (n - k * u)/(d - k * v). This is nearer
|
||||
to or further from x than u/v according as 2 * k * v < or > d.
|
||||
|
||||
Iteration of cfsim(x,8) until an integer is obtained gives a sequence of
|
||||
"good" approximations to x with decreasing denominators and
|
||||
correspondingly decreasing accuracy; each denominator is less than half
|
||||
the preceding denominator. (Unlike the "forward" sequence of
|
||||
continued-fraction approximants these are not necessarily alternately
|
||||
greater than and less than x.)
|
||||
|
||||
Some other properties:
|
||||
|
||||
For rnd = 0 or 1 and any x, or rnd = 8 or 16 and x with den(x) > 2:
|
||||
|
||||
cfsim(n + x, rnd) = n + cfsim(x, rnd).
|
||||
|
||||
This equation also holds for the other values of rnd if n + x and x
|
||||
have the same sign.
|
||||
|
||||
For rnd = 2, 3, 8 or 16, and any x:
|
||||
|
||||
cfsim(-x, rnd) = -cfsim(x, rnd).
|
||||
|
||||
If rnd = 8 or 16, except for integer x or 1/x for rnd = 8, and
|
||||
zero x for rnd = 16:
|
||||
|
||||
cfsim(1/x, rnd) = 1/cfsim(x, rnd).
|
||||
|
||||
EXAMPLE
|
||||
> c = config("mode", "frac");
|
||||
|
||||
> print cfsim(43/30, 0), cfsim(43/30, 1), cfsim(43/30, 8), cfsim(43/30,16)
|
||||
10/7 33/23 10/7 33/23
|
||||
|
||||
> x = pi(1e-20); c = config("mode", "frac");
|
||||
> while (!isint(x)) {x = cfsim(x,8); if (den(x) < 1e6) print x,:;}
|
||||
1146408/364913 312689/99532 104348/33215 355/113 22/7 3
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qcfsim(NUMBER *x, long rnd)
|
||||
|
||||
SEE ALSO
|
||||
cfappr
|
27
help/char
Normal file
27
help/char
Normal file
@@ -0,0 +1,27 @@
|
||||
NAME
|
||||
char - character corresponding to a value
|
||||
|
||||
SYNOPSIS
|
||||
char(j)
|
||||
|
||||
TYPES
|
||||
j integer, 0 <= j < 256
|
||||
|
||||
return string
|
||||
|
||||
DESCRIPTION
|
||||
For j > 0, returns a string of length 1 with a character that has
|
||||
the same value as j. For j = 0, returns the null string "".
|
||||
|
||||
EXAMPLE
|
||||
> print char(0102), char(0x6f), char(119), char(0145), char(0x6e)
|
||||
B o w e n
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
none
|
||||
|
||||
SEE ALSO
|
||||
ord
|
26
help/cmdbuf
Normal file
26
help/cmdbuf
Normal file
@@ -0,0 +1,26 @@
|
||||
NAME
|
||||
cmdbuf - print the command buffer
|
||||
|
||||
SYNOPSIS
|
||||
cmdbuf()
|
||||
|
||||
TYPES
|
||||
return str
|
||||
|
||||
DESCRIPTION
|
||||
This function returns the command string that was formed by calc based
|
||||
on its command line arguments. If calc was invoked without arguments,
|
||||
this function will return an empty string.
|
||||
|
||||
EXAMPLE
|
||||
> cmdbuf("")
|
||||
""
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
none
|
||||
|
||||
SEE ALSO
|
||||
XXX - fill in
|
90
help/cmp
Normal file
90
help/cmp
Normal file
@@ -0,0 +1,90 @@
|
||||
NAME
|
||||
cmp - compare two values
|
||||
|
||||
SYNOPSIS
|
||||
cmp(x, y)
|
||||
|
||||
TYPES
|
||||
If x is an object of type xx or x is not an object and y is an object
|
||||
of type xx, the funcion xx_cmp has to have been defined; any
|
||||
further conditions on x and y, and the type of the returned
|
||||
value depends on the definition of xx_cmp.
|
||||
|
||||
For non-object x and y:
|
||||
|
||||
x number or string
|
||||
y same as x
|
||||
|
||||
return -1, 0, 1 (real & string)
|
||||
-1, 0, 1, -1+1i, 1i, 1+1i, -1-1i, -1i or 1-1i (complex)
|
||||
|
||||
DESCRIPTION
|
||||
Compare two values and return a value based on their relationship.
|
||||
Comparison by type is indicated below. Where more than one test is
|
||||
indicated, tests are performed in the order listed. If the test is
|
||||
inconclusive, the next test is performed. If all tests are
|
||||
inconclusive, the values are considered equivalent.
|
||||
|
||||
real (returns -1, 0, or 1)
|
||||
the greater number is greater
|
||||
|
||||
complex (returns -1, 0, 1, -1+1i, 1i, 1+1i, -1-1i, -1i or 1-1i)
|
||||
sgn(re(x) - re(y)) + sgn(im(x) - im(y)) * 1i
|
||||
|
||||
string (returns -1, 0, or 1)
|
||||
the string with the greater first different character is greater
|
||||
the longer string is greater
|
||||
|
||||
object (depends on xx_cmp)
|
||||
the greater object as defined by xx_cmp is greater
|
||||
|
||||
String comparison is performed via the strcmp() libc function.
|
||||
|
||||
Note that this function is not a substitution for equality. The ==
|
||||
operator always takes epsilon() into account when comparing numeric
|
||||
values. For example:
|
||||
|
||||
> cmp(1, 1+epsilon()/2)
|
||||
-1
|
||||
> 1 == 1+epsilon()/2
|
||||
0
|
||||
|
||||
It should be noted epsilon() is used when comparing complex values.
|
||||
|
||||
Properties of cmp(a,b) for real or complex a and b are:
|
||||
|
||||
cmp(a + c, b + c) = cmp(a,b)
|
||||
|
||||
cmp(a, b) == 0 if and only if a == b
|
||||
|
||||
cmp(b, a) = -cmp(a,b)
|
||||
|
||||
if c is real or pure imaginary, cmp(c * a, c * b) = c * cmp(a,b)
|
||||
|
||||
cmp(a,b) == cmp(b,c) if and only if b is "between" a and c
|
||||
|
||||
The numbers between 2 + 3i and 4 + 5i are those with real part between
|
||||
2 and 4, imaginary part between 3 and 5; the numbers between 2 + 3i
|
||||
and 4 + 3i are those with real part between 2 and 4, imaginary part = 3.
|
||||
|
||||
EXAMPLE
|
||||
> print cmp(3,4), cmp(4,3), cmp(4,4), cmp("a","b"), cmp("abcd","abc")
|
||||
-1 1 0 -1 1
|
||||
|
||||
> print cmp(3,4i), cmp(4,4i), cmp(5,4i), cmp(-5,4i), cmp(-4i,5), cmp(-4i,-5)
|
||||
1-1i 1-1i 1-1i -1-1i -1-1i 1-1i
|
||||
|
||||
> print cmp(3i,4i), cmp(4i,4i), cmp(5i,4i), cmp(3+4i,5), cmp(3+4i,-5)
|
||||
-1i 0 1i -1+1i 1+1i
|
||||
|
||||
> print cmp(3+4i,3+4i), cmp(3+4i,3-4i), cmp(3+4i,2+3i), cmp(3+4i,-4-5i)
|
||||
0 1i 1+1i 1+1i
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
none
|
||||
|
||||
SEE ALSO
|
||||
abs, epsilon, sgn
|
39
help/comb
Normal file
39
help/comb
Normal file
@@ -0,0 +1,39 @@
|
||||
NAME
|
||||
comb - combinatorial number
|
||||
|
||||
SYNOPSIS
|
||||
comb(x, y)
|
||||
|
||||
TYPES
|
||||
x int
|
||||
y int
|
||||
|
||||
return int
|
||||
|
||||
DESCRIPTION
|
||||
Return the combinatorial number C(x,y) which is defined as:
|
||||
|
||||
x!
|
||||
---------
|
||||
y!*(x-y)!
|
||||
|
||||
This function computes the number of combinations in which y things
|
||||
may be chosen from x items ignoring the order in which they are chosen.
|
||||
|
||||
EXAMPLE
|
||||
> print comb(7,3), comb(7,4), comb(7,5), comb(3,0), comb(0,0)
|
||||
35 35 21 1 1
|
||||
|
||||
> print comb(2^31+1,2^31-1)
|
||||
2305843010287435776
|
||||
|
||||
LIMITS
|
||||
x >= y >= 0
|
||||
y < 2^24
|
||||
x-y < 2^24
|
||||
|
||||
LIBRARY
|
||||
void zcomb(NUMBER x, y, *ret)
|
||||
|
||||
SEE ALSO
|
||||
fact, perm
|
99
help/command
Normal file
99
help/command
Normal file
@@ -0,0 +1,99 @@
|
||||
Command sequence
|
||||
|
||||
This is a sequence of any the following command formats, where
|
||||
each command is terminated by a semicolon or newline. Long command
|
||||
lines can be extended by using a back-slash followed by a newline
|
||||
character. When this is done, the prompt shows a double angle
|
||||
bracket to indicate that the line is still in progress. Certain
|
||||
cases will automatically prompt for more input in a similar manner,
|
||||
even without the back-slash. The most common case for this is when
|
||||
a function is being defined, but is not yet completed.
|
||||
|
||||
Each command sequence terminates only on an end of file. In
|
||||
addition, commands can consist of expression sequences, which are
|
||||
described in the next section.
|
||||
|
||||
|
||||
NOTE: Calc commands are in lower case. UPPER case is used below
|
||||
for emphasis only, and should be considered in lower case.
|
||||
|
||||
|
||||
DEFINE function(params) { body }
|
||||
DEFINE function(params) = expression
|
||||
This first form defines a full function which can consist
|
||||
of declarations followed by many statements which implement
|
||||
the function.
|
||||
|
||||
The second form defines a simple function which calculates
|
||||
the specified expression value from the specified parameters.
|
||||
The expression cannot be a statement. However, the comma
|
||||
and question mark operators can be useful. Examples of
|
||||
simple functions are:
|
||||
|
||||
define sumcubes(a, b) = a^3 + b^3;
|
||||
define pimod(a) = a % pi();
|
||||
|
||||
HELP
|
||||
This displays a general help message.
|
||||
|
||||
READ filename
|
||||
This reads definitions from the specified filename.
|
||||
The name can be quoted if desired. The calculator
|
||||
uses the CALCPATH environment variable to search
|
||||
through the specified directories for the filename,
|
||||
similarly to the use of the PATH environment variable.
|
||||
If CALCPATH is not defined, then a default path which is
|
||||
usually ":/usr/local/lib/calc" is used (that is, the current
|
||||
directory followed by a general calc library directory).
|
||||
The ".cal" extension is defaulted for input files, so
|
||||
that if "filename" is not found, then "filename.cal" is
|
||||
then searched for. The contents of the filename are
|
||||
command sequences which can consist of expressions to
|
||||
evaluate or functions to define, just like at the top
|
||||
level command level.
|
||||
|
||||
If the -m mode disallows opening of files for reading,
|
||||
this command will be disabled.
|
||||
|
||||
READ -once filename
|
||||
This command acts like the regular READ expect that it
|
||||
will ignore filename if is has been previously read.
|
||||
|
||||
This command is particularly useful in a library that
|
||||
needs to read a 2nd library. By using the READ -once
|
||||
command, one will not reread that 2nd library, nor will
|
||||
once risk entering into a infinite READ loop (where
|
||||
that 2nd library directly or indirectly does a READ of
|
||||
the first library).
|
||||
|
||||
If the -m mode disallows opening of files for reading,
|
||||
this command will be disabled.
|
||||
|
||||
WRITE filename
|
||||
This writes the values of all global variables to the
|
||||
specified filename, in such a way that the file can be
|
||||
later read in order to recreate the variable values.
|
||||
For speed reasons, values are written as hex fractions.
|
||||
This command currently only saves simple types, so that
|
||||
matrices, lists, and objects are not saved. Function
|
||||
definitions are also not saved.
|
||||
|
||||
If the -m mode disallows opening of files for writing,
|
||||
this command will be disabled.
|
||||
|
||||
QUIT
|
||||
This leaves the calculator, when given as a top-level
|
||||
command.
|
||||
|
||||
CD
|
||||
Change the current directory to the home directory, if $HOME
|
||||
is set in the environment.
|
||||
|
||||
CD dir
|
||||
Change the current directory to dir.
|
||||
|
||||
|
||||
Also see the help topic:
|
||||
|
||||
statement flow control and declaration statements
|
||||
usage for -m modes
|
267
help/config
Normal file
267
help/config
Normal file
@@ -0,0 +1,267 @@
|
||||
Configuration parameters
|
||||
|
||||
Configuration parameters affect how the calculator performs certain
|
||||
operations. Among features that are controlled by these parameters
|
||||
are the accuracy of some calculations, the displayed format of results,
|
||||
the choice from possible alternative algorithms, and whether or not
|
||||
debugging information is displayed. The parameters are
|
||||
read or set using the "config" built-in function; they remain in effect
|
||||
until their values are changed by a config or equivalent instruction.
|
||||
The following parameters can be specified:
|
||||
|
||||
"all" all configuration values listed below
|
||||
|
||||
"trace" turns tracing features on or off
|
||||
"display" sets number of digits in prints.
|
||||
"epsilon" sets error value for transcendentals.
|
||||
"maxprint" sets maximum number of elements printed.
|
||||
"mode" sets printout mode.
|
||||
"mul2" sets size for alternative multiply.
|
||||
"sq2" sets size for alternative squaring.
|
||||
"pow2" sets size for alternate powering.
|
||||
"redc2" sets size for alternate REDC.
|
||||
"tilde" enable/disable printing of the roundoff '~'
|
||||
"tab" enable/disable printing of leading tabs
|
||||
"quomod" sets rounding mode for quomod
|
||||
"quo" sets rounding mode for //, default for quo
|
||||
"mod" sets "rounding" mode for %, default for mod
|
||||
"sqrt" sets rounding mode for sqrt
|
||||
"appr" sets rounding mode for appr
|
||||
"cfappr" sets rounding mode for cfappr
|
||||
"cfsim" sets rounding mode for cfsim
|
||||
"round" sets rounding mode for round and bround
|
||||
"outround" sets rounding mode for printing of numbers
|
||||
"leadzero" enables/disables printing of 0 as in 0.5
|
||||
"fullzero" enables/disables padding zeros as in .5000
|
||||
"maxerr" maximum number of scan errors before abort
|
||||
"prompt" default interactive prompt
|
||||
"more" default interactive multi-line input prompt
|
||||
|
||||
|
||||
The "all" config value allows one to save/restore the configuration
|
||||
set of values. The return of:
|
||||
|
||||
config("all")
|
||||
|
||||
is a CONFIG type which may be used as the 2rd arg in a later call.
|
||||
One may save, modify and restore the configuration state as follows:
|
||||
|
||||
oldstate = config("all")
|
||||
...
|
||||
config("tab", 0)
|
||||
config("mod", 10)
|
||||
...
|
||||
config("all", oldstate)
|
||||
|
||||
This save/restore method is useful within functions.
|
||||
It allows functions to control their configuration without impacting
|
||||
the calling function.
|
||||
|
||||
There are two configuration state aliases that may be set. To
|
||||
set the backward compatible standard configuration:
|
||||
|
||||
config("all", "oldstd")
|
||||
|
||||
The "oldstd" will restore the configuration to the default at startup.
|
||||
|
||||
A new configuration that some people prefer may be set by:
|
||||
|
||||
config("all", "newstd")
|
||||
|
||||
The "newstd" is not backward compatible with the historic
|
||||
configuration. Even so, some people prefer this configuration
|
||||
and place the config("all", "newstd") command in their CALCRC
|
||||
startup files.
|
||||
|
||||
When nonzero, the "trace" parameter activates one or more features
|
||||
that may be useful for debugging. These features correspond to
|
||||
powers of 2 which contribute additively to config("trace"):
|
||||
|
||||
1: opcodes are displayed as functions are evaluated
|
||||
|
||||
2: disables the inclusion of debug lines in opcodes for functions
|
||||
whose definitions are introduced with a left-brace.
|
||||
|
||||
4: the number of links for real and complex numbers are displayed
|
||||
when the numbers are printed; for real numbers "#" or for
|
||||
complex numbers "##", followed by the number of links, are
|
||||
printed immediately after the number.
|
||||
|
||||
8: the opcodes for a new functions are displayed when the function
|
||||
is successfully defined.
|
||||
|
||||
The "display" parameter specifies the maximum number of digits after
|
||||
the decimal point to be printed in real or exponential mode in
|
||||
normal unformatted printing (print, strprint, fprint) or in
|
||||
formatted printing (printf, strprintf, fprintf) when precision is not
|
||||
specified. The initial value is 20. This parameter does not change
|
||||
the stored value of a number. Where rounding is necessary, the type
|
||||
of rounding to be used is controlled by "outround".
|
||||
|
||||
The "epsilon" parameter specifies the default accuracy for the
|
||||
calculation of functions for which exact values are not possible or
|
||||
not desired. For most functions, the
|
||||
|
||||
remainder = exact value - calculated value
|
||||
|
||||
has absolute value less than epsilon, but, except when the sign of
|
||||
the remainder is controlled by an appropriate parameter, the
|
||||
absolute value of the remainder usually does not exceed epsilon/2.
|
||||
Functions which require an epsilon value accept an
|
||||
optional argument which overrides this default epsilon value for
|
||||
that single call. (The value v can be assigned to the "epsilon"
|
||||
parameter by epsilon(v) as well as by config("epsilon", v), and the
|
||||
current value obtained by epsilon() as well as by config("epsilon").)
|
||||
For the transcendental functions and the functions sqrt() and
|
||||
appr(), the calculated value is always a multiple of epsilon.
|
||||
|
||||
The "mode" parameter is a string specifying the mode for printing of
|
||||
numbers by the unformatted print functions, and the default
|
||||
("%d" specifier) for formatted print functions. The initial mode
|
||||
is "real". The available modes are:
|
||||
|
||||
"frac" decimal fractions
|
||||
"int" decimal integer
|
||||
"real" decimal floating point
|
||||
"exp" decimal exponential
|
||||
"hex" hex fractions
|
||||
"oct" octal fractions
|
||||
"bin" binary fractions
|
||||
|
||||
|
||||
The "maxprint" parameter specifies the maximum number of elements to
|
||||
be displayed when a matrix or list is printed. The initial value is 16.
|
||||
|
||||
Mul2 and sq2 specify the sizes of numbers at which calc switches
|
||||
from its first to its second algorithm for multiplying and squaring.
|
||||
The first algorithm is the usual method of cross multiplying, which
|
||||
runs in a time of O(N^2). The second method is a recursive and
|
||||
complicated method which runs in a time of O(N^1.585). The argument
|
||||
for these parameters is the number of binary words at which the
|
||||
second algorithm begins to be used. The minimum value is 2, and
|
||||
the maximum value is very large. If 2 is used, then the recursive
|
||||
algorithm is used all the way down to single digits, which becomes
|
||||
slow since the recursion overhead is high. If a number such as
|
||||
1000000 is used, then the recursive algorithm is never used, causing
|
||||
calculations for large numbers to slow down. For a typical example
|
||||
on a 386, the two algorithms are about equal in speed for a value
|
||||
of 20, which is about 100 decimal digits. A value of zero resets
|
||||
the parameter back to its default value. Usually there is no need
|
||||
to change these parameters.
|
||||
|
||||
Pow2 specifies the sizes of numbers at which calc switches from
|
||||
its first to its second algorithm for calculating powers modulo
|
||||
another number. The first algorithm for calculating modular powers
|
||||
is by repeated squaring and multiplying and dividing by the modulus.
|
||||
The second method uses the REDC algorithm given by Peter Montgomery
|
||||
which avoids divisions. The argument for pow2 is the size of the
|
||||
modulus at which the second algorithm begins to be used.
|
||||
|
||||
Redc2 specifies the sizes of numbers at which calc switches from
|
||||
its first to its second algorithm when using the REDC algorithm.
|
||||
The first algorithm performs a multiply and a modular reduction
|
||||
together in one loop which runs in O(N^2). The second algorithm
|
||||
does the REDC calculation using three multiplies, and runs in
|
||||
O(N^1.585). The argument for redc2 is the size of the modulus at
|
||||
which the second algorithm begins to be used.
|
||||
|
||||
Config("tilde") controls whether or not a leading tilde ('~') is
|
||||
printed to indicate that a number has not been printed exactly
|
||||
because the number of decimal digits required would exceed the
|
||||
specified maximum number. The initial "tilde" value is 1.
|
||||
|
||||
Config ("tab") controls the printing of a tab before results
|
||||
automatically displayed when working interactively. It does not
|
||||
affect the printing by the functions print, printf, etc. The inital
|
||||
"tab" value is 1.
|
||||
|
||||
The "quomod", "quo", "mod", "sqrt", "appr", "cfappr", "cfsim", and
|
||||
"round" control the way in which any necessary rounding occurs.
|
||||
Rounding occurs when for some reason, a calculated or displayed
|
||||
value (the "approximation") has to differ from the "true value",
|
||||
e.g. for quomod and quo, the quotient is to be an integer, for sqrt
|
||||
and appr, the approximation is to be a multiple of an explicit or
|
||||
implicit "epsilon", for round and bround (both controlled by
|
||||
config("round")) the number of decimal places or fractional bits
|
||||
in the approximation is limited. Zero value for any of these
|
||||
parameters indicates that the true value is greater than the approximation,
|
||||
i.e. the rounding is "down", or in the case of mod, that the
|
||||
residue has the same sign as the divisor. If bit 4 of the
|
||||
parameter is set, the rounding of to the nearest acceptable candidate
|
||||
when this is uniquely determined; in the remaining ambiguous cases,
|
||||
the type of rounding is determined by the lower bits of the parameter
|
||||
value. If bit 3 is set, the rounding for quo, appr and sqrt,
|
||||
is to the nearest even integer or the nearest even multiple of epsilon,
|
||||
and for round to the nearest even "last decimal place". The effects
|
||||
of the 3 lowest bits of the parameter value are as follows:
|
||||
|
||||
Bit 0: Unconditional reversal (down to up, even to odd, etc.)
|
||||
Bit 1: Reversal if the exact value is negative
|
||||
Bit 2: Reversal if the divisor or epsilon is negative
|
||||
|
||||
(Bit 2 is irrelevant for the functions round and bround since the
|
||||
equivalent epsilon (a power of 1/10 or 1/2) is always positive.)
|
||||
|
||||
For quomod, the quotient is rounded to an integer value as if
|
||||
evaluating quo with config("quo") == config("quomod"). Similarly,
|
||||
quomod and mod give the same residues if config("mod") == config("quomod").
|
||||
|
||||
For the sqrt function, if bit 5 of config("sqrt") is set, the exact
|
||||
square-root is returned when this is possible; otherwise the
|
||||
result is rounded to a multiple of epsilon as determined by the
|
||||
five lower order bits. Bit 6 of config("sqrt") controls whether the
|
||||
principal or non-principal square-root is returned.
|
||||
|
||||
For the functions cfappr and cfsim, whether the "rounding" is down
|
||||
or up, etc. is controlled by the appropriate bits of config("cfappr")
|
||||
and config("cfsim") as for quomod, quo, etc.
|
||||
|
||||
The "outround" parameter determines the type of rounding to be used
|
||||
by the various kinds of printing to the output: bits 0, 1, 3 and 4
|
||||
are used in the same way as for the functions round and bround.
|
||||
|
||||
The "leadzero" parameter controls whether or not a 0 is printed
|
||||
before the decimal point in non-zero fractions with absolute value
|
||||
less than 1, e.g. whether 1/2 is printed as 0.5 or .5. The
|
||||
initial value is 0, corresponding to the printing .5.
|
||||
|
||||
The "fullzero" parameter controls whether or not in decimal floating-
|
||||
point printing, the digits are padded with zeros to reach the
|
||||
number of digits specified by config("display") or by a precision
|
||||
specification in formatted printing. The initial value for this
|
||||
parameter is 0, so that, for example, if config("display") >= 2,
|
||||
5/4 will print in "real" mode as 1.25.
|
||||
|
||||
The maxerr value controls how many scan errors are allowed
|
||||
before the compiling phase of a computation is aborted. The initial
|
||||
value of "maxerr" is 20. Setting maxerr to 0 disables this feature.
|
||||
|
||||
The default prompt when in teractive mode is "> ". One may change
|
||||
this prompt to a more cut-and-paste friendly prompt by:
|
||||
|
||||
config("prompt", "; ")
|
||||
|
||||
On windowing systems that support cut/paste of a line, one may
|
||||
cut/copy an input line and paste it directly into input. The
|
||||
leading ';' will be ignored.
|
||||
|
||||
When inside multi-line input, the more prompt is used. One may
|
||||
change it by:
|
||||
|
||||
config("more", ";; ")
|
||||
|
||||
The following are synonyms for true:
|
||||
|
||||
"on" "yes" "y" "true" "t" "1" any non-zero number
|
||||
|
||||
The following are synonyms for false:
|
||||
|
||||
"off" "no" "n" "false" "f" "0" the number zero (0)
|
||||
|
||||
Examples of setting some parameters are:
|
||||
|
||||
config("mode", "exp"); exponential output
|
||||
config("display", 50); 50 digits of output
|
||||
epsilon(epsilon() / 8); 3 bits more accuracy
|
||||
config("tilde", 0) disable roundoff tilde printing
|
||||
config("tab", "off") disable leading tab printing
|
35
help/conj
Normal file
35
help/conj
Normal file
@@ -0,0 +1,35 @@
|
||||
NAME
|
||||
conj - complex conjugate
|
||||
|
||||
SYNOPSIS
|
||||
conj(x)
|
||||
|
||||
TYPES
|
||||
If x is an object of type xx, conj(x) calls xx_conj(x).
|
||||
|
||||
For non-object x:
|
||||
|
||||
x real, complex, or matrix
|
||||
|
||||
return real, complex, or matrix
|
||||
|
||||
DESCRIPTION
|
||||
For real x, conj(x) returns x.
|
||||
|
||||
For complex x, conj(x) returns re(x) - im(x) * 1i.
|
||||
|
||||
For matrix x, conj(x) returns a matrix of the same structure as x
|
||||
in which each element t of x has been replaced by conj(t).
|
||||
|
||||
EXAMPLE
|
||||
> print conj(3), conj(3 + 4i)
|
||||
3 3-4i
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
void conjvalue(VALUE *x, *res)
|
||||
|
||||
SEE ALSO
|
||||
norm, abs, arg
|
36
help/cos
Normal file
36
help/cos
Normal file
@@ -0,0 +1,36 @@
|
||||
NAME
|
||||
cos - cosine
|
||||
|
||||
SYNOPSIS
|
||||
cos(x [,eps])
|
||||
|
||||
TYPES
|
||||
x number (real or complex)
|
||||
eps nonzero real, defaults to epsilon()
|
||||
|
||||
return number
|
||||
|
||||
DESCRIPTION
|
||||
Calculate the cosine of x to a multiple of eps with error less in
|
||||
absolute value than .75 * eps.
|
||||
|
||||
EXAMPLE
|
||||
> print cos(1, 1e-5), cos(1, 1e-10), cos(1, 1e-15), cos(1, 1e-20)
|
||||
.5403 .5403023059 .54030230586814 .5403023058681397174
|
||||
|
||||
> print cos(2 +3i, 1e-5), cos(2 + 3i, 1e-10)
|
||||
-4.18963-9.10923i -4.189625691-9.1092278938i
|
||||
|
||||
> pi = pi(1e-20)
|
||||
> print cos(pi/3, 1e-10), cos(pi/2, 1e-10), cos(pi, 1e-10)
|
||||
.5 0 -1
|
||||
|
||||
LIMITS
|
||||
eps > 0
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qcos(NUMBER *x, NUMBER *eps)
|
||||
COMPLEX *ccos(COMPLEX *x, NUMBER *eps)
|
||||
|
||||
SEE ALSO
|
||||
sin, tan, sec, csc, cot, epsilon
|
31
help/cosh
Normal file
31
help/cosh
Normal file
@@ -0,0 +1,31 @@
|
||||
NAME
|
||||
cosh - hyperbolic cosine
|
||||
|
||||
SYNOPSIS
|
||||
cosh(x [,eps])
|
||||
|
||||
TYPES
|
||||
x real
|
||||
eps nonzero real, defaults to epsilon()
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
Calculate the cosh of x to the nearest or next to nearest multiple of
|
||||
epsilon, with absolute error less than .75 * abs(eps).
|
||||
|
||||
cosh(x) = (exp(x) + exp(-x))/2
|
||||
|
||||
EXAMPLE
|
||||
> print cosh(1, 1e-5), cosh(1, 1e-10), cosh(1, 1e-15), cosh(1, 1e-20)
|
||||
1.54308 1.5430806348 1.543080634815244 1.54308063481524377848
|
||||
|
||||
LIMITS
|
||||
unlike sin and cos, x must be real
|
||||
eps > 0
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qcosh(NUMBER *x, NUMBER *eps)
|
||||
|
||||
SEE ALSO
|
||||
sinh, tanh, sech, csch, coth, epsilon
|
30
help/cot
Normal file
30
help/cot
Normal file
@@ -0,0 +1,30 @@
|
||||
NAME
|
||||
cot - trigonometric cotangent
|
||||
|
||||
SYNOPSIS
|
||||
cot(x [,eps])
|
||||
|
||||
TYPES
|
||||
x nonzero real
|
||||
acc nonzero real, defaults to epsilon()
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
Calculate the cotangent of x to a multiple of eps, with error less
|
||||
in absolute value than .75 * eps.
|
||||
|
||||
EXAMPLE
|
||||
> print cot(1, 1e-5), cot(1, 1e-10), cot(1, 1e-15), cot(1, 1e-20)
|
||||
.64209 .6420926159 .642092615934331 .64209261593433070301
|
||||
|
||||
LIMITS
|
||||
unlike sin and cos, x must be real
|
||||
x != 0
|
||||
eps > 0
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qcot(NUMBER *x, *eps)
|
||||
|
||||
SEE ALSO
|
||||
sin, cos, tan, sec, csc, epsilon
|
32
help/coth
Normal file
32
help/coth
Normal file
@@ -0,0 +1,32 @@
|
||||
NAME
|
||||
coth - hyperbolic cotangent
|
||||
|
||||
SYNOPSIS
|
||||
coth(x [,eps])
|
||||
|
||||
TYPES
|
||||
x nonzero real
|
||||
eps nonzero real, defaults to epsilon()
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
Calculate the coth of x to a multiple of eps with error less in
|
||||
absolute value than .75 * eps.
|
||||
|
||||
coth(x) = (exp(2*x) + 1)/(exp(2*x) - 1)
|
||||
|
||||
EXAMPLE
|
||||
> print coth(1, 1e-5), coth(1, 1e-10), coth(1, 1e-15), coth(1, 1e-20)
|
||||
1.31304 1.3130352855 1.313035285499331 1.31303528549933130364
|
||||
|
||||
LIMITS
|
||||
unlike sin and cos, x must be real
|
||||
x != 0
|
||||
eps > 0
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qcoth(NUMBER *x, NUMBER *eps)
|
||||
|
||||
SEE ALSO
|
||||
sinh, cosh, tanh, sech, csch, epsilon
|
31
help/count
Normal file
31
help/count
Normal file
@@ -0,0 +1,31 @@
|
||||
NAME
|
||||
count - count elements of list or matrix satisfying a stated condition
|
||||
|
||||
SYNOPSIS
|
||||
count(x, y)
|
||||
|
||||
TYPES
|
||||
x list or matrix
|
||||
y string
|
||||
|
||||
return int
|
||||
|
||||
DESCRIPTION
|
||||
For count(x, y), y is to be the name of a user-defined function;
|
||||
count(x,y) then returns the number of elements of x for which y
|
||||
tests as "true".
|
||||
|
||||
EXAMPLE
|
||||
> define f(a) = (a < 5)
|
||||
> A = list(1,2,7,6,4,8)
|
||||
> count(A, "f")
|
||||
3
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
none
|
||||
|
||||
SEE ALSO
|
||||
XXX - fill in
|
37
help/cp
Normal file
37
help/cp
Normal file
@@ -0,0 +1,37 @@
|
||||
NAME
|
||||
cp - cross product of two 3 element vectors
|
||||
|
||||
SYNOPSIS
|
||||
cp(x, y)
|
||||
|
||||
TYPES
|
||||
x, y 1-dimensional matrices with 3 elements
|
||||
|
||||
return 1-dimensional matrix with 3 elements
|
||||
|
||||
DESCRIPTION
|
||||
Calculate the product of two 3 1-dimensional matrices.
|
||||
If x has elements (x0, x1, x2), and y has elements (y0, y1, y2),
|
||||
cp(x,y) returns the matrix of type [0:2] with elements:
|
||||
|
||||
{x1 * y2 - x2 * y1, x3 * y1 - x1 * y3, x1 * y2 - x2 * y1}
|
||||
|
||||
EXAMPLE
|
||||
> mat x[3] = {2,3,4}
|
||||
> mat y[3] = {3,4,5}
|
||||
> print cp(x,y)
|
||||
|
||||
mat [3] (3 elements, 3 nonzero):
|
||||
[0] = -1
|
||||
[1] = 2
|
||||
[2] = -1
|
||||
|
||||
LIMITS
|
||||
x 1-dimensional matrix with 3 elements
|
||||
y 1-dimensional matrix with 3 elements
|
||||
|
||||
LIBRARY
|
||||
MATRIX *matcross(MATRIX *x, MATRIX *y)
|
||||
|
||||
SEE ALSO
|
||||
dp
|
62
help/credit
Normal file
62
help/credit
Normal file
@@ -0,0 +1,62 @@
|
||||
Credits
|
||||
|
||||
The majority of calc was written by David I. Bell.
|
||||
|
||||
Calc archives and calc-tester mailing list maintained by Landon Curt Noll.
|
||||
|
||||
Thanks for suggestions and encouragement from Peter Miller,
|
||||
Neil Justusson, and Landon Noll.
|
||||
|
||||
Thanks to Stephen Rothwell for writing the original version of
|
||||
hist.c which is used to do the command line editing.
|
||||
|
||||
Thanks to Ernest W. Bowen for supplying many improvements in
|
||||
accuracy and generality for some numeric functions. Much of
|
||||
this was in terms of actual code which I gratefully accepted.
|
||||
Ernest also supplied the original text for many of the help files.
|
||||
|
||||
Portions of this program are derived from an earlier set of
|
||||
public domain arbitrarily precision routines which was posted
|
||||
to the net around 1984. By now, there is almost no recognizable
|
||||
code left from that original source.
|
||||
|
||||
Most of this source and binary has one of the following copyrights:
|
||||
|
||||
Copyright (c) 19xx David I. Bell
|
||||
Copyright (c) 19xx David I. Bell and Landon Curt Noll
|
||||
Copyright (c) 19xx Landon Curt Noll
|
||||
Copyright (c) 19xx Ernest Bowen and Landon Curt Noll
|
||||
|
||||
Permission is granted to use, distribute, or modify this source,
|
||||
provided that this copyright notice remains intact.
|
||||
|
||||
Send calc comments, suggestions, bug fixes, enhancements and
|
||||
interesting calc scripts that you would like you see included in
|
||||
future distributions to:
|
||||
|
||||
dbell@auug.org.au
|
||||
chongo@toad.com
|
||||
|
||||
Landon Noll maintains the official calc ftp archive at:
|
||||
|
||||
ftp://ftp.uu.net/pub/calc
|
||||
|
||||
Alpha test versions, complete with bugs, untested code and
|
||||
experimental features may be fetched (if you are brave) under:
|
||||
|
||||
http://reality.sgi.com/chongo/calc/
|
||||
|
||||
One may join the calc testing group by sending a request to:
|
||||
|
||||
calc-tester-request@postofc.corp.sgi.com
|
||||
|
||||
Your message body (not the subject) should consist of:
|
||||
|
||||
subscribe calc-tester address
|
||||
end
|
||||
name your_full_name
|
||||
|
||||
where "address" is your EMail address and "your_full_name"
|
||||
is your full name.
|
||||
|
||||
Enjoy!
|
29
help/csc
Normal file
29
help/csc
Normal file
@@ -0,0 +1,29 @@
|
||||
NAME
|
||||
csc - trigonometric cosecant function
|
||||
|
||||
SYNOPSIS
|
||||
csc(x [,eps])
|
||||
|
||||
TYPES
|
||||
x real
|
||||
eps nonzero real, defaults to epsilon()
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
Calculate the cosecant of x to a multiple of eps, with error less
|
||||
in absolute value than .75 * eps.
|
||||
|
||||
EXAMPLE
|
||||
> print csc(1, 1e-5), csc(1, 1e-10), csc(1, 1e-15), csc(1, 1e-20)
|
||||
1.1884 1.1883951058 1.188395105778121 1.18839510577812121626
|
||||
|
||||
LIMITS
|
||||
unlike sin and cos, x must be real
|
||||
eps > 0
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qcsc(NUMBER *x, NUMBER *eps)
|
||||
|
||||
SEE ALSO
|
||||
sin, cos, tan, sec, cot, epsilon
|
32
help/csch
Normal file
32
help/csch
Normal file
@@ -0,0 +1,32 @@
|
||||
NAME
|
||||
csch - hyperbolic cosecant
|
||||
|
||||
SYNOPSIS
|
||||
csch(x [,eps])
|
||||
|
||||
TYPES
|
||||
x nonzero real
|
||||
eps nonzero real, defaults to epsilon()
|
||||
|
||||
return real
|
||||
|
||||
DESCRIPTION
|
||||
Calculate the csch of x to a multiple of epsilon, with error less in
|
||||
absolute value than .75 * eps.
|
||||
|
||||
csch(x) = 2/(exp(x) - exp(-x))
|
||||
|
||||
EXAMPLE
|
||||
> print csch(1, 1e-5), csch(1, 1e-10), csch(1, 1e-15), csch(1, 1e-20)
|
||||
.85092 .8509181282 .850918128239322 .85091812823932154513
|
||||
|
||||
LIMITS
|
||||
unlike sin and cos, x must be real
|
||||
x != 0
|
||||
eps > 0
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qcsch(NUMBER *x, NUMBER *eps)
|
||||
|
||||
SEE ALSO
|
||||
sinh, cosh, tanh, sech, coth, epsilon
|
29
help/ctime
Normal file
29
help/ctime
Normal file
@@ -0,0 +1,29 @@
|
||||
NAME
|
||||
ctime - current local time
|
||||
|
||||
SYNOPSIS
|
||||
ctime()
|
||||
|
||||
TYPES
|
||||
return string
|
||||
|
||||
DESCRIPTION
|
||||
The ctime() builtin returns the string formed by the first 24
|
||||
characters returned by the C library function, ctime():
|
||||
|
||||
"Mon Oct 28 00:47:00 1996"
|
||||
|
||||
The 25th ctime() character, '\n' is removed.
|
||||
|
||||
EXAMPLE
|
||||
> printf("The time is now %s.\n", time())
|
||||
The time is now Mon Apr 15 12:41:44 1996.
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
none
|
||||
|
||||
SEE ALSO
|
||||
runtime, time
|
68
help/define
Normal file
68
help/define
Normal file
@@ -0,0 +1,68 @@
|
||||
Function definitions
|
||||
|
||||
Function definitions are introduced by the 'define' keyword.
|
||||
Other than this, the basic structure of a function is like in C.
|
||||
That is, parameters are specified for the function within parenthesis,
|
||||
the function body is introduced by a left brace, variables are
|
||||
declared for the function, statements implementing the function
|
||||
follow, and the function is ended with a right brace.
|
||||
|
||||
There are some subtle differences, however. The types of parameters
|
||||
and variables are not defined at compile time, but instead are typed
|
||||
at runtime. Thus there is no definitions needed to distinguish
|
||||
between integers, fractions, complex numbers, matrices, and so on.
|
||||
Thus when declaring parameters for a function, only the name of
|
||||
the parameter is needed. Thus there are never any declarations
|
||||
between the function parameter list and the body of the function.
|
||||
|
||||
For example, the following function computes a factorial:
|
||||
|
||||
define factorial(n)
|
||||
{
|
||||
local ans;
|
||||
|
||||
ans = 1;
|
||||
while (n > 1)
|
||||
ans *= n--;
|
||||
return ans;
|
||||
}
|
||||
|
||||
If a function is very simple and just returns a value, then the
|
||||
function can be defined in shortened manner by using an equals sign
|
||||
in place of the left brace. In this case, the function declaration
|
||||
is terminated by a newline character, and its value is the specified
|
||||
expression. Statements such as 'if' are not allowed. An optional
|
||||
semicolon ending the expression is allowed. As an example, the
|
||||
average of two numbers could be defined as:
|
||||
|
||||
define average(a, b) = (a + b) / 2;
|
||||
|
||||
Functions can be defined which can be very complex. These can be
|
||||
defined on the command line if desired, but editing of partial
|
||||
functions is not possible past a single line. If an error is made
|
||||
on a previous line, then the function must be finished (with probable
|
||||
errors) and reentered from the beginning. Thus for complicated
|
||||
functions, it is best to use an editor to create the function in a
|
||||
file, and then enter the calculator and read in the file containing
|
||||
the definition.
|
||||
|
||||
The parameters of a function can be referenced by name, as in
|
||||
normal C usage, or by using the 'param' function. This function
|
||||
returns the specified parameter of the function it is in, where
|
||||
the parameters are numbered starting from 1. The total number
|
||||
of parameters to the function is returned by using 'param(0)'.
|
||||
Using this function allows you to implement varargs-like routines
|
||||
which can handle any number of calling parameters. For example:
|
||||
|
||||
define sc()
|
||||
{
|
||||
local s, i;
|
||||
|
||||
s = 0;
|
||||
for (i = 1; i <= param(0); i++)
|
||||
s += param(i)^3;
|
||||
return s;
|
||||
}
|
||||
|
||||
defines a function which returns the sum of the cubes of all it's
|
||||
parameters.
|
44
help/delete
Normal file
44
help/delete
Normal file
@@ -0,0 +1,44 @@
|
||||
NAME
|
||||
delete - delete an element from a list at a given position
|
||||
|
||||
SYNOPSIS
|
||||
delete(lst, idx)
|
||||
|
||||
TYPES
|
||||
lst list, &list
|
||||
idx int, &int
|
||||
|
||||
return any
|
||||
|
||||
DESCRIPTION
|
||||
Delete element at index idx from list lst.
|
||||
|
||||
The index must refer to an element in the list. That is, idx must
|
||||
be in the range [0, size(lst)-1].
|
||||
|
||||
EXAMPLE
|
||||
> lst = list(2,3,4,5)
|
||||
|
||||
list (4 elements, 4 nonzero):
|
||||
[[0]] = 2
|
||||
[[1]] = 3
|
||||
[[2]] = 4
|
||||
[[3]] = 5
|
||||
|
||||
> delete(lst, 2)
|
||||
4
|
||||
> print lst
|
||||
|
||||
list (3 elements, 3 nonzero):
|
||||
[[0]] = 2
|
||||
[[1]] = 3
|
||||
[[2]] = 5
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
none
|
||||
|
||||
SEE ALSO
|
||||
append, insert, islist, list, pop, push, remove, rsearch, search, size
|
38
help/den
Normal file
38
help/den
Normal file
@@ -0,0 +1,38 @@
|
||||
NAME
|
||||
den - denominator of a real number
|
||||
|
||||
SYNOPSIS
|
||||
den(x)
|
||||
|
||||
TYPES
|
||||
x real
|
||||
|
||||
return integer
|
||||
|
||||
DESCRIPTION
|
||||
For real x, den(x) returns the denominator of x. In calc,
|
||||
real values are actually rational values. Each calc real
|
||||
value can be uniquely expressed as:
|
||||
|
||||
n / d
|
||||
|
||||
where:
|
||||
|
||||
n and d are integers
|
||||
gcd(n,d) == 1
|
||||
d > 0
|
||||
|
||||
If x = n/x, then den(x) == d.
|
||||
|
||||
EXAMPLE
|
||||
> print den(7), den(-1.25), den(121/33)
|
||||
1 4 3
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
NUMBER *qden(NUMBER *x)
|
||||
|
||||
SEE ALSO
|
||||
num
|
74
help/det
Normal file
74
help/det
Normal file
@@ -0,0 +1,74 @@
|
||||
NAME
|
||||
det - determinant
|
||||
|
||||
SYNOPSIS
|
||||
det(m)
|
||||
|
||||
TYPES
|
||||
m square matrix with elements of suitable type
|
||||
|
||||
return zero or value of type determined by types of elements
|
||||
|
||||
DESCRIPTION
|
||||
The matrix m has to be square, i.e. of dimension 2 with:
|
||||
|
||||
matmax(m,1) - matmin(m,1) == matmax(m,2) - matmin(m,2).
|
||||
|
||||
If the elements of m are numbers (real or complex), det(m)
|
||||
returns the value of the determinant of m.
|
||||
|
||||
If some or all of the elements of m are not numbers, the algorithm
|
||||
used to evaluate det(m) assumes the definitions of *, unary -, binary -,
|
||||
being zero or nonzero, are consistent with commutative ring structure,
|
||||
and if the m is larger than 2 x 2, division by nonzero elements is
|
||||
consistent with integral-domain structure.
|
||||
|
||||
If m is a 2 x 2 matrix with elements a, b, c, d, where a tests as
|
||||
nonzero, det(m) is evaluated by
|
||||
|
||||
det(m) = (a * d) - (c * b).
|
||||
|
||||
If a tests as zero, det(m) = - ((c * b) - (a * d)) is used.
|
||||
|
||||
If m is 3 * 3 with elements a, b, c, d, e, f, g, h, i, where a and
|
||||
a * e - d * b test as nonzero, det(m) is evaluated by
|
||||
|
||||
det(m) = ((a * e - d * b) * (a * i - g * c)
|
||||
- (a * h - g * b) * (a * f - d * c))/a.
|
||||
|
||||
EXAMPLE
|
||||
> mat A[3,3] = {2, 3, 5, 7, 11, 13, 17, 19, 23}
|
||||
> c = config("mode", "frac")
|
||||
> print det(A), det(A^2), det(A^3), det(A^-1)
|
||||
-78 6084 -474552 -1/78
|
||||
|
||||
> obj res {r}
|
||||
> global md
|
||||
> define res_test(a) = !ismult(a.r, md)
|
||||
> define res_sub(a,b) {local obj res v = {(a.r - b.r) % md}; return v;}
|
||||
> define res_mul(a,b) {local obj res v = {(a.r * b.r) % md}; return v;}
|
||||
> define res_neg(a) {local obj res v = {(-a.r) % md}; return v;}
|
||||
> define res(x) {local obj res v = {x % md}; return v;}
|
||||
> md = 0
|
||||
> mat A[2,2] = {res(2), res(3), res(5), res(7)}
|
||||
> md = 5
|
||||
> print det(A)
|
||||
obj res {4}
|
||||
> md = 6
|
||||
> print det(A)
|
||||
obj res {5}
|
||||
|
||||
Note that if A had been a 3 x 3 or larger matrix, res_div(a,b) for
|
||||
non-zero b would have had to be defined (assuming at least one
|
||||
division is necessary); for consistent results when md is composite,
|
||||
res_div(a,b) should be defined only when b and md are relatively
|
||||
prime; there is no problem when md is prime.
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
VALUE matdet(MATRIX *m)
|
||||
|
||||
SEE ALSO
|
||||
matdim, matmax, matmin, inverse
|
38
help/digit
Normal file
38
help/digit
Normal file
@@ -0,0 +1,38 @@
|
||||
NAME
|
||||
digit - digit at specified position in a decimal representation
|
||||
|
||||
SYNOPSIS
|
||||
digit(x, y)
|
||||
|
||||
TYPES
|
||||
x real
|
||||
y integer
|
||||
|
||||
return integer
|
||||
|
||||
DESCRIPTION
|
||||
By extending the digits on the left, and if necessary, the digits
|
||||
on the right, by infinite strings of zeros, abs(x) may be considered
|
||||
to have the decimal representation:
|
||||
|
||||
... d_2 d_1 d_0.d_-1 d_-2 ...
|
||||
|
||||
digit(x,y) then returns the digit d_y.
|
||||
|
||||
EXAMPLE
|
||||
> x = 12.34
|
||||
> print digit(x,2), digit(x,1), digit(x,0), digit(x,-1), digit(x,-2)
|
||||
0 1 2 3 4
|
||||
|
||||
> x = 10/7
|
||||
> print digit(x,1), digit(x,0), digit(x,-1), digit(x,-2), digit(x,-3)
|
||||
0 1 4 2 8
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
long qdigit(NUMBER *x, long y)
|
||||
|
||||
SEE ALSO
|
||||
bit
|
27
help/digits
Normal file
27
help/digits
Normal file
@@ -0,0 +1,27 @@
|
||||
NAME
|
||||
digits - return number of digits in an integer or integer part
|
||||
|
||||
SYNOPSIS
|
||||
digits(x)
|
||||
|
||||
TYPES
|
||||
x real
|
||||
|
||||
return integer
|
||||
|
||||
DESCRIPTION
|
||||
For real x, digits(x) returns the number of digits in the decimal
|
||||
representation of int(abs(x)).
|
||||
|
||||
EXAMPLE
|
||||
> print digits(0), digits(0.0123), digits(3.7), digits(-27), digits(-99.7)
|
||||
1 1 1 2 2
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
long qdigits(NUMBER *x)
|
||||
|
||||
SEE ALSO
|
||||
places
|
38
help/dp
Normal file
38
help/dp
Normal file
@@ -0,0 +1,38 @@
|
||||
NAME
|
||||
dp - dot product of two vectors
|
||||
|
||||
SYNOPSIS
|
||||
dp(x, y)
|
||||
|
||||
TYPES
|
||||
x, y 1-dimensional matrices with the same number of elements
|
||||
|
||||
return depends on the nature of the elements of x and y
|
||||
|
||||
DESCRIPTION
|
||||
Compute the dot product of two 1-dimensional matrices.
|
||||
|
||||
Let:
|
||||
|
||||
x = {x0, x1, ... xn}
|
||||
y = {y0, y1, ... yn}
|
||||
|
||||
Then dp(x,y) returns the result of the calculation:
|
||||
|
||||
x0*y0 + x1*y1 + ... + xn*yn
|
||||
|
||||
EXAMPLE
|
||||
> mat x[3] = {2,3,4}
|
||||
> mat y[3] = {3,4,5}
|
||||
> print dp(x,y)
|
||||
38
|
||||
|
||||
LIMITS
|
||||
x and y are 1-dimensional matrices
|
||||
x and y have the same number of elements
|
||||
|
||||
LIBRARY
|
||||
VALUE matdot(MATRIX *x, MATRIX *y)
|
||||
|
||||
SEE ALSO
|
||||
cp
|
86
help/environment
Normal file
86
help/environment
Normal file
@@ -0,0 +1,86 @@
|
||||
Environment variables
|
||||
|
||||
CALCPATH
|
||||
|
||||
A :-separated list of directories used to search for
|
||||
scripts filenames that do not begin with /, ./ or ~.
|
||||
|
||||
If this variable does not exist, a compiled value
|
||||
is used. Typically compiled in value is:
|
||||
|
||||
.:./lib:~/lib:${LIBDIR}/calc
|
||||
|
||||
where ${LIBDIR} is usually:
|
||||
|
||||
/usr/local/lib/calc
|
||||
|
||||
This value is used by the READ command. It is an error
|
||||
if no such readable file is found.
|
||||
|
||||
The CALCBINDINGS file searches the CALCPATH as well.
|
||||
|
||||
|
||||
CALCRC
|
||||
|
||||
On startup (unless -h or -q was given on the command
|
||||
line), calc searches for files along the :-separated
|
||||
$CALCRC environment variable.
|
||||
|
||||
If this variable does not exist, a compiled value
|
||||
is used. Typically compiled in value is:
|
||||
|
||||
${LIBDIR}/startup:~/.calcrc
|
||||
|
||||
where ${LIBDIR} is usually:
|
||||
|
||||
/usr/local/lib/calc
|
||||
|
||||
Missing files along the $CALCRC path are silently ignored.
|
||||
|
||||
CALCBINDINGS
|
||||
|
||||
On startup (unless -h or -q was given on the command
|
||||
line), calc reads key bindings from the filename specified
|
||||
in the $CALCRC environment variable. These key bindings
|
||||
are used for command line editing and the command history.
|
||||
|
||||
If this variable does not exist, a compiled value is used.
|
||||
Typically compiled in value is:
|
||||
|
||||
bindings
|
||||
or:
|
||||
altbind (bindings where ^D means exit)
|
||||
|
||||
The bindings file is searched along the CALCPATH. Unlike
|
||||
the READ command, a .cal extension is not added.
|
||||
|
||||
If the file could not be opened, or if standard input is not
|
||||
a terminal, then calc will still run, but fancy command line
|
||||
editing is disabled.
|
||||
|
||||
HOME
|
||||
|
||||
This value is taken to be the home directory of the
|
||||
current user. It is used when files begin with '~/'.
|
||||
|
||||
If this variable does not exist, the home directory password
|
||||
entry of the current user is used. If that information
|
||||
is not available, '.' is used.
|
||||
|
||||
PAGER
|
||||
|
||||
When invoking help, this environment variable is used
|
||||
to display a help file.
|
||||
|
||||
If this variable does not exist, a compiled value
|
||||
is used. Typically compiled in value is something
|
||||
such as 'more', 'less', 'pg' or 'cat'.
|
||||
|
||||
SHELL
|
||||
|
||||
When a !-command is used, the program indicated by
|
||||
this environment variable is used.
|
||||
|
||||
If this variable does not exist, a compiled value
|
||||
is used. Typically compiled in value is something
|
||||
such as 'sh' is used.
|
34
help/epsilon
Normal file
34
help/epsilon
Normal file
@@ -0,0 +1,34 @@
|
||||
NAME
|
||||
epsilon - set or read the stored epsilon value
|
||||
|
||||
SYNOPSIS
|
||||
epsilon([eps])
|
||||
|
||||
TYPES
|
||||
eps real number greater than 0 and less than 1
|
||||
|
||||
return real number greater than 0 and less than 1
|
||||
|
||||
DESCRIPTION
|
||||
Without args, epsilon() returns the current epsilon value.
|
||||
|
||||
With one arg, epsilon(eps) returns the current epsilon value
|
||||
and sets the stored epsilon value to eps.
|
||||
|
||||
The stored epsilon value is used as default value for eps in
|
||||
the functions appr(x, eps, rnd), sqrt(x, eps, rnd), etc.
|
||||
|
||||
EXAMPLE
|
||||
> oldeps = epsilon(1e-6)
|
||||
> print epsilon(), sqrt(2), epsilon(1e-4), sqrt(2), epsilon(oldeps)
|
||||
> .000001 1.414214 .000001 1.4142 .0001
|
||||
|
||||
LIMITS
|
||||
0 < eps < 1
|
||||
|
||||
LIBRARY
|
||||
void setepsilon(NUMBER *eps)
|
||||
NUMBER *_epsilon_
|
||||
|
||||
SEE ALSO
|
||||
XXX - fill in
|
38
help/errno
Normal file
38
help/errno
Normal file
@@ -0,0 +1,38 @@
|
||||
NAME
|
||||
errno - return a system error message
|
||||
|
||||
SYNOPSIS
|
||||
errno(errnum)
|
||||
|
||||
TYPES
|
||||
errnum int
|
||||
|
||||
return string
|
||||
|
||||
DESCRIPTION
|
||||
If a file builtin function such as fopen() encounters an error,
|
||||
it will return an errno number. This function will convert this
|
||||
number into a somewhat more meaningful string.
|
||||
|
||||
Note that errno() may return different strings on different systems.
|
||||
|
||||
EXAMPLE
|
||||
> badfile = fopen("not_a_file", "r")
|
||||
> if (!isfile(badfile)) print "error #" : badfile : ":", errno(badfile);
|
||||
error #2: No such file or directory
|
||||
|
||||
> print errno(13)
|
||||
Permission denied
|
||||
|
||||
> errno(31)
|
||||
"Too many links"
|
||||
|
||||
LIMITS
|
||||
none
|
||||
|
||||
LIBRARY
|
||||
none
|
||||
|
||||
SEE ALSO
|
||||
errno, fclose, feof, ferror, fflush, fgetc, fgetline, files, fopen,
|
||||
fprintf, isfile, printf, prompt
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user