Fix to doprnt.c and moded modff, modf etc

This commit is contained in:
igor-m
2014-04-12 01:14:47 +02:00
parent 5b1496e5c3
commit 2afff6f8aa
5 changed files with 107 additions and 136 deletions

View File

@@ -11,30 +11,20 @@
* isinff(x) returns 1 is x is inf, -1 if x is -inf, else 0;
* no branching!
*/
typedef union {
float x;
struct {
long lxx;
};
} ival;
//int isinff (float x)
//{
// long lx = *(long*) &x;
// long v = (lx & 0x7fffffff) ^ 0x7f800000;
// return ~((v | -v) >> 31) & (lx >> 30);
//}
int isinff (float xx)
int isinff (float x)
{
ival temp;
temp.x = xx;
long lx = temp.lxx;
long v = (lx & 0x7fffffff) ^ 0x7f800000;
return ~((v | -v) >> 31) & (lx >> 30);
union {
long s32;
float f32;
} u;
long v;
u.f32 = x;
v = (u.s32 & 0x7fffffff) ^ 0x7f800000;
return ~((v | -v) >> 31) & (u.s32 >> 30);
}
/*
* For PIC32, double is the same as float.
*/
//int isinf (double x) __attribute__((alias ("isinff")));
int isinf (double x) __attribute__((alias ("isinff")));

View File

