{- Copyright (C) 2011 Dr. Alistair Ward This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. -} {- | [@AUTHOR@] Dr. Alistair Ward [@DESCRIPTION@] * Describes a simple numeric type, designed to contain an /exponential/ number. * <https://en.wikipedia.org/wiki/Exponentiation>. -} module Factory.Data.Exponential( -- * Types -- ** Type-synonyms Exponential, -- * Functions evaluate, invert, -- ** Accessors getBase, getExponent, -- ** Constructor rightIdentity, -- ** Operators (<^), (=~) ) where import qualified Control.Arrow infix 4 =~ -- Same as (==). infixr 8 <^ -- Same as (^). -- | Describes an /exponential/, in terms of its /base/ and /exponent/. type Exponential base exponent = (base, exponent) -- | Accessor. {-# INLINE getBase #-} getBase :: Exponential base exponent -> base getBase = fst -- | Accessor. {-# INLINE getExponent #-} getExponent :: Exponential base exponent -> exponent getExponent = snd {- | * Construct an 'Exponential' merely raised to the 1st power. * The value of the resulting exponential is the same as specified 'base'; <https://en.wikipedia.org/wiki/Identity_element>. -} rightIdentity :: Num exponent => base -> Exponential base exponent rightIdentity x = (x, 1) -- | Evaluate the specified 'Exponential', returning the resulting number. {-# INLINE evaluate #-} evaluate :: (Num base, Integral exponent) => Exponential base exponent -> base evaluate = uncurry (^) -- CAVEAT: in this eta-reduced form, it'll only be inlined when called without arguments. -- | True if the /bases/ are equal. (=~) :: Eq base => Exponential base exponent -> Exponential base exponent -> Bool (l, _) =~ (r, _) = l == r -- | Raise the specified 'Exponential' to a power. (<^) :: Num exponent => Exponential base exponent -- ^ The operand. -> exponent -- ^ The power to which the exponential is to be raised. -> Exponential base exponent -- ^ The result. (b, e) <^ power = (b, e * power) -- | Invert the value, by negating the exponent. invert :: Num exponent => Exponential base exponent -> Exponential base exponent invert = Control.Arrow.second negate