Refill some copyright headers.
[bpt/emacs.git] / lisp / calc / calc-units.el
CommitLineData
8cd8ee52
CW
1;;; calc-units.el --- unit conversion functions for Calc
2
e9bffc61
GM
3;; Copyright (C) 1990, 1991, 1992, 1993, 2001, 2002, 2003, 2004, 2005,
4;; 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
8cd8ee52
CW
5
6;; Author: David Gillespie <daveg@synaptics.com>
e8fff8ed 7;; Maintainer: Jay Belanger <jay.p.belanger@gmail.com>
136211a9
EZ
8
9;; This file is part of GNU Emacs.
10
662c9c64 11;; GNU Emacs is free software: you can redistribute it and/or modify
7c671b23 12;; it under the terms of the GNU General Public License as published by
662c9c64
GM
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
7c671b23 15
136211a9 16;; GNU Emacs is distributed in the hope that it will be useful,
7c671b23
GM
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
662c9c64 22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
136211a9 23
8cd8ee52 24;;; Commentary:
136211a9 25
8cd8ee52 26;;; Code:
136211a9
EZ
27
28;; This file is autoloaded from calc-ext.el.
136211a9 29
7d02e8cd 30(require 'calc-ext)
136211a9 31(require 'calc-macs)
c7388379
JB
32(eval-when-compile
33 (require 'calc-alg))
136211a9 34
8cd8ee52
CW
35;;; Units operations.
36
37;;; Units table last updated 9-Jan-91 by Ulrich Mueller (ulm@vsnhd1.cern.ch)
38;;; with some additions by Przemek Klosowski (przemek@rrdstrad.nist.gov)
ae6bc504 39;;; Updated April 2002 by Jochen Küpper
be59410c 40
a21f3259
JB
41;;; Updated August 2007, using
42;;; CODATA (http://physics.nist.gov/cuu/Constants/index.html)
43;;; NIST (http://physics.nist.gov/Pubs/SP811/appenB9.html)
44;;; ESUWM (Encyclopaedia of Scientific Units, Weights and
ae6bc504 45;;; Measures, by François Cardarelli)
a21f3259 46;;; All conversions are exact unless otherwise noted.
8cd8ee52
CW
47
48(defvar math-standard-units
49 '( ;; Length
cf39c182 50 ( m nil "*Meter" )
60afd99b 51 ( in "254*10^(-2) cm" "Inch" nil
19bdc4d8
JB
52 "2.54 cm")
53 ( ft "12 in" "Foot")
cf39c182
JB
54 ( yd "3 ft" "Yard" )
55 ( mi "5280 ft" "Mile" )
60afd99b 56 ( au "149597870691. m" "Astronomical Unit" nil
19bdc4d8 57 "149597870691 m (*)")
a21f3259
JB
58 ;; (approx) NASA JPL (http://neo.jpl.nasa.gov/glossary/au.html)
59 ( lyr "c yr" "Light Year" )
1265829e 60 ( pc "3.0856775854*10^16 m" "Parsec (**)" nil
ac318df0 61 "3.0856775854 10^16 m (*)") ;; (approx) ESUWM
cf39c182
JB
62 ( nmi "1852 m" "Nautical Mile" )
63 ( fath "6 ft" "Fathom" )
ac318df0 64 ( fur "660 ft" "Furlong")
cf39c182 65 ( mu "1 um" "Micron" )
ac318df0 66 ( mil "(1/1000) in" "Mil" )
1265829e 67 ( point "(1/72) in" "Point (PostScript convention)" )
a21f3259 68 ( Ang "10^(-10) m" "Angstrom" )
cf39c182
JB
69 ( mfi "mi+ft+in" "Miles + feet + inches" )
70 ;; TeX lengths
1265829e
JB
71 ( texpt "(100/7227) in" "Point (TeX convention) (**)" )
72 ( texpc "12 texpt" "Pica (TeX convention) (**)" )
73 ( texbp "point" "Big point (TeX convention) (**)" )
74 ( texdd "(1238/1157) texpt" "Didot point (TeX convention) (**)" )
75 ( texcc "12 texdd" "Cicero (TeX convention) (**)" )
76 ( texsp "(1/65536) texpt" "Scaled TeX point (TeX convention) (**)" )
a1506d29 77
be59410c 78 ;; Area
cf39c182
JB
79 ( hect "10000 m^2" "*Hectare" )
80 ( a "100 m^2" "Are")
ac318df0 81 ( acre "(1/640) mi^2" "Acre" )
a21f3259 82 ( b "10^(-28) m^2" "Barn" )
a1506d29 83
be59410c 84 ;; Volume
a21f3259 85 ( L "10^(-3) m^3" "*Liter" )
cf39c182
JB
86 ( l "L" "Liter" )
87 ( gal "4 qt" "US Gallon" )
88 ( qt "2 pt" "Quart" )
1265829e 89 ( pt "2 cup" "Pint (**)" )
cf39c182
JB
90 ( cup "8 ozfl" "Cup" )
91 ( ozfl "2 tbsp" "Fluid Ounce" )
92 ( floz "2 tbsp" "Fluid Ounce" )
93 ( tbsp "3 tsp" "Tablespoon" )
7026903c
JB
94 ;; ESUWM defines a US gallon as 231 in^3.
95 ;; That gives the following exact value for tsp.
60afd99b 96 ( tsp "492892159375*10^(-11) ml" "Teaspoon" nil
19bdc4d8 97 "4.92892159375 ml")
ac318df0
JB
98 ( vol "tsp+tbsp+ozfl+cup+pt+qt+gal" "Gallons + ... + teaspoons" nil
99 "tsp+tbsp+ozfl+cup+pt+qt+gal")
a21f3259 100 ( galC "galUK" "Canadian Gallon" )
60afd99b 101 ( galUK "454609*10^(-5) L" "UK Gallon" nil
19bdc4d8 102 "4.54609 L") ;; NIST
a1506d29 103
be59410c 104 ;; Time
cf39c182
JB
105 ( s nil "*Second" )
106 ( sec "s" "Second" )
107 ( min "60 s" "Minute" )
108 ( hr "60 min" "Hour" )
109 ( day "24 hr" "Day" )
110 ( wk "7 day" "Week" )
111 ( hms "wk+day+hr+min+s" "Hours, minutes, seconds" )
ac318df0
JB
112 ( yr "36525*10^(-2) day" "Year (Julian)" nil
113 "365.25 day")
cf39c182 114 ( Hz "1/s" "Hertz" )
be59410c
CW
115
116 ;; Speed
cf39c182
JB
117 ( mph "mi/hr" "*Miles per hour" )
118 ( kph "km/hr" "Kilometers per hour" )
119 ( knot "nmi/hr" "Knot" )
a21f3259 120 ( c "299792458 m/s" "Speed of light" ) ;;; CODATA
a1506d29 121
be59410c 122 ;; Acceleration
60afd99b 123 ( ga "980665*10^(-5) m/s^2" "*\"g\" acceleration" nil
19bdc4d8 124 "9.80665 m / s^2") ;; CODATA
be59410c
CW
125
126 ;; Mass
cf39c182
JB
127 ( g nil "*Gram" )
128 ( lb "16 oz" "Pound (mass)" )
60afd99b 129 ( oz "28349523125*10^(-9) g" "Ounce (mass)" nil
19bdc4d8 130 "28.349523125 g") ;; ESUWM
cf39c182
JB
131 ( ton "2000 lb" "Ton" )
132 ( tpo "ton+lb+oz" "Tons + pounds + ounces (mass)" )
133 ( t "1000 kg" "Metric ton" )
60afd99b 134 ( tonUK "10160469088*10^(-7) kg" "UK ton" nil
19bdc4d8 135 "1016.0469088 kg") ;; ESUWM
cf39c182 136 ( lbt "12 ozt" "Troy pound" )
60afd99b 137 ( ozt "311034768*10^(-7) g" "Troy ounce" nil
ac318df0 138 "31.10347680 g") ;; ESUWM, 1/12 exact value for lbt
60afd99b 139 ( ct "(2/10) g" "Carat" nil
19bdc4d8 140 "0.2 g") ;; ESUWM
60afd99b 141 ( u "1.660538782*10^(-27) kg" "Unified atomic mass" nil
ac318df0 142 "1.660538782 10^-27 kg (*)");;(approx) CODATA
be59410c
CW
143
144 ;; Force
cf39c182 145 ( N "m kg/s^2" "*Newton" )
a21f3259 146 ( dyn "10^(-5) N" "Dyne" )
cf39c182 147 ( gf "ga g" "Gram (force)" )
a21f3259 148 ( lbf "ga lb" "Pound (force)" )
cf39c182 149 ( kip "1000 lbf" "Kilopound (force)" )
60afd99b 150 ( pdl "138254954376*10^(-12) N" "Poundal" nil
19bdc4d8 151 "0.138254954376 N") ;; ESUWM
be59410c
CW
152
153 ;; Energy
cf39c182 154 ( J "N m" "*Joule" )
a21f3259 155 ( erg "10^(-7) J" "Erg" )
60afd99b 156 ( cal "41868*10^(-4) J" "International Table Calorie" nil
ac318df0 157 "4.1868 J") ;; NIST
60afd99b 158 ( calth "4184*10^(-3) J" "Thermochemical Calorie" nil
ac318df0
JB
159 "4.184 J") ;; NIST
160 ( Cal "1000 cal" "Large Calorie")
60afd99b 161 ( Btu "105505585262*10^(-8) J" "International Table Btu" nil
19bdc4d8 162 "1055.05585262 J") ;; ESUWM
cf39c182
JB
163 ( eV "ech V" "Electron volt" )
164 ( ev "eV" "Electron volt" )
165 ( therm "105506000 J" "EEC therm" )
166 ( invcm "h c/cm" "Energy in inverse centimeters" )
167 ( Kayser "invcm" "Kayser (inverse centimeter energy)" )
168 ( men "100/invcm" "Inverse energy in meters" )
169 ( Hzen "h Hz" "Energy in Hertz")
170 ( Ken "k K" "Energy in Kelvins")
02bf5ab9 171 ( Wh "W hr" "Watt hour")
cf39c182 172 ( Ws "W s" "Watt second")
be59410c
CW
173
174 ;; Power
cf39c182 175 ( W "J/s" "*Watt" )
ac318df0
JB
176 ( hp "550 ft lbf/s" "Horsepower") ;;ESUWM
177 ( hpm "75 m kgf/s" "Metric Horsepower") ;;ESUWM
be59410c
CW
178
179 ;; Temperature
cf39c182
JB
180 ( K nil "*Degree Kelvin" K )
181 ( dK "K" "Degree Kelvin" K )
182 ( degK "K" "Degree Kelvin" K )
183 ( dC "K" "Degree Celsius" C )
184 ( degC "K" "Degree Celsius" C )
185 ( dF "(5/9) K" "Degree Fahrenheit" F )
186 ( degF "(5/9) K" "Degree Fahrenheit" F )
be59410c
CW
187
188 ;; Pressure
cf39c182 189 ( Pa "N/m^2" "*Pascal" )
a21f3259
JB
190 ( bar "10^5 Pa" "Bar" )
191 ( atm "101325 Pa" "Standard atmosphere" ) ;; CODATA
ac318df0 192 ( Torr "(1/760) atm" "Torr")
cf39c182 193 ( mHg "1000 Torr" "Meter of mercury" )
60afd99b 194 ( inHg "254*10^(-1) mmHg" "Inch of mercury" nil
19bdc4d8 195 "25.4 mmHg")
60afd99b 196 ( inH2O "2.490889*10^2 Pa" "Inch of water" nil
ac318df0 197 "2.490889 10^2 Pa (*)") ;;(approx) NIST
a21f3259 198 ( psi "lbf/in^2" "Pounds per square inch" )
be59410c
CW
199
200 ;; Viscosity
a21f3259
JB
201 ( P "(1/10) Pa s" "*Poise" )
202 ( St "10^(-4) m^2/s" "Stokes" )
be59410c
CW
203
204 ;; Electromagnetism
cf39c182
JB
205 ( A nil "*Ampere" )
206 ( C "A s" "Coulomb" )
207 ( Fdy "ech Nav" "Faraday" )
a21f3259 208 ( e "ech" "Elementary charge" )
60afd99b 209 ( ech "1.602176487*10^(-19) C" "Elementary charge" nil
ac318df0 210 "1.602176487 10^-19 C (*)") ;;(approx) CODATA
cf39c182
JB
211 ( V "W/A" "Volt" )
212 ( ohm "V/A" "Ohm" )
ae6bc504 213 ( Ω "ohm" "Ohm" )
cf39c182
JB
214 ( mho "A/V" "Mho" )
215 ( S "A/V" "Siemens" )
216 ( F "C/V" "Farad" )
217 ( H "Wb/A" "Henry" )
218 ( T "Wb/m^2" "Tesla" )
a21f3259 219 ( Gs "10^(-4) T" "Gauss" )
cf39c182 220 ( Wb "V s" "Weber" )
be59410c
CW
221
222 ;; Luminous intensity
cf39c182 223 ( cd nil "*Candela" )
a21f3259 224 ( sb "10000 cd/m^2" "Stilb" )
cf39c182
JB
225 ( lm "cd sr" "Lumen" )
226 ( lx "lm/m^2" "Lux" )
a21f3259 227 ( ph "10000 lx" "Phot" )
ac318df0 228 ( fc "lm/ft^2" "Footcandle") ;; ESUWM
a21f3259 229 ( lam "10000 lm/m^2" "Lambert" )
ac318df0 230 ( flam "(1/pi) cd/ft^2" "Footlambert") ;; ESUWM
be59410c
CW
231
232 ;; Radioactivity
cf39c182 233 ( Bq "1/s" "*Becquerel" )
a21f3259 234 ( Ci "37*10^9 Bq" "Curie" ) ;; ESUWM
cf39c182
JB
235 ( Gy "J/kg" "Gray" )
236 ( Sv "Gy" "Sievert" )
a21f3259
JB
237 ( R "258*10^(-6) C/kg" "Roentgen" ) ;; NIST
238 ( rd "(1/100) Gy" "Rad" )
cf39c182 239 ( rem "rd" "Rem" )
be59410c
CW
240
241 ;; Amount of substance
cf39c182 242 ( mol nil "*Mole" )
be59410c
CW
243
244 ;; Plane angle
cf39c182
JB
245 ( rad nil "*Radian" )
246 ( circ "2 pi rad" "Full circle" )
247 ( rev "circ" "Full revolution" )
248 ( deg "circ/360" "Degree" )
249 ( arcmin "deg/60" "Arc minute" )
250 ( arcsec "arcmin/60" "Arc second" )
251 ( grad "circ/400" "Grade" )
252 ( rpm "rev/min" "Revolutions per minute" )
be59410c
CW
253
254 ;; Solid angle
cf39c182 255 ( sr nil "*Steradian" )
be59410c 256
cf39c182 257 ;; Other physical quantities
a21f3259 258 ;; The values are from CODATA, and are approximate.
60afd99b 259 ( h "6.62606896*10^(-34) J s" "*Planck's constant" nil
ac318df0
JB
260 "6.62606896 10^-34 J s (*)")
261 ( hbar "h / (2 pi)" "Planck's constant" ) ;; Exact
262 ( mu0 "4 pi 10^(-7) H/m" "Permeability of vacuum") ;; Exact
ae6bc504 263 ( μ0 "mu0" "Permeability of vacuum") ;; Exact
4929aa69 264 ( eps0 "1 / (mu0 c^2)" "Permittivity of vacuum" )
ae6bc504 265 ( ε0 "eps0" "Permittivity of vacuum" )
60afd99b 266 ( G "6.67428*10^(-11) m^3/(kg s^2)" "Gravitational constant" nil
9b3e5667 267 "6.67428 10^-11 m^3/(kg s^2) (*)")
60afd99b 268 ( Nav "6.02214179*10^(23) / mol" "Avogadro's constant" nil
ac318df0 269 "6.02214179 10^23 / mol (*)")
60afd99b 270 ( me "9.10938215*10^(-31) kg" "Electron rest mass" nil
ac318df0 271 "9.10938215 10^-31 kg (*)")
60afd99b 272 ( mp "1.672621637*10^(-27) kg" "Proton rest mass" nil
ac318df0 273 "1.672621637 10^-27 kg (*)")
60afd99b 274 ( mn "1.674927211*10^(-27) kg" "Neutron rest mass" nil
ac318df0 275 "1.674927211 10^-27 kg (*)")
60afd99b 276 ( mmu "1.88353130*10^(-28) kg" "Muon rest mass" nil
ac318df0 277 "1.88353130 10^-28 kg (*)")
ae6bc504
JB
278 ( mμ "mmu" "Muon rest mass" nil
279 "1.88353130 10^-28 kg (*)")
60afd99b 280 ( Ryd "10973731.568527 /m" "Rydberg's constant" nil
19bdc4d8 281 "10973731.568527 /m (*)")
60afd99b 282 ( k "1.3806504*10^(-23) J/K" "Boltzmann's constant" nil
ac318df0 283 "1.3806504 10^-23 J/K (*)")
60afd99b 284 ( alpha "7.2973525376*10^(-3)" "Fine structure constant" nil
ac318df0 285 "7.2973525376 10^-3 (*)")
ae6bc504
JB
286 ( α "alpha" "Fine structure constant" nil
287 "7.2973525376 10^-3 (*)")
60afd99b 288 ( muB "927.400915*10^(-26) J/T" "Bohr magneton" nil
ac318df0 289 "927.400915 10^-26 J/T (*)")
60afd99b 290 ( muN "5.05078324*10^(-27) J/T" "Nuclear magneton" nil
ac318df0 291 "5.05078324 10^-27 J/T (*)")
60afd99b 292 ( mue "-928.476377*10^(-26) J/T" "Electron magnetic moment" nil
ac318df0 293 "-928.476377 10^-26 J/T (*)")
60afd99b 294 ( mup "1.410606662*10^(-26) J/T" "Proton magnetic moment" nil
ac318df0 295 "1.410606662 10^-26 J/T (*)")
60afd99b 296 ( R0 "8.314472 J/(mol K)" "Molar gas constant" nil
19bdc4d8 297 "8.314472 J/(mol K) (*)")
60afd99b 298 ( V0 "22.710981*10^(-3) m^3/mol" "Standard volume of ideal gas" nil
ac318df0 299 "22.710981 10^-3 m^3/mol (*)")))
8cd8ee52
CW
300
301
302(defvar math-additional-units nil
303 "*Additional units table for user-defined units.
60afd99b 304Must be formatted like `math-standard-units'.
11220394 305If you change this, be sure to set `math-units-table' to nil to ensure
8cd8ee52
CW
306that the combined units table will be rebuilt.")
307
308(defvar math-unit-prefixes
a21f3259
JB
309 '( ( ?Y (^ 10 24) "Yotta" )
310 ( ?Z (^ 10 21) "Zetta" )
311 ( ?E (^ 10 18) "Exa" )
312 ( ?P (^ 10 15) "Peta" )
313 ( ?T (^ 10 12) "Tera" )
314 ( ?G (^ 10 9) "Giga" )
315 ( ?M (^ 10 6) "Mega" )
316 ( ?k (^ 10 3) "Kilo" )
317 ( ?K (^ 10 3) "Kilo" )
318 ( ?h (^ 10 2) "Hecto" )
319 ( ?H (^ 10 2) "Hecto" )
320 ( ?D (^ 10 1) "Deka" )
321 ( 0 (^ 10 0) nil )
322 ( ?d (^ 10 -1) "Deci" )
323 ( ?c (^ 10 -2) "Centi" )
324 ( ?m (^ 10 -3) "Milli" )
325 ( ?u (^ 10 -6) "Micro" )
be19ef0b 326 ( ?μ (^ 10 -6) "Micro" )
a21f3259
JB
327 ( ?n (^ 10 -9) "Nano" )
328 ( ?p (^ 10 -12) "Pico" )
329 ( ?f (^ 10 -15) "Femto" )
330 ( ?a (^ 10 -18) "Atto" )
331 ( ?z (^ 10 -21) "zepto" )
332 ( ?y (^ 10 -24) "yocto" )))
8cd8ee52
CW
333
334(defvar math-standard-units-systems
335 '( ( base nil )
a21f3259
JB
336 ( si ( ( g '(/ (var kg var-kg) 1000) ) ) )
337 ( mks ( ( g '(/ (var kg var-kg) 1000) ) ) )
338 ( cgs ( ( m '(* (var cm var-cm) 100 ) ) ) )))
8cd8ee52
CW
339
340(defvar math-units-table nil
60afd99b
JB
341 "Internal units table.
342Derived from `math-standard-units' and `math-additional-units'.
8cd8ee52
CW
343Entries are (SYMBOL EXPR DOC-STRING TEMP-TYPE BASE-UNITS).")
344
345(defvar math-units-table-buffer-valid nil)
136211a9
EZ
346
347;;; Units commands.
348
349(defun calc-base-units ()
350 (interactive)
351 (calc-slow-wrapper
352 (let ((calc-autorange-units nil))
353 (calc-enter-result 1 "bsun" (math-simplify-units
354 (math-to-standard-units (calc-top-n 1)
c9aef719 355 nil))))))
136211a9
EZ
356
357(defun calc-quick-units ()
358 (interactive)
359 (calc-slow-wrapper
e93c003e 360 (let* ((num (- last-command-event ?0))
136211a9
EZ
361 (pos (if (= num 0) 10 num))
362 (units (calc-var-value 'var-Units))
363 (expr (calc-top-n 1)))
8cd8ee52 364 (unless (and (>= num 0) (<= num 9))
91af11b2 365 (error "Bad unit number"))
8cd8ee52 366 (unless (math-vectorp units)
91af11b2 367 (error "No \"quick units\" are defined"))
8cd8ee52 368 (unless (< pos (length units))
91af11b2 369 (error "Unit number %d not defined" pos))
136211a9
EZ
370 (if (math-units-in-expr-p expr nil)
371 (calc-enter-result 1 (format "cun%d" num)
372 (math-convert-units expr (nth pos units)))
373 (calc-enter-result 1 (format "*un%d" num)
374 (math-simplify-units
c9aef719 375 (math-mul expr (nth pos units))))))))
136211a9 376
5360ea16
JB
377(defun math-get-standard-units (expr)
378 "Return the standard units in EXPR."
379 (math-simplify-units
380 (math-extract-units
381 (math-to-standard-units expr nil))))
382
383(defun math-get-units (expr)
384 "Return the units in EXPR."
385 (math-simplify-units
386 (math-extract-units expr)))
387
388(defun math-make-unit-string (expr)
389 "Return EXPR in string form.
390If EXPR is nil, return nil."
391 (if expr
392 (let ((cexpr (math-compose-expr expr 0)))
09040c8d 393 (replace-regexp-in-string
a21f3259
JB
394 " / " "/"
395 (if (stringp cexpr)
396 cexpr
397 (math-composition-to-string cexpr))))))
5360ea16 398
09040c8d 399(defvar math-default-units-table
5360ea16
JB
400 (make-hash-table :test 'equal)
401 "A table storing previously converted units.")
402
403(defun math-get-default-units (expr)
404 "Get default units to use when converting the units in EXPR."
405 (let* ((units (math-get-units expr))
406 (standard-units (math-get-standard-units expr))
09040c8d 407 (default-units (gethash
5360ea16
JB
408 standard-units
409 math-default-units-table)))
410 (if (equal units (car default-units))
411 (math-make-unit-string (cadr default-units))
412 (math-make-unit-string (car default-units)))))
413
414(defun math-put-default-units (expr)
415 "Put the units in EXPR in the default units table."
416 (let* ((units (math-get-units expr))
417 (standard-units (math-get-standard-units expr))
418 (default-units (gethash
419 standard-units
420 math-default-units-table)))
421 (cond
422 ((not default-units)
423 (puthash standard-units (list units) math-default-units-table))
424 ((not (equal units (car default-units)))
425 (puthash standard-units
426 (list units (car default-units))
427 math-default-units-table)))))
428
429
136211a9
EZ
430(defun calc-convert-units (&optional old-units new-units)
431 (interactive)
432 (calc-slow-wrapper
433 (let ((expr (calc-top-n 1))
434 (uoldname nil)
27971241 435 unew
5360ea16
JB
436 units
437 defunits)
8cd8ee52
CW
438 (unless (math-units-in-expr-p expr t)
439 (let ((uold (or old-units
440 (progn
441 (setq uoldname (read-string "Old units: "))
442 (if (equal uoldname "")
443 (progn
444 (setq uoldname "1")
445 1)
446 (if (string-match "\\` */" uoldname)
447 (setq uoldname (concat "1" uoldname)))
448 (math-read-expr uoldname))))))
449 (when (eq (car-safe uold) 'error)
450 (error "Bad format in units expression: %s" (nth 1 uold)))
451 (setq expr (math-mul expr uold))))
452 (unless new-units
5360ea16 453 (setq defunits (math-get-default-units expr))
09040c8d 454 (setq new-units
5360ea16
JB
455 (read-string (concat
456 (if uoldname
457 (concat "Old units: "
458 uoldname
459 ", new units")
460 "New units")
461 (if defunits
462 (concat
0f3955d9 463 " (default "
5360ea16
JB
464 defunits
465 "): ")
466 ": "))))
09040c8d 467
5360ea16
JB
468 (if (and
469 (string= new-units "")
470 defunits)
471 (setq new-units defunits)))
8cd8ee52
CW
472 (when (string-match "\\` */" new-units)
473 (setq new-units (concat "1" new-units)))
136211a9 474 (setq units (math-read-expr new-units))
8cd8ee52
CW
475 (when (eq (car-safe units) 'error)
476 (error "Bad format in units expression: %s" (nth 2 units)))
5360ea16 477 (math-put-default-units units)
136211a9
EZ
478 (let ((unew (math-units-in-expr-p units t))
479 (std (and (eq (car-safe units) 'var)
480 (assq (nth 1 units) math-standard-units-systems))))
481 (if std
482 (calc-enter-result 1 "cvun" (math-simplify-units
483 (math-to-standard-units expr
484 (nth 1 std))))
8cd8ee52
CW
485 (unless unew
486 (error "No units specified"))
136211a9
EZ
487 (calc-enter-result 1 "cvun"
488 (math-convert-units
489 expr units
c9aef719 490 (and uoldname (not (equal uoldname "1"))))))))))
136211a9
EZ
491
492(defun calc-autorange-units (arg)
493 (interactive "P")
494 (calc-wrapper
495 (calc-change-mode 'calc-autorange-units arg nil t)
496 (message (if calc-autorange-units
8cd8ee52
CW
497 "Adjusting target unit prefix automatically"
498 "Using target units exactly"))))
136211a9
EZ
499
500(defun calc-convert-temperature (&optional old-units new-units)
501 (interactive)
502 (calc-slow-wrapper
503 (let ((expr (calc-top-n 1))
504 (uold nil)
505 (uoldname nil)
5360ea16
JB
506 unew
507 defunits)
136211a9
EZ
508 (setq uold (or old-units
509 (let ((units (math-single-units-in-expr-p expr)))
510 (if units
511 (if (consp units)
512 (list 'var (car units)
513 (intern (concat "var-"
514 (symbol-name
515 (car units)))))
516 (error "Not a pure temperature expression"))
517 (math-read-expr
518 (setq uoldname (read-string
519 "Old temperature units: ")))))))
8cd8ee52
CW
520 (when (eq (car-safe uold) 'error)
521 (error "Bad format in units expression: %s" (nth 2 uold)))
136211a9
EZ
522 (or (math-units-in-expr-p expr nil)
523 (setq expr (math-mul expr uold)))
5360ea16 524 (setq defunits (math-get-default-units expr))
136211a9 525 (setq unew (or new-units
fa786329
JB
526 (read-string
527 (concat
528 (if uoldname
529 (concat "Old temperature units: "
530 uoldname
531 ", new units")
532 "New temperature units")
533 (if defunits
534 (concat " (default "
535 defunits
536 "): ")
537 ": ")))))
538 (setq unew (math-read-expr (if (string= unew "") defunits unew)))
8cd8ee52
CW
539 (when (eq (car-safe unew) 'error)
540 (error "Bad format in units expression: %s" (nth 2 unew)))
5360ea16 541 (math-put-default-units unew)
a34f800f
JB
542 (let ((ntemp (calc-normalize
543 (math-simplify-units
544 (math-convert-temperature expr uold unew
545 uoldname)))))
546 (if (Math-zerop ntemp)
547 (setq ntemp (list '* ntemp unew)))
548 (let ((calc-simplify-mode 'none))
549 (calc-enter-result 1 "cvtm" ntemp))))))
136211a9
EZ
550
551(defun calc-remove-units ()
552 (interactive)
553 (calc-slow-wrapper
554 (calc-enter-result 1 "rmun" (math-simplify-units
c9aef719 555 (math-remove-units (calc-top-n 1))))))
136211a9
EZ
556
557(defun calc-extract-units ()
558 (interactive)
559 (calc-slow-wrapper
560 (calc-enter-result 1 "rmun" (math-simplify-units
c9aef719 561 (math-extract-units (calc-top-n 1))))))
136211a9 562
09040c8d 563;; The variables calc-num-units and calc-den-units are local to
27971241
JB
564;; calc-explain-units, but are used by calc-explain-units-rec,
565;; which is called by calc-explain-units.
566(defvar calc-num-units)
567(defvar calc-den-units)
568
136211a9
EZ
569(defun calc-explain-units ()
570 (interactive)
571 (calc-wrapper
27971241
JB
572 (let ((calc-num-units nil)
573 (calc-den-units nil))
136211a9 574 (calc-explain-units-rec (calc-top-n 1) 1)
27971241
JB
575 (and calc-den-units (string-match "^[^(].* .*[^)]$" calc-den-units)
576 (setq calc-den-units (concat "(" calc-den-units ")")))
577 (if calc-num-units
578 (if calc-den-units
579 (message "%s per %s" calc-num-units calc-den-units)
580 (message "%s" calc-num-units))
581 (if calc-den-units
582 (message "1 per %s" calc-den-units)
c9aef719 583 (message "No units in expression"))))))
136211a9
EZ
584
585(defun calc-explain-units-rec (expr pow)
586 (let ((u (math-check-unit-name expr))
587 pos)
588 (if (and u (not (math-zerop pow)))
589 (let ((name (or (nth 2 u) (symbol-name (car u)))))
590 (if (eq (aref name 0) ?\*)
591 (setq name (substring name 1)))
ae6bc504
JB
592 (if (string-match "[^a-zA-Zα-ωΑ-Ω0-9']" name)
593 (if (string-match "^[a-zA-Zα-ωΑ-Ω0-9' ()]*$" name)
136211a9
EZ
594 (while (setq pos (string-match "[ ()]" name))
595 (setq name (concat (substring name 0 pos)
596 (if (eq (aref name pos) 32) "-" "")
597 (substring name (1+ pos)))))
598 (setq name (concat "(" name ")"))))
599 (or (eq (nth 1 expr) (car u))
600 (setq name (concat (nth 2 (assq (aref (symbol-name
601 (nth 1 expr)) 0)
602 math-unit-prefixes))
ae6bc504 603 (if (and (string-match "[^a-zA-Zα-ωΑ-Ω0-9']" name)
136211a9
EZ
604 (not (memq (car u) '(mHg gf))))
605 (concat "-" name)
606 (downcase name)))))
607 (cond ((or (math-equal-int pow 1)
608 (math-equal-int pow -1)))
609 ((or (math-equal-int pow 2)
610 (math-equal-int pow -2))
611 (if (equal (nth 4 u) '((m . 1)))
612 (setq name (concat "Square-" name))
613 (setq name (concat name "-squared"))))
614 ((or (math-equal-int pow 3)
615 (math-equal-int pow -3))
616 (if (equal (nth 4 u) '((m . 1)))
617 (setq name (concat "Cubic-" name))
618 (setq name (concat name "-cubed"))))
619 (t
620 (setq name (concat name "^"
621 (math-format-number (math-abs pow))))))
622 (if (math-posp pow)
27971241
JB
623 (setq calc-num-units (if calc-num-units
624 (concat calc-num-units " " name)
136211a9 625 name))
27971241
JB
626 (setq calc-den-units (if calc-den-units
627 (concat calc-den-units " " name)
136211a9
EZ
628 name))))
629 (cond ((eq (car-safe expr) '*)
630 (calc-explain-units-rec (nth 1 expr) pow)
631 (calc-explain-units-rec (nth 2 expr) pow))
632 ((eq (car-safe expr) '/)
633 (calc-explain-units-rec (nth 1 expr) pow)
634 (calc-explain-units-rec (nth 2 expr) (- pow)))
635 ((memq (car-safe expr) '(neg + -))
636 (calc-explain-units-rec (nth 1 expr) pow))
637 ((and (eq (car-safe expr) '^)
638 (math-realp (nth 2 expr)))
639 (calc-explain-units-rec (nth 1 expr)
c9aef719 640 (math-mul pow (nth 2 expr))))))))
136211a9
EZ
641
642(defun calc-simplify-units ()
643 (interactive)
644 (calc-slow-wrapper
645 (calc-with-default-simplification
c9aef719 646 (calc-enter-result 1 "smun" (math-simplify-units (calc-top-n 1))))))
136211a9
EZ
647
648(defun calc-view-units-table (n)
649 (interactive "P")
650 (and n (setq math-units-table-buffer-valid nil))
651 (let ((win (get-buffer-window "*Units Table*")))
652 (if (and win
653 math-units-table
654 math-units-table-buffer-valid)
655 (progn
656 (bury-buffer (window-buffer win))
657 (let ((curwin (selected-window)))
658 (select-window win)
659 (switch-to-buffer nil)
660 (select-window curwin)))
c9aef719 661 (math-build-units-table-buffer nil))))
136211a9
EZ
662
663(defun calc-enter-units-table (n)
664 (interactive "P")
665 (and n (setq math-units-table-buffer-valid nil))
666 (math-build-units-table-buffer t)
5c08522d 667 (message "%s" (substitute-command-keys "Type \\[calc] to return to the Calculator")))
136211a9 668
19bdc4d8
JB
669(defun calc-define-unit (uname desc &optional disp)
670 (interactive "SDefine unit name: \nsDescription: \nP")
671 (if disp (setq disp (read-string "Display definition: ")))
136211a9
EZ
672 (calc-wrapper
673 (let ((form (calc-top-n 1))
674 (unit (assq uname math-additional-units)))
675 (or unit
676 (setq math-additional-units
19bdc4d8 677 (cons (setq unit (list uname nil nil nil nil))
136211a9
EZ
678 math-additional-units)
679 math-units-table nil))
680 (setcar (cdr unit) (and (not (and (eq (car-safe form) 'var)
681 (eq (nth 1 form) uname)))
682 (not (math-equal-int form 1))
683 (math-format-flat-expr form 0)))
684 (setcar (cdr (cdr unit)) (and (not (equal desc ""))
19bdc4d8
JB
685 desc))
686 (if disp
687 (setcar (cdr (cdr (cdr (cdr unit)))) disp))))
c9aef719 688 (calc-invalidate-units-table))
136211a9
EZ
689
690(defun calc-undefine-unit (uname)
691 (interactive "SUndefine unit name: ")
692 (calc-wrapper
693 (let ((unit (assq uname math-additional-units)))
694 (or unit
695 (if (assq uname math-standard-units)
696 (error "\"%s\" is a predefined unit name" uname)
697 (error "Unit name \"%s\" not found" uname)))
698 (setq math-additional-units (delq unit math-additional-units)
699 math-units-table nil)))
c9aef719 700 (calc-invalidate-units-table))
136211a9
EZ
701
702(defun calc-invalidate-units-table ()
703 (setq math-units-table nil)
704 (let ((buf (get-buffer "*Units Table*")))
705 (and buf
6df9b6d7 706 (with-current-buffer buf
136211a9
EZ
707 (save-excursion
708 (goto-char (point-min))
709 (if (looking-at "Calculator Units Table")
ed8060d9 710 (let ((inhibit-read-only t))
c9aef719 711 (insert "(Obsolete) "))))))))
136211a9
EZ
712
713(defun calc-get-unit-definition (uname)
714 (interactive "SGet definition for unit: ")
715 (calc-wrapper
716 (math-build-units-table)
717 (let ((unit (assq uname math-units-table)))
718 (or unit
719 (error "Unit name \"%s\" not found" uname))
720 (let ((msg (nth 2 unit)))
721 (if (stringp msg)
722 (if (string-match "^\\*" msg)
723 (setq msg (substring msg 1)))
724 (setq msg (symbol-name uname)))
725 (if (nth 1 unit)
726 (progn
727 (calc-enter-result 0 "ugdf" (nth 1 unit))
728 (message "Derived unit: %s" msg))
729 (calc-enter-result 0 "ugdf" (list 'var uname
730 (intern
731 (concat "var-"
732 (symbol-name uname)))))
c9aef719 733 (message "Base unit: %s" msg))))))
136211a9
EZ
734
735(defun calc-permanent-units ()
736 (interactive)
737 (calc-wrapper
738 (let (pos)
739 (set-buffer (find-file-noselect (substitute-in-file-name
740 calc-settings-file)))
741 (goto-char (point-min))
742 (if (and (search-forward ";;; Custom units stored by Calc" nil t)
743 (progn
744 (beginning-of-line)
745 (setq pos (point))
746 (search-forward "\n;;; End of custom units" nil t)))
747 (progn
748 (beginning-of-line)
749 (forward-line 1)
750 (delete-region pos (point)))
751 (goto-char (point-max))
752 (insert "\n\n")
753 (forward-char -1))
754 (insert ";;; Custom units stored by Calc on " (current-time-string) "\n")
755 (if math-additional-units
756 (progn
757 (insert "(setq math-additional-units '(\n")
758 (let ((list math-additional-units))
759 (while list
760 (insert " (" (symbol-name (car (car list))) " "
761 (if (nth 1 (car list))
762 (if (stringp (nth 1 (car list)))
763 (prin1-to-string (nth 1 (car list)))
764 (prin1-to-string (math-format-flat-expr
765 (nth 1 (car list)) 0)))
766 "nil")
767 " "
768 (prin1-to-string (nth 2 (car list)))
769 ")\n")
770 (setq list (cdr list))))
771 (insert "))\n"))
772 (insert ";;; (no custom units defined)\n"))
773 (insert ";;; End of custom units\n")
c9aef719 774 (save-buffer))))
136211a9
EZ
775
776
27971241
JB
777;; The variable math-cu-unit-list is local to math-build-units-table,
778;; but is used by math-compare-unit-names, which is called (indirectly)
779;; by math-build-units-table.
780;; math-cu-unit-list is also local to math-convert-units, but is used
781;; by math-convert-units-rec, which is called by math-convert-units.
782(defvar math-cu-unit-list)
136211a9 783
136211a9
EZ
784(defun math-build-units-table ()
785 (or math-units-table
786 (let* ((combined-units (append math-additional-units
787 math-standard-units))
27971241 788 (math-cu-unit-list (mapcar 'car combined-units))
136211a9
EZ
789 tab)
790 (message "Building units table...")
791 (setq math-units-table-buffer-valid nil)
792 (setq tab (mapcar (function
793 (lambda (x)
794 (list (car x)
795 (and (nth 1 x)
796 (if (stringp (nth 1 x))
797 (let ((exp (math-read-plain-expr
798 (nth 1 x))))
799 (if (eq (car-safe exp) 'error)
800 (error "Format error in definition of %s in units table: %s"
801 (car x) (nth 2 exp))
802 exp))
803 (nth 1 x)))
804 (nth 2 x)
805 (nth 3 x)
806 (and (not (nth 1 x))
19bdc4d8
JB
807 (list (cons (car x) 1)))
808 (nth 4 x))))
136211a9
EZ
809 combined-units))
810 (let ((math-units-table tab))
09040c8d 811 (mapc 'math-find-base-units tab))
136211a9 812 (message "Building units table...done")
c9aef719 813 (setq math-units-table tab))))
136211a9 814
27971241
JB
815;; The variables math-fbu-base and math-fbu-entry are local to
816;; math-find-base-units, but are used by math-find-base-units-rec,
817;; which is called by math-find-base-units.
818(defvar math-fbu-base)
819(defvar math-fbu-entry)
820
3effaa28
JB
821(defun math-find-base-units (math-fbu-entry)
822 (if (eq (nth 4 math-fbu-entry) 'boom)
823 (error "Circular definition involving unit %s" (car math-fbu-entry)))
824 (or (nth 4 math-fbu-entry)
825 (let (math-fbu-base)
826 (setcar (nthcdr 4 math-fbu-entry) 'boom)
827 (math-find-base-units-rec (nth 1 math-fbu-entry) 1)
828 '(or math-fbu-base
829 (error "Dimensionless definition for unit %s" (car math-fbu-entry)))
830 (while (eq (cdr (car math-fbu-base)) 0)
831 (setq math-fbu-base (cdr math-fbu-base)))
832 (let ((b math-fbu-base))
136211a9
EZ
833 (while (cdr b)
834 (if (eq (cdr (car (cdr b))) 0)
835 (setcdr b (cdr (cdr b)))
836 (setq b (cdr b)))))
3effaa28
JB
837 (setq math-fbu-base (sort math-fbu-base 'math-compare-unit-names))
838 (setcar (nthcdr 4 math-fbu-entry) math-fbu-base)
839 math-fbu-base)))
136211a9
EZ
840
841(defun math-compare-unit-names (a b)
27971241 842 (memq (car b) (cdr (memq (car a) math-cu-unit-list))))
136211a9
EZ
843
844(defun math-find-base-units-rec (expr pow)
845 (let ((u (math-check-unit-name expr)))
846 (cond (u
847 (let ((ulist (math-find-base-units u)))
848 (while ulist
849 (let ((p (* (cdr (car ulist)) pow))
3effaa28 850 (old (assq (car (car ulist)) math-fbu-base)))
136211a9
EZ
851 (if old
852 (setcdr old (+ (cdr old) p))
09040c8d 853 (setq math-fbu-base
3effaa28 854 (cons (cons (car (car ulist)) p) math-fbu-base))))
136211a9
EZ
855 (setq ulist (cdr ulist)))))
856 ((math-scalarp expr))
857 ((and (eq (car expr) '^)
858 (integerp (nth 2 expr)))
859 (math-find-base-units-rec (nth 1 expr) (* pow (nth 2 expr))))
860 ((eq (car expr) '*)
861 (math-find-base-units-rec (nth 1 expr) pow)
862 (math-find-base-units-rec (nth 2 expr) pow))
863 ((eq (car expr) '/)
864 (math-find-base-units-rec (nth 1 expr) pow)
865 (math-find-base-units-rec (nth 2 expr) (- pow)))
866 ((eq (car expr) 'neg)
867 (math-find-base-units-rec (nth 1 expr) pow))
868 ((eq (car expr) '+)
869 (math-find-base-units-rec (nth 1 expr) pow))
870 ((eq (car expr) 'var)
871 (or (eq (nth 1 expr) 'pi)
872 (error "Unknown name %s in defining expression for unit %s"
3effaa28
JB
873 (nth 1 expr) (car math-fbu-entry))))
874 (t (error "Malformed defining expression for unit %s" (car math-fbu-entry))))))
136211a9
EZ
875
876
877(defun math-units-in-expr-p (expr sub-exprs)
878 (and (consp expr)
879 (if (eq (car expr) 'var)
880 (math-check-unit-name expr)
881 (and (or sub-exprs
882 (memq (car expr) '(* / ^)))
883 (or (math-units-in-expr-p (nth 1 expr) sub-exprs)
c9aef719 884 (math-units-in-expr-p (nth 2 expr) sub-exprs))))))
136211a9
EZ
885
886(defun math-only-units-in-expr-p (expr)
887 (and (consp expr)
888 (if (eq (car expr) 'var)
889 (math-check-unit-name expr)
890 (if (memq (car expr) '(* /))
891 (and (math-only-units-in-expr-p (nth 1 expr))
892 (math-only-units-in-expr-p (nth 2 expr)))
893 (and (eq (car expr) '^)
894 (and (math-only-units-in-expr-p (nth 1 expr))
c9aef719 895 (math-realp (nth 2 expr))))))))
136211a9
EZ
896
897(defun math-single-units-in-expr-p (expr)
898 (cond ((math-scalarp expr) nil)
899 ((eq (car expr) 'var)
900 (math-check-unit-name expr))
901 ((eq (car expr) '*)
902 (let ((u1 (math-single-units-in-expr-p (nth 1 expr)))
903 (u2 (math-single-units-in-expr-p (nth 2 expr))))
904 (or (and u1 u2 'wrong)
905 u1
906 u2)))
907 ((eq (car expr) '/)
908 (if (math-units-in-expr-p (nth 2 expr) nil)
909 'wrong
910 (math-single-units-in-expr-p (nth 1 expr))))
c9aef719 911 (t 'wrong)))
136211a9
EZ
912
913(defun math-check-unit-name (v)
914 (and (eq (car-safe v) 'var)
915 (or (assq (nth 1 v) (or math-units-table (math-build-units-table)))
916 (let ((name (symbol-name (nth 1 v))))
917 (and (> (length name) 1)
918 (assq (aref name 0) math-unit-prefixes)
919 (or (assq (intern (substring name 1)) math-units-table)
920 (and (eq (aref name 0) ?M)
921 (> (length name) 3)
922 (eq (aref name 1) ?e)
923 (eq (aref name 2) ?g)
924 (assq (intern (substring name 3))
c9aef719 925 math-units-table))))))))
136211a9 926
27971241
JB
927;; The variable math-which-standard is local to math-to-standard-units,
928;; but is used by math-to-standard-rec, which is called by
929;; math-to-standard-units.
930(defvar math-which-standard)
136211a9 931
27971241 932(defun math-to-standard-units (expr math-which-standard)
c9aef719 933 (math-to-standard-rec expr))
136211a9
EZ
934
935(defun math-to-standard-rec (expr)
936 (if (eq (car-safe expr) 'var)
937 (let ((u (math-check-unit-name expr))
938 (base (nth 1 expr)))
939 (if u
940 (progn
941 (if (nth 1 u)
942 (setq expr (math-to-standard-rec (nth 1 u)))
27971241 943 (let ((st (assq (car u) math-which-standard)))
136211a9
EZ
944 (if st
945 (setq expr (nth 1 st))
946 (setq expr (list 'var (car u)
947 (intern (concat "var-"
948 (symbol-name
949 (car u)))))))))
950 (or (null u)
951 (eq base (car u))
952 (setq expr (list '*
953 (nth 1 (assq (aref (symbol-name base) 0)
954 math-unit-prefixes))
955 expr)))
956 expr)
957 (if (eq base 'pi)
958 (math-pi)
959 expr)))
960 (if (Math-primp expr)
961 expr
962 (cons (car expr)
c9aef719 963 (mapcar 'math-to-standard-rec (cdr expr))))))
136211a9
EZ
964
965(defun math-apply-units (expr units ulist &optional pure)
2e2b4fbe 966 (setq expr (math-simplify-units expr))
136211a9
EZ
967 (if ulist
968 (let ((new 0)
969 value)
136211a9
EZ
970 (or (math-numberp expr)
971 (error "Incompatible units"))
972 (while (cdr ulist)
973 (setq value (math-div expr (nth 1 (car ulist)))
974 value (math-floor (let ((calc-internal-prec
975 (1- calc-internal-prec)))
976 (math-normalize value)))
977 new (math-add new (math-mul value (car (car ulist))))
978 expr (math-sub expr (math-mul value (nth 1 (car ulist))))
979 ulist (cdr ulist)))
980 (math-add new (math-mul (math-div expr (nth 1 (car ulist)))
981 (car (car ulist)))))
2e2b4fbe
JB
982 (if pure
983 expr
984 (math-simplify-units (list '* expr units)))))
136211a9 985
8cd8ee52 986(defvar math-decompose-units-cache nil)
136211a9
EZ
987(defun math-decompose-units (units)
988 (let ((u (math-check-unit-name units)))
989 (and u (eq (car-safe (nth 1 u)) '+)
990 (setq units (nth 1 u))))
991 (setq units (calcFunc-expand units))
992 (and (eq (car-safe units) '+)
993 (let ((entry (list units calc-internal-prec calc-prefer-frac)))
994 (or (equal entry (car math-decompose-units-cache))
995 (let ((ulist nil)
996 (utemp units)
997 qty unit)
998 (while (eq (car-safe utemp) '+)
999 (setq ulist (cons (math-decompose-unit-part (nth 2 utemp))
1000 ulist)
1001 utemp (nth 1 utemp)))
1002 (setq ulist (cons (math-decompose-unit-part utemp) ulist)
1003 utemp ulist)
1004 (while (setq utemp (cdr utemp))
8cd8ee52
CW
1005 (unless (equal (nth 2 (car utemp)) (nth 2 (car ulist)))
1006 (error "Inconsistent units in sum")))
136211a9
EZ
1007 (setq math-decompose-units-cache
1008 (cons entry
1009 (sort ulist
1010 (function
1011 (lambda (x y)
1012 (not (Math-lessp (nth 1 x)
1013 (nth 1 y))))))))))
c9aef719 1014 (cdr math-decompose-units-cache))))
136211a9
EZ
1015
1016(defun math-decompose-unit-part (unit)
1017 (cons unit
1018 (math-is-multiple (math-simplify-units (math-to-standard-units
1019 unit nil))
c9aef719 1020 t)))
136211a9 1021
27971241
JB
1022;; The variable math-fcu-u is local to math-find-compatible-unit,
1023;; but is used by math-find-compatible-rec which is called by
1024;; math-find-compatible-unit.
1025(defvar math-fcu-u)
1026
136211a9 1027(defun math-find-compatible-unit (expr unit)
27971241
JB
1028 (let ((math-fcu-u (math-check-unit-name unit)))
1029 (if math-fcu-u
c9aef719 1030 (math-find-compatible-unit-rec expr 1))))
136211a9
EZ
1031
1032(defun math-find-compatible-unit-rec (expr pow)
1033 (cond ((eq (car-safe expr) '*)
1034 (or (math-find-compatible-unit-rec (nth 1 expr) pow)
1035 (math-find-compatible-unit-rec (nth 2 expr) pow)))
1036 ((eq (car-safe expr) '/)
1037 (or (math-find-compatible-unit-rec (nth 1 expr) pow)
1038 (math-find-compatible-unit-rec (nth 2 expr) (- pow))))
1039 ((and (eq (car-safe expr) '^)
1040 (integerp (nth 2 expr)))
1041 (math-find-compatible-unit-rec (nth 1 expr) (* pow (nth 2 expr))))
1042 (t
1043 (let ((u2 (math-check-unit-name expr)))
27971241 1044 (if (equal (nth 4 math-fcu-u) (nth 4 u2))
c9aef719 1045 (cons expr pow))))))
136211a9 1046
09040c8d
JB
1047;; The variables math-cu-new-units and math-cu-pure are local to
1048;; math-convert-units, but are used by math-convert-units-rec,
27971241
JB
1049;; which is called by math-convert-units.
1050(defvar math-cu-new-units)
1051(defvar math-cu-pure)
1052
1053(defun math-convert-units (expr math-cu-new-units &optional math-cu-pure)
65b62d0a
JB
1054 (if (eq (car-safe math-cu-new-units) 'var)
1055 (let ((unew (assq (nth 1 math-cu-new-units)
1056 (math-build-units-table))))
1057 (if (eq (car-safe (nth 1 unew)) '+)
1058 (setq math-cu-new-units (nth 1 unew)))))
136211a9 1059 (math-with-extra-prec 2
09040c8d 1060 (let ((compat (and (not math-cu-pure)
27971241
JB
1061 (math-find-compatible-unit expr math-cu-new-units)))
1062 (math-cu-unit-list nil)
136211a9
EZ
1063 (math-combining-units nil))
1064 (if compat
1065 (math-simplify-units
1066 (math-mul (math-mul (math-simplify-units
1067 (math-div expr (math-pow (car compat)
1068 (cdr compat))))
27971241 1069 (math-pow math-cu-new-units (cdr compat)))
136211a9
EZ
1070 (math-simplify-units
1071 (math-to-standard-units
27971241 1072 (math-pow (math-div (car compat) math-cu-new-units)
136211a9
EZ
1073 (cdr compat))
1074 nil))))
27971241
JB
1075 (when (setq math-cu-unit-list (math-decompose-units math-cu-new-units))
1076 (setq math-cu-new-units (nth 2 (car math-cu-unit-list))))
8cd8ee52
CW
1077 (when (eq (car-safe expr) '+)
1078 (setq expr (math-simplify-units expr)))
136211a9
EZ
1079 (if (math-units-in-expr-p expr t)
1080 (math-convert-units-rec expr)
1081 (math-apply-units (math-to-standard-units
27971241
JB
1082 (list '/ expr math-cu-new-units) nil)
1083 math-cu-new-units math-cu-unit-list math-cu-pure))))))
136211a9
EZ
1084
1085(defun math-convert-units-rec (expr)
1086 (if (math-units-in-expr-p expr nil)
09040c8d 1087 (math-apply-units (math-to-standard-units
27971241
JB
1088 (list '/ expr math-cu-new-units) nil)
1089 math-cu-new-units math-cu-unit-list math-cu-pure)
136211a9
EZ
1090 (if (Math-primp expr)
1091 expr
1092 (cons (car expr)
c9aef719 1093 (mapcar 'math-convert-units-rec (cdr expr))))))
136211a9
EZ
1094
1095(defun math-convert-temperature (expr old new &optional pure)
1096 (let* ((units (math-single-units-in-expr-p expr))
1097 (uold (if old
1098 (if (or (null units)
1099 (equal (nth 1 old) (car units)))
1100 (math-check-unit-name old)
1101 (error "Inconsistent temperature units"))
1102 units))
1103 (unew (math-check-unit-name new)))
8cd8ee52
CW
1104 (unless (and (consp unew) (nth 3 unew))
1105 (error "Not a valid temperature unit"))
1106 (unless (and (consp uold) (nth 3 uold))
1107 (error "Not a pure temperature expression"))
136211a9
EZ
1108 (let ((v (car uold)))
1109 (setq expr (list '/ expr (list 'var v
1110 (intern (concat "var-"
1111 (symbol-name v)))))))
1112 (or (eq (nth 3 uold) (nth 3 unew))
1113 (cond ((eq (nth 3 uold) 'K)
e6cd99dc 1114 (setq expr (list '- expr '(/ 27315 100)))
136211a9 1115 (if (eq (nth 3 unew) 'F)
e6cd99dc 1116 (setq expr (list '+ (list '* expr '(/ 9 5)) 32))))
136211a9
EZ
1117 ((eq (nth 3 uold) 'C)
1118 (if (eq (nth 3 unew) 'F)
e6cd99dc
JB
1119 (setq expr (list '+ (list '* expr '(/ 9 5)) 32))
1120 (setq expr (list '+ expr '(/ 27315 100)))))
136211a9 1121 (t
e6cd99dc 1122 (setq expr (list '* (list '- expr 32) '(/ 5 9)))
136211a9 1123 (if (eq (nth 3 unew) 'K)
e6cd99dc 1124 (setq expr (list '+ expr '(/ 27315 100)))))))
136211a9
EZ
1125 (if pure
1126 expr
c9aef719 1127 (list '* expr new))))
136211a9
EZ
1128
1129
1130
1131(defun math-simplify-units (a)
1132 (let ((math-simplifying-units t)
1133 (calc-matrix-mode 'scalar))
c9aef719 1134 (math-simplify a)))
8cd8ee52 1135(defalias 'calcFunc-usimplify 'math-simplify-units)
136211a9 1136
f095c6c9
JB
1137;; The function created by math-defsimplify uses the variable
1138;; math-simplify-expr, and so is used by functions in math-defsimplify
1139(defvar math-simplify-expr)
1140
136211a9
EZ
1141(math-defsimplify (+ -)
1142 (and math-simplifying-units
f095c6c9
JB
1143 (math-units-in-expr-p (nth 1 math-simplify-expr) nil)
1144 (let* ((units (math-extract-units (nth 1 math-simplify-expr)))
136211a9 1145 (ratio (math-simplify (math-to-standard-units
f095c6c9 1146 (list '/ (nth 2 math-simplify-expr) units) nil))))
136211a9
EZ
1147 (if (math-units-in-expr-p ratio nil)
1148 (progn
f095c6c9
JB
1149 (calc-record-why "*Inconsistent units" math-simplify-expr)
1150 math-simplify-expr)
1151 (list '* (math-add (math-remove-units (nth 1 math-simplify-expr))
09040c8d 1152 (if (eq (car math-simplify-expr) '-)
f095c6c9 1153 (math-neg ratio) ratio))
c9aef719 1154 units)))))
136211a9
EZ
1155
1156(math-defsimplify *
c9aef719 1157 (math-simplify-units-prod))
136211a9
EZ
1158
1159(defun math-simplify-units-prod ()
1160 (and math-simplifying-units
1161 calc-autorange-units
f095c6c9
JB
1162 (Math-realp (nth 1 math-simplify-expr))
1163 (let* ((num (math-float (nth 1 math-simplify-expr)))
136211a9 1164 (xpon (calcFunc-xpon num))
f095c6c9 1165 (unitp (cdr (cdr math-simplify-expr)))
136211a9 1166 (unit (car unitp))
f095c6c9 1167 (pow (if (eq (car math-simplify-expr) '*) 1 -1))
136211a9
EZ
1168 u)
1169 (and (eq (car-safe unit) '*)
1170 (setq unitp (cdr unit)
1171 unit (car unitp)))
1172 (and (eq (car-safe unit) '^)
1173 (integerp (nth 2 unit))
1174 (setq pow (* pow (nth 2 unit))
1175 unitp (cdr unit)
1176 unit (car unitp)))
1177 (and (setq u (math-check-unit-name unit))
1178 (integerp xpon)
1179 (or (< xpon 0)
1180 (>= xpon (if (eq (car u) 'm) 1 3)))
1181 (let* ((uxpon 0)
1182 (pref (if (< pow 0)
1183 (reverse math-unit-prefixes)
1184 math-unit-prefixes))
1185 (p pref)
1186 pxpon pname)
1187 (or (eq (car u) (nth 1 unit))
1188 (setq uxpon (* pow
1189 (nth 2 (nth 1 (assq
1190 (aref (symbol-name
1191 (nth 1 unit)) 0)
1192 math-unit-prefixes))))))
1193 (setq xpon (+ xpon uxpon))
1194 (while (and p
1195 (or (memq (car (car p)) '(?d ?D ?h ?H))
1196 (and (eq (car (car p)) ?c)
1197 (not (eq (car u) 'm)))
1198 (< xpon (setq pxpon (* (nth 2 (nth 1 (car p)))
1199 pow)))
1200 (progn
1201 (setq pname (math-build-var-name
1202 (if (eq (car (car p)) 0)
1203 (car u)
1204 (concat (char-to-string
1205 (car (car p)))
1206 (symbol-name
1207 (car u))))))
1208 (and (/= (car (car p)) 0)
1209 (assq (nth 1 pname)
1210 math-units-table)))))
1211 (setq p (cdr p)))
1212 (and p
1213 (/= pxpon uxpon)
1214 (or (not (eq p pref))
1215 (< xpon (+ pxpon (* (math-abs pow) 3))))
1216 (progn
f095c6c9 1217 (setcar (cdr math-simplify-expr)
136211a9 1218 (let ((calc-prefer-frac nil))
f095c6c9 1219 (calcFunc-scf (nth 1 math-simplify-expr)
136211a9
EZ
1220 (- uxpon pxpon))))
1221 (setcar unitp pname)
f095c6c9 1222 math-simplify-expr)))))))
136211a9 1223
27971241
JB
1224(defvar math-try-cancel-units)
1225
136211a9
EZ
1226(math-defsimplify /
1227 (and math-simplifying-units
f095c6c9 1228 (let ((np (cdr math-simplify-expr))
27971241 1229 (math-try-cancel-units 0)
136211a9 1230 n nn)
f095c6c9
JB
1231 (setq n (if (eq (car-safe (nth 2 math-simplify-expr)) '*)
1232 (cdr (nth 2 math-simplify-expr))
1233 (nthcdr 2 math-simplify-expr)))
136211a9
EZ
1234 (if (math-realp (car n))
1235 (progn
f095c6c9 1236 (setcar (cdr math-simplify-expr) (math-mul (nth 1 math-simplify-expr)
136211a9
EZ
1237 (let ((calc-prefer-frac nil))
1238 (math-div 1 (car n)))))
1239 (setcar n 1)))
1240 (while (eq (car-safe (setq n (car np))) '*)
f095c6c9 1241 (math-simplify-units-divisor (cdr n) (cdr (cdr math-simplify-expr)))
136211a9 1242 (setq np (cdr (cdr n))))
f095c6c9 1243 (math-simplify-units-divisor np (cdr (cdr math-simplify-expr)))
27971241 1244 (if (eq math-try-cancel-units 0)
136211a9 1245 (let* ((math-simplifying-units nil)
09040c8d 1246 (base (math-simplify
f095c6c9 1247 (math-to-standard-units math-simplify-expr nil))))
136211a9 1248 (if (Math-numberp base)
f095c6c9
JB
1249 (setq math-simplify-expr base))))
1250 (if (eq (car-safe math-simplify-expr) '/)
136211a9 1251 (math-simplify-units-prod))
f095c6c9 1252 math-simplify-expr)))
136211a9
EZ
1253
1254(defun math-simplify-units-divisor (np dp)
1255 (let ((n (car np))
1256 d dd temp)
1257 (while (eq (car-safe (setq d (car dp))) '*)
8cd8ee52
CW
1258 (when (setq temp (math-simplify-units-quotient n (nth 1 d)))
1259 (setcar np (setq n temp))
1260 (setcar (cdr d) 1))
136211a9 1261 (setq dp (cdr (cdr d))))
8cd8ee52
CW
1262 (when (setq temp (math-simplify-units-quotient n d))
1263 (setcar np (setq n temp))
1264 (setcar dp 1))))
136211a9
EZ
1265
1266;; Simplify, e.g., "in / cm" to "2.54" in a units expression.
1267(defun math-simplify-units-quotient (n d)
1268 (let ((pow1 1)
1269 (pow2 1))
8cd8ee52
CW
1270 (when (and (eq (car-safe n) '^)
1271 (integerp (nth 2 n)))
1272 (setq pow1 (nth 2 n) n (nth 1 n)))
1273 (when (and (eq (car-safe d) '^)
1274 (integerp (nth 2 d)))
1275 (setq pow2 (nth 2 d) d (nth 1 d)))
136211a9
EZ
1276 (let ((un (math-check-unit-name n))
1277 (ud (math-check-unit-name d)))
1278 (and un ud
1279 (if (and (equal (nth 4 un) (nth 4 ud))
1280 (eq pow1 pow2))
0317ca78
JB
1281 (if (eq pow1 1)
1282 (math-to-standard-units (list '/ n d) nil)
1283 (list '^ (math-to-standard-units (list '/ n d) nil) pow1))
136211a9
EZ
1284 (let (ud1)
1285 (setq un (nth 4 un)
1286 ud (nth 4 ud))
1287 (while un
1288 (setq ud1 ud)
1289 (while ud1
1290 (and (eq (car (car un)) (car (car ud1)))
27971241
JB
1291 (setq math-try-cancel-units
1292 (+ math-try-cancel-units
136211a9
EZ
1293 (- (* (cdr (car un)) pow1)
1294 (* (cdr (car ud)) pow2)))))
1295 (setq ud1 (cdr ud1)))
1296 (setq un (cdr un)))
c9aef719 1297 nil))))))
136211a9
EZ
1298
1299(math-defsimplify ^
1300 (and math-simplifying-units
f095c6c9
JB
1301 (math-realp (nth 2 math-simplify-expr))
1302 (if (memq (car-safe (nth 1 math-simplify-expr)) '(* /))
1303 (list (car (nth 1 math-simplify-expr))
09040c8d 1304 (list '^ (nth 1 (nth 1 math-simplify-expr))
f095c6c9 1305 (nth 2 math-simplify-expr))
09040c8d 1306 (list '^ (nth 2 (nth 1 math-simplify-expr))
f095c6c9 1307 (nth 2 math-simplify-expr)))
09040c8d 1308 (math-simplify-units-pow (nth 1 math-simplify-expr)
f095c6c9 1309 (nth 2 math-simplify-expr)))))
136211a9
EZ
1310
1311(math-defsimplify calcFunc-sqrt
1312 (and math-simplifying-units
f095c6c9
JB
1313 (if (memq (car-safe (nth 1 math-simplify-expr)) '(* /))
1314 (list (car (nth 1 math-simplify-expr))
1315 (list 'calcFunc-sqrt (nth 1 (nth 1 math-simplify-expr)))
1316 (list 'calcFunc-sqrt (nth 2 (nth 1 math-simplify-expr))))
1317 (math-simplify-units-pow (nth 1 math-simplify-expr) '(frac 1 2)))))
136211a9
EZ
1318
1319(math-defsimplify (calcFunc-floor
1320 calcFunc-ceil
1321 calcFunc-round
1322 calcFunc-rounde
1323 calcFunc-roundu
1324 calcFunc-trunc
1325 calcFunc-float
1326 calcFunc-frac
1327 calcFunc-abs
1328 calcFunc-clean)
1329 (and math-simplifying-units
f095c6c9
JB
1330 (= (length math-simplify-expr) 2)
1331 (if (math-only-units-in-expr-p (nth 1 math-simplify-expr))
1332 (nth 1 math-simplify-expr)
1333 (if (and (memq (car-safe (nth 1 math-simplify-expr)) '(* /))
136211a9 1334 (or (math-only-units-in-expr-p
f095c6c9 1335 (nth 1 (nth 1 math-simplify-expr)))
136211a9 1336 (math-only-units-in-expr-p
f095c6c9
JB
1337 (nth 2 (nth 1 math-simplify-expr)))))
1338 (list (car (nth 1 math-simplify-expr))
1339 (cons (car math-simplify-expr)
1340 (cons (nth 1 (nth 1 math-simplify-expr))
1341 (cdr (cdr math-simplify-expr))))
1342 (cons (car math-simplify-expr)
1343 (cons (nth 2 (nth 1 math-simplify-expr))
1344 (cdr (cdr math-simplify-expr)))))))))
136211a9
EZ
1345
1346(defun math-simplify-units-pow (a pow)
1347 (if (and (eq (car-safe a) '^)
1348 (math-check-unit-name (nth 1 a))
1349 (math-realp (nth 2 a)))
1350 (list '^ (nth 1 a) (math-mul pow (nth 2 a)))
1351 (let* ((u (math-check-unit-name a))
1352 (pf (math-to-simple-fraction pow))
1353 (d (and (eq (car-safe pf) 'frac) (nth 2 pf))))
1354 (and u d
1355 (math-units-are-multiple u d)
c9aef719 1356 (list '^ (math-to-standard-units a nil) pow)))))
136211a9
EZ
1357
1358
1359(defun math-units-are-multiple (u n)
1360 (setq u (nth 4 u))
1361 (while (and u (= (% (cdr (car u)) n) 0))
1362 (setq u (cdr u)))
c9aef719 1363 (null u))
136211a9
EZ
1364
1365(math-defsimplify calcFunc-sin
1366 (and math-simplifying-units
f095c6c9 1367 (math-units-in-expr-p (nth 1 math-simplify-expr) nil)
136211a9
EZ
1368 (let ((rad (math-simplify-units
1369 (math-evaluate-expr
f095c6c9 1370 (math-to-standard-units (nth 1 math-simplify-expr) nil))))
136211a9
EZ
1371 (calc-angle-mode 'rad))
1372 (and (eq (car-safe rad) '*)
1373 (math-realp (nth 1 rad))
1374 (eq (car-safe (nth 2 rad)) 'var)
1375 (eq (nth 1 (nth 2 rad)) 'rad)
c9aef719 1376 (list 'calcFunc-sin (nth 1 rad))))))
136211a9
EZ
1377
1378(math-defsimplify calcFunc-cos
1379 (and math-simplifying-units
f095c6c9 1380 (math-units-in-expr-p (nth 1 math-simplify-expr) nil)
136211a9
EZ
1381 (let ((rad (math-simplify-units
1382 (math-evaluate-expr
f095c6c9 1383 (math-to-standard-units (nth 1 math-simplify-expr) nil))))
136211a9
EZ
1384 (calc-angle-mode 'rad))
1385 (and (eq (car-safe rad) '*)
1386 (math-realp (nth 1 rad))
1387 (eq (car-safe (nth 2 rad)) 'var)
1388 (eq (nth 1 (nth 2 rad)) 'rad)
c9aef719 1389 (list 'calcFunc-cos (nth 1 rad))))))
136211a9
EZ
1390
1391(math-defsimplify calcFunc-tan
1392 (and math-simplifying-units
f095c6c9 1393 (math-units-in-expr-p (nth 1 math-simplify-expr) nil)
136211a9
EZ
1394 (let ((rad (math-simplify-units
1395 (math-evaluate-expr
f095c6c9 1396 (math-to-standard-units (nth 1 math-simplify-expr) nil))))
136211a9
EZ
1397 (calc-angle-mode 'rad))
1398 (and (eq (car-safe rad) '*)
1399 (math-realp (nth 1 rad))
1400 (eq (car-safe (nth 2 rad)) 'var)
1401 (eq (nth 1 (nth 2 rad)) 'rad)
c9aef719 1402 (list 'calcFunc-tan (nth 1 rad))))))
136211a9 1403
40b444ac
JB
1404(math-defsimplify calcFunc-sec
1405 (and math-simplifying-units
1406 (math-units-in-expr-p (nth 1 math-simplify-expr) nil)
1407 (let ((rad (math-simplify-units
1408 (math-evaluate-expr
1409 (math-to-standard-units (nth 1 math-simplify-expr) nil))))
1410 (calc-angle-mode 'rad))
1411 (and (eq (car-safe rad) '*)
1412 (math-realp (nth 1 rad))
1413 (eq (car-safe (nth 2 rad)) 'var)
1414 (eq (nth 1 (nth 2 rad)) 'rad)
1415 (list 'calcFunc-sec (nth 1 rad))))))
1416
1417(math-defsimplify calcFunc-csc
1418 (and math-simplifying-units
1419 (math-units-in-expr-p (nth 1 math-simplify-expr) nil)
1420 (let ((rad (math-simplify-units
1421 (math-evaluate-expr
1422 (math-to-standard-units (nth 1 math-simplify-expr) nil))))
1423 (calc-angle-mode 'rad))
1424 (and (eq (car-safe rad) '*)
1425 (math-realp (nth 1 rad))
1426 (eq (car-safe (nth 2 rad)) 'var)
1427 (eq (nth 1 (nth 2 rad)) 'rad)
1428 (list 'calcFunc-csc (nth 1 rad))))))
1429
1430(math-defsimplify calcFunc-cot
1431 (and math-simplifying-units
1432 (math-units-in-expr-p (nth 1 math-simplify-expr) nil)
1433 (let ((rad (math-simplify-units
1434 (math-evaluate-expr
1435 (math-to-standard-units (nth 1 math-simplify-expr) nil))))
1436 (calc-angle-mode 'rad))
1437 (and (eq (car-safe rad) '*)
1438 (math-realp (nth 1 rad))
1439 (eq (car-safe (nth 2 rad)) 'var)
1440 (eq (nth 1 (nth 2 rad)) 'rad)
1441 (list 'calcFunc-cot (nth 1 rad))))))
1442
136211a9
EZ
1443
1444(defun math-remove-units (expr)
1445 (if (math-check-unit-name expr)
1446 1
1447 (if (Math-primp expr)
1448 expr
1449 (cons (car expr)
c9aef719 1450 (mapcar 'math-remove-units (cdr expr))))))
136211a9
EZ
1451
1452(defun math-extract-units (expr)
1453 (if (memq (car-safe expr) '(* /))
1454 (cons (car expr)
1455 (mapcar 'math-extract-units (cdr expr)))
c9aef719 1456 (if (math-check-unit-name expr) expr 1)))
136211a9
EZ
1457
1458(defun math-build-units-table-buffer (enter-buffer)
1459 (if (not (and math-units-table math-units-table-buffer-valid
1460 (get-buffer "*Units Table*")))
1461 (let ((buf (get-buffer-create "*Units Table*"))
1462 (uptr (math-build-units-table))
1463 (calc-language (if (eq calc-language 'big) nil calc-language))
1464 (calc-float-format '(float 0))
1465 (calc-group-digits nil)
1466 (calc-number-radix 10)
7b999abb 1467 (calc-twos-complement-mode nil)
136211a9
EZ
1468 (calc-point-char ".")
1469 (std nil)
1470 u name shadowed)
1471 (save-excursion
1472 (message "Formatting units table...")
1473 (set-buffer buf)
ed8060d9
JB
1474 (let ((inhibit-read-only t))
1475 (erase-buffer)
1476 (insert "Calculator Units Table:\n\n")
ac318df0 1477 (insert "(All definitions are exact unless marked with an asterisk (*).)\n\n")
ed8060d9
JB
1478 (insert "Unit Type Definition Description\n\n")
1479 (while uptr
1480 (setq u (car uptr)
1481 name (nth 2 u))
1482 (when (eq (car u) 'm)
1483 (setq std t))
1484 (setq shadowed (and std (assq (car u) math-additional-units)))
1485 (when (and name
1486 (> (length name) 1)
1487 (eq (aref name 0) ?\*))
1488 (unless (eq uptr math-units-table)
1489 (insert "\n"))
1490 (setq name (substring name 1)))
1491 (insert " ")
1492 (and shadowed (insert "("))
1493 (insert (symbol-name (car u)))
1494 (and shadowed (insert ")"))
1495 (if (nth 3 u)
1496 (progn
1497 (indent-to 10)
1498 (insert (symbol-name (nth 3 u))))
1499 (or std
1500 (progn
1501 (indent-to 10)
1502 (insert "U"))))
1503 (indent-to 14)
1504 (and shadowed (insert "("))
19bdc4d8
JB
1505 (if (nth 5 u)
1506 (insert (nth 5 u))
1507 (if (nth 1 u)
1508 (insert (math-format-value (nth 1 u) 80))
1509 (insert (symbol-name (car u)))))
ed8060d9
JB
1510 (and shadowed (insert ")"))
1511 (indent-to 41)
1512 (insert " ")
1513 (when name
1514 (insert name))
1515 (if shadowed
1516 (insert " (redefined above)")
1517 (unless (nth 1 u)
1518 (insert " (base unit)")))
1519 (insert "\n")
1520 (setq uptr (cdr uptr)))
1521 (insert "\n\nUnit Prefix Table:\n\n")
1522 (setq uptr math-unit-prefixes)
1523 (while uptr
1524 (setq u (car uptr))
1525 (insert " " (char-to-string (car u)))
1526 (if (equal (nth 1 u) (nth 1 (nth 1 uptr)))
1527 (insert " " (char-to-string (car (car (setq uptr (cdr uptr)))))
1528 " ")
1529 (insert " "))
1530 (insert "10^" (int-to-string (nth 2 (nth 1 u))))
1531 (indent-to 15)
1532 (insert " " (nth 2 u) "\n")
1533 (while (eq (car (car (setq uptr (cdr uptr)))) 0)))
1265829e
JB
1534 (insert "\n\n")
1535 (insert "(**) When in TeX or LaTeX display mode, the TeX specific unit\n"
1536 "names will not use the `tex' prefix; the unit name for a\n"
1537 "TeX point will be `pt' instead of `texpt', for example.\n"
1538 "To avoid conflicts, the unit names for pint and parsec will\n"
1539 "be `pint' and `parsec' instead of `pt' and `pc'."))
ed8060d9 1540 (view-mode)
136211a9
EZ
1541 (message "Formatting units table...done"))
1542 (setq math-units-table-buffer-valid t)
1543 (let ((oldbuf (current-buffer)))
1544 (set-buffer buf)
1545 (goto-char (point-min))
1546 (set-buffer oldbuf))
1547 (if enter-buffer
1548 (pop-to-buffer buf)
1549 (display-buffer buf)))
1550 (if enter-buffer
1551 (pop-to-buffer (get-buffer "*Units Table*"))
c9aef719 1552 (display-buffer (get-buffer "*Units Table*")))))
136211a9 1553
7d02e8cd
JB
1554(provide 'calc-units)
1555
be19ef0b
GM
1556;; Local variables:
1557;; coding: utf-8
1558;; End:
1559
c9aef719 1560;;; calc-units.el ends here