@@ -9,6 +9,12 @@ using StaticArrays: SArray, MArray
9
9
using LinearAlgebra: norm
10
10
using Test
11
11
12
+ function record_show (s, f= show)
13
+ io = IOBuffer ()
14
+ f (io, s)
15
+ return String (take! (io))
16
+ end
17
+
12
18
@testset " Basic utilities" begin
13
19
14
20
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
149
155
@test isinf (x * Inf ) == true
150
156
@test isnan (x) == false
151
157
@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
152
173
153
174
@test nextfloat (x) == Quantity (nextfloat (- 1.2 ), length= 2 // 5 )
154
175
@test prevfloat (x) == Quantity (prevfloat (- 1.2 ), length= 2 // 5 )
432
453
# Conversion to Rational without specifying type
433
454
@test convert (Rational, FixedRational {UInt8,6} (2 )) === Rational {UInt8} (2 )
434
455
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"
443
458
444
459
# Promotion rules
445
460
@test promote_type (FixedRational{Int64,10 },FixedRational{BigInt,10 }) == FixedRational{BigInt,10 }
@@ -1104,3 +1119,135 @@ end
1104
1119
@test convert (typeof (qx), qy)[1 ] == convert (Quantity{Float64}, qy[1 ])
1105
1120
end
1106
1121
end
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