Skip to content

Improve test coverage #92

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# BFloat16s.jl
[![MIT license](http://img.shields.io/badge/license-MIT-brightgreen.svg)](http://opensource.org/licenses/MIT)
[![MIT license](http://img.shields.io/badge/license-MIT-brightgreen.svg)](http://opensource.org/licenses/MIT)
[![codecov-img]][codecov-url]

[codecov-img]: https://codecov.io/gh/JuliaMath/BFloat16s.jl/branch/master/graph/badge.svg
[codecov-url]: https://codecov.io/gh/JuliaMath/BFloat16s.jl

This package defines the [BFloat16 data type](https://en.wikipedia.org/wiki/Bfloat16_floating-point_format),
a floating-point format with 1 sign bit, 8 exponent bits and 7 mantissa bits.
Expand Down
25 changes: 25 additions & 0 deletions test/lowprecarrays.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
@testset "lowprecarrays" begin
A = rand(Float32, 10,10)
lpA = LowPrecArray(A)

@test lpA isa LowPrecArray
@test size(A) == size(lpA)

lpA[3] = 4
@test lpA[3] == A[3]

a = rand(Float32)
ab = BFloat16s.ExpandingBFloat16(a)
b = rand(Float32)
bb = BFloat16s.ExpandingBFloat16(b)

@test ab isa BFloat16s.ExpandingBFloat16
@test ab.a isa BFloat16
@test ab * bb isa Float32

B = LowPrecArray(rand(Float32, 10,10))
C = LowPrecArray(rand(Float32, 10,10))

lpA .= B*C

end # @testset "lowprecarrays"
15 changes: 9 additions & 6 deletions test/mathfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ for F in (:abs, :abs2, :sqrt, :cbrt,
:asin, :acos, :atan, :acot,
:sinh, :cosh, :tanh, :csch, :sech, :coth,
:asinh, :atanh, :acsch, :asech)
@eval begin
@test $F(invphi) == BFloat16($F(Float32(invphi)))
end
@eval begin
@test $F(invphi) == BFloat16($F(Float32(invphi)))
end
end

for F in (:asec, :acsc, :cosh, :acosh, :acoth)
@eval begin
@test $F(phi) == BFloat16($F(Float32(phi)))
end
@eval begin
@test $F(phi) == BFloat16($F(Float32(phi)))
end
end


x,y = rand(Float32, 2)
@test widemul(BFloat16(x), BFloat16(y)) isa Float32
184 changes: 113 additions & 71 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@ using Test, BFloat16s, Printf, Random

@info "Testing BFloat16s" BFloat16s.llvm_storage BFloat16s.llvm_arithmetic

@testset "BFloat16s" begin

@testset "basics" begin
@test Base.exponent_bits(BFloat16) == 8
@test Base.significand_bits(BFloat16) == 7
@test precision(BFloat16) == 8
@test Base.uinttype(BFloat16) == UInt16

@test typemin(BFloat16) == -BFloat16s.InfB16
@test typemax(BFloat16) == BFloat16s.InfB16
end

@testset "comparisons" begin
@test BFloat16(1) < BFloat16(2)
@test BFloat16(1f0) < BFloat16(2f0)
Expand All @@ -18,6 +30,8 @@ using Test, BFloat16s, Printf, Random
@test BFloat16(2) != BFloat16(1)
@test BFloat16(2f0) != BFloat16(1f0)
@test BFloat16(2.0) != BFloat16(1.0)
@test BFloat16(NaN) != BFloat16(1.0)
@test !(BFloat16(1.0) == BFloat16(NaN))
@test iszero(BFloat16(0)) == true
@test iszero(BFloat16(3.45)) == false
end
Expand All @@ -26,39 +40,57 @@ end
@test Float32(BFloat16(10)) == 1f1
@test Float64(BFloat16(10)) == 10.0
@test Int32(BFloat16(10)) == Int32(10)
@test UInt32(BFloat16(10)) == Int32(10)
@test Int64(BFloat16(10)) == Int64(10)
@test UInt64(BFloat16(10)) == Int64(10)
@test BFloat16(BigFloat(1)) == BFloat16(1)
@test BigFloat(BFloat16(1)) == BigFloat(1)
@test Float16(BFloat16(3.140625)) == Float16(π)
@test BFloat16(Float16(π)) == BFloat16(3.140625)
@test BFloat16(pi) == BFloat16(3.14159)
@test all(R -> R<:BFloat16, Base.return_types(BFloat16))

@test promote(BFloat16(4.5), Float64(5.0)) == (Float64(4.5), Float64(5.0))
@test promote(BFloat16(4.5), Float32(5.0)) == (Float32(4.5), Float32(5.0))

@test_throws InexactError Int16(typemax(BFloat16))
@test_throws InexactError UInt16(typemax(BFloat16))
end

@testset "trunc" begin
f_val = 5 .+ rand(100)
bf_val = BFloat16.(f_val)

@testset "$Ts, $(unsigned(Ts))" for Ts in (Int128,)
@testset "$Ts, $(unsigned(Ts))" for Ts in (Int8, Int16, Int32, Int64, Int128)
@test trunc.(Ts, bf_val) == trunc.(Ts, bf_val)
@test trunc.(Ts, -bf_val) == trunc.(Ts, -bf_val)

Tu = unsigned(Ts)
@test trunc.(Tu, bf_val) == trunc.(Tu, bf_val)
end

@test trunc(BFloat16, Float32(π)) == BFloat16(3.140625)

# InexactError
@test_throws InexactError trunc(Int16, typemax(BFloat16))
@test_throws InexactError trunc(UInt16, typemax(BFloat16))
end

@testset "abi" begin
f() = BFloat16(1)
@test f() == BFloat16(1)
f() = BFloat16(1)
@test f() == BFloat16(1)

g(x) = x+BFloat16(1)
@test g(BFloat16(2)) == BFloat16(3)
g(x) = x+BFloat16(1)
@test g(BFloat16(2)) == BFloat16(3)
end

@testset "functions" begin
@test abs(BFloat16(-10)) == BFloat16(10)
@test BFloat16(2) ^ BFloat16(4) == BFloat16(16)
@test eps(BFloat16) == BFloat16(0.0078125)
@test sqrt(BFloat16(4f0)) == BFloat16(2f0)
@test rem(BFloat16(3.14), Int) == 3
@test round(BFloat16(10.4), RoundToZero) == BFloat16(10.0)
@test round(BFloat16(10.4), RoundUp) == BFloat16(11.0)
@test round(BFloat16(10.6), RoundDown) == BFloat16(10.0)
@test round(BFloat16(3.2), RoundNearest) == BFloat16(3.0)
Expand All @@ -84,7 +116,7 @@ end
("%.3E", "1.234E+00"),
("%.2a", "0x1.3cp+0"),
("%.2A", "0X1.3CP+0")),
num in (BFloat16(1.234),)
num in (BFloat16(1.234),)
@eval @test @sprintf($fmt, $num) == $val
end
@test (@sprintf "%f" BFloat16(Inf)) == "Inf"
Expand All @@ -107,101 +139,111 @@ end
@test (@sprintf "%a" BFloat16(1.5)) == "0x1.8p+0"
end

@testset "random" begin
x = Array{BFloat16}(undef, 10)
y = Array{BFloat16}(undef, 10)
rand!(x)
rand!(y)
@test x !== y

randn!(x)
randn!(y)
@test x !== y

randexp!(x)
randexp!(y)
@test x !== y

x = rand(BFloat16, 10)
y = rand(BFloat16, 10)
@test x !== y

x = randn(BFloat16, 10)
y = randn(BFloat16, 10)
@test x !== y
@testset "show" begin
@test repr(BFloat16(Inf)) == "InfB16"
@test repr(BFloat16(-Inf)) == "-InfB16"
@test repr(BFloat16(NaN)) == "NaNB16"
@test repr(BFloat16(2)) == "BFloat16(2.0)"
end

x = randexp(BFloat16, 10)
y = randexp(BFloat16, 10)
@test x !== y
@testset "random" begin
x = Array{BFloat16}(undef, 10)
y = Array{BFloat16}(undef, 10)
rand!(x)
rand!(y)
@test x !== y

randn!(x)
randn!(y)
@test x !== y

randexp!(x)
randexp!(y)
@test x !== y

x = rand(BFloat16, 10)
y = rand(BFloat16, 10)
@test x !== y

x = randn(BFloat16, 10)
y = randn(BFloat16, 10)
@test x !== y

x = randexp(BFloat16, 10)
y = randexp(BFloat16, 10)
@test x !== y
end

@testset "round" begin
@test round(Int, BFloat16(3.4)) == 3
@test round(Int, BFloat16(3.4)) == 3
end

@testset "Next/prevfloat" begin
for x in (one(BFloat16),
-one(BFloat16),
zero(BFloat16))
@test x == nextfloat(prevfloat(x))
@test x == prevfloat(nextfloat(x))

for x in (one(BFloat16),
-one(BFloat16),
zero(BFloat16))
@test x == nextfloat(prevfloat(x))
@test x == prevfloat(nextfloat(x))
@test x < nextfloat(x)
@test x > prevfloat(x)

@test x < nextfloat(x)
@test x > prevfloat(x)
end
@test nextfloat(x, typemax(Int)) == typemax(BFloat16)
@test prevfloat(x, typemax(Int)) == typemin(BFloat16)
end

@test isnan(nextfloat(BFloat16s.NaNB16))
@test isinf(nextfloat(BFloat16s.InfB16))
@test isnan(nextfloat(BFloat16s.NaNB16))
@test isinf(nextfloat(BFloat16s.InfB16))

@test isnan(prevfloat(BFloat16s.NaNB16))
@test isnan(prevfloat(BFloat16s.NaNB16))
end

@testset "Decompose BFloat16" begin
for x in randn(100)
bf16 = BFloat16(x)
s,e,d = Base.decompose(bf16)
@test BFloat16(s*2.0^e/d) == bf16
end
for x in randn(100)
bf16 = BFloat16(x)
s,e,d = Base.decompose(bf16)
@test BFloat16(s*2.0^e/d) == bf16
end
end


@testset "Next/prevfloat(x,::Integer)" begin
x = one(BFloat16)
@test x == prevfloat(nextfloat(x,100),100)
@test x == nextfloat(prevfloat(x,100),100)

x = one(BFloat16)
@test x == prevfloat(nextfloat(x,100),100)
@test x == nextfloat(prevfloat(x,100),100)

x = -one(BFloat16)
@test x == prevfloat(nextfloat(x,100),100)
@test x == nextfloat(prevfloat(x,100),100)
x = -one(BFloat16)
@test x == prevfloat(nextfloat(x,100),100)
@test x == nextfloat(prevfloat(x,100),100)

x = one(BFloat16)
@test nextfloat(x,5) == prevfloat(x,-5)
@test prevfloat(x,-5) == nextfloat(x,5)
x = one(BFloat16)
@test nextfloat(x,5) == prevfloat(x,-5)
@test prevfloat(x,-5) == nextfloat(x,5)

@test isinf(nextfloat(floatmax(BFloat16),5))
@test prevfloat(floatmin(BFloat16),2^8) < 0
@test nextfloat(-floatmin(BFloat16),2^8) > 0
@test isinf(nextfloat(floatmax(BFloat16),5))
@test prevfloat(floatmin(BFloat16),2^8) < 0
@test nextfloat(-floatmin(BFloat16),2^8) > 0
end

@testset "maxintfloat" begin

a = maxintfloat(BFloat16)
@test a+1-1 == a-1 # the first +1 cannot be represented
@test a-1+1 == a # but -1 can
a = maxintfloat(BFloat16)
@test a+1-1 == a-1 # the first +1 cannot be represented
@test a-1+1 == a # but -1 can
end

@testset "rand sampling" begin
Random.seed!(123)
mi, ma = extrema(rand(BFloat16, 1_000_000))
Random.seed!(123)
mi, ma = extrema(rand(BFloat16, 1_000_000))

# zero should be the lowest BFloat16 sampled
@test mi === zero(BFloat16)
# zero should be the lowest BFloat16 sampled
@test mi === zero(BFloat16)

# prevfloat(one(BFloat16)) should be maximum
@test ma === prevfloat(one(BFloat16), 1)
# prevfloat(one(BFloat16)) should be maximum
@test ma === prevfloat(one(BFloat16), 1)
end

include("structure.jl")
include("mathfuncs.jl")
include("lowprecarrays.jl")

end # @testset "BFloat16s"
8 changes: 5 additions & 3 deletions test/structure.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ invphi3 = invphi * invphi * invphi
uint(x::BFloat16) = reinterpret(UInt16, x)

@testset "BFloat16 bits" begin
@test uint(two) == 0x4000
@test uint(half) == 0x3f00
@test signbit(two) == false
@test uint(two) == 0x4000
@test uint(half) == 0x3f00
@test bitstring(two) == "0100000000000000"
@test bitstring(half) == "0011111100000000"
@test signbit(two) == false
end

@testset "BFloat16 parts" begin
Expand Down
Loading