module SDR.Util (
Mult,
mult,
makeComplexBufferVect,
convertC,
convertCSSE,
convertCAVX,
convertFast,
scaleC,
scaleCSSE,
scaleCAVX,
scaleFast,
cplxMap,
quarterBandUp
) where
import Foreign.C.Types
import Data.Complex
import Data.Vector.Generic as VG hiding ((++))
import qualified Data.Vector.Generic.Mutable as VGM
import Data.Vector.Storable as VS hiding ((++))
import Data.Vector.Storable.Mutable as VSM
import Control.Monad.Primitive
import Unsafe.Coerce
import Foreign.Ptr
import System.IO.Unsafe
import Foreign.Storable.Complex
import SDR.CPUID
class Mult a b where
mult :: a -> b -> a
instance (Num a) => Mult a a where
mult = (*)
instance (Num a) => Mult (Complex a) a where
mult (x :+ y) z = (x * z) :+ (y * z)
makeComplexBufferVect :: (Num a, Integral a, Num b, Fractional b, VG.Vector v1 a, VG.Vector v2 (Complex b)) => v1 a -> v2 (Complex b)
makeComplexBufferVect input = VG.generate (VG.length input `quot` 2) convert
where
convert idx = convert' (input `VG.unsafeIndex` (2 * idx)) :+ convert' (input `VG.unsafeIndex` (2 * idx + 1))
convert' val = (fromIntegral val 128) / 128
foreign import ccall unsafe "convertC"
convertC_c :: CInt -> Ptr CUChar -> Ptr CFloat -> IO ()
convertC :: VS.Vector CUChar -> VS.Vector (Complex Float)
convertC inBuf = unsafePerformIO $ do
outBuf <- VGM.new $ VG.length inBuf `quot` 2
VS.unsafeWith inBuf $ \iPtr ->
VSM.unsafeWith (unsafeCoerce outBuf) $ \oPtr ->
convertC_c (fromIntegral $ VG.length inBuf) iPtr oPtr
VG.freeze outBuf
foreign import ccall unsafe "convertCSSE"
convertCSSE_c :: CInt -> Ptr CUChar -> Ptr CFloat -> IO ()
convertCSSE :: VS.Vector CUChar -> VS.Vector (Complex Float)
convertCSSE inBuf = unsafePerformIO $ do
outBuf <- VGM.new $ VG.length inBuf `quot` 2
VS.unsafeWith inBuf $ \iPtr ->
VSM.unsafeWith (unsafeCoerce outBuf) $ \oPtr ->
convertCSSE_c (fromIntegral $ VG.length inBuf) iPtr oPtr
VG.freeze outBuf
foreign import ccall unsafe "convertCAVX"
convertCAVX_c :: CInt -> Ptr CUChar -> Ptr CFloat -> IO ()
convertCAVX :: VS.Vector CUChar -> VS.Vector (Complex Float)
convertCAVX inBuf = unsafePerformIO $ do
outBuf <- VGM.new $ VG.length inBuf `quot` 2
VS.unsafeWith inBuf $ \iPtr ->
VSM.unsafeWith (unsafeCoerce outBuf) $ \oPtr ->
convertCAVX_c (fromIntegral $ VG.length inBuf) iPtr oPtr
VG.freeze outBuf
convertFast :: CPUInfo -> VS.Vector CUChar -> VS.Vector (Complex Float)
convertFast info = featureSelect info convertC [(hasAVX2, convertCAVX), (hasSSE42, convertCSSE)]
foreign import ccall unsafe "scale"
scale_c :: CInt -> CFloat -> Ptr CFloat -> Ptr CFloat -> IO ()
scaleC :: Float
-> VS.Vector Float
-> VS.MVector RealWorld Float
-> IO ()
scaleC factor inBuf outBuf =
VS.unsafeWith (unsafeCoerce inBuf) $ \iPtr ->
VS.unsafeWith (unsafeCoerce outBuf) $ \oPtr ->
scale_c (fromIntegral (VG.length inBuf)) (unsafeCoerce factor) iPtr oPtr
foreign import ccall unsafe "scaleSSE"
scaleSSE_c :: CInt -> CFloat -> Ptr CFloat -> Ptr CFloat-> IO ()
scaleCSSE :: Float
-> VS.Vector Float
-> VS.MVector RealWorld Float
-> IO ()
scaleCSSE factor inBuf outBuf =
VS.unsafeWith (unsafeCoerce inBuf) $ \iPtr ->
VS.unsafeWith (unsafeCoerce outBuf) $ \oPtr ->
scaleSSE_c (fromIntegral (VG.length inBuf)) (unsafeCoerce factor) iPtr oPtr
foreign import ccall unsafe "scaleAVX"
scaleAVX_c :: CInt -> CFloat -> Ptr CFloat -> Ptr CFloat -> IO ()
scaleCAVX :: Float
-> VS.Vector Float
-> VS.MVector RealWorld Float
-> IO ()
scaleCAVX factor inBuf outBuf =
VS.unsafeWith (unsafeCoerce inBuf) $ \iPtr ->
VS.unsafeWith (unsafeCoerce outBuf) $ \oPtr ->
scaleAVX_c (fromIntegral (VG.length inBuf)) (unsafeCoerce factor) iPtr oPtr
scaleFast :: CPUInfo -> Float -> VS.Vector Float -> VS.MVector RealWorld Float -> IO ()
scaleFast info = featureSelect info scaleC [(hasAVX, scaleCAVX), (hasSSE42, scaleCSSE)]
cplxMap :: (a -> b)
-> Complex a
-> Complex b
cplxMap f (x :+ y) = f x :+ f y
quarterBandUp :: (VG.Vector v (Complex n), Num n)
=> Int
-> v (Complex n)
quarterBandUp size = VG.generate size func
where
func idx
| m == 0 = 1 :+ 0
| m == 1 = 0 :+ 1
| m == 2 = (1) :+ 0
| m == 3 = 0 :+ (1)
where
m = idx `mod` 4