Dec 102017

C precision math library. | |||
---|---|---|---|

File Name | File Size | Zip Size | Zip Type |

ADDSUB.C | 13292 | 4318 | deflated |

APM.ARF | 95 | 65 | deflated |

APM.H | 14634 | 4956 | deflated |

APMLOCAL.H | 10616 | 4052 | deflated |

AUTHOR.NOT | 828 | 497 | deflated |

CALC.C | 18723 | 5475 | deflated |

FUNCTION | 16743 | 4692 | deflated |

LICENSE | 8342 | 3315 | deflated |

MAKEFILE | 1507 | 600 | deflated |

MAKEFILE.MSC | 977 | 318 | deflated |

MEMORY.C | 13116 | 4688 | deflated |

MISC.C | 18872 | 5475 | deflated |

MULDIV.C | 16553 | 5402 | deflated |

README | 7206 | 3069 | deflated |

README.1ST | 116 | 96 | deflated |

TEST.ZIP | 3451 | 3228 | deflated |

UTILS.C | 28270 | 7514 | deflated |

# Download File APM.ZIP Here

## Contents of the README file

Arbitrary Precision Math Library

The Arbitrary Precision Math Library is a series of routines that

allows the user to perform math to any level of accuracy that is

desired. These APM entities ("APM" == "Arbitrary Precision Math") can

be initialized from character strings or from long integers, and they

can be converted back into character strings by a routine that allows

simple formatting. With the exception of the routines that do

division, the results of APM operations are guaranteed to contain

enough precision to hold exact values. The APM routines will

automatically allocate enough space in their results to hold the

proper number of digits.

The APM math is done on a new data type called "APM". This is

actually a pointer to a structure, but the contents of the structure

should never be manipulated: all operations on APM entities are done

through a functional interface.

APM items can be represented in any of 36 bases: 2 through 36 and

10000. The latter is quite useful: numbers that are represented in

bases that are powers of 10 are quite easy to accurately convert to

and from character strings containing their decimal representation,

and 10000 is the largest power of 10 that fits into a short integer

(16 bits). The base must fit into a short integer since calculations

internal to the APM routines need up to twice as much storage as is

needed to hold the base, and the largest unit we can deal with easily

is a long integer (2 shorts). It turns out that speed improves and

memory usage decreases as the magnitude of the base increases, so base

10000 is a win in both counts. I have done some informal benchmarks

in which base 10000 is 6 to 10 times faster than base 10 for numbers

with 15 - 20 decimal digits of precision.

Although there is a multitude of bases, there is as yet no provision

for conversion from one base to another, except for the special case

of converting between base-10 character strings and base-10000 APM

values. All the input APM parameters to any given APM routine must be

of the same base.

The caller must initialize all APM values before the routines can

operate on them (including the values intended to contain results of

calculations). Once this initialization is done, the user never needs

to worry about resizing the APM values, as this is handled inside the

APM routines and is totally invisible to the user.

The result of a APM operation cannot be one of the other APM operands.

If you want this to be the case, you must put the result into a

temporary variable and then assign it to the appropriate operand.

All of the routines set the value of a global integer called

"apm_errno" to an error status: 0 means the operation succeeded, > 0

means there was a warning but that there still is a result, and < 0

means there was an error which prohibited the operation from

completing. Except where otherwise noted, the routines return this

same status value.

The caller has the option of registering a handler for errors and

warnings. If this has been done, the handler will be invoked as each

APM routine returns, and it will be passed appropriate information as

to the status of the call to this APM routine. With a registered

error handler it is not necessary for the caller to check the error

code after each call to a APM routine.

For ease of debugging, each APM routine is actually a macro that saves

the file name and line number and then calls a function of a slightly

different name. This allows the error handler to report the exact

location of the APM operation which caused the error. The macros you

will use have names of the form "apmRoutineName". To get the

corresponding actual function name (say, when using a debugger),

replace all capital letters with an underbar ("_") followed by its

lower-case counterpart. For example, for a hypothetical routine

called "apmRoutineName", the actual function will be named

"apm_routine_name". You should never explicitly call the actual

function.

You should avoid using symbols that start with the characters "APM_"

