home *** CD-ROM | disk | FTP | other *** search
-
- ; *******************************************************
- ; * *
- ; * Turbo Pascal Runtime Library Version 7.0 *
- ; * Real Logarithm *
- ; * *
- ; * Copyright (C) 1989-1993 Norbert Juffa *
- ; * *
- ; *******************************************************
-
- TITLE FPLOG
-
-
- 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