1 -- | This module provides an alternate definition of the floating point types
3 {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, OverlappingInstances #-}
4 {-# LANGUAGE ForeignFunctionInterface, MagicHash #-}
5 {-# INCLUDE cfloat.h #-}
6 module Data
.Floating
.Types
(
7 Float(..), Double(..), FloatConvert
(..)
10 import Prelude
hiding (Double, Float)
11 import qualified GHC
.Exts
as GHC
18 -- | For reasons unknown to me, we actually need to do foreign calls in order
19 -- to convert between floating types.
20 foreign import ccall unsafe
"double_to_float"
21 double_to_float
:: CDouble
-> CFloat
22 -- | The opposite of double_to_float.
23 foreign import ccall unsafe
"float_to_double"
24 float_to_double
:: CFloat
-> CDouble
26 -- | The Double type. This is expected to be an identical declaration to
27 -- the one found in GHC.Prim. We avoid simply using GHC's type because we need
28 -- to define our own class instances.
29 data Double = D
# Double#
32 data Float = F
# Float#
34 -- | This type is identical to CDouble. For some reason unknown to me, it is
35 -- impossible to marshal data from Double to CDouble without losing
36 -- information. The issue is further complicated by Foreign.C.Types not
37 -- exporting CDouble's constructor. Thus, to marshal data from Double to
38 -- CDouble, we construct an instance of this type and then use unsafeCoerce.
39 newtype FuckFFIDouble
= FuckD
Double
41 -- | The analogue of FuckFFIDouble for CFloat.
42 newtype FuckFFIFloat
= FuckF
Float
44 -- | Coercion to floating point types.
45 class FloatConvert a b
where
48 instance FloatConvert
Double CDouble
where
49 toFloating
= unsafeCoerce
. FuckD
51 instance FloatConvert CDouble
Double where
52 toFloating f
= let FuckD x
= unsafeCoerce f
in x
54 instance FloatConvert
Float CFloat
where
55 toFloating
= unsafeCoerce
. FuckF
57 instance FloatConvert CFloat
Float where
58 toFloating f
= let FuckF x
= unsafeCoerce f
in x
60 instance FloatConvert
Double Float where
61 toFloating
= toFloating
. double_to_float
. toFloating
63 instance FloatConvert
Float Double where
64 toFloating
= toFloating
. float_to_double
. toFloating
66 instance Integral a
=> FloatConvert a
Double where
67 toFloating x
= D
# (doubleFromInteger
(toInteger x
))
69 instance Integral a
=> FloatConvert a
Float where
70 toFloating x
= F
# (floatFromInteger
(toInteger x
))
72 instance FloatConvert a a
where