FPU Object
Updated: Feb 11, 2008
With some practice and perhaps the help of a manual on FPU function, even the
beginning programmer can use the FPU object. In brief, one loads one or more
values and uses methods to modify them. A statement as simple as x=FPU.pop
retrieves the result.
Developers can implement their formulas by using both the conventional and FPU
object instructions and compare the results as follows:
DEFREAL10 x1,x2
x1=y*cos(z) 'conventional coding
FPU.load y: FPU.load z: FPU.cos: FPU.mul: x2=FPU.pop
' alternatively,
' WITH FPU
' .load y: .load z: .cos: .mul
' END WITH: x2=FPU.pop
IF x1=x2 THEN PRINT "I coded it right."
Now the x2 calculation may appear to be more cumbersome than the x1. Sure, but
imagine you are multiplying var y times a million numbers. With the
conventional coding for x1, you would be loading var y 999,999 times for
nothing. The x2 steps above illustrate that one can load y just once and then
proceed through your million values of z.
Here is a common example of speed optimization. We have calculated the mean
and standard deviation (sd) of a set of numbers D. Now we normalize the data
in the array D:
FPU.load mean: FPU.load sd
for i=1 to n
x=D(i): FPU.load x
FPU.sub 2: FPU.div 1 'x=(x-mean)/sd
D(i)=FPU.pop 'normalized value: D_mean=0; D_sd=1
next i
x=FPU.pop: x=FPU.pop 'remove preloaded values
Notice the conventional formula (x-mean)/sd would require loading the mean and
sd over and over with each iteration 1 to n above. Rather, the FPU Object
allows you to load the mean and sd once, and then loop through the data
normalizing it.
Please keep in mind that a "constant" for a loop as shown above is simply any
value that does not change in the loop and thus may be a variable in your code.
HotBasic defaults to maximum precision by storing floating literals such as
"2.5" with REAL10 precision. However, in loops and extensive calcuations,
reading REAL10 values takes more time than reading DOUBLE values. Hence, if
speed is a concern and your constant does not require REAL10 precision, save
such floating literals as DOUBLE constants:
defdbl c2_5 = 2.5
'code
fpu.load c2_5: fpu.load x: fpu.mul 1 'x = x * c2_5
x = fpu.pop 'get result
The exclusive HotBasic FPU Object differs from conventional coding in several
ways. For operations on two operands (specifically ADD, SUB, SUBR, MUL, DIV,
DIVR, IADD, ISUB, ISUBR, IMUL, IDIV and IDIVR) the operand loaded first stays
on the FPU. E.g, if a matrix is to be multiplied by a constant, that value
would have to be loaded just once.
Normally, IDIV and IDIVR can result in floating values; however, the FPU Object
is coded to produce integer results similar to the "\" operator in conventional
coding. E.g., i = a \ b 'is integer divide.
Note: "top" refers to ST or ST(0) or last value loaded.
PROPERTIES (Read/Write):
~~~~~~~~~~ ~~~~~~~~~~~~~
CONTROL Returns or stores FPU control word. See STATUS examples.
STATE Saves or restores coprocesser state to/from a 14 byte buffer.
STATUS Returns FPU status word. fpustat=FPU.status
Stores FPU status word. FPU.status=fpustat
PROPERTIES (Read Only Numeric):
~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
ERROR 0 = no exception.
FPU.error returns 7 FPU exception bits which may be examined:
invalid operation (&H1), denormalized (&H2), divide by zero (&H4),
overflow (&H8), underflow (&H10), precision reduced (&H20),
FPU stack fault (&H40).
i = FPU.error 'assign to non-float to avoid resetting FPU error flags
IF i OR 28 THEN PRINT "zero divide or overflow or underflow"
Except where specified, METHODS modify the value at "top" of FPU stack:
METHODS Arguments & Comments
~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
ABS Absolute value
ACOS Arc cosine
ADD Add
ADD n Add FPU value at index n (1 to 7)
ADDP Add FPU values 0 and 1; ; value 0 popped; result at 0
AND Logical AND
ASIN Arc sine
ATAN,ATN Arc tangent where top = x/y
BCDLOAD src Load BCD data from src; src = real10-dimensioned variable.
BCDPOP dst dst receives BCD data; dst = real10 variable (10 byte buffer).
CHS Change sign
COPY Load copy of top value; e.g, .load x: .copy: .mul gives x^2
COS Cosine
DIV Divide
DIV n Dividy by FPU value at index n (1 to 7)
DIVP Divide FPU value 0 by value 1; value 0 popped; result at 0
DIVR Divide reverse operand order
EXAM Examine top value and set condition codes in STATUS.
EXP Exponential function; e raised to the power of top
EXCHANGE n Exchange FPU value n by top, n = 1 to 7; default n = 1
EXTRACT Exponent replaces top; mantissa pushed on to FPU stack.
FRAC Fractional part of top replaces top
HCOS Hyperbolic cosine
HSIN Hyperbolic sine
HTAN Hyperbolic tangent
IADD Integer add (integer result)
IDIV Integer divide (integer result)
IDIVR Integer divide reverse operand order (integer result)
IMUL Integer multiply (integer result)
INIT Initialize FPU unit
INT Convert to integer less than or equal to top
ISUB Integer subtract (integer result)
ISUBR Integer subtract reverse operand order (integer result)
LOAD scr Load FPU from scr, any valid numeric data type.
LOADENV scr Load FPU environment from scr (94 byte buffer)
LN Natural logarithm
LNTWO Load natural log of 2
LOG Logarithm base 10
LOG2E Load logarithm base 2 of e
LOG2TEN Load logarithm base 2 of 10
LOGTWO Load logarithm base 10 of 2
MUL Multiply
MUL n Multiply by FPU value at index n (1 to 7)
MULP Multiply FPU values 0 and 1; value 0 popped; result at 0
NAPIER Load napier value e
NEG Change sign; same as CHS
ONE Load value = 1
OR Logical OR FPU value 1 and top
PI Load pi
POP Retrieve value and "pop" FPU stack. E.g., x=FPU.pop
PREM Partial remainder
READ Retrieve value. E.g., x=FPU.read
ROUND Convert to integer by round method
SAVEENV dst Save FPU environment to dst (94 byte buffer)
SCALE Scale by power of 2
SGN Get sign (1,0,-1) of top
SIN Sine
SINCOS FPU sincos generation
SQR Square root
SUB Subtract
SUB n Subtract FPU value at index n (1 to 7)
SUBP Subtract FPU value 1 from 0; value 0 popped; result at 0
SUBR Subtract reverse operand order
TAN Tangent
TEST Integer compare and pop
XOR Logical XOR FPU value 1 and top
XEXPY X ^ Y where X is FPU value 1; Y is top
YL2X Y * logarithm base 2 of X
YL2XP1 Y * logarithm base 2 of (X+1)
2XM1 (2 ^ X) - 1
ZERO Load value of zero
###########
hotfpu.bas and hotfpu2.bas show FPU Object coding examples.
Copyright 2003-2008 James J Keene PhD
Original Publication: Aug 26, 2003