{- numbers for humans
 -
 - Copyright 2012-2021 Joey Hess <id@joeyh.name>
 -
 - License: BSD-2-clause
 -}

module Utility.HumanNumber (showImprecise) where

{- Displays a fractional value as a string with a limited number
 - of decimal digits. -}
showImprecise :: RealFrac a => Int -> a -> String
showImprecise :: Int -> a -> String
showImprecise Int
precision a
n
	| Int
precision Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 Bool -> Bool -> Bool
|| Integer
remainder' Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 = Integer -> String
forall a. Show a => a -> String
show (a -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round a
n :: Integer)
	| Bool
otherwise = Integer -> String
forall a. Show a => a -> String
show Integer
int' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"." String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
striptrailing0s (String -> String
pad0s (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Integer -> String
forall a. Show a => a -> String
show Integer
remainder')
  where
	int :: Integer
	(Integer
int, a
frac) = a -> (Integer, a)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction a
n
	remainder :: Integer
remainder = a -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round (a
frac a -> a -> a
forall a. Num a => a -> a -> a
* a
10 a -> Int -> a
forall a b. (Num a, Integral b) => a -> b -> a
^ Int
precision) :: Integer
	(Integer
int', Integer
remainder')
		-- carry the 1
		| Integer
remainder Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
10 Integer -> Int -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ Int
precision = (Integer
int Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1, Integer
0)
		| Bool
otherwise = (Integer
int, Integer
remainder)
	pad0s :: String -> String
pad0s String
s = Int -> Char -> String
forall a. Int -> a -> [a]
replicate (Int
precision Int -> Int -> Int
forall a. Num a => a -> a -> a
- String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
s) Char
'0' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s
	striptrailing0s :: String -> String
striptrailing0s = String -> String
forall a. [a] -> [a]
reverse (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
dropWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'0') (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
forall a. [a] -> [a]
reverse