Module

Data.Fixed

Package
purescript-fixed-precision
Repository
lumihq/purescript-fixed-precision

This module defines a numeric type Fixed for working with fixed point numbers in base 10. The precision is tracked in the types.

#Fixed Source

newtype Fixed (precision :: Precision)

A fixed point representation of a real number, with the specified precision.

A value is multiplied by the precision, truncated and stored as a big integer. That is, we approximate the number by numerator/10^precision, storing only the numerator, and carrying the precision around as type information.

The Semiring and associated instances allow us to perform basic arithmetic operations.

Instances

#fromInt Source

fromInt :: forall precision. KnownPrecision precision => Int -> Fixed precision

Create a Fixed representation of an Int.

#fromNumber Source

fromNumber :: forall precision. KnownPrecision precision => Number -> Maybe (Fixed precision)

Approximate a Number as a Fixed value with the specified precision.

> fromNumber 0.1234 :: Maybe (Fixed P10000)
(Just (fromNumber 0.1234 :: P10000))

> fromNumber 0.1234 :: Maybe (Fixed P100)
(Just (fromNumber 0.12 :: P100))

When given a finite Number, this function always succeeds: the number is truncated (rounded towards zero) to the closest possible Fixed value. This function only returns Nothing if it is given NaN, or positive or negative infinity.

> fromNumber (1.0 / 0.0) :: Maybe (Fixed P100)
Nothing

#toNumber Source

toNumber :: forall precision. KnownPrecision precision => Fixed precision -> Number

Convert a Fixed value to a Number.

Note: Overflow is possible here if the numerator is sufficiently large.

#numerator Source

numerator :: forall precision. Fixed precision -> BigInt

Extract the numerator from the representation of the number as a fraction.

> map numerator (fromNumber 0.1234 :: Fixed P1000)
(Just fromString "123")

> map numerator (fromNumber 0.1239 :: Fixed P1000)
(Just fromString "123")

#floor Source

floor :: forall precision. KnownPrecision precision => Fixed precision -> Fixed precision

Calculate the largest whole number smaller than or equal to the provided value.

> map floor $ fromNumber 0.1 :: Maybe (Fixed P10)
(Just (fromNumber 0.0 :: P10))

> map floor $ fromNumber 1.0 :: Maybe (Fixed P10)
(Just (fromNumber 1.0 :: P10))

> floor $ fromNumber (-0.1) :: Maybe (Fixed P10)
(Just (fromNumber (-1.0) :: P10))

#ceil Source

ceil :: forall precision. KnownPrecision precision => Fixed precision -> Fixed precision

Calculate the smallest whole number greater than or equal to the provided value.

> map ceil $ fromNumber 0.1 :: Maybe (Fixed P10)
(Just (fromNumber 1.0 :: P10))

> map ceil $ fromNumber 1.0 :: Maybe (Fixed P10)
(Just (fromNumber 1.0 :: P10))

> map ceil $ fromNumber (-0.1) :: Maybe (Fixed P10)
(Just (fromNumber 0.0 :: P10))

#round Source

round :: forall precision. KnownPrecision precision => Fixed precision -> Fixed precision

Round the specified value to the nearest whole number.

> map round $ fromNumber 0.1 :: Maybe (Fixed P10)
(Just (fromNumber 0.0 :: P10))

> map round $ fromNumber 0.9 :: Maybe (Fixed P10)
(Just (fromNumber 1.0 :: P10))

> map round $ fromNumber 0.5 :: Maybe (Fixed P10)
(Just (fromNumber 1.0 :: P10))

> map round $ fromNumber (-0.1) :: Maybe (Fixed P10)
(Just (fromNumber 0.0 :: P10))

#approxDiv Source

approxDiv :: forall precision. KnownPrecision precision => Fixed precision -> Fixed precision -> Fixed precision

Approximate division of fixed-precision numbers.

> lift2 approxDiv (fromNumber 22.0) (fromNumber 7.0) :: Maybe (Fixed P100)
(Just (fromNumber 3.14 :: P100))

Note: Fixed is not a EuclideanRing in general - it is not even an integral domain, since it has non-zero zero-divisors:

> lift2 (*) (fromNumber 0.1) (fromNumber 0.1) :: Maybe (Fixed P10)
(Just (fromNumber 0.0 :: P10))

#Precision Source

data Precision :: Type

A kind for type-level precision information

#One Source

data One :: Precision

No decimal places

Instances

#TenTimes Source

data TenTimes :: Precision -> Precision

One more decimal place

Instances

#P1 Source

type P1 = One

#P10 Source

type P10 = TenTimes P1

One decimal place

#P100 Source

type P100 = TenTimes P10

Two decimal places

#P1000 Source

type P1000 = TenTimes P100

Three decimal places

#P10000 Source

type P10000 = TenTimes P1000

Four decimal places

#P100000 Source

type P100000 = TenTimes P10000

Five decimal places

#P1000000 Source

type P1000000 = TenTimes P100000

Six decimal places

#PProxy Source

data PProxy (precision :: Precision)

A value-level proxy for a type-level precision.

Constructors

#KnownPrecision Source

class KnownPrecision (precision :: Precision)  where

Precision which is known, i.e. it can be reflected to a value at runtime, given a PProxy.

reflectPrecision returns a multiple of ten, corresponding to the maximum number of decimal places which can be stored.

Members

Instances

#reifyPrecision Source

reifyPrecision :: forall r. Int -> (forall precision. KnownPrecision precision => PProxy precision -> r) -> Maybe r

Reify an non-negative integer (a power of ten) as a Precision.

For example

> reifyPrecision 0 reflectPrecision
Just 1
> reifyPrecision 1 reflectPrecision
Just 10
> reifyPrecision 2 reflectPrecision
Just 100
> reifyPrecision (-1) reflectPrecision
Nothing
Modules
Data.Fixed