and "apm_", as they may clash with symbols that already exist in the

APM Library.

There is one routine for each basic arithmetic operation such as

adding, subtracting, etc. This can become cumbersome when the result

of a complicated expression is desired. Therefore, I have added a

routine that will perform a series of operations in the manner of an

RPN ("Reverse Polish Notation") calculator. See the routine 'apmCalc'

(below) for more details.

In my original version of this library, I discovered that a great deal

of system overhead was wasted allocating and deallocating APM values.

So, I adopted what has turned out to be a noticibly faster allocation

scheme: newly allocated APM values are stored in a list. When the

user disposes of one of these, it isn't really freed: its entry in the

list is marked as unused. Subsequent attempts to allocate a new APM

value will make use of any existing entries in this list that are

marked as unused instead of allocating a new entry. Only when there

are no unused entries in the list will a new entry be allocated.

There is a routine that can be called which will perform a garbage

collection: i.e., it actually frees all unused APM entries (see

'apmGarbageCollect', below).

A file called apm.h must be included in all programs that use the APM

routines. It defines the "APM" data type, the error codes, the

apm_errno variable, and several other things.

This software was written in as portable a manner as possible. I have

gotten it running successfully under several environments: on a Sun

3/xxx using SunOS 3.5 and 4.0, on an IBM RT running under AIX, under

MSDOS on an IBM PC using Microsoft C version 5.1 and Turbo C version

1.5 (or was it version 2.0?). There are two makefiles: the one called

"Makefile" is the unix version ... it works under SunOS 3.5 and I

presume it would be easy to alter it to work under other unix

environments; the one called "makefile.msc" will build the library

under MSDOS using Microsoft C version 5.1 ... it is meant to run with

the make program "PC/MAKE".

I'm sure that some of you will find ways of enhancing and speeding up

the routines in this library. Time permitting, I will be doing that

as well. I urge you to post your bug fixes and changes to the net and

mail them to me at my address below, so they might be incorporated

into a later version of this library. Some suggested areas of

enhancement and optimization are:

1)Somehow speeding up the memory allocation scheme.

2)Some sort of floating-point/APM conversion. I left this out

because of the widely varying floating-point formats that

exist on the various machines these routines can and might run

on, and because I intended APM to *replace* floating-point,

not to work in conjunction with it.

3)Base conversion.

4)Roots, powers, logarithms, trig functions, exponential functions,

etc.

5) More productions in the makefiles ("install", "rdist", etc.).

6) A fancy installation script.

7)Writing a man page for all this.

## Contents of the README.1ST file

Arbitrary Precision Math Library

The Arbitrary Precision Math Library is a series of routines that

allows the user to perform math to any level of accuracy that is

desired. These APM entities ("APM" == "Arbitrary Precision Math") can

be initialized from character strings or from long integers, and they

can be converted back into character strings by a routine that allows

simple formatting. With the exception of the routines that do

division, the results of APM operations are guaranteed to contain

enough precision to hold exact values. The APM routines will

automatically allocate enough space in their results to hold the

proper number of digits.

The APM math is done on a new data type called "APM". This is

actually a pointer to a structure, but the contents of the structure

should never be manipulated: all operations on APM entities are done

through a functional interface.

APM items can be represented in any of 36 bases: 2 through 36 and

10000. The latter is quite useful: numbers that are represented in

bases that are powers of 10 are quite easy to accurately convert to

and from character strings containing their decimal representation,

and 10000 is the largest power of 10 that fits into a short integer

(16 bits). The base must fit into a short integer since calculations

internal to the APM routines need up to twice as much storage as is

needed to hold the base, and the largest unit we can deal with easily

is a long integer (2 shorts). It turns out that speed improves and

memory usage decreases as the magnitude of the base increases, so base

10000 is a win in both counts. I have done some informal benchmarks

in which base 10000 is 6 to 10 times faster than base 10 for numbers

with 15 - 20 decimal digits of precision.

Although there is a multitude of bases, there is as yet no provision

for conversion from one base to another, except for the special case

of converting between base-10 character strings and base-10000 APM

values. All the input APM parameters to any given APM routine must be

