mirror of
https://github.com/KhronosGroup/OpenCL-CTS.git
synced 2026-03-19 06:09:01 +00:00
The maintenance of the conformance tests is moving to Github. This commit contains all the changes that have been done in Gitlab since the first public release of the conformance tests. Signed-off-by: Kevin Petit <kevin.petit@arm.com>
775 lines
15 KiB
C
775 lines
15 KiB
C
//
|
|
// Copyright (c) 2017 The Khronos Group Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
#include "compat.h"
|
|
|
|
#if defined ( _MSC_VER )
|
|
|
|
#include <limits.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <CL/cl.h>
|
|
|
|
#include <windows.h>
|
|
|
|
#if ! defined( __INTEL_COMPILER )
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// rint, rintf
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
float copysignf( float x, float y )
|
|
{
|
|
union{ cl_uint u; float f; }ux, uy;
|
|
|
|
ux.f = x;
|
|
uy.f = y;
|
|
|
|
ux.u = (ux.u & 0x7fffffffU) | (uy.u & 0x80000000U);
|
|
|
|
return ux.f;
|
|
}
|
|
|
|
double copysign( double x, double y )
|
|
{
|
|
union{ cl_ulong u; double f; }ux, uy;
|
|
|
|
ux.f = x;
|
|
uy.f = y;
|
|
|
|
ux.u = (ux.u & 0x7fffffffffffffffULL) | (uy.u & 0x8000000000000000ULL);
|
|
|
|
return ux.f;
|
|
}
|
|
|
|
long double copysignl( long double x, long double y )
|
|
{
|
|
union
|
|
{
|
|
long double f;
|
|
struct{ cl_ulong m; cl_ushort sexp; }u;
|
|
}ux, uy;
|
|
|
|
ux.f = x;
|
|
uy.f = y;
|
|
|
|
ux.u.sexp = (ux.u.sexp & 0x7fff) | (uy.u.sexp & 0x8000);
|
|
|
|
return ux.f;
|
|
}
|
|
|
|
float rintf(float x)
|
|
{
|
|
float absx = fabsf(x);
|
|
|
|
if( absx < 8388608.0f /* 0x1.0p23f */ )
|
|
{
|
|
float magic = copysignf( 8388608.0f /* 0x1.0p23f */, x );
|
|
float rounded = x + magic;
|
|
rounded -= magic;
|
|
x = copysignf( rounded, x );
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
double rint(double x)
|
|
{
|
|
double absx = fabs(x);
|
|
|
|
if( absx < 4503599627370496.0 /* 0x1.0p52f */ )
|
|
{
|
|
double magic = copysign( 4503599627370496.0 /* 0x1.0p52 */, x );
|
|
double rounded = x + magic;
|
|
rounded -= magic;
|
|
x = copysign( rounded, x );
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
long double rintl(long double x)
|
|
{
|
|
double absx = fabs(x);
|
|
|
|
if( absx < 9223372036854775808.0L /* 0x1.0p64f */ )
|
|
{
|
|
long double magic = copysignl( 9223372036854775808.0L /* 0x1.0p63L */, x );
|
|
long double rounded = x + magic;
|
|
rounded -= magic;
|
|
x = copysignl( rounded, x );
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// ilogb, ilogbf, ilogbl
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
#ifndef FP_ILOGB0
|
|
#define FP_ILOGB0 INT_MIN
|
|
#endif
|
|
|
|
#ifndef FP_ILOGBNAN
|
|
#define FP_ILOGBNAN INT_MIN
|
|
#endif
|
|
|
|
int ilogb (double x)
|
|
{
|
|
union{ double f; cl_ulong u;} u;
|
|
u.f = x;
|
|
|
|
cl_ulong absx = u.u & CL_LONG_MAX;
|
|
if( absx - 0x0001000000000000ULL >= 0x7ff0000000000000ULL - 0x0001000000000000ULL)
|
|
{
|
|
switch( absx )
|
|
{
|
|
case 0:
|
|
return FP_ILOGB0;
|
|
case 0x7ff0000000000000ULL:
|
|
return INT_MAX;
|
|
default:
|
|
if( absx > 0x7ff0000000000000ULL )
|
|
return FP_ILOGBNAN;
|
|
|
|
// subnormal
|
|
u.u = absx | 0x3ff0000000000000ULL;
|
|
u.f -= 1.0;
|
|
return (u.u >> 52) - (1023 + 1022);
|
|
}
|
|
}
|
|
|
|
return (absx >> 52) - 1023;
|
|
}
|
|
|
|
|
|
int ilogbf (float x)
|
|
{
|
|
union{ float f; cl_uint u;} u;
|
|
u.f = x;
|
|
|
|
cl_uint absx = u.u & 0x7fffffff;
|
|
if( absx - 0x00800000U >= 0x7f800000U - 0x00800000U)
|
|
{
|
|
switch( absx )
|
|
{
|
|
case 0:
|
|
return FP_ILOGB0;
|
|
case 0x7f800000U:
|
|
return INT_MAX;
|
|
default:
|
|
if( absx > 0x7f800000 )
|
|
return FP_ILOGBNAN;
|
|
|
|
// subnormal
|
|
u.u = absx | 0x3f800000U;
|
|
u.f -= 1.0f;
|
|
return (u.u >> 23) - (127 + 126);
|
|
}
|
|
}
|
|
|
|
return (absx >> 23) - 127;
|
|
}
|
|
|
|
int ilogbl (long double x)
|
|
{
|
|
union
|
|
{
|
|
long double f;
|
|
struct{ cl_ulong m; cl_ushort sexp; }u;
|
|
} u;
|
|
u.f = x;
|
|
|
|
int exp = u.u.sexp & 0x7fff;
|
|
if( 0 == exp )
|
|
{
|
|
if( 0 == u.u.m )
|
|
return FP_ILOGB0;
|
|
|
|
//subnormal
|
|
u.u.sexp = 0x3fff;
|
|
u.f -= 1.0f;
|
|
exp = u.u.sexp & 0x7fff;
|
|
|
|
return exp - (0x3fff + 0x3ffe);
|
|
}
|
|
else if( 0x7fff == exp )
|
|
{
|
|
if( u.u.m & CL_LONG_MAX )
|
|
return FP_ILOGBNAN;
|
|
|
|
return INT_MAX;
|
|
}
|
|
|
|
return exp - 0x3fff;
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// fmax, fmin, fmaxf, fminf
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
static void GET_BITS_SP32(float fx, unsigned int* ux)
|
|
{
|
|
volatile union {float f; unsigned int u;} _bitsy;
|
|
_bitsy.f = (fx);
|
|
*ux = _bitsy.u;
|
|
}
|
|
/* static void GET_BITS_SP32(float fx, unsigned int* ux) */
|
|
/* { */
|
|
/* volatile union {float f; unsigned int i;} _bitsy; */
|
|
/* _bitsy.f = (fx); */
|
|
/* *ux = _bitsy.i; */
|
|
/* } */
|
|
static void PUT_BITS_SP32(unsigned int ux, float* fx)
|
|
{
|
|
volatile union {float f; unsigned int u;} _bitsy;
|
|
_bitsy.u = (ux);
|
|
*fx = _bitsy.f;
|
|
}
|
|
/* static void PUT_BITS_SP32(unsigned int ux, float* fx) */
|
|
/* { */
|
|
/* volatile union {float f; unsigned int i;} _bitsy; */
|
|
/* _bitsy.i = (ux); */
|
|
/* *fx = _bitsy.f; */
|
|
/* } */
|
|
static void GET_BITS_DP64(double dx, unsigned __int64* lx)
|
|
{
|
|
volatile union {double d; unsigned __int64 l;} _bitsy;
|
|
_bitsy.d = (dx);
|
|
*lx = _bitsy.l;
|
|
}
|
|
static void PUT_BITS_DP64(unsigned __int64 lx, double* dx)
|
|
{
|
|
volatile union {double d; unsigned __int64 l;} _bitsy;
|
|
_bitsy.l = (lx);
|
|
*dx = _bitsy.d;
|
|
}
|
|
|
|
#if 0
|
|
int SIGNBIT_DP64(double x )
|
|
{
|
|
int hx;
|
|
_GET_HIGH_WORD(hx,x);
|
|
return((hx>>31));
|
|
}
|
|
#endif
|
|
|
|
/* fmax(x, y) returns the larger (more positive) of x and y.
|
|
NaNs are treated as missing values: if one argument is NaN,
|
|
the other argument is returned. If both arguments are NaN,
|
|
the first argument is returned. */
|
|
|
|
/* This works so long as the compiler knows that (x != x) means
|
|
that x is NaN; gcc does. */
|
|
double fmax(double x, double y)
|
|
{
|
|
if( isnan(y) )
|
|
return x;
|
|
|
|
return x >= y ? x : y;
|
|
}
|
|
|
|
|
|
/* fmin(x, y) returns the smaller (more negative) of x and y.
|
|
NaNs are treated as missing values: if one argument is NaN,
|
|
the other argument is returned. If both arguments are NaN,
|
|
the first argument is returned. */
|
|
|
|
double fmin(double x, double y)
|
|
{
|
|
if( isnan(y) )
|
|
return x;
|
|
|
|
return x <= y ? x : y;
|
|
}
|
|
|
|
|
|
float fmaxf( float x, float y )
|
|
{
|
|
if( isnan(y) )
|
|
return x;
|
|
|
|
return x >= y ? x : y;
|
|
}
|
|
|
|
/* fminf(x, y) returns the smaller (more negative) of x and y.
|
|
NaNs are treated as missing values: if one argument is NaN,
|
|
the other argument is returned. If both arguments are NaN,
|
|
the first argument is returned. */
|
|
|
|
float fminf(float x, float y)
|
|
{
|
|
if( isnan(y) )
|
|
return x;
|
|
|
|
return x <= y ? x : y;
|
|
}
|
|
|
|
long double scalblnl(long double x, long n)
|
|
{
|
|
union
|
|
{
|
|
long double d;
|
|
struct{ cl_ulong m; cl_ushort sexp;}u;
|
|
}u;
|
|
u.u.m = CL_LONG_MIN;
|
|
|
|
if( x == 0.0L || n < -2200)
|
|
return copysignl( 0.0L, x );
|
|
|
|
if( n > 2200 )
|
|
return INFINITY;
|
|
|
|
if( n < 0 )
|
|
{
|
|
u.u.sexp = 0x3fff - 1022;
|
|
while( n <= -1022 )
|
|
{
|
|
x *= u.d;
|
|
n += 1022;
|
|
}
|
|
u.u.sexp = 0x3fff + n;
|
|
x *= u.d;
|
|
return x;
|
|
}
|
|
|
|
if( n > 0 )
|
|
{
|
|
u.u.sexp = 0x3fff + 1023;
|
|
while( n >= 1023 )
|
|
{
|
|
x *= u.d;
|
|
n -= 1023;
|
|
}
|
|
u.u.sexp = 0x3fff + n;
|
|
x *= u.d;
|
|
return x;
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// log2
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
const static cl_double log_e_base2 = 1.4426950408889634074;
|
|
const static cl_double log_10_base2 = 3.3219280948873623478;
|
|
|
|
//double log10(double x);
|
|
|
|
double log2(double x)
|
|
{
|
|
return 1.44269504088896340735992468100189214 * log(x);
|
|
}
|
|
|
|
long double log2l(long double x)
|
|
{
|
|
return 1.44269504088896340735992468100189214L * log(x);
|
|
}
|
|
|
|
double trunc(double x)
|
|
{
|
|
double absx = fabs(x);
|
|
|
|
if( absx < 4503599627370496.0 /* 0x1.0p52f */ )
|
|
{
|
|
cl_long rounded = x;
|
|
x = copysign( (double) rounded, x );
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
float truncf(float x)
|
|
{
|
|
float absx = fabsf(x);
|
|
|
|
if( absx < 8388608.0f /* 0x1.0p23f */ )
|
|
{
|
|
cl_int rounded = x;
|
|
x = copysignf( (float) rounded, x );
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
long lround(double x)
|
|
{
|
|
double absx = fabs(x);
|
|
|
|
if( absx < 0.5 )
|
|
return 0;
|
|
|
|
if( absx < 4503599627370496.0 /* 0x1.0p52 */)
|
|
{
|
|
absx += 0.5;
|
|
cl_long rounded = absx;
|
|
absx = rounded;
|
|
x = copysign( absx, x );
|
|
}
|
|
|
|
if( x >= (double) LONG_MAX )
|
|
return LONG_MAX;
|
|
|
|
return (long) x;
|
|
}
|
|
|
|
long lroundf(float x)
|
|
{
|
|
float absx = fabsf(x);
|
|
|
|
if( absx < 0.5f )
|
|
return 0;
|
|
|
|
if( absx < 8388608.0f )
|
|
{
|
|
absx += 0.5f;
|
|
cl_int rounded = absx;
|
|
absx = rounded;
|
|
x = copysignf( absx, x );
|
|
}
|
|
|
|
if( x >= (float) LONG_MAX )
|
|
return LONG_MAX;
|
|
|
|
return (long) x;
|
|
}
|
|
|
|
double round(double x)
|
|
{
|
|
double absx = fabs(x);
|
|
|
|
if( absx < 0.5 )
|
|
return copysign( 0.0, x);
|
|
|
|
if( absx < 4503599627370496.0 /* 0x1.0p52 */)
|
|
{
|
|
absx += 0.5;
|
|
cl_long rounded = absx;
|
|
absx = rounded;
|
|
x = copysign( absx, x );
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
float roundf(float x)
|
|
{
|
|
float absx = fabsf(x);
|
|
|
|
if( absx < 0.5f )
|
|
return copysignf( 0.0f, x);
|
|
|
|
if( absx < 8388608.0f )
|
|
{
|
|
absx += 0.5f;
|
|
cl_int rounded = absx;
|
|
absx = rounded;
|
|
x = copysignf( absx, x );
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
long double roundl(long double x)
|
|
{
|
|
long double absx = fabsl(x);
|
|
|
|
if( absx < 0.5L )
|
|
return copysignl( 0.0L, x);
|
|
|
|
if( absx < 9223372036854775808.0L /*0x1.0p63L*/ )
|
|
{
|
|
absx += 0.5L;
|
|
cl_ulong rounded = absx;
|
|
absx = rounded;
|
|
x = copysignl( absx, x );
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
float cbrtf( float x )
|
|
{
|
|
float z = pow( fabs((double) x), 1.0 / 3.0 );
|
|
return copysignf( z, x );
|
|
}
|
|
|
|
double cbrt( double x )
|
|
{
|
|
return copysign( pow( fabs( x ), 1.0 / 3.0 ), x );
|
|
}
|
|
|
|
long int lrint (double x)
|
|
{
|
|
double absx = fabs(x);
|
|
|
|
if( x >= (double) LONG_MAX )
|
|
return LONG_MAX;
|
|
|
|
if( absx < 4503599627370496.0 /* 0x1.0p52 */ )
|
|
{
|
|
double magic = copysign( 4503599627370496.0 /* 0x1.0p52 */, x );
|
|
double rounded = x + magic;
|
|
rounded -= magic;
|
|
return (long int) rounded;
|
|
}
|
|
|
|
return (long int) x;
|
|
}
|
|
|
|
long int lrintf (float x)
|
|
{
|
|
float absx = fabsf(x);
|
|
|
|
if( x >= (float) LONG_MAX )
|
|
return LONG_MAX;
|
|
|
|
if( absx < 8388608.0f /* 0x1.0p23f */ )
|
|
{
|
|
float magic = copysignf( 8388608.0f /* 0x1.0p23f */, x );
|
|
float rounded = x + magic;
|
|
rounded -= magic;
|
|
return (long int) rounded;
|
|
}
|
|
|
|
return (long int) x;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// fenv functions
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
#if _MSC_VER < 1900
|
|
int fetestexcept(int excepts)
|
|
{
|
|
unsigned int status = _statusfp();
|
|
return excepts & (
|
|
((status & _SW_INEXACT) ? FE_INEXACT : 0) |
|
|
((status & _SW_UNDERFLOW) ? FE_UNDERFLOW : 0) |
|
|
((status & _SW_OVERFLOW) ? FE_OVERFLOW : 0) |
|
|
((status & _SW_ZERODIVIDE) ? FE_DIVBYZERO : 0) |
|
|
((status & _SW_INVALID) ? FE_INVALID : 0)
|
|
);
|
|
}
|
|
|
|
int feclearexcept(int excepts)
|
|
{
|
|
_clearfp();
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#endif // __INTEL_COMPILER
|
|
|
|
#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER < 1300)
|
|
|
|
float make_nan()
|
|
{
|
|
/* This is the IEEE 754 single-precision format:
|
|
unsigned int mantissa: 22;
|
|
unsigned int quiet_nan: 1;
|
|
unsigned int exponent: 8;
|
|
unsigned int negative: 1;
|
|
*/
|
|
//const static unsigned
|
|
static const int32_t _nan = 0x7fc00000;
|
|
return *(const float*)(&_nan);
|
|
}
|
|
|
|
float nanf( const char* str)
|
|
{
|
|
cl_uint u = atoi( str );
|
|
u |= 0x7fc00000U;
|
|
return *( float*)(&u);
|
|
}
|
|
|
|
|
|
double nan( const char* str)
|
|
{
|
|
cl_ulong u = atoi( str );
|
|
u |= 0x7ff8000000000000ULL;
|
|
return *( double*)(&u);
|
|
}
|
|
|
|
// double check this implementatation
|
|
long double nanl( const char* str)
|
|
{
|
|
union
|
|
{
|
|
long double f;
|
|
struct { cl_ulong m; cl_ushort sexp; }u;
|
|
}u;
|
|
u.u.sexp = 0x7fff;
|
|
u.u.m = 0x8000000000000000ULL | atoi( str );
|
|
|
|
return u.f;
|
|
}
|
|
|
|
#endif
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// misc functions
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
/*
|
|
// This function is commented out because the Windows implementation should never call munmap.
|
|
// If it is calling it, we have a bug. Please file a bugzilla.
|
|
int munmap(void *addr, size_t len)
|
|
{
|
|
// FIXME: this is not correct. munmap is like free() http://www.opengroup.org/onlinepubs/7990989775/xsh/munmap.html
|
|
|
|
return (int)VirtualAlloc( (LPVOID)addr, len,
|
|
MEM_COMMIT|MEM_RESERVE, PAGE_NOACCESS );
|
|
}
|
|
*/
|
|
|
|
uint64_t ReadTime( void )
|
|
{
|
|
LARGE_INTEGER current;
|
|
QueryPerformanceCounter(¤t);
|
|
return (uint64_t)current.QuadPart;
|
|
}
|
|
|
|
double SubtractTime( uint64_t endTime, uint64_t startTime )
|
|
{
|
|
static double PerformanceFrequency = 0.0;
|
|
|
|
if (PerformanceFrequency == 0.0) {
|
|
LARGE_INTEGER frequency;
|
|
QueryPerformanceFrequency(&frequency);
|
|
PerformanceFrequency = (double) frequency.QuadPart;
|
|
}
|
|
|
|
return (double)(endTime - startTime) / PerformanceFrequency * 1e9;
|
|
}
|
|
|
|
int cf_signbit(double x)
|
|
{
|
|
union
|
|
{
|
|
double f;
|
|
cl_ulong u;
|
|
}u;
|
|
u.f = x;
|
|
return u.u >> 63;
|
|
}
|
|
|
|
int cf_signbitf(float x)
|
|
{
|
|
union
|
|
{
|
|
float f;
|
|
cl_uint u;
|
|
}u;
|
|
u.f = x;
|
|
return u.u >> 31;
|
|
}
|
|
|
|
float int2float (int32_t ix)
|
|
{
|
|
union {
|
|
float f;
|
|
int32_t i;
|
|
} u;
|
|
u.i = ix;
|
|
return u.f;
|
|
}
|
|
|
|
int32_t float2int (float fx)
|
|
{
|
|
union {
|
|
float f;
|
|
int32_t i;
|
|
} u;
|
|
u.f = fx;
|
|
return u.i;
|
|
}
|
|
|
|
#if !defined(_WIN64)
|
|
/** Returns the number of leading 0-bits in x,
|
|
starting at the most significant bit position.
|
|
If x is 0, the result is undefined.
|
|
*/
|
|
int __builtin_clz(unsigned int pattern)
|
|
{
|
|
#if 0
|
|
int res;
|
|
__asm {
|
|
mov eax, pattern
|
|
bsr eax, eax
|
|
mov res, eax
|
|
}
|
|
return 31 - res;
|
|
#endif
|
|
unsigned long index;
|
|
unsigned char res = _BitScanReverse( &index, pattern);
|
|
if (res) {
|
|
return 8*sizeof(int) - 1 - index;
|
|
} else {
|
|
return 8*sizeof(int);
|
|
}
|
|
}
|
|
#else
|
|
int __builtin_clz(unsigned int pattern)
|
|
{
|
|
int count;
|
|
if (pattern == 0u) {
|
|
return 32;
|
|
}
|
|
count = 31;
|
|
if (pattern >= 1u<<16) { pattern >>= 16; count -= 16; }
|
|
if (pattern >= 1u<<8) { pattern >>= 8; count -= 8; }
|
|
if (pattern >= 1u<<4) { pattern >>= 4; count -= 4; }
|
|
if (pattern >= 1u<<2) { pattern >>= 2; count -= 2; }
|
|
if (pattern >= 1u<<1) { count -= 1; }
|
|
return count;
|
|
}
|
|
|
|
#endif // !defined(_WIN64)
|
|
|
|
#include <intrin.h>
|
|
#include <emmintrin.h>
|
|
|
|
int usleep(int usec)
|
|
{
|
|
Sleep((usec + 999) / 1000);
|
|
return 0;
|
|
}
|
|
|
|
unsigned int sleep( unsigned int sec )
|
|
{
|
|
Sleep( sec * 1000 );
|
|
return 0;
|
|
}
|
|
|
|
#endif // defined( _MSC_VER )
|