FloatingHex (empty) → 0.1
raw patch · 8 files changed
+248/−0 lines, 8 filesdep +basedep +template-haskellsetup-changed
Dependencies added: base, template-haskell
Files
- CHANGES.md +13/−0
- COPYRIGHT +5/−0
- Data/Numbers/FloatingHex.hs +111/−0
- FloatingHex.cabal +30/−0
- INSTALL +3/−0
- LICENSE +26/−0
- README.md +42/−0
- Setup.hs +18/−0
+ CHANGES.md view
@@ -0,0 +1,13 @@+* Hackage: <http://hackage.haskell.org/package/FloatingHex>+* GitHub: <http://github.com/LeventErkok/FloatingHex/>++* Latest Hackage released version: 0.1, 2017-01-14++### Version 0.1, 2017-01-14++ * First implementation. The quasiquoter and the pretty-printer are implemented.++ * NB. The pretty-printer is currently not 100% compatible with the %a modifier+ of C printf function. While it will print correct values, it will not always+ print the same string as C does. (Note that string representations are not+ unique for hexadecimal floats, similar to the scientific notation.)
+ COPYRIGHT view
@@ -0,0 +1,5 @@+Copyright (c) 2017, Levent Erkok (erkokl@gmail.com)+All rights reserved.++The FloatingHex library is distributed with the BSD3 license. See the LICENSE file+for details.
+ Data/Numbers/FloatingHex.hs view
@@ -0,0 +1,111 @@+-------------------------------------------------------------------------+-- |+-- Module : Data.Numbers.FloatingHex+-- Copyright : (c) Levent Erkok+-- License : BSD3+-- Maintainer : erkokl@gmail.com+-- Stability : experimental+--+-- Reading/Writing hexadecimal floating-point numbers.+--+-- See: <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf>, pages 57-58.+-- We slightly diverge from the standard and do not allow for the "floating-suffix,"+-- as the type inference of Haskell makes this unnecessary.+-----------------------------------------------------------------------------+module Data.Numbers.FloatingHex (hf, showHFloat) where++import Data.Char (toLower)+import Data.Ratio ((%))+import Numeric (showHex)++import qualified Language.Haskell.TH.Syntax as TH+import Language.Haskell.TH.Quote++-- | Turn a hexadecimal float to an internal double, if parseable.+parseHexFloat :: String -> Maybe Double+parseHexFloat = go0 . map toLower+ where go0 ('0':'x':rest) = go1 rest+ go0 _ = Nothing++ go1 cs = case break (== 'p') cs of+ (pre, 'p':'+':d) -> go2 pre d+ (pre, 'p': d) -> go2 pre d+ _ -> Nothing++ go2 cs = case break (== '.') cs of+ (pre, '.':post) -> construct pre post+ _ -> construct cs ""++ rd :: Read a => String -> Maybe a+ rd s = case reads s of+ [(x, "")] -> Just x+ _ -> Nothing++ construct pre post d = do a <- rd $ "0x" ++ pre ++ post+ e <- rd d+ return $ val a (length post) e++ val :: Integer -> Int -> Integer -> Double+ val a b e+ | e > 0 = fromRational $ (top * expt) % bot+ | True = fromRational $ top % (expt * bot)+ where top, bot, expt :: Integer+ top = a+ bot = 16 ^ b+ expt = 2 ^ abs e++-- | A quasiquoter for hexadecimal floating-point literals.+-- See: <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf>, pages 57-58.+-- We slightly diverge from the standard and do not allow for the "floating-suffix,"+-- as the type inference of Haskell makes this unnecessary.+--+-- Example:+--+-- > {-# LANGUAGE QuasiQuotes #-}+-- > import Data.Numbers.FloatingHex+-- >+-- > f :: Double+-- > f = [hf|0x1.f44abd5aa7ca4p+25|]+--+-- With these definitions, @f@ will be equal to the number @6.5574266708245546e7@+hf :: QuasiQuoter+hf = QuasiQuoter { quoteExp = q+ , quotePat = p+ , quoteType = error "Unexpected hexadecimal float in a type context"+ , quoteDec = error "Unexpected hexadecimal float in a declaration context"+ }+ where q :: String -> TH.Q TH.Exp+ q s = case parseHexFloat s of+ Just d -> TH.lift d+ Nothing -> fail $ "Invalid hexadecimal floating point number: |" ++ s ++ "|"++ p :: String -> TH.Q TH.Pat+ p s = case parseHexFloat s of+ Just d -> return (TH.LitP (TH.RationalL (toRational d)))+ Nothing -> fail $ "Invalid hexadecimal floating point number: |" ++ s ++ "|"++-- | Show a floating-point value in the hexadecimal format.+--+-- NB. While this function will print a faithful (i.e., correct) value, it is+-- not 100% compatible with the @%a@ modifier as found in the C's printf implementation.+--+-- >>> showHFloat (212.21 :: Double) ""+-- "0x1.a86b851eb851fp7"+-- >>> showHFloat (-12.76 :: Float) ""+-- "-0xc.c28f6p0"+showHFloat :: RealFloat a => a -> ShowS+showHFloat x+ | isNaN x = showString "nan"+ | isInfinite x = showString $ if x > 0 then "+inf" else "-inf"+ | isNegativeZero x = showString "-0x0p1"+ | x < 0 = showString $ "-0x" ++ body+ | True = showString $ "0x" ++ body+ where (m, n) = decodeFloat (abs x)+ pre = showHex m ""+ (pre', l) = case pre of+ "" -> error $ "impossible happened! " ++ show (pre, m)+ (f:p) -> (f : trim p, length p)+ trim s = case dropWhile (== '0') (reverse s) of+ "" -> ""+ t -> "." ++ reverse t+ body = pre' ++ "p" ++ show (n + 4 * l)
+ FloatingHex.cabal view
@@ -0,0 +1,30 @@+Name: FloatingHex+Version: 0.1+Synopsis: Read and write hexadecimal floating point numbers+Description: Read and write hexadecimal floating point numbers. Provides a quasiquoter for+ entering hex-float literals, and a function for printing them in hexadecimal.+ .+ See: <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf>, pages 57-58.+ We slightly diverge from the standard and do not allow for the "floating-suffix,"+ as the type inference of Haskell makes this unnecessary.+ .+ For details, please see: <http://github.com/LeventErkok/FloatingHex/>+License: BSD3+License-file: LICENSE+Author: Levent Erkok+Maintainer: erkokl@gmail.com+Copyright: Levent Erkok+Category: Tools+Build-type: Simple+Cabal-version: >= 1.10+Extra-Source-Files: INSTALL, README.md, COPYRIGHT, CHANGES.md++source-repository head+ type: git+ location: git://github.com/LeventErkok/FloatingHex.git++Library+ ghc-options : -Wall+ default-language: Haskell2010+ Build-Depends : base >= 4 && < 5, template-haskell+ Exposed-modules : Data.Numbers.FloatingHex
+ INSTALL view
@@ -0,0 +1,3 @@+The FloatingHex library can be installed simply by issuing cabal install like this:++ cabal install FloatingHex
+ LICENSE view
@@ -0,0 +1,26 @@+FloatingHex: Read/Write Hexadecimal Floating point values++Copyright (c) 2017, Levent Erkok (erkokl@gmail.com)+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:+ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.+ * Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.+ * Neither the name of the developer (Levent Erkok) nor the+ names of its contributors may be used to endorse or promote products+ derived from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL LEVENT ERKOK BE LIABLE FOR ANY+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,42 @@+## FloatingHex: Read/Write Hexadecimal floats++[](http://hackage.haskell.org/package/FloatingHex)+[](http://travis-ci.org/LeventErkok/FloatingHex)++### Hexadecimal Floats++For syntax reference, see: <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf>, pages 57-58.+We slightly diverge from the standard and do not allow for the "floating-suffix,"+as the type inference of Haskell makes this unnecessary. Some examples are:++```+ 0x1p+1+ 0x1p+8+ 0x1.b7p-1+ 0x1.fffffffffffffp+1023+ 0X1.921FB4D12D84AP-1+```++This format allows for concise and precise string representation for floating point numbers.++## Example++```haskell+{-# LANGUAGE QuasiQuotes #-}+import Data.Numbers.FloatingHex++-- expressions+f :: Double+f = [hf|0x1.f44abd5aa7ca4p+25|]++-- patterns+g :: Float -> String+g [hf|0x1p1|] = "two!"+g [hf|0x1p-1|] = "half!"+g d = "something else: " ++ show d++-- showing hexadecimal floats+test = showHFloat [hf|0x1.f44abd5aa7ca4p+25|] ""+```++(Note that while the quasiquoter allows for floating-point patterns, it is usually not a good idea to have floating-point literals used in pattern matching.)
+ Setup.hs view
@@ -0,0 +1,18 @@+-----------------------------------------------------------------------------+-- |+-- Module : Main+-- Copyright : (c) Levent Erkok+-- License : BSD3+-- Maintainer : erkokl@gmail.com+-- Stability : experimental+--+-- Setup module for FloatingHex+-----------------------------------------------------------------------------++{-# OPTIONS_GHC -Wall #-}+module Main(main) where++import Distribution.Simple++main :: IO ()+main = defaultMain