license: Fix copyright years in source files.
[altfloat.git] / Data / Floating / Types.hs
blob5db555599feb60016b165fa5273180dc9598dcac
1 {-
2 - Copyright (C) 2009-2010 Nick Bowler.
4 - License BSD2: 2-clause BSD license. See LICENSE for full terms.
5 - This is free software: you are free to change and redistribute it.
6 - There is NO WARRANTY, to the extent permitted by law.
7 -}
9 -- | Definition of the core floating point types and basic manipulation of
10 -- them.
11 {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, OverlappingInstances #-}
12 {-# LANGUAGE MagicHash #-}
13 module Data.Floating.Types (
14 Double(..), Float(..), FloatConvert(..)
15 ) where
17 import Prelude hiding (Double, Float)
18 import qualified GHC.Exts as GHC
19 import GHC.Integer
20 import GHC.Prim
21 import Foreign.C
23 import Data.Ratio
25 import Unsafe.Coerce
27 -- | The Double type. This is expected to be an identical declaration to
28 -- the one found in GHC.Prim. We avoid simply using GHC's type because we need
29 -- to define our own class instances.
30 data Double = D# Double#
32 -- | The Float type.
33 data Float = F# Float#
35 -- | This type is identical to CDouble. For some reason unknown to me, it is
36 -- impossible to marshal data from Double to CDouble without losing
37 -- information. The issue is further complicated by Foreign.C.Types not
38 -- exporting CDouble's constructor. Thus, to marshal data from Double to
39 -- CDouble, we construct an instance of this type and then use unsafeCoerce.
40 newtype FuckFFIDouble = FuckD Double
42 -- | The analogue of FuckFFIDouble for CFloat.
43 newtype FuckFFIFloat = FuckF Float
45 -- | Coercion to floating point types.
46 class FloatConvert a b where
47 -- | Convert to a floating point type. Conversions from integers and real
48 -- types are provided, as well as conversions between floating point types.
49 -- Conversions between floating point types preserve infinities, negative
50 -- zeros and NaNs.
51 toFloating :: a -> b
53 instance FloatConvert Double CDouble where
54 toFloating = unsafeCoerce . FuckD
56 instance FloatConvert CDouble Double where
57 toFloating f = let FuckD x = unsafeCoerce f in x
59 instance FloatConvert Float CFloat where
60 toFloating = unsafeCoerce . FuckF
62 instance FloatConvert CFloat Float where
63 toFloating f = let FuckF x = unsafeCoerce f in x
65 instance FloatConvert Double Float where
66 toFloating (D# x) = F# (double2Float# x)
68 instance FloatConvert Float Double where
69 toFloating (F# x) = D# (float2Double# x)
71 instance FloatConvert Integer Double where
72 toFloating x = D# (doubleFromInteger x)
74 instance FloatConvert Integer Float where
75 toFloating x = F# (floatFromInteger x)
77 instance Real a => FloatConvert a Double where
78 toFloating x = D# (num /## denom) where
79 !(D# num) = toFloating . numerator . toRational $ x
80 !(D# denom) = toFloating . denominator . toRational $ x
82 instance Real a => FloatConvert a Float where
83 toFloating x = F# (divideFloat# num denom) where
84 !(F# num) = toFloating . numerator . toRational $ x
85 !(F# denom) = toFloating . denominator . toRational $ x
87 instance FloatConvert a a where
88 toFloating = id