Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions dimensional-dk.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ library
Numeric.Units.Dimensional.DK.Dimensions,
Numeric.Units.Dimensional.DK.Dimensions.TermLevel,
Numeric.Units.Dimensional.DK.Dimensions.TypeLevel,
Numeric.Units.Dimensional.DK.Functor
Numeric.Units.Dimensional.DK.Functor,
Numeric.Units.Dimensional.DK.SI,
Numeric.Units.Dimensional.DK.SI.Prelude,
Numeric.Units.Dimensional.DK.SI.SIUnits,
Numeric.Units.Dimensional.DK.SI.Quantities

test-suite tests
type: exitcode-stdio-1.0
Expand All @@ -78,4 +82,4 @@ benchmark simple
dimensional-dk
default-language: Haskell2010
ghc-options: -O2


4 changes: 2 additions & 2 deletions examples/NewtonianMechanics.hs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ rotationalMomentum i w = i * w
rotationalPower :: (Num a) => Torque a -> AngularVelocity a -> Power a
rotationalPower t w = t * w

torque :: (Num a) => Force a -> Length a -> Torque a
torque r f = r * f
torque :: (Fractional a) => Force a -> Length a -> Torque a
torque r f = r * f / (1 *~ radian)

torqueFromChangeInMomentum :: (Fractional a) => AngularMomentum a -> Time a -> Torque a
torqueFromChangeInMomentum dL dt = dL / dt
68 changes: 50 additions & 18 deletions src/Numeric/Units/Dimensional/DK.hs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ module Numeric.Units.Dimensional.DK
Dimension (Dim),
-- ** Dimension Arithmetic
-- $dimension-arithmetic
type (*), type (/), type (^), Root, Recip,
type (*), type (/), type (^), Root, Recip, type SIDim, type ToSIDim,
-- ** Term Level Representation of Dimensions
-- $dimension-terms
Dimension' (Dim'), HasDimension(..), KnownDimension,
Expand All @@ -209,20 +209,22 @@ module Numeric.Units.Dimensional.DK
negate, abs, nroot, sqrt, cbrt,
-- ** Transcendental Functions
exp, log, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh, atan2,
-- ** Dealing with Angles
removeAngles, coerceAngles,
-- ** Operations on Collections
-- $collections
(*~~), (/~~), sum, mean, dimensionlessLength, nFromTo,
-- * Dimension Synonyms
-- $dimension-synonyms
DOne, DLength, DMass, DTime, DElectricCurrent, DThermodynamicTemperature, DAmountOfSubstance, DLuminousIntensity,
DOne, DLength, DMass, DTime, DElectricCurrent, DThermodynamicTemperature, DAmountOfSubstance, DLuminousIntensity, DPlaneAngle,
-- * Quantity Synonyms
-- $quantity-synonyms
Dimensionless, Length, Mass, Time, ElectricCurrent, ThermodynamicTemperature, AmountOfSubstance, LuminousIntensity,
Dimensionless, Length, Mass, Time, ElectricCurrent, ThermodynamicTemperature, AmountOfSubstance, LuminousIntensity, PlaneAngle,
-- * Constants
-- $constants
_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, pi, tau,
-- * Constructing Units
prefix, siUnit, one,
prefix, baseUnit, siUnit, one,
-- * On 'Functor', and Conversion Between Number Representations
-- $functor
dmap, changeRep
Expand Down Expand Up @@ -385,6 +387,7 @@ type ElectricCurrent = Quantity DElectricCurrent
type ThermodynamicTemperature = Quantity DThermodynamicTemperature
type AmountOfSubstance = Quantity DAmountOfSubstance
type LuminousIntensity = Quantity DLuminousIntensity
type PlaneAngle = Quantity DPlaneAngle

{- $dimension-arithmetic
When performing arithmetic on units and quantities the arithmetics
Expand Down Expand Up @@ -581,39 +584,68 @@ We continue by defining elementary functions on 'Dimensionless'
that may be obviously useful.
-}

exp, log, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh
exp, log, sinh, cosh, tanh, asinh, acosh, atanh
:: Floating a => Dimensionless a -> Dimensionless a
exp = fmap Prelude.exp
log = fmap Prelude.log
sin = fmap Prelude.sin
cos = fmap Prelude.cos
tan = fmap Prelude.tan
asin = fmap Prelude.asin
acos = fmap Prelude.acos
atan = fmap Prelude.atan
sinh = fmap Prelude.sinh
cosh = fmap Prelude.cosh
tanh = fmap Prelude.tanh
asinh = fmap Prelude.asinh
acosh = fmap Prelude.acosh
atanh = fmap Prelude.atanh

sin, cos, tan :: Floating a => PlaneAngle a -> Dimensionless a
sin = (*~ one) . Prelude.sin . (/~ baseUnit)
cos = (*~ one) . Prelude.cos . (/~ baseUnit)
tan = (*~ one) . Prelude.tan . (/~ baseUnit)

