*********************** MATHEMATICAL SOLUTIONS ***************************** ASMLIB's SOLVE subroutines are handy for many number crunching problems. Most SOLVE subroutines require a math coprocessor. In subroutines requiring a math coprocessor, the coprocessor must have been initialized with FINIT or FNINIT before calling the subroutine. See MathChip in SYSTEM.DOC. Note that the 80x87 math coprocessors do not understand unsigned integers. °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° C2F: convert degrees Celcius to degrees Fahrenheit Source: f2c.asm 80x87 required Call with: ST(0) = degrees Celcius Returns: ST(0) = degrees Fahrenheit Uses: ST(0), 80x87 flags Example: extrn c2f:proc .data c0 dw 100 ; 100 degrees Celcius f0 dw ? ; going to store degrees Fahrenheit here .code . . . fild c0 ; load degrees Celcius into ST(0) call c2f ; returns degrees Fahrenheit in ST(0) fistp f0 ; save degrees Fahrenheit and pop the 8087's stack °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° CUBEFITF4: fit a cubic equation to a set of float4 data CUBEFITF8: fit a cubic equation to a set of float8 data CUBEFITI2: fit a cubic equation to a set of integer2 data CUBEFITI4: fit a cubic equation to a set of integer4 data Source: cubefit.asm 80x87 required CubeFit subroutines use the Least Squares method to calculate the a, b, c and d coefficients of the equation y = a + bx + c(x^2) + d(x^3) which best fits the given data points. See also QuadFit and LineFit. The data series at DS:[BX] consists of n sets of x and y coordinates. Call with: DS:[BX] pointing to data series CX = number of (x,y) points Returns: ST(0) = a ST(1) = b ST(2) = c ST(3) = d Uses: entire 80x87 stack Example: extrn cubefiti2:proc .data points dw 1,6 ; first (x,y) coordinate pair: x0 = 1, y0 = 6 dw 2,17 ; x1 = 2, y1 = 17 dw 5,86 ; x2 = 5, y2 = 86 dw 4,57 ; x3 = 4, y3 = 57 dw 3,34 ; x4 = 3, y4 = 34 n equ ($-points) shr 2 ; number of coordinate pairs (5 in this case) .code ; program fragment assumes DS:@data . . . lea bx,points ; point to data series mov cx,n ; 5 data points call cubefiti2 ; returns ST(0) = a ; ST(1) = b ; ST(2) = c ; ST(3) = d °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° DEG2RAD: convert degrees of arc to radians Source: deg2rad.asm 80x87 required Call with: ST(0) = degrees of arc Returns: ST(0) = radians Uses: 80x87 stack - ST(6) and ST(7) are lost Example: include asm.inc extrn deg2rad:proc .data deg dw 180 ; dumb example - everyone knows this is pi radians .code ; program fragment assumes DS:@data . . . fild deg ; load degrees into ST(0) call deg2rad ; it comes back with ST(0) = radians °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° F2C: convert degrees Fahrenheit to degrees Celcius Source: f2c.asm 80x87 required Call with: ST(0) = degrees Fahrenheit Returns: ST(0) = degrees Celcius Uses: ST(0), 80x87 flags Example: extrn f2c:proc .data f0 dw 212 ; 212 degrees Farenheit c0 dw ? ; going to store degrees Celcius here .code ; program fragment assumes DS:@data . . . fild f0 ; load degrees Fahrenheit into ST(0) call f2c ; returns degrees Celcius in ST(0) fistp c0 ; save degrees Celcius and pop the 8087's stack °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° FACTORIAL: calculates the factorial of an integer Source: factori.asm 80x87 required Call with: AX = signed integer value Returns: ST(0) = factorial of the integer value Note: factorials get very large with relatively small integers Uses: ST(0); coprocessor stack is pushed, ST(7) is lost Example: extrn factorial:proc .code . . . mov ax,6 ; gonna calculate the factorial of 6 call factorial °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° FPRIMEI2: calculate the derivative of a polynomial function Source: fprimei2.asm 80x87 NOT required Call with: DS:[SI] pointing to equation coefficients; all coefficients must be 2-byte signed integers CX = order of polynomial (i. e., a quadratic function is a second-order polynomial, so CX = 2) Returns: nothing Uses: nothing Example: extrn fprimei2:proc .data fx dw 2,0,3,2,0,5 ; the function y = 2+3*(x^2)+2*(x^3)+5*(x^5) .code ; program fragment assumes DS:@data . . . mov cx,5 ; fifth order polynomial lea si,fx ; point to f(x) coefficients (2-byte integers) call fprimei2 ; calculate derivative of the function ; results: ; fx=0, fx+2=6, fx+4=6, fx+6=0, fx+8=25, fx+10=0 °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° FPRIMEF4: calculate the derivative of a polynomial function Source: fprimef4.asm (mathchip.asm, i2tof4.asm, mulf4.asm) 80x87 NOT required Call with: DS:[SI] pointing to equation coefficients; all coefficients must be float4 values CX = order of polynomial (i. e., a quadratic function is a second-order polynomial, so CX = 2) FPrimeF4 uses the 80x87 if present, or uses ASMLIB's 80x87 emulation subroutines if no 80x87 is in the system. Registerd ASMLIB users with ASMLIB source code may eliminate the 80x87 emulation code by re-assembling with the NOEM conditional assembly directive. Returns: nothing Uses: nothing Example: extrn fprimef4:proc .data fx dd 2.2,0.0,3.5,2.0,0.0,5.1 ; the function y = 2.2+3.5*(x^2)+2*(x^3)+5.1*(x^5) .code ; program fragment assumes DS:@data . . . mov cx,5 ; fifth order polynomial lea si,fx ; point to f(x) coefficients (float4 values) call fprimef4 ; calculate derivative of the function °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° FVALUE: calculate the future value of a given present value and equal periodic payments Source: fvalue.asm (xtothey.asm) 80x87 required Call with: DS:[SI] pointing to an ASMLIB Financial data structure (see FINDATA.INC). The pv, n, i, and pmt data must be current before calling fvalue. Returns: updates fv in FINDATA data structure; future value also returned in ST(0) Uses: 80x87 stack Evample: include asm.inc include findata.inc extrn fvalue:proc .data case1 findata <12,.0525,100.0,10.0,> ; n = 12 periods ; i = .0525 (5.25% interest rate per n) ; present value = 100 ; 10 = payment per n period .code ; program fragment assumes DS:@data . . . lea si,case1 call fvalue ; calculate future value; update ; fv in case1 °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° LINEFITF4: fit a line equation to a series of float4 data points LINEFITF8: fit a line equation to a series of float8 data points LINEFITI2: fit a line equation to a series of i2 data points LINEFITI4: fit a line equation to a series of i4 data points Source: linefit.asm 80x87 required LineFit subroutines use the Least Squares method to calculate the a and b coefficients of the equation y = a + bx which best fits the given data points. See also CubeFit and QuadFit. The data series at DS:[BX] consists of n sets of x and y coordinates. Call with: DS:[BX] pointing to data series CX = number of (x,y) points Returns: ST(0) = a ST(1) = b ST(2) = äx ST(3) = äxx ST(4) = äy ST(5) = äxy Uses: entire 80x87 stack Example: extrn linefiti2:proc .data points dw 1,5 ; first (x,y) coordinate pair dw 3,12 ; x1 = 3, y1 = 12 dw 7,24 ; x2 = 7, y2 = 24 dw 5,17 ; x3 = 5, y3 = 17 dw 10,33 ; x4 = 10, y4 = 33 n equ ($-points) shr 2 ; number of coordinate pairs (5 in this case) .code ; assumes DS:@data . . . lea bx,points ; point to data series mov cx,n ; 5 data points call linefiti2 ; returns a in ST(0) and b in ST(1) °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° NORMF4, NORMF4b: normalize a float4 array Source: small & medium: normf4.asm (maxf4.asm) huge: normf4.asm (maxf4.asm, lowDS2hi.asm) NORMF8, NORMF8b: normalize a float8 array Source: small & medium: normf8.asm (maxf8.asm) huge: normf8.asm (maxf8.asm, lowDS2hi.asm) 80x87 required Call with: ES:[DI] pointing to the numeric array CX = number of values in the array ST(0) = number to normalize the array to normf?b: BX = bytes between data points normf4 assumes BX = 4, norm f8 assumes BX = 8 NormF4 and NormF8 assume that the maximum value of the data is greater than zero. I have used these subroutines to scale data upward or downward, for example, to convert from raw data to percent-of-maximum data. Returns: ST(0) = scaling factor Uses: ST(0); ST(7) and ST(6) are pushed off the coprocessor stack Example: extrn normf4:proc .data hundred dw 100 ; convert all data to percent-of-peak .code . . . mov ax,f4seg ; segment where the values are stored mov es,ax mov di,f4ptr ; now ES:[DI] points to the data mov cx,1488 ; half-hourly data for a month fild hundred ; make the maximum value 100 call normf4 ; normalize the data °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° NPVALUE: calculate net present value of an uneven cash flow Source: npvalue.asm (xtothey.asm) 80x87 required Call with: DS:[SI] pointing to ASMLIB's FINDATA data structure ES:[BX] pointing to float4 cash flow data n, i, and fv in FINDATA must be current before calling NPValue, and there must be at least n cash flows Returns: updates pv in FINDATA ST(0) = present value Uses: 80x87 stack Example: include asm.inc include findata.inc extrn npvalue:proc .data case1 findata <30,.105,,,0.0> ; 30 payments, 10.5% interest, fv = 0.0 payments dd 10 dup (80.0) ; need 30 payments for this example dd 10 dup (95.0) dd 10 dup (103.0) .code ; program fragment assumes DS:@data . . . push ds pop es ; ES = DS assume es:@data lea bx,payments lea si,case1 call npvalue °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° PSOLVEF4: solve a polynomial equation for y, given x; float4 equation coefficients Source: psolvef4.asm PSOLVEF8: solve a polynomial equation for y, given x; float8 equation coefficients Source: psolvef8.asm PSOLVEI2: solve a polynomial equation for y, given x; 2-byte integer equation coefficients Source: psolvei2.asm PSOLVEI4: solve a polynomial equation for y, given x; 4-byte integer equation coefficients Source: psolvei4.asm 80x87 required for all psolve subroutines Call with: DS:[SI] pointing to equation coefficients CX = n (order of the equation, i. e., a quadratic equation is a second-order polynomial, so CX = 2) ST(0) = x value Returns: ST(0) = y value Uses: most coprocessor registers Example: ; I want to calculate y for the equation ; y = 12 + 2x + 17(x**2) + 4(x**3) extrn psolvei2:proc .data fx dw 12,2,17,4 n equ 3 ; third-order equation x dd 0.85 .code ; program fragment assumes DS:@data . . . lea si,fx ; DS:[SI] points to equation coefficients mov cx,n ; a third-order polynomial fld x ; find y given x call psolvei2 ; returns y in register ST(0) °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° PVALUE: calculate the present value of an even cash flow Source: pvalue.asm (xtothey.asm) 80x87 required Call with: DS:[SI] pointing to FINDATA data structure n, i, pmt and fv must be updated before calling pvalue. Returns: updates pv in FINDATA data structure ST(0) = present value Uses: 80x87 stack Example: include asm.inc include findata.inc extrn pvalue:proc .data case1 findata <12,.0525,,10.0,0.0> ; n = 12 periods ; i = .0525 (5.25% interest rate per n) ; present value unknown ; payment per n period = 10 ; future value = 0 .code ; program fragment assumes DS:@data . . . lea si,case1 call pvalue ; calculate present value; update ; pv in case1 °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° QUADFITF4: fit a quadratic equation to a series of float4 data points QUADFITF8: fit a quadratic equation to a series of float8 data points QUADFITI2: fit a quadratic equation to a series of i2 data points QUADFITI4: fit a quadratic equation to a series of i4 data points Source: quadfit.asm 80x87 required QuadFit subroutines use the Least Squares method to calculate the a, b and c coefficients of the equation y = a + bx + c(x^2) which best fits the given data points. See also CubeFit and LineFit. The data series at DS:[BX] consists of n sets of x and y coordinates. Call with: DS:[BX] pointing to data series CX = number of (x,y) points Returns: ST(0) = a ST(1) = b ST(2) = c Uses: entire 80x87 stack Example: extrn quadfiti2:proc .data points dw 1,6 ; first (x,y) coordinate pair: x0 = 1, y0 = 6 dw 2,17 ; x1 = 2, y1 = 17 dw 5,86 ; x2 = 5, y2 = 86 dw 4,57 ; x3 = 4, y3 = 57 dw 3,34 ; x4 = 3, y4 = 34 n equ ($-points) shr 2 ; number of coordinate pairs (5 in this case) .code ; assumes DS:@data . . . lea bx,points ; point to data series mov cx,n ; 5 data points call quadfiti2 ; returns a in ST(0), b in ST(1) and c in ST(2) °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° RAD2DEG: convert radians to degrees of arc Source: rad2deg.asm 80x87 required Call with: ST(0) = radians Returns: ST(0) = degrees of arc Uses: 80x87 stack - ST(6) and ST(7) are lost Example: include asm.inc extrn rad2deg:proc .data rad dd 3.14159 ; dumb example - everyone knows this is 180 degrees .code ; program fragment assumes DS:@data . . . fld rad ; load radians into ST(0) call rad2deg ; it comes back with ST(0) = degrees °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° SAMP2POP: convert sample standard deviation to population standard deviation; used with StdDev subroutines. Source: samp2pop.asm 80x87 required Call with: ST(0) = sample standard deviation CX = n (number of data points) Returns: ST(0) = population standard deviation Uses: ST(0); ST(7), ST(6) and ST(5) are lost Example: see StdDev series subroutines °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° STDDEVF4: calculate standard deviation of a float4 data series STDDEVF8: calculate standard deviation of a float8 data series STDDEVI2: calculate standard deviation of an i2 data series STDDEVI4: calculate standard deviation of an i4 data series Source: small & medium: stddev.asm huge: stddev.asm (lowDS2hi.asm) 80x87 required Call with: ES:[DI] pointing to data series CX = number of values Note that integer values are signed integers Returns: if CF = 1, CX = 0 if CF = 0, ST(0) = standard deviation The value returned by StdDev subroutines is the sample standard deviation S; population standard deviation SP is calculated from sample standard deviation with this formula: SP = S * SQRT((n - 1) / n) Uses: CF, coprocessor registers Example: extrn stddevf4:proc ; my data series is in float4 format extrn samp2pop:proc ; I want the result as a ; population standard deviation .code . . . ; the program has established a series of float4 values, and I need the ; standard deviation of the series mov es,series_segment mov bx,series_offset mov cx,1600 ; a whole bunch of data call stddevf4 ; ST(0) = sample standard deviation ; the standard deviation returned by StdDev subroutines is the sample ; standard deviation. Use samp2pop to convert to population standard ; deviation call samp2pop ; ST(0) = population standard deviation °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° XTOTHEY: calculates x to the y power (x^y) Source: xtothey.asm 80x87 required Call with: ST(0) = x, ST(1) = y Returns: ST(0) = x^y, coprocessor stack popped Uses: coprocessor stack Example: extrn xtothey:proc .data x dd 17.4 y dd .3 .code mov ax,@data ; make the x & y data available mov ds,ax ; normally you would not need to do this assume ds:@data ; after the startup code unless the program ; has messed with DS . . . fld y ; ST(0) = exponent fld x ; ST(0) = x, ST(1) = exponent call xtothey ; calculate x**y