;;; calc-units.el --- unit conversion functions for Calc
-;; Copyright (C) 1990, 1991, 1992, 1993, 2001, 2002, 2003, 2004, 2005,
-;; 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2011 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
;; Maintainer: Jay Belanger <jay.p.belanger@gmail.com>
"149597870691 m (*)")
;; (approx) NASA JPL (http://neo.jpl.nasa.gov/glossary/au.html)
( lyr "c yr" "Light Year" )
- ( pc "3.0856775854*10^16 m" "Parsec" nil
+ ( pc "3.0856775854*10^16 m" "Parsec (**)" nil
"3.0856775854 10^16 m (*)") ;; (approx) ESUWM
( nmi "1852 m" "Nautical Mile" )
( fath "6 ft" "Fathom" )
( fur "660 ft" "Furlong")
( mu "1 um" "Micron" )
( mil "(1/1000) in" "Mil" )
- ( point "(1/72) in" "Point (1/72 inch)" )
+ ( point "(1/72) in" "Point (PostScript convention)" )
( Ang "10^(-10) m" "Angstrom" )
( mfi "mi+ft+in" "Miles + feet + inches" )
;; TeX lengths
- ( texpt "(100/7227) in" "Point (TeX conventions)" )
- ( texpc "12 texpt" "Pica" )
- ( texbp "point" "Big point (TeX conventions)" )
- ( texdd "(1238/1157) texpt" "Didot point" )
- ( texcc "12 texdd" "Cicero" )
- ( texsp "(1/65536) texpt" "Scaled TeX point" )
+ ( texpt "(100/7227) in" "Point (TeX convention) (**)" )
+ ( texpc "12 texpt" "Pica (TeX convention) (**)" )
+ ( texbp "point" "Big point (TeX convention) (**)" )
+ ( texdd "(1238/1157) texpt" "Didot point (TeX convention) (**)" )
+ ( texcc "12 texdd" "Cicero (TeX convention) (**)" )
+ ( texsp "(1/65536) texpt" "Scaled TeX point (TeX convention) (**)" )
;; Area
( hect "10000 m^2" "*Hectare" )
( l "L" "Liter" )
( gal "4 qt" "US Gallon" )
( qt "2 pt" "Quart" )
- ( pt "2 cup" "Pint" )
+ ( pt "2 cup" "Pint (**)" )
( cup "8 ozfl" "Cup" )
( ozfl "2 tbsp" "Fluid Ounce" )
( floz "2 tbsp" "Fluid Ounce" )
( R0 "8.314472 J/(mol K)" "Molar gas constant" nil
"8.314472 J/(mol K) (*)")
( V0 "22.710981*10^(-3) m^3/mol" "Standard volume of ideal gas" nil
- "22.710981 10^-3 m^3/mol (*)")))
+ "22.710981 10^-3 m^3/mol (*)")
+ ;; Logarithmic units
+ ( Np nil "*Neper")
+ ( dB "(ln(10)/20) Np" "decibel")))
(defvar math-additional-units nil
(or (eq (nth 1 expr) 'pi)
(error "Unknown name %s in defining expression for unit %s"
(nth 1 expr) (car math-fbu-entry))))
+ ((equal expr '(calcFunc-ln 10)))
(t (error "Malformed defining expression for unit %s" (car math-fbu-entry))))))
(indent-to 15)
(insert " " (nth 2 u) "\n")
(while (eq (car (car (setq uptr (cdr uptr)))) 0)))
- (insert "\n"))
+ (insert "\n\n")
+ (insert "(**) When in TeX or LaTeX display mode, the TeX specific unit\n"
+ "names will not use the `tex' prefix; the unit name for a\n"
+ "TeX point will be `pt' instead of `texpt', for example.\n"
+ "To avoid conflicts, the unit names for pint and parsec will\n"
+ "be `pint' and `parsec' instead of `pt' and `pc'."))
(view-mode)
(message "Formatting units table...done"))
(setq math-units-table-buffer-valid t)
(pop-to-buffer (get-buffer "*Units Table*"))
(display-buffer (get-buffer "*Units Table*")))))
+;;; Logarithmic units functions
+
+(defvar math-logunits '((var dB var-dB)
+ (var Np var-Np)))
+
+(defun math-conditional-apply (fn &rest args)
+ "Evaluate f(args) unless in symbolic mode.
+In symbolic mode, return the list (fn args)."
+ (if calc-symbolic-mode
+ (cons fn args)
+ (apply fn args)))
+
+(defun math-conditional-pow (a b)
+ "Evaluate a^b unless in symbolic mode.
+In symbolic mode, return the list (^ a b)."
+ (if calc-symbolic-mode
+ (list '^ a b)
+ (math-pow a b)))
+
+(defun math-extract-logunits (expr)
+ (if (memq (car-safe expr) '(* /))
+ (cons (car expr)
+ (mapcar 'math-extract-logunits (cdr expr)))
+ (if (memq (car-safe expr) '(^))
+ (list '^ (math-extract-logunits (nth 1 expr)) (nth 2 expr))
+ (if (member expr math-logunits) expr 1))))
+
+(defun math-logunits-add (a b neg power)
+ (let ((aunit (math-simplify (math-extract-logunits a))))
+ (if (not (eq (car-safe aunit) 'var))
+ (calc-record-why "*Improper logarithmic unit" aunit)
+ (let* ((units (math-extract-units a))
+ (acoeff (math-simplify (math-remove-units a)))
+ (bcoeff (math-simplify (math-to-standard-units
+ (list '/ b units) nil))))
+ (if (math-units-in-expr-p bcoeff nil)
+ (calc-record-why "*Inconsistent units" nil)
+ (if (and neg
+ (or (math-lessp acoeff bcoeff)
+ (math-equal acoeff bcoeff)))
+ (calc-record-why "*Improper coefficients" nil)
+ (math-mul
+ (if (equal aunit '(var dB var-dB))
+ (let ((coef (if power 10 20)))
+ (math-mul coef
+ (math-conditional-apply 'calcFunc-log10
+ (if neg
+ (math-sub
+ (math-conditional-pow 10 (math-div acoeff coef))
+ (math-conditional-pow 10 (math-div bcoeff coef)))
+ (math-add
+ (math-conditional-pow 10 (math-div acoeff coef))
+ (math-conditional-pow 10 (math-div bcoeff coef)))))))
+ (let ((coef (if power 2 1)))
+ (math-div
+ (math-conditional-apply 'calcFunc-ln
+ (if neg
+ (math-sub
+ (math-conditional-apply 'calcFunc-exp (math-mul coef acoeff))
+ (math-conditional-apply 'calcFunc-exp (math-mul coef bcoeff)))
+ (math-add
+ (math-conditional-apply 'calcFunc-exp (math-mul coef acoeff))
+ (math-conditional-apply 'calcFunc-exp (math-mul coef bcoeff)))))
+ coef)))
+ units)))))))
+
+(defun calcFunc-lufieldplus (a b)
+ (math-logunits-add a b nil nil))
+
+(defun calcFunc-lupowerplus (a b)
+ (math-logunits-add a b nil t))
+
+(defun calcFunc-lufieldminus (a b)
+ (math-logunits-add a b t nil))
+
+(defun calcFunc-lupowerminus (a b)
+ (math-logunits-add a b t t))
+
+(defun calc-logunits-add (arg)
+ (interactive "P")
+ (calc-slow-wrapper
+ (if (calc-is-inverse)
+ (if (calc-is-hyperbolic)
+ (calc-binary-op "lu-" 'calcFunc-lufieldminus arg)
+ (calc-binary-op "lu-" 'calcFunc-lupowerminus arg))
+ (if (calc-is-hyperbolic)
+ (calc-binary-op "lu+" 'calcFunc-lufieldplus arg)
+ (calc-binary-op "lu+" 'calcFunc-lupowerplus arg)))))
+
+(defun calc-logunits-sub (arg)
+ (interactive "P")
+ (calc-slow-wrapper
+ (if (calc-is-inverse)
+ (if (calc-is-hyperbolic)
+ (calc-binary-op "lu+" 'calcFunc-lufieldplus arg)
+ (calc-binary-op "lu+" 'calcFunc-lupowerplus arg))
+ (if (calc-is-hyperbolic)
+ (calc-binary-op "lu-" 'calcFunc-lufieldminus arg)
+ (calc-binary-op "lu-" 'calcFunc-lupowerminus arg)))))
+
+(defun math-logunits-mul (a b power)
+ (let (logunit coef units number)
+ (cond
+ ((and
+ (setq logunit (math-simplify (math-extract-logunits a)))
+ (eq (car-safe logunit) 'var)
+ (eq (math-simplify (math-extract-units b)) 1))
+ (setq coef (math-simplify (math-remove-units a))
+ units (math-extract-units a)
+ number b))
+ ((and
+ (setq logunit (math-simplify (math-extract-logunits b)))
+ (eq (car-safe logunit) 'var)
+ (eq (math-simplify (math-extract-units a)) 1))
+ (setq coef (math-simplify (math-remove-units b))
+ units (math-extract-units b)
+ number a))
+ (t (setq logunit nil)))
+ (if logunit
+ (cond
+ ((equal logunit '(var dB var-dB))
+ (math-simplify
+ (math-mul
+ (math-add
+ coef
+ (math-mul (if power 10 20)
+ (math-conditional-apply 'calcFunc-log10 number)))
+ units)))
+ (t
+ (math-simplify
+ (math-mul
+ (math-add
+ coef
+ (math-div (math-conditional-apply 'calcFunc-ln number) (if power 2 1)))
+ units))))
+ (calc-record-why "*Improper units" nil))))
+
+(defun math-logunits-divide (a b power)
+ (let ((logunit (math-simplify (math-extract-logunits a))))
+ (if (not (eq (car-safe logunit) 'var))
+ (calc-record-why "*Improper logarithmic unit" logunit)
+ (if (math-units-in-expr-p b nil)
+ (calc-record-why "*Improper units quantity" b)
+ (let* ((units (math-extract-units a))
+ (coef (math-simplify (math-remove-units a))))
+ (cond
+ ((equal logunit '(var dB var-dB))
+ (math-simplify
+ (math-mul
+ (math-sub
+ coef
+ (math-mul (if power 10 20)
+ (math-conditional-apply 'calcFunc-log10 b)))
+ units)))
+ (t
+ (math-simplify
+ (math-mul
+ (math-sub
+ coef
+ (math-div (math-conditional-apply 'calcFunc-ln b) (if power 2 1)))
+ units)))))))))
+
+(defun calcFunc-lufieldtimes (a b)
+ (math-logunits-mul a b nil))
+
+(defun calcFunc-lupowertimes (a b)
+ (math-logunits-mul a b t))
+
+(defun calc-logunits-mul (arg)
+ (interactive "P")
+ (calc-slow-wrapper
+ (if (calc-is-inverse)
+ (if (calc-is-hyperbolic)
+ (calc-binary-op "lu/" 'calcFunc-lufielddiv arg)
+ (calc-binary-op "lu/" 'calcFunc-lupowerdiv arg))
+ (if (calc-is-hyperbolic)
+ (calc-binary-op "lu*" 'calcFunc-lufieldtimes arg)
+ (calc-binary-op "lu*" 'calcFunc-lupowertimes arg)))))
+
+(defun calcFunc-lufielddiv (a b)
+ (math-logunits-divide a b nil))
+
+(defun calcFunc-lupowerdiv (a b)
+ (math-logunits-divide a b t))
+
+(defun calc-logunits-divide (arg)
+ (interactive "P")
+ (calc-slow-wrapper
+ (if (calc-is-inverse)
+ (if (calc-is-hyperbolic)
+ (calc-binary-op "lu*" 'calcFunc-lufieldtimes arg)
+ (calc-binary-op "lu*" 'calcFunc-lupowertimes arg))
+ (if (calc-is-hyperbolic)
+ (calc-binary-op "lu/" 'calcFunc-lufielddiv arg)
+ (calc-binary-op "lu/" 'calcFunc-lupowerdiv arg)))))
+
+(defun math-logunits-quant (val ref power)
+ (let* ((units (math-simplify (math-extract-units val)))
+ (lunit (math-simplify (math-extract-logunits units))))
+ (if (not (eq (car-safe lunit) 'var))
+ (calc-record-why "*Improper logarithmic unit" lunit)
+ (let ((runits (math-simplify (math-div units lunit)))
+ (coeff (math-simplify (math-div val units))))
+ (math-mul
+ (if (equal lunit '(var dB var-dB))
+ (math-mul
+ ref
+ (math-conditional-pow
+ 10
+ (math-div
+ coeff
+ (if power 10 20))))
+ (math-mul
+ ref
+ (math-conditional-apply 'calcFunc-exp
+ (if power
+ (math-mul 2 coeff)
+ coeff))))
+ runits)))))
+
+(defvar calc-logunits-field-reference)
+(defvar calc-logunits-power-reference)
+
+(defun calcFunc-fieldquant (val &optional ref)
+ (unless ref
+ (setq ref (math-read-expr calc-logunits-field-reference)))
+ (math-logunits-quant val ref nil))
+
+(defun calcFunc-powerquant (val &optional ref)
+ (unless ref
+ (setq ref (math-read-expr calc-logunits-power-reference)))
+ (math-logunits-quant val ref t))
+
+(defun calc-logunits-quantity (arg)
+ (interactive "P")
+ (calc-slow-wrapper
+ (if (calc-is-hyperbolic)
+ (if (calc-is-option)
+ (calc-binary-op "lupq" 'calcFunc-fieldquant arg)
+ (calc-unary-op "lupq" 'calcFunc-fieldquant arg))
+ (if (calc-is-option)
+ (calc-binary-op "lufq" 'calcFunc-powerquant arg)
+ (calc-unary-op "lufq" 'calcFunc-powerquant arg)))))
+
+(defun math-logunits-level (val ref db power)
+ "Compute the value of VAL in decibels or nepers."
+ (let* ((ratio (math-simplify-units (math-div val ref)))
+ (ratiou (math-simplify-units (math-remove-units ratio)))
+ (units (math-simplify (math-extract-units ratio))))
+ (math-mul
+ (if db
+ (math-mul
+ (math-mul (if power 10 20)
+ (math-conditional-apply 'calcFunc-log10 ratiou))
+ '(var dB var-dB))
+ (math-mul
+ (math-div (math-conditional-apply 'calcFunc-ln ratiou) (if power 2 1))
+ '(var Np var-Np)))
+ units)))
+
+(defun calcFunc-dbfieldlevel (val &optional ref)
+ (unless ref
+ (setq ref (math-read-expr calc-logunits-field-reference)))
+ (math-logunits-level val ref t nil))
+
+(defun calcFunc-dbpowerlevel (val &optional ref)
+ (unless ref
+ (setq ref (math-read-expr calc-logunits-power-reference)))
+ (math-logunits-level val ref t t))
+
+(defun calcFunc-npfieldlevel (val &optional ref)
+ (unless ref
+ (setq ref (math-read-expr calc-logunits-field-reference)))
+ (math-logunits-level val ref nil nil))
+
+(defun calcFunc-nppowerlevel (val &optional ref)
+ (unless ref
+ (setq ref (math-read-expr calc-logunits-power-reference)))
+ (math-logunits-level val ref nil t))
+
+(defun calc-logunits-dblevel (arg)
+ (interactive "P")
+ (calc-slow-wrapper
+ (if (calc-is-hyperbolic)
+ (if (calc-is-option)
+ (calc-binary-op "ludb" 'calcFunc-dbfieldlevel arg)
+ (calc-unary-op "ludb" 'calcFunc-dbfieldlevel arg))
+ (if (calc-is-option)
+ (calc-binary-op "ludb" 'calcFunc-dbpowerlevel arg)
+ (calc-unary-op "ludb" 'calcFunc-dbpowerlevel arg)))))
+
+(defun calc-logunits-nplevel (arg)
+ (interactive "P")
+ (calc-slow-wrapper
+ (if (calc-is-hyperbolic)
+ (if (calc-is-option)
+ (calc-binary-op "lunp" 'calcFunc-npfieldlevel arg)
+ (calc-unary-op "lunp" 'calcFunc-npfieldlevel arg))
+ (if (calc-is-option)
+ (calc-binary-op "lunp" 'calcFunc-nppowerlevel arg)
+ (calc-unary-op "lunp" 'calcFunc-nppowerlevel arg)))))
+
(provide 'calc-units)
;; Local variables:
;; coding: utf-8
;; End:
-;; arch-tag: e993314f-3adc-4191-be61-4ef8874881c4
;;; calc-units.el ends here