/******************************************************************************
版权所有：	
文件名称：	rt_clib.c
文件版本：	01.01
创建作者：	sunxi
创建日期：	2020-06-18
功能说明：	实时微系统标准C库接口。
其它说明：
修改记录：
*/
/*------------------------------- 头文件 --------------------------------------
*/
#include "rt_clib.h"
#include "rt.h"

/*------------------------------- 宏定义 --------------------------------------
*/


/*------------------------------ 类型结构 -------------------------------------
*/


/*------------------------------ 全局变量 -------------------------------------
*/


/*------------------------------ 函数声明 -------------------------------------
*/
  

/*------------------------------ 外部函数 -------------------------------------
外部函数供其它实体文件引用，必须仔细检查传入参数的合法性.
*/

//noted by sunxi: 20220415 好像没有用，屏蔽掉
/*
//64位除法
static inline u64 div64_u64(u64 dividend, u64 divisor)
{
	return dividend / divisor;
}

uint32_t long __udivdi3(uint32_t long num,uint32_t long den)
{
	return div64_u64(num,den);
}
*/

#if 0
//abort,函数打印消息后返回，并不会终止程序运行。
void abort(void)
{
	rt_printf("!!!call abort!!!\r\n");
}
#endif

#if 0
//http://www.opensource.apple.com/source/xnu/xnu-792.13.8/libsa/bsearch.c
void * bsearch(const void *key, const void *base0, int nmemb, int size, int (*compar)(const void *, const void *)) 
{

	register const char *base = base0;
	register int lim;
	register int cmp;
	register const void *p;

	for (lim = nmemb; lim != 0; lim >>= 1) {
		p = base + (lim >> 1) * size;
		cmp = (*compar)(key, p);
		if (cmp == 0)
			return ((void *)p);
		if (cmp > 0) {	/* key > p: move right */
			base = (char *)p + size;
			lim--;
		}		/* else move left */
	}
	return (0);
}
#endif

//http://www.opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/libkern/strtol.c
static inline int
_isupper(char c)
{
    return (c >= 'A' && c <= 'Z');
}

static inline int
_isalpha(char c)
{
    return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
}


static inline int
_isspace(char c)
{
    return (c == ' ' || c == '\t' || c == '\n' || c == '\12');
}

static inline int
_isdigit(char c)
{
    return (c >= '0' && c <= '9');
}


/*
 * Convert a string to a long integer.
 *
 * Ignores `locale' stuff.  Assumes that the upper and lower case
 * alphabets and digits are each contiguous.
 */
long strtol(const char *nptr, char **endptr, int base)
{
	register const char *s = nptr;
	register unsigned long acc;
	register int c;
	register unsigned long cutoff;
	register int neg = 0, any, cutlim;

	/*
	 * Skip white space and pick up leading +/- sign if any.
	 * If base is 0, allow 0x for hex and 0 for octal, else
	 * assume decimal; if base is already 16, allow 0x.
	 */
	do {
		c = *s++;
	} while (_isspace(c));
	if (c == '-') {
		neg = 1;
		c = *s++;
	} else if (c == '+')
		c = *s++;
	if ((base == 0 || base == 16) &&
	    c == '0' && (*s == 'x' || *s == 'X')) {
		c = s[1];
		s += 2;
		base = 16;
	} else if ((base == 0 || base == 2) &&
	    c == '0' && (*s == 'b' || *s == 'B')) {
		c = s[1];
		s += 2;
		base = 2;
	}
	if (base == 0)
		base = c == '0' ? 8 : 10;

	/*
	 * Compute the cutoff value between legal numbers and illegal
	 * numbers.  That is the largest legal value, divided by the
	 * base.  An input number that is greater than this value, if
	 * followed by a legal input character, is too big.  One that
	 * is equal to this value may be valid or not; the limit
	 * between valid and invalid numbers is then based on the last
	 * digit.  For instance, if the range for longs is
	 * [-2147483648..2147483647] and the input base is 10,
	 * cutoff will be set to 214748364 and cutlim to either
	 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
	 * a value > 214748364, or equal but the next digit is > 7 (or 8),
	 * the number is too big, and we will return a range error.
	 *
	 * Set any if any `digits' consumed; make it negative to indicate
	 * overflow.
	 */
	cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
	cutlim = cutoff % (unsigned long)base;
	cutoff /= (unsigned long)base;
	for (acc = 0, any = 0;; c = *s++) {
		if (_isdigit(c))
			c -= '0';
		else if (_isalpha(c))
			c -= _isupper(c) ? 'A' - 10 : 'a' - 10;
		else
			break;
		if (c >= base)
			break;
		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
			any = -1;
		else {
			any = 1;
			acc *= base;
			acc += c;
		}
	}
	if (any < 0) {
		acc = neg ? LONG_MIN : LONG_MAX;
//		errno = ERANGE;
	} else if (neg)
		acc = -acc;
	if (endptr != 0)
		*endptr = (char *)(any ? s - 1 : nptr);
	return (acc);
}

