#include <math.h>
#include <stdint.h>
#include <limits.h>
#ifdef ARMLIBM_SET_FLAGS
#include <fenv.h>
#include "required_arithmetic.h"
#pragma STDC FENV_ACCESS ON
int ilogbf( float x )
{
union{ float f; uint32_t u;}u = {x};
u.u &= 0x7fffffff;
int32_t exp = u.u >> 23;
if( __builtin_expect( (uint32_t) exp - 1U >= 254, 0 ) )
{ if( 0.0f == x )
{
required_multiply_float( x, __builtin_inff() ); return FP_ILOGB0;
}
if( x != x )
{
required_multiply_float( 0.0f, __builtin_inff() ); return FP_ILOGBNAN;
}
if( u.u == 0x7f800000 )
{
required_multiply_float( 0.0f, x ); return INT_MAX;
}
u.u |= 0x3f800000U;
u.f -= 1.0f;
exp = u.u >> 23;
return exp - (127+126);
}
return exp - 127;
}
#else
int ilogbf( float x )
{
union{ float f; uint32_t u;}u = {x};
u.u &= 0x7fffffff;
int32_t exp = u.u >> 23;
if( __builtin_expect( (uint32_t) exp - 1U >= 254, 0 ) )
{ if( 0.0f == x )
{
return FP_ILOGB0;
}
if( x != x )
{
return FP_ILOGBNAN;
}
if( u.u == 0x7f800000 )
{
return INT_MAX;
}
u.u |= 0x3f800000U;
u.f -= 1.0f;
exp = u.u >> 23;
return exp - (127+126);
}
return exp - 127;
}
#endif // ARMLIBM_SET_FLAGS