import numpy as np
from numpy import uint16, float16, float32, float64
from numpy.testing import *

import warnings

def assert_raises_fpe(strmatch, callable, *args, **kwargs):
    try:
        callable(*args, **kwargs)
    except FloatingPointError, exc:
        assert_(str(exc).find(strmatch) >= 0,
                "Did not raise floating point %s error" % strmatch)
    else:
        assert_(False,
                "Did not raise floating point %s error" % strmatch)

class TestHalf(TestCase):
    def setUp(self):
        # An array of all possible float16 values
        self.all_f16 = np.arange(0x10000, dtype=uint16)
        self.all_f16.dtype = float16
        self.all_f32 = np.array(self.all_f16, dtype=float32)
        self.all_f64 = np.array(self.all_f16, dtype=float64)

        # An array of all non-NaN float16 values, in sorted order
        self.nonan_f16 = np.concatenate(
                                    (np.arange(0xfc00,0x7fff,-1, dtype=uint16),
                                     np.arange(0x0000,0x7c01,1, dtype=uint16))
                                    )
        self.nonan_f16.dtype = float16
        self.nonan_f32 = np.array(self.nonan_f16, dtype=float32)
        self.nonan_f64 = np.array(self.nonan_f16, dtype=float64)

        # An array of all finite float16 values, in sorted order
        self.finite_f16 = self.nonan_f16[1:-1]
        self.finite_f32 = self.nonan_f32[1:-1]
        self.finite_f64 = self.nonan_f64[1:-1]

    def test_half_conversions(self):
        """Checks that all 16-bit values survive conversion
           to/from 32-bit and 64-bit float"""
        # Because the underlying routines preserve the NaN bits, every
        # value is preserved when converting to/from other floats.

        # Convert from float32 back to float16
        b = np.array(self.all_f32, dtype=float16)
        assert_equal(self.all_f16.view(dtype=uint16),
                     b.view(dtype=uint16))

        # Convert from float64 back to float16
        b = np.array(self.all_f64, dtype=float16)
        assert_equal(self.all_f16.view(dtype=uint16),
                     b.view(dtype=uint16))

        # Convert float16 to longdouble and back
        # This doesn't necessarily preserve the extra NaN bits,
        # so exclude NaNs.
        a_ld = np.array(self.nonan_f16, dtype=np.longdouble)
        b = np.array(a_ld, dtype=float16)
        assert_equal(self.nonan_f16.view(dtype=uint16),
                     b.view(dtype=uint16))

        # Check the range for which all integers can be represented
        i_int = np.arange(-2048,2049)