/*
 * Convert a string to an unsigned long integer.
 *
 * Ignores `locale' stuff.  Assumes that the upper and lower case
 * alphabets and digits are each contiguous.
 */
unsigned long strtoul(const char *nptr, char **endptr, int base)
{
	register const char *s = nptr;
	register unsigned long acc;
	register int c;
	register unsigned long cutoff;
	register int neg = 0, any, cutlim;

	/*
	 * See strtol for comments as to the logic used.
	 */
	do {
		c = *s++;
	} while (_isspace(c));
	if (c == '-') {
		neg = 1;
		c = *s++;
	} else if (c == '+')
		c = *s++;
	if ((base == 0 || base == 16) &&
	    c == '0' && (*s == 'x' || *s == 'X')) {
		c = s[1];
		s += 2;
		base = 16;
	} else if ((base == 0 || base == 2) &&
	    c == '0' && (*s == 'b' || *s == 'B')) {
		c = s[1];
		s += 2;
		base = 2;
	}
	if (base == 0)
		base = c == '0' ? 8 : 10;
	cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
	cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
	for (acc = 0, any = 0;; c = *s++) {
		if (_isdigit(c))
			c -= '0';
		else if (_isalpha(c))
			c -= _isupper(c) ? 'A' - 10 : 'a' - 10;
		else
			break;
		if (c >= base)
			break;
		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
			any = -1;
		else {
			any = 1;
			acc *= base;
			acc += c;
		}
	}
	if (any < 0) {
		acc = ULONG_MAX;
//		errno = ERANGE;
	} else if (neg)
		acc = -acc;
	if (endptr != 0)
		*endptr = (char *)(any ? s - 1 : nptr);
	return (acc);
}

/* MSL
 * Copyright 1995-2007 Freescale Corporation.  All rights reserved.
 *
 * $Date: 2009/11/05 19:15:41 $
 * $Revision: 1.2 $
 */
 
/*
 Author:  Matthew D. Fassiotto
 Date:    first written 4/15/99
 Purpose: non-optimal single precision version of standard sqrt functions
 Assumptions: --IEEE 754 single precision float format
     *fp difference should never produce -0
     *casting a float to an int always truncates regardless of fp rounding mode.
     *the type _INT32 is 32 bits(i.e. sizeof(_INT32)=sizeof(float)
     
Note: need to eliminate two divisions in Newton iteration     
*/
//#include <math.h>
//#include <errno.h>

