packages feed

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 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.)
@@ -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++[![Hackage version](http://img.shields.io/hackage/v/FloatingHex.svg?label=Hackage)](http://hackage.haskell.org/package/FloatingHex)+[![Build Status](http://img.shields.io/travis/LeventErkok/FloatingHex.svg?label=Build)](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