packages feed

fp-ieee-0.1.0.7: 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;
}

#elif defined(__riscv)

#if defined(__riscv_zfa)
float hs_minimumFloat(float x, float y)
{
    float result;
    __asm__("fminm.s %0, %1, %2" : "=f"(result) : "f"(x), "f"(y));
    return result;
}

float hs_maximumFloat(float x, float y)
{
    float result;
    __asm__("fmaxm.s %0, %1, %2" : "=f"(result) : "f"(x), "f"(y));
    return result;
}

double hs_minimumDouble(double x, double y)
{
    double result;
    __asm__("fminm.d %0, %1, %2" : "=f"(result) : "f"(x), "f"(y));
    return result;
}

double hs_maximumDouble(double x, double y)
{
    double result;
    __asm__("fmaxm.d %0, %1, %2" : "=f"(result) : "f"(x), "f"(y));
    return result;
}
#endif

float hs_minimumNumberFloat(float x, float y)
{
    float result;
    __asm__("fmin.s %0, %1, %2" : "=f"(result) : "f"(x), "f"(y));
    return result;
}

float hs_maximumNumberFloat(float x, float y)
{
    float result;
    __asm__("fmax.s %0, %1, %2" : "=f"(result) : "f"(x), "f"(y));
    return result;
}

double hs_minimumNumberDouble(double x, double y)
{
    double result;
    __asm__("fmin.d %0, %1, %2" : "=f"(result) : "f"(x), "f"(y));
    return result;
}

double hs_maximumNumberDouble(double x, double y)
{
    double result;
    __asm__("fmax.d %0, %1, %2" : "=f"(result) : "f"(x), "f"(y));
    return result;
}

#else

#error "Unsupported platform"

#endif