static int sqrt_guess[]={0x3F35B99E,0x3F366D96,0x3F3720DD,0x3F37D375,0x3F388560,0x3F3936A1,0x3F39E738,
0x3F3A9728,0x3F3B4673,0x3F3BF51B,0x3F3CA321,0x3F3D5087,0x3F3DFD4E,0x3F3EA979,0x3F3F5509,0x3F400000,
0x3F40AA5F,0x3F415428,0x3F41FD5C,0x3F42A5FE,0x3F434E0D,0x3F43F58D,0x3F449C7E,0x3F4542E1,0x3F45E8B9,
0x3F468E06,0x3F4732CA,0x3F47D706,0x3F487ABC,0x3F491DEC,0x3F49C098,0x3F4A62C2,0x3F4B046A,0x3F4BA592,
0x3F4C463A,0x3F4CE665,0x3F4D8613,0x3F4E2545,0x3F4EC3FC,0x3F4F623A,0x3F500000,0x3F509D4E,0x3F513A26,
0x3F51D689,0x3F527278,0x3F530DF3,0x3F53A8FD,0x3F544395,0x3F54DDBC,0x3F557775,0x3F5610BF,0x3F56A99B,
0x3F57420B,0x3F57DA10,0x3F5871A9,0x3F5908D9,0x3F599FA0,0x3F5A35FE,0x3F5ACBF5,0x3F5B6186,0x3F5BF6B1,
0x3F5C8B77,0x3F5D1FD9,0x3F5DB3D7,0x3F5E4773,0x3F5EDAAE,0x3F5F6D87,0x3F600000,0x3F609219,0x3F6123D4,
0x3F61B531,0x3F624630,0x3F62D6D3,0x3F636719,0x3F63F704,0x3F648695,0x3F6515CC,0x3F65A4A9,0x3F66332E,
0x3F66C15A,0x3F674F2F,0x3F67DCAE,0x3F6869D6,0x3F68F6A9,0x3F698327,0x3F6A0F50,0x3F6A9B26,0x3F6B26A9,
0x3F6BB1D9,0x3F6C3CB7,0x3F6CC744,0x3F6D517F,0x3F6DDB6B,0x3F6E6507,0x3F6EEE53,0x3F6F7751,0x3F700000,
0x3F708862,0x3F711076,0x3F71983E,0x3F721FBA,0x3F72A6EA,0x3F732DCF,0x3F73B46A,0x3F743ABA,0x3F74C0C0,
0x3F75467E,0x3F75CBF2,0x3F76511E,0x3F76D603,0x3F775AA0,0x3F77DEF6,0x3F786305,0x3F78E6CE,0x3F796A52,
0x3F79ED91,0x3F7A708B,0x3F7AF340,0x3F7B75B1,0x3F7BF7DF,0x3F7C79CA,0x3F7CFB72,0x3F7D7CD8,0x3F7DFDFC,
0x3F7E7EDE,0x3F7EFF7F,0x3F7F7FE0,0x3F800000,0x3F803FF0};

static int sqrt_guess2[]={0x3F00FF02,0x3F017DC7,0x3F01FC10,0x3F0279DF,0x3F02F734,0x3F037413,0x3F03F07B,
0x3F046C6F,0x3F04E7EE,0x3F0562FC,0x3F05DD98,0x3F0657C5,0x3F06D182,0x3F074AD3,0x3F07C3B6,0x3F083C2F,
0x3F08B43D,0x3F092BE3,0x3F09A320,0x3F0A19F6,0x3F0A9067,0x3F0B0672,0x3F0B7C1A,0x3F0BF15E,0x3F0C6641,
0x3F0CDAC3,0x3F0D4EE4,0x3F0DC2A7,0x3F0E360B,0x3F0EA912,0x3F0F1BBD,0x3F0F8E0C,0x3F100000,0x3F10719A,
0x3F10E2DC,0x3F1153C4,0x3F11C456,0x3F123491,0x3F12A476,0x3F131406,0x3F138341,0x3F13F229,0x3F1460BE,
0x3F14CF01,0x3F153CF2,0x3F15AA92,0x3F1617E3,0x3F1684E4,0x3F16F196,0x3F175DFA,0x3F17CA11,0x3F1835DC,
0x3F18A15A,0x3F190C8C,0x3F197774,0x3F19E211,0x3F1A4C65,0x3F1AB66F,0x3F1B2032,0x3F1B89AC,0x3F1BF2DF,
0x3F1C5BCB,0x3F1CC471,0x3F1D2CD1,0x3F1D94EC,0x3F1DFCC2,0x3F1E6455,0x3F1ECBA4,0x3F1F32AF,0x3F1F9979,
0x3F200000,0x3F206646,0x3F20CC4A,0x3F21320E,0x3F219792,0x3F21FCD7,0x3F2261DC,0x3F22C6A3,0x3F232B2B,
0x3F238F75,0x3F23F383,0x3F245753,0x3F24BAE7,0x3F251E3E,0x3F25815A,0x3F25E43B,0x3F2646E1,0x3F26A94D,
0x3F270B7F,0x3F276D77,0x3F27CF36,0x3F2830BC,0x3F28920A,0x3F28F31F,0x3F2953FD,0x3F29B4A4,0x3F2A1514,
0x3F2A754D,0x3F2AD550,0x3F2B351D,0x3F2B94B5,0x3F2BF417,0x3F2C5345,0x3F2CB23E,0x3F2D1104,0x3F2D6F95,
0x3F2DCDF3,0x3F2E2C1E,0x3F2E8A16,0x3F2EE7DB,0x3F2F456F,0x3F2FA2D0,0x3F300000,0x3F305CFF,0x3F30B9CC,
0x3F31166A,0x3F3172D6,0x3F31CF13,0x3F322B20,0x3F3286FE,0x3F32E2AC,0x3F333E2C,0x3F33997C,0x3F33F49F,
0x3F344F93,0x3F34AA5A,0x3F3504F3,0x3F355F5F,0x3F35B99E,
};

