home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 2
/
ctrom_ii_b.zip
/
ctrom_ii_b
/
PROGRAM
/
PASCAL
/
TPL60N19
/
ARISOURC
/
F48FLOG.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-01-25
|
8KB
|
174 lines
; *******************************************************
; * *
; * Turbo Pascal Runtime Library Version 6.0 *
; * Real Logarithm *
; * *
; * Copyright (C) 1989-1992 Norbert Juffa *
; * *
; *******************************************************
TITLE F48FLOG
INCLUDE SE.ASM
CODE SEGMENT BYTE PUBLIC
ASSUME CS:CODE
; Externals
EXTRN RealAdd:NEAR,CmpMantissa:NEAR,RealFloat:NEAR,RealSub:NEAR
EXTRN RealDivRev:NEAR,RealMulNoChk:NEAR,RealPoly:NEAR
EXTRN HaltError:NEAR,ROverflow:NEAR,realmulfnochk:near
EXTRN ShortMulRev:NEAR
; Publics
PUBLIC RLn
IFDEF EXTENSIONS
PUBLIC RLog2,RLog10
ENDIF
;-------------------------------------------------------------------------------
; RLn computes the natural logarithm of its argument. It uses a polynomial
; approximation to compute the natural logarithm of the reduced argument z. The
; reduced argument satisfies the inequality |z| <= (sqrt(2)-1)^2. RLog10 and
; RLog2 are additional routines that compute the logarithms base two and ten,
; respectively. Both first execute RLn to compute the natural logarithm and
; then proceed to multiply the result with the appropriate constants to get
; Log10 and Log2. The following polynomial approximation is used to compute
; the natural logarithm:
;
; rz := ((((0.09790802001953*z^2 + 0.1108818338371)*z^2 + 0.1428605246897)*z^2
; 0.1999999783036)*z^2 + 0.3333333333786)*z^2 * z + z
;
; This approximation has a theoretical maximum relative error of 3.20e-14.
; Maximum observed error when evaluated in REAL arithmetic is 9.31e-13.
;
; If the argument is negative or zero, runtime error 207 is invoked through the
; error handler.
;
; INPUT: DX:BX:AX argument
;
; OUTPUT: DX:BX:AX ln, log10, log2 of argument depending on routine called
;
; DESTROYS: AX,BX,CX,DX,SI,DI,Flags
;-------------------------------------------------------------------------------
IFDEF EXTENSIONS
RLog10 PROC FAR
MOV DI,OFFSET $log_ten; push address of log10 tail-routine
JMPS $start_log ; compute common logarithm
RLog10 ENDP
ALIGN 4
RLog2 PROC FAR
MOV DI,OFFSET $log_two; push address of log2 tail-routine
JMPS $start_log ; compute logarithm dualis
RLog2 ENDP
ENDIF
ALIGN 4
RLn PROC FAR
MOV DI,OFFSET $log_end; push address of ln tail-routine
$start_log: OR DH, DH ; x negative ?
JS $range_err ; yes, error
OR AL, AL ; x zero ?
JZ $range_err ; yes, error
PUSH DI ; save log routine tail address
MOV CX, 0FA81h ; CL = exponent of constant a = 1,
MOV SI, 0F333h ; DI:SI:CH = mantissa
MOV DI, 03504h ; of 0.5*sqrt(2)
CALL CmpMantissa ; compare mantissas of x and 0.5*sqrt(2)
JNC $gt_root2 ; if mantissa x > mantissa 0.5*sqrt(2)
DEC CX ; exponent of constant a = 0.5
DEC AX ; exponent = exponent - 1
$gt_root2: PUSH AX ; save exponent of x
MOV AL, 80h ; x = mantissa of x
XOR CH, CH ; clear LSB of constant a
PUSH CX ; save exponent of constant a
XOR SI, SI ; real constant
MOV DI, SI ; a = 1 or a = 0.5
CALL RealSub ; x-a
POP CX ; get exponent of constant a
PUSH DX ; save
PUSH BX ; x-a
PUSH AX ; on stack
INC CX ; create
XOR SI, SI ; constant
MOV DI, SI ; 2a
CALL RealAdd ; compute (x-a) + 2a = x+a
POP CX ; get
POP SI ; back
POP DI ; x-a
CALL RealDivRev ; compute (x-a)/(x+a)
MOV CX, 5 ; polynomial has five coefficients
MOV DI,OFFSET LN_COEFF; pointer to first coefficient
XOR SI, SI ; polynomial of type P(x^2)*x+x
CALL RealPoly ; z+z*p(z^2), max. rel. err. 2.6e-12
ADD AL, 0FFh ; compute rz := 2 * (z + z * p(^2))
ADC AL, 1 ; except when result is zero
POP CX ; get exponent
PUSH DX ; save
PUSH BX ; rz on
PUSH AX ; stack
XCHG AX, CX ; AL = exponent
SUB AL, 80h ; compute n = exponent - $80
CBW ; convert n to word
CWD ; convert n to longint
CALL RealFloat ; compute float (n)
MOV CX, 0D280h ; load
MOV SI, 017F7h ; real constant
MOV DI, 03172h ; ln(2)
CALL ShortMulRev ; compute n*ln(2),max. rel. err. 1.12e-12
POP CX ; get
POP SI ; rz from
POP DI ; stack
JMP RealAdd ; compute rz + n * ln(2)
IFDEF NOOVERFLOW
$range_err: MOV CH, -1 ; result negativ
JMP ROverflow ; largest REAL number
ELSE
$range_err: MOV AX, 0CFh ; load error code 207
JMP HaltError ; execute error handler
ENDIF
IFDEF EXTENSIONS
$log_ten: MOV CX, 0377Fh ; load
MOV SI, 0D8A9h ; constant
MOV DI, 05E5Bh ; 1/ln(10)
JMPS $mult_const ; compute common log from natural log
$log_two: MOV CX, 05C81h ; load
MOV SI, 03B29h ; constant
MOV DI, 038AAh ; 1/ln(2)
$mult_const: CALL RealMulNoChk ; compute log dualis from natural log
ENDIF
ALIGN 4
$log_end: RET ; done
LN_COEFF DB 07Dh, 084h,048h ; 9.790802001953e-2
DB 07Dh,068h,0D0h,003h,016h,063h ; 1.108818338371e-1
DB 07Eh,0BAh,085h,007h,04Ah,012h ; 1.428605246897e-1
DB 07Eh,00Fh,058h,0CBh,0CCh,04Ch ; 1.999999783036e-1
DB 07Fh,00Eh,0ABh,0AAh,0AAh,02Ah ; 3.333333333786e-1
RLn ENDP
ALIGN 4
CODE ENDS
END