### ----------------------------------------------------
### -- TinyFloats
### -- Licenses: Artistic-2.0
### -- Authors: Geoffrey Broadwell
### -- File: t/02-bfloat16.rakutest
### ----------------------------------------------------
use v6.d;
use Test;

use TinyFloats;

plan 50;


sub check($bf16, $num) {
    use Test;

    my $reduced  = bf16-from-num($num);
    my $expanded = num-from-bf16($bf16);

    # diag "Reduced: $reduced.fmt('0x%04x'), Expanded: $expanded.fmt('%.10f')";
    ok $reduced  == $bf16, "Able to reduce $num.fmt('%.10f') to $bf16.fmt('0x%04x')";
    ok $expanded == $num || $expanded.isNaN && $num.isNaN,
                            "Able to expand $bf16.fmt('0x%04x') to $num.fmt('%.10f')";
}


### Test cases below adapted from:
### https://en.wikipedia.org/wiki/Bfloat16_floating-point_format#Examples
### https://en.wikipedia.org/wiki/Half-precision_floating-point_format#Half_precision_examples

# Signed 0
check 0x0000,  0e0;
check 0x8000, -0e0;

# Signed Inf
check 0x7F80,  Inf;
check 0xFF80, -Inf;

# NaN
check 0x7FC0,  NaN;

# One
check 0x3F80,  1e0;
check 0xBF80, -1e0;

# One + 1/128
check 0x3F81,  (1e0 + 1/128);
check 0xBF81, -(1e0 + 1/128);

# One - 1/256
check 0x3F7F,  (1e0 - 1/256);
check 0xBF7F, -(1e0 - 1/256);

# Two
check 0x4000,  2e0;
check 0xC000, -2e0;

# 16-bit max
check 0x7F7F,  255e0 * 2**120;
check 0xFF7F, -255e0 * 2**120;

# 16-bit min
check 0x0001,  1e0/(2**133);
check 0x8001, -1e0/(2**133);

# 16-bit 2*min
check 0x0002,  1e0/(2**132);
check 0x8002, -1e0/(2**132);

# 16-bit smallest normal
check 0x0080,  1e0/(2**126);
check 0x8080, -1e0/(2**126);

# 1/3, rounded to nearest
check 0x3EAB,  .25e0 * (171/128);
check 0xBEAB, -.25e0 * (171/128);

# π, rounded to nearest
check 0x4049,  2e0 * (201/128);
check 0xC049, -2e0 * (201/128);


done-testing;


