fp-ieee-0.1.0: cbits/minmax.c
// In case of GCC, -fsignaling-nans must be set to use '*= 1.0' as canonicalization
// #if defined(__GNUC__) && !defined(__SUPPORT_SNAN__)
// #error "-fsignaling-nans must be set"
// #endif
#if defined(__aarch64__)
// Properties of minimum and maximum:
// * -0 < +0
// * If either of inputs is NaN, returns a quiet NaN.
float hs_minimumFloat(float x, float y)
{
float result;
asm("fmin %s0, %s1, %s2" : "=w"(result) : "w"(x), "w"(y));
return result;
}
float hs_maximumFloat(float x, float y)
{
float result;
asm("fmax %s0, %s1, %s2" : "=w"(result) : "w"(x), "w"(y));
return result;
}
double hs_minimumDouble(double x, double y)
{
double result;
asm("fmin %d0, %d1, %d2" : "=w"(result) : "w"(x), "w"(y));
return result;
}
double hs_maximumDouble(double x, double y)
{
double result;
asm("fmax %d0, %d1, %d2" : "=w"(result) : "w"(x), "w"(y));
return result;
}
// Properties of minimumNumber and maximumNumber:
// * -0 < +0
// * Treat a NaN as "lack of input".
// If both of inputs are NaNs, returns a quiet NaN.
float hs_minimumNumberFloat(float x, float y)
{
float result;
// FMINNM always returns a NaN if either of inputs is signaling NaN.
// Therefore, we convert signaling NaNs to quiet ones before applying FMINNM.
// x *= 1.0f;
// y *= 1.0f;
asm("fmul %s0, %s0, %s1" : "+w"(x) : "w"(1.0f));
asm("fmul %s0, %s0, %s1" : "+w"(y) : "w"(1.0f));
asm("fminnm %s0, %s1, %s2" : "=w"(result) : "w"(x), "w"(y));
return result;
}
float hs_maximumNumberFloat(float x, float y)
{
float result;
// FMAXNM always returns a NaN if either of inputs is signaling NaN.
// Therefore, we convert signaling NaNs to quiet ones before applying FMAXNM.
// x *= 1.0f;
// y *= 1.0f;
asm("fmul %s0, %s0, %s1" : "+w"(x) : "w"(1.0f));
asm("fmul %s0, %s0, %s1" : "+w"(y) : "w"(1.0f));
asm("fmaxnm %s0, %s1, %s2" : "=w"(result) : "w"(x), "w"(y));
return result;
}
double hs_minimumNumberDouble(double x, double y)
{
double result;
// FMINNM always returns a NaN if either of inputs is signaling NaN.
// Therefore, we convert signaling NaNs to quiet ones before applying FMINNM.
// x *= 1.0;
// y *= 1.0;
asm("fmul %d0, %d0, %d1" : "+w"(x) : "w"(1.0));
asm("fmul %d0, %d0, %d1" : "+w"(y) : "w"(1.0));
asm("fminnm %d0, %d1, %d2" : "=w"(result) : "w"(x), "w"(y));
return result;
}
double hs_maximumNumberDouble(double x, double y)
{
double result;
// FMAXNM always returns a NaN if either of inputs is signaling NaN.
// Therefore, we convert signaling NaNs to quiet ones before applying FMAXNM.
// x *= 1.0;
// y *= 1.0;
asm("fmul %d0, %d0, %d1" : "+w"(x) : "w"(1.0));
asm("fmul %d0, %d0, %d1" : "+w"(y) : "w"(1.0));
asm("fmaxnm %d0, %d1, %d2" : "=w"(result) : "w"(x), "w"(y));
return result;
}
#else
#error "Unsupported platform"
#endif