#define _UINT32 unsigned int
#define _INT32   int

float sqrtf(float x)
{
  const _UINT32 numbits = (sizeof(sqrt_guess))/(4*64) + 5;

  /* calculated at compile time(hopefully)--assumes minimal # of
     elements in sqrt_guess is 32 or an integral (power of two)*32 
  */

  _UINT32 *u32tmp1 = (_UINT32*)&x;
  _INT32 *s32tmp1 = (_INT32*)&x;
  const _UINT32 bit_shift=23-numbits;
  const _UINT32 bit_mask=0x007fffff&(~(sizeof(sqrt_guess)>>2)<<bit_shift);
  const _UINT32 first_several_sig_bits_of_x=(*u32tmp1) & bit_mask;
  const _INT32 biased_exp=(*u32tmp1) & 0x7f800000;
  float guess;
  float scaled_x;
  _UINT32 *u32tmp2 = (_UINT32*)&guess;
  _UINT32 *u32tmp3 = (_UINT32*)&scaled_x;
 
  //if(*(_UINT32*)&x & 0x80000000) /* either < 0 or -0 */
 // {
  // if((*(_UINT32*)&x) & 0x7fffffff) return NAN;
 //  else return x;  /* x = -0 */
 // }  
  
  //if(!biased_exp) return 0.0f;  //flush denormal to 0.0
  /* the condition below insures that we round x so that ||sqrt(x)-guess||<=||sqrt(x)-y|| for all y in sqrt_guess[](round to nearest)
     since sqrt is monotonically increasing --> ||sqrt(x)-sqrt(guess)|| <= ||sqrt(x)-sqrt(y)||
     we look at the remaining low order significant bits of x below the bit_mask.
  */
#if 0
#if _EWL_C99  
		if ((x < 0) && (math_errhandling & MATH_ERRNO))	
		{
			_EWL_LOCALDATA(errno) = EDOM;
			return(NAN);
		} 
#endif
#endif

   if( biased_exp & 0x00800000)  // if biased_exp is odd then the sqrt of the exponent is 2^^intsqrt(2)
   {
    (*u32tmp3)=0x3E800000 + ((*u32tmp1)&0x007fffff);  //scaled_x in [.25,.5)
    (*u32tmp2)=sqrt_guess2[(first_several_sig_bits_of_x>>bit_shift)];
    
   }
   else
   {
    (*u32tmp3)=0x3f000000 + ((*s32tmp1)&0x007fffff);  //scaled_x in [.5,1.0)
    (*u32tmp2)=sqrt_guess[(first_several_sig_bits_of_x>>bit_shift)];
   } 
   
   guess += scaled_x/guess;  // now have 12 sig bits
   guess =.25f*guess + (scaled_x/guess);  // now we have about 24 sig bits
              
   /* we now reduce x to 2^^n*y  where y is in [.5,1) we then calculate sqrt(x)=sqrt(2^^n)*sqrt(y) 
      where if n is even we simply shift the exponent of guess appropriately or if n is odd we shift
      and multiply by sqrt(2) if n > 0 and 1/sqrt(2) if n > 0
   */

   s32tmp1 = (_INT32*)&guess;
   if(biased_exp > 0x3f000000)
    (*s32tmp1)+=(((biased_exp - 0x3e800000)>>1)&0xffbfffff) ;  // this subtracts off bias(127=0x3f80...)                                                              // from biased_exp and one more which divides by two
   else
    (*s32tmp1)-=((0x3f000000 - biased_exp)>>1)&0xffbfffff;
    
  return guess;
}  



/*
 * ====================================================
 * 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.
 * ====================================================
 */

/*
 * from: @(#)fdlibm.h 5.1 93/09/24
 */

 /* A union which permits us to convert between a float and a 32 bit
   int.  */

typedef union
{
  float value;
  u32 word;
} ieee_float_shape_type;

/* Get a 32 bit int from a float.  */
#ifndef GET_FLOAT_WORD
# define GET_FLOAT_WORD(i,d)					\
do {								\
  ieee_float_shape_type gf_u;					\
  gf_u.value = (d);						\
  (i) = gf_u.word;						\
} while (0)
#endif

