{-# LANGUAGE ForeignFunctionInterface #-} module Dist (dist_slow, dist_slow', dist_fast, dist_fast_inlined, c_dist) where import Data.Array.Vector (UArr, toU, sumU, zipWithU) import Data.Foldable (foldl') import Foreign import Foreign.C.Types -- Euclidean distance between two n-dimensional points -- slow implementation using lists of Doubles dist_slow :: [Double] -> [Double] -> Double dist_slow p1 p2 = (sqrt . sum) ds where ds = zipWith euclidean p1 p2 euclidean x y = d*d where d = x-y -- Euclidean distance between two n-dimensional points -- same as dist_slow, but with strict sum dist_slow' :: [Double] -> [Double] -> Double dist_slow' p1 p2 = (sqrt . foldl' (+) 0.0) ds where ds = zipWith euclidean p1 p2 euclidean x y = d*d where d = x-y -- Euclidean distance between two n-dimensional points -- fast implementation using uvector package and streaming dist_fast :: UArr Double -> UArr Double -> Double dist_fast p1 p2 = sumDs `seq` sqrt sumDs where sumDs = sumU ds ds = zipWithU euclidean p1 p2 euclidean x y = d*d where d = x-y dist_fast_inlined :: UArr Double -> UArr Double -> Double {-# INLINE dist_fast_inlined #-} dist_fast_inlined p1 p2 = sumDs `seq` sqrt sumDs where sumDs = sumU ds ds = zipWithU euclidean p1 p2 euclidean x y = d*d where d = x-y foreign import ccall unsafe "dist" c_dist :: CInt -> Ptr CDouble -> Ptr CDouble -> CDouble