@@ -11,31 +11,20 @@
* isnan(x) returns 1 is x is nan, else 0;
* no branching!
*/
int isnanf (float x)
{
union {
long s32;
float f32;
} u;
unsigned long ul;
typedef union {
float x;
struct {
long lxx;
};
} ival;
//int isnanf (float x)
//{
// long lx = *(long*) &x;
// lx = 0x7f800000 - (lx & 0x7fffffff);
// return (int) (((unsigned long) lx) >> 31);
//}
int isnanf (float xx) {
ival temp;
temp.x = xx;
long lx = temp.lxx;
lx = 0x7f800000 - (lx & 0x7fffffff);
return (int) (((unsigned long) lx) >> 31);
u.f32 = x;
ul = 0x7f800000 - (u.s32 & 0x7fffffff);
return ul >> 31;
}
/*
* For PIC32, double is the same as float.
*/
//int isnan (double x) __attribute__((alias ("isnanf")));
int isnan (double x) __attribute__((alias ("isnanf")));

View File

@@ -1,72 +1,54 @@
/*
* ====================================================
* 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.
* ====================================================
*/
// *** modified by Pito 11/2013 for RetroBSD ***
typedef union // LITTLE ENDIAN
{
double value;
struct
{
unsigned long lsw;
unsigned long msw;
} parts;
} ieee_double_shape_type;
#include <math.h>
/* Get two 32 bit ints from a double. */
#define EXTRACT_WORDS(ix0,ix1,d) \
do { \
ieee_double_shape_type ew_u; \
ew_u.value = (d); \
(ix0) = ew_u.parts.msw; \
(ix1) = ew_u.parts.lsw; \
} while (0)
#define EXTRACT_WORDS(high,low,d) \
high = *(unsigned long long*) &d; \
low = (*(unsigned long long*) &d) >> 32
/* Get the more significant 32 bit int from a double. */
#define GET_HIGH_WORD(i,d) \
do { \
ieee_double_shape_type gh_u; \
gh_u.value = (d); \
(i) = gh_u.parts.msw; \
} while (0)
/* Set a double from two 32 bit ints. */
#define INSERT_WORDS(d,ix0,ix1) \
do { \
ieee_double_shape_type iw_u; \
iw_u.parts.msw = (ix0); \
iw_u.parts.lsw = (ix1); \
(d) = iw_u.value; \
} while (0)
#define INSERT_WORDS(d,high,low) \
*(unsigned long long*) &(x) = (unsigned long long) (high) << 32 | (low)
/*
* modf(double x, double *iptr)
* return fraction part of x, and return x's integral part in *iptr.
* Method:
* Bit twiddling.
*
* Exception:
* No exception.
*/
static const double one = 1.0;
double modf (double x, double *iptr)
{
long int i0,i1,j0;
long i0, i1, j0;
unsigned long i;
double one = 1.0;
EXTRACT_WORDS (i0, i1, x);
j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; /* exponent of x */
if (j0 < 20) { /* integer part in high x */
if (j0 < 0) { /* |x|<1 */
INSERT_WORDS(*iptr,i0&0x80000000,0); /* *iptr = +-0 */
INSERT_WORDS (*iptr, i0 & 0x80000000, 0);
/* *iptr = +-0 */
return x;
} else {
i = (0x000fffff) >> j0;
if (((i0 & i) | i1) == 0) { /* x is integral */
unsigned long high;
*iptr = x;
GET_HIGH_WORD(high,x);
INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */
INSERT_WORDS (x, i0 & 0x80000000, 0);
/* return +-0 */
return x;
} else {
INSERT_WORDS (*iptr, i0 & (~i), 0);
@@ -74,18 +56,20 @@ double modf(double x, double *iptr)
}
}
} else if (j0 > 51) { /* no fraction part */
unsigned long high;
*iptr = x * one;
GET_HIGH_WORD(high,x);
INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */
/* We must handle NaNs separately. */
if (j0 == 0x400 && ((i0 & 0xfffff) | i1))
return x * one;
INSERT_WORDS (x, i0 & 0x80000000, 0);
/* return +-0 */
return x;
} else { /* fraction part in low x */
i = ((unsigned long) (0xffffffff)) >> (j0 - 20);
if ((i1 & i) == 0) { /* x is integral */
unsigned long high;
*iptr = x;
GET_HIGH_WORD(high,x);
INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */
INSERT_WORDS (x, i0 & 0x80000000, 0);
/* return +-0 */
return x;
} else {
INSERT_WORDS (*iptr, i0, i1 & (~i));

View File

@@ -13,35 +13,43 @@
*/
static const float one = 1.0;
float modff (float x, float *iptr)
float modff (float fx, float *iptr)
{
unsigned hx = *(unsigned*) &x & ~0x80000000;
unsigned s;
union {
unsigned u32;
float f32;
} x;
unsigned hx, s;
x.f32 = fx;
hx = x.u32 & ~0x80000000;
if (hx >= 0x4b000000) { /* x is NaN, infinite, or integral */
*iptr = x;
*iptr = x.f32;
if (hx <= 0x7f800000)
*(unsigned*) &x &= 0x80000000;
return x;
x.u32 &= 0x80000000;
return x.f32;
}
if (hx < 0x3f800000) { /* |x| < 1 */
*iptr = x;
*(unsigned*) iptr &= 0x80000000;
return x;
float ret = x.f32;
x.u32 &= 0x80000000;
*iptr = x.f32;
return ret;
}
/* split x at the binary point */
s = *(unsigned*) &x & 0x80000000;
*(unsigned*) iptr = *(unsigned*) &x & ~((1 << (0x96 - (hx >> 23))) - 1);
x -= *iptr;
s = x.u32 & 0x80000000;
fx = x.f32;
x.u32 &= ~((1 << (0x96 - (hx >> 23))) - 1);
*iptr = x.f32;
x.f32 = fx - *iptr;
/* restore sign in case difference is 0 */
*(unsigned*) &x = (*(unsigned*) &x & ~0x80000000) | s;
return x;
x.u32 = (x.u32 & ~0x80000000) | s;
return x.f32;
}
/*
* For PIC32, double is the same as float.
*/
//double modf (double x, double *iptr) __attribute__((alias ("modff")));
double modf (double x, double *iptr) __attribute__((alias ("modff")));

View File

@@ -367,7 +367,7 @@ number: if (sign && ((long) ul != 0L)) {
double d;
unsigned long *l = (unsigned long *) &d;
if (*(unsigned long*)&ap & 4) {
if (*(unsigned long*)&ap & 4L) {
l[0]= va_arg(ap, unsigned long);
l[1]= va_arg(ap, unsigned long);
}