Annotation of 43BSDReno/contrib/emacs-18.55/lisp/float.el, revision 1.1.1.1

1.1       root        1: ;; Copyright (C) 1986 Free Software Foundation, Inc.
                      2: ;; Author Bill Rosenblatt
                      3: 
                      4: ;; This file is part of GNU Emacs.
                      5: 
                      6: ;; GNU Emacs is distributed in the hope that it will be useful,
                      7: ;; but WITHOUT ANY WARRANTY.  No author or distributor
                      8: ;; accepts responsibility to anyone for the consequences of using it
                      9: ;; or for whether it serves any particular purpose or works at all,
                     10: ;; unless he says so in writing.  Refer to the GNU Emacs General Public
                     11: ;; License for full details.
                     12: 
                     13: ;; Everyone is granted permission to copy, modify and redistribute
                     14: ;; GNU Emacs, but only under the conditions described in the
                     15: ;; GNU Emacs General Public License.   A copy of this license is
                     16: ;; supposed to have been given to you along with GNU Emacs so you
                     17: ;; can know your rights and responsibilities.  It should be in a
                     18: ;; file named COPYING.  Among other things, the copyright notice
                     19: ;; and this notice must be preserved on all copies.
                     20: 
                     21: ;; Floating point arithmetic package.
                     22: ;;
                     23: ;; Floating point numbers are represented by dot-pairs (mant . exp)
                     24: ;; where mant is the 24-bit signed integral mantissa and exp is the
                     25: ;; base 2 exponent.
                     26: ;;
                     27: ;; Emacs LISP supports a 24-bit signed integer data type, which has a
                     28: ;; range of -(2**23) to +(2**23)-1, or -8388608 to 8388607 decimal.
                     29: ;; This gives six significant decimal digit accuracy.  Exponents can
                     30: ;; be anything in the range -(2**23) to +(2**23)-1.
                     31: ;;
                     32: ;; User interface:
                     33: ;; function f converts from integer to floating point
                     34: ;; function string-to-float converts from string to floating point
                     35: ;; function fint converts a floating point to integer (with truncation)
                     36: ;; function float-to-string converts from floating point to string
                     37: ;;                   
                     38: ;; Caveats:
                     39: ;; -  Exponents outside of the range of +/-100 or so will cause certain 
                     40: ;;    functions (especially conversion routines) to take forever.
                     41: ;; -  Very little checking is done for fixed point overflow/underflow.
                     42: ;; -  No checking is done for over/underflow of the exponent
                     43: ;;    (hardly necessary when exponent can be 2**23).
                     44: ;; 
                     45: ;;
                     46: ;; Bill Rosenblatt
                     47: ;; June 20, 1986
                     48: ;;
                     49: 
                     50: ;; fundamental implementation constants
                     51: (defconst exp-base 2
                     52:   "Base of exponent in this floating point representation.")
                     53: 
                     54: (defconst mantissa-bits 24
                     55:   "Number of significant bits in this floating point representation.")
                     56: 
                     57: (defconst decimal-digits 6
                     58:   "Number of decimal digits expected to be accurate.")
                     59: 
                     60: (defconst expt-digits 2
                     61:   "Maximum permitted digits in a scientific notation exponent.")
                     62: 
                     63: ;; other constants
                     64: (defconst maxbit (1- mantissa-bits)
                     65:   "Number of highest bit")
                     66: 
                     67: (defconst mantissa-maxval (1- (ash 1 maxbit))
                     68:   "Maximum permissable value of mantissa")
                     69: 
                     70: (defconst mantissa-minval (ash 1 maxbit)
                     71:   "Minimum permissable value of mantissa")
                     72: 
                     73: (defconst floating-point-regexp
                     74:   "^[ \t]*\\(-?\\)\\([0-9]*\\)\
                     75: \\(\\.\\([0-9]*\\)\\|\\)\
                     76: \\(\\(\\([Ee]\\)\\(-?\\)\\([0-9][0-9]*\\)\\)\\|\\)[ \t]*$"
                     77:   "Regular expression to match floating point numbers.  Extract matches:
                     78: 1 - minus sign
                     79: 2 - integer part
                     80: 4 - fractional part
                     81: 8 - minus sign for power of ten
                     82: 9 - power of ten
                     83: ")
                     84: 
                     85: (defconst high-bit-mask (ash 1 maxbit)
                     86:   "Masks all bits except the high-order (sign) bit.")
                     87: 
                     88: (defconst second-bit-mask (ash 1 (1- maxbit))
                     89:   "Masks all bits except the highest-order magnitude bit")
                     90: 
                     91: ;; various useful floating point constants
                     92: (setq _f0 '(0 . 1))
                     93: 
                     94: (setq _f1/2 '(4194304 . -23))
                     95: 
                     96: (setq _f1 '(4194304 . -22))
                     97: 
                     98: (setq _f10 '(5242880 . -19))
                     99: 
                    100: ;; support for decimal conversion routines
                    101: (setq powers-of-10 (make-vector (1+ decimal-digits) _f1))
                    102: (aset powers-of-10 1 _f10)
                    103: (aset powers-of-10 2 '(6553600 . -16))
                    104: (aset powers-of-10 3 '(8192000 . -13))
                    105: (aset powers-of-10 4 '(5120000 . -9))
                    106: (aset powers-of-10 5 '(6400000 . -6))
                    107: (aset powers-of-10 6 '(8000000 . -3))
                    108: 
                    109: (setq all-decimal-digs-minval (aref powers-of-10 (1- decimal-digits))
                    110:       highest-power-of-10 (aref powers-of-10 decimal-digits))
                    111: 
                    112: (defun fashl (fnum)                    ; floating-point arithmetic shift left
                    113:   (cons (ash (car fnum) 1) (1- (cdr fnum))))
                    114: 
                    115: (defun fashr (fnum)                    ; floating point arithmetic shift right
                    116:   (cons (ash (car fnum) -1) (1+ (cdr fnum))))
                    117: 
                    118: (defun normalize (fnum)
                    119:   (if (> (car fnum) 0)                 ; make sure next-to-highest bit is set
                    120:       (while (zerop (logand (car fnum) second-bit-mask))
                    121:        (setq fnum (fashl fnum)))
                    122:     (if (< (car fnum) 0)               ; make sure highest bit is set
                    123:        (while (zerop (logand (car fnum) high-bit-mask))
                    124:          (setq fnum (fashl fnum)))
                    125:       (setq fnum _f0)))                        ; "standard 0"
                    126:   fnum)
                    127:       
                    128: (defun abs (n)                         ; integer absolute value
                    129:   (if (natnump n) n (- n)))
                    130: 
                    131: (defun fabs (fnum)                     ; re-normalize after taking abs value
                    132:   (normalize (cons (abs (car fnum)) (cdr fnum))))
                    133: 
                    134: (defun xor (a b)                       ; logical exclusive or
                    135:   (and (or a b) (not (and a b))))
                    136: 
                    137: (defun same-sign (a b)                 ; two f-p numbers have same sign?
                    138:   (not (xor (natnump (car a)) (natnump (car b)))))
                    139: 
                    140: (defun extract-match (str i)           ; used after string-match
                    141:   (condition-case ()
                    142:       (substring str (match-beginning i) (match-end i))
                    143:     (error "")))
                    144: 
                    145: ;; support for the multiplication function
                    146: (setq halfword-bits (/ mantissa-bits 2)        ; bits in a halfword
                    147:       masklo (1- (ash 1 halfword-bits)) ; isolate the lower halfword
                    148:       maskhi (lognot masklo)           ; isolate the upper halfword
                    149:       round-limit (ash 1 (/ halfword-bits 2)))
                    150: 
                    151: (defun hihalf (n)                      ; return high halfword, shifted down
                    152:   (ash (logand n maskhi) (- halfword-bits)))
                    153: 
                    154: (defun lohalf (n)                      ; return low halfword
                    155:   (logand n masklo))
                    156: 
                    157: ;; Visible functions
                    158: 
                    159: ;; Arithmetic functions
                    160: (defun f+ (a1 a2)
                    161:   "Returns the sum of two floating point numbers."
                    162:   (let ((f1 (fmax a1 a2))
                    163:        (f2 (fmin a1 a2)))
                    164:     (if (same-sign a1 a2)
                    165:        (setq f1 (fashr f1)             ; shift right to avoid overflow
                    166:              f2 (fashr f2)))
                    167:     (normalize
                    168:      (cons (+ (car f1) (ash (car f2) (- (cdr f2) (cdr f1))))
                    169:           (cdr f1)))))
                    170: 
                    171: (defun f- (a1 &optional a2)            ; unary or binary minus
                    172:   "Returns the difference of two floating point numbers."
                    173:   (if a2
                    174:       (f+ a1 (f- a2))
                    175:     (normalize (cons (- (car a1)) (cdr a1)))))
                    176: 
                    177: (defun f* (a1 a2)                      ; multiply in halfword chunks
                    178:   "Returns the product of two floating point numbers."
                    179:   (let* ((i1 (car (fabs a1)))
                    180:         (i2 (car (fabs a2)))
                    181:         (sign (not (same-sign a1 a2)))
                    182:         (prodlo (+ (hihalf (* (lohalf i1) (lohalf i2)))
                    183:                    (lohalf (* (hihalf i1) (lohalf i2)))
                    184:                    (lohalf (* (lohalf i1) (hihalf i2)))))
                    185:         (prodhi (+ (* (hihalf i1) (hihalf i2))
                    186:                    (hihalf (* (hihalf i1) (lohalf i2)))
                    187:                    (hihalf (* (lohalf i1) (hihalf i2)))
                    188:                    (hihalf prodlo))))
                    189:     (if (> (lohalf prodlo) round-limit)
                    190:        (setq prodhi (1+ prodhi)))      ; round off truncated bits
                    191:     (normalize
                    192:      (cons (if sign (- prodhi) prodhi)
                    193:           (+ (cdr (fabs a1)) (cdr (fabs a2)) mantissa-bits)))))
                    194: 
                    195: (defun f/ (a1 a2)                      ; SLOW subtract-and-shift algorithm
                    196:   "Returns the quotient of two floating point numbers."
                    197:   (if (zerop (car a2))                 ; if divide by 0
                    198:       (signal 'arith-error (list "attempt to divide by zero" a1 a2))
                    199:     (let ((bits (1- maxbit))
                    200:          (quotient 0) 
                    201:          (dividend (car (fabs a1)))
                    202:          (divisor (car (fabs a2)))
                    203:          (sign (not (same-sign a1 a2))))
                    204:       (while (natnump bits)
                    205:        (if (< (- dividend divisor) 0)
                    206:            (setq quotient (ash quotient 1))
                    207:          (setq quotient (1+ (ash quotient 1))
                    208:                dividend (- dividend divisor)))
                    209:        (setq dividend (ash dividend 1)
                    210:              bits (1- bits)))
                    211:       (normalize
                    212:        (cons (if sign (- quotient) quotient)
                    213:             (- (cdr (fabs a1)) (cdr (fabs a2)) (1- maxbit)))))))
                    214:   
                    215: (defun f% (a1 a2)
                    216:   "Returns the remainder of first floating point number divided by second."
                    217:   (f- a1 (f* (ftrunc (f/ a1 a2)) a2)))
                    218:          
                    219: 
                    220: ;; Comparison functions
                    221: (defun f= (a1 a2)
                    222:   "Returns t if two floating point numbers are equal, nil otherwise."
                    223:   (equal a1 a2))
                    224: 
                    225: (defun f> (a1 a2)
                    226:   "Returns t if first floating point number is greater than second,
                    227: nil otherwise."
                    228:   (cond ((and (natnump (car a1)) (< (car a2) 0)) 
                    229:         t)                             ; a1 nonnegative, a2 negative
                    230:        ((and (> (car a1) 0) (<= (car a2) 0))
                    231:         t)                             ; a1 positive, a2 nonpositive
                    232:        ((and (<= (car a1) 0) (natnump (car a2)))
                    233:         nil)                           ; a1 nonpos, a2 nonneg
                    234:        ((/= (cdr a1) (cdr a2))         ; same signs.  exponents differ
                    235:         (> (cdr a1) (cdr a2)))         ; compare the mantissas.
                    236:        (t
                    237:         (> (car a1) (car a2)))))       ; same exponents.
                    238: 
                    239: (defun f>= (a1 a2)
                    240:   "Returns t if first floating point number is greater than or equal to 
                    241: second, nil otherwise."
                    242:   (or (f> a1 a2) (f= a1 a2)))
                    243: 
                    244: (defun f< (a1 a2)
                    245:   "Returns t if first floating point number is less than second,
                    246: nil otherwise."
                    247:   (not (f>= a1 a2)))
                    248: 
                    249: (defun f<= (a1 a2)
                    250:   "Returns t if first floating point number is less than or equal to
                    251: second, nil otherwise."
                    252:   (not (f> a1 a2)))
                    253: 
                    254: (defun f/= (a1 a2)
                    255:   "Returns t if first floating point number is not equal to second,
                    256: nil otherwise."
                    257:   (not (f= a1 a2)))
                    258: 
                    259: (defun fmin (a1 a2)
                    260:   "Returns the minimum of two floating point numbers."
                    261:   (if (f< a1 a2) a1 a2))
                    262: 
                    263: (defun fmax (a1 a2)
                    264:   "Returns the maximum of two floating point numbers."
                    265:   (if (f> a1 a2) a1 a2))
                    266:       
                    267: (defun fzerop (fnum)
                    268:   "Returns t if the floating point number is zero, nil otherwise."
                    269:   (= (car fnum) 0))
                    270: 
                    271: (defun floatp (fnum)
                    272:   "Returns t if the arg is a floating point number, nil otherwise."
                    273:   (and (consp fnum) (integerp (car fnum)) (integerp (cdr fnum))))
                    274: 
                    275: ;; Conversion routines
                    276: (defun f (int)
                    277:   "Convert the integer argument to floating point, like a C cast operator."
                    278:   (normalize (cons int '0)))
                    279: 
                    280: (defun int-to-hex-string (int)
                    281:   "Convert the integer argument to a C-style hexadecimal string."
                    282:   (let ((shiftval -20)
                    283:        (str "0x")
                    284:        (hex-chars "0123456789ABCDEF"))
                    285:     (while (<= shiftval 0)
                    286:       (setq str (concat str (char-to-string 
                    287:                        (aref hex-chars
                    288:                              (logand (lsh int shiftval) 15))))
                    289:            shiftval (+ shiftval 4)))
                    290:     str))
                    291: 
                    292: (defun ftrunc (fnum)                   ; truncate fractional part
                    293:   "Truncate the fractional part of a floating point number."
                    294:   (cond ((natnump (cdr fnum))          ; it's all integer, return number as is
                    295:         fnum)
                    296:        ((<= (cdr fnum) (- maxbit))     ; it's all fractional, return 0
                    297:         '(0 . 1))
                    298:        (t                              ; otherwise mask out fractional bits
                    299:         (let ((mant (car fnum)) (exp (cdr fnum)))
                    300:           (normalize 
                    301:            (cons (if (natnump mant)    ; if negative, use absolute value
                    302:                      (ash (ash mant exp) (- exp))
                    303:                    (- (ash (ash (- mant) exp) (- exp))))
                    304:                  exp))))))
                    305: 
                    306: (defun fint (fnum)                     ; truncate and convert to integer
                    307:   "Convert the floating point number to integer, with truncation, 
                    308: like a C cast operator."
                    309:   (let* ((tf (ftrunc fnum)) (tint (car tf)) (texp (cdr tf)))
                    310:     (cond ((>= texp mantissa-bits)     ; too high, return "maxint"
                    311:           mantissa-maxval)
                    312:          ((<= texp (- mantissa-bits))  ; too low, return "minint"
                    313:           mantissa-minval)
                    314:          (t                            ; in range
                    315:           (ash tint texp)))))          ; shift so that exponent is 0
                    316: 
                    317: (defun float-to-string (fnum &optional sci)
                    318:   "Convert the floating point number to a decimal string.
                    319: Optional second argument non-nil means use scientific notation."
                    320:   (let* ((value (fabs fnum)) (sign (< (car fnum) 0))
                    321:         (power 0) (result 0) (str "") 
                    322:         (temp 0) (pow10 _f1))
                    323: 
                    324:     (if (f= fnum _f0)
                    325:        "0"
                    326:       (if (f>= value _f1)                      ; find largest power of 10 <= value
                    327:          (progn                                ; value >= 1, power is positive
                    328:            (while (f<= (setq temp (f* pow10 highest-power-of-10)) value)
                    329:              (setq pow10 temp
                    330:                    power (+ power decimal-digits)))
                    331:            (while (f<= (setq temp (f* pow10 _f10)) value)
                    332:              (setq pow10 temp
                    333:                    power (1+ power))))
                    334:        (progn                          ; value < 1, power is negative
                    335:          (while (f> (setq temp (f/ pow10 highest-power-of-10)) value)
                    336:            (setq pow10 temp
                    337:                  power (- power decimal-digits)))
                    338:          (while (f> pow10 value)
                    339:            (setq pow10 (f/ pow10 _f10)
                    340:                  power (1- power)))))
                    341:                                          ; get value in range 100000 to 999999
                    342:       (setq value (f* (f/ value pow10) all-decimal-digs-minval)
                    343:            result (ftrunc value))
                    344:       (if (f> (f- value result) _f1/2) ; round up if remainder > 0.5
                    345:          (setq str (int-to-string (1+ (fint result))))
                    346:        (setq str (int-to-string (fint result))))
                    347: 
                    348:       (if sci                          ; scientific notation
                    349:          (setq str (concat (substring str 0 1) "." (substring str 1)
                    350:                            "E" (int-to-string power)))
                    351: 
                    352:                                          ; regular decimal string
                    353:        (cond ((>= power (1- decimal-digits))
                    354:                                          ; large power, append zeroes
                    355:               (let ((zeroes (- power decimal-digits)))
                    356:                 (while (natnump zeroes)
                    357:                   (setq str (concat str "0")
                    358:                         zeroes (1- zeroes)))))
                    359: 
                    360:                                          ; negative power, prepend decimal
                    361:              ((< power 0)              ; point and zeroes
                    362:               (let ((zeroes (- (- power) 2)))
                    363:                 (while (natnump zeroes)
                    364:                   (setq str (concat "0" str)
                    365:                         zeroes (1- zeroes)))
                    366:                 (setq str (concat "0." str))))
                    367: 
                    368:              (t                                ; in range, insert decimal point
                    369:               (setq str (concat
                    370:                          (substring str 0 (1+ power))
                    371:                          "."
                    372:                          (substring str (1+ power)))))))
                    373: 
                    374:       (if sign                         ; if negative, prepend minus sign
                    375:          (concat "-" str)
                    376:        str))))
                    377: 
                    378:     
                    379: ;; string to float conversion.
                    380: ;; accepts scientific notation, but ignores anything after the first two
                    381: ;; digits of the exponent.
                    382: (defun string-to-float (str)
                    383:   "Convert the string to a floating point number.
                    384: Accepts a decimal string in scientific notation, 
                    385: with exponent preceded by either E or e.
                    386: Only the 6 most significant digits of the integer and fractional parts
                    387: are used; only the first two digits of the exponent are used.
                    388: Negative signs preceding both the decimal number and the exponent
                    389: are recognized."
                    390: 
                    391:   (if (string-match floating-point-regexp str 0)
                    392:       (let (power)
                    393:        (f*
                    394:         ; calculate the mantissa
                    395:         (let* ((int-subst (extract-match str 2))
                    396:                (fract-subst (extract-match str 4))
                    397:                (digit-string (concat int-subst fract-subst))
                    398:                (mant-sign (equal (extract-match str 1) "-"))
                    399:                (leading-0s 0) (round-up nil))
                    400: 
                    401:           ; get rid of leading 0's
                    402:           (setq power (- (length int-subst) decimal-digits))
                    403:           (while (and (< leading-0s (length digit-string))
                    404:                       (= (aref digit-string leading-0s) ?0))
                    405:             (setq leading-0s (1+ leading-0s)))
                    406:           (setq power (- power leading-0s)
                    407:                 digit-string (substring digit-string leading-0s))
                    408:           
                    409:           ; if more than 6 digits, round off
                    410:           (if (> (length digit-string) decimal-digits)
                    411:               (setq round-up (>= (aref digit-string decimal-digits) ?5)
                    412:                     digit-string (substring digit-string 0 decimal-digits))
                    413:             (setq power (+ power (- decimal-digits (length digit-string)))))
                    414: 
                    415:           ; round up and add minus sign, if necessary
                    416:           (f (* (+ (string-to-int digit-string)
                    417:                    (if round-up 1 0))
                    418:                 (if mant-sign -1 1))))
                    419:           
                    420:         ; calculate the exponent (power of ten)
                    421:         (let* ((expt-subst (extract-match str 9))
                    422:                (expt-sign (equal (extract-match str 8) "-"))
                    423:                (expt 0) (chunks 0) (tens 0) (exponent _f1)
                    424:                (func 'f*))
                    425:  
                    426:           (setq expt (+ (* (string-to-int
                    427:                             (substring expt-subst 0
                    428:                                        (min expt-digits (length expt-subst))))
                    429:                            (if expt-sign -1 1))
                    430:                         power))
                    431:           (if (< expt 0)               ; if power of 10 negative
                    432:               (setq expt (- expt)      ; take abs val of exponent
                    433:                     func 'f/))         ; and set up to divide, not multiply
                    434: 
                    435:           (setq chunks (/ expt decimal-digits)
                    436:                 tens (% expt decimal-digits))
                    437:           ; divide or multiply by "chunks" of 10**6
                    438:           (while (> chunks 0)  
                    439:             (setq exponent (funcall func exponent highest-power-of-10)
                    440:                   chunks (1- chunks)))
                    441:           ; divide or multiply by remaining power of ten
                    442:           (funcall func exponent (aref powers-of-10 tens)))))
                    443:                  
                    444:     _f0))                              ; if invalid, return 0
                    445: 
                    446: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.