@@ -1,4 +1,4 @@
1−{-# LANGUAGE CPP, DeriveDataTypeable #-}
1+{-# LANGUAGE CPP, DeriveDataTypeable, UnboxedTuples #-}
2{-# OPTIONS_HADDOCK not-home #-}
2{-# OPTIONS_HADDOCK not-home #-}
@@ -20,6 +20,10 @@
20-- with the internals, as the functions here do just about nothing to
20-- with the internals, as the functions here do just about nothing to
21-- preserve data invariants. You have been warned!
21-- preserve data invariants. You have been warned!
23+#if defined(__GLASGOW_HASKELL__) && !defined(__HADDOCK__)
23module Data.Text.Internal
27module Data.Text.Internal
25 -- * Types
29 -- * Types
@@ -34,6 +38,10 @@ module Data.Text.Internal
35 -- * Utilities
39 -- * Utilities
41+ -- * Checked multiplication
37 -- * Debugging
45 -- * Debugging
38 , showText
46 , showText
@@ -41,10 +49,11 @@ module Data.Text.Internal
41#if defined(ASSERTS)
49#if defined(ASSERTS)
42import Control.Exception (assert)
50import Control.Exception (assert)
44−import Data.Bits ((.&.))
52+import Data.Bits
45−import qualified Data.Text.Array as A
53+import Data.Int (Int32, Int64)
46import Data.Text.Internal.Unsafe.Char (ord)
54import Data.Text.Internal.Unsafe.Char (ord)
47import Data.Typeable (Typeable)
55import Data.Typeable (Typeable)
56+import qualified Data.Text.Array as A
49-- | A space efficient, packed, unboxed Unicode text type.
58-- | A space efficient, packed, unboxed Unicode text type.
50data Text = Text
59data Text = Text
@@ -108,6 +117,51 @@ firstf :: (a -> c) -> Maybe (a,b) -> Maybe (c,b)
108firstf f (Just (a, b)) = Just (f a, b)
117firstf f (Just (a, b)) = Just (f a, b)
109firstf _ Nothing = Nothing
118firstf _ Nothing = Nothing
120+-- | Checked multiplication. Calls 'error' if the result would
122+mul :: Int -> Int -> Int
123+#if WORD_SIZE_IN_BITS == 64
124+mul a b = fromIntegral $ fromIntegral a `mul64` fromIntegral b
126+mul a b = fromIntegral $ fromIntegral a `mul32` fromIntegral b
131+-- | Checked multiplication. Calls 'error' if the result would
133+mul64 :: Int64 -> Int64 -> Int64
135+ | a >= 0 && b >= 0 = mul64_ a b
136+ | a >= 0 = -mul64_ a (-b)
137+ | b >= 0 = -mul64_ (-a) b
138+ | otherwise = mul64_ (-a) (-b)
142+mul64_ :: Int64 -> Int64 -> Int64
144+ | ahi > 0 && bhi > 0 = error "overflow"
145+ | top > 0x7fffffff = error "overflow"
146+ | total < 0 = error "overflow"
148+ where (# ahi, alo #) = (# a `shiftR` 32, a .&. 0xffffffff #)
149+ (# bhi, blo #) = (# b `shiftR` 32, b .&. 0xffffffff #)
150+ top = ahi * blo + alo * bhi
151+ total = (top `shiftL` 32) + alo * blo
152+{-# INLINE mul64_ #-}
154+-- | Checked multiplication. Calls 'error' if the result would
156+mul32 :: Int32 -> Int32 -> Int32
157+mul32 a b = case fromIntegral a * fromIntegral b of
158+ ab | ab < min32 || ab > max32 -> error "overflow"
159+ | otherwise -> fromIntegral ab
160+ where min32 = -0x80000000 :: Int64
111-- $internals
165-- $internals
113-- Internally, the 'Text' type is represented as an array of 'Word16'
167-- Internally, the 'Text' type is represented as an array of 'Word16'