/* Set a float from a 32 bit int.  */
#ifndef SET_FLOAT_WORD
# define SET_FLOAT_WORD(d,i)					\
do {								\
  ieee_float_shape_type sf_u;					\
  sf_u.word = (i);						\
  (d) = sf_u.value;						\
} while (0)
#endif

/*
 * fabsf(x) returns the absolute value of x.
 */


inline float fabsf(float x)
{

#if 1
	if(x < 0.0)
	{
		x = -x;
	}

	return x;
#else
	u32 ix;
	GET_FLOAT_UWORD(ix, x);
	SET_FLOAT_UWORD(x, ix & 0x7fffffffU);

    return x;
#endif
}

/* s_atanf.c -- float version of s_atan.c.
 * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
 */

/*
 * ====================================================
 * 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.
 * ====================================================
 */

//#include <math.h>
//#include <math_private.h>

static const float atanhi[] = {
  4.6364760399e-01, /* atan(0.5)hi 0x3eed6338 */
  7.8539812565e-01, /* atan(1.0)hi 0x3f490fda */
  9.8279368877e-01, /* atan(1.5)hi 0x3f7b985e */
  1.5707962513e+00, /* atan(inf)hi 0x3fc90fda */
};

static const float atanlo[] = {
  5.0121582440e-09, /* atan(0.5)lo 0x31ac3769 */
  3.7748947079e-08, /* atan(1.0)lo 0x33222168 */
  3.4473217170e-08, /* atan(1.5)lo 0x33140fb4 */
  7.5497894159e-08, /* atan(inf)lo 0x33a22168 */
};

static const float aT[] = {
  3.3333334327e-01, /* 0x3eaaaaaa */
 -2.0000000298e-01, /* 0xbe4ccccd */
  1.4285714924e-01, /* 0x3e124925 */
 -1.1111110449e-01, /* 0xbde38e38 */
  9.0908870101e-02, /* 0x3dba2e6e */
 -7.6918758452e-02, /* 0xbd9d8795 */
  6.6610731184e-02, /* 0x3d886b35 */
 -5.8335702866e-02, /* 0xbd6ef16b */
  4.9768779427e-02, /* 0x3d4bda59 */
 -3.6531571299e-02, /* 0xbd15a221 */
  1.6285819933e-02, /* 0x3c8569d7 */
};

static const float
one   = 1.0,
huge   = 1.0e30;

float __atanf(float x)
{
	float w,s1,s2,z;
	int ix,hx,id;

	GET_FLOAT_WORD(hx,x);
	ix = hx&0x7fffffff;
	if(ix>=0x50800000) {	/* if |x| >= 2^34 */
	    if(ix>0x7f800000)
		return x+x;		/* NaN */
	    if(hx>0) return  atanhi[3]+atanlo[3];
	    else     return -atanhi[3]-atanlo[3];
	} if (ix < 0x3ee00000) {	/* |x| < 0.4375 */
	    if (ix < 0x31000000) {	/* |x| < 2^-29 */
		if(huge+x>one) return x;	/* raise inexact */
	    }
	    id = -1;
	} else {
	x = fabsf(x);
	if (ix < 0x3f980000) {		/* |x| < 1.1875 */
	    if (ix < 0x3f300000) {	/* 7/16 <=|x|<11/16 */
		id = 0; x = ((float)2.0*x-one)/((float)2.0+x); 
	    } else {			/* 11/16<=|x|< 19/16 */
		id = 1; x  = (x-one)/(x+one); 
	    }
	} else {
	    if (ix < 0x401c0000) {	/* |x| < 2.4375 */
		id = 2; x  = (x-(float)1.5)/(one+(float)1.5*x);
	    } else {			/* 2.4375 <= |x| < 2^66 */
		id = 3; x  = -(float)1.0/x;
	    }
	}}
    /* end of argument reduction */
	z = x*x;
	w = z*z;
    /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
	s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10])))));
	s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9]))));
	if (id<0) return x - x*(s1+s2);
	else {
	    z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x);
	    return (hx<0)? -z:z;
	}
}


/* e_atan2f.c -- float version of e_atan2.c.
 * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
 */

/*
 * ====================================================
 * 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.
 * ====================================================
 */

//#include <math.h>
//#include <math_private.h>

