#include "fenv.h"
#include "xmmLibm_prefix.h"
static inline double _nextafter( double x, double y ) ALWAYS_INLINE;
static inline double _nextafter( double x, double y )
{
static const double smallest = 0x0.0000000000001p-1022;
if( EXPECT_FALSE( x != x ) )
return x + x;
if( EXPECT_TRUE( x < y ) )
{
if( EXPECT_FALSE( x == - __builtin_inf() ) )
return -0x1.fffffffffffffp1023;
if( EXPECT_FALSE( x == - smallest ) ) return -0.0;
int oldmxcsr = _mm_getcsr();
int newmxcsr = (oldmxcsr & ~ROUND_MASK ) | ROUND_TO_INFINITY;
_mm_setcsr( newmxcsr );
x += smallest;
oldmxcsr |= _mm_getcsr() & ALL_FLAGS;
_mm_setcsr( oldmxcsr );
return x;
}
if( EXPECT_TRUE( x > y ) )
{
if( EXPECT_FALSE( x == __builtin_inf() ) )
return 0x1.fffffffffffffp1023;
int oldmxcsr = _mm_getcsr();
int newmxcsr = (oldmxcsr & ~ROUND_MASK ) | ROUND_TO_NEG_INFINITY;
_mm_setcsr( newmxcsr );
x -= smallest;
oldmxcsr |= _mm_getcsr() & ALL_FLAGS;
_mm_setcsr( oldmxcsr );
return x;
}
if( EXPECT_TRUE( x == y ) )
return y;
return y + y;
}
#if defined( BUILDING_FOR_CARBONCORE_LEGACY )
float nextafterf( float x, float y )
{
static const float smallest = 0x0.000002p-126f;
if( EXPECT_FALSE( x != x ) )
return x + x;
if( EXPECT_TRUE( x < y ) )
{
if( EXPECT_FALSE( x == - __builtin_inff() ) )
return -0x1.fffffep127f;
if( EXPECT_FALSE( x == - smallest ) ) return -0.0f;
int oldmxcsr = _mm_getcsr();
int newmxcsr = (oldmxcsr & ~ROUND_MASK ) | ROUND_TO_INFINITY;
_mm_setcsr( newmxcsr );
x += smallest;
oldmxcsr |= _mm_getcsr() & ALL_FLAGS;
_mm_setcsr( oldmxcsr );
return x;
}
if( EXPECT_TRUE( x > y ) )
{
if( EXPECT_FALSE( x == __builtin_inff() ) )
return 0x1.fffffep127f;
int oldmxcsr = _mm_getcsr();
int newmxcsr = (oldmxcsr & ~ROUND_MASK ) | ROUND_TO_NEG_INFINITY;
_mm_setcsr( newmxcsr );
x -= smallest;
oldmxcsr |= _mm_getcsr() & ALL_FLAGS;
_mm_setcsr( oldmxcsr );
return x;
}
if( EXPECT_TRUE( x == y ) )
return y;
return y + y;
}
double nextafterd( double x, double y )
{
return _nextafter( x, y );
}
#else
double nextafter( double x, double y )
{
return _nextafter( x, y );
}
float nexttowardf( float x, long double y )
{
static const float smallest = 0x0.000002p-126f;
if( EXPECT_FALSE( x != x ) )
return x + x;
if( EXPECT_TRUE( x < y ) )
{
if( EXPECT_FALSE( x == - __builtin_inff() ) )
return -0x1.fffffep127f;
int oldmxcsr = _mm_getcsr();
int newmxcsr = (oldmxcsr & ~ROUND_MASK ) | ROUND_TO_INFINITY;
_mm_setcsr( newmxcsr );
x += smallest;
oldmxcsr |= _mm_getcsr() & ALL_FLAGS;
_mm_setcsr( oldmxcsr );
return x;
}
if( EXPECT_TRUE( x > y ) )
{
if( EXPECT_FALSE( x == __builtin_inff() ) )
return 0x1.fffffep127f;
int oldmxcsr = _mm_getcsr();
int newmxcsr = (oldmxcsr & ~ROUND_MASK ) | ROUND_TO_NEG_INFINITY;
_mm_setcsr( newmxcsr );
x -= smallest;
oldmxcsr |= _mm_getcsr() & ALL_FLAGS;
_mm_setcsr( oldmxcsr );
return x;
}
if( EXPECT_TRUE( x == y ) )
return y;
return y + y;
}
double nexttoward( double x, long double y )
{
static const double smallest = 0x0.0000000000001p-1022;
if( EXPECT_FALSE( x != x ) )
return x + x;
if( EXPECT_TRUE( x < y ) )
{
if( EXPECT_FALSE( x == - __builtin_inf() ) )
return -0x1.fffffffffffffp1023;
int oldmxcsr = _mm_getcsr();
int newmxcsr = (oldmxcsr & ~ROUND_MASK ) | ROUND_TO_INFINITY;
_mm_setcsr( newmxcsr );
x += smallest;
oldmxcsr |= _mm_getcsr() & ALL_FLAGS;
_mm_setcsr( oldmxcsr );
return x;
}
if( EXPECT_TRUE( x > y ) )
{
if( EXPECT_FALSE( x == __builtin_inf() ) )
return 0x1.fffffffffffffp1023;
int oldmxcsr = _mm_getcsr();
int newmxcsr = (oldmxcsr & ~ROUND_MASK ) | ROUND_TO_NEG_INFINITY;
_mm_setcsr( newmxcsr );
x -= smallest;
oldmxcsr |= _mm_getcsr() & ALL_FLAGS;
_mm_setcsr( oldmxcsr );
return x;
}
if( EXPECT_TRUE( x == y ) )
return y;
return y + y;
}
#endif