{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-} -- for Vector instances only
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeSynonymInstances #-}

module Numeric.Units.Dimensional.Internal
(
  KnownVariant(..),
  Dimensional(..),
  type Unit, type Quantity, type SQuantity,
  siUnit, showIn,
  liftD, liftD2,
  liftQ, liftQ2
)
where

import Control.Applicative
import Control.DeepSeq
import Data.AEq (AEq)
import Data.Coerce (coerce)
import Data.Data
import Data.Kind
import Data.ExactPi
import Data.Functor.Classes (Eq1(..), Ord1(..))
import qualified Data.ExactPi.TypeLevel as E
import Data.Monoid (Monoid(..))
import Data.Semigroup (Semigroup(..))
import Foreign.Ptr (Ptr, castPtr)
import Foreign.Storable (Storable(..))
import GHC.Generics
import Numeric.Units.Dimensional.Dimensions
import Numeric.Units.Dimensional.Variants
import Numeric.Units.Dimensional.UnitNames hiding ((*), (/), (^), weaken, strengthen)
import qualified Numeric.Units.Dimensional.UnitNames.Internal as Name
import Numeric.Units.Dimensional.UnitNames.InterchangeNames (HasInterchangeName(..))
import qualified Data.Vector.Generic.Mutable as M
import qualified Data.Vector.Generic as G
import qualified Data.Vector.Unboxed.Base as U
import Prelude
  ( Show, Eq(..), Ord, Bounded(..), Num, Fractional, Functor, Real(..)
  , String, Maybe(..), Double
  , (.), ($), (++), (+), (/)
  , show, otherwise, undefined, error, fmap, realToFrac
  )
import qualified Prelude as P

-- $setup
-- >>> :set -XNoImplicitPrelude
-- >>> import Numeric.Units.Dimensional.Prelude

