summaryrefslogtreecommitdiff
path: root/macros/luatex/latex/lua-physical/test/testQuantity.lua
diff options
context:
space:
mode:
Diffstat (limited to 'macros/luatex/latex/lua-physical/test/testQuantity.lua')
-rw-r--r--macros/luatex/latex/lua-physical/test/testQuantity.lua609
1 files changed, 609 insertions, 0 deletions
diff --git a/macros/luatex/latex/lua-physical/test/testQuantity.lua b/macros/luatex/latex/lua-physical/test/testQuantity.lua
new file mode 100644
index 0000000000..c8b19d929d
--- /dev/null
+++ b/macros/luatex/latex/lua-physical/test/testQuantity.lua
@@ -0,0 +1,609 @@
+--[[
+This file contains the unit tests for the physical.Quantity class.
+
+Copyright (c) 2017 Thomas Jenni (tjenni@me.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+]]--
+
+local lu = require("luaunit")
+
+package.path = "../?.lua;" .. package.path
+local physical = require("physical")
+
+local N = physical.Number
+local Q = physical.Quantity
+
+function dump(o)
+ if type(o) == 'table' then
+ local s = '{ '
+ for k,v in pairs(o) do
+ if type(k) ~= 'number' then k = '"'..k..'"' end
+ if getmetatable(v) == physical.Unit then
+ s = s .. '['..k..'] = ' .. v.symbol .. ','
+ else
+ s = s .. '['..k..'] = ' .. dump(v) .. ','
+ end
+ end
+ return s .. '}\n'
+ else
+ return tostring(o)
+ end
+end
+
+
+TestQuantity = {}
+
+-- Quantity.new(o=nil)
+function TestQuantity:testEmptyConstructor()
+ local q = Q()
+ lu.assertEquals( q.value, 1 )
+end
+function TestQuantity:testNumberConstructor()
+ local q = Q(42)
+ lu.assertEquals( q.value, 42 )
+ lu.assertTrue( q.dimension:iszero() )
+end
+function TestQuantity:testCopyConstructor()
+ local q = Q(73*_m)
+ lu.assertEquals( q.value, 73 )
+ lu.assertTrue( q.dimension == _m.dimension )
+end
+
+
+-- Quantity.defineBase(symbol,name,dimension)
+
+
+
+
+
+-- Quantity.define(symbol, name, o, tobase, frombase)
+
+
+
+
+
+
+
+function TestQuantity:testToString()
+ N.seperateUncertainty = true
+
+ lu.assertEquals( tostring(5 * _m), "5 * _m" )
+ lu.assertEquals( tostring(5 * _m^2), "5.0 * _m^2" )
+ lu.assertEquals( tostring(5 * _km/_h), "5.0 * _km / _h" )
+
+ lu.assertEquals( tostring( N(2.7,0.04) * _g/_cm^3), "(2.70 +/- 0.04) * _g / _cm^3" )
+end
+
+
+function TestQuantity:testToSIUnitX()
+ N.seperateUncertainty = false
+
+ lu.assertEquals( (5 * _m):tosiunitx(), "\\SI{5}{\\meter}" )
+ lu.assertEquals( (5 * _m):tosiunitx("x=1"), "\\SI[x=1]{5}{\\meter}" )
+
+ lu.assertEquals( (5 * _m):tosiunitx("x=5",1), "\\num[x=5]{5}" )
+ lu.assertEquals( (5 * _m):tosiunitx("x=5",2), "\\si[x=5]{\\meter}" )
+
+ lu.assertEquals( (5 * _m^2):tosiunitx(), "\\SI{5.0}{\\meter\\tothe{2}}" )
+
+ lu.assertEquals( (56 * _km):tosiunitx(), "\\SI{56}{\\kilo\\meter}" )
+ lu.assertEquals( (5 * _km/_h):tosiunitx(), "\\SI{5.0}{\\kilo\\meter\\per\\hour}" )
+ lu.assertEquals( (4.81 * _J / (_kg * _K) ):tosiunitx(), "\\SI{4.81}{\\joule\\per\\kilogram\\per\\kelvin}" )
+
+ lu.assertEquals( (N(2.7,0.04) * _g/_cm^3):tosiunitx(), "\\SI{2.70(4)}{\\gram\\per\\centi\\meter\\tothe{3}}" )
+end
+
+
+
+
+
+function TestQuantity.addError()
+ local l = 5*_m + 10*_s
+end
+function TestQuantity:testAdd()
+ local l = 5*_m + 10*_m
+ lu.assertEquals( l.value, 15 )
+ lu.assertEquals( l.dimension, _m.dimension )
+
+ local msg = "Error: Cannot add '5 * _m' to '10 * _s', because they have different dimensions."
+ lu.assertErrorMsgContains(msg, TestQuantity.addError )
+end
+
+
+
+
+function TestQuantity.subtractError()
+ local l = 5*_m - 10*_s
+end
+function TestQuantity:testSubtract()
+ local l = 5*_m - 15*_m
+ lu.assertEquals( l.value, -10 )
+ lu.assertEquals( l.dimension, _m.dimension )
+
+ local msg = "Error: Cannot subtract '10 * _s' from '5 * _m', because they have different dimensions."
+ lu.assertErrorMsgContains(msg, TestQuantity.subtractError )
+end
+
+
+function TestQuantity:testUnaryMinus()
+ local l = -5*_m
+ lu.assertEquals( l.value, -5 )
+ lu.assertEquals( l.dimension, _m.dimension )
+end
+
+
+function TestQuantity:testMultiply()
+ local A = 5*_m * 10 * _m
+ lu.assertEquals( A.value, 50 )
+ lu.assertEquals( A.dimension, (_m^2).dimension )
+end
+
+
+function TestQuantity:testMultiplyOfTemperatures()
+ local m_1 = 5 * _kg
+ local m_2 = 3 * _kg
+ local T_1 = 20 * _degC
+ local T_2 = 40 * _degC
+
+ -- if one multiplies a temperature by another quantity
+ -- the temperature will be interpreted as a temperature difference
+ local T_m = ( (m_1*T_1 + m_2*T_2) / (m_1 + m_2) ):to(_degC, false)
+
+ lu.assertEquals( T_m.value, 27.5 )
+
+
+ local m_1 = 5 * _kg
+ local m_2 = 3 * _kg
+ local T_1 = 20 * _degF
+ local T_2 = 40 * _degF
+
+ -- if one multiplies a temperature by another quantity
+ -- the temperature will be interpreted as a temperature difference.
+ local T_m = ( (m_1*T_1 + m_2*T_2) / (m_1 + m_2) ):to(_degC, false)
+
+ lu.assertAlmostEquals( T_m.value, 15.277777777778, 1e-3 )
+end
+
+
+function TestQuantity:testMultiplyWithNumber()
+ local one = N(1,0.1) * _1
+
+ lu.assertEquals( one.value, N(1,0.1) )
+ lu.assertEquals( one.dimension, (_1).dimension )
+
+ local mu = ( N(1,0.1) * _u_0 ):to(_N/_A^2)
+ lu.assertAlmostEquals( mu.value._dx, 1.256e-6, 1e-3 )
+ lu.assertEquals( mu.dimension, (_N/_A^2).dimension )
+end
+
+
+function TestQuantity.divideError()
+ local l = 7*_m / ((2*6 - 12)*_s)
+end
+function TestQuantity:testDivide()
+ local v = 7*_m / (2*_s)
+ lu.assertEquals( v.value, 3.5 )
+ lu.assertEquals( v.dimension, (_m/_s).dimension )
+
+ lu.assertError( divideError )
+end
+
+-- test power function
+function TestQuantity:testPow()
+ local V = (5*_m)^3
+ lu.assertEquals( V.value, 125 )
+ lu.assertEquals( V.dimension, (_m^3).dimension )
+end
+
+function TestQuantity:testPowWithQuantityAsExponent()
+ local V = (5*_m)^(24*_m / (12*_m))
+ lu.assertAlmostEquals( V.value, 25, 0.00001 )
+ lu.assertEquals( V.dimension, (_m^2).dimension )
+end
+
+-- test isclose function
+function TestQuantity:testisclose()
+ local rho1 = 19.3 * _g / _cm^3
+ local rho2 = 19.2 * _g / _cm^3
+
+ lu.assertTrue( rho1:isclose(rho2,0.1) )
+ lu.assertTrue( rho1:isclose(rho2,10 * _percent) )
+ lu.assertFalse( rho1:isclose(rho2,0.1 * _percent) )
+end
+
+-- test min function
+function TestQuantity:testMin()
+ local l = Q.min(-2.5,5)
+ lu.assertEquals( l.value, -2.5 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = (3 * _cm):min(5 * _dm)
+ lu.assertEquals( l.value, 3 )
+ lu.assertEquals( l.dimension, _m.dimension )
+
+ local q1 = 20 * _cm
+ local q2 = 10 * _dm
+ local q3 = 1 * _m
+ lu.assertEquals( Q.min(q1,q2,q3), q1 )
+
+ local q1 = 20 * _A
+ lu.assertEquals( Q.min(q1), q1 )
+
+ local q1 = N(10,1) * _s
+ local q2 = N(9,1) * _s
+ lu.assertEquals( q1:min(q2), q2 )
+end
+
+-- test max function
+function TestQuantity:testMax()
+ local l = Q.max(-2.5,5)
+ lu.assertEquals( l.value, 5 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = (3 * _m):max(5 * _m)
+ lu.assertEquals( l.value, 5 )
+ lu.assertEquals( l.dimension, _m.dimension )
+
+ local q1 = 20 * _cm
+ local q2 = 10 * _dm
+ local q3 = 1 * _m
+ lu.assertEquals( Q.max(q1,q2,q3), q2 )
+
+ local q1 = 20 * _A
+ lu.assertEquals( Q.max(q1), q1 )
+
+ local q1 = N(10,1) * _s
+ local q2 = N(9,1) * _s
+ lu.assertEquals( q1:max(q2), q1 )
+end
+
+-- test absolute value function
+function TestQuantity:testAbs()
+ local l = Q.abs(-2.5)
+ lu.assertEquals( l.value, 2.5 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = (-45.3 * _m):abs()
+ lu.assertEquals( l.value, 45.3 )
+ lu.assertEquals( l.dimension, _m.dimension )
+
+ local l = ( N(-233,3) * _m^2):abs()
+ lu.assertEquals( l.value, N(233,3) )
+ lu.assertEquals( l.dimension, (_m^2).dimension )
+end
+
+-- test square root function
+function TestQuantity:testSqrt()
+ local l = (103 * _cm^2):sqrt()
+ lu.assertEquals( l.value, 10.148891565092219 )
+ lu.assertEquals( l.dimension, _m.dimension )
+
+ local l = (N(103,2) * _cm^2):sqrt()
+ lu.assertAlmostEquals( l.value._x, 10.148891565092219, 0.0001 )
+ lu.assertAlmostEquals( l.value._dx, 0.098532927816429, 0.0001 )
+ lu.assertEquals( l.dimension, _m.dimension )
+end
+
+-- test logarithm function
+function TestQuantity.logError()
+ local l = (100 * _s):log()
+end
+function TestQuantity:testLog()
+ lu.assertError( logError )
+
+ local l = Q.log(2)
+ lu.assertAlmostEquals( l.value, 0.693147180559945, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = Q.log(3 * _1)
+ lu.assertAlmostEquals( l.value, 1.09861228866811, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = Q.log(2, 10)
+ lu.assertAlmostEquals( l.value, 0.301029995663981, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = Q.log(4, 10 * _1)
+ lu.assertAlmostEquals( l.value, 0.602059991327962, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = Q.log(4 * _1, 8 * _1)
+ lu.assertAlmostEquals( l.value, 0.666666666666666, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = (100 * _1):log()
+ lu.assertAlmostEquals( l.value, 4.605170185988091, 0.0001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = (600 * _m / (50000 * _cm)):log()
+ lu.assertAlmostEquals( l.value, 0.182321556793955, 0.0001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = ( N(100,0) * _1 ):log()
+ lu.assertAlmostEquals( l.value._x, 4.605170185988091, 0.0001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+end
+
+function TestQuantity:testLogAdvanced()
+ local L_I1 = N(125,0.1) * _dB
+ local I_0 = 1e-12 * _W/_m^2
+ local I_1 = ( I_0 * 10^(L_I1/10) ):to(_W/_m^2)
+
+ local l = (I_1/I_0):log(10)
+ lu.assertAlmostEquals( l.value._x, 12.5, 0.001 )
+end
+
+-- test exponential function
+function TestQuantity.expError()
+ local l = (100 * _s):log()
+end
+function TestQuantity:testExp()
+ lu.assertError( expError )
+
+ local l = (-2*_m/(5*_m)):exp()
+ lu.assertAlmostEquals( l.value, 0.670320046035639, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = Q.exp(2)
+ lu.assertAlmostEquals( l.value, 7.38905609893065, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+end
+
+-- test sine function
+function TestQuantity.sinError()
+ local l = (100 * _s):sin()
+end
+function TestQuantity:testSin()
+ lu.assertError( sinError )
+
+ local l = Q.sin(1.570796326794897)
+ lu.assertAlmostEquals( l.value, 1, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = (45 * _deg):sin()
+ lu.assertAlmostEquals( l.value, 0.707106781186548, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+end
+
+-- test cosine function
+function TestQuantity.cosError()
+ local l = (100 * _s):cos()
+end
+function TestQuantity:testCos()
+ lu.assertError( cosError )
+
+ local l = Q.cos(0)
+ lu.assertAlmostEquals( l.value, 1, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = (50 * _deg):cos()
+ lu.assertAlmostEquals( l.value, 0.642787609686539, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+end
+
+-- test tangens function
+function TestQuantity.tanError()
+ local l = (100 * _s):tan()
+end
+function TestQuantity:testTan()
+ lu.assertError( tanError )
+
+ local l = Q.tan(0.785398163397448)
+ lu.assertAlmostEquals( l.value, 1, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = (50 * _deg):tan()
+ lu.assertAlmostEquals( l.value, 1.19175359259421, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+end
+
+
+-- test asin function
+function TestQuantity.asinError()
+ local l = (100 * _s):asin()
+end
+function TestQuantity:testAsin()
+ lu.assertError( asinError )
+
+ local l = Q.asin(0.785398163397448)
+ lu.assertAlmostEquals( l.value, 0.903339110766512, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = (0.5 * _1):asin()
+ lu.assertAlmostEquals( l.value, 0.523598775598299, 0.000001 )
+ lu.assertEquals( l.dimension, _rad.dimension )
+end
+
+
+-- test acos function
+function TestQuantity.acosError()
+ local l = (100 * _s):acos()
+end
+function TestQuantity:testAcos()
+ lu.assertError( acosError )
+
+ local l = Q.acos(0.785398163397448)
+ lu.assertAlmostEquals( l.value, 0.667457216028384, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = (0.5 * _1):acos()
+ lu.assertAlmostEquals( l.value, 1.047197551196598, 0.000001 )
+ lu.assertEquals( l.dimension, _rad.dimension )
+end
+
+
+-- test atan function
+function TestQuantity.atanError()
+ local l = (100 * _s):atan()
+end
+function TestQuantity:testAtan()
+ lu.assertError( atanError )
+
+ local l = Q.atan(0.785398163397448)
+ lu.assertAlmostEquals( l.value, 0.665773750028354, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = (0.5 * _1):atan()
+ lu.assertAlmostEquals( l.value, 0.463647609000806, 0.000001 )
+ lu.assertEquals( l.dimension, _rad.dimension )
+end
+
+-- test sinh function
+function TestQuantity.sinhError()
+ local l = (100 * _s):sinh()
+end
+function TestQuantity:testSinh()
+ lu.assertError( sinhError )
+
+ local l = Q.sinh(2)
+ lu.assertAlmostEquals( l.value, 3.626860407847019, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = (0.75 * _1):sinh()
+ lu.assertAlmostEquals( l.value, 0.82231673193583, 1e-9 )
+
+ local l = (N(0.75,0.01) * _1):sinh()
+ lu.assertAlmostEquals( l.value:__tonumber(), 0.82231673193583, 1e-9 )
+end
+
+-- test cosh function
+function TestQuantity.coshError()
+ local l = (100 * _s):cosh()
+end
+function TestQuantity:testCosh()
+ lu.assertError( coshError )
+
+ local l = Q.cosh(2)
+ lu.assertAlmostEquals( l.value, 3.762195691083631, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = (0.25 * _1):cosh()
+ lu.assertAlmostEquals( l.value, 1.031413099879573, 1e-9 )
+
+ local l = (N(0.25,0.01) * _1):cosh()
+ lu.assertAlmostEquals( l.value:__tonumber(), 1.031413099879573, 1e-9 )
+end
+
+-- test tanh function
+function TestQuantity.tanhError()
+ local l = (100 * _s):tanh()
+end
+function TestQuantity:testTanh()
+ lu.assertError( tanhError )
+
+ local l = Q.tanh(2)
+ lu.assertAlmostEquals( l.value, 0.964027580075817, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = (0.5 * _1):tanh()
+ lu.assertAlmostEquals( l.value, 0.46211715726001, 1e-9 )
+
+ local l = (N(0.5,0.01) * _1):tanh()
+ lu.assertAlmostEquals( l.value:__tonumber(), 0.46211715726001, 1e-9 )
+end
+
+-- test asinh function
+function TestQuantity.asinhError()
+ local l = (100 * _s):asinh()
+end
+function TestQuantity:testAsinh()
+ lu.assertError( asinhError )
+
+ local l = Q.asinh(1)
+ lu.assertAlmostEquals( l.value, 0.881373587019543, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = (2 * _1):asinh()
+ lu.assertAlmostEquals( l.value, 1.44363547517881, 1e-9 )
+
+ local l = (N(2,0.01) * _1):asinh()
+ lu.assertAlmostEquals( l.value:__tonumber(), 1.44363547517881, 1e-9 )
+end
+
+-- test acosh function
+function TestQuantity.acoshError()
+ local l = (100 * _s):acosh()
+end
+function TestQuantity:testAcosh()
+ lu.assertError( acoshError )
+
+ local l = Q.acosh(1.5)
+ lu.assertAlmostEquals( l.value, 0.962423650119207, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = (1.2 * _1):acosh()
+ lu.assertAlmostEquals( l.value, 0.622362503714779, 1e-9 )
+
+ local l = (N(1.2,0.01) * _1):acosh()
+ lu.assertAlmostEquals( l.value:__tonumber(), 0.622362503714779, 1e-9 )
+end
+
+-- test atanh function
+function TestQuantity.atanhError()
+ local l = (100 * _s):atanh()
+end
+function TestQuantity:testAtanh()
+ lu.assertError( atanhError )
+
+ local l = Q.atanh(0.5)
+ lu.assertAlmostEquals( l.value, 0.549306144334055, 0.000001 )
+ lu.assertEquals( l.dimension, _1.dimension )
+
+ local l = (0.9 * _1):atanh()
+ lu.assertAlmostEquals( l.value, 1.47221948958322, 1e-9 )
+
+ local l = (N(0.9,0.01) * _1):atanh()
+ lu.assertAlmostEquals( l.value:__tonumber(), 1.47221948958322, 1e-9 )
+end
+
+-- test less than
+function TestQuantity:testLessThan()
+
+ local Pi = 3.1415926535897932384626433832795028841971693993751
+
+ local l_D = 5 * _m
+ local d_D = N(0.25,0.001) * _mm
+
+ local d = N(5,0.01) * _cm
+ local l = N(10,0.01) * _cm
+
+ local I_max = N(1,0.001) * _A
+ local B = N(0.5,0.001) * _mT
+
+ local Nw = ( B*l/(_u_0*I_max) ):to(_1)
+ local N_max = (l/d_D):to(_1)
+ local l_max = (Nw*Pi*d):to(_m)
+
+ lu.assertTrue(l_D < l_max)
+end
+
+-- test less than zero
+function TestQuantity:testLessThanZero()
+ lu.assertTrue(1*_1 > 0)
+ lu.assertTrue(0*_1 > -1)
+ lu.assertTrue(-1*_1 < 0)
+
+ lu.assertTrue(0 < 1*_1)
+ lu.assertTrue(-1 < 0*_1)
+ lu.assertTrue(0 > -1*_1)
+end
+
+
+return TestQuantity