# Category : BASIC Source Code

Archive : MATHWZ10.ZIP

Filename : MATHWIZ.DOC

The Math Wizard's Library for BASIC page 1

=-------------------------------------=

Version 1.0

MATHWIZ Copyright (c) 1991 Thomas G. Hanlin III

This is MATHWIZ, a library of assembly language and BASIC routines for use

with QuickBASIC version 4.5. Support for other recent versions of the BASIC

compiler is provided with registration. The MATHWIZ collection is

copyrighted and may be distributed only under the following conditions:

1) No fee of over $10.00 may be charged for distribution. This

restriction applies only to physical copies and is not meant to

prevent distribution by telecommunication services.

2) All MATHWIZ files must be distributed together in original, unaltered

form. This includes MATHWIZ.BI, MATHWIZ.DOC, MATHWIZ.LIB, MATHWIZ.NEW,

MATHWIZ.QLB, MATHWIZ.REF, BIBLIO.TXT, CATALOG.TXT, FILES.LST,

LIBRARY.TXT, QUESTION.TXT, and REGISTER.TXT.

You use this library at your own risk. It has been tested by me on my own

computer, but I will not assume any responsibility for any problems which

MATHWIZ may cause you. If you do encounter a problem, please let me know

about it, and I will do my best to verify and repair the error.

It is expected that if you find MATHWIZ useful, you will register your copy.

You may not use MATHWIZ routines in programs intended for sale unless you

have registered. Registration entitles you to receive the latest version of

MATHWIZ, complete with full source code in assembly language and BASIC. The

assembly code is designed for the OPTASM assembler by SLR Systems and will

require modifications if you wish to use it with MASM or TASM. You will be

able to compile the BASIC code with whatever version of the compiler you

have, allowing you to use MATHWIZ with QuickBASIC versions 4.0 - 4.5 and