-- | A unit of measurement.
type Unit (m :: Metricality) = Dimensional ('DUnit m)

-- | A dimensional quantity.
type Quantity = SQuantity E.One

-- | A dimensional quantity, stored as an 'ExactPi'' multiple of its value in its dimension's SI coherent unit.
--
-- The name is an abbreviation for scaled quantity.
type SQuantity s = Dimensional ('DQuantity s)

-- | A KnownVariant is one whose term-level 'Dimensional' values we can represent with an associated data family instance
-- and manipulate with certain functions, not all of which are exported from the package.
--
-- Each validly constructed type of kind 'Variant' has a 'KnownVariant' instance.
class KnownVariant (v :: Variant) where
  -- | A dimensional value, either a 'Quantity' or a 'Unit', parameterized by its 'Dimension' and representation.
  data Dimensional v :: Dimension -> Type -> Type
  -- | A scale factor by which the numerical value of this dimensional value is implicitly multiplied.
  type ScaleFactor v :: E.ExactPi'
  extractValue :: Dimensional v d a -> (a, Maybe ExactPi)
  extractName :: Dimensional v d a -> Maybe (UnitName 'NonMetric)
  injectValue :: Maybe (UnitName 'NonMetric) -> (a, Maybe ExactPi) -> Dimensional v d a
  -- | Maps over the underlying representation of a dimensional value.
  -- The caller is responsible for ensuring that the supplied function respects the dimensional abstraction.
  -- This means that the function must preserve numerical values, or linearly scale them while preserving the origin.
  dmap :: (a1 -> a2) -> Dimensional v d a1 -> Dimensional v d a2

deriving instance Typeable Dimensional

instance KnownVariant ('DQuantity s) where
  newtype Dimensional ('DQuantity s) d a = Quantity a
    deriving (Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
(Dimensional ('DQuantity s) d a
 -> Dimensional ('DQuantity s) d a -> Bool)
-> (Dimensional ('DQuantity s) d a
    -> Dimensional ('DQuantity s) d a -> Bool)
-> Eq (Dimensional ('DQuantity s) d a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (s :: ExactPi') (d :: Dimension) a.
Eq a =>
Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
/= :: Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
$c/= :: forall (s :: ExactPi') (d :: Dimension) a.
Eq a =>
Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
== :: Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
$c== :: forall (s :: ExactPi') (d :: Dimension) a.
Eq a =>
Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
Eq, Eq (Dimensional ('DQuantity s) d a)
Eq (Dimensional ('DQuantity s) d a)
-> (Dimensional ('DQuantity s) d a
    -> Dimensional ('DQuantity s) d a -> Ordering)
-> (Dimensional ('DQuantity s) d a
    -> Dimensional ('DQuantity s) d a -> Bool)
-> (Dimensional ('DQuantity s) d a
    -> Dimensional ('DQuantity s) d a -> Bool)
-> (Dimensional ('DQuantity s) d a
    -> Dimensional ('DQuantity s) d a -> Bool)
-> (Dimensional ('DQuantity s) d a
    -> Dimensional ('DQuantity s) d a -> Bool)
-> (Dimensional ('DQuantity s) d a
    -> Dimensional ('DQuantity s) d a
    -> Dimensional ('DQuantity s) d a)
-> (Dimensional ('DQuantity s) d a
    -> Dimensional ('DQuantity s) d a
    -> Dimensional ('DQuantity s) d a)
-> Ord (Dimensional ('DQuantity s) d a)
Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Ordering
Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Dimensional ('DQuantity s) d a
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall (s :: ExactPi') (d :: Dimension) a.
Ord a =>
Eq (Dimensional ('DQuantity s) d a)
forall (s :: ExactPi') (d :: Dimension) a.
Ord a =>
Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
forall (s :: ExactPi') (d :: Dimension) a.
Ord a =>
Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Ordering
forall (s :: ExactPi') (d :: Dimension) a.
Ord a =>
Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Dimensional ('DQuantity s) d a
min :: Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Dimensional ('DQuantity s) d a
$cmin :: forall (s :: ExactPi') (d :: Dimension) a.
Ord a =>
Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Dimensional ('DQuantity s) d a
max :: Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Dimensional ('DQuantity s) d a
$cmax :: forall (s :: ExactPi') (d :: Dimension) a.
Ord a =>
Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Dimensional ('DQuantity s) d a
>= :: Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
$c>= :: forall (s :: ExactPi') (d :: Dimension) a.
Ord a =>
Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
> :: Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
$c> :: forall (s :: ExactPi') (d :: Dimension) a.
Ord a =>
Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
<= :: Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
$c<= :: forall (s :: ExactPi') (d :: Dimension) a.
Ord a =>
Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
< :: Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
$c< :: forall (s :: ExactPi') (d :: Dimension) a.
Ord a =>
Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
compare :: Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Ordering
$ccompare :: forall (s :: ExactPi') (d :: Dimension) a.
Ord a =>
Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Ordering
$cp1Ord :: forall (s :: ExactPi') (d :: Dimension) a.
Ord a =>
Eq (Dimensional ('DQuantity s) d a)
Ord, Eq (Dimensional ('DQuantity s) d a)
Eq (Dimensional ('DQuantity s) d a)
-> (Dimensional ('DQuantity s) d a
    -> Dimensional ('DQuantity s) d a -> Bool)
-> (Dimensional ('DQuantity s) d a
    -> Dimensional ('DQuantity s) d a -> Bool)
-> AEq (Dimensional ('DQuantity s) d a)
Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
forall a. Eq a -> (a -> a -> Bool) -> (a -> a -> Bool) -> AEq a
forall (s :: ExactPi') (d :: Dimension) a.
AEq a =>
Eq (Dimensional ('DQuantity s) d a)
forall (s :: ExactPi') (d :: Dimension) a.
AEq a =>
Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
~== :: Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
$c~== :: forall (s :: ExactPi') (d :: Dimension) a.
AEq a =>
Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
=== :: Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
$c=== :: forall (s :: ExactPi') (d :: Dimension) a.
AEq a =>
Dimensional ('DQuantity s) d a
-> Dimensional ('DQuantity s) d a -> Bool
$cp1AEq :: forall (s :: ExactPi') (d :: Dimension) a.
AEq a =>
Eq (Dimensional ('DQuantity s) d a)
AEq, Typeable (Dimensional ('DQuantity s) d a)
DataType
Constr
Typeable (Dimensional ('DQuantity s) d a)
-> (forall (c :: Type -> Type).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g)
    -> Dimensional ('DQuantity s) d a
    -> c (Dimensional ('DQuantity s) d a))
-> (forall (c :: Type -> Type).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r)
    -> Constr
    -> c (Dimensional ('DQuantity s) d a))
-> (Dimensional ('DQuantity s) d a -> Constr)
-> (Dimensional ('DQuantity s) d a -> DataType)
-> (forall (t :: Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d. Data d => c (t d))
    -> Maybe (c (Dimensional ('DQuantity s) d a)))
-> (forall (t :: Type -> Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c (Dimensional ('DQuantity s) d a)))
-> ((forall b. Data b => b -> b)
    -> Dimensional ('DQuantity s) d a
    -> Dimensional ('DQuantity s) d a)
-> (forall r r'.
    (r -> r' -> r)
    -> r
    -> (forall d. Data d => d -> r')
    -> Dimensional ('DQuantity s) d a
    -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r
    -> (forall d. Data d => d -> r')
    -> Dimensional ('DQuantity s) d a
    -> r)
-> (forall u.
    (forall d. Data d => d -> u)
    -> Dimensional ('DQuantity s) d a -> [u])
-> (forall u.
    Int
    -> (forall d. Data d => d -> u)
    -> Dimensional ('DQuantity s) d a
    -> u)
-> (forall (m :: Type -> Type).
    Monad m =>
    (forall d. Data d => d -> m d)
    -> Dimensional ('DQuantity s) d a
    -> m (Dimensional ('DQuantity s) d a))
-> (forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> Dimensional ('DQuantity s) d a
    -> m (Dimensional ('DQuantity s) d a))
-> (forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> Dimensional ('DQuantity s) d a
    -> m (Dimensional ('DQuantity s) d a))
-> Data (Dimensional ('DQuantity s) d a)
Dimensional ('DQuantity s) d a -> DataType
Dimensional ('DQuantity s) d a -> Constr
(forall b. Data b => b -> b)
-> Dimensional ('DQuantity s) d a -> Dimensional ('DQuantity s) d a
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g)
-> Dimensional ('DQuantity s) d a
-> c (Dimensional ('DQuantity s) d a)
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r)
-> Constr
-> c (Dimensional ('DQuantity s) d a)
forall a.
Typeable a
-> (forall (c :: Type -> Type).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: Type -> Type).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: Type -> Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: Type -> Type).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u.
Int
-> (forall d. Data d => d -> u)
-> Dimensional ('DQuantity s) d a
-> u
forall u.
(forall d. Data d => d -> u)
-> Dimensional ('DQuantity s) d a -> [u]
forall r r'.
(r -> r' -> r)
-> r
-> (forall d. Data d => d -> r')
-> Dimensional ('DQuantity s) d a
-> r
forall r r'.
(r' -> r -> r)
-> r
-> (forall d. Data d => d -> r')
-> Dimensional ('DQuantity s) d a
-> r
forall (s :: ExactPi') (d :: Dimension) a.
(Typeable s, Typeable d, Data a) =>
Typeable (Dimensional ('DQuantity s) d a)
forall (s :: ExactPi') (d :: Dimension) a.
(Typeable s, Typeable d, Data a) =>
Dimensional ('DQuantity s) d a -> DataType
forall (s :: ExactPi') (d :: Dimension) a.
(Typeable s, Typeable d, Data a) =>
Dimensional ('DQuantity s) d a -> Constr
forall (s :: ExactPi') (d :: Dimension) a.
(Typeable s, Typeable d, Data a) =>
(forall b. Data b => b -> b)
-> Dimensional ('DQuantity s) d a -> Dimensional ('DQuantity s) d a
forall (s :: ExactPi') (d :: Dimension) a u.
(Typeable s, Typeable d, Data a) =>
Int
-> (forall d. Data d => d -> u)
-> Dimensional ('DQuantity s) d a
-> u
forall (s :: ExactPi') (d :: Dimension) a u.
(Typeable s, Typeable d, Data a) =>
(forall d. Data d => d -> u)
-> Dimensional ('DQuantity s) d a -> [u]
forall (s :: ExactPi') (d :: Dimension) a r r'.
(Typeable s, Typeable d, Data a) =>
(r -> r' -> r)
-> r
-> (forall d. Data d => d -> r')
-> Dimensional ('DQuantity s) d a
-> r
forall (s :: ExactPi') (d :: Dimension) a r r'.
(Typeable s, Typeable d, Data a) =>
(r' -> r -> r)
-> r
-> (forall d. Data d => d -> r')
-> Dimensional ('DQuantity s) d a
-> r
forall (s :: ExactPi') (d :: Dimension) a (m :: Type -> Type).
(Typeable s, Typeable d, Data a, Monad m) =>
(forall d. Data d => d -> m d)
-> Dimensional ('DQuantity s) d a
-> m (Dimensional ('DQuantity s) d a)
forall (s :: ExactPi') (d :: Dimension) a (m :: Type -> Type).
(Typeable s, Typeable d, Data a, MonadPlus m) =>
(forall d. Data d => d -> m d)
-> Dimensional ('DQuantity s) d a
-> m (Dimensional ('DQuantity s) d a)
forall (s :: ExactPi') (d :: Dimension) a (c :: Type -> Type).
(Typeable s, Typeable d, Data a) =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r)
-> Constr
-> c (Dimensional ('DQuantity s) d a)
forall (s :: ExactPi') (d :: Dimension) a (c :: Type -> Type).
(Typeable s, Typeable d, Data a) =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g)
-> Dimensional ('DQuantity s) d a
-> c (Dimensional ('DQuantity s) d a)
forall (s :: ExactPi') (d :: Dimension) a (t :: Type -> Type)
       (c :: Type -> Type).
(Typeable s, Typeable d, Data a, Typeable t) =>
(forall d. Data d => c (t d))
-> Maybe (c (Dimensional ('DQuantity s) d a))
forall (s :: ExactPi') (d :: Dimension) a
       (t :: Type -> Type -> Type) (c :: Type -> Type).
(Typeable s, Typeable d, Data a, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (Dimensional ('DQuantity s) d a))
forall (m :: Type -> Type).
Monad m =>
(forall d. Data d => d -> m d)
-> Dimensional ('DQuantity s) d a
-> m (Dimensional ('DQuantity s) d a)
forall (m :: Type -> Type).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> Dimensional ('DQuantity s) d a
-> m (Dimensional ('DQuantity s) d a)
forall (c :: Type -> Type).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r)
-> Constr
-> c (Dimensional ('DQuantity s) d a)
forall (c :: Type -> Type).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g)
-> Dimensional ('DQuantity s) d a
-> c (Dimensional ('DQuantity s) d a)
forall (t :: Type -> Type) (c :: Type -> Type).
Typeable t =>
(forall d. Data d => c (t d))
-> Maybe (c (Dimensional ('DQuantity s) d a))
forall (t :: Type -> Type -> Type) (c :: Type -> Type).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (Dimensional ('DQuantity s) d a))
$cQuantity :: Constr
$tR:DimensionalDQuantityda :: DataType
gmapMo :: (forall d. Data d => d -> m d)
-> Dimensional ('DQuantity s) d a
-> m (Dimensional ('DQuantity s) d a)
$cgmapMo :: forall (s :: ExactPi') (d :: Dimension) a (m :: Type -> Type).
(Typeable s, Typeable d, Data a, MonadPlus m) =>
(forall d. Data d => d -> m d)
-> Dimensional ('DQuantity s) d a
-> m (Dimensional ('DQuantity s) d a)
gmapMp :: (forall d. Data d => d -> m d)
-> Dimensional ('DQuantity s) d a
-> m (Dimensional ('DQuantity s) d a)
$cgmapMp :: forall (s :: ExactPi') (d :: Dimension) a (m :: Type -> Type).
(Typeable s, Typeable d, Data a, MonadPlus m) =>
(forall d. Data d => d -> m d)
-> Dimensional ('DQuantity s) d a
-> m (Dimensional ('DQuantity s) d a)
gmapM :: (forall d. Data d => d -> m d)
-> Dimensional ('DQuantity s) d a
-> m (Dimensional ('DQuantity s) d a)
$cgmapM :: forall (s :: ExactPi') (d :: Dimension) a (m :: Type -> Type).
(Typeable s, Typeable d, Data a, Monad m) =>
(forall d. Data d => d -> m d)
-> Dimensional ('DQuantity s) d a
-> m (Dimensional ('DQuantity s) d a)
gmapQi :: Int
-> (forall d. Data d => d -> u)
-> Dimensional ('DQuantity s) d a
-> u
$cgmapQi :: forall (s :: ExactPi') (d :: Dimension) a u.
(Typeable s, Typeable d, Data a) =>
Int
-> (forall d. Data d => d -> u)
-> Dimensional ('DQuantity s) d a
-> u
gmapQ :: (forall d. Data d => d -> u)
-> Dimensional ('DQuantity s) d a -> [u]
$cgmapQ :: forall (s :: ExactPi') (d :: Dimension) a u.
(Typeable s, Typeable d, Data a) =>
(forall d. Data d => d -> u)
-> Dimensional ('DQuantity s) d a -> [u]
gmapQr :: (r' -> r -> r)
-> r
-> (forall d. Data d => d -> r')
-> Dimensional ('DQuantity s) d a
-> r
$cgmapQr :: forall (s :: ExactPi') (d :: Dimension) a r r'.
(Typeable s, Typeable d, Data a) =>
(r' -> r -> r)
-> r
-> (forall d. Data d => d -> r')
-> Dimensional ('DQuantity s) d a
-> r
gmapQl :: (r -> r' -> r)
-> r
-> (forall d. Data d => d -> r')
-> Dimensional ('DQuantity s) d a
-> r
$cgmapQl :: forall (s :: ExactPi') (d :: Dimension) a r r'.
(Typeable s, Typeable d, Data a) =>
(r -> r' -> r)
-> r
-> (forall d. Data d => d -> r')
-> Dimensional ('DQuantity s) d a
-> r
gmapT :: (forall b. Data b => b -> b)
-> Dimensional ('DQuantity s) d a -> Dimensional ('DQuantity s) d a
$cgmapT :: forall (s :: ExactPi') (d :: Dimension) a.
(Typeable s, Typeable d, Data a) =>
(forall b. Data b => b -> b)
-> Dimensional ('DQuantity s) d a -> Dimensional ('DQuantity s) d a
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (Dimensional ('DQuantity s) d a))
$cdataCast2 :: forall (s :: ExactPi') (d :: Dimension) a
       (t :: Type -> Type -> Type) (c :: Type -> Type).
(Typeable s, Typeable d, Data a, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (Dimensional ('DQuantity s) d a))
dataCast1 :: (forall d. Data d => c (t d))
-> Maybe (c (Dimensional ('DQuantity s) d a))
$cdataCast1 :: forall (s :: ExactPi') (d :: Dimension) a (t :: Type -> Type)
       (c :: Type -> Type).
(Typeable s, Typeable d, Data a, Typeable t) =>
(forall d. Data d => c (t d))
-> Maybe (c (Dimensional ('DQuantity s) d a))
dataTypeOf :: Dimensional ('DQuantity s) d a -> DataType
$cdataTypeOf :: forall (s :: ExactPi') (d :: Dimension) a.
(Typeable s, Typeable d, Data a) =>
Dimensional ('DQuantity s) d a -> DataType
toConstr :: Dimensional ('DQuantity s) d a -> Constr
$ctoConstr :: forall (s :: ExactPi') (d :: Dimension) a.
(Typeable s, Typeable d, Data a) =>
Dimensional ('DQuantity s) d a -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r)
-> Constr
-> c (Dimensional ('DQuantity s) d a)
$cgunfold :: forall (s :: ExactPi') (d :: Dimension) a (c :: Type -> Type).
(Typeable s, Typeable d, Data a) =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r)
-> Constr
-> c (Dimensional ('DQuantity s) d a)
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g)
-> Dimensional ('DQuantity s) d a
-> c (Dimensional ('DQuantity s) d a)
$cgfoldl :: forall (s :: ExactPi') (d :: Dimension) a (c :: Type -> Type).
(Typeable s, Typeable d, Data a) =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g)
-> Dimensional ('DQuantity s) d a
-> c (Dimensional ('DQuantity s) d a)
$cp1Data :: forall (s :: ExactPi') (d :: Dimension) a.
(Typeable s, Typeable d, Data a) =>
Typeable (Dimensional ('DQuantity s) d a)
Data, (forall x.
 Dimensional ('DQuantity s) d a
 -> Rep (Dimensional ('DQuantity s) d a) x)
-> (forall x.
    Rep (Dimensional ('DQuantity s) d a) x
    -> Dimensional ('DQuantity s) d a)
-> Generic (Dimensional ('DQuantity s) d a)
forall x.
Rep (Dimensional ('DQuantity s) d a) x
-> Dimensional ('DQuantity s) d a
forall x.
Dimensional ('DQuantity s) d a
-> Rep (Dimensional ('DQuantity s) d a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (s :: ExactPi') (d :: Dimension) a x.
Rep (Dimensional ('DQuantity s) d a) x
-> Dimensional ('DQuantity s) d a
forall (s :: ExactPi') (d :: Dimension) a x.
Dimensional ('DQuantity s) d a
-> Rep (Dimensional ('DQuantity s) d a) x
$cto :: forall (s :: ExactPi') (d :: Dimension) a x.
Rep (Dimensional ('DQuantity s) d a) x
-> Dimensional ('DQuantity s) d a
$cfrom :: forall (s :: ExactPi') (d :: Dimension) a x.
Dimensional ('DQuantity s) d a
-> Rep (Dimensional ('DQuantity s) d a) x
Generic, (forall a.
 Dimensional ('DQuantity s) d a
 -> Rep1 (Dimensional ('DQuantity s) d) a)
-> (forall a.
    Rep1 (Dimensional ('DQuantity s) d) a
    -> Dimensional ('DQuantity s) d a)
-> Generic1 (Dimensional ('DQuantity s) d)
forall a.
Rep1 (Dimensional ('DQuantity s) d) a
-> Dimensional ('DQuantity s) d a
forall a.
Dimensional ('DQuantity s) d a
-> Rep1 (Dimensional ('DQuantity s) d) a
forall k (f :: k -> Type).
(forall (a :: k). f a -> Rep1 f a)
-> (forall (a :: k). Rep1 f a -> f a) -> Generic1 f
forall (s :: ExactPi') (d :: Dimension) a.
Rep1 (Dimensional ('DQuantity s) d) a
-> Dimensional ('DQuantity s) d a
forall (s :: ExactPi') (d :: Dimension) a.
Dimensional ('DQuantity s) d a
-> Rep1 (Dimensional ('DQuantity s) d) a
$cto1 :: forall (s :: ExactPi') (d :: Dimension) a.
Rep1 (Dimensional ('DQuantity s) d) a
-> Dimensional ('DQuantity s) d a
$cfrom1 :: forall (s :: ExactPi') (d :: Dimension) a.
Dimensional ('DQuantity s) d a
-> Rep1 (Dimensional ('DQuantity s) d) a
Generic1, Typeable)
  type (ScaleFactor ('DQuantity s)) = s
  extractValue :: Dimensional ('DQuantity s) d a -> (a, Maybe ExactPi)
extractValue (Quantity x) = (a
x, Maybe ExactPi
forall a. Maybe a
Nothing)
  extractName :: Dimensional ('DQuantity s) d a -> Maybe (UnitName 'NonMetric)
extractName Dimensional ('DQuantity s) d a
_ = Maybe (UnitName 'NonMetric)
forall a. Maybe a
Nothing
  injectValue :: Maybe (UnitName 'NonMetric)
-> (a, Maybe ExactPi) -> Dimensional ('DQuantity s) d a
injectValue Maybe (UnitName 'NonMetric)
_ (a
x, Maybe ExactPi
_) = a -> Dimensional ('DQuantity s) d a
forall (s :: ExactPi') (d :: Dimension) a.
a -> Dimensional ('DQuantity s) d a
Quantity a
x
  dmap :: (a1 -> a2)
-> Dimensional ('DQuantity s) d a1
-> Dimensional ('DQuantity s) d a2
dmap = (a1 -> a2)
-> Dimensional ('DQuantity s) d a1
-> Dimensional ('DQuantity s) d a2
coerce

instance (Typeable m) => KnownVariant ('DUnit m) where
  data Dimensional ('DUnit m) d a = Unit !(UnitName m) !ExactPi !a
    deriving ((forall x.
 Dimensional ('DUnit m) d a -> Rep (Dimensional ('DUnit m) d a) x)
-> (forall x.
    Rep (Dimensional ('DUnit m) d a) x -> Dimensional ('DUnit m) d a)
-> Generic (Dimensional ('DUnit m) d a)
forall x.
Rep (Dimensional ('DUnit m) d a) x -> Dimensional ('DUnit m) d a
forall x.
Dimensional ('DUnit m) d a -> Rep (Dimensional ('DUnit m) d a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (m :: Metricality) (d :: Dimension) a x.
Rep (Dimensional ('DUnit m) d a) x -> Dimensional ('DUnit m) d a
forall (m :: Metricality) (d :: Dimension) a x.
Dimensional ('DUnit m) d a -> Rep (Dimensional ('DUnit m) d a) x
$cto :: forall (m :: Metricality) (d :: Dimension) a x.
Rep (Dimensional ('DUnit m) d a) x -> Dimensional ('DUnit m) d a
$cfrom :: forall (m :: Metricality) (d :: Dimension) a x.
Dimensional ('DUnit m) d a -> Rep (Dimensional ('DUnit m) d a) x
Generic, (forall a.
 Dimensional ('DUnit m) d a -> Rep1 (Dimensional ('DUnit m) d) a)
-> (forall a.
    Rep1 (Dimensional ('DUnit m) d) a -> Dimensional ('DUnit m) d a)
-> Generic1 (Dimensional ('DUnit m) d)
forall a.
Rep1 (Dimensional ('DUnit m) d) a -> Dimensional ('DUnit m) d a
forall a.
Dimensional ('DUnit m) d a -> Rep1 (Dimensional ('DUnit m) d) a
forall k (f :: k -> Type).
(forall (a :: k). f a -> Rep1 f a)
-> (forall (a :: k). Rep1 f a -> f a) -> Generic1 f
forall (m :: Metricality) (d :: Dimension) a.
Rep1 (Dimensional ('DUnit m) d) a -> Dimensional ('DUnit m) d a
forall (m :: Metricality) (d :: Dimension) a.
Dimensional ('DUnit m) d a -> Rep1 (Dimensional ('DUnit m) d) a
$cto1 :: forall (m :: Metricality) (d :: Dimension) a.
Rep1 (Dimensional ('DUnit m) d) a -> Dimensional ('DUnit m) d a
$cfrom1 :: forall (m :: Metricality) (d :: Dimension) a.
Dimensional ('DUnit m) d a -> Rep1 (Dimensional ('DUnit m) d) a
Generic1, Typeable)
  type (ScaleFactor ('DUnit m)) = E.One
  extractValue :: Dimensional ('DUnit m) d a -> (a, Maybe ExactPi)
extractValue (Unit _ e x) = (a
x, ExactPi -> Maybe ExactPi
forall a. a -> Maybe a
Just ExactPi
e)
  extractName :: Dimensional ('DUnit m) d a -> Maybe (UnitName 'NonMetric)
extractName (Unit n _ _) = UnitName 'NonMetric -> Maybe (UnitName 'NonMetric)
forall a. a -> Maybe a
Just (UnitName 'NonMetric -> Maybe (UnitName 'NonMetric))
-> (UnitName m -> UnitName 'NonMetric)
-> UnitName m
-> Maybe (UnitName 'NonMetric)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnitName m -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName 'NonMetric
Name.weaken (UnitName m -> Maybe (UnitName 'NonMetric))
-> UnitName m -> Maybe (UnitName 'NonMetric)
forall a b. (a -> b) -> a -> b
$ UnitName m
n
  injectValue :: Maybe (UnitName 'NonMetric)
-> (a, Maybe ExactPi) -> Dimensional ('DUnit m) d a
injectValue (Just UnitName 'NonMetric
n) (a
x, Just ExactPi
e) | Just UnitName m
n' <- UnitName 'NonMetric -> Maybe (UnitName m)
forall (m1 :: Metricality) (m2 :: Metricality).
(Typeable m1, Typeable m2) =>
UnitName m1 -> Maybe (UnitName m2)
relax UnitName 'NonMetric
n = UnitName m -> ExactPi -> a -> Dimensional ('DUnit m) d a
forall (m :: Metricality) (d :: Dimension) a.
UnitName m -> ExactPi -> a -> Dimensional ('DUnit m) d a
Unit UnitName m
n' ExactPi
e a
x
                                   | Bool
otherwise          = [Char] -> Dimensional ('DUnit m) d a
forall a. HasCallStack => [Char] -> a
error [Char]
"Shouldn't be reachable. Needed a metric name but got a non-metric one."
  injectValue Maybe (UnitName 'NonMetric)
_        (a, Maybe ExactPi)
_ = [Char] -> Dimensional ('DUnit m) d a
forall a. HasCallStack => [Char] -> a
error [Char]
"Shouldn't be reachable. Needed to name a quantity."
  dmap :: (a1 -> a2)
-> Dimensional ('DUnit m) d a1 -> Dimensional ('DUnit m) d a2
dmap a1 -> a2
f (Unit n e x) = UnitName m -> ExactPi -> a2 -> Dimensional ('DUnit m) d a2
forall (m :: Metricality) (d :: Dimension) a.
UnitName m -> ExactPi -> a -> Dimensional ('DUnit m) d a
Unit UnitName m
n ExactPi
e (a1 -> a2
f a1
x)

-- GHC is somewhat unclear about why, but it won't derive this instance, so we give it explicitly.
instance (Bounded a) => Bounded (SQuantity s d a) where
  minBound :: SQuantity s d a
minBound = a -> SQuantity s d a
forall (s :: ExactPi') (d :: Dimension) a.
a -> Dimensional ('DQuantity s) d a
Quantity a
forall a. Bounded a => a
minBound
  maxBound :: SQuantity s d a
maxBound = a -> SQuantity s d a
forall (s :: ExactPi') (d :: Dimension) a.
a -> Dimensional ('DQuantity s) d a
Quantity a
forall a. Bounded a => a
maxBound

instance Eq1 (SQuantity s d) where
  liftEq :: (a -> b -> Bool) -> SQuantity s d a -> SQuantity s d b -> Bool
liftEq = (a -> b -> Bool) -> SQuantity s d a -> SQuantity s d b -> Bool
coerce

instance Ord1 (SQuantity s d) where
  liftCompare :: (a -> b -> Ordering)
-> SQuantity s d a -> SQuantity s d b -> Ordering
liftCompare = (a -> b -> Ordering)
-> SQuantity s d a -> SQuantity s d b -> Ordering
coerce

instance HasInterchangeName (Unit m d a) where
  interchangeName :: Unit m d a -> InterchangeName
interchangeName (Unit n _ _) = UnitName m -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName UnitName m
n

{-
Since quantities form a monoid under addition, but not under multiplication unless they are dimensionless,
we will define a monoid instance that adds.
-}

-- | 'Quantity's of a given 'Dimension' form a 'Semigroup' under addition.
instance (Num a) => Semigroup (SQuantity s d a) where
  <> :: SQuantity s d a -> SQuantity s d a -> SQuantity s d a
(<>) = (a -> a -> a)
-> SQuantity s d a -> SQuantity s d a -> SQuantity s d a
forall a (s1 :: ExactPi') (d1 :: Dimension) (s2 :: ExactPi')
       (d2 :: Dimension) (s3 :: ExactPi') (d3 :: Dimension).
(a -> a -> a)
-> SQuantity s1 d1 a -> SQuantity s2 d2 a -> SQuantity s3 d3 a
liftQ2 a -> a -> a
forall a. Num a => a -> a -> a
(+)

-- | 'Quantity's of a given 'Dimension' form a 'Monoid' under addition.
instance (Num a) => Monoid (SQuantity s d a) where
  mempty :: SQuantity s d a
mempty = a -> SQuantity s d a
forall (s :: ExactPi') (d :: Dimension) a.
a -> Dimensional ('DQuantity s) d a
Quantity a
0
  mappend :: SQuantity s d a -> SQuantity s d a -> SQuantity s d a
mappend = SQuantity s d a -> SQuantity s d a -> SQuantity s d a
forall a. Semigroup a => a -> a -> a
(<>)

{-

= Dimensionless =

For dimensionless quantities pretty much any operation is applicable.
We provide this freedom by making 'Dimensionless' an instance of
'Functor'.
-}

instance Functor (SQuantity s DOne) where
  fmap :: (a -> b) -> SQuantity s DOne a -> SQuantity s DOne b
fmap = (a -> b) -> SQuantity s DOne a -> SQuantity s DOne b
forall (v :: Variant) a1 a2 (d :: Dimension).
KnownVariant v =>
(a1 -> a2) -> Dimensional v d a1 -> Dimensional v d a2
dmap

instance (KnownDimension d) => HasDynamicDimension (Dimensional v d a) where

instance (KnownDimension d) => HasDimension (Dimensional v d a) where
  dimension :: Dimensional v d a -> Dimension'
dimension Dimensional v d a
_ = Proxy d -> Dimension'
forall a. HasDimension a => a -> Dimension'
dimension (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d)

-- | 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 :: forall d a.(KnownDimension d, Num a) => Unit 'NonMetric d a
siUnit :: Unit 'NonMetric d a
siUnit = UnitName 'NonMetric -> ExactPi -> a -> Unit 'NonMetric d a
forall (m :: Metricality) (d :: Dimension) a.
UnitName m -> ExactPi -> a -> Dimensional ('DUnit m) d a
Unit (Dimension' -> UnitName 'NonMetric
baseUnitName (Dimension' -> UnitName 'NonMetric)
-> Dimension' -> UnitName 'NonMetric
forall a b. (a -> b) -> a -> b
$ Proxy d -> Dimension'
forall a. HasDimension a => a -> Dimension'
dimension (Proxy d
forall k (t :: k). Proxy t
Proxy :: Proxy d)) ExactPi
1 a
1

instance NFData a => NFData (Quantity d a) -- instance is derived from Generic instance

instance Storable a => Storable (SQuantity s d a) where
  sizeOf :: SQuantity s d a -> Int
sizeOf SQuantity s d a
_ = a -> Int
forall a. Storable a => a -> Int
sizeOf (a
forall a. HasCallStack => a
undefined :: a)
  {-# INLINE sizeOf #-}
  alignment :: SQuantity s d a -> Int
alignment SQuantity s d a
_ = a -> Int
forall a. Storable a => a -> Int
alignment (a
forall a. HasCallStack => a
undefined :: a)
  {-# INLINE alignment #-}
  poke :: Ptr (SQuantity s d a) -> SQuantity s d a -> IO ()
poke Ptr (SQuantity s d a)
ptr = Ptr a -> a -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke (Ptr (SQuantity s d a) -> Ptr a
forall a b. Ptr a -> Ptr b
castPtr Ptr (SQuantity s d a)
ptr :: Ptr a) (a -> IO ()) -> (SQuantity s d a -> a) -> SQuantity s d a -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SQuantity s d a -> a
coerce
  {-# INLINE poke #-}
  peek :: Ptr (SQuantity s d a) -> IO (SQuantity s d a)
peek Ptr (SQuantity s d a)
ptr = (a -> SQuantity s d a) -> IO a -> IO (SQuantity s d a)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> SQuantity s d a
forall (s :: ExactPi') (d :: Dimension) a.
a -> Dimensional ('DQuantity s) d a
Quantity (Ptr a -> IO a
forall a. Storable a => Ptr a -> IO a
peek (Ptr (SQuantity s d a) -> Ptr a
forall a b. Ptr a -> Ptr b
castPtr Ptr (SQuantity s d a)
ptr :: Ptr a))
  {-# INLINE peek #-}

{-
Instances for vectors of quantities.
-}
newtype instance U.Vector (SQuantity s d a)    =  V_Quantity {Vector (SQuantity s d a) -> Vector a
unVQ :: U.Vector a}
newtype instance U.MVector v (SQuantity s d a) = MV_Quantity {MVector v (SQuantity s d a) -> MVector v a
unMVQ :: U.MVector v a}
instance U.Unbox a => U.Unbox (SQuantity s d a)

instance (M.MVector U.MVector a) => M.MVector U.MVector (SQuantity s d a) where
  basicLength :: MVector s (SQuantity s d a) -> Int
basicLength          = MVector s a -> Int
forall (v :: Type -> Type -> Type) a s. MVector v a => v s a -> Int
M.basicLength (MVector s a -> Int)
-> (MVector s (SQuantity s d a) -> MVector s a)
-> MVector s (SQuantity s d a)
-> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MVector s (SQuantity s d a) -> MVector s a
forall v (s :: ExactPi') (d :: Dimension) a.
MVector v (SQuantity s d a) -> MVector v a
unMVQ
  {-# INLINE basicLength #-}
  basicUnsafeSlice :: Int
-> Int
-> MVector s (SQuantity s d a)
-> MVector s (SQuantity s d a)
basicUnsafeSlice Int
m Int
n = MVector s a -> MVector s (SQuantity s d a)
forall v (s :: ExactPi') (d :: Dimension) a.
MVector v a -> MVector v (SQuantity s d a)
MV_Quantity (MVector s a -> MVector s (SQuantity s d a))
-> (MVector s (SQuantity s d a) -> MVector s a)
-> MVector s (SQuantity s d a)
-> MVector s (SQuantity s d a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int -> MVector s a -> MVector s a
forall (v :: Type -> Type -> Type) a s.
MVector v a =>
Int -> Int -> v s a -> v s a
M.basicUnsafeSlice Int
m Int
n (MVector s a -> MVector s a)
-> (MVector s (SQuantity s d a) -> MVector s a)
-> MVector s (SQuantity s d a)
-> MVector s a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MVector s (SQuantity s d a) -> MVector s a
forall v (s :: ExactPi') (d :: Dimension) a.
MVector v (SQuantity s d a) -> MVector v a
unMVQ
  {-# INLINE basicUnsafeSlice #-}
  basicOverlaps :: MVector s (SQuantity s d a) -> MVector s (SQuantity s d a) -> Bool
basicOverlaps MVector s (SQuantity s d a)
u MVector s (SQuantity s d a)
v    = MVector s a -> MVector s a -> Bool
forall (v :: Type -> Type -> Type) a s.
MVector v a =>
v s a -> v s a -> Bool
M.basicOverlaps (MVector s (SQuantity s d a) -> MVector s a
forall v (s :: ExactPi') (d :: Dimension) a.
MVector v (SQuantity s d a) -> MVector v a
unMVQ MVector s (SQuantity s d a)
u) (MVector s (SQuantity s d a) -> MVector s a
forall v (s :: ExactPi') (d :: Dimension) a.
MVector v (SQuantity s d a) -> MVector v a
unMVQ MVector s (SQuantity s d a)
v)
  {-# INLINE basicOverlaps #-}
  basicUnsafeNew :: Int -> ST s (MVector s (SQuantity s d a))
basicUnsafeNew       = (MVector s a -> MVector s (SQuantity s d a))
-> ST s (MVector s a) -> ST s (MVector s (SQuantity s d a))
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap MVector s a -> MVector s (SQuantity s d a)
forall v (s :: ExactPi') (d :: Dimension) a.
MVector v a -> MVector v (SQuantity s d a)
MV_Quantity (ST s (MVector s a) -> ST s (MVector s (SQuantity s d a)))
-> (Int -> ST s (MVector s a))
-> Int
-> ST s (MVector s (SQuantity s d a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ST s (MVector s a)
forall (v :: Type -> Type -> Type) a s.
MVector v a =>
Int -> ST s (v s a)
M.basicUnsafeNew
  {-# INLINE basicUnsafeNew #-}
  basicUnsafeRead :: MVector s (SQuantity s d a) -> Int -> ST s (SQuantity s d a)
basicUnsafeRead MVector s (SQuantity s d a)
v    = (a -> SQuantity s d a) -> ST s a -> ST s (SQuantity s d a)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> SQuantity s d a
forall (s :: ExactPi') (d :: Dimension) a.
a -> Dimensional ('DQuantity s) d a
Quantity (ST s a -> ST s (SQuantity s d a))
-> (Int -> ST s a) -> Int -> ST s (SQuantity s d a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MVector s a -> Int -> ST s a
forall (v :: Type -> Type -> Type) a s.
MVector v a =>
v s a -> Int -> ST s a
M.basicUnsafeRead (MVector s (SQuantity s d a) -> MVector s a
forall v (s :: ExactPi') (d :: Dimension) a.
MVector v (SQuantity s d a) -> MVector v a
unMVQ MVector s (SQuantity s d a)
v)
  {-# INLINE basicUnsafeRead #-}
  basicUnsafeWrite :: MVector s (SQuantity s d a) -> Int -> SQuantity s d a -> ST s ()
basicUnsafeWrite MVector s (SQuantity s d a)
v Int
i = MVector s a -> Int -> a -> ST s ()
forall (v :: Type -> Type -> Type) a s.
MVector v a =>
v s a -> Int -> a -> ST s ()
M.basicUnsafeWrite (MVector s (SQuantity s d a) -> MVector s a
forall v (s :: ExactPi') (d :: Dimension) a.
MVector v (SQuantity s d a) -> MVector v a
unMVQ MVector s (SQuantity s d a)
v) Int
i (a -> ST s ())
-> (SQuantity s d a -> a) -> SQuantity s d a -> ST s ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SQuantity s d a -> a
coerce
  {-# INLINE basicUnsafeWrite #-}
#if MIN_VERSION_vector(0,11,0)
  basicInitialize :: MVector s (SQuantity s d a) -> ST s ()
basicInitialize      = MVector s a -> ST s ()
forall (v :: Type -> Type -> Type) a s.
MVector v a =>
v s a -> ST s ()
M.basicInitialize (MVector s a -> ST s ())
-> (MVector s (SQuantity s d a) -> MVector s a)
-> MVector s (SQuantity s d a)
-> ST s ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MVector s (SQuantity s d a) -> MVector s a
forall v (s :: ExactPi') (d :: Dimension) a.
MVector v (SQuantity s d a) -> MVector v a
unMVQ
  {-# INLINE basicInitialize #-}
#endif

instance (G.Vector U.Vector a) => G.Vector U.Vector (SQuantity s d a) where
  basicUnsafeFreeze :: Mutable Vector s (SQuantity s d a)
-> ST s (Vector (SQuantity s d a))
basicUnsafeFreeze    = (Vector a -> Vector (SQuantity s d a))
-> ST s (Vector a) -> ST s (Vector (SQuantity s d a))
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap Vector a -> Vector (SQuantity s d a)
forall (s :: ExactPi') (d :: Dimension) a.
Vector a -> Vector (SQuantity s d a)
V_Quantity  (ST s (Vector a) -> ST s (Vector (SQuantity s d a)))
-> (MVector s (SQuantity s d a) -> ST s (Vector a))
-> MVector s (SQuantity s d a)
-> ST s (Vector (SQuantity s d a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MVector s a -> ST s (Vector a)
forall (v :: Type -> Type) a s.
Vector v a =>
Mutable v s a -> ST s (v a)
G.basicUnsafeFreeze (MVector s a -> ST s (Vector a))
-> (MVector s (SQuantity s d a) -> MVector s a)
-> MVector s (SQuantity s d a)
-> ST s (Vector a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MVector s (SQuantity s d a) -> MVector s a
forall v (s :: ExactPi') (d :: Dimension) a.
MVector v (SQuantity s d a) -> MVector v a
unMVQ
  {-# INLINE basicUnsafeFreeze #-}
  basicUnsafeThaw :: Vector (SQuantity s d a)
-> ST s (Mutable Vector s (SQuantity s d a))
basicUnsafeThaw      = (MVector s a -> MVector s (SQuantity s d a))
-> ST s (MVector s a) -> ST s (MVector s (SQuantity s d a))
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap MVector s a -> MVector s (SQuantity s d a)
forall v (s :: ExactPi') (d :: Dimension) a.
MVector v a -> MVector v (SQuantity s d a)
MV_Quantity (ST s (MVector s a) -> ST s (MVector s (SQuantity s d a)))
-> (Vector (SQuantity s d a) -> ST s (MVector s a))
-> Vector (SQuantity s d a)
-> ST s (MVector s (SQuantity s d a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector a -> ST s (MVector s a)
forall (v :: Type -> Type) a s.
Vector v a =>
v a -> ST s (Mutable v s a)
G.basicUnsafeThaw   (Vector a -> ST s (MVector s a))
-> (Vector (SQuantity s d a) -> Vector a)
-> Vector (SQuantity s d a)
-> ST s (MVector s a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector (SQuantity s d a) -> Vector a
forall (s :: ExactPi') (d :: Dimension) a.
Vector (SQuantity s d a) -> Vector a
unVQ
  {-# INLINE basicUnsafeThaw #-}
  basicLength :: Vector (SQuantity s d a) -> Int
basicLength          = Vector a -> Int
forall (v :: Type -> Type) a. Vector v a => v a -> Int
G.basicLength (Vector a -> Int)
-> (Vector (SQuantity s d a) -> Vector a)
-> Vector (SQuantity s d a)
-> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector (SQuantity s d a) -> Vector a
forall (s :: ExactPi') (d :: Dimension) a.
Vector (SQuantity s d a) -> Vector a
unVQ
  {-# INLINE basicLength #-}
  basicUnsafeSlice :: Int -> Int -> Vector (SQuantity s d a) -> Vector (SQuantity s d a)
basicUnsafeSlice Int
m Int
n = Vector a -> Vector (SQuantity s d a)
forall (s :: ExactPi') (d :: Dimension) a.
Vector a -> Vector (SQuantity s d a)
V_Quantity (Vector a -> Vector (SQuantity s d a))
-> (Vector (SQuantity s d a) -> Vector a)
-> Vector (SQuantity s d a)
-> Vector (SQuantity s d a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int -> Vector a -> Vector a
forall (v :: Type -> Type) a.
Vector v a =>
Int -> Int -> v a -> v a
G.basicUnsafeSlice Int
m Int
n (Vector a -> Vector a)
-> (Vector (SQuantity s d a) -> Vector a)
-> Vector (SQuantity s d a)
-> Vector a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector (SQuantity s d a) -> Vector a
forall (s :: ExactPi') (d :: Dimension) a.
Vector (SQuantity s d a) -> Vector a
unVQ
  {-# INLINE basicUnsafeSlice #-}
  basicUnsafeIndexM :: Vector (SQuantity s d a) -> Int -> Box (SQuantity s d a)
basicUnsafeIndexM Vector (SQuantity s d a)
v  = (a -> SQuantity s d a) -> Box a -> Box (SQuantity s d a)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> SQuantity s d a
forall (s :: ExactPi') (d :: Dimension) a.
a -> Dimensional ('DQuantity s) d a
Quantity (Box a -> Box (SQuantity s d a))
-> (Int -> Box a) -> Int -> Box (SQuantity s d a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector a -> Int -> Box a
forall (v :: Type -> Type) a. Vector v a => v a -> Int -> Box a
G.basicUnsafeIndexM (Vector (SQuantity s d a) -> Vector a
forall (s :: ExactPi') (d :: Dimension) a.
Vector (SQuantity s d a) -> Vector a
unVQ Vector (SQuantity s d a)
v)
  {-# INLINE basicUnsafeIndexM #-}

{-
We will conclude by providing a reasonable 'Show' instance for
quantities. The SI unit of the quantity is inferred
from its dimension.
-}
-- | Uses non-breaking spaces between the value and the unit, and within the unit name.
instance (KnownDimension d, E.KnownExactPi s, Show a, Real a) => Show (SQuantity s d a) where
  show :: SQuantity s d a -> [Char]
show (Quantity x) | ExactPi -> Bool
isExactOne ExactPi
s' = a -> [Char]
forall a. Show a => a -> [Char]
show a
x [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ UnitName 'NonMetric -> [Char]
showName UnitName 'NonMetric
n
                    | Bool
otherwise = [Char]
"Quantity " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ a -> [Char]
forall a. Show a => a -> [Char]
show a
x [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
" {- " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ Quantity d Double -> [Char]
forall a. Show a => a -> [Char]
show Quantity d Double
q [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
" -}"
    where
      s' :: ExactPi
s' = Proxy s -> ExactPi
forall (v :: ExactPi'). KnownExactPi v => Proxy v -> ExactPi
E.exactPiVal (Proxy s
forall k (t :: k). Proxy t
Proxy :: Proxy s)
      s'' :: Double
s'' = ExactPi -> Double
forall a. Floating a => ExactPi -> a
approximateValue ExactPi
s' :: Double
      q :: Quantity d Double
q = Double -> Quantity d Double
forall (s :: ExactPi') (d :: Dimension) a.
a -> Dimensional ('DQuantity s) d a
Quantity (a -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac a
x Double -> Double -> Double
forall a. Num a => a -> a -> a
P.* Double
s'') :: Quantity d Double
      (Unit n _ _) = Dimensional ('DUnit 'NonMetric) d a
forall (d :: Dimension) a.
(KnownDimension d, Num a) =>
Unit 'NonMetric d a
siUnit :: Unit 'NonMetric d a

-- | Shows the value of a 'Quantity' expressed in a specified 'Unit' of the same 'Dimension'.
--
-- Uses non-breaking spaces between the value and the unit, and within the unit name.
--
-- >>> putStrLn $ showIn watt $ (37 *~ volt) * (4 *~ ampere)
-- 148.0 W
showIn :: (Show a, Fractional a) => Unit m d a -> Quantity d a -> String
showIn :: Unit m d a -> Quantity d a -> [Char]
showIn (Unit n _ y) (Quantity x) = a -> [Char]
forall a. Show a => a -> [Char]
show (a
x a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
y) [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ (UnitName 'NonMetric -> [Char]
showName (UnitName 'NonMetric -> [Char])
-> (UnitName m -> UnitName 'NonMetric) -> UnitName m -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnitName m -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName 'NonMetric
Name.weaken (UnitName m -> [Char]) -> UnitName m -> [Char]
forall a b. (a -> b) -> a -> b
$ UnitName m
n)

showName :: UnitName 'NonMetric -> String
showName :: UnitName 'NonMetric -> [Char]
showName UnitName 'NonMetric
n | UnitName 'NonMetric
n UnitName 'NonMetric -> UnitName 'NonMetric -> Bool
forall a. Eq a => a -> a -> Bool
== UnitName 'NonMetric
nOne = [Char]
""
           | Bool
otherwise = [Char]
"\xA0" [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ UnitName 'NonMetric -> [Char]
forall a. Show a => a -> [Char]
show UnitName 'NonMetric
n

-- | Unit names are shown with non-breaking spaces.
instance (Show a) => Show (Unit m d a) where
  show :: Unit m d a -> [Char]
show (Unit n e x) = [Char]
"The unit " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ UnitName m -> [Char]
forall a. Show a => a -> [Char]
show UnitName m
n [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
", with value " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ ExactPi -> [Char]
forall a. Show a => a -> [Char]
show ExactPi
e [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
" (or " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ a -> [Char]
forall a. Show a => a -> [Char]
show a
x [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
")"

-- Operates on a dimensional value using a unary operation on values, possibly yielding a Unit.
liftD :: (KnownVariant v1, KnownVariant v2) => (ExactPi -> ExactPi) -> (a -> b) -> UnitNameTransformer -> Dimensional v1 d1 a -> Dimensional v2 d2 b
liftD :: (ExactPi -> ExactPi)
-> (a -> b)
-> (forall (m :: Metricality). UnitName m -> UnitName 'NonMetric)
-> Dimensional v1 d1 a
-> Dimensional v2 d2 b
liftD ExactPi -> ExactPi
fe a -> b
f forall (m :: Metricality). UnitName m -> UnitName 'NonMetric
nt Dimensional v1 d1 a
x = let (a
x', Maybe ExactPi
e') = Dimensional v1 d1 a -> (a, Maybe ExactPi)
forall (v :: Variant) (d :: Dimension) a.
KnownVariant v =>
Dimensional v d a -> (a, Maybe ExactPi)
extractValue Dimensional v1 d1 a
x
                      n :: Maybe (UnitName 'NonMetric)
n = Dimensional v1 d1 a -> Maybe (UnitName 'NonMetric)
forall (v :: Variant) (d :: Dimension) a.
KnownVariant v =>
Dimensional v d a -> Maybe (UnitName 'NonMetric)
extractName Dimensional v1 d1 a
x
                      n' :: Maybe (UnitName 'NonMetric)
n' = (UnitName 'NonMetric -> UnitName 'NonMetric)
-> Maybe (UnitName 'NonMetric) -> Maybe (UnitName 'NonMetric)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName 'NonMetric
nt Maybe (UnitName 'NonMetric)
n
                   in Maybe (UnitName 'NonMetric)
-> (b, Maybe ExactPi) -> Dimensional v2 d2 b
forall (v :: Variant) a (d :: Dimension).
KnownVariant v =>
Maybe (UnitName 'NonMetric)
-> (a, Maybe ExactPi) -> Dimensional v d a
injectValue Maybe (UnitName 'NonMetric)
n' (a -> b
f a
x', (ExactPi -> ExactPi) -> Maybe ExactPi -> Maybe ExactPi
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap ExactPi -> ExactPi
fe Maybe ExactPi
e')

-- Operates on a dimensional value using a unary operation on values, yielding a Quantity.
liftQ :: (a -> a) -> SQuantity s1 d1 a -> SQuantity s2 d2 a
liftQ :: (a -> a) -> SQuantity s1 d1 a -> SQuantity s2 d2 a
liftQ = (a -> a) -> SQuantity s1 d1 a -> SQuantity s2 d2 a
coerce

-- Combines two dimensional values using a binary operation on values, possibly yielding a Unit.
liftD2 :: (KnownVariant v1, KnownVariant v2, KnownVariant v3) => (ExactPi -> ExactPi -> ExactPi) -> (a -> a -> a) -> UnitNameTransformer2 -> Dimensional v1 d1 a -> Dimensional v2 d2 a -> Dimensional v3 d3 a
liftD2 :: (ExactPi -> ExactPi -> ExactPi)
-> (a -> a -> a)
-> UnitNameTransformer2
-> Dimensional v1 d1 a
-> Dimensional v2 d2 a
-> Dimensional v3 d3 a
liftD2 ExactPi -> ExactPi -> ExactPi
fe a -> a -> a
f UnitNameTransformer2
nt Dimensional v1 d1 a
x1 Dimensional v2 d2 a
x2 = let (a
x1', Maybe ExactPi
e1') = Dimensional v1 d1 a -> (a, Maybe ExactPi)
forall (v :: Variant) (d :: Dimension) a.
KnownVariant v =>
Dimensional v d a -> (a, Maybe ExactPi)
extractValue Dimensional v1 d1 a
x1
                           (a
x2', Maybe ExactPi
e2') = Dimensional v2 d2 a -> (a, Maybe ExactPi)
forall (v :: Variant) (d :: Dimension) a.
KnownVariant v =>
Dimensional v d a -> (a, Maybe ExactPi)
extractValue Dimensional v2 d2 a
x2
                           n1 :: Maybe (UnitName 'NonMetric)
n1 = Dimensional v1 d1 a -> Maybe (UnitName 'NonMetric)
forall (v :: Variant) (d :: Dimension) a.
KnownVariant v =>
Dimensional v d a -> Maybe (UnitName 'NonMetric)
extractName Dimensional v1 d1 a
x1
                           n2 :: Maybe (UnitName 'NonMetric)
n2 = Dimensional v2 d2 a -> Maybe (UnitName 'NonMetric)
forall (v :: Variant) (d :: Dimension) a.
KnownVariant v =>
Dimensional v d a -> Maybe (UnitName 'NonMetric)
extractName Dimensional v2 d2 a
x2
                           n' :: Maybe (UnitName 'NonMetric)
n' = (UnitName 'NonMetric -> UnitName 'NonMetric -> UnitName 'NonMetric)
-> Maybe (UnitName 'NonMetric)
-> Maybe (UnitName 'NonMetric)
-> Maybe (UnitName 'NonMetric)
forall (f :: Type -> Type) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 UnitName 'NonMetric -> UnitName 'NonMetric -> UnitName 'NonMetric
UnitNameTransformer2
nt Maybe (UnitName 'NonMetric)
n1 Maybe (UnitName 'NonMetric)
n2
                        in Maybe (UnitName 'NonMetric)
-> (a, Maybe ExactPi) -> Dimensional v3 d3 a
forall (v :: Variant) a (d :: Dimension).
KnownVariant v =>
Maybe (UnitName 'NonMetric)
-> (a, Maybe ExactPi) -> Dimensional v d a
injectValue Maybe (UnitName 'NonMetric)
n' (a -> a -> a
f a
x1' a
x2', ExactPi -> ExactPi -> ExactPi
fe (ExactPi -> ExactPi -> ExactPi)
-> Maybe ExactPi -> Maybe (ExactPi -> ExactPi)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe ExactPi
e1' Maybe (ExactPi -> ExactPi) -> Maybe ExactPi -> Maybe ExactPi
forall (f :: Type -> Type) a b.
Applicative f =>
f (a -> b) -> f a -> f b
<*> Maybe ExactPi
e2')

-- Combines two dimensional values using a binary operation on values, yielding a Quantity.
liftQ2 :: (a -> a -> a) -> SQuantity s1 d1 a -> SQuantity s2 d2 a -> SQuantity s3 d3 a
liftQ2 :: (a -> a -> a)
-> SQuantity s1 d1 a -> SQuantity s2 d2 a -> SQuantity s3 d3 a
liftQ2 = (a -> a -> a)
-> SQuantity s1 d1 a -> SQuantity s2 d2 a -> SQuantity s3 d3 a
coerce