Add 2010 to copyright years.
[bpt/emacs.git] / lisp / calc / calc.el
index b291969..a3f95fc 100644 (file)
@@ -1,7 +1,7 @@
 ;;; calc.el --- the GNU Emacs calculator
 
-;; Copyright (C) 1990, 1991, 1992, 1993, 2001, 2002, 2003, 2004,
-;;   2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+;; Copyright (C) 1990, 1991, 1992, 1993, 2001, 2002, 2003, 2004, 2005,
+;;   2006, 2007, 2008, 2009, 2010  Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 ;; Maintainer: Jay Belanger <jay.p.belanger@gmail.com>
 (declare-function calcFunc-unixtime "calc-forms" (date &optional zone))
 (declare-function math-parse-date "calc-forms" (math-pd-str))
 (declare-function math-lessp "calc-ext" (a b))
+(declare-function math-compare "calc-ext" (a b))
 (declare-function calc-embedded-finish-command "calc-embed" ())
 (declare-function calc-embedded-select-buffer "calc-embed" ())
 (declare-function calc-embedded-mode-line-change "calc-embed" ())
 (declare-function calc-incomplete-error "calc-incom" (a))
 (declare-function math-float-fancy "calc-arith" (a))
 (declare-function math-neg-fancy "calc-arith" (a))
-(declare-function math-zerop "calc-misc" (a))
 (declare-function calc-add-fractions "calc-frac" (a b))
 (declare-function math-add-objects-fancy "calc-arith" (a b))
 (declare-function math-add-symb-fancy "calc-arith" (a b))
 (declare-function math-adjust-fraction "calc-ext" (a))
 (declare-function math-format-binary "calc-bin" (a))
 (declare-function math-format-radix "calc-bin" (a))
+(declare-function math-format-twos-complement "calc-bin" (a))
 (declare-function math-group-float "calc-ext" (str))
 (declare-function math-mod "calc-misc" (a b))
 (declare-function math-format-number-fancy "calc-ext" (a prec))
   :tag    "Calc"
   :group  'applications)
 
