    module TextBuilder.Domains.Digits where

    import qualified Data.Text.Array as TextArray
    import qualified TextBuilder.Domains.Digits.Codepoints as Codepoints
    import TextBuilder.Prelude
    import TextBuilderCore

    -- | Decimal digit.
    {-# INLINE decimalDigit #-}
    decimalDigit :: (Integral a) => a -> TextBuilder
    decimalDigit :: forall a. Integral a => a -> TextBuilder
    decimalDigit (a -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral -> Int
    n) =
      Int -> TextBuilder
    unicodeCodepoint (Int
    n Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    48)

    -- | Hexadecimal digit.
    {-# INLINE hexadecimalDigit #-}
    hexadecimalDigit :: (Integral a) => a -> TextBuilder
    hexadecimalDigit :: forall a. Integral a => a -> TextBuilder
    hexadecimalDigit (a -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral -> Int
    n) =
      if Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    9
        then Int -> TextBuilder
    unicodeCodepoint (Int
    n Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    48)
        else Int -> TextBuilder
    unicodeCodepoint (Int
    n Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    87)

    {-# INLINE customFixedNumeralSystem #-}
    customFixedNumeralSystem ::
      (FiniteBits a, Integral a) =>
      -- | Number of bits per digit.
      Int ->
      -- | Projection to codepoint with handling of overflow.
      (a -> a) ->
      -- | Value.
      a ->
      TextBuilder
    customFixedNumeralSystem :: forall a.
    (FiniteBits a, Integral a) =>
    Int -> (a -> a) -> a -> TextBuilder
    customFixedNumeralSystem Int
    bitsPerDigit a -> a
    digitCodepoint a
    val =
      let size :: Int
    size = Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    div (a -> Int
    forall b. FiniteBits b => b -> Int
    finiteBitSize a
    val Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    bitsPerDigit Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1) Int
    bitsPerDigit
       in Int -> (forall s. MArray s -> Int -> ST s Int) -> TextBuilder
    TextBuilder Int
    size \MArray s
    array Int
    arrayStartIndex ->
            let go :: a -> Int -> ST s Int
    go a
    val Int
    arrayIndex =
                  if Int
    arrayIndex Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    arrayStartIndex
                    then do
                      MArray s -> Int -> Word8 -> ST s ()
    forall s. MArray s -> Int -> Word8 -> ST s ()
    TextArray.unsafeWrite MArray s
    array Int
    arrayIndex (a -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (a -> a
    digitCodepoint a
    val))
                      a -> Int -> ST s Int
    go (a -> Int -> a
    forall a. Bits a => a -> Int -> a
    unsafeShiftR a
    val Int
    bitsPerDigit) (Int -> Int
    forall a. Enum a => a -> a
    pred Int
    arrayIndex)
                    else Int -> ST s Int
    forall a. a -> ST s a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Int
    indexAfter
                indexAfter :: Int
    indexAfter =
                  Int
    arrayStartIndex Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    size
             in a -> Int -> ST s Int
    go a
    val (Int -> Int
    forall a. Enum a => a -> a
    pred Int
    indexAfter)

    -- |
    -- [Two's complement](https://en.wikipedia.org/wiki/Two%27s_complement) binary representation of a value.
    --
    -- Bits of a statically sized value padded from the left according to the size.
    -- If it's a negatable integer, the sign is reflected in the bits.
    --
    -- >>> binary @Int8 0
    -- "00000000"
    --
    -- >>> binary @Int8 4
    -- "00000100"
    --
    -- >>> binary @Int8 (-1)
    -- "11111111"
    --
    -- >>> binary @Word8 255
    -- "11111111"
    --
    -- >>> binary @Int16 4
    -- "0000000000000100"
    --
    -- >>> binary @Int16 (-4)
    -- "1111111111111100"
    {-# INLINE binary #-}
    binary :: (FiniteBits a) => a -> TextBuilder
    binary :: forall a. FiniteBits a => a -> TextBuilder
    binary a
    val =
      let size :: Int
    size = a -> Int
    forall b. FiniteBits b => b -> Int
    finiteBitSize a
    val
       in Int -> (forall s. MArray s -> Int -> ST s Int) -> TextBuilder
    TextBuilder Int
    size \MArray s
    array Int
    arrayStartIndex ->
            let go :: a -> Int -> ST s Int
    go a
    val Int
    arrayIndex =
                  if Int
    arrayIndex Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    arrayStartIndex
                    then do
                      MArray s -> Int -> Word8 -> ST s ()
    forall s. MArray s -> Int -> Word8 -> ST s ()
    TextArray.unsafeWrite MArray s
    array Int
    arrayIndex if a -> Int -> Bool
    forall a. Bits a => a -> Int -> Bool
    testBit a
    val Int
    0 then Word8
    49 else Word8
    48
                      a -> Int -> ST s Int
    go (a -> Int -> a
    forall a. Bits a => a -> Int -> a
    unsafeShiftR a
    val Int
    1) (Int -> Int
    forall a. Enum a => a -> a
    pred Int
    arrayIndex)
                    else Int -> ST s Int
    forall a. a -> ST s a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Int
    indexAfter
                indexAfter :: Int
    indexAfter =
                  Int
    arrayStartIndex Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    size
             in a -> Int -> ST s Int
    go a
    val (Int -> Int
    forall a. Enum a => a -> a
    pred Int
    indexAfter)

    -- |
    -- Same as 'binary', but with the \"0b\" prefix.
    --
    -- >>> prefixedBinary @Int8 0
    -- "0b00000000"
    {-# INLINE prefixedBinary #-}
    prefixedBinary :: (FiniteBits a) => a -> TextBuilder
    prefixedBinary :: forall a. FiniteBits a => a -> TextBuilder
    prefixedBinary = TextBuilder -> TextBuilder -> TextBuilder
    forall a. Monoid a => a -> a -> a
    mappend TextBuilder
    "0b" (TextBuilder -> TextBuilder)
    -> (a -> TextBuilder) -> a -> TextBuilder
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . a -> TextBuilder
    forall a. FiniteBits a => a -> TextBuilder
    binary

    -- | Octal representation of an integer.
    --
    -- >>> octal @Int32 123456
    -- "00000361100"
    --
    -- >>> octal @Int32 (-123456)
    -- "77777416700"
    {-# INLINE octal #-}
    octal :: (FiniteBits a, Integral a) => a -> TextBuilder
    octal :: forall a. (FiniteBits a, Integral a) => a -> TextBuilder
    octal = Int -> (a -> a) -> a -> TextBuilder
    forall a.
    (FiniteBits a, Integral a) =>
    Int -> (a -> a) -> a -> TextBuilder
    customFixedNumeralSystem Int
    3 (a -> a
    forall a. (Bits a, Num a) => a -> a
    Codepoints.octalDigit (a -> a) -> (a -> a) -> a -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . a -> a
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral)

    -- |
    -- Same as 'octal', but with the \"0o\" prefix.
    --
    -- >>> prefixedOctal @Int8 0
    -- "0o000"
    {-# INLINE prefixedOctal #-}
    prefixedOctal :: (FiniteBits a, Integral a) => a -> TextBuilder
    prefixedOctal :: forall a. (FiniteBits a, Integral a) => a -> TextBuilder
    prefixedOctal = TextBuilder -> TextBuilder -> TextBuilder
    forall a. Monoid a => a -> a -> a
    mappend TextBuilder
    "0o" (TextBuilder -> TextBuilder)
    -> (a -> TextBuilder) -> a -> TextBuilder
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . a -> TextBuilder
    forall a. (FiniteBits a, Integral a) => a -> TextBuilder
    octal

    -- | Integer in hexadecimal notation with a fixed number of digits determined by the size of the type.
    --
    -- >>> hexadecimal @Int8 0
    -- "00"
    --
    -- >>> hexadecimal @Int8 4
    -- "04"
    --
    -- >>> hexadecimal @Int8 (-128)
    -- "80"
    --
    -- >>> hexadecimal @Int8 (-1)
    -- "ff"
    --
    -- >>> hexadecimal @Word8 255
    -- "ff"
    --
    -- >>> hexadecimal @Int32 123456
    -- "0001e240"
    --
    -- >>> hexadecimal @Int32 (-123456)
    -- "fffe1dc0"
    {-# INLINE hexadecimal #-}
    hexadecimal :: (FiniteBits a, Integral a) => a -> TextBuilder
    hexadecimal :: forall a. (FiniteBits a, Integral a) => a -> TextBuilder
    hexadecimal = Int -> (a -> a) -> a -> TextBuilder
    forall a.
    (FiniteBits a, Integral a) =>
    Int -> (a -> a) -> a -> TextBuilder
    customFixedNumeralSystem Int
    4 (a -> a
    forall a. (Bits a, Num a, Ord a) => a -> a
    Codepoints.hexDigit (a -> a) -> (a -> a) -> a -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . a -> a
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral)

    -- |
    -- Same as 'hexadecimal', but with the \"0x\" prefix.
    --
    -- >>> prefixedHexadecimal @Int8 0
    -- "0x00"
    {-# INLINE prefixedHexadecimal #-}
    prefixedHexadecimal :: (FiniteBits a, Integral a) => a -> TextBuilder
    prefixedHexadecimal :: forall a. (FiniteBits a, Integral a) => a -> TextBuilder
    prefixedHexadecimal = TextBuilder -> TextBuilder -> TextBuilder
    forall a. Monoid a => a -> a -> a
    mappend TextBuilder
    "0x" (TextBuilder -> TextBuilder)
    -> (a -> TextBuilder) -> a -> TextBuilder
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . a -> TextBuilder
    forall a. (FiniteBits a, Integral a) => a -> TextBuilder
    hexadecimal

    -- * Signed Numbers

    {-# INLINE signed #-}
    signed :: (Integral a) => (forall a. (Integral a) => a -> TextBuilder) -> a -> TextBuilder
    signed :: forall a.
    Integral a =>
    (forall a. Integral a => a -> TextBuilder) -> a -> TextBuilder
    signed forall a. Integral a => a -> TextBuilder
    onUnsigned a
    a =
      if a
    a a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    >= a
    0
        then a -> TextBuilder
    forall a. Integral a => a -> TextBuilder
    onUnsigned a
    a
        else
          Int -> TextBuilder
    unicodeCodepoint Int
    45
            TextBuilder -> TextBuilder -> TextBuilder
    forall a. Semigroup a => a -> a -> a
    <> let negated :: a
    negated = a -> a
    forall a. Num a => a -> a
    negate a
    a
                in if a
    negated a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    /= a
    a
                     then a -> TextBuilder
    forall a. Integral a => a -> TextBuilder
    onUnsigned a
    negated
                     else
                       -- This is a special case for the minimum value of signed types.
                       -- The negation of the minimum value is not representable in the same type.
                       -- For example, for Int8, -128 is not representable as a positive number.
                       Integer -> TextBuilder
    forall a. Integral a => a -> TextBuilder
    onUnsigned (Integer -> Integer
    forall a. Num a => a -> a
    negate (a -> Integer
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral a
    a :: Integer))

    -- | Signed decimal representation of an integer.
    --
    -- >>> decimal 123456
    -- "123456"
    --
    -- >>> decimal (-123456)
    -- "-123456"
    --
    -- >>> decimal 0
    -- "0"
    --
    -- >>> decimal (-2 :: Int8)
    -- "-2"
    --
    -- >>> decimal (-128 :: Int8)
    -- "-128"
    {-# INLINE decimal #-}
    decimal :: (Integral a) => a -> TextBuilder
    decimal :: forall a. Integral a => a -> TextBuilder
    decimal = (forall a. Integral a => a -> TextBuilder) -> a -> TextBuilder
    forall a.
    Integral a =>
    (forall a. Integral a => a -> TextBuilder) -> a -> TextBuilder
    signed a -> TextBuilder
    forall a. Integral a => a -> TextBuilder
    unsignedDecimal

    -- * Unsigned Numbers

    -- | Render a number in the given radix.
    {-# INLINE digitsByRadix #-}
    digitsByRadix :: (Integral a) => a -> (a -> a) -> a -> TextBuilder
    digitsByRadix :: forall a. Integral a => a -> (a -> a) -> a -> TextBuilder
    digitsByRadix a
    radix a -> a
    digitCodepoint =
      Int -> [a] -> a -> TextBuilder
    go Int
    0 []
      where
        go :: Int -> [a] -> a -> TextBuilder
    go !Int
    offset ![a]
    digits a
    x = case a -> a -> (a, a)
    forall a. Integral a => a -> a -> (a, a)
    divMod a
    x a
    radix of
          (a
    next, a
    digit) ->
            if a
    next a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    <= a
    0
              then Int -> [a] -> TextBuilder
    finish (Int -> Int
    forall a. Enum a => a -> a
    succ Int
    offset) (a
    digit a -> [a] -> [a]
    forall a. a -> [a] -> [a]
    : [a]
    digits)
              else Int -> [a] -> a -> TextBuilder
    go (Int -> Int
    forall a. Enum a => a -> a
    succ Int
    offset) (a
    digit a -> [a] -> [a]
    forall a. a -> [a] -> [a]
    : [a]
    digits) a
    next

        finish :: Int -> [a] -> TextBuilder
    finish Int
    size [a]
    digits =
          Int -> (forall s. MArray s -> Int -> ST s Int) -> TextBuilder
    TextBuilder Int
    size MArray s -> Int -> ST s Int
    forall s. MArray s -> Int -> ST s Int
    action
          where
            action :: TextArray.MArray s -> Int -> ST s Int
            action :: forall s. MArray s -> Int -> ST s Int
    action MArray s
    array =
              [a] -> Int -> ST s Int
    go [a]
    digits
              where
                go :: [a] -> Int -> ST s Int
    go [a]
    digits Int
    offset = case [a]
    digits of
                  [] -> Int -> ST s Int
    forall a. a -> ST s a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Int
    offset
                  (a
    digit : [a]
    digits) -> do
                    MArray s -> Int -> Word8 -> ST s ()
    forall s. MArray s -> Int -> Word8 -> ST s ()
    TextArray.unsafeWrite MArray s
    array Int
    offset (a -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (a -> a
    digitCodepoint a
    digit))
                    [a] -> Int -> ST s Int
    go [a]
    digits (Int -> Int
    forall a. Enum a => a -> a
    succ Int
    offset)

    -- | Unsigned octal representation of a non-negative integral value.
    --
    -- __Warning:__ It is your responsibility to ensure that the value is non-negative.
    --
    --
    -- >>> unsignedOctal 7
    -- "7"
    --
    -- >>> unsignedOctal 9
    -- "11"
    --
    -- >>> unsignedOctal 16
    -- "20"
    {-# INLINE unsignedOctal #-}
    unsignedOctal :: (Integral a) => a -> TextBuilder
    unsignedOctal :: forall a. Integral a => a -> TextBuilder
    unsignedOctal =
      a -> (a -> a) -> a -> TextBuilder
    forall a. Integral a => a -> (a -> a) -> a -> TextBuilder
    digitsByRadix a
    8 (a -> a -> a
    forall a. Num a => a -> a -> a
    + a
    48)

    -- | Unsigned decimal representation of a non-negative integral value.
    --
    -- __Warning:__ It is your responsibility to ensure that the value is non-negative.
    --
    -- >>> unsignedDecimal 123456
    -- "123456"
    --
    -- >>> unsignedDecimal 0
    -- "0"
    {-# INLINE unsignedDecimal #-}
    unsignedDecimal :: (Integral a) => a -> TextBuilder
    unsignedDecimal :: forall a. Integral a => a -> TextBuilder
    unsignedDecimal =
      a -> (a -> a) -> a -> TextBuilder
    forall a. Integral a => a -> (a -> a) -> a -> TextBuilder
    digitsByRadix a
    10 (a -> a -> a
    forall a. Num a => a -> a -> a
    + a
    48)

    -- | Unsigned hexadecimal representation of a non-negative integral value.
    --
    -- __Warning:__ It is your responsibility to ensure that the value is non-negative.
    --
    -- >>> unsignedHexadecimal 123456
    -- "1e240"
    --
    -- >>> unsignedHexadecimal 0
    -- "0"
    {-# INLINE unsignedHexadecimal #-}
    unsignedHexadecimal :: (Integral a) => a -> TextBuilder
    unsignedHexadecimal :: forall a. Integral a => a -> TextBuilder
    unsignedHexadecimal =
      a -> (a -> a) -> a -> TextBuilder
    forall a. Integral a => a -> (a -> a) -> a -> TextBuilder
    digitsByRadix a
    16 (\a
    digit -> if a
    digit a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    <= a
    9 then a
    digit a -> a -> a
    forall a. Num a => a -> a -> a
    + a
    48 else a
    digit a -> a -> a
    forall a. Num a => a -> a -> a
    + a
    87)

    -- * Other

    -- | Fixed-length decimal without sign.
    -- Padded with zeros or trimmed depending on whether it's shorter or longer
    -- than specified.
    --
    -- >>> fixedLengthDecimal 5 123
    -- "00123"
    --
    -- >>> fixedLengthDecimal 5 123456
    -- "23456"
    --
    -- >>> fixedLengthDecimal 5 (-123456)
    -- "23456"
    --
    -- >>> fixedLengthDecimal 7 (-123456)
    -- "0123456"
    --
    -- >>> fixedLengthDecimal 0 123
    -- ""
    --
    -- >>> fixedLengthDecimal (-2) 123
    -- ""
    {-# INLINEABLE fixedLengthDecimal #-}
    fixedLengthDecimal :: (Integral a) => Int -> a -> TextBuilder
    fixedLengthDecimal :: forall a. Integral a => Int -> a -> TextBuilder
    fixedLengthDecimal (Int -> Int -> Int
    forall a. Ord a => a -> a -> a
    max Int
    0 -> Int
    size) (a -> a
    forall a. Num a => a -> a
    abs -> a
    val) =
      Int -> (forall s. MArray s -> Int -> ST s Int) -> TextBuilder
    TextBuilder Int
    size ((forall s. MArray s -> Int -> ST s Int) -> TextBuilder)
    -> (forall s. MArray s -> Int -> ST s Int) -> TextBuilder
    forall a b. (a -> b) -> a -> b
    $ \MArray s
    array Int
    startOffset ->
        let offsetAfter :: Int
    offsetAfter = Int
    startOffset Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    size
            writeValue :: a -> Int -> ST s Int
    writeValue a
    val Int
    offset =
              if Int
    offset Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    startOffset
                then
                  if a
    val a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    /= a
    0
                    then case a -> a -> (a, a)
    forall a. Integral a => a -> a -> (a, a)
    divMod a
    val a
    10 of
                      (a
    val, a
    digit) -> do
                        MArray s -> Int -> Word8 -> ST s ()
    forall s. MArray s -> Int -> Word8 -> ST s ()
    TextArray.unsafeWrite MArray s
    array Int
    offset (Word8 -> ST s ()) -> Word8 -> ST s ()
    forall a b. (a -> b) -> a -> b
    $ Word8
    48 Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    + a -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral a
    digit
                        a -> Int -> ST s Int
    writeValue a
    val (Int -> Int
    forall a. Enum a => a -> a
    pred Int
    offset)
                    else Int -> ST s Int
    writePadding Int
    offset
                else Int -> ST s Int
    forall a. a -> ST s a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Int
    offsetAfter
            writePadding :: Int -> ST s Int
    writePadding Int
    offset =
              if Int
    offset Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    startOffset
                then do
                  MArray s -> Int -> Word8 -> ST s ()
    forall s. MArray s -> Int -> Word8 -> ST s ()
    TextArray.unsafeWrite MArray s
    array Int
    offset Word8
    48
                  Int -> ST s Int
    writePadding (Int -> Int
    forall a. Enum a => a -> a
    pred Int
    offset)
                else Int -> ST s Int
    forall a. a -> ST s a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Int
    offsetAfter
         in a -> Int -> ST s Int
    writeValue a
    val (Int -> Int
    forall a. Enum a => a -> a
    pred Int
    offsetAfter)

    -- | Decimal representation of an integral value with thousands separated by the specified character.
    --
    -- >>> thousandSeparatedDecimal ',' 1234567890
    -- "1,234,567,890"
    --
    -- >>> thousandSeparatedDecimal ' ' (-1234567890)
    -- "-1 234 567 890"
    {-# INLINEABLE thousandSeparatedDecimal #-}
    thousandSeparatedDecimal :: (Integral a) => Char -> a -> TextBuilder
    thousandSeparatedDecimal :: forall a. Integral a => Char -> a -> TextBuilder
    thousandSeparatedDecimal Char
    separatorChar =
      (forall a. Integral a => a -> TextBuilder) -> a -> TextBuilder
    forall a.
    Integral a =>
    (forall a. Integral a => a -> TextBuilder) -> a -> TextBuilder
    signed (Char -> a -> TextBuilder
    forall a. Integral a => Char -> a -> TextBuilder
    unsignedThousandSeparatedDecimal Char
    separatorChar)

    -- | Decimal representation of an unsigned integral value with thousands separated by the specified character.
    --
    -- __Warning:__ It is your responsibility to ensure that the value is non-negative.
    --
    -- >>> unsignedThousandSeparatedDecimal ',' 1234567890
    -- "1,234,567,890"
    --
    -- >>> unsignedThousandSeparatedDecimal ' ' 1234567890
    -- "1 234 567 890"
    --
    -- >>> unsignedThousandSeparatedDecimal ',' 0
    -- "0"
    {-# INLINEABLE unsignedThousandSeparatedDecimal #-}
    unsignedThousandSeparatedDecimal :: (Integral a) => Char -> a -> TextBuilder
    unsignedThousandSeparatedDecimal :: forall a. Integral a => Char -> a -> TextBuilder
    unsignedThousandSeparatedDecimal Char
    separatorChar =
      a -> TextBuilder
    processRightmostDigit
      where
        processRightmostDigit :: a -> TextBuilder
    processRightmostDigit a
    value =
          case a -> a -> (a, a)
    forall a. Integral a => a -> a -> (a, a)
    divMod a
    value a
    10 of
            (a
    value, a
    digit) ->
              [TextBuilder] -> Int -> a -> TextBuilder
    processAnotherDigit [a -> TextBuilder
    forall a. Integral a => a -> TextBuilder
    decimalDigit a
    digit] (Int
    1 :: Int) a
    value
        processAnotherDigit :: [TextBuilder] -> Int -> a -> TextBuilder
    processAnotherDigit [TextBuilder]
    builders Int
    index a
    value =
          if a
    value a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == a
    0
            then [TextBuilder] -> TextBuilder
    forall a. Monoid a => [a] -> a
    mconcat [TextBuilder]
    builders
            else case a -> a -> (a, a)
    forall a. Integral a => a -> a -> (a, a)
    divMod a
    value a
    10 of
              (a
    value, a
    digit) ->
                if Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    mod Int
    index Int
    3 Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    0
                  then
                    [TextBuilder] -> Int -> a -> TextBuilder
    processAnotherDigit
                      (a -> TextBuilder
    forall a. Integral a => a -> TextBuilder
    decimalDigit a
    digit TextBuilder -> [TextBuilder] -> [TextBuilder]
    forall a. a -> [a] -> [a]
    : Char -> TextBuilder
    char Char
    separatorChar TextBuilder -> [TextBuilder] -> [TextBuilder]
    forall a. a -> [a] -> [a]
    : [TextBuilder]
    builders)
                      (Int -> Int
    forall a. Enum a => a -> a
    succ Int
    index)
                      a
    value
                  else
                    [TextBuilder] -> Int -> a -> TextBuilder
    processAnotherDigit
                      (a -> TextBuilder
    forall a. Integral a => a -> TextBuilder
    decimalDigit a
    digit TextBuilder -> [TextBuilder] -> [TextBuilder]
    forall a. a -> [a] -> [a]
    : [TextBuilder]
    builders)
                      (Int -> Int
    forall a. Enum a => a -> a
    succ Int
    index)
                      a
    value