packages feed

number-length (empty) → 0.1.0.0

raw patch · 15 files changed

+1735/−0 lines, 15 filesdep +HUnitdep +QuickCheckdep +basesetup-changed

Dependencies added: HUnit, QuickCheck, base, criterion, number-length, tagged, test-framework, test-framework-hunit, test-framework-quickcheck2

Files

+ ChangeLog.md view
@@ -0,0 +1,13 @@+# ChangeLog / ReleaseNotes+++## Version 0.1.0.0++* First public release.+* Uploaded to [Hackage][]: <http://hackage.haskell.org/package/number-length-0.1.0.0>++++[Hackage]:+  http://hackage.haskell.org/+  "HackageDB (or just Hackage) is a collection of releases of Haskell packages."
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2015-2016, Peter Trško++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 Peter Trško nor the names of other+      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 THE COPYRIGHT+OWNER OR CONTRIBUTORS 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,49 @@+# Number Length++[![Hackage](http://img.shields.io/hackage/v/number-length.svg)][Hackage: number-length]+[![Hackage Dependencies](https://img.shields.io/hackage-deps/v/number-length.svg)](http://packdeps.haskellers.com/reverse/number-length)+[![Haskell Programming Language](https://img.shields.io/badge/language-Haskell-blue.svg)][Haskell.org]+[![BSD3 License](http://img.shields.io/badge/license-BSD3-brightgreen.svg)][tl;dr Legal: BSD3]++[![Build](https://travis-ci.org/trskop/number-length.svg)](https://travis-ci.org/trskop/number-length)+++## Description++Number length in decimal and hexadecimal representation.++There are situations when it is necessary to know the length of a number in+decimal or hexadecimal form. In example when allocating buffer while+serializing a number in to binary or human readable format.+++## Building Options++* `-fpedantic` (disabled by default)++  Pass additional warning flags to GHC.+++## License++The BSD 3-Clause License, see [LICENSE][] file for details.+++## Contributions++Contributions, pull requests and bug reports are welcome! Please don't be+afraid to contact author using GitHub or by e-mail.+++[Hackage: number-length]:+  http://hackage.haskell.org/package/number-length+  "number-length package on Hackage"+[Haskell.org]:+  http://www.haskell.org+  "The Haskell Programming Language"+[LICENSE]:+  https://github.com/trskop/number-length/blob/master/LICENSE+  "License of number-length package."+[tl;dr Legal: BSD3]:+  https://tldrlegal.com/license/bsd-3-clause-license-%28revised%29+  "BSD 3-Clause License (Revised)"
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ number-length.cabal view
@@ -0,0 +1,144 @@+name:                   number-length+version:                0.1.0.0+synopsis:+  Number of digits in a number in decimal and hexadecimal representation.+description:+  There are situations when it is necessary to know the length of a number in+  decimal or hexadecimal form. In example when allocating buffer while+  serializing a number in to binary or human readable format.++homepage:               https://github.com/trskop/number-length+license:                BSD3+license-file:           LICENSE+author:                 Peter Trško+maintainer:             peter.trsko@gmail.com+copyright:              (c) 2015-2016, Peter Trško+category:               Data+build-type:             Simple+cabal-version:          >=1.10++extra-source-files:     ChangeLog.md, README.md++flag pedantic+  description:          Pass additional warning flags to GHC.+  default:              False+  manual:               True++flag old-base+  description:          Supplement Data.Proxy, which is available since+                        base >=4.7, using tagged package.+  default:              False+  manual:               False++library+  hs-source-dirs:       src+  exposed-modules:+      Data.NumberLength+    , Data.NumberLength.Int+    , Data.NumberLength.Internal+    , Data.NumberLength.Word+  -- other-modules:++  default-language:     Haskell2010+  other-extensions:     NoImplicitPrelude++  if flag(old-base)+    build-depends:+        base >=4.5 && <4.7+      , tagged >=0.6 && <0.9+  else+    build-depends:+        base >=4.7 && <5++  ghc-options:          -Wall -fwarn-tabs++  if flag(pedantic)+    ghc-options:+      -fwarn-implicit-prelude+      -fwarn-missing-import-lists+--    -Werror++test-suite unit-tests+  hs-source-dirs:       src, test+  type:                 exitcode-stdio-1.0+  main-is:              unit-tests.hs+  other-modules:+      TestCase+    , TestCase.Data.NumberLength+    , TestCase.Data.NumberLength.Int+    , TestCase.Data.NumberLength.Word++  default-language:     Haskell2010+  other-extensions:     DefaultSignatures, NoImplicitPrelude++  build-depends:+    -- {{{ Test-suite dependencies --------------------------------------------+      HUnit >=1.2 && <2+      -- ^ Same constraints as test-framework-hunit+    , QuickCheck >=2.6 && <2.9+      -- ^ Same constraints as test-framework-quickcheck2==0.3.0.3.+    , test-framework >=0.8 && <1+      -- ^ Same constraint as test-framework-skip, other packages that+      -- depend on it have less restrictive bounds.+    , test-framework-hunit >=0.2.6 && <1+      -- ^ Lower versions have more restrictive bounds on test-framework.+    , test-framework-quickcheck2 >=0.3+      -- ^ There were changes in QuickCheck bounds in 0.2 branch and last one+      -- on it had a compilation failure on Hackage.+    -- }}} Test-suite dependencies --------------------------------------------++  if flag(old-base)+    build-depends:+        base >=4.5 && <4.7+      , tagged >=0.6 && <0.9+  else+    build-depends:+        base >=4.7 && <5++  ghc-options:          -Wall -fwarn-tabs++  if flag(pedantic)+    ghc-options:+      -fwarn-implicit-prelude+      -fwarn-missing-import-lists+--    -Werror++benchmark benchmark+  hs-source-dirs:       src, test+  type:                 exitcode-stdio-1.0+  main-is:              benchmark.hs+--other-modules:++  default-language:     Haskell2010+  other-extensions:     NoImplicitPrelude++  -- {{{ Dependencies of the library ------------------------------------------+  if flag(old-base)+    build-depends:+        base >=4.5 && <4.7+      , tagged >=0.6 && <0.9+  else+    build-depends:+        base >=4.7 && <5+  -- }}} Dependencies of the library ------------------------------------------++  build-depends:+      criterion >= 1.0.0.0 && < 2+    , number-length++  ghc-options:          -Wall -fwarn-tabs++  if flag(pedantic)+    ghc-options:+      -fwarn-implicit-prelude+      -fwarn-missing-import-lists+--    -Werror++source-repository head+  type:                 git+  location:             git://github.com/trskop/number-length.git++source-repository this+  type:                 git+  location:             git://github.com/trskop/number-length.git+  tag:                  v0.1.0.0
+ src/Data/NumberLength.hs view
@@ -0,0 +1,242 @@+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE NoImplicitPrelude #-}+-- |+-- Module:       $HEADER$+-- Description:  Polymorphic interface for getting number of digits of a number+--               in decimal or hexadecimal representation.+-- Copyright:    (c) 2015-2016, Peter Trško+-- License:      BSD3+--+-- Stability:    experimental+-- Portability:  DefaultSignatures, NoImplicitPrelude+--+-- Polymorphic interface for getting number of digits of a number in decimal or+-- hexadecimal representation.+module Data.NumberLength+    (+      NumberLength(..)+    , SignedNumberLength(..)+    , BoundedNumberLength(..)+    )+  where++import Prelude(Num((+)), fromIntegral)++import Data.Int (Int, Int16, Int32, Int64, Int8)+import Data.Ord (Ord((<)))+import Data.Proxy (Proxy)+import Data.Word (Word, Word16, Word32, Word64, Word8)++import Data.NumberLength.Int+    ( lengthInt+    , lengthInt16+    , lengthInt16hex+    , lengthInt32+    , lengthInt32hex+    , lengthInt64+    , lengthInt64hex+    , lengthInt8+    , lengthInt8hex+    , lengthIntHex+    )+import Data.NumberLength.Internal (either32or64)+import Data.NumberLength.Word+    ( lengthWord+    , lengthWord16+    , lengthWord16hex+    , lengthWord32+    , lengthWord32hex+    , lengthWord64+    , lengthWord64hex+    , lengthWord8+    , lengthWord8hex+    , lengthWordHex+    )+++-- | Get number of digits of a number in base 10 and base 16. Note the+-- following:+--+-- * There is no 'Num' constraint, so that type wrappers aren't forced to+--   provide instance for it. This is because there are things represented+--   using numbers, but they aren't numbers, e.g. telephone numbers.+--+-- * This type class doesn't handle signed numbers, in an intuitive way. See+--   also 'SignedNumberLength'.+--+-- * There is a special class for bounded numbers, see 'BoundedNumberLength',+--   that provides similar functionality as 'Prelude.Bounded', but for number+--   of digits in a number.+class NumberLength a where+    -- | Get number of digits in base 10 for specified number. Note that if+    -- number is signed, then this function will return length of its absolute+    -- value.+    --+    -- >>> numberLength (123 :: Int)+    -- 3+    -- >>> numberLength (-123 :: Int)+    -- 3+    --+    -- See also 'signedNumberLength'.+    numberLength :: a -> Int++    -- | Get number of digits in base 16 for specified number. Note that if+    -- number is signed, then this function will return length of its absolute+    -- value.+    --+    -- >>> numberLengthHex (123 :: Int)  -- 123 = 7b in hex+    -- 2+    -- >>> numberLengthHex (-123 :: Int)+    -- 2+    --+    -- See also 'signedNumberLengthHex'.+    numberLengthHex :: a -> Int++-- | Get number of digits of a signed number in base 10 and base 16.+class NumberLength a => SignedNumberLength a where+    {-# MINIMAL signedNumberLengthHex #-}++    -- | Get number of digits in base 10 for specified number.+    --+    -- >>> signedNumberLength (123 :: Int)+    -- 3+    -- >>> signedNumberLength (-123 :: Int)+    -- 4+    --+    -- Default implementation provided if @a@ has also 'Num' and 'Ord'+    -- instances:+    --+    -- @+    -- 'signedNumberLength' n = signLength + 'numberLength' n+    --   where+    --     signLength = if n < 0 then 1 else 0+    -- @+    signedNumberLength :: a -> Int++    default signedNumberLength :: (Num a, Ord a) => a -> Int+    signedNumberLength n = signLength + numberLength n+      where+        signLength = if n < 0 then 1 else 0++    -- | Get number of digits in base 16 for specified number.+    --+    -- >>> signedNumberLengthHex (123 :: Int)+    -- 2+    -- >>> signedNumberLengthHex (-123 :: Int)+    -- 16+    --+    -- Negative number is shown as ones' complement, e.g. @(-123 :: Int) =+    -- ffffffffffffff85@ on 64 bit platform.+    signedNumberLengthHex :: a -> Int++-- | Get maximum number of digits of a number in base 10 and 16. Minimal number+-- of digits is considered to be always 1, and therefore there is no method for+-- it.+class NumberLength a => BoundedNumberLength a where+    -- | Get maximum number of digits of a number in base 10.+    maxNumberLength :: Proxy a -> Int++    -- | Get maximum number of digits of a number in base 16.+    maxNumberLengthHex :: Proxy a -> Int++-- {{{ Int* -------------------------------------------------------------------++instance NumberLength Int where+    numberLength = lengthInt+    numberLengthHex = lengthIntHex++instance SignedNumberLength Int where+    signedNumberLengthHex n = numberLengthHex (fromIntegral n :: Word)++instance BoundedNumberLength Int where+    maxNumberLength _ = 10 `either32or64` 19+    maxNumberLengthHex _ = 8 `either32or64` 16++instance NumberLength Int64 where+    numberLength = lengthInt64+    numberLengthHex = lengthInt64hex++instance SignedNumberLength Int64 where+    signedNumberLengthHex n = numberLengthHex (fromIntegral n :: Word64)++instance BoundedNumberLength Int64 where+    maxNumberLength _ = 19+    maxNumberLengthHex _ = 16++instance NumberLength Int32 where+    numberLength = lengthInt32+    numberLengthHex = lengthInt32hex++instance SignedNumberLength Int32 where+    signedNumberLengthHex n = numberLengthHex (fromIntegral n :: Word32)++instance BoundedNumberLength Int32 where+    maxNumberLength _ = 10+    maxNumberLengthHex _ = 8++instance NumberLength Int16 where+    numberLength = lengthInt16+    numberLengthHex = lengthInt16hex++instance SignedNumberLength Int16 where+    signedNumberLengthHex n = numberLengthHex (fromIntegral n :: Word16)++instance BoundedNumberLength Int16 where+    maxNumberLength _ = 5+    maxNumberLengthHex _ = 4++instance NumberLength Int8 where+    numberLength = lengthInt8+    numberLengthHex = lengthInt8hex++instance SignedNumberLength Int8 where+    signedNumberLengthHex n = numberLengthHex (fromIntegral n :: Word8)++instance BoundedNumberLength Int8 where+    maxNumberLength _ = 3+    maxNumberLengthHex _ = 2++-- }}} Int* -------------------------------------------------------------------+-- {{{ Word* ------------------------------------------------------------------++instance NumberLength Word where+    numberLength = lengthWord+    numberLengthHex = lengthWordHex++instance BoundedNumberLength Word where+    maxNumberLength _ = 10 `either32or64` 20+    maxNumberLengthHex _ = 8 `either32or64` 16++instance NumberLength Word64 where+    numberLength = lengthWord64+    numberLengthHex = lengthWord64hex++instance BoundedNumberLength Word64 where+    maxNumberLength _ = 20+    maxNumberLengthHex _ = 16++instance NumberLength Word32 where+    numberLength = lengthWord32+    numberLengthHex = lengthWord32hex++instance BoundedNumberLength Word32 where+    maxNumberLength _ = 10+    maxNumberLengthHex _ = 8++instance NumberLength Word16 where+    numberLength = lengthWord16+    numberLengthHex = lengthWord16hex++instance BoundedNumberLength Word16 where+    maxNumberLength _ = 5+    maxNumberLengthHex _ = 4++instance NumberLength Word8 where+    numberLength = lengthWord8+    numberLengthHex = lengthWord8hex++instance BoundedNumberLength Word8 where+    maxNumberLength _ = 3+    maxNumberLengthHex _ = 2++-- }}} Word* ------------------------------------------------------------------
+ src/Data/NumberLength/Int.hs view
@@ -0,0 +1,252 @@+{-# LANGUAGE NoImplicitPrelude #-}+-- |+-- Module:       $HEADER$+-- Description:  Get number of digits of a number from a Int-family of numbers+--               in decimal or hexadecimal representation.+-- Copyright:    (c) 2015-2016, Peter Trško+-- License:      BSD3+--+-- Stability:    experimental+-- Portability:  NoImplicitPrelude+--+-- Get number of digits of a number from a 'Int'-family of numbers in decimal+-- or hexadecimal representation.+module Data.NumberLength.Int+    (+    -- * Decimal+      lengthInt+    , lengthInt8+    , lengthInt16+    , lengthInt32+    , lengthInt64++    -- * Hexadecimal+    , lengthIntHex+    , lengthInt8hex+    , lengthInt16hex+    , lengthInt32hex+    , lengthInt64hex+    )+  where++import Prelude+    ( Bounded(minBound)+    , Integral(quot)+    , Num((+), negate)+    , fromIntegral+    )++import Data.Bool ((&&), otherwise)+import Data.Eq (Eq((==)))+import Data.Int (Int, Int16, Int32, Int64, Int8)+import Data.Ord (Ord((<), (>), (>=)))++import Data.NumberLength.Internal (either32or64)+++-- {{{ Decimal ----------------------------------------------------------------++lengthInt8 :: Int8 -> Int+lengthInt8 n+  | n < 0         = go (negate (fromIntegral n))+  | otherwise     = go (fromIntegral n)+  where+    go :: Int -> Int+    go m+      -- Maximum is 127 for positive and 128 for negative integer.+      | m < 10     = 1+      | m < 100    = 2+      | otherwise  = 3+{-# INLINE lengthInt8 #-}++lengthInt16 :: Int16 -> Int+lengthInt16 n+  | n < 0     = go (negate (fromIntegral n))+  | otherwise = go (fromIntegral n)+  where+    -- Maximum is 32767 for positive and 32768 for negative integer.+    go :: Int -> Int+    go m+      | m < 10     = 1+      | m < 100    = 2+      | m < 1000   = 3+      | m < 10000  = 4+      | otherwise  = 5+{-# INLINE lengthInt16 #-}++lengthInt32 :: Int32 -> Int+lengthInt32 n+  | n == minBound = 10  -- "negate minBound" is out of range of Int32.+  | n < 0         = go (negate (fromIntegral n))+  | otherwise     = go (fromIntegral n)+  where+    -- Maximum is 2147483647 for positive and 2147483648 for negative integer.+    go :: Int -> Int+    go m+      | m < 10         = 1+      | m < 100        = 2+      | m < 1000       = 3+      | m < 10000      = 4+      | m >= 100000000 = 8 + go (m `quot` 100000000)+      | otherwise      = 4 + go (m `quot` 10000)+        -- m >= 10000+{-# INLINE lengthInt32 #-}++lengthInt64 :: Int64 -> Int+lengthInt64 n+  | n == minBound = 19 -- "negate minBound" is out of range of Int64+  | n < 0         = go (negate n)+  | otherwise     = go n+  where+    -- Maximum is 9223372036854775807 for positive and 9223372036854775808+    -- for negative integer.+    go m+      | m < 10                 = 1+      | m < 100                = 2+      | m < 1000               = 3+      | m < 10000              = 4+      | m >= 10000000000000000 = 16 + go (m `quot` 10000000000000000)+      | m >= 100000000         = 8  + go (m `quot` 100000000)+      | otherwise              = 4  + go (m `quot` 10000)+        -- m >= 10000+{-# INLINE lengthInt64 #-}++lengthInt :: Int -> Int+lengthInt n = l32 `either32or64` l64+  where+    -- Same code as lengthInt64:+    l64+      | n == minBound = 19 -- "negate minBound" is out of range of Int64+      | n < 0         = go (negate n)+      | otherwise     = go n+      where+        -- Maximum is 9223372036854775807 for positive and 9223372036854775808+        -- for negative integer.+        go m+          | m < 10                 = 1+          | m < 100                = 2+          | m < 1000               = 3+          | m < 10000              = 4+          | m >= 10000000000000000 = 16 + go (m `quot` 10000000000000000)+          | m >= 100000000         = 8  + go (m `quot` 100000000)+          | otherwise              = 4  + go (m `quot` 10000)+            -- m >= 10000++    -- Same code as lengthInt32:+    l32+      | n == minBound = 10  -- "negate minBound" is out of range of Int32.+      | n < 0         = go (negate n)+      | otherwise     = go n+      where+        -- Maximum is 2147483647 for positive and 2147483648 for negative integer.+        go m+          | m < 10         = 1+          | m < 100        = 2+          | m < 1000       = 3+          | m < 10000      = 4+          | m >= 100000000 = 8 + go (m `quot` 100000000)+          | otherwise      = 4 + go (m `quot` 10000)+            -- m >= 10000+{-# INLINE lengthInt #-}++-- }}} Decimal ----------------------------------------------------------------++-- {{{ Hexadecimal ------------------------------------------------------------++lengthInt8hex :: Int8 -> Int+lengthInt8hex n+  | n < 16 && n > -16 = 1+  | otherwise         = 2+  -- Maximum is 127 = 0x7f for positive and 128 = 0x80 for negative integer.+{-# INLINE lengthInt8hex #-}++lengthInt16hex :: Int16 -> Int+lengthInt16hex n+  | n < 0     = go (negate (fromIntegral n))+  | otherwise = go (fromIntegral n)+  where+    -- Maximum is 32767 = 0x7fff for positive and 32768 = 0x8000 for negative+    -- integer.+    go :: Int -> Int+    go m+      | m < 0x10   = 1+      | m < 0x100  = 2+      | m < 0x1000 = 3+      | otherwise  = 4+{-# INLINE lengthInt16hex #-}++lengthInt32hex :: Int32 -> Int+lengthInt32hex n+  | n == minBound = 8   -- "negate minBound" is out of range of Int32.+  | n < 0         = go (negate (fromIntegral n))+  | otherwise     = go (fromIntegral n)+  where+    -- Maximum is 2147483647 = 0x7fffffff for positive and+    -- 2147483648 = 0x80000000 for negative integer.+    go :: Int -> Int+    go m+      | m < 0x10    = 1+      | m < 0x100   = 2+      | m < 0x1000  = 3+      | m < 0x10000 = 4+      | otherwise   = 4 + go (m `quot` 0x10000)+        -- m >= 0x10000+{-# INLINE lengthInt32hex #-}++lengthInt64hex :: Int64 -> Int+lengthInt64hex n+  | n == minBound = 16 -- "negate minBound" is out of range of Int64+  | n < 0         = if n == minBound then 16 else go (negate n)+  | otherwise     = go n+  where+    -- Maximum is 9223372036854775807 = 0x7fffffffffffffff for positive and+    -- 9223372036854775808 = 0x8000000000000000 for negative integer.+    go m+      | m <  0x10        = 1+      | m <  0x100       = 2+      | m <  0x1000      = 3+      | m <  0x10000     = 4+      | m >= 0x100000000 = 8  + go (m `quot` 0x100000000)+      | otherwise        = 4  + go (m `quot` 0x10000)+        -- m >= 0x10000+{-# INLINE lengthInt64hex #-}++lengthIntHex :: Int -> Int+lengthIntHex n = l32hex `either32or64` l64hex+  where+    -- Same code as lengthInt64hex:+    l64hex+      | n == minBound = 16 -- "negate minBound" is out of range of Int64+      | n < 0         = if n == minBound then 16 else go (negate n)+      | otherwise     = go n+      where+        -- Maximum is 9223372036854775807 = 0x7fffffffffffffff for positive and+        -- 9223372036854775808 = 0x8000000000000000 for negative integer.+        go m+          | m <  0x10        = 1+          | m <  0x100       = 2+          | m <  0x1000      = 3+          | m <  0x10000     = 4+          | m >= 0x100000000 = 8  + go (m `quot` 0x100000000)+          | otherwise        = 4  + go (m `quot` 0x10000)+            -- m >= 0x10000++    -- Same code as lengthInt32hex:+    l32hex+      | n == minBound = 8   -- "negate minBound" is out of range of Int32.+      | n < 0         = go (negate n)+      | otherwise     = go n+      where+        -- Maximum is 2147483647 = 0x7fffffff for positive and+        -- 2147483648 = 0x80000000 for negative integer.+        go :: Int -> Int+        go m+          | m < 0x10    = 1+          | m < 0x100   = 2+          | m < 0x1000  = 3+          | m < 0x10000 = 4+          | otherwise   = 4 + go (m `quot` 0x10000)+            -- m >= 0x10000+{-# INLINE lengthIntHex #-}++-- }}} Hexadecimal ------------------------------------------------------------
+ src/Data/NumberLength/Internal.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE NoImplicitPrelude #-}+-- |+-- Module:       $HEADER$+-- Description:  Internally used utilities.+-- Copyright:    (c) 2015, Peter Trško+-- License:      BSD3+--+-- Stability:    unstable+-- Portability:  CPP, NoImplicitPrelude+module Data.NumberLength.Internal+  where++import Prelude (error)++#if MIN_VERSION_base(4,7,0)+import Data.Bits (FiniteBits(finiteBitSize))+#else+import Data.Bits (Bits(bitSize))+#endif++import Data.Function (($))+import Data.Monoid ((<>))+import Data.Word (Word)+import Text.Show (Show(show))+++-- | Returns one of its arguments, depending on bit size of 'Word' type on+-- current hardware.+either32or64+    :: a+    -- ^ Used in case when 'Word' is 32bit long.+    -> a+    -- ^ Used in case when 'Word' is 64bit long.+    -> a+either32or64 on32bit on64bit = case wordSize (0 :: Word) of+    32 -> on32bit+    64 -> on64bit+    bs -> error $ "Data.NumberLength.either32or64: " <> show bs+        <> ": System uses Word size not supported by this library."+  where+    wordSize =+#if MIN_VERSION_base(4,7,0)+        finiteBitSize+#else+        bitSize+#endif+{-# INLINE either32or64 #-}
+ src/Data/NumberLength/Word.hs view
@@ -0,0 +1,136 @@+{-# LANGUAGE NoImplicitPrelude #-}+-- |+-- Module:       $HEADER$+-- Description:  Get number of digits of a number from a Word-family of numbers+--               in decimal or hexadecimal representation.+-- Copyright:    (c) 2015, Peter Trško+-- License:      BSD3+--+-- Stability:    experimental+-- Portability:  NoImplicitPrelude+--+-- Get number of digits of a number from a 'Word'-family of numbers in decimal+-- or hexadecimal representation.+module Data.NumberLength.Word+    (+    -- * Decimal+      lengthWord+    , lengthWord8+    , lengthWord16+    , lengthWord32+    , lengthWord64++    -- * Hexadecimal+    , lengthWordHex+    , lengthWord8hex+    , lengthWord16hex+    , lengthWord32hex+    , lengthWord64hex+    )+  where++import Prelude+    ( Integral(quot)+    , Num((+))+    , fromIntegral+    )++import Data.Bool (otherwise)+import Data.Int (Int)+import Data.Ord (Ord((<), (>=)))+import Data.Word (Word, Word16, Word32, Word64, Word8)++import Data.NumberLength.Internal (either32or64)+++-- {{{ Decimal ----------------------------------------------------------------++lengthWord8 :: Word8 -> Int+lengthWord8 n   -- Maximum is 255.+  | n < 10     = 1+  | n < 100    = 2+  | otherwise  = 3+{-# INLINE lengthWord8 #-}++lengthWord16 :: Word16 -> Int+lengthWord16 n   -- Maximum is 65535.+  | n < 10     = 1+  | n < 100    = 2+  | n < 1000   = 3+  | n < 10000  = 4+  | otherwise  = 5+{-# INLINE lengthWord16 #-}++lengthWord32 :: Word32 -> Int+lengthWord32 n   -- Maximum is 4294967295.+  | n < 10         = 1+  | n < 100        = 2+  | n < 1000       = 3+  | n < 10000      = 4+  | n >= 100000000 = 8 + lengthWord32 (n `quot` 100000000)+  | otherwise      = 4 + lengthWord32 (n `quot` 10000)+    -- n >= 10000+{-# INLINE lengthWord32 #-}++lengthWord64 :: Word64 -> Int+lengthWord64 n   -- Maximum is 18446744073709551615.+  | n < 10                 = 1+  | n < 100                = 2+  | n < 1000               = 3+  | n < 10000              = 4+  | n >= 10000000000000000 = 16 + lengthWord64 (n `quot` 10000000000000000)+  | n >= 100000000         = 8  + lengthWord64 (n `quot` 100000000)+  | otherwise              = 4  + lengthWord64 (n `quot` 10000)+    -- n >= 10000+{-# INLINE lengthWord64 #-}++lengthWord :: Word -> Int+lengthWord n =+    lengthWord32 (fromIntegral n) `either32or64` lengthWord64 (fromIntegral n)+{-# INLINE lengthWord #-}++-- }}} Decimal ----------------------------------------------------------------++-- {{{ Hexadecimal ------------------------------------------------------------++lengthWord8hex :: Word8 -> Int+lengthWord8hex n    -- Maximum is 255 = 0xff.+  | n < 16    = 1+  | otherwise = 2+{-# INLINE lengthWord8hex #-}++lengthWord16hex :: Word16 -> Int+lengthWord16hex n   -- Maximum is 65535 = 0xffff.+  | n < 0x10   = 1+  | n < 0x100  = 2+  | n < 0x1000 = 3+  | otherwise  = 4+{-# INLINE lengthWord16hex #-}++lengthWord32hex :: Word32 -> Int+lengthWord32hex n   -- Maximum is 4294967295 = 0xffffffff.+  | n < 0x10    = 1+  | n < 0x100   = 2+  | n < 0x1000  = 3+  | n < 0x10000 = 4+  | otherwise   = 4 + lengthWord32hex (n `quot` 0x10000)+    -- n >= 0x10000+{-# INLINE lengthWord32hex #-}++lengthWord64hex :: Word64 -> Int+lengthWord64hex n   -- Maximum is 18446744073709551615 = 0xffffffffffffffff.+  | n <  0x10        = 1+  | n <  0x100       = 2+  | n <  0x1000      = 3+  | n <  0x10000     = 4+  | n >= 0x100000000 = 8 + lengthWord64hex (n `quot` 0x100000000)+  | otherwise        = 4 + lengthWord64hex (n `quot` 0x10000)+    -- n >= 0x10000+{-# INLINE lengthWord64hex #-}++lengthWordHex :: Word -> Int+lengthWordHex n = lengthWord32hex (fromIntegral n)+    `either32or64` lengthWord64hex (fromIntegral n)+{-# INLINE lengthWordHex #-}++-- }}} Hexadecimal ------------------------------------------------------------
+ test/TestCase.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE NoImplicitPrelude #-}+-- |+-- Module:       $HEADER$+-- Description:  All test cases aggregated and exported as tests :: [Test].+-- Copyright:    (c) 2015, Peter Trško+-- License:      BSD3+--+-- Stability:    stable+-- Portability:  NoImplicitPrelude+--+-- All test cases aggregated and exported as @tests :: ['Test']@.+module TestCase (tests)+    where++import Test.Framework (Test, testGroup)++import qualified TestCase.Data.NumberLength.Int as NumberLength.Int (tests)+import qualified TestCase.Data.NumberLength as NumberLength (tests)+import qualified TestCase.Data.NumberLength.Word as NumberLength.Word (tests)+++tests :: [Test]+tests =+    [ testGroup "Data.NumberLength.Int" NumberLength.Int.tests+    , testGroup "Data.NumberLength.Word" NumberLength.Word.tests+    , testGroup "Data.NumberLength" NumberLength.tests+    ]
+ test/TestCase/Data/NumberLength.hs view
@@ -0,0 +1,150 @@+{-# LANGUAGE NoImplicitPrelude #-}+-- |+-- Module:       $HEADER$+-- Description:  TODO+-- Copyright:    (c) 2015, Peter Trško+-- License:      BSD3+--+-- Stability:    experimental+-- Portability:  NoImplicitPrelude+module TestCase.Data.NumberLength+  where++import Prelude (Bounded(maxBound))++import Control.Applicative (liftA2)+import Data.Bool (Bool)+import Data.Eq (Eq((==)))+import Data.Function (($))+import Data.Int (Int, Int16, Int32, Int64, Int8)+import Data.Proxy (Proxy(Proxy))+import Data.Word (Word, Word16, Word32, Word64, Word8)++import Test.HUnit ((@?=))+import Test.Framework (Test, testGroup)+import Test.Framework.Providers.HUnit (testCase)+import Test.Framework.Providers.QuickCheck2 (testProperty)++import Data.NumberLength+    ( NumberLength(numberLength, numberLengthHex)+    , BoundedNumberLength(maxNumberLength, maxNumberLengthHex)+    )+import Data.NumberLength.Int+    ( lengthInt+    , lengthInt16+    , lengthInt16hex+    , lengthInt32+    , lengthInt32hex+    , lengthInt64+    , lengthInt64hex+    , lengthInt8+    , lengthInt8hex+    , lengthIntHex+    )+import Data.NumberLength.Word+    ( lengthWord+    , lengthWord16+    , lengthWord16hex+    , lengthWord32+    , lengthWord32hex+    , lengthWord64+    , lengthWord64hex+    , lengthWord8+    , lengthWord8hex+    , lengthWordHex+    )+++tests :: [Test]+tests =+    [ testGroup "class NumberLength"+        [ testGroup "numberLengthHex"+            [ testProperty "Int"    $ numberLength <==> lengthInt+            , testProperty "Int8"   $ numberLength <==> lengthInt8+            , testProperty "Int16"  $ numberLength <==> lengthInt16+            , testProperty "Int32"  $ numberLength <==> lengthInt32+            , testProperty "Int64"  $ numberLength <==> lengthInt64+            , testProperty "Word"   $ numberLength <==> lengthWord+            , testProperty "Word8"  $ numberLength <==> lengthWord8+            , testProperty "Word16" $ numberLength <==> lengthWord16+            , testProperty "Word32" $ numberLength <==> lengthWord32+            , testProperty "Word64" $ numberLength <==> lengthWord64+            ]++        , testGroup "numberLengthHex"+            [ testProperty "Int"    $ numberLengthHex <==> lengthIntHex+            , testProperty "Int8"   $ numberLengthHex <==> lengthInt8hex+            , testProperty "Int16"  $ numberLengthHex <==> lengthInt16hex+            , testProperty "Int32"  $ numberLengthHex <==> lengthInt32hex+            , testProperty "Int64"  $ numberLengthHex <==> lengthInt64hex+            , testProperty "Word"   $ numberLengthHex <==> lengthWordHex+            , testProperty "Word8"  $ numberLengthHex <==> lengthWord8hex+            , testProperty "Word16" $ numberLengthHex <==> lengthWord16hex+            , testProperty "Word32" $ numberLengthHex <==> lengthWord32hex+            , testProperty "Word64" $ numberLengthHex <==> lengthWord64hex+            ]+        ]++    , testGroup "class BoundedNumberLength"+        [ testGroup "maxNumberLength"+            [ testCase "Int"+                $ maxNumberLength int    @?= lengthInt    maxBound+            , testCase "Int8"+                $ maxNumberLength int8   @?= lengthInt8   maxBound+            , testCase "Int16"+                $ maxNumberLength int16  @?= lengthInt16  maxBound+            , testCase "Int32"+                $ maxNumberLength int32  @?= lengthInt32  maxBound+            , testCase "Int64"+                $ maxNumberLength int64  @?= lengthInt64  maxBound+            , testCase "Word"+                $ maxNumberLength word   @?= lengthWord   maxBound+            , testCase "Word8"+                $ maxNumberLength word8  @?= lengthWord8  maxBound+            , testCase "Word16"+                $ maxNumberLength word16 @?= lengthWord16 maxBound+            , testCase "Word32"+                $ maxNumberLength word32 @?= lengthWord32 maxBound+            , testCase "Word64"+                $ maxNumberLength word64 @?= lengthWord64 maxBound+            ]++        , testGroup "maxNumberLengthHex"+            [ testCase "Int"+                $ maxNumberLengthHex int    @?= lengthIntHex    maxBound+            , testCase "Int8"+                $ maxNumberLengthHex int8   @?= lengthInt8hex   maxBound+            , testCase "Int16"+                $ maxNumberLengthHex int16  @?= lengthInt16hex  maxBound+            , testCase "Int32"+                $ maxNumberLengthHex int32  @?= lengthInt32hex  maxBound+            , testCase "Int64"+                $ maxNumberLengthHex int64  @?= lengthInt64hex  maxBound+            , testCase "Word"+                $ maxNumberLengthHex word   @?= lengthWordHex   maxBound+            , testCase "Word8"+                $ maxNumberLengthHex word8  @?= lengthWord8hex  maxBound+            , testCase "Word16"+                $ maxNumberLengthHex word16 @?= lengthWord16hex maxBound+            , testCase "Word32"+                $ maxNumberLengthHex word32 @?= lengthWord32hex maxBound+            , testCase "Word64"+                $ maxNumberLengthHex word64 @?= lengthWord64hex maxBound+            ]+        ]+    ]+  where+    int    = Proxy :: Proxy Int+    int8   = Proxy :: Proxy Int8+    int16  = Proxy :: Proxy Int16+    int32  = Proxy :: Proxy Int32+    int64  = Proxy :: Proxy Int64++    word   = Proxy :: Proxy Word+    word8  = Proxy :: Proxy Word8+    word16 = Proxy :: Proxy Word16+    word32 = Proxy :: Proxy Word32+    word64 = Proxy :: Proxy Word64++(<==>) :: Eq b => (a -> b) -> (a -> b) -> a -> Bool+(<==>) = liftA2 (==)
+ test/TestCase/Data/NumberLength/Int.hs view
@@ -0,0 +1,257 @@+{-# LANGUAGE NoImplicitPrelude #-}+-- |+-- Module:       $HEADER$+-- Description:  TODO+-- Copyright:    (c) 2015, Peter Trško+-- License:      BSD3+--+-- Stability:    experimental+-- Portability:  NoImplicitPrelude+module TestCase.Data.NumberLength.Int+  where++import Prelude+    ( Bounded(maxBound, minBound)+    , Integral+    , Num(negate)+    , fromIntegral+    )++import Control.Applicative (liftA2)+import Data.Bool (Bool, otherwise)+import Data.Eq (Eq((==)))+import Data.Function ((.), ($), id)+import Data.Int (Int, Int16, Int32, Int64, Int8)+import qualified Data.List as List (dropWhile, length)+import Data.Ord (Ord((<)))+import Data.String (String)+import Text.Printf (PrintfArg, printf)+import Text.Show (Show(show))++import Test.HUnit (Assertion, (@?=))+import Test.Framework (Test)+import Test.Framework.Providers.HUnit (testCase)+import Test.Framework.Providers.QuickCheck2 (testProperty)++import Data.NumberLength.Int+    ( lengthInt+    , lengthInt16+    , lengthInt16hex+    , lengthInt32+    , lengthInt32hex+    , lengthInt64+    , lengthInt64hex+    , lengthInt8+    , lengthInt8hex+    , lengthIntHex+    )+++tests :: [Test]+tests =+    [ testCase     "lengthInt8 minBound"         test_lengthInt8_minBound+    , testCase     "lengthInt8 maxBound"         test_lengthInt8_maxBound+    , testProperty "lengthInt8 = length . show"  property_lengthInt8++    , testCase     "lengthInt16 minBound"        test_lengthInt16_minBound+    , testCase     "lengthInt16 maxBound"        test_lengthInt16_maxBound+    , testProperty "lengthInt16 = length . show" property_lengthInt16++    , testCase     "lengthInt32 minBound"        test_lengthInt32_minBound+    , testCase     "lengthInt32 maxBound"        test_lengthInt32_maxBound+    , testProperty "lengthInt32 = length . show" property_lengthInt32++    , testCase     "lengthInt64 minBound"        test_lengthInt64_minBound+    , testCase     "lengthInt64 maxBound"        test_lengthInt64_maxBound+    , testProperty "lengthInt64 = length . show" property_lengthInt64++    , testCase     "lengthInt minBound"          test_lengthInt_minBound+    , testCase     "lengthInt maxBound"          test_lengthInt_maxBound+    , testProperty "lengthInt = length . show"   property_lengthInt++    , testCase     "lengthInt8hex minBound"         test_lengthInt8hex_minBound+    , testCase     "lengthInt8hex maxBound"         test_lengthInt8hex_maxBound+    , testProperty "lengthInt8hex = length . show"  property_lengthInt8hex++    , testCase     "lengthInt16hex minBound"        test_lengthInt16hex_minBound+    , testCase     "lengthInt16hex maxBound"        test_lengthInt16hex_maxBound+    , testProperty "lengthInt16hex = length . show" property_lengthInt16hex++    , testCase     "lengthInt32hex minBound"        test_lengthInt32hex_minBound+    , testCase     "lengthInt32hex maxBound"        test_lengthInt32hex_maxBound+    , testProperty "lengthInt32hex = length . show" property_lengthInt32hex++    , testCase     "lengthInt64hex minBound"        test_lengthInt64hex_minBound+    , testCase     "lengthInt64hex maxBound"        test_lengthInt64hex_maxBound+    , testProperty "lengthInt64hex = length . show" property_lengthInt64hex++    , testCase     "lengthIntHex minBound"          test_lengthIntHex_minBound+    , testCase     "lengthIntHex maxBound"          test_lengthIntHex_maxBound+    , testProperty "lengthIntHex = length . show"   property_lengthIntHex+    ]++numberLengthDec :: Show n => n -> Int+numberLengthDec = List.length . List.dropWhile (== '-') . show++numberLengthHex :: (PrintfArg n, Integral n, Ord n) => n -> Int+numberLengthHex n+  | n < 0     = numberLengthHex' . negate . int64 $ fromIntegral n+  | otherwise = numberLengthHex' n+  where+    numberLengthHex' :: PrintfArg n => n -> Int+    numberLengthHex' m = List.length (printf "%x" m :: String)++    int64 :: Int64 -> Int64+    int64 = id++(<==>) :: Eq b => (a -> b) -> (a -> b) -> a -> Bool+(<==>) = liftA2 (==)++-- {{{ Decimal ----------------------------------------------------------------+-- {{{ lengthInt8 -------------------------------------------------------------++test_lengthInt8_minBound, test_lengthInt8_maxBound :: Assertion++test_lengthInt8_minBound =+    lengthInt8 minBound @?= numberLengthDec (minBound :: Int8)++test_lengthInt8_maxBound =+    lengthInt8 maxBound @?= numberLengthDec (maxBound :: Int8)++property_lengthInt8 :: Int8 -> Bool+property_lengthInt8 = lengthInt8 <==> numberLengthDec++-- }}} lengthInt8 -------------------------------------------------------------+-- {{{ lengthInt16 ------------------------------------------------------------++test_lengthInt16_minBound, test_lengthInt16_maxBound :: Assertion++test_lengthInt16_minBound =+    lengthInt16 minBound @?= numberLengthDec (minBound :: Int16)++test_lengthInt16_maxBound =+    lengthInt16 maxBound @?= numberLengthDec (maxBound :: Int16)++property_lengthInt16 :: Int16 -> Bool+property_lengthInt16 = lengthInt16 <==> numberLengthDec++-- }}} lengthInt16 ------------------------------------------------------------+-- {{{ lengthInt32 ------------------------------------------------------------++test_lengthInt32_minBound, test_lengthInt32_maxBound :: Assertion++test_lengthInt32_minBound =+    lengthInt32 minBound @?= numberLengthDec (minBound :: Int32)++test_lengthInt32_maxBound =+    lengthInt32 maxBound @?= numberLengthDec (maxBound :: Int32)++property_lengthInt32 :: Int32 -> Bool+property_lengthInt32 = lengthInt32 <==> numberLengthDec++-- }}} lengthInt32 ------------------------------------------------------------+-- {{{ lengthInt64 ------------------------------------------------------------++test_lengthInt64_minBound, test_lengthInt64_maxBound :: Assertion++test_lengthInt64_minBound =+    lengthInt64 minBound @?= numberLengthDec (minBound :: Int64)++test_lengthInt64_maxBound =+    lengthInt64 maxBound @?= numberLengthDec (maxBound :: Int64)++property_lengthInt64 :: Int64 -> Bool+property_lengthInt64 = lengthInt64 <==> numberLengthDec++-- }}} lengthInt64 ------------------------------------------------------------+-- {{{ lengthInt --------------------------------------------------------------++test_lengthInt_minBound, test_lengthInt_maxBound :: Assertion++test_lengthInt_minBound =+    lengthInt minBound @?= numberLengthDec (minBound :: Int)++test_lengthInt_maxBound =+    lengthInt maxBound @?= numberLengthDec (maxBound :: Int)++property_lengthInt :: Int -> Bool+property_lengthInt = lengthInt <==> numberLengthDec++-- }}} lengthInt --------------------------------------------------------------+-- }}} Decimal ----------------------------------------------------------------++-- {{{ Hexadecimal ------------------------------------------------------------+-- {{{ lengthInt8hex ----------------------------------------------------------++test_lengthInt8hex_minBound, test_lengthInt8hex_maxBound :: Assertion++test_lengthInt8hex_minBound =+    lengthInt8hex minBound @?= numberLengthHex (minBound :: Int8)++test_lengthInt8hex_maxBound =+    lengthInt8hex maxBound @?= numberLengthHex (maxBound :: Int8)++property_lengthInt8hex :: Int8 -> Bool+property_lengthInt8hex = lengthInt8hex <==> numberLengthHex++-- }}} lengthInt8hex ----------------------------------------------------------+-- {{{ lengthInt16hex ---------------------------------------------------------++test_lengthInt16hex_minBound, test_lengthInt16hex_maxBound :: Assertion++test_lengthInt16hex_minBound =+    lengthInt16hex minBound @?= numberLengthHex (minBound :: Int16)++test_lengthInt16hex_maxBound =+    lengthInt16hex maxBound @?= numberLengthHex (maxBound :: Int16)++property_lengthInt16hex :: Int16 -> Bool+property_lengthInt16hex = lengthInt16hex <==> numberLengthHex++-- }}} lengthInt16hex ---------------------------------------------------------+-- {{{ lengthInt32hex ---------------------------------------------------------++test_lengthInt32hex_minBound, test_lengthInt32hex_maxBound :: Assertion++test_lengthInt32hex_minBound =+    lengthInt32hex minBound @?= numberLengthHex (minBound :: Int32)++test_lengthInt32hex_maxBound =+    lengthInt32hex maxBound @?= numberLengthHex (maxBound :: Int32)++property_lengthInt32hex :: Int32 -> Bool+property_lengthInt32hex = lengthInt32hex <==> numberLengthHex++-- }}} lengthInt32hex ---------------------------------------------------------+-- {{{ lengthInt64hex ---------------------------------------------------------++test_lengthInt64hex_minBound, test_lengthInt64hex_maxBound :: Assertion++test_lengthInt64hex_minBound =+    lengthInt64hex minBound @?= 16 -- negate issue++test_lengthInt64hex_maxBound =+    lengthInt64hex maxBound @?= numberLengthHex (maxBound :: Int64)++property_lengthInt64hex :: Int64 -> Bool+property_lengthInt64hex = lengthInt64hex <==> numberLengthHex++-- }}} lengthInt64hex ---------------------------------------------------------+-- {{{ lengthIntHex -----------------------------------------------------------++test_lengthIntHex_minBound, test_lengthIntHex_maxBound :: Assertion++test_lengthIntHex_minBound = lengthIntHex minBound @?=+    -- Handling of "negate" issue:+    if (minBound :: Int) == fromIntegral (minBound :: Int32)+        then 8  -- 32bit+        else 16 -- 64bit++test_lengthIntHex_maxBound =+    lengthIntHex maxBound @?= numberLengthHex (maxBound :: Int)++property_lengthIntHex :: Int -> Bool+property_lengthIntHex = lengthIntHex <==> numberLengthHex++-- }}} lengthIntHex -----------------------------------------------------------+-- }}} Hexadecimal ------------------------------------------------------------
+ test/TestCase/Data/NumberLength/Word.hs view
@@ -0,0 +1,242 @@+{-# LANGUAGE NoImplicitPrelude #-}+-- |+-- Module:       $HEADER$+-- Description:  TODO+-- Copyright:    (c) 2015, Peter Trško+-- License:      BSD3+--+-- Stability:    experimental+-- Portability:  NoImplicitPrelude+module TestCase.Data.NumberLength.Word+  where++import Prelude (Bounded(maxBound, minBound), Integral, fromIntegral)++import Control.Applicative (liftA2)+import Data.Bool (Bool)+import Data.Eq (Eq((==)))+import Data.Function ((.))+import Data.Int (Int)+import qualified Data.List as List (length)+import Data.String (String)+import Data.Word (Word, Word16, Word32, Word64, Word8)+import Text.Printf (PrintfArg, printf)+import Text.Show (Show(show))++import Test.HUnit (Assertion, (@?=))+import Test.Framework (Test)+import Test.Framework.Providers.HUnit (testCase)+import Test.Framework.Providers.QuickCheck2 (testProperty)++import Data.NumberLength.Word+    ( lengthWord+    , lengthWord16+    , lengthWord16hex+    , lengthWord32+    , lengthWord32hex+    , lengthWord64+    , lengthWord64hex+    , lengthWord8+    , lengthWord8hex+    , lengthWordHex+    )+++tests :: [Test]+tests =+    [ testCase "lengthWord8 minBound" test_lengthWord8_minBound+    , testCase "lengthWord8 maxBound" test_lengthWord8_maxBound+    , testProperty "lengthWord8 = length . show" property_lengthWord8++    , testCase "lengthWord16 minBound" test_lengthWord16_minBound+    , testCase "lengthWord16 maxBound" test_lengthWord16_maxBound+    , testProperty "lengthWord16 = length . show" property_lengthWord16++    , testCase "lengthWord32 minBound" test_lengthWord32_minBound+    , testCase "lengthWord32 maxBound" test_lengthWord32_maxBound+    , testProperty "lengthWord32 = length . show" property_lengthWord32++    , testCase "lengthWord64 minBound" test_lengthWord64_minBound+    , testCase "lengthWord64 maxBound" test_lengthWord64_maxBound+    , testProperty "lengthWord64 = length . show" property_lengthWord64++    , testCase "lengthWord minBound" test_lengthWord_minBound+    , testCase "lengthWord maxBound" test_lengthWord_maxBound+    , testProperty "lengthWord = length . show" property_lengthWord++    , testCase "lengthWord8hex minBound" test_lengthWord8hex_minBound+    , testCase "lengthWord8hex maxBound" test_lengthWord8hex_maxBound+    , testProperty "lengthWord8hex = length . show" property_lengthWord8++    , testCase "lengthWord16hex minBound" test_lengthWord16hex_minBound+    , testCase "lengthWord16hex maxBound" test_lengthWord16hex_maxBound+    , testProperty "lengthWord16hex = length . show" property_lengthWord16++    , testCase "lengthWord32hex minBound" test_lengthWord32hex_minBound+    , testCase "lengthWord32hex maxBound" test_lengthWord32hex_maxBound+    , testProperty "lengthWord32hex = length . show" property_lengthWord32++    , testCase "lengthWord64hex minBound" test_lengthWord64hex_minBound+    , testCase "lengthWord64hex maxBound" test_lengthWord64hex_maxBound+    , testProperty "lengthWord64hex = length . show" property_lengthWord64hex++    , testCase "lengthWordHex minBound" test_lengthWordHex_minBound+    , testCase "lengthWordHex maxBound" test_lengthWordHex_maxBound+    , testProperty "lengthWordHex = length . show" property_lengthWordHex+    ]++numberLength :: Show n => n -> Int+numberLength = List.length . show++numberLengthHex :: (PrintfArg n, Integral n) => n -> Int+numberLengthHex n =+    List.length (printf "%x" (fromIntegral n :: Word64) :: String)++(<==>) :: Eq b => (a -> b) -> (a -> b) -> a -> Bool+(<==>) = liftA2 (==)++-- {{{ Decimal ----------------------------------------------------------------+-- {{{ lengthWord8 ------------------------------------------------------------++test_lengthWord8_minBound, test_lengthWord8_maxBound :: Assertion++test_lengthWord8_minBound =+    lengthWord8 minBound @?= numberLength (minBound :: Word8)++test_lengthWord8_maxBound =+    lengthWord8 maxBound @?= numberLength (maxBound :: Word8)++property_lengthWord8 :: Word8 -> Bool+property_lengthWord8 = lengthWord8 <==> numberLength++-- }}} lengthWord8 ------------------------------------------------------------+-- {{{ lengthWord16 -----------------------------------------------------------++test_lengthWord16_minBound, test_lengthWord16_maxBound :: Assertion++test_lengthWord16_minBound =+    lengthWord16 minBound @?= numberLength (minBound :: Word16)++test_lengthWord16_maxBound =+    lengthWord16 maxBound @?= numberLength (maxBound :: Word16)++property_lengthWord16 :: Word16 -> Bool+property_lengthWord16 = lengthWord16 <==> numberLength++-- }}} lengthWord16 -----------------------------------------------------------+-- {{{ lengthWord32 -----------------------------------------------------------++test_lengthWord32_minBound, test_lengthWord32_maxBound :: Assertion++test_lengthWord32_minBound =+    lengthWord32 minBound @?= numberLength (minBound :: Word32)++test_lengthWord32_maxBound =+    lengthWord32 maxBound @?= numberLength (maxBound :: Word32)++property_lengthWord32 :: Word32 -> Bool+property_lengthWord32 = lengthWord32 <==> numberLength++-- }}} lengthWord32 -----------------------------------------------------------+-- {{{ lengthWord64 -----------------------------------------------------------++test_lengthWord64_minBound, test_lengthWord64_maxBound :: Assertion++test_lengthWord64_minBound =+    lengthWord64 minBound @?= numberLength (minBound :: Word64)++test_lengthWord64_maxBound =+    lengthWord64 maxBound @?= numberLength (maxBound :: Word64)++property_lengthWord64 :: Word64 -> Bool+property_lengthWord64 = lengthWord64 <==> numberLength++-- }}} lengthWord64 -----------------------------------------------------------+-- {{{ lengthWord -------------------------------------------------------------++test_lengthWord_minBound, test_lengthWord_maxBound :: Assertion++test_lengthWord_minBound =+    lengthWord minBound @?= numberLength (minBound :: Word)++test_lengthWord_maxBound =+    lengthWord maxBound @?= numberLength (maxBound :: Word)++property_lengthWord :: Word -> Bool+property_lengthWord = lengthWord <==> numberLength++-- }}} lengthWord -------------------------------------------------------------+-- }}} Decimal ----------------------------------------------------------------++-- {{{ Hexadecimal ------------------------------------------------------------+-- {{{ lengthWord8hex ---------------------------------------------------------++test_lengthWord8hex_minBound, test_lengthWord8hex_maxBound :: Assertion++test_lengthWord8hex_minBound =+    lengthWord8hex minBound @?= numberLengthHex (minBound :: Word8)++test_lengthWord8hex_maxBound =+    lengthWord8hex maxBound @?= numberLengthHex (maxBound :: Word8)++property_lengthWord8hex :: Word8 -> Bool+property_lengthWord8hex = lengthWord8hex <==> numberLengthHex++-- }}} lengthWord8hex ---------------------------------------------------------+-- {{{ lengthWord16hex --------------------------------------------------------++test_lengthWord16hex_minBound, test_lengthWord16hex_maxBound :: Assertion++test_lengthWord16hex_minBound =+    lengthWord16hex minBound @?= numberLengthHex (minBound :: Word16)++test_lengthWord16hex_maxBound =+    lengthWord16hex maxBound @?= numberLengthHex (maxBound :: Word16)++property_lengthWord16hex :: Word16 -> Bool+property_lengthWord16hex = lengthWord16hex <==> numberLengthHex++-- }}} lengthWord16hex --------------------------------------------------------+-- {{{ lengthWord32hex --------------------------------------------------------++test_lengthWord32hex_minBound, test_lengthWord32hex_maxBound :: Assertion++test_lengthWord32hex_minBound =+    lengthWord32hex minBound @?= numberLengthHex (minBound :: Word32)++test_lengthWord32hex_maxBound =+    lengthWord32hex maxBound @?= numberLengthHex (maxBound :: Word32)++property_lengthWord32hex :: Word32 -> Bool+property_lengthWord32hex = lengthWord32hex <==> numberLengthHex++-- }}} lengthWord32hex --------------------------------------------------------+-- {{{ lengthWord64hex --------------------------------------------------------++test_lengthWord64hex_minBound, test_lengthWord64hex_maxBound :: Assertion++test_lengthWord64hex_minBound =+    lengthWord64hex minBound @?= numberLengthHex (minBound :: Word64)++test_lengthWord64hex_maxBound =+    lengthWord64hex maxBound @?= numberLengthHex (maxBound :: Word64)++property_lengthWord64hex :: Word64 -> Bool+property_lengthWord64hex = lengthWord64hex <==> numberLengthHex++-- }}} lengthWord64hex --------------------------------------------------------+-- {{{ lengthWordHex ----------------------------------------------------------++test_lengthWordHex_minBound, test_lengthWordHex_maxBound :: Assertion++test_lengthWordHex_minBound =+    lengthWordHex minBound @?= numberLengthHex (minBound :: Word)++test_lengthWordHex_maxBound =+    lengthWordHex maxBound @?= numberLengthHex (maxBound :: Word)++property_lengthWordHex :: Word -> Bool+property_lengthWordHex = lengthWordHex <==> numberLengthHex++-- }}} lengthWordHex ----------------------------------------------------------+-- }}} Hexadecimal ------------------------------------------------------------
+ test/benchmark.hs view
@@ -0,0 +1,120 @@+{-# LANGUAGE NoImplicitPrelude #-}+-- |+-- Module:       Main+-- Description:  Benchmarks for low-level functions.+-- Copyright:    (c) 2016, Peter Trško+-- License:      BSD3+--+-- Stability:    stable+-- Portability:  NoImplicitPrelude+--+-- Benchmarks for low-level functions.+module Main (main)+  where++import Prelude (Bounded(minBound, maxBound))++import Data.Function (($))+import System.IO (IO)++import Criterion.Main (bench, defaultMain, nf)++import Data.NumberLength.Int+    ( lengthInt+    , lengthInt16+    , lengthInt16hex+    , lengthInt32+    , lengthInt32hex+    , lengthInt64+    , lengthInt64hex+    , lengthInt8+    , lengthInt8hex+    , lengthIntHex+    )+import Data.NumberLength.Word+    ( lengthWord+    , lengthWord16+    , lengthWord16hex+    , lengthWord32+    , lengthWord32hex+    , lengthWord64+    , lengthWord64hex+    , lengthWord8+    , lengthWord8hex+    , lengthWordHex+    )+++main :: IO ()+main = defaultMain+    [ bench "lengthInt minBound" $ nf lengthInt minBound+    , bench "lengthInt 0"        $ nf lengthInt 0+    , bench "lengthInt maxBound" $ nf lengthInt maxBound++    , bench "lengthInt8 minBound" $ nf lengthInt8 minBound+    , bench "lengthInt8 0"        $ nf lengthInt8 0+    , bench "lengthInt8 maxBound" $ nf lengthInt8 maxBound++    , bench "lengthInt16 minBound" $ nf lengthInt16 minBound+    , bench "lengthInt16 0"        $ nf lengthInt16 0+    , bench "lengthInt16 maxBound" $ nf lengthInt16 maxBound++    , bench "lengthInt32 minBound" $ nf lengthInt32 minBound+    , bench "lengthInt32 0"        $ nf lengthInt32 0+    , bench "lengthInt32 maxBound" $ nf lengthInt32 maxBound++    , bench "lengthInt64 minBound" $ nf lengthInt64 minBound+    , bench "lengthInt64 0"        $ nf lengthInt64 0+    , bench "lengthInt64 maxBound" $ nf lengthInt64 maxBound++    , bench "lengthIntHex minBound" $ nf lengthIntHex minBound+    , bench "lengthIntHex 0"        $ nf lengthIntHex 0+    , bench "lengthIntHex maxBound" $ nf lengthIntHex maxBound++    , bench "lengthInt8hex minBound" $ nf lengthInt8hex minBound+    , bench "lengthInt8hex 0"        $ nf lengthInt8hex 0+    , bench "lengthInt8hex maxBound" $ nf lengthInt8hex maxBound++    , bench "lengthInt16hex minBound" $ nf lengthInt16hex minBound+    , bench "lengthInt16hex 0"        $ nf lengthInt16hex 0+    , bench "lengthInt16hex maxBound" $ nf lengthInt16hex maxBound++    , bench "lengthInt32hex minBound" $ nf lengthInt32hex minBound+    , bench "lengthInt32hex 0"        $ nf lengthInt32hex 0+    , bench "lengthInt32hex maxBound" $ nf lengthInt32hex maxBound++    , bench "lengthInt64hex minBound" $ nf lengthInt64hex minBound+    , bench "lengthInt64hex 0"        $ nf lengthInt64hex 0+    , bench "lengthInt64hex maxBound" $ nf lengthInt64hex maxBound+++    , bench "lengthWord 0"        $ nf lengthWord 0+    , bench "lengthWord maxBound" $ nf lengthWord maxBound++    , bench "lengthWord8 0"        $ nf lengthWord8 0+    , bench "lengthWord8 maxBound" $ nf lengthWord8 maxBound++    , bench "lengthWord16 0"        $ nf lengthWord16 0+    , bench "lengthWord16 maxBound" $ nf lengthWord16 maxBound++    , bench "lengthWord32 0"        $ nf lengthWord32 0+    , bench "lengthWord32 maxBound" $ nf lengthWord32 maxBound++    , bench "lengthWord64 0"        $ nf lengthWord64 0+    , bench "lengthWord64 maxBound" $ nf lengthWord64 maxBound++    , bench "lengthWordHex 0"        $ nf lengthWordHex 0+    , bench "lengthWordHex maxBound" $ nf lengthWordHex maxBound++    , bench "lengthWord8hex 0"        $ nf lengthWord8hex 0+    , bench "lengthWord8hex maxBound" $ nf lengthWord8hex maxBound++    , bench "lengthWord16hex 0"        $ nf lengthWord16hex 0+    , bench "lengthWord16hex maxBound" $ nf lengthWord16hex maxBound++    , bench "lengthWord32hex 0"        $ nf lengthWord32hex 0+    , bench "lengthWord32hex maxBound" $ nf lengthWord32hex maxBound++    , bench "lengthWord64hex 0"        $ nf lengthWord64hex 0+    , bench "lengthWord64hex maxBound" $ nf lengthWord64hex maxBound+    ]
+ test/unit-tests.hs view
@@ -0,0 +1,23 @@+{-# LANGUAGE NoImplicitPrelude #-}+-- |+-- Module:       Main+-- Description:  Tests main+-- Copyright:    (c) 2015, Jan Šipr, Matej Kollár, Peter Trško+-- License:      BSD3+--+-- Stability:    stable+-- Portability:  NoImplicitPrelude+--+-- Tests main.+module Main (main)+    where++import System.IO (IO)++import Test.Framework (defaultMain)++import TestCase (tests)+++main :: IO ()+main = defaultMain tests