added support for native and double precision trigonometry/transendentals

This commit is contained in:
Evghenii
2014-02-07 15:28:39 +01:00
parent 81aa19a8f0
commit 70a9b286e5
18 changed files with 340 additions and 108 deletions

View File

@@ -691,39 +691,6 @@ SHIFT(__vec16_f, float, float)
SHUFFLES(__vec16_f, float, float)
LOAD_STORE(__vec16_f, float)
static FORCEINLINE float __exp_uniform_float(float v) {
return expf(v);
}
static FORCEINLINE __vec16_f __exp_varying_float(__vec16_f v) {
__vec16_f ret;
for (int i = 0; i < 16; ++i)
ret.v[i] = expf(v.v[i]);
return ret;
}
static FORCEINLINE float __log_uniform_float(float v) {
return logf(v);
}
static FORCEINLINE __vec16_f __log_varying_float(__vec16_f v) {
__vec16_f ret;
for (int i = 0; i < 16; ++i)
ret.v[i] = logf(v.v[i]);
return ret;
}
static FORCEINLINE float __pow_uniform_float(float a, float b) {
return powf(a, b);
}
static FORCEINLINE __vec16_f __pow_varying_float(__vec16_f a, __vec16_f b) {
__vec16_f ret;
for (int i = 0; i < 16; ++i)
ret.v[i] = powf(a.v[i], b.v[i]);
return ret;
}
static FORCEINLINE int __intbits(float v) {
union {
float f;
@@ -1813,3 +1780,97 @@ static FORCEINLINE uint64_t __clock() {
#endif // !WIN32
///////////////////////////////////////////////////////////////////////////
// Transcendentals
//
//
#define TRANSCENDENTALS(op) \
static FORCEINLINE float __##op##_uniform_float(float v) { \
return op##f(v); \
} \
static FORCEINLINE __vec16_f __##op##_varying_float(__vec16_f v) { \
__vec16_f ret; \
for (int i = 0; i < 16; ++i) \
ret.v[i] = op##f(v.v[i]); \
return ret; \
} \
static FORCEINLINE double __##op##_uniform_double(double v) { \
return op(v); \
} \
static FORCEINLINE __vec16_d __##op##_varying_double(__vec16_d v) { \
__vec16_d ret; \
for (int i = 0; i < 16; ++i) \
ret.v[i] = op(v.v[i]); \
return ret; \
}
TRANSCENDENTALS(log)
TRANSCENDENTALS(exp)
static FORCEINLINE float __pow_uniform_float(float a, float b) {
return powf(a, b);
}
static FORCEINLINE __vec16_f __pow_varying_float(__vec16_f a, __vec16_f b) {
__vec16_f ret;
for (int i = 0; i < 16; ++i)
ret.v[i] = powf(a.v[i], b.v[i]);
return ret;
}
static FORCEINLINE double __pow_uniform_double(double a, double b) {
return pow(a, b);
}
static FORCEINLINE __vec16_d __pow_varying_double(__vec16_d a, __vec16_d b) {
__vec16_d ret;
for (int i = 0; i < 16; ++i)
ret.v[i] = pow(a.v[i], b.v[i]);
return ret;
}
///////////////////////////////////////////////////////////////////////////
// Trigonometry
TRANSCENDENTALS(sin)
TRANSCENDENTALS(asin)
TRANSCENDENTALS(cos)
TRANSCENDENTALS(acos)
TRANSCENDENTALS(tan)
TRANSCENDENTALS(atan)
static FORCEINLINE float __atan2_uniform_float(float a, float b) {
return atan2f(a, b);
}
static FORCEINLINE __vec16_f __atan2_varying_float(__vec16_f a, __vec16_f b) {
__vec16_f ret;
for (int i = 0; i < 16; ++i)
ret.v[i] = atan2f(a.v[i], b.v[i]);
return ret;
}
static FORCEINLINE double __atan2_uniform_double(double a, double b) {
return atan2(a, b);
}
static FORCEINLINE __vec16_d __atan2_varying_double(__vec16_d a, __vec16_d b) {
__vec16_d ret;
for (int i = 0; i < 16; ++i)
ret.v[i] = atan2(a.v[i], b.v[i]);
return ret;
}
static FORCEINLINE void __sincos_uniform_float(float x, float *a, float *b) {
sincosf(x,a,b);
}
static FORCEINLINE void __sincos_varying_float(__vec16_f x, __vec16_f *a, __vec16_f *b) {
__vec16_f ret;
for (int i = 0; i < 16; ++i)
sincosf(x.v[i], (float*)a + i, (float*)b+i);
}
static FORCEINLINE void __sincos_uniform_double(double x, double *a, double *b) {
sincos(x,a,b);
}
static FORCEINLINE void __sincos_varying_double(__vec16_d x, __vec16_d *a, __vec16_d *b) {
__vec16_d ret;
for (int i = 0; i < 16; ++i)
sincos(x.v[i], (double*)a + i, (double*)b+i);
}

View File

