造轮子之math.h

最近自己实现了math.h中的一些函数, 目的还是为了熟悉一些原理性的知识, 虽然很多函数都有直接对应的硬件指令了…

#define LLMAX 0x7FFFFFFFFFFFFFFFLL
#define LLMIN 0X8000000000000000LL

typedef union
{
    long long llnu;
    double dbnu;
}ll_db_t;

typedef struct
{
    long long base : 52;
    int exp : 11;
    int sign : 1;
}db_bits_t;

int abs_x(int x)
{
    //return x >= 0 ? x : -x;

    int y, z;

    y = z = x;
    z >>= 31;
    y ^= z;
    y -= z;

    return y;
}

double fabs_x (double x)
{
    //return x >= 0 ? x : -x;

    long long y;

    y = *(long long *)&x;
    y &= LLMAX;

    return *(double *)&y;
}

double ceil_x(double x)
{
    double dmax = (double)(long long)LLMAX;
    double dmin = (double)(long long)LLMIN;

    if(x >= dmax || x<= dmin)
    {
        return x;
    }

    double y = (double)(long long)x;
    x > y ? y += 1.0 : 0;

    return y;
}

double floor_x(double x)
{
    double dmax = (double)(long long)LLMAX;
    double dmin = (double)(long long)LLMIN;

    if(x >= dmax || x<= dmin)
        return x;

    double y = (double)(long long)x;
    x < y ? y -= 1.0 : 0;

    return y;
}

double frexp_x(double x, int *e)
{
    double y = x;

    short *s = (short *)&y + 3;

    short w = *s;

    *s &= 0xbfef;
    *s |= 0x3fe0;

    w &= 0x7fff;
    w >>= 4;
    w -= 0x03fe;

    *e = w;
    return y;
}

double ldexp_x(double x, int n)
{
    db_bits_t *y = (db_bits_t *)&x;
    y->exp += n;

    return x;

    /*
    double y = x;

    short s = *((unsigned short *)&y + 3);
    short t = s & 0x000f;

    s >>= 4;
    s += n;
    s <<= 4;
    s |= t;

    *((unsigned short *)&y + 3) = s;

    return y;
    */
}

double fmod_x(double nu, double de)
{
    de = fabs_x(de);
    double fl = floor_x(nu / de);

    return nu - fl * de;
}

double modf_x(double x, double *n)
{
    ll_db_t y, intpart, fractpart;
    y.dbnu = x;
    long long flag = LLMIN & y.llnu;

    y.llnu &= LLMAX;

    intpart.dbnu = floor_x(y.dbnu);
    fractpart.dbnu = y.dbnu - intpart.dbnu;

    intpart.llnu |= flag;
    fractpart.llnu |= flag;

    *n = intpart.dbnu;

    return fractpart.dbnu;
}