@@ -9,6 +9,12 @@ using StaticArrays: SArray, MArray
99using LinearAlgebra: norm
1010using Test
1111
12+ function record_show (s, f= show)
13+ io = IOBuffer ()
14+ f (io, s)
15+ return String (take! (io))
16+ end
17+
1218@testset " Basic utilities" begin
1319
1420 for Q in [Quantity, GenericQuantity], T in [DEFAULT_VALUE_TYPE, Float16, Float32, Float64], R in [DEFAULT_DIM_BASE_TYPE, Rational{Int16}, Rational{Int32}, SimpleRatio{Int}, SimpleRatio{SafeInt16}]
@@ -149,6 +155,21 @@ using Test
149155 @test isinf (x * Inf ) == true
150156 @test isnan (x) == false
151157 @test isnan (x * NaN ) == true
158+ @test isreal (x) == true
159+ @test isreal (x * (1 + 2im )) == false
160+ @test signbit (x) == true
161+ @test signbit (- x) == false
162+ @test isempty (x) == false
163+ @test isempty (GenericQuantity ([0.0 , 1.0 ])) == false
164+ @test isempty (GenericQuantity (Float64[])) == true
165+ @test iseven (Quantity (2 , length= 1 )) == true
166+ @test iseven (Quantity (3 , length= 1 )) == false
167+ @test isodd (Quantity (2 , length= 1 )) == false
168+ @test isodd (Quantity (3 , length= 1 )) == true
169+ @test isinteger (Quantity (2 , length= 1 )) == true
170+ @test isinteger (Quantity (2.1 , length= 1 )) == false
171+ @test ispow2 (Quantity (2 , length= 1 )) == true
172+ @test ispow2 (Quantity (3 , length= 1 )) == false
152173
153174 @test nextfloat (x) == Quantity (nextfloat (- 1.2 ), length= 2 // 5 )
154175 @test prevfloat (x) == Quantity (prevfloat (- 1.2 ), length= 2 // 5 )
432453 # Conversion to Rational without specifying type
433454 @test convert (Rational, FixedRational {UInt8,6} (2 )) === Rational {UInt8} (2 )
434455
435- # Showing rationals
436- function show_string (i)
437- io = IOBuffer ()
438- show (io, i)
439- return String (take! (io))
440- end
441- @test show_string (FixedRational {Int,10} (2 )) == " 2"
442- @test show_string (FixedRational {Int,10} (11 // 10 )) == " 11//10"
456+ @test record_show (FixedRational {Int,10} (2 )) == " 2"
457+ @test record_show (FixedRational {Int,10} (11 // 10 )) == " 11//10"
443458
444459 # Promotion rules
445460 @test promote_type (FixedRational{Int64,10 },FixedRational{BigInt,10 }) == FixedRational{BigInt,10 }
@@ -1104,3 +1119,135 @@ end
11041119 @test convert (typeof (qx), qy)[1 ] == convert (Quantity{Float64}, qy[1 ])
11051120 end
11061121end
1122+
1123+ function is_input_valid (f, x)
1124+ try
1125+ f (x)
1126+ catch e
1127+ e isa DomainError && return false
1128+ rethrow (e)
1129+ end
1130+ return true
1131+ end
1132+
1133+ @testset " Assorted dimensionless functions" begin
1134+ functions = (
1135+ :sin , :cos , :tan , :sinh , :cosh , :tanh , :asin , :acos ,
1136+ :asinh , :acosh , :atanh , :sec , :csc , :cot , :asec , :acsc , :acot , :sech , :csch ,
1137+ :coth , :asech , :acsch , :acoth , :sinc , :cosc , :cosd , :cotd , :cscd , :secd ,
1138+ :sinpi , :cospi , :sind , :tand , :acosd , :acotd , :acscd , :asecd , :asind ,
1139+ :log , :log2 , :log10 , :log1p , :exp , :exp2 , :exp10 , :expm1 , :frexp , :exponent ,
1140+ :atan , :atand
1141+ )
1142+ for Q in (Quantity, GenericQuantity), D in (Dimensions, SymbolicDimensions), f in functions
1143+ # Only test on valid domain
1144+ valid_inputs = filter (
1145+ x -> is_input_valid (eval (f), x),
1146+ 5 rand (100 ) .- 2.5
1147+ )
1148+ for x in valid_inputs[1 : 3 ]
1149+ qx_dimensionless = Quantity (x, D)
1150+ qx_dimensions = Quantity (x, convert (D, dimension (u " m/s" )))
1151+ @eval @test $ f ($ qx_dimensionless) == $ f ($ x)
1152+ @eval @test_throws DimensionError $ f ($ qx_dimensions)
1153+ if f in (:atan , :atand )
1154+ for y in valid_inputs[end - 3 : end ]
1155+ qy_dimensionless = Quantity (y, D)
1156+ qy_dimensions = Quantity (y, convert (D, dimension (u " m/s" )))
1157+ @eval @test $ f ($ y, $ qx_dimensionless) == $ f ($ y, $ x)
1158+ @eval @test $ f ($ qy_dimensionless, $ x) == $ f ($ y, $ x)
1159+ @eval @test $ f ($ qy_dimensionless, $ qx_dimensionless) == $ f ($ y, $ x)
1160+ @eval @test $ f ($ qy_dimensions, $ qx_dimensions) == $ f ($ y, $ x)
1161+ @eval @test_throws DimensionError $ f ($ qy_dimensions, $ x)
1162+ @eval @test_throws DimensionError $ f ($ y, $ qx_dimensions)
1163+ end
1164+ end
1165+ end
1166+ end
1167+ s = record_show (DimensionError (u " km/s" ), showerror)
1168+ @test occursin (" not dimensionless" , s)
1169+ end
1170+
1171+ @testset " Assorted dimensionful functions" begin
1172+ functions = (
1173+ :float , :abs , :real , :imag , :conj , :adjoint , :unsigned ,
1174+ :nextfloat , :prevfloat , :identity , :transpose ,
1175+ :copysign , :flipsign , :mod , :modf ,
1176+ :floor , :trunc , :ceil , :significand ,
1177+ :ldexp , :round ,
1178+ )
1179+ for Q in (Quantity, GenericQuantity), D in (Dimensions, SymbolicDimensions), f in functions
1180+ T = f in (:abs , :real , :imag , :conj ) ? ComplexF64 : Float64
1181+ if f == :modf # Functions that return multiple outputs
1182+ for x in 5 rand (T, 3 ) .- 2.5
1183+ dim = convert (D, dimension (u " m/s" ))
1184+ qx_dimensions = Q (x, dim)
1185+ num_outputs = 2
1186+ for i= 1 : num_outputs
1187+ @eval @test $ f ($ qx_dimensions)[$ i] == $ Q ($ f ($ x)[$ i], $ dim)
1188+ end
1189+ end
1190+ elseif f in (:copysign , :flipsign , :rem , :mod ) # Functions that need multiple inputs
1191+ for x in 5 rand (T, 3 ) .- 2.5
1192+ for y in 5 rand (T, 3 ) .- 2.5
1193+ dim = convert (D, dimension (u " m/s" ))
1194+ qx_dimensions = Q (x, dim)
1195+ qy_dimensions = Q (y, dim)
1196+ @eval @test $ f ($ qx_dimensions, $ qy_dimensions) == $ Q ($ f ($ x, $ y), $ dim)
1197+ if f in (:copysign , :flipsign , :mod )
1198+ # Also do test without dimensions
1199+ @eval @test $ f ($ x, $ qy_dimensions) == $ f ($ x, $ y)
1200+ @eval @test $ f ($ qx_dimensions, $ y) == $ Q ($ f ($ x, $ y), $ dim)
1201+ end
1202+ end
1203+ end
1204+ elseif f == :unsigned
1205+ for x in 5 rand (- 10 : 10 , 3 )
1206+ dim = convert (D, dimension (u " m/s" ))
1207+ qx_dimensions = Q (x, dim)
1208+ @eval @test $ f ($ qx_dimensions) == $ Q ($ f ($ x), $ dim)
1209+ end
1210+ elseif f in (:round , :floor , :trunc , :ceil )
1211+ for x in 5 rand (T, 3 ) .- 2.5
1212+ dim = convert (D, dimension (u " m/s" ))
1213+ qx_dimensions = Q (x, dim)
1214+ @eval @test $ f ($ qx_dimensions) == $ Q ($ f ($ x), $ dim)
1215+ @eval @test $ f (Int32, $ qx_dimensions) == $ Q ($ f (Int32, $ x), $ dim)
1216+ end
1217+ elseif f == :ldexp
1218+ for x in 5 rand (T, 3 ) .- 2.5
1219+ dim = convert (D, dimension (u " m/s" ))
1220+ qx_dimensions = Q (x, dim)
1221+ for i= 1 : 3
1222+ @eval @test $ f ($ qx_dimensions, $ i) == $ Q ($ f ($ x, $ i), $ dim)
1223+ end
1224+ end
1225+ else
1226+ # Only test on valid domain
1227+ valid_inputs = filter (
1228+ x -> is_input_valid (eval (f), x),
1229+ 5 rand (T, 100 ) .- 2.5
1230+ )
1231+ for x in valid_inputs[1 : 3 ]
1232+ dim = convert (D, dimension (u " m/s" ))
1233+ qx_dimensions = Q (x, dim)
1234+ @eval @test $ f ($ qx_dimensions) == $ Q ($ f ($ x), $ dim)
1235+ end
1236+ end
1237+ end
1238+ end
1239+
1240+ @testset " Test div" begin
1241+ for Q in (Quantity, GenericQuantity)
1242+ x = Q {Int} (10 , length= 1 )
1243+ y = Q {Int} (3 , mass= - 1 )
1244+ @test div (x, y) == Q {Int} (3 , length= 1 , mass= 1 )
1245+ @test div (x, 3 ) == Q {Int} (3 , length= 1 )
1246+ @test div (10 , y) == Q {Int} (3 , mass= 1 )
1247+ if VERSION >= v " 1.9"
1248+ @test div (x, y, RoundFromZero) == Q {Int} (4 , length= 1 , mass= 1 )
1249+ @test div (x, 3 , RoundFromZero) == Q {Int} (4 , length= 1 )
1250+ @test div (10 , y, RoundFromZero) == Q {Int} (4 , mass= 1 )
1251+ end
1252+ end
1253+ end
0 commit comments