asin, acos, atan :: Floating a => Dimensionless a -> PlaneAngle a
asin = (*~ baseUnit) . Prelude.asin . (/~ one)
acos = (*~ baseUnit) . Prelude.acos . (/~ one)
atan = (*~ baseUnit) . Prelude.atan . (/~ one)

-- | Removes angular dimensions from a dimensional value by equating radians
-- with the dimensionless quantity one.
removeAngles :: Dimensional v ('Dim l m t i th n j pa) a -> Dimensional v (SIDim l m t i th n j) a
removeAngles = coerceAngles

-- | Equates values whose dimensions differ in plane angles by equating
-- radians with the dimensionless quantity one.
--
-- See `removeAngles`, which offers a more specific result type, if you are only interested
-- in ignoring angle dimensions.
coerceAngles :: Dimensional v ('Dim l m t i th n j pa) a -> Dimensional v ('Dim l m t i th n j pa') a
coerceAngles = coerce

(**) :: Floating a => Dimensionless a -> Dimensionless a -> Dimensionless a
Dimensional x ** Dimensional y = Dimensional (x Prelude.** y)

{-
For 'atan2' the operands need not be dimensionless but they must be
of the same type. The result will of course always be dimensionless.
of the same type. The result will of course always be a plane angle.
-}

atan2 :: RealFloat a => Quantity d a -> Quantity d a -> Dimensionless a
atan2 :: RealFloat a => Quantity d a -> Quantity d a -> PlaneAngle a
atan2 (Dimensional y) (Dimensional x) = Dimensional (Prelude.atan2 y x)

-- | A polymorphic 'Unit' which can be used in place of the coherent
-- base unit of any dimension. This allows polymorphic quantity
-- creation and destruction without exposing the 'Dimensional' constructor.
--
-- `siUnit` is similar but does not include the radians associated
-- with plane angles.
baseUnit :: Num a => Unit d a
baseUnit = Dimensional 1

-- | A polymorphic 'Unit' which can be used in place of the coherent
-- SI base unit of any dimension. This allows polymorphic quantity
-- creation and destruction without exposing the 'Dimensional' constructor.
siUnit :: Num a => Unit d a
siUnit = Dimensional 1
--
-- `baseUnit` is similar but includes the radians associated
-- with plane angles.
siUnit :: Num a => Unit (SIDim l m t i th n j) a
siUnit = removeAngles baseUnit

{-
The only unit we will define in this module is 'one'.
Expand All @@ -626,7 +658,7 @@ The only unit we will define in this module is 'one'.
-- appear in expressions. However, for us it is necessary to use 'one'
-- as we would any other unit to perform the "boxing" of dimensionless values.
one :: Num a => Unit DOne a
one = siUnit
one = baseUnit

{- $constants
For convenience we define some constants for small integer values
Expand All @@ -639,7 +671,7 @@ good measure.
-- it to express zero Length or Capacitance or Velocity etc, in addition
-- to the dimensionless value zero.
_0 :: Num a => Quantity d a
_0 = 0 *~ siUnit
_0 = 0 *~ baseUnit

_1, _2, _3, _4, _5, _6, _7, _8, _9 :: (Num a) => Dimensionless a
_1 = 1 *~ one
Expand Down Expand Up @@ -704,7 +736,7 @@ even a requirement.
-}
instance (KnownDimension d, Show a) => Show (Quantity d a) where
show q@(Dimensional x) = let powers = asList $ dimension q
units = ["m", "kg", "s", "A", "K", "mol", "cd"]
units = ["m", "kg", "s", "A", "K", "mol", "cd", "rad", "sr"]
dims = concat $ zipWith dimUnit units powers
in show x ++ dims

Expand Down
44 changes: 23 additions & 21 deletions src/Numeric/Units/Dimensional/DK/Dimensions/TermLevel.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
Portability: GHC only

This module defines physical dimensions expressed in terms of
the SI base dimensions, including arithmetic.
the SI base dimensions along with plane angles, including arithmetic.

-}
module Numeric.Units.Dimensional.DK.Dimensions.TermLevel
Expand All @@ -22,7 +22,7 @@ module Numeric.Units.Dimensional.DK.Dimensions.TermLevel
(*), (/), (^), recip,
-- * Synonyms for Base Dimensions
dOne,
dLength, dMass, dTime, dElectricCurrent, dThermodynamicTemperature, dAmountOfSubstance, dLuminousIntensity,
dLength, dMass, dTime, dElectricCurrent, dThermodynamicTemperature, dAmountOfSubstance, dLuminousIntensity, dPlaneAngle,
-- * Deconstruction
asList
)
Expand All @@ -32,10 +32,11 @@ import Data.Monoid (Monoid(..))
import Prelude (id, (+), (-), Int, Show, Eq, Ord)
import qualified Prelude as P

-- | A physical dimension, encoded as 7 integers, representing a factorization of the dimension into the
-- 7 SI base dimensions. By convention they are stored in the same order as
-- | A physical dimension, encoded as 8 integers, representing a factorization of the dimension into the
-- 7 SI base dimensions, along with the dimensions of plane angle.
-- By convention they are stored in the same order as
-- in the 'Numeric.Units.Dimensional.DK.Dimensions.TypeLevel.Dimension' data kind.
data Dimension' = Dim' !Int !Int !Int !Int !Int !Int !Int
data Dimension' = Dim' !Int !Int !Int !Int !Int !Int !Int !Int
deriving (Show, Eq, Ord)

-- | The monoid of dimensions under multiplication.
Expand All @@ -53,16 +54,17 @@ instance HasDimension Dimension' where

-- | The dimension of dimensionless values.
dOne :: Dimension'
dOne = Dim' 0 0 0 0 0 0 0

dLength, dMass, dTime, dElectricCurrent, dThermodynamicTemperature, dAmountOfSubstance, dLuminousIntensity :: Dimension'
dLength = Dim' 1 0 0 0 0 0 0
dMass = Dim' 0 1 0 0 0 0 0
dTime = Dim' 0 0 1 0 0 0 0
dElectricCurrent = Dim' 0 0 0 1 0 0 0
dThermodynamicTemperature = Dim' 0 0 0 0 1 0 0
dAmountOfSubstance = Dim' 0 0 0 0 0 1 0
dLuminousIntensity = Dim' 0 0 0 0 0 0 1
dOne = Dim' 0 0 0 0 0 0 0 0

dLength, dMass, dTime, dElectricCurrent, dThermodynamicTemperature, dAmountOfSubstance, dLuminousIntensity, dPlaneAngle :: Dimension'
dLength = Dim' 1 0 0 0 0 0 0 0
dMass = Dim' 0 1 0 0 0 0 0 0
dTime = Dim' 0 0 1 0 0 0 0 0
dElectricCurrent = Dim' 0 0 0 1 0 0 0 0
dThermodynamicTemperature = Dim' 0 0 0 0 1 0 0 0
dAmountOfSubstance = Dim' 0 0 0 0 0 1 0 0
dLuminousIntensity = Dim' 0 0 0 0 0 0 1 0
dPlaneAngle = Dim' 0 0 0 0 0 0 0 1

{-
We will reuse the operators and function names from the Prelude.
Expand All @@ -75,21 +77,21 @@ infixl 7 *, /

-- | Forms the product of two dimensions.
(*) :: Dimension' -> Dimension' -> Dimension'
(Dim' l m t i th n j) * (Dim' l' m' t' i' th' n' j') = Dim' (l + l') (m + m') (t + t') (i + i') (th + th') (n + n') (j + j')
(Dim' l m t i th n j pa) * (Dim' l' m' t' i' th' n' j' pa') = Dim' (l + l') (m + m') (t + t') (i + i') (th + th') (n + n') (j + j') (pa + pa')

-- | Forms the quotient of two dimensions.
(/) :: Dimension' -> Dimension' -> Dimension'
(Dim' l m t i th n j) / (Dim' l' m' t' i' th' n' j') = Dim' (l - l') (m - m') (t - t') (i - i') (th - th') (n - n') (j - j')
(Dim' l m t i th n j pa) / (Dim' l' m' t' i' th' n' j' pa') = Dim' (l - l') (m - m') (t - t') (i - i') (th - th') (n - n') (j - j') (pa - pa')

-- | Raises a dimension to an integer power.
(^) :: Dimension' -> Int -> Dimension'
(Dim' l m t i th n j) ^ x = Dim' (x P.* l) (x P.* m) (x P.* t) (x P.* i) (x P.* th) (x P.* n) (x P.* j)
(Dim' l m t i th n j pa) ^ x = Dim' (x P.* l) (x P.* m) (x P.* t) (x P.* i) (x P.* th) (x P.* n) (x P.* j) (x P.* pa)

-- | Forms the reciprocal of a dimension.
recip :: Dimension' -> Dimension'
recip = (dOne /)

-- | Converts a dimension to a list of 7 integers, representing the exponent associated with each
-- of the 7 SI base dimensions in the standard order.
-- | Converts a dimension to a list of 9 integers, representing the exponent associated with each
-- of the 7 SI base dimensions in the standard order, followed by the dimensions of plane and spherical angles.
asList :: Dimension' -> [Int]
asList (Dim' l m t i th n j) = [l, m, t, i, th, n, j]
asList (Dim' l m t i th n j pa) = [l, m, t, i, th, n, j, pa]
Loading