diff --git a/changelog.txt b/changelog.txt
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,7 @@
+0.5.0
+- Replace calls to Prelude's `atan2` function with calls to the C math
+  library in `ArcTan2` instances for `Float` and `Double`
+
 0.4.0
 - Switch quat2dcm mode to avoid divide by 0, add Ord constraint
 
diff --git a/spatial-math.cabal b/spatial-math.cabal
--- a/spatial-math.cabal
+++ b/spatial-math.cabal
@@ -1,5 +1,5 @@
 name:                spatial-math
-version:             0.4.0.0
+version:             0.5.0.0
 synopsis:            3d math including quaternions/euler angles/dcms and utility functions
 description:         This is a port of my 'mathlib' C library: `https://github.com/ghorn/mathlib`
 license:             BSD3
@@ -18,6 +18,7 @@
   hs-source-dirs:      src
   exposed-modules:     SpatialMath
                        SpatialMathT
+                       SpatialMath.Internal
   other-modules:       Types
   build-depends:       base >= 4 && < 5,
                        ghc-prim,
diff --git a/src/SpatialMath.hs b/src/SpatialMath.hs
--- a/src/SpatialMath.hs
+++ b/src/SpatialMath.hs
@@ -33,11 +33,7 @@
 
 import Types
 
--- | doesn't require RealFloat, used for overloading symbolics
-class Floating a => ArcTan2 a where
-  arctan2 :: a -> a -> a
-instance ArcTan2 Double where arctan2 = atan2
-instance ArcTan2 Float where arctan2 = atan2
+import SpatialMath.Internal ( libm_atan2, libm_atan2f )
 
 -- $setup
 -- |
@@ -50,7 +46,56 @@
 --               | nearZero (x - 1) = 1
 --               | nearZero (x + 1) = -1
 --               | otherwise = x
+--         inf = 1/0
+--         neginf = negate inf
 -- :}
+
+
+-- | doesn't require RealFloat, used for overloading symbolics
+class Floating a => ArcTan2 a where
+  -- | @arctan2 y x@ computes the arctangent from two arguments.  The
+  -- 'Double' and 'Float' instances call out to a sufficiently recent
+  -- version of @libm@ to compute this.
+  --
+  -- The following test cases are the /full/ set of recommended
+  -- function properties specified for function @atan2Pi()@ on page 45
+  -- of the IEEE Std 754-2008 document.
+  --
+  -- >>> arctan2 0 (-0) :: Double
+  -- 3.141592653589793
+  -- >>> arctan2 (-0) (-0) :: Double
+  -- -3.141592653589793
+  -- >>> arctan2 0 0 :: Double
+  -- 0.0
+  -- >>> arctan2 (-0) 0 :: Double
+  -- -0.0
+  --
+  -- prop> \x -> x < 0 ==> arctan2 (-0) x == (-pi :: Double)
+  -- prop> \x -> x < 0 ==> arctan2 0 x == (pi :: Double)
+  -- prop> \x -> x > 0 ==> arctan2 (-0) x == (-0 :: Double)
+  -- prop> \x -> x > 0 ==> arctan2 0 x == (0 :: Double)
+  -- prop> \y -> y < 0 ==> arctan2 y (-0) == (-pi / 2 :: Double)
+  -- prop> \y -> y > 0 ==> arctan2 y 0 == (pi / 2 :: Double)
+  -- prop> \y -> y > 0 && not (isNaN y || isInfinite y) ==> arctan2 y (negate $ 1/0) == (pi :: Double)
+  -- prop> \y -> y < 0 && not (isNaN y || isInfinite y) ==> arctan2 y (negate $ 1/0) == (-pi :: Double)
+  -- prop> \y -> y > 0 && not (isNaN y || isInfinite y) ==> arctan2 y (1/0) == (0 :: Double)
+  -- prop> \y -> y < 0 && not (isNaN y || isInfinite y) ==> arctan2 y (1/0) == (-0 :: Double)
+  -- prop> \x -> not (isNaN x || isInfinite x) ==> arctan2 (negate $ 1/0) x == (-pi/2 :: Double)
+  -- prop> \x -> not (isNaN x || isInfinite x) ==> arctan2 (1/0) x == (pi/2 :: Double)
+  --
+  -- >>> arctan2 neginf neginf :: Double
+  -- -2.356194490192345
+  -- >>> arctan2 inf neginf :: Double
+  -- 2.356194490192345
+  -- >>> arctan2 neginf inf :: Double
+  -- -0.7853981633974483
+  -- >>> arctan2 inf inf :: Double
+  -- 0.7853981633974483
+  arctan2 :: a -> a -> a
+instance ArcTan2 Double where
+  arctan2 = libm_atan2
+instance ArcTan2 Float where
+  arctan2 = libm_atan2f
 
 normalize' :: Floating a => Quaternion a -> Quaternion a
 normalize' q = fmap (* normInv) q
diff --git a/src/SpatialMath/Internal.hs b/src/SpatialMath/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/SpatialMath/Internal.hs
@@ -0,0 +1,25 @@
+{-# OPTIONS_GHC -Wall #-}
+{-# Language ForeignFunctionInterface #-}
+
+module SpatialMath.Internal (
+  libm_atan2
+  , libm_atan2f
+  ) where
+
+import Foreign.C.Types ( CDouble(..), CFloat(..) )
+
+foreign import ccall unsafe "math.h atan2" c_atan2
+  :: CDouble -> CDouble -> CDouble
+
+foreign import ccall unsafe "math.h atan2f" c_atan2f
+  :: CFloat -> CFloat -> CFloat
+
+libm_atan2 :: Double -> Double -> Double
+libm_atan2 y x = ret
+  where
+    CDouble ret = c_atan2 (CDouble y) (CDouble x)
+
+libm_atan2f :: Float -> Float -> Float
+libm_atan2f y x = ret
+  where
+    CFloat ret = c_atan2f (CFloat y) (CFloat x)
diff --git a/src/SpatialMathT.hs b/src/SpatialMathT.hs
--- a/src/SpatialMathT.hs
+++ b/src/SpatialMathT.hs
@@ -31,7 +31,7 @@
        , (:.)(..), unO
        ) where
 
-import Control.Applicative ( Applicative )
+import Control.Applicative ( Applicative, pure)
 import Control.Compose ( (:.)(..), unO )
 import Data.Foldable ( Foldable )
 import Data.Binary ( Binary(..) )
