source/libtomo/gridrec/pal.h
// Platform Compatability Layer (PAL)
//
// Uses the preprocessor to swap implementations of key functions for different
// platforms without complicating the implementaiton of gridrec
#pragma once
// Complex types and functions ----------------------------------------------//
#ifdef __cplusplus
// For CXX use the standard library complex types
# include <complex>
typedef std::complex<float> PAL_COMPLEX;
# define conjf std::conj<float>
# define crealf std::real<float>
# define cimagf std::imag<float>
using namespace std::literals::complex_literals;
# define I 1if
#else
// For C use the complex header which is only present with some compilers
# include <complex.h>
typedef float _Complex PAL_COMPLEX;
# include <stdlib.h>
#endif
// Memory allocation and alignment ------------------------------------------//
// Use X/Open-7, where posix_memalign is introduced
#define _XOPEN_SOURCE 700
#define __LIKELY(x) __builtin_expect(!!(x), 1)
#if defined(_MSC_VER)
# if defined(__LIKELY)
# undef __LIKELY
# endif
# define __LIKELY(EXPR) EXPR
#endif
#ifdef __INTEL_COMPILER
# define __PRAGMA_SIMD _Pragma("simd assert")
# define __PRAGMA_SIMD_VECREMAINDER _Pragma("simd assert, vecremainder")
# define __PRAGMA_SIMD_VECREMAINDER_VECLEN8 \
_Pragma("simd assert, vecremainder, vectorlength(8)")
# define __PRAGMA_OMP_SIMD_COLLAPSE _Pragma("omp simd collapse(2)")
# define __PRAGMA_IVDEP _Pragma("ivdep")
# define __ASSSUME_64BYTES_ALIGNED(x) __assume_aligned((x), 64)
#else
# define __PRAGMA_SIMD
# define __PRAGMA_SIMD_VECREMAINDER
# define __PRAGMA_SIMD_VECREMAINDER_VECLEN8
# define __PRAGMA_OMP_SIMD_COLLAPSE
# define __PRAGMA_IVDEP
# define __ASSSUME_64BYTES_ALIGNED(x)
#endif
//===========================================================================//
inline float*
malloc_vector_f(size_t n)
{
#ifdef __cplusplus
return new float[n];
#else
return (float*) malloc(n * sizeof(float));
#endif
}
inline void
free_vector_f(float* v)
{
#ifdef __cplusplus
delete[] v;
v = nullptr;
#else
free(v);
#endif
}
//===========================================================================//
inline PAL_COMPLEX*
malloc_vector_c(size_t n)
{
#ifdef __cplusplus
return new PAL_COMPLEX[n];
#else
return (PAL_COMPLEX*) malloc(n * sizeof(PAL_COMPLEX));
#endif
}
#ifdef __cplusplus
inline void
free_vector_c(PAL_COMPLEX*& v)
{
delete[] v;
v = nullptr;
}
#else
inline void
free_vector_c(PAL_COMPLEX* v)
{
free(v);
}
#endif
//===========================================================================//
static inline void*
malloc_64bytes_aligned(size_t sz)
{
#if defined(__MINGW32__)
return __mingw_aligned_malloc(sz, 64);
#elif defined(_MSC_VER)
void* r = _aligned_malloc(sz, 64);
return r;
#else
void* r = NULL;
int err = posix_memalign(&r, 64, sz);
return (err) ? NULL : r;
#endif
}
//===========================================================================//
PAL_COMPLEX**
malloc_matrix_c(size_t nr, size_t nc)
{
#ifdef __cplusplus
PAL_COMPLEX** m = nullptr;
#else
PAL_COMPLEX** m = NULL;
#endif
size_t i;
// Allocate pointers to rows,
m = (PAL_COMPLEX**) malloc_64bytes_aligned(nr * sizeof(PAL_COMPLEX*));
/* Allocate rows and set the pointers to them */
m[0] = malloc_vector_c(nr * nc);
for(i = 1; i < nr; i++)
{
m[i] = m[i - 1] + nc;
}
return m;
}
//===========================================================================//
#ifdef __cplusplus
void
free_matrix_c(PAL_COMPLEX**& m)
{
free_vector_c(m[0]);
# if defined(__MINGW32__)
__mingw_aligned_free(m);
# elif defined(_MSC_VER)
_aligned_free(m);
# else
free(m);
# endif
m = nullptr;
}
#else
inline void
free_matrix_c(PAL_COMPLEX** m)
{
free_vector_c(m[0]);
# ifdef __MINGW32__
__mingw_aligned_free(m);
# else
free(m);
# endif
}
#endif