text: /*!
   * -------------------------------------------------------------------------------------------------
   * \file s_floor.c
   * \par ESA Contract Number
   *      4000117691/16/NL/FE
   * \brief Implementation file for floor.
   * \version c07acbf539f8880d8c1255e7f85138b89f33387b
   * \date 2018-03-22 17:44:24 +0100
   * \par Last Commit
   * Fabian Schriever, 2018-03-22 17:44:24 +0100
   *
   * \par Detailed Description
   * -
   *
   * -------------------------------------------------------------------------------------------------
   * \par Changelog
   * Date       | Name         | Change
   * -----------|--------------|------------------------------
   * 2017-06-07 | F. Schriever | Add FPU DAZ behaviour #ifdef.
   * 
   * \copyright Modified work Copyright European Space Agency, 2017.
   */
  
  /* @(#)s_floor.c 5.1 93/09/24 */
  /*
   * ====================================================
   * 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.
   * ====================================================
   */
  
  /*
  FUNCTION
  <<floor>>, <<floorf>>, <<ceil>>, <<ceilf>>---floor and ceiling
  INDEX
  	floor
  INDEX
  	floorf
  INDEX
  	ceil
  INDEX
  	ceilf
  
  ANSI_SYNOPSIS
  	#include <math.h>
  	double floor(double <[x]>);
          float floorf(float <[x]>);
          double ceil(double <[x]>);
          float ceilf(float <[x]>);
  
  TRAD_SYNOPSIS
  	#include <math.h>
          double floor(<[x]>)
  	double <[x]>;
          float floorf(<[x]>) 
  	float <[x]>;
          double ceil(<[x]>) 
  	double <[x]>;
          float ceilf(<[x]>) 
  	float <[x]>;
  
  DESCRIPTION
  <<floor>> and <<floorf>> find 
  @tex
  $\lfloor x \rfloor$, 
  @end tex
  the nearest integer less than or equal to <[x]>.
  <<ceil>> and <<ceilf>> find 
  @tex
  $\lceil x\rceil$,
  @end tex
  the nearest integer greater than or equal to <[x]>.
  
  RETURNS
  <<floor>> and <<ceil>> return the integer result as a double.
  <<floorf>> and <<ceilf>> return the integer result as a float.
  
  PORTABILITY
  <<floor>> and <<ceil>> are ANSI.
  <<floorf>> and <<ceilf>> are extensions.
  
  
  */
  
  /*
   * floor(x)
   * Return x rounded toward -inf to integral value
   * Method:
   *	Bit twiddling.
   * Exception:
   *	Inexact flag raised if x not equal to floor(x).
   */
  
  #include "fdlibm.h"
  
  #ifndef _DOUBLE_IS_32BITS
  
  #ifdef __STDC__
  static const double huge = 1.0e300;
  #else
  static double huge = 1.0e300;
  #endif
  
  #ifdef __STDC__
  	double floor(double x)
  #else
  	double floor(x)
  	double x;
  #endif
  {
  #ifdef MLFS_FPU_DAZ
  	x *= __volatile_one;
  #endif /* MLFS_FPU_DAZ */
  
  	__int32_t i0,i1,j0;
  	__uint32_t i,j;
  	EXTRACT_WORDS(i0,i1,x);
  	j0 = ((i0>>20)&0x7ff)-0x3ff;
  	if(j0<20) {
  	    if(j0<0) { 	/* raise inexact if x != 0 */
  		if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
  		    if(i0>=0) {i0=i1=0;} 
  		    else if(((i0&0x7fffffff)|i1)!=0)
  			{ i0=(__int32_t)0xbff00000U;i1=0;}
  		}
  	    } else {
  		i = (0x000fffff)>>j0;
  		if(((i0&i)|i1)==0) return x; /* x is integral */
  		if(huge+x>0.0) {	/* raise inexact flag */
  		    if(i0<0) i0 += (0x00100000)>>j0;
  		    i0 &= (~i); i1=0;
  		}
  	    }
  	} else if (j0>51) {
  	    if(j0==0x400) return x+x;	/* inf or NaN */
  	    else return x;		/* x is integral */
  	} else {
  	    i = ((__uint32_t)(0xffffffffU))>>(j0-20);
  	    if((i1&i)==0) return x;	/* x is integral */
  	    if(huge+x>0.0) { 		/* raise inexact flag */
  		if(i0<0) {
  		    if(j0==20) i0+=1; 
  		    else {
  			j = i1+(1<<(52-j0));
  			if(j<(__uint32_t)i1) i0 +=1 ; 	/* got a carry */
  			i1=j;
  		    }
  		}
  		i1 &= (~i);
  	    }
  	}
  	INSERT_WORDS(x,i0,i1);
  	return x;
  }
  
  #endif /* _DOUBLE_IS_32BITS */
  