+ (q, r) = n `quotRemInteger` p
+
+ jsplitb :: Integer -> [Integer] -> [Integer]
+ jsplitb p [] = []
+ jsplitb p (n:ns) = q : r : jsplitb p ns
+ where
+ (q, r) = n `quotRemInteger` p
+
+ -- Convert a number that has been split into digits in base BASE^2
+ -- this includes a last splitting step and then conversion of digits
+ -- that all fit into a machine word.
+ jprinth :: [Integer] -> String -> String
+ jprinth (n:ns) cs =
+ if q > 0 then jhead q $ jblock r $ jprintb ns cs
+ else jhead r $ jprintb ns cs
+ where
+ (q', r') = n `quotRemInteger` BASE
+ q = fromInteger q'
+ r = fromInteger r'
+
+ jprintb :: [Integer] -> String -> String
+ jprintb [] cs = cs
+ jprintb (n:ns) cs = jblock q $ jblock r $ jprintb ns cs
+ where
+ (q', r') = n `quotRemInteger` BASE
+ q = fromInteger q'
+ r = fromInteger r'
+
+ -- Convert an integer that fits into a machine word. Again, we have two
+ -- functions, one that drops leading zeros (jhead) and one that doesn't
+ -- (jblock)
+ jhead :: Int -> String -> String
+ jhead n cs
+ | n < 10 = case unsafeChr (ord '0' + n) of
+ c@(C# _) -> c : cs
+ | otherwise = case unsafeChr (ord '0' + r) of
+ c@(C# _) -> jhead q (c : cs)
+ where
+ (q, r) = n `quotRemInt` 10
+
+ jblock = jblock' {- ' -} DIGITS
+
+ jblock' :: Int -> Int -> String -> String
+ jblock' d n cs
+ | d == 1 = case unsafeChr (ord '0' + n) of
+ c@(C# _) -> c : cs
+ | otherwise = case unsafeChr (ord '0' + r) of
+ c@(C# _) -> jblock' (d - 1) q (c : cs)
+ where
+ (q, r) = n `quotRemInt` 10
+