{-# LANGUAGE OverloadedStrings #-}
module Miso.Flow.Internal.JSNum
( jsShow
) where
import Numeric (floatToDigits)
import Prelude
import Miso.String (MisoString, ms)
jsShow :: Double -> MisoString
jsShow :: Double -> MisoString
jsShow Double
x
| Double -> Bool
forall a. RealFloat a => a -> Bool
isNaN Double
x = MisoString
"NaN"
| Double -> Bool
forall a. RealFloat a => a -> Bool
isInfinite Double
x = if Double
x Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
0 then MisoString
"Infinity" else MisoString
"-Infinity"
| Double
x Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
0 = MisoString
"0"
| Double
x Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0 = MisoString
"-" MisoString -> MisoString -> MisoString
forall a. Semigroup a => a -> a -> a
<> Double -> MisoString
jsShow (Double -> Double
forall a. Num a => a -> a
negate Double
x)
| Bool
otherwise = String -> MisoString
forall str. ToMisoString str => str -> MisoString
ms (Double -> String
positive Double
x)
positive :: Double -> String
positive :: Double -> String
positive Double
x =
let ([Int]
digits, Int
n) = Integer -> Double -> ([Int], Int)
forall a. RealFloat a => Integer -> a -> ([Int], Int)
floatToDigits Integer
10 Double
x
ds :: String
ds = (Int -> String) -> [Int] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Int -> String
forall a. Show a => a -> String
show [Int]
digits
k :: Int
k = String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
ds
in if Int
k Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
n Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
21
then String
ds String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> Char -> String
forall a. Int -> a -> [a]
replicate (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
k) Char
'0'
else if Int
0 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
n Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
21
then Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
n String
ds String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"." String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String -> String
forall a. Int -> [a] -> [a]
drop Int
n String
ds
else if -Int
6 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
n Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0
then String
"0." String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> Char -> String
forall a. Int -> a -> [a]
replicate (Int -> Int
forall a. Num a => a -> a
negate Int
n) Char
'0' String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
ds
else
let mantissa :: String
mantissa = case String
ds of
[Char
d] -> [Char
d]
(Char
d:String
rest) -> Char
d Char -> String -> String
forall a. a -> [a] -> [a]
: Char
'.' Char -> String -> String
forall a. a -> [a] -> [a]
: String
rest
[] -> String
"0"
e :: Int
e = Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
sign :: String
sign = if Int
e Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 then String
"+" else String
"-"
in String
mantissa String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"e" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
sign String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show (Int -> Int
forall a. Num a => a -> a
abs Int
e)