{-|
Module: Squeal.PostgreSQL.Expression.Math
Description: math functions
Copyright: (c) Eitan Chatav, 2019
Maintainer: eitan@morphism.tech
Stability: experimental

math functions
-}

{-# LANGUAGE
    DataKinds
  , OverloadedStrings
  , TypeOperators
#-}

module Squeal.PostgreSQL.Expression.Math
  ( -- * Math Function
    atan2_
  , quot_
  , rem_
  , trunc
  , round_
  , ceiling_
  ) where

import Squeal.PostgreSQL.Expression
import Squeal.PostgreSQL.Type.List
import Squeal.PostgreSQL.Type.Schema

-- $setup
-- >>> import Squeal.PostgreSQL

-- | >>> :{
-- let
--   expression :: Expr (null 'PGfloat4)
--   expression = atan2_ (pi *: 2)
-- in printSQL expression
-- :}
-- atan2(pi(), (2.0 :: float4))
atan2_ :: float `In` PGFloating => '[ null float, null float] ---> null float
atan2_ = unsafeFunctionN "atan2"


-- | integer division, truncates the result
--
-- >>> :{
-- let
--   expression :: Expression grp lat with db params from (null 'PGint2)
--   expression = 5 `quot_` 2
-- in printSQL expression
-- :}
-- ((5 :: int2) / (2 :: int2))
quot_
  :: int `In` PGIntegral
  => Operator (null int) (null int) (null int)
quot_ = unsafeBinaryOp "/"

-- | remainder upon integer division
--
-- >>> :{
-- let
--   expression :: Expression grp lat with db params from (null 'PGint2)
--   expression = 5 `rem_` 2
-- in printSQL expression
-- :}
-- ((5 :: int2) % (2 :: int2))
rem_
  :: int `In` PGIntegral
  => Operator (null int) (null int) (null int)
rem_ = unsafeBinaryOp "%"

-- | >>> :{
-- let
--   expression :: Expression grp lat with db params from (null 'PGfloat4)
--   expression = trunc pi
-- in printSQL expression
-- :}
-- trunc(pi())
trunc :: frac `In` PGFloating => null frac --> null frac
trunc = unsafeFunction "trunc"

-- | >>> :{
-- let
--   expression :: Expression grp lat with db params from (null 'PGfloat4)
--   expression = round_ pi
-- in printSQL expression
-- :}
-- round(pi())
round_ :: frac `In` PGFloating => null frac --> null frac
round_ = unsafeFunction "round"

-- | >>> :{
-- let
--   expression :: Expression grp lat with db params from (null 'PGfloat4)
--   expression = ceiling_ pi
-- in printSQL expression
-- :}
-- ceiling(pi())
ceiling_ :: frac `In` PGFloating => null frac --> null frac
ceiling_ = unsafeFunction "ceiling"