-;;;###autoload
+;; Do not autoload, so it is evaluated at run-time rather than at dump time.
+;; ;;;###autoload
 (defcustom calc-settings-file
-  (convert-standard-filename "~/.calc.el")
+  (locate-user-emacs-file "calc.el" ".calc.el")
   "File in which to record permanent settings."
   :group 'calc
   :type '(file))
@@ -688,6 +690,10 @@ If `sqmatrix', variables are assumed to be square matrices of an unspecified siz
 If `scalar', variables are assumed to be scalar-valued.
 If nil, symbolic math routines make no assumptions about variables.")
 
+(defcalcmodevar calc-twos-complement-mode nil
+  "If non-nil, display integers in two's complement mode.")
+
+
 (defcalcmodevar calc-shift-prefix nil
   "If non-nil, shifted letter keys are prefix keys rather than normal meanings.")
 
@@ -1042,25 +1048,13 @@ Used by `calc-user-invocation'.")
     map)
   "The key map for Calc.")
 
-
-
 (defvar calc-digit-map
   (let ((map (make-keymap)))
-    (if (featurep 'xemacs)
-        (map-keymap (function
-                     (lambda (keys bind)
-                       (define-key map keys
-                         (if (eq bind 'undefined)
-                             'undefined 'calcDigit-nondigit))))
-                    calc-mode-map)
-      (let ((cmap (nth 1 calc-mode-map))
-            (dmap (nth 1 map))
-            (i 0))
-        (while (< i 128)
-          (aset dmap i
-                (if (eq (aref cmap i) 'undefined)
-                    'undefined 'calcDigit-nondigit))
-          (setq i (1+ i)))))
+    (map-keymap (lambda (key bind)
+                  (define-key map (vector key)
+                    (if (eq bind 'undefined)
+                        'undefined 'calcDigit-nondigit)))
+                calc-mode-map)
     (mapc (lambda (x) (define-key map (char-to-string x) 'calcDigit-key))
           "_0123456789.e+-:n#@oh'\"mspM")
     (mapc (lambda (x) (define-key map (char-to-string x) 'calcDigit-letter))
@@ -1077,15 +1071,13 @@ Used by `calc-user-invocation'.")
              (define-key calc-digit-map x 'calcDigit-backspace)
              (define-key calc-mode-map x 'calc-pop)
              (define-key calc-mode-map
-                 (if (vectorp x)
-                     (if (featurep 'xemacs)
-                         (if (= (length x) 1)
-                             (vector (if (consp (aref x 0))
-                                         (cons 'meta (aref x 0))
-                                       (list 'meta (aref x 0))))
-                           "\e\C-d")
-                       (vconcat "\e" x))
-                   (concat "\e" x))
+                (if (and (vectorp x) (featurep 'xemacs))
+                    (if (= (length x) 1)
+                        (vector (if (consp (aref x 0))
+                                    (cons 'meta (aref x 0))
+                                  (list 'meta (aref x 0))))
+                      "\e\C-d")
+                  (vconcat "\e" x))
                'calc-pop-above))
          (error nil)))
       (if calc-scan-for-dels
@@ -1441,8 +1433,7 @@ commands given here will actually operate on the *Calculator* stack."
                       (set-window-buffer w (current-buffer))
                       (select-window w))
                   (pop-to-buffer (current-buffer)))))))
-       (save-excursion
-         (set-buffer (calc-trail-buffer))
+       (with-current-buffer (calc-trail-buffer)
          (and calc-display-trail
               (= (window-width) (frame-width))
               (calc-trail-display 1 t)))
@@ -1510,7 +1501,7 @@ commands given here will actually operate on the *Calculator* stack."
         ;; next time Calc is called, the window will be the same size
         ;; as the current window.
         (if (and win
-                 (< (window-height win) (1- (frame-height)))
+                (not (window-full-height-p win))
                  (window-full-width-p win) ; avoid calc-keypad
                  (not (get-buffer-window "*Calc Keypad*")))
             (setq calc-window-height (- (window-height win) 2)))
@@ -1615,11 +1606,13 @@ See calc-keypad for details."
       (and (memq 'position-point calc-command-flags)
           (if (eq major-mode 'calc-mode)
               (progn
-                (goto-line calc-final-point-line)
+                (goto-char (point-min))
+                (forward-line (1- calc-final-point-line))
                 (move-to-column calc-final-point-column))
             (save-current-buffer
               (calc-select-buffer)
-              (goto-line calc-final-point-line)
+              (goto-char (point-min))
+              (forward-line (1- calc-final-point-line))
               (move-to-column calc-final-point-column))))
       (unless (memq 'keep-flags calc-command-flags)
        (save-excursion
@@ -1717,6 +1710,7 @@ See calc-keypad for details."
                           ((= calc-number-radix 8) "Oct ")
                           ((= calc-number-radix 16) "Hex ")
                           (t (format "Radix%d " calc-number-radix)))
+                     (if calc-twos-complement-mode "TwosComp " "")
                     (if calc-leading-zeros "Zero " "")
                     (cond ((null calc-language) "")
                            ((get calc-language 'math-lang-name)
@@ -1991,8 +1985,7 @@ See calc-keypad for details."
           (goto-char save-point))
         (if save-mark (set-mark save-mark))))
   (and calc-embedded-info (not (eq major-mode 'calc-mode))
-       (save-excursion
-        (set-buffer (aref calc-embedded-info 1))
+       (with-current-buffer (aref calc-embedded-info 1)
         (calc-refresh align)))
   (setq calc-refresh-count (1+ calc-refresh-count)))
 
@@ -2017,9 +2010,9 @@ See calc-keypad for details."
               (calc-trail-mode buf)))))
   (or (and calc-trail-pointer
           (eq (marker-buffer calc-trail-pointer) calc-trail-buffer))
-      (save-excursion
-       (set-buffer calc-trail-buffer)
-       (goto-line 2)
+      (with-current-buffer calc-trail-buffer
+       (goto-char (point-min))
+       (forward-line 1)
        (setq calc-trail-pointer (point-marker))))
   calc-trail-buffer)
 
@@ -2036,8 +2029,7 @@ See calc-keypad for details."
                         (math-showing-full-precision
                          (math-format-flat-expr val 0)))
                     "")))
-       (save-excursion
-         (set-buffer buf)
+       (with-current-buffer buf
          (let ((aligned (calc-check-trail-aligned))
                (buffer-read-only nil))
            (goto-char (point-max))
@@ -2273,8 +2265,7 @@ See calc-keypad for details."
   (or (boundp 'calc-buffer)
       (use-local-map minibuffer-local-map))
   (let ((str (minibuffer-contents)))
-    (setq calc-digit-value (save-excursion
-                            (set-buffer calc-buffer)
+    (setq calc-digit-value (with-current-buffer calc-buffer
                             (math-read-number str))))
   (if (and (null calc-digit-value) (> (calc-minibuffer-size) 0))
       (progn
@@ -2366,7 +2357,7 @@ See calc-keypad for details."
          (insert "mod "))))
      (t
       (insert (char-to-string last-command-event))
-      (if (or (and (calc-minibuffer-contains "[-+]?\\(.*\\+/- *\\|.*mod *\\)?\\([0-9][0-9]?\\)#[0-9a-zA-Z]*\\(:[0-9a-zA-Z]*\\(:[0-9a-zA-Z]*\\)?\\|.[0-9a-zA-Z]*\\(e[-+]?[0-9]*\\)?\\)?\\'")
+      (if (or (and (calc-minibuffer-contains "[-+]?\\(.*\\+/- *\\|.*mod *\\)?\\([0-9][0-9]?\\)#[#]?[0-9a-zA-Z]*\\(:[0-9a-zA-Z]*\\(:[0-9a-zA-Z]*\\)?\\|.[0-9a-zA-Z]*\\(e[-+]?[0-9]*\\)?\\)?\\'")
                   (let ((radix (string-to-number
                                 (buffer-substring
                                  (match-beginning 2) (match-end 2)))))
@@ -2432,101 +2423,101 @@ largest Emacs integer.")
 
 
 ;;;; Arithmetic routines.
-;;;
-;;; An object as manipulated by one of these routines may take any of the
-;;; following forms:
-;;;
-;;; integer                 An integer.  For normalized numbers, this format
-;;;                        is used only for
-;;;                         negative math-small-integer-size + 1 to
-;;;                         math-small-integer-size - 1
-;;;
-;;; (bigpos N0 N1 N2 ...)   A big positive integer,
-;;;                           N0 + N1*math-bignum-digit-size
-;;;                              + N2*(math-bignum-digit-size)^2 ...
-;;; (bigneg N0 N1 N2 ...)   A big negative integer,
-;;;                           - N0 - N1*math-bignum-digit-size ...
-;;;                        Each digit N is in the range
-;;;                             0 ... math-bignum-digit-size -1.
-;;;                        Normalized, always at least three N present,
-;;;                        and the most significant N is nonzero.
-;;;
-;;; (frac NUM DEN)          A fraction.  NUM and DEN are small or big integers.
-;;;                         Normalized, DEN > 1.
-;;;
-;;; (float NUM EXP)         A floating-point number, NUM * 10^EXP;
-;;;                         NUM is a small or big integer, EXP is a small int.
-;;;                        Normalized, NUM is not a multiple of 10, and
-;;;                        abs(NUM) < 10^calc-internal-prec.
-;;;                        Normalized zero is stored as (float 0 0).
-;;;
-;;; (cplx REAL IMAG)        A complex number; REAL and IMAG are any of above.
-;;;                        Normalized, IMAG is nonzero.
-;;;
-;;; (polar R THETA)         Polar complex number.  Normalized, R > 0 and THETA
-;;;                         is neither zero nor 180 degrees (pi radians).
-;;;
-;;; (vec A B C ...)         Vector of objects A, B, C, ...  A matrix is a
-;;;                         vector of vectors.
-;;;
-;;; (hms H M S)             Angle in hours-minutes-seconds form.  All three
-;;;                         components have the same sign; H and M must be
-;;;                         numerically integers; M and S are expected to
-;;;                         lie in the range [0,60).
-;;;
-;;; (date N)                A date or date/time object.  N is an integer to
-;;;                        store a date only, or a fraction or float to
-;;;                        store a date and time.
-;;;
-;;; (sdev X SIGMA)          Error form, X +/- SIGMA.  When normalized,
-;;;                         SIGMA > 0.  X is any complex number and SIGMA
-;;;                        is real numbers; or these may be symbolic
-;;;                         expressions where SIGMA is assumed real.
-;;;
-;;; (intv MASK LO HI)       Interval form.  MASK is 0=(), 1=(], 2=[), or 3=[].
-;;;                         LO and HI are any real numbers, or symbolic
-;;;                        expressions which are assumed real, and LO < HI.
-;;;                        For [LO..HI], if LO = HI normalization produces LO,
-;;;                        and if LO > HI normalization produces [LO..LO).
-;;;                        For other intervals, if LO > HI normalization
-;;;                        sets HI equal to LO.
-;;;
-;;; (mod N M)              Number modulo M.  When normalized, 0 <= N < M.
-;;;                        N and M are real numbers.
-;;;
-;;; (var V S)              Symbolic variable.  V is a Lisp symbol which
-;;;                        represents the variable's visible name.  S is
-;;;                        the symbol which actually stores the variable's
-;;;                        value:  (var pi var-pi).
-;;;
-;;; In general, combining rational numbers in a calculation always produces
-;;; a rational result, but if either argument is a float, result is a float.
-
-;;; In the following comments, [x y z] means result is x, args must be y, z,
-;;; respectively, where the code letters are:
-;;;
-;;;    O  Normalized object (vector or number)
-;;;    V  Normalized vector
-;;;    N  Normalized number of any type
-;;;    N  Normalized complex number
-;;;    R  Normalized real number (float or rational)
-;;;    F  Normalized floating-point number
-;;;    T  Normalized rational number
-;;;    I  Normalized integer
-;;;    B  Normalized big integer
-;;;    S  Normalized small integer
-;;;    D  Digit (small integer, 0..999)
-;;;    L  Normalized bignum digit list (without "bigpos" or "bigneg" symbol)
-;;;       or normalized vector element list (without "vec")
-;;;    P  Predicate (truth value)
-;;;    X  Any Lisp object
-;;;    Z  "nil"
-;;;
-;;; Lower-case letters signify possibly un-normalized values.
-;;; "L.D" means a cons of an L and a D.
-;;; [N N; n n] means result will be normalized if argument is.
-;;; Also, [Public] marks routines intended to be called from outside.
-;;; [This notation has been neglected in many recent routines.]
+;;
+;; An object as manipulated by one of these routines may take any of the
+;; following forms:
+;;
+;; integer                 An integer.  For normalized numbers, this format
+;;                         is used only for
+;;                         negative math-small-integer-size + 1 to
+;;                         math-small-integer-size - 1
+;;
+;; (bigpos N0 N1 N2 ...)   A big positive integer,
+;;                           N0 + N1*math-bignum-digit-size
+;;                              + N2*(math-bignum-digit-size)^2 ...
+;; (bigneg N0 N1 N2 ...)   A big negative integer,
+;;                           - N0 - N1*math-bignum-digit-size ...
+;;                         Each digit N is in the range
+;;                             0 ... math-bignum-digit-size -1.
+;;                         Normalized, always at least three N present,
+;;                         and the most significant N is nonzero.
+;;
+;; (frac NUM DEN)          A fraction.  NUM and DEN are small or big integers.
+;;                         Normalized, DEN > 1.
+;;
+;; (float NUM EXP)         A floating-point number, NUM * 10^EXP;
+;;                         NUM is a small or big integer, EXP is a small int.
+;;                         Normalized, NUM is not a multiple of 10, and
+;;                         abs(NUM) < 10^calc-internal-prec.
+;;                         Normalized zero is stored as (float 0 0).
+;;
+;; (cplx REAL IMAG)        A complex number; REAL and IMAG are any of above.
+;;                         Normalized, IMAG is nonzero.
+;;
+;; (polar R THETA)         Polar complex number.  Normalized, R > 0 and THETA
+;;                         is neither zero nor 180 degrees (pi radians).
+;;
+;; (vec A B C ...)         Vector of objects A, B, C, ...  A matrix is a
+;;                         vector of vectors.
+;;
+;; (hms H M S)             Angle in hours-minutes-seconds form.  All three
+;;                         components have the same sign; H and M must be
+;;                         numerically integers; M and S are expected to
+;;                         lie in the range [0,60).
+;;
+;; (date N)                A date or date/time object.  N is an integer to
+;;                         store a date only, or a fraction or float to
+;;                         store a date and time.
+;;
+;; (sdev X SIGMA)          Error form, X +/- SIGMA.  When normalized,
+;;                         SIGMA > 0.  X is any complex number and SIGMA
+;;                         is real numbers; or these may be symbolic
+;;                         expressions where SIGMA is assumed real.
+;;
+;; (intv MASK LO HI)       Interval form.  MASK is 0=(), 1=(], 2=[), or 3=[].
+;;                         LO and HI are any real numbers, or symbolic
+;;                         expressions which are assumed real, and LO < HI.
+;;                         For [LO..HI], if LO = HI normalization produces LO,
+;;                         and if LO > HI normalization produces [LO..LO).
+;;                         For other intervals, if LO > HI normalization
+;;                         sets HI equal to LO.
+;;
+;; (mod N M)               Number modulo M.  When normalized, 0 <= N < M.
+;;                         N and M are real numbers.
+;;
+;; (var V S)               Symbolic variable.  V is a Lisp symbol which
+;;                         represents the variable's visible name.  S is
+;;                         the symbol which actually stores the variable's
+;;                         value:  (var pi var-pi).
+;;
+;; In general, combining rational numbers in a calculation always produces
+;; a rational result, but if either argument is a float, result is a float.
+
+;; In the following comments, [x y z] means result is x, args must be y, z,
+;; respectively, where the code letters are:
+;;
+;;    O  Normalized object (vector or number)
+;;    V  Normalized vector
+;;    N  Normalized number of any type
+;;    N  Normalized complex number
+;;    R  Normalized real number (float or rational)
+;;    F  Normalized floating-point number
+;;    T  Normalized rational number
+;;    I  Normalized integer
+;;    B  Normalized big integer
+;;    S  Normalized small integer
+;;    D  Digit (small integer, 0..999)
+;;    L  Normalized bignum digit list (without "bigpos" or "bigneg" symbol)
+;;       or normalized vector element list (without "vec")
+;;    P  Predicate (truth value)
+;;    X  Any Lisp object
+;;    Z  "nil"
+;;
+;; Lower-case letters signify possibly un-normalized values.
+;; "L.D" means a cons of an L and a D.
+;; [N N; n n] means result will be normalized if argument is.
+;; Also, [Public] marks routines intended to be called from outside.
+;; [This notation has been neglected in many recent routines.]
 
 (defvar math-eval-rules-cache)
 (defvar math-eval-rules-cache-other)
@@ -2658,7 +2649,7 @@ largest Emacs integer.")
 
 
 
-;;; True if A is a floating-point real or complex number.  [P x] [Public]
+;; True if A is a floating-point real or complex number.  [P x] [Public]
 (defun math-floatp (a)
   (cond ((eq (car-safe a) 'float) t)
        ((memq (car-safe a) '(cplx polar mod sdev intv))
@@ -2670,7 +2661,7 @@ largest Emacs integer.")
 
 
 
-;;; Verify that A is a complete object and return A.  [x x] [Public]
+;; Verify that A is a complete object and return A.  [x x] [Public]
 (defun math-check-complete (a)
   (cond ((integerp a) a)
        ((eq (car-safe a) 'incomplete)
@@ -2680,7 +2671,7 @@ largest Emacs integer.")
 
 
 
-;;; Coerce integer A to be a bignum.  [B S]
+;; Coerce integer A to be a bignum.  [B S]
 (defun math-bignum (a)
   (if (>= a 0)
       (cons 'bigpos (math-bignum-big a))
@@ -2693,7 +2684,7 @@ largest Emacs integer.")
           (math-bignum-big (/ a math-bignum-digit-size)))))
 
 
-;;; Build a normalized floating-point number.  [F I S]
+;; Build a normalized floating-point number.  [F I S]
 (defun math-make-float (mant exp)
   (if (eq mant 0)
       '(float 0 0)
@@ -3398,9 +3389,24 @@ largest Emacs integer.")
 
 
 ;;; Format a number as a string.
+(defvar math-half-2-word-size)
 (defun math-format-number (a &optional prec)   ; [X N]   [Public]
   (cond
    ((eq calc-display-raw t) (format "%s" a))
+   ((and calc-twos-complement-mode
+         math-radix-explicit-format
+         (Math-integerp a)
+         (or (eq a 0)
+             (and (Math-integer-posp a)
+                  (Math-lessp a math-half-2-word-size))
+             (and (Math-integer-negp a)
+                  (require 'calc-ext)
+                  (let ((comparison 
+                         (math-compare (Math-integer-neg a) math-half-2-word-size)))
+                    (or (= comparison 0)
+                        (= comparison -1))))))
+    (require 'calc-bin)
+    (math-format-twos-complement a))
    ((and (nth 1 calc-frac-format) (Math-integerp a))
     (require 'calc-ext)
     (math-format-number (math-adjust-fraction a)))
@@ -3537,88 +3543,90 @@ largest Emacs integer.")
 (defun math-read-number (s &optional decimal)
   "Convert the string S into a Calc number."
   (math-normalize
-   (cond
-
-    ;; Integers (most common case)
-    ((string-match "\\` *\\([0-9]+\\) *\\'" s)
-     (let ((digs (math-match-substring s 1)))
-       (if (and (memq calc-language calc-lang-c-type-hex)
-               (> (length digs) 1)
-               (eq (aref digs 0) ?0)
-                (null decimal))
-          (math-read-number (concat "8#" digs))
-        (if (<= (length digs) (* 2 math-bignum-digit-length))
-            (string-to-number digs)
-          (cons 'bigpos (math-read-bignum digs))))))
-
-    ;; Clean up the string if necessary
-    ((string-match "\\`\\(.*\\)[ \t\n]+\\([^\001]*\\)\\'" s)
-     (math-read-number (concat (math-match-substring s 1)
-                              (math-match-substring s 2))))
-
-    ;; Plus and minus signs
-    ((string-match "^[-_+]\\(.*\\)$" s)
-     (let ((val (math-read-number (math-match-substring s 1))))
-       (and val (if (eq (aref s 0) ?+) val (math-neg val)))))
-
-    ;; Forms that require extensions module
-    ((string-match "[^-+0-9eE.]" s)
-     (require 'calc-ext)
-     (math-read-number-fancy s))
-
-    ;; Decimal point
-    ((string-match "^\\([0-9]*\\)\\.\\([0-9]*\\)$" s)
-     (let ((int (math-match-substring s 1))
-          (frac (math-match-substring s 2)))
-       (let ((ilen (length int))
-            (flen (length frac)))
-        (let ((int (if (> ilen 0) (math-read-number int t) 0))
-              (frac (if (> flen 0) (math-read-number frac t) 0)))
-          (and int frac (or (> ilen 0) (> flen 0))
-               (list 'float
-                     (math-add (math-scale-int int flen) frac)
-                     (- flen)))))))
-
-    ;; "e" notation
-    ((string-match "^\\(.*\\)[eE]\\([-+]?[0-9]+\\)$" s)
-     (let ((mant (math-match-substring s 1))
-          (exp (math-match-substring s 2)))
-       (let ((mant (if (> (length mant) 0) (math-read-number mant t) 1))
-            (exp (if (<= (length exp) (if (memq (aref exp 0) '(?+ ?-)) 8 7))
-                     (string-to-number exp))))
-        (and mant exp (Math-realp mant) (> exp -4000000) (< exp 4000000)
-             (let ((mant (math-float mant)))
-               (list 'float (nth 1 mant) (+ (nth 2 mant) exp)))))))
-
-    ;; Syntax error!
-    (t nil))))
+   (save-match-data
+     (cond
+      
+      ;; Integers (most common case)
+      ((string-match "\\` *\\([0-9]+\\) *\\'" s)
+       (let ((digs (math-match-substring s 1)))
+         (if (and (memq calc-language calc-lang-c-type-hex)
+                  (> (length digs) 1)
+                  (eq (aref digs 0) ?0)
+                  (null decimal))
+             (math-read-number (concat "8#" digs))
+           (if (<= (length digs) (* 2 math-bignum-digit-length))
+               (string-to-number digs)
+             (cons 'bigpos (math-read-bignum digs))))))
+      
+      ;; Clean up the string if necessary
+      ((string-match "\\`\\(.*\\)[ \t\n]+\\([^\001]*\\)\\'" s)
+       (math-read-number (concat (math-match-substring s 1)
+                                 (math-match-substring s 2))))
+      
+      ;; Plus and minus signs
+      ((string-match "^[-_+]\\(.*\\)$" s)
+       (let ((val (math-read-number (math-match-substring s 1))))
+         (and val (if (eq (aref s 0) ?+) val (math-neg val)))))
+      
+      ;; Forms that require extensions module
+      ((string-match "[^-+0-9eE.]" s)
+       (require 'calc-ext)
+       (math-read-number-fancy s))
+      
+      ;; Decimal point
+      ((string-match "^\\([0-9]*\\)\\.\\([0-9]*\\)$" s)
+       (let ((int (math-match-substring s 1))
+             (frac (math-match-substring s 2)))
+         (let ((ilen (length int))
+               (flen (length frac)))
+           (let ((int (if (> ilen 0) (math-read-number int t) 0))
+                 (frac (if (> flen 0) (math-read-number frac t) 0)))
+             (and int frac (or (> ilen 0) (> flen 0))
+                  (list 'float
+                        (math-add (math-scale-int int flen) frac)
+                        (- flen)))))))
+      
+      ;; "e" notation
+      ((string-match "^\\(.*\\)[eE]\\([-+]?[0-9]+\\)$" s)
+       (let ((mant (math-match-substring s 1))
+             (exp (math-match-substring s 2)))
+         (let ((mant (if (> (length mant) 0) (math-read-number mant t) 1))
+               (exp (if (<= (length exp) (if (memq (aref exp 0) '(?+ ?-)) 8 7))
+                        (string-to-number exp))))
+           (and mant exp (Math-realp mant) (> exp -4000000) (< exp 4000000)
+                (let ((mant (math-float mant)))
+                  (list 'float (nth 1 mant) (+ (nth 2 mant) exp)))))))
+      
+      ;; Syntax error!
+      (t nil)))))
 
 ;;; Parse a very simple number, keeping all digits.
 (defun math-read-number-simple (s)
   "Convert the string S into a Calc number.
 S is assumed to be a simple number (integer or float without an exponent)
 and all digits are kept, regardless of Calc's current precision."
-   (cond
-    ;; Integer
-    ((string-match "^[0-9]+$" s)
-     (if (string-match "^\\(0+\\)" s)
-         (setq s (substring s (match-end 0))))
-     (if (<= (length s) (* 2 math-bignum-digit-length))
-         (string-to-number s)
-       (cons 'bigpos (math-read-bignum s))))
-    ;; Minus sign
-    ((string-match "^-[0-9]+$" s)
-     (if (<= (length s) (1+ (* 2 math-bignum-digit-length)))
-         (string-to-number s)
-       (cons 'bigneg (math-read-bignum (substring s 1)))))
-    ;; Decimal point
-    ((string-match "^\\(-?[0-9]*\\)\\.\\([0-9]*\\)$" s)
-     (let ((int (math-match-substring s 1))
-          (frac (math-match-substring s 2)))
-       (list 'float (math-read-number-simple (concat int frac))
-             (- (length frac)))))
-    ;; Syntax error!
-    (t nil)))
+  (save-match-data
+    (cond
+     ;; Integer
+     ((string-match "^[0-9]+$" s)
+      (if (string-match "^\\(0+\\)" s)
+          (setq s (substring s (match-end 0))))
+      (if (<= (length s) (* 2 math-bignum-digit-length))
+          (string-to-number s)
+        (cons 'bigpos (math-read-bignum s))))
+     ;; Minus sign
+     ((string-match "^-[0-9]+$" s)
+      (if (<= (length s) (1+ (* 2 math-bignum-digit-length)))
+          (string-to-number s)
+        (cons 'bigneg (math-read-bignum (substring s 1)))))
+     ;; Decimal point
+     ((string-match "^\\(-?[0-9]*\\)\\.\\([0-9]*\\)$" s)
+      (let ((int (math-match-substring s 1))
+            (frac (math-match-substring s 2)))
+        (list 'float (math-read-number-simple (concat int frac))
+              (- (length frac)))))
+     ;; Syntax error!
+     (t nil))))
 
 (defun math-match-substring (s n)
   (if (match-beginning n)
@@ -3781,6 +3789,14 @@ See Info node `(calc)Defining Functions'."
       (setq unread-command-event nil)
     (setq unread-command-events nil)))
 
+(defcalcmodevar math-2-word-size 
+  (math-read-number-simple "4294967296")
+  "Two to the power of `calc-word-size'.")
+
+(defcalcmodevar math-half-2-word-size
+  (math-read-number-simple "2147483648")
+  "One-half of two to the power of `calc-word-size'.")
+
 (when calc-always-load-extensions
   (require 'calc-ext)
   (calc-load-everything))