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

use TinyFloats;

plan 46;


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

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

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


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

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

# Signed Inf
check 0x7C00,  Inf;
check 0xFC00, -Inf;

# NaN
check 0x7E00,  NaN;

# One
check 0x3C00,  1e0;
check 0xBC00, -1e0;

# One + 1/1024
check 0x3C01,  (1e0 + 1/1024);
check 0xBC01, -(1e0 + 1/1024);

# One - 1/2048
check 0x3BFF,  (1e0 - 1/2048);
check 0xBBFF, -(1e0 - 1/2048);

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

# 16-bit max
check 0x7BFF,  65504e0;
check 0xFBFF, -65504e0;

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

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

# 16-bit smallest normal
check 0x0400,  1e0/(2**14);
check 0x8400, -1e0/(2**14);

# 1/3, rounded to nearest
check 0x3555,  .25e0 * (1365/1024);
check 0xB555, -.25e0 * (1365/1024);


done-testing;


