{-# LANGUAGE DataKinds            #-}
{-# LANGUAGE FlexibleInstances    #-}
{-# LANGUAGE TypeApplications     #-}
{-# LANGUAGE ScopedTypeVariables  #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
--------------------------------------------------------------------------------
-- |
-- Module      : ArrayFire.Orphans
-- Copyright   : David Johnson (c) 2019-2020
-- License     : BSD 3
-- Maintainer  : David Johnson <djohnson.m@gmail.com>
-- Stability   : Experimental
-- Portability : GHC
--
--------------------------------------------------------------------------------
module ArrayFire.Orphans where

import           Prelude

import qualified ArrayFire.Arith     as A
import qualified ArrayFire.Array     as A
import qualified ArrayFire.Algorithm as A
import qualified ArrayFire.Data      as A
import           ArrayFire.Types
import           ArrayFire.Util

instance (AFType a, Eq a) => Eq (Array a) where
  Array a
x == :: Array a -> Array a -> Bool
== Array a
y = Array CBool -> (Double, Double)
forall a. AFType a => Array a -> (Double, Double)
A.allTrueAll (Array a -> Array a -> Bool -> Array CBool
forall a. AFType a => Array a -> Array a -> Bool -> Array CBool
A.eqBatched Array a
x Array a
y Bool
False) (Double, Double) -> (Double, Double) -> Bool
forall a. Eq a => a -> a -> Bool
== (Double
1.0,Double
0.0)
  Array a
x /= :: Array a -> Array a -> Bool
/= Array a
y = Array CBool -> (Double, Double)
forall a. AFType a => Array a -> (Double, Double)
A.allTrueAll (Array a -> Array a -> Bool -> Array CBool
forall a. AFType a => Array a -> Array a -> Bool -> Array CBool
A.neqBatched Array a
x Array a
y Bool
False) (Double, Double) -> (Double, Double) -> Bool
forall a. Eq a => a -> a -> Bool
== (Double
0.0,Double
0.0)

instance (Num a, AFType a) => Num (Array a) where
  Array a
x + :: Array a -> Array a -> Array a
+ Array a
y       = Array a -> Array a -> Array a
forall a. AFType a => Array a -> Array a -> Array a
A.add Array a
x Array a
y
  Array a
x * :: Array a -> Array a -> Array a
* Array a
y       = Array a -> Array a -> Array a
forall a. AFType a => Array a -> Array a -> Array a
A.mul Array a
x Array a
y
  abs :: Array a -> Array a
abs         = Array a -> Array a
forall a. AFType a => Array a -> Array a
A.abs
  signum :: Array a -> Array a
signum      = Array a -> Array a
forall a. AFType a => Array a -> Array a
A.sign
  negate :: Array a -> Array a
negate Array a
arr  = do
    let (Int
w,Int
x,Int
y,Int
z) = Array a -> (Int, Int, Int, Int)
forall a. AFType a => Array a -> (Int, Int, Int, Int)
A.getDims Array a
arr
    Array a -> Array a
forall a b. (AFType a, AFType b) => Array a -> Array b
A.cast (forall a. AFType a => [Int] -> a -> Array a
A.constant @a [Int
w,Int
x,Int
y,Int
z] a
0) Array a -> Array a -> Array a
forall a. AFType a => Array a -> Array a -> Array a
`A.sub` Array a
arr
  Array a
x - :: Array a -> Array a -> Array a
- Array a
y       = Array a -> Array a -> Array a
forall a. AFType a => Array a -> Array a -> Array a
A.sub Array a
x Array a
y
  fromInteger :: Integer -> Array a
fromInteger = a -> Array a
forall a. AFType a => a -> Array a
A.scalar (a -> Array a) -> (Integer -> a) -> Integer -> Array a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral

instance Show (Array a) where
  show :: Array a -> String
show = Array a -> String
forall a. Array a -> String
arrayString

instance forall a . (Fractional a, AFType a) => Fractional (Array a) where
  Array a
x / :: Array a -> Array a -> Array a
/ Array a
y  = Array a -> Array a -> Array a
forall a. AFType a => Array a -> Array a -> Array a
A.div Array a
x Array a
y
  fromRational :: Rational -> Array a
fromRational Rational
n = forall a. AFType a => a -> Array a
A.scalar @a (Rational -> a
forall a. Fractional a => Rational -> a
fromRational Rational
n)

instance forall a . (Ord a, AFType a, Fractional a) => Floating (Array a) where
  pi :: Array a
pi   = forall a. AFType a => a -> Array a
A.scalar @a a
3.14159
  exp :: Array a -> Array a
exp  = forall a. AFType a => Array a -> Array a
A.exp @a
  log :: Array a -> Array a
log  = forall a. AFType a => Array a -> Array a
A.log @a
  sin :: Array a -> Array a
sin  = forall a. AFType a => Array a -> Array a
A.sin @a
  cos :: Array a -> Array a
cos  = forall a. AFType a => Array a -> Array a
A.cos @a
  asin :: Array a -> Array a
asin = forall a. AFType a => Array a -> Array a
A.asin @a
  acos :: Array a -> Array a
acos = forall a. AFType a => Array a -> Array a
A.acos @a
  atan :: Array a -> Array a
atan = forall a. AFType a => Array a -> Array a
A.atan @a
  sinh :: Array a -> Array a
sinh = forall a. AFType a => Array a -> Array a
A.sinh @a
  cosh :: Array a -> Array a
cosh = forall a. AFType a => Array a -> Array a
A.cosh @a
  acosh :: Array a -> Array a
acosh = forall a. AFType a => Array a -> Array a
A.acosh @a
  atanh :: Array a -> Array a
atanh = forall a. AFType a => Array a -> Array a
A.atanh @a
  asinh :: Array a -> Array a
asinh = forall a. AFType a => Array a -> Array a
A.asinh @a