summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/SNIP/ldfloor.c
blob: acea285e5f4b5831b84a1084e15006ecc0176fb8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/* ldfloor() -- long double floor
** public domain by Raymond Gardner  Englewood, CO
** tested with TC++
** assumptions: 80-bit IEEE format numbers, stored LSB first 
**   (Intel style), longs & ints are accessed from arbitrary boundaries
*/

long double ldfloor(long double a)
{
    long double a0;
    int e, n;
   
    a0 = a;
    e = ((int *)&a)[4] & 0x7FFF;        /* extract exponent         */
    if ( e == 0 )                       /* 0 is special case        */
        return (long double) 0.0;
    e -= 16383;                         /* unbias exponent          */
    if (e < 0)                          /* if < 0, num is < 1,...   */
    {
        a = 0.0;                        /* so floor is zero         */
    }
    else if ((n = 63 - e) > 0)          /* clear n least sig. bits  */
    {
        if (n < 32)                     /* clear n lowest bits      */
        {
            ((unsigned long *)&a)[0] &= ~((1L << n) - 1);
        }
        else                            /* n >= 32 */
        {
            ((unsigned long *)&a)[0] = 0; /* clear lower 32 bits            */
            n -= 32;                    /* how many left to clear ?         */
            if (n)                      /* if any, clear n next lowest bits */
            {
                ((unsigned long *)&a)[1] &= ~((1L << n) - 1);
            }
        }
    }
    if (a0 < 0 && a0 != a)          /* if neg. and it had fractional bits */
        a -= 1.0;                   /* adjust the floor                   */
    return a;                       /* return it                          */
}