hydra-kernel-0.16.0: src/main/haskell/Hydra/Haskell/Lib/Math.hs
-- | Haskell implementations of hydra.lib.math primitives
module Hydra.Haskell.Lib.Math where
import Prelude (Num, Ord, Integral, Enum, Bool, Double, Int, Integer, Float, Maybe(..), (.), ($), (+), (-), (*), (==), (||))
import qualified Prelude
-- | Return the absolute value.
abs :: Num a => a -> a
abs = Prelude.abs
-- | Return the arc cosine of x in radians.
acos :: Double -> Double
acos = Prelude.acos
-- | Return the inverse hyperbolic cosine of x.
acosh :: Double -> Double
acosh = Prelude.acosh
-- | Add two numbers.
add :: Num a => a -> a -> a
add x y = x + y
-- | Add two Float64 numbers.
addFloat64 :: Double -> Double -> Double
addFloat64 = add
-- | Return the arc sine of x in radians.
asin :: Double -> Double
asin = Prelude.asin
-- | Return the inverse hyperbolic sine of x.
asinh :: Double -> Double
asinh = Prelude.asinh
-- | Return the arc tangent of x in radians.
atan :: Double -> Double
atan = Prelude.atan
-- | Return the arc tangent of y/x in radians, using signs to determine quadrant.
atan2 :: Double -> Double -> Double
atan2 = Prelude.atan2
-- | Return the inverse hyperbolic tangent of x.
atanh :: Double -> Double
atanh = Prelude.atanh
-- | Return the ceiling of x as a float.
--
-- DIVERGENCE FROM HASKELL: Haskell's Prelude.ceiling returns an Integer, which
-- cannot represent NaN or Inf; GHC's behavior on those inputs is undefined and
-- produces nonsensical gigantic integers. Hydra returns a Float64 instead so
-- that NaN and ±Inf propagate naturally per IEEE 754, matching the conventions
-- of C (ceil), Java (Math.ceil), Go (math.Ceil), Rust (f64::ceil), and JavaScript
-- (Math.ceil). Users who need an Integer value must convert explicitly.
ceiling :: Double -> Double
ceiling x
| Prelude.isNaN x Prelude.|| Prelude.isInfinite x = x
| Prelude.otherwise = Prelude.fromIntegral (Prelude.ceiling x :: Integer)
-- | Return the cosine of x radians.
cos :: Double -> Double
cos = Prelude.cos
-- | Return the hyperbolic cosine of x.
cosh :: Double -> Double
cosh = Prelude.cosh
-- | Euler's number (e ≈ 2.71828).
e :: Double
e = Prelude.exp 1.0
-- | Check if an integer is even.
even :: Integral a => a -> Bool
even = Prelude.even
-- | Return e raised to the power x.
exp :: Double -> Double
exp = Prelude.exp
-- | Return the floor of x as a float.
--
-- DIVERGENCE FROM HASKELL: see the note on ceiling. Returns Float64 rather than
-- Integer so that NaN and ±Inf propagate naturally per IEEE 754.
floor :: Double -> Double
floor x
| Prelude.isNaN x Prelude.|| Prelude.isInfinite x = x
| Prelude.otherwise = Prelude.fromIntegral (Prelude.floor x :: Integer)
-- | Return the natural logarithm of x.
log :: Double -> Double
log = Prelude.log
-- | Return the logarithm of x to the given base.
logBase :: Double -> Double -> Double
logBase = Prelude.logBase
-- | Return the maximum of two values.
max :: Ord a => a -> a -> a
max = Prelude.max
-- | Divide two integers using integer division, returning Nothing on division by zero.
maybeDiv :: Int -> Int -> Maybe Int
maybeDiv _ 0 = Nothing
maybeDiv x y = Just (Prelude.div x y)
-- | Return the minimum of two values.
min :: Ord a => a -> a -> a
min = Prelude.min
-- | Mathematical modulo, returning Nothing on division by zero.
maybeMod :: Int -> Int -> Maybe Int
maybeMod _ 0 = Nothing
maybeMod x y = Just (Prelude.mod x y)
-- | Multiply two numbers.
mul :: Num a => a -> a -> a
mul x y = x * y
-- | Multiply two Float64 numbers.
mulFloat64 :: Double -> Double -> Double
mulFloat64 = mul
-- | Negate a number.
negate :: Num a => a -> a
negate = Prelude.negate
-- | Negate a Float64 number.
negateFloat64 :: Double -> Double
negateFloat64 = Prelude.negate
-- | Check if an integer is odd.
odd :: Integral a => a -> Bool
odd = Prelude.odd
-- | Pi (π ≈ 3.14159).
pi :: Double
pi = Prelude.pi
-- | Return x raised to the power y.
pow :: Double -> Double -> Double
pow = (Prelude.**)
-- | Return the predecessor (x - 1), returning Nothing on int32 minBound.
maybePred :: Int -> Maybe Int
maybePred x
| x == (-2147483648) = Nothing
| Prelude.otherwise = Just (x - 1)
-- | Generate a range of values from start to end (inclusive).
range :: Enum a => a -> a -> [a]
range start end = [start .. end]
-- | Integer remainder, returning Nothing on division by zero.
maybeRem :: Int -> Int -> Maybe Int
maybeRem _ 0 = Nothing
maybeRem x y = Just (Prelude.rem x y)
-- | Return x rounded to the nearest integer, as a float.
--
-- DIVERGENCE FROM HASKELL: see the note on ceiling. Returns Float64 rather than
-- Integer so that NaN and ±Inf propagate naturally per IEEE 754.
round :: Double -> Double
round x
| Prelude.isNaN x Prelude.|| Prelude.isInfinite x = x
| Prelude.otherwise = Prelude.fromIntegral (Prelude.round x :: Integer)
-- | Round a float32 to n significant digits.
-- Returns NaN/Inf inputs unchanged (no rounding is possible).
roundFloat32 :: Int -> Float -> Float
roundFloat32 n x
| Prelude.isNaN x Prelude.|| Prelude.isInfinite x = x
| x Prelude.== 0 = 0
| Prelude.otherwise =
let factor = 10 Prelude.^^ (n - 1 - Prelude.floor (Prelude.logBase 10 (Prelude.abs x)))
in Prelude.fromIntegral (Prelude.round (x * factor) :: Integer) Prelude./ factor
-- | Round a float64 to n significant digits.
-- Returns NaN/Inf inputs unchanged (no rounding is possible).
roundFloat64 :: Int -> Double -> Double
roundFloat64 n x
| Prelude.isNaN x Prelude.|| Prelude.isInfinite x = x
| x Prelude.== 0 = 0
| Prelude.otherwise =
let factor = 10 Prelude.^^ (n - 1 - Prelude.floor (Prelude.logBase 10 (Prelude.abs x)))
in Prelude.fromIntegral (Prelude.round (x * factor) :: Integer) Prelude./ factor
-- | Return the sign of a number (-1, 0, or 1).
signum :: Num a => a -> a
signum = Prelude.signum
-- | Return the sine of x radians.
sin :: Double -> Double
sin = Prelude.sin
-- | Return the hyperbolic sine of x.
sinh :: Double -> Double
sinh = Prelude.sinh
-- | Return the square root of x.
sqrt :: Double -> Double
sqrt = Prelude.sqrt
-- | Subtract two numbers.
sub :: Num a => a -> a -> a
sub x y = x - y
-- | Subtract two Float64 numbers.
subFloat64 :: Double -> Double -> Double
subFloat64 = sub
-- | Return the successor (x + 1), returning Nothing on int32 maxBound.
maybeSucc :: Int -> Maybe Int
maybeSucc x
| x == 2147483647 = Nothing
| Prelude.otherwise = Just (x + 1)
-- | Return the tangent of x radians.
tan :: Double -> Double
tan = Prelude.tan
-- | Return the hyperbolic tangent of x.
tanh :: Double -> Double
tanh = Prelude.tanh
-- | Return x truncated (towards zero), as a float.
--
-- DIVERGENCE FROM HASKELL: see the note on ceiling. Returns Float64 rather than
-- Integer so that NaN and ±Inf propagate naturally per IEEE 754.
truncate :: Double -> Double
truncate x
| Prelude.isNaN x Prelude.|| Prelude.isInfinite x = x
| Prelude.otherwise = Prelude.fromIntegral (Prelude.truncate x :: Integer)