Skip to content

Instantly share code, notes, and snippets.

@leventov
Last active December 10, 2015 18:48
Show Gist options
  • Save leventov/4476908 to your computer and use it in GitHub Desktop.
Save leventov/4476908 to your computer and use it in GitHub Desktop.
-- minmax.h
float max_ss(float a, float b);
float min_ss(float a, float b);
double max_sd(double a, double b);
double min_sd(double a, double b);
float clamp_ss(float x, float mn, float mx);
double clamp_sd(double x, double mn, double mx);
-- minmax.c
#include "minmax.h"
#include <xmmintrin.h>
#include <emmintrin.h>
inline float max_ss(float a, float b) {
_mm_store_ss(&a, _mm_max_ss(_mm_set_ss(a), _mm_set_ss(b)));
return a;
}
inline float min_ss(float a, float b) {
_mm_store_ss(&a, _mm_min_ss(_mm_set_ss(a), _mm_set_ss(b)));
return a;
}
inline double max_sd(double a, double b) {
_mm_store_sd(&a, _mm_max_sd(_mm_set_sd(a), _mm_set_sd(b)));
return a;
}
inline double min_sd(double a, double b) {
_mm_store_sd(&a, _mm_min_sd(_mm_set_sd(a), _mm_set_sd(b)));
return a;
}
inline float clamp_ss(float x, float mn, float mx) {
_mm_store_ss(&x, _mm_min_ss(_mm_max_ss(_mm_set_ss(x),
_mm_set_ss(mn)), _mm_set_ss(mx)));
return x;
}
inline double clamp_sd(double x, double mn, double mx) {
_mm_store_sd(&x, _mm_min_sd(_mm_max_sd(_mm_set_sd(x),
_mm_set_sd(mn)), _mm_set_sd(mx)));
return x;
}
-- MinMax.hs
{-# LANGUAGE ForeignFunctionInterface, CPP #-}
module MinMax (
max_ss, min_ss,
max_sd, min_sd,
clamp_ss, clamp_sd
) where
import Foreign
import Foreign.C.Types
#define FFI_MM(name,cname,ty) \
foreign import ccall unsafe "minmax.c name" cname :: ty -> ty -> ty ;\
name :: RealFloat a => a -> a -> a ;\
name a b = realToFrac $ cname (realToFrac a) (realToFrac b) ;\
{-# INLINE cname #-} ;\
{-# INLINE name #-}
FFI_MM(max_ss,c_max_ss,CFloat)
FFI_MM(min_ss,c_min_ss,CFloat)
FFI_MM(max_sd,c_max_sd,CDouble)
FFI_MM(min_sd,c_min_sd,CDouble)
#define FFI_CLAMP(name,cname,ty) \
foreign import ccall unsafe "minmax.c name" cname :: ty -> ty -> ty -> ty ;\
name :: RealFloat a => a -> a -> a -> a ;\
name mn mx x = realToFrac $ \
cname (realToFrac x) (realToFrac mn) (realToFrac mx) ;\
{-# INLINE cname #-} ;\
{-# INLINE name #-}
FFI_CLAMP(clamp_ss,c_clamp_ss,CFloat)
FFI_CLAMP(clamp_sd,c_clamp_sd,CFloat)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment