--------------------------------------------------------------------------------

-- |

--

-- Module      :  Data.Units.AngleSI.System

-- Description :  SI unit system with dimensional angles of dimension A

-- Copyright   :  (c) Alice Rixte 2025

-- License     :  BSD 3

-- Maintainer  :  alice.rixte@u-bordeaux.fr

-- Stability   :  unstable

-- Portability :  non-portable (GHC extensions)

--

-- This module defines radians as the standard unit for the angle (`@A@`)

-- dimension.

--

-- See "Data.Units.SI.Angle" for dimensionless radians and steradians.

--

--------------------------------------------------------------------------------



module Data.Units.AngleSI.System
  ( module Data.Units.SI.System
  , Angle (..)
  , Radian (..)
  , normalizeRadians
  )
  where

import Data.Fixed
import Data.Coerce

import Data.Units.Base
import Data.Units.SI.System

-- | The angle dimension, denotated @A@.

--

$(mkDim "Angle" "A" 1000)


-- | An angle in radians.

--

$(mkBaseUnit "Radian" "rad" ''Angle)

-- | Normalize an angle to the range ]-pi, pi]

normalizeRadians :: (RealFrac a, Floating a) => Radian a -> Radian a
normalizeRadians :: forall a. (RealFrac a, Floating a) => Radian a -> Radian a
normalizeRadians Radian a
x = if Radian a
xmod Radian a -> Radian a -> Bool
forall a. Ord a => a -> a -> Bool
> Radian a
forall a. Floating a => a
pi then Radian a
xmod Radian a -> Radian a -> Radian a
forall a. Num a => a -> a -> a
- Radian a
twoPi else Radian a
xmod
  where
    twoPi :: Radian a
twoPi = Radian a
2 Radian a -> Radian a -> Radian a
forall a. Num a => a -> a -> a
* Radian a
forall a. Floating a => a
pi
    xmod :: Radian a
xmod = Radian a
x Radian a -> Radian a -> Radian a
forall a. Real a => a -> a -> a
`mod'` Radian a
twoPi