of the same base.

The caller must initialize all APM values before the routines can

operate on them (including the values intended to contain results of

calculations). Once this initialization is done, the user never needs

to worry about resizing the APM values, as this is handled inside the

APM routines and is totally invisible to the user.

The result of a APM operation cannot be one of the other APM operands.

If you want this to be the case, you must put the result into a

temporary variable and then assign it to the appropriate operand.

All of the routines set the value of a global integer called

"apm_errno" to an error status: 0 means the operation succeeded, > 0

means there was a warning but that there still is a result, and < 0

means there was an error which prohibited the operation from

completing. Except where otherwise noted, the routines return this

same status value.

The caller has the option of registering a handler for errors and

warnings. If this has been done, the handler will be invoked as each

APM routine returns, and it will be passed appropriate information as

to the status of the call to this APM routine. With a registered

error handler it is not necessary for the caller to check the error

code after each call to a APM routine.

For ease of debugging, each APM routine is actually a macro that saves

the file name and line number and then calls a function of a slightly

different name. This allows the error handler to report the exact

location of the APM operation which caused the error. The macros you

will use have names of the form "apmRoutineName". To get the

corresponding actual function name (say, when using a debugger),

replace all capital letters with an underbar ("_") followed by its

lower-case counterpart. For example, for a hypothetical routine

called "apmRoutineName", the actual function will be named

"apm_routine_name". You should never explicitly call the actual

function.

You should avoid using symbols that start with the characters "APM_"

and "apm_", as they may clash with symbols that already exist in the

APM Library.

There is one routine for each basic arithmetic operation such as

adding, subtracting, etc. This can become cumbersome when the result

of a complicated expression is desired. Therefore, I have added a

routine that will perform a series of operations in the manner of an

RPN ("Reverse Polish Notation") calculator. See the routine 'apmCalc'

(below) for more details.

In my original version of this library, I discovered that a great deal

of system overhead was wasted allocating and deallocating APM values.

So, I adopted what has turned out to be a noticibly faster allocation

scheme: newly allocated APM values are stored in a list. When the

user disposes of one of these, it isn't really freed: its entry in the

list is marked as unused. Subsequent attempts to allocate a new APM

value will make use of any existing entries in this list that are

marked as unused instead of allocating a new entry. Only when there

are no unused entries in the list will a new entry be allocated.

There is a routine that can be called which will perform a garbage

collection: i.e., it actually frees all unused APM entries (see

'apmGarbageCollect', below).

A file called apm.h must be included in all programs that use the APM

routines. It defines the "APM" data type, the error codes, the

apm_errno variable, and several other things.

This software was written in as portable a manner as possible. I have

gotten it running successfully under several environments: on a Sun

3/xxx using SunOS 3.5 and 4.0, on an IBM RT running under AIX, under

MSDOS on an IBM PC using Microsoft C version 5.1 and Turbo C version

1.5 (or was it version 2.0?). There are two makefiles: the one called

"Makefile" is the unix version ... it works under SunOS 3.5 and I

presume it would be easy to alter it to work under other unix

environments; the one called "makefile.msc" will build the library

under MSDOS using Microsoft C version 5.1 ... it is meant to run with

the make program "PC/MAKE".

I'm sure that some of you will find ways of enhancing and speeding up

the routines in this library. Time permitting, I will be doing that

as well. I urge you to post your bug fixes and changes to the net and

mail them to me at my address below, so they might be incorporated

into a later version of this library. Some suggested areas of

enhancement and optimization are:

1)Somehow speeding up the memory allocation scheme.

2)Some sort of floating-point/APM conversion. I left this out

because of the widely varying floating-point formats that

exist on the various machines these routines can and might run

on, and because I intended APM to *replace* floating-point,

not to work in conjunction with it.

3)Base conversion.

4)Roots, powers, logarithms, trig functions, exponential functions,

etc.

5) More productions in the makefiles ("install", "rdist", etc.).

6) A fancy installation script.

7)Writing a man page for all this.

The files in TEST.ARC are to be installed in a separate directory

(they duplicate names of files in APM.ARC).

December 10, 2017
Add comments