(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)
(list '^ (math-extract-logunits (nth 1 expr)) (nth 2 expr))
(if (member expr math-logunits) expr 1))))
-(defun math-logcombine (a b neg)
+(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)
(calc-record-why "*Improper coefficients" nil)
(math-mul
(if (equal aunit '(var dB var-dB))
- (math-mul 10
- (calcFunc-log10
- (if neg
- (math-sub
- (math-pow 10 (math-div acoeff 10))
- (math-pow 10 (math-div bcoeff 10)))
- (math-add
- (math-pow 10 (math-div acoeff 10))
- (math-pow 10 (math-div bcoeff 10))))))
- (calcFunc-ln
- (if neg
- (math-sub
- (calcFunc-exp acoeff)
- (calcFunc-exp bcoeff))
- (math-add
- (calcFunc-exp acoeff)
- (calcFunc-exp bcoeff)))))
+ (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-luplus (a b)
- (math-logcombine a b nil))
+(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-luminus (a b)
- (math-logcombine a b t))
+(defun calcFunc-lufieldminus (a b)
+ (math-logunits-add a b t nil))
-(defun calc-luplus (arg)
+(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)
- (calc-binary-op "lu-" 'calcFunc-luminus arg)
- (calc-binary-op "lu+" 'calcFunc-luplus arg))))
-
-(defun calc-luminus (arg)
+ (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)
- (calc-binary-op "lu+" 'calcFunc-luplus arg)
- (calc-binary-op "lu-" 'calcFunc-luminus arg))))
+ (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-lmul (a b)
+(defun calcFunc-lufielddiv (a b)
+ (math-logunits-divide a b nil))
+(defun calcFunc-lupowerdiv (a b)
+ (math-logunits-divide a b t))
-(defun math-logunit-level (val ref power)
- (let ((lunit (math-simplify (math-extract-logunits val))))
+(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)
- (if (not (eq 1 (math-simplify (math-extract-units (math-div val lunit)))))
- (calc-record-why "*Inappropriate units" nil)
- (let ((coeff (math-simplify (math-div val lunit))))
- (if (equal lunit '(var dB var-dB))
- (math-mul
- ref
- (math-pow
- 10
- (math-div
- coeff
- (if power 10 20))))
- (math-mul
- ref
- (calcFunc-exp
- (if power
- (math-mul 2 coeff)
- coeff)))))))))
+ (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))
-(defvar calc-default-field-reference-level)
-(defvar calc-default-power-reference-level)
+(defun calcFunc-powerquant (val &optional ref)
+ (unless ref
+ (setq ref (math-read-expr calc-logunits-power-reference)))
+ (math-logunits-quant val ref t))
-(defun calcFunc-fieldlevel (val &optional ref)
+(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-default-field-reference-level)))
- (math-logunit-level val ref nil))
+ (setq ref (math-read-expr calc-logunits-field-reference)))
+ (math-logunits-level val ref nil nil))
-(defun calcFunc-powerlevel (val &optional ref)
+(defun calcFunc-nppowerlevel (val &optional ref)
(unless ref
- (setq ref (math-read-expr calc-default-power-reference-level)))
- (math-logunit-level val ref t))
+ (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-level (arg)
+(defun calc-logunits-nplevel (arg)
(interactive "P")
(calc-slow-wrapper
(if (calc-is-hyperbolic)
(if (calc-is-option)
- (calc-binary-op "plvl" 'calcFunc-powerlevel arg)
- (calc-unary-op "plvl" 'calcFunc-powerlevel arg))
+ (calc-binary-op "lunp" 'calcFunc-npfieldlevel arg)
+ (calc-unary-op "lunp" 'calcFunc-npfieldlevel arg))
(if (calc-is-option)
- (calc-binary-op "flvl" 'calcFunc-fieldlevel arg)
- (calc-unary-op "flvl" 'calcFunc-fieldlevel arg)))))
+ (calc-binary-op "lunp" 'calcFunc-nppowerlevel arg)
+ (calc-unary-op "lunp" 'calcFunc-nppowerlevel arg)))))
(provide 'calc-units)