Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-

Implementing floor/ceil in C

Name: Anonymous 2011-06-01 13:00

how is it implemented

Name: Anonymous 2011-06-01 13:10

With some lines of computer code.

Name: Anonymous 2011-06-01 13:11

int floor(double d) {
   return round(d-0.5);
}

int ceil(double d) {
   return round(d+0.5);
}

int round(double d) {
   return floor(d+0.5)
}


oh wait, there's recur... nvm, carry on

Name: Anonymous 2011-06-01 13:14

>>3
You're mixing up types.

Name: Anonymous 2011-06-01 13:20

>>3
And in strict theoretical computing terms, the types should form a linear mapping like the following

<object, type, variable> -> <value, type, variable>

The mapping is bijective and forms a projection on the vector space.

Name: Anonymous 2011-06-01 13:34

vector space huh *grabs dick*

Name: Anonymous 2011-06-01 14:06

/* s_ceill.c -- long double version of s_ceil.c.
 * Conversion to IEEE quad long double by Jakub Jelinek, jj@ultra.linux.cz.
 */

/*
 * ====================================================
 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
 *
 * Developed at SunPro, a Sun Microsystems, Inc. business.
 * Permission to use, copy, modify, and distribute this
 * software is freely granted, provided that this notice
 * is preserved.
 * ====================================================
 */

#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: $";
#endif

/*
 * ceill(x)
 * Return x rounded toward -inf to integral value
 * Method:
 *    Bit twiddling.
 * Exception:
 *    Inexact flag raised if x not equal to ceil(x).
 */

#include "math.h"
#include "math_private.h"

#ifdef __STDC__
static const long double huge = 1.0e4930;
#else
static long double huge = 1.0e4930;
#endif

#ifdef __STDC__
    long double __ceill(long double x)
#else
    long double __ceill(x)
    long double x;
#endif
{
    int64_t i0,i1,j0;
    u_int64_t i,j;
    GET_LDOUBLE_WORDS64(i0,i1,x);
    j0 = ((i0>>48)&0x7fff)-0x3fff;
    if(j0<48) {
        if(j0<0) {     /* raise inexact if x != 0 */
        if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
            if(i0<0) {i0=0x8000000000000000ULL;i1=0;}
            else if((i0|i1)!=0) { i0=0x3fff000000000000ULL;i1=0;}
        }
        } else {
        i = (0x0000ffffffffffffULL)>>j0;
        if(((i0&i)|i1)==0) return x; /* x is integral */
        if(huge+x>0.0) {    /* raise inexact flag */
            if(i0>0) i0 += (0x0001000000000000LL)>>j0;
            i0 &= (~i); i1=0;
        }
        }
    } else if (j0>111) {
        if(j0==0x4000) return x+x;    /* inf or NaN */
        else return x;        /* x is integral */
    } else {
        i = -1ULL>>(j0-48);
        if((i1&i)==0) return x;    /* x is integral */
        if(huge+x>0.0) {         /* raise inexact flag */
        if(i0>0) {
            if(j0==48) i0+=1;
            else {
            j = i1+(1LL<<(112-j0));
            if(j<i1) i0 +=1 ;     /* got a carry */
            i1=j;
            }
        }
        i1 &= (~i);
        }
    }
    SET_LDOUBLE_WORDS64(x,i0,i1);
    return x;
}
weak_alias (__ceill, ceill)

Name: Anonymous 2011-06-01 14:17

>>7
That's the canonical portable implementation. There are also CPU architecture specific implementations in the corresponding directories in the glibc/eglibc source package.

OP, I suggest you read the following: http://floating-point-gui.de/

Most CPU's have different instructions for setting the rounding and denormal modes of the FPU. Modern x86-64 CPUs have deprecated the FPU in favor of SSE and AVX and have individual instructions for rounding scalar and vector numbers in different fashions, without need to set rounding mode state.

So, ceil, floor, round, rint, etc. all distill down to one or two instructions each.

Name: Anonymous 2011-06-01 14:58

Now that we are talking about implementations of functions, how is sleep implemented without busy wait? For example, what does the Sleep API in Windows do since it somehow doesn't hog the CPU?

Name: Anonymous 2011-06-01 15:07

>>9
C is meant to be portable. That means there shouldn't be any kind of OS specific functions in the code itself. Crap like that should either be in a seperate module or in a library.

Name: Anonymous 2011-06-01 15:10

>>9
Now I can't speak for Windows, but on Unix sleep() is used to "block" a system call. You would normally do this if say a socket didn't to a full read(). Sleep() can also be used as a crude way to synchronized two processes that communicate with each other.

Name: Anonymous 2011-06-01 17:17

>>9
It's not a busy wait because the OS puts the thread that calls Sleep to the back of the thread queue on it's priority level, and context switches in a thread that isn't blocking, and won't consider the thread that went to sleep to be reactivated until it's timeout period has elapsed, so it never context switches back to it while it is sleeping. Context switching is done by swapping out the CPU's register file with data stored in memory, and a few other things.

Name: Anonymous 2011-06-01 18:01

>>8
As long as "portable" equals IEEE 754 I guess.

Name: Anonymous 2011-06-01 21:46

>>11
Sleep() can be used as a broken way to synchronize two processes.

Don't change these.
Name: Email:
Entire Thread Thread List