BASCOM versions 6.0 - 7.1 (QBX and BASCOM 7.x far strings aren't supported).

Warning: Use of MATHWIZ for more than 30 days without registering has been

determined to cause the Surgeon General to issue warning labels! If you use

this product, please do register.

For an example of how to set up your program to access the MATHWIZ library,

how to LINK the routines, and so forth, see the LIBRARY.TXT file.

So who's the Math Wizard? With this library, you will be! Read this

tome well, for invoking these routines without proper preparation may bring

unexpected results. Cape and hat (optional) not included. No assembly

required.

Note that MATHWIZ may be considered an extension of my main BASIC library,

BASWIZ. See CATALOG.TXT for additional information.

Table of Contents page 2

Overview and Legal Info ................................................ 1

Extensions to BASIC's floating point ................................... 3

BCD Math ............................................................... 4

Fractions .............................................................. 7

Miscellaneous Notes .................................................... 8

Troubleshooting ........................................................ 9

Using MATHWIZ with PDQ ................................................ 10

Extensions to BASIC's floating point page 3

For the most part, this library is designed to provide alternatives to the

math routines that are built into BASIC. Still, BASIC's floating point is

quite adequate for many purposes, so there's no sense in ignoring it. Here

are a few functions which make BASIC math a bit more convenient.

Result! = FactS!(Nr%) ' factorial

Result! = CotS!(Nr!) ' cotangent

Result! = CscS!(Nr!) ' cosecant

Result! = SecS!(Nr!) ' secant

Result! = Deg2RadS!(Nr!) ' convert degrees to radians

Result! = Rad2DegS!(Nr!) ' convert radians to degrees

Result! = Cent2Fahr!(Nr!) ' convert centigrade to Fahrenheit

Result! = Fahr2Cent!(Nr!) ' convert Fahrenheit to centigrade

Result! = Kg2Pound!(Nr!) ' convert kilograms to pounds

Result! = Pound2Kg!(Nr!) ' convert pounds to kilograms

Pi! = PiS! ' the constant "pi"

e! = eS! ' the constant "e"

Result# = FactD#(Nr%) ' factorial

Result# = CotD#(Nr#) ' cotangent

Result# = CscD#(Nr#) ' cosecant

Result# = SecD#(Nr#) ' secant

Result# = Deg2RadD#(Nr#) ' convert degrees to radians

Result# = Rad2DegD#(Nr#) ' convert radians to degrees

Pi# = PiD# ' the constant "pi"

e# = eD# ' the constant "e"

Like BASIC, the trig functions expect the angle to be in radians. Constants

are expressed to the maximum precision available. If you are not familiar

with variable postfix symbols, "!" indicates single precision and "#"

indicates double precision. See your BASIC manual for further details.

BCD Math page 4

Some of you may not have heard of BCD math, or at least not have more than a

passing acquaintance with the subject. BCD (short for Binary-Coded Decimal)

is a way of encoding numbers. It differs from the normal method of handling

numbers in several respects. On the down side, BCD math is much slower than

normal math and the numbers take up more memory. However, the benefits may

far outweigh these disadvantages, depending on your application: BCD math is

absolutely precise within your desired specifications, and you can make a BCD

number as large as you need. If your applications don't require great range

or precision out of numbers, normal BASIC math is probably the best choice.

For scientific applications, accounting, engineering and other demanding

tasks, though, BCD may be just the thing you need.

The BCD math routines provided by MATHWIZ allow numbers of up to 255 digits

long (the sign counts as a digit, but the decimal point doesn't). You may

set the decimal point to any position you like, as long as there is at least

one digit position to the left of the decimal.

Since QuickBASIC doesn't support BCD numbers directly, we store the BCD

numbers in strings. The results are not in text format and won't mean much

if displayed. A conversion routine allows you to change a BCD number to a

text string in any of a variety of formats. The BCD numbers can also be

compressed to allow more efficient storage.

Note that the BCD math handler doesn't yet track overflow/underflow error

conditions. If you anticipate that this may be a problem, it would be a good

idea to screen your input or to make the BCD range large enough to avoid

these errors.

Let's start off by examining the routine which allows you to set the BCD

range:

BCDSetSize LeftDigits%, RightDigits%

The parameters specify the maximum number of digits to the left and to the

right of the decimal point. There must be at least one digit on the left,

and the total number of digits must be less than 255. The BCD strings will

have a length that's one larger than the total number of digits, to account

for the sign of the number. The decimal point is implicit and doesn't take

up any extra space.

It is assumed that you will only use one size of BCD number in your program--

there are no provisions for handling mixed-length BCD numbers. Of course,

you could manage that yourself with a little extra work, if it seems like a

useful capability. If you don't use BCDSetSize, the default size of the BCD

numbers will be 32 (20 to the left, 11 to the right, 1 for the sign).

You can get the current size settings in your program, too:

BCDGetSize LeftDigits%, RightDigits%

BCD Math page 5

Before doing any BCD calculations, you must have some BCD numbers! The

BCDSet routine takes a number in text string form and converts it to BCD:

TextSt$ = "1234567890.50"

Nr$ = BCDSet$(TextSt$)

If your numbers are stored as actual numbers, you can convert them to a text

string with BASIC's STR$ function, then to BCD. Leading spaces are ignored:

Nr$ = BCDSet$(STR$(AnyNum#))

BCD numbers can also be converted back to text strings, of course. You may

specify how many digits to the right of the decimal to keep (the number will

be truncated, not rounded). If the RightDigits% is positive, trailing zeros

will be kept; if negative, trailing zeros will be removed. There are also

various formatting options which may be used. Here's how it works:

TextSt$ = BCDFormat$(Nr$, HowToFormat%, RightDigits%)

The HowToFormat% value may be any combination of the following (just add the

numbers of the desired formats together):

0 plain number

1 use commas to separate thousands, etc

2 start number with a dollar sign

4 put the sign on the right side instead of the left side

8 use a plus sign instead of a space if number is not negative

The BCD math functions are pretty much self-explanatory, so I'll keep the

descriptions brief. Here are the single-parameter functions:

Result$ = BCDAbs$(Nr$) ' take the absolute value of a number

Result$ = BCDCos$(Nr$) ' cosine function

Result$ = BCDCot$(Nr$) ' cotangent function

Result$ = BCDCsc$(Nr$) ' cosecant function

Result$ = BCDDeg2Rad$(Nr$) ' convert degrees to radians

e$ = BCDe$ ' get the value of the constant "e"

Result$ = BCDFact$(N%) ' calculate the factorial of integer N

Result$ = BCDNeg$(Nr$) ' negate a number

pi$ = BCDpi$ ' get the value of the constant "pi"

Result$ = BCDRad2Deg$(Nr$) ' convert radians to degrees

Result$ = BCDSec$(Nr$) ' secant function

Result% = BCDSgn%(Nr$) ' signum function

Result$ = BCDSin$(Nr$) ' sine function

Result$ = BCDSqr$(Nr$) ' get the square root of a number

Result$ = BCDTan$(Nr$) ' tangent function

BCD Math page 6

Notes on the single-parameter functions:

The signum function returns an integer based on the sign of the BCD number:

-1 the BCD number is negative

0 the BCD number is zero

1 the BCD number is positive

BCDpi is currently accurate to as many as 200 decimal positions. BCDe is

accurate to as many as 115 decimal places. The actual accuracy, of course,

depends on the size of BCD numbers you've chosen.

The trigonometric functions (cos, sin, tan, sec, csc, cot) expect angles in

radians. BCDDeg2Rad and BCDRad2Deg will allow you to convert back and

forth between radians and degrees, although some accuracy may be lost

inasmuch as they rely on BCDpi.

Here is a list of the two-parameter functions:

Result$ = BCDAdd$(Nr1$, Nr2$) ' add two numbers together

Result$ = BCDSub$(Nr1$, Nr2$) ' subtract the second nr from the first

Result$ = BCDMul$(Nr1$, Nr2$) ' multiply one number by another

Result$ = BCDDiv$(Nr1$, Nr2$) ' divide the first number by the second

Result$ = BCDPower$(Nr$, Power%) ' raise a number to a power

Result% = BCDCompare%(Nr1$, Nr2$) ' compare two numbers

The comparison function returns an integer which reflects how the two numbers

compare to eachother:

-1 Nr1 < Nr2

0 Nr1 = Nr2

1 Nr1 > Nr2

Fractions page 7

Using BCD allows you to represent numbers with excellent precision, but at a

fairly large cost in speed. Another way to represent numbers with good

precision is to use fractions. Fractions can represent numbers far more

accurately than BCD, but can be handled much more quickly. There are some

limitations, of course, but by now you've guessed that's always true!

Each fraction is represented by MATHWIZ as a string of 8 characters. The

numerator (top part of the fraction) may be anywhere from -999,999,999 to

999,999,999. The denominator (the bottom part) may be from 0 to 999,999,999.

This allows handling a fairly wide range of numbers quite exactly.

Fractions can be converted to or from numeric text strings in any of three

formats: real number (e.g., "1.5"), plain fraction (e.g., "3/2"), or whole

number and fraction (e.g., "1 1/2"). Internally, the numbers are stored as a

plain fraction, reduced to the smallest fraction possible which means the

same thing (for instance, "5/10" will be reduced to "1/2").

To convert a numeric text string into a fraction, do this:

Nr$ = FracSet$(NumSt$)

To convert a fraction into a numeric text string, try this:

NumSt$ = FracFormat$(Nr$, HowToFormat%)

The formatting options are:

0 convert to plain fraction

1 convert to whole number and fraction

2 convert to decimal number

Here is a list of the other functions available:

Result$ = FracAbs$(Nr$) ' take the absolute value of a fraction

Result$ = FracAdd$(Nr1$, Nr2$) ' add two fractions

Result% = FracCompare%(Nr1$, Nr2$) ' compare two fractions

Result$ = FracDiv$(Nr1$, Nr2$) ' divide the first fraction by the second

Result$ = FracMul$(Nr1$, Nr2$) ' multiply two fractions

Result$ = FracNeg$(Nr$) ' negate a fraction

Result% = FracSgn%(Nr$) ' signum function for a fraction

Result$ = FracSub$(Nr1$, Nr2$) ' subtract the 2nd fraction from the 1st

Fractions are automatically reduced to allow the greatest possible range.

Note that little range-checking is done at this point, so you may wish to

screen any input to keep it reasonable.

Result FracSgn FracCompare

-1 negative # 1st < 2nd

0 # is zero 1st = 2nd

1 positive # 1st > 2nd

Miscellaneous Notes page 8

A certain lack of speed is inherent in BCD math, especially if you require

high precision. The division, root, and trig routines in particular are

quite slow. I'll attempt to improve this in the future, but the routines are

already fairly well optimized, so don't expect miracles. Precision costs!

The fraction routines are much faster, but they have a much smaller range.

I'll have to do some experimenting on that. It may prove practical to use a

subset of the BCD routines to provide an extended range for fractions without

an unreasonable loss in speed.

I am hoping to add Bessel functions, matrix math, logarithms and other

goodies in the future as I am able to obtain information on how to handle

these things. Your suggestions as to good reference books and other routines

that might be useful will be most welcome.

Troubleshooting page 9

Problem:

QB says "subprogram not defined".

Solution:

The definition file was not included. Your program must contain the line

REM $INCLUDE: 'MATHWIZ.BI'

before any executable code in your program. You should also start

QuickBASIC with

QB /L MATHWIZ

so it knows to use the MATHWIZ library.

Problem:

LINK says "unresolved external reference".

Solution:

Did you specify MATHWIZ as the library when you used LINK? You should!

The MATHWIZ.LIB file must be in the current directory or along a path

specified by the LIB environment variable (like PATH, but for LIB files).

Problem:

The BCDSIN$ function returns strange results.

Solution:

Make sure you have left some room on the left side of the decimal as well

as the right! The sine calculations can involve fairly large numbers.

Using MATHWIZ with PDQ page 10

Unfortunately, most MATHWIZ routines are not compatible with Crescent

Software's PDQ library. Some of the routines require floating point math,

which is not supported by PDQ. Many of the routines require dynamic string

functions, which aren't supported by PDQ either. So it goes.

Crescent thoughtfully provided me with a free copy of PDQ in order that I

might resolve any incompatibilities between it and my BASIC libraries. In

this case, it didn't prove practical to do so.

If you are not familiar with PDQ, it is a replacement library for BASIC's own

runtime libraries. While not providing every capability of plain QuickBASIC,

it allows you to create substantially smaller EXE files for those programs

that qualify. Support is currently lacking for floating point (single/double

precision) numbers, music, and graphics, among other things. I understand

that these will be added to a future version of the library. Communications

support is available as an add-on package. PDQ also adds new capabilities

which are quite impressive, such as being able to write small TSRs in BASIC.

Check with Crescent for more recent details.