module Bench.Vector.Algo.Spectral ( spectral ) where

import Data.Vector.Unboxed as V

import Data.Bits

spectral :: Vector Double -> Vector Double
{-# NOINLINE spectral #-}
spectral :: Vector Double -> Vector Double
spectral Vector Double
us = Vector Double
us Vector Double -> Vector Double -> Vector Double
forall a b. a -> b -> b
`seq` (Int -> Double) -> Vector Int -> Vector Double
forall a b. (Unbox a, Unbox b) => (a -> b) -> Vector a -> Vector b
V.map Int -> Double
row (Int -> Int -> Vector Int
forall a. (Unbox a, Enum a) => a -> a -> Vector a
V.enumFromTo Int
0 (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1))
    where
      n :: Int
n = Vector Double -> Int
forall a. Unbox a => Vector a -> Int
V.length Vector Double
us

      row :: Int -> Double
row Int
i = Int
i Int -> Double -> Double
forall a b. a -> b -> b
`seq` Vector Double -> Double
forall a. (Unbox a, Num a) => Vector a -> a
V.sum ((Int -> Double -> Double) -> Vector Double -> Vector Double
forall a b.
(Unbox a, Unbox b) =>
(Int -> a -> b) -> Vector a -> Vector b
V.imap (\Int
j Double
u -> Int -> Int -> Double
forall {a} {a}. (Fractional a, Integral a, Bits a) => a -> a -> a
eval_A Int
i Int
j Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
u) Vector Double
us)

      eval_A :: a -> a -> a
eval_A a
i a
j = a
1 a -> a -> a
forall a. Fractional a => a -> a -> a
/ a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
r
        where
          r :: a
r = a
u a -> a -> a
forall a. Num a => a -> a -> a
+ (a
ia -> a -> a
forall a. Num a => a -> a -> a
+a
1)
          u :: a
u = a
t a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftR` Int
1
          t :: a
t = a
n a -> a -> a
forall a. Num a => a -> a -> a
* (a
na -> a -> a
forall a. Num a => a -> a -> a
+a
1)
          n :: a
n = a
ia -> a -> a
forall a. Num a => a -> a -> a
+a
j