static const float
tiny  = 1.0e-30,
zero  = 0.0,
pi_o_4  = 7.8539818525e-01,  /* 0x3f490fdb */
pi_o_2  = 1.5707963705e+00,  /* 0x3fc90fdb */
pi      = 3.1415927410e+00,  /* 0x40490fdb */
pi_lo   = -8.7422776573e-08; /* 0xb3bbbd2e */
 
float  atan2f (float y, float x)
{
	float z;
	int32_t k,m,hx,hy,ix,iy;

	GET_FLOAT_WORD(hx,x);
	ix = hx&0x7fffffff;
	GET_FLOAT_WORD(hy,y);
	iy = hy&0x7fffffff;
	if((ix>0x7f800000)||
	   (iy>0x7f800000))	/* x or y is NaN */
	   return x+y;
	if(hx==0x3f800000) return __atanf(y);   /* x=1.0 */
	m = ((hy>>31)&1)|((hx>>30)&2);	/* 2*sign(x)+sign(y) */

    /* when y = 0 */
	if(iy==0) {
	    switch(m) {
		case 0:
		case 1: return y;	/* atan(+-0,+anything)=+-0 */
		case 2: return  pi+tiny;/* atan(+0,-anything) = pi */
		case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */
	    }
	}
    /* when x = 0 */
	if(ix==0) return (hy<0)?  -pi_o_2-tiny: pi_o_2+tiny;

    /* when x is INF */
	if(ix==0x7f800000) {
	    if(iy==0x7f800000) {
		switch(m) {
		    case 0: return  pi_o_4+tiny;/* atan(+INF,+INF) */
		    case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */
		    case 2: return  (float)3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/
		    case 3: return (float)-3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/
		}
	    } else {
		switch(m) {
		    case 0: return  zero  ;	/* atan(+...,+INF) */
		    case 1: return -zero  ;	/* atan(-...,+INF) */
		    case 2: return  pi+tiny  ;	/* atan(+...,-INF) */
		    case 3: return -pi-tiny  ;	/* atan(-...,-INF) */
		}
	    }
	}
    /* when y is INF */
	if(iy==0x7f800000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;

    /* compute y/x */
	k = (iy-ix)>>23;
	if(k > 60) z=pi_o_2+(float)0.5*pi_lo;	/* |y/x| >  2**60 */
	else if(hx<0&&k<-60) z=0.0;	/* |y|/x < -2**60 */
	else z=__atanf(fabsf(y/x));	/* safe to do y/x */
	switch (m) {
	    case 0: return       z  ;	/* atan(+,+) */
	    case 1: {
		      u_int32_t zh;
		      GET_FLOAT_WORD(zh,z);
		      SET_FLOAT_WORD(z,zh ^ 0x80000000);
		    }
		    return       z  ;	/* atan(-,+) */
	    case 2: return  pi-(z-pi_lo);/* atan(+,-) */
	    default: /* case 3 */
		    return  (z-pi_lo)-pi;/* atan(-,-) */
	}
}


long atol(const char *str)
{
	return strtol(str, (char **)0, 10);
}
#if 0
long atoi(const char *str)
{
	return strtol(str, (char **)0, 10);
}
#endif

void swap32(void *p)
{
	char *ptr,c;

	if(!p)
	{
		return;
	}
		
	ptr=(char *)p;
	
	//swap 1,4
	c=*ptr;
	*ptr=*(ptr+3);
	*(ptr+3)=c;

	//swap 2,3
	c=*(ptr+1);
	*(ptr+1)=*(ptr+2);
	*(ptr+2)=c;

	return ;
}

void swap16(void *p)
{
	char *ptr,c;
	
	if(!p)
	{
		return;
	}

	ptr=(char *)p;
	
	//swap 1,2
	c=*ptr;
	*ptr=*(ptr+1);
	*(ptr+1)=c;

	return ;
}


int test_round(void)
{
	int n;
	float f;

	for(f=-2; f<2; f+= 0.1)
	{
		n = (int)rt_round(f);
		rt_printf("f=%f,n=%d.\r\n",f,n);
	}

	return 0;
}
/*------------------------------ 内部函数 -------------------------------------
内部函数以下划线‘_’开头，不需要检查参数的合法性.
*/


/*------------------------------ 测试函数 -------------------------------------
一个实体文件必须带一个本模块的测试函数来进行单元测试，如果的确不方便在本模块中
进行单元测试，必须在此注明实际的测试位置（例如在哪个实体文件中使用哪个测试函数）.
*/


/*------------------------------ 文件结束 -------------------------------------
*/