@@ -167,6 +167,10 @@ struct __vec4_d {
}
__m128d v[2];
FORCEINLINE __vec4_d(double *p) {
v[0] = _mm_set_pd(p[1], p[0]);
v[1] = _mm_set_pd(p[3], p[2]);
}
};
@@ -2471,39 +2475,6 @@ static FORCEINLINE __vec4_d __sqrt_varying_double(__vec4_d v) {
return __vec4_d(_mm_sqrt_pd(v.v[0]), _mm_sqrt_pd(v.v[1]));
}
static FORCEINLINE __vec4_f __pow_varying_float(__vec4_f a, __vec4_f b) {
float r[4];
for (int i = 0; i < 4; ++i)
r[i] = powf(__extract_element(a, i), __extract_element(b, i));
return __vec4_f(r);
}
static FORCEINLINE float __pow_uniform_float(float a, float b) {
return powf(a, b);
}
static FORCEINLINE __vec4_f __exp_varying_float(__vec4_f a) {
float r[4];
for (int i = 0; i < 4; ++i)
r[i] = expf(__extract_element(a, i));
return __vec4_f(r);
}
static FORCEINLINE float __exp_uniform_float(float a) {
return expf(a);
}
static FORCEINLINE __vec4_f __log_varying_float(__vec4_f a) {
float r[4];
for (int i = 0; i < 4; ++i)
r[i] = logf(__extract_element(a, i));
return __vec4_f(r);
}
static FORCEINLINE float __log_uniform_float(float a) {
return logf(a);
}
static FORCEINLINE int __intbits(float v) {
union {
float f;
@@ -4166,4 +4137,97 @@ static FORCEINLINE uint64_t __clock() {
}
#endif // !WIN32
///////////////////////////////////////////////////////////////////////////
// Transcendentals
#define TRANSCENDENTALS(op) \
static FORCEINLINE __vec4_f __##op##_varying_float(__vec4_f a) {\
float r[4];\
for (int i = 0; i < 4; ++i)\
r[i] = op##f(__extract_element(a, i));\
return __vec4_f(r);\
}\
static FORCEINLINE float __##op##_uniform_float(float a) {\
return op##f(a);\
}\
static FORCEINLINE __vec4_d __##op##_varying_double(__vec4_d a) {\
double r[4];\
for (int i = 0; i < 4; ++i)\
r[i] = op(__extract_element(a, i));\
return __vec4_d(r);\
}\
static FORCEINLINE double __##op##_uniform_double(double a) {\
return op(a);\
}
TRANSCENDENTALS(log)
TRANSCENDENTALS(exp)
static FORCEINLINE __vec4_f __pow_varying_float(__vec4_f a, __vec4_f b) {
float r[4];
for (int i = 0; i < 4; ++i)
r[i] = powf(__extract_element(a, i), __extract_element(b, i));
return __vec4_f(r);
}
static FORCEINLINE float __pow_uniform_float(float a, float b) {
return powf(a, b);
}
static FORCEINLINE __vec4_d __pow_varying_double(__vec4_d a, __vec4_d b) {
double r[4];
for (int i = 0; i < 4; ++i)
r[i] = pow(__extract_element(a, i), __extract_element(b, i));
return __vec4_d(r);
}
static FORCEINLINE double __pow_uniform_double(double a, double b) {
return pow(a, b);
}
///////////////////////////////////////////////////////////////////////////
// Trigonometry
TRANSCENDENTALS(sin)
TRANSCENDENTALS(asin)
TRANSCENDENTALS(cos)
TRANSCENDENTALS(acos)
TRANSCENDENTALS(tan)
TRANSCENDENTALS(atan)
static FORCEINLINE __vec4_f __atan2_varying_float(__vec4_f a, __vec4_f b) {
float r[4];
for (int i = 0; i < 4; ++i)
r[i] = atan2f(__extract_element(a, i), __extract_element(b, i));
return __vec4_f(r);
}
static FORCEINLINE float __atan2_uniform_float(float a, float b) {
return atan2f(a, b);
}
static FORCEINLINE __vec4_d __atan2_varying_double(__vec4_d a, __vec4_d b) {
double r[4];
for (int i = 0; i < 4; ++i)
r[i] = atan2(__extract_element(a, i), __extract_element(b, i));
return __vec4_d(r);
}
static FORCEINLINE double __atan2_uniform_double(double a, double b) {
return atan2(a, b);
}
static FORCEINLINE void __sincos_varying_float(__vec4_f x, __vec4_f * _sin, __vec4_f * _cos) {
for (int i = 0; i < 4; ++i)
sincosf(__extract_element(x, i), (float*)_sin + i, (float*)_cos + i);
}
static FORCEINLINE void __sincos_uniform_float(float x, float *_sin, float *_cos) {
sincosf(x, _sin, _cos);
}
static FORCEINLINE void __sincos_varying_double(__vec4_d x, __vec4_d * _sin, __vec4_d * _cos) {
for (int i = 0; i < 4; ++i)
sincos(__extract_element(x, i), (double*)_sin + i, (double*)_cos + i);
}
static FORCEINLINE void __sincos_uniform_double(double x, double *_sin, double *_cos) {
sincos(x, _sin, _cos);
}
#undef FORCEINLINE