|
Packit |
67cb25 |
/* ieee-utils/make_rep.c
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
67cb25 |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
67cb25 |
* the Free Software Foundation; either version 3 of the License, or (at
|
|
Packit |
67cb25 |
* your option) any later version.
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* This program is distributed in the hope that it will be useful, but
|
|
Packit |
67cb25 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
67cb25 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
67cb25 |
* General Public License for more details.
|
|
Packit |
67cb25 |
*
|
|
Packit |
67cb25 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
67cb25 |
* along with this program; if not, write to the Free Software
|
|
Packit |
67cb25 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#include <config.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_ieee_utils.h>
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#include "endian.c"
|
|
Packit |
67cb25 |
#include "standardize.c"
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static void sprint_nybble(int i, char *s) ;
|
|
Packit |
67cb25 |
static void sprint_byte(int i, char *s) ;
|
|
Packit |
67cb25 |
static int determine_ieee_type (int non_zero, int exponent, int max_exponent);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* For the IEEE float format the bits are found from the following
|
|
Packit |
67cb25 |
masks,
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
sign = 0x80000000
|
|
Packit |
67cb25 |
exponent = 0x7f800000
|
|
Packit |
67cb25 |
mantisssa = 0x007fffff
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
For the IEEE double format the masks are,
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
sign = 0x8000000000000000
|
|
Packit |
67cb25 |
exponent = 0x7ff0000000000000
|
|
Packit |
67cb25 |
mantissa = 0x000fffffffffffff
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
*/
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
void
|
|
Packit |
67cb25 |
gsl_ieee_float_to_rep (const float * x, gsl_ieee_float_rep * r)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int e, non_zero;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
union {
|
|
Packit |
67cb25 |
float f;
|
|
Packit |
67cb25 |
struct {
|
|
Packit |
67cb25 |
unsigned char byte[4] ;
|
|
Packit |
67cb25 |
} ieee ;
|
|
Packit |
67cb25 |
} u;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
u.f = *x ;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (little_endian_p())
|
|
Packit |
67cb25 |
make_float_bigendian(&(u.f)) ;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* note that r->sign is signed, u.ieee.byte is unsigned */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (u.ieee.byte[3]>>7)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
r->sign = 1 ;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
r->sign = 0 ;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
e = (u.ieee.byte[3] & 0x7f) << 1 | (u.ieee.byte[2] & 0x80)>>7 ;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
r->exponent = e - 127 ;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
sprint_byte((u.ieee.byte[2] & 0x7f) << 1,r->mantissa) ;
|
|
Packit |
67cb25 |
sprint_byte(u.ieee.byte[1],r->mantissa + 7) ;
|
|
Packit |
67cb25 |
sprint_byte(u.ieee.byte[0],r->mantissa + 15) ;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
r->mantissa[23] = '\0' ;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
non_zero = u.ieee.byte[0] || u.ieee.byte[1] || (u.ieee.byte[2] & 0x7f);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
r->type = determine_ieee_type (non_zero, e, 255) ;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
void
|
|
Packit |
67cb25 |
gsl_ieee_double_to_rep (const double * x, gsl_ieee_double_rep * r)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
int e, non_zero;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
union
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double d;
|
|
Packit |
67cb25 |
struct {
|
|
Packit |
67cb25 |
unsigned char byte[8];
|
|
Packit |
67cb25 |
} ieee ;
|
|
Packit |
67cb25 |
} u;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
u.d= *x ;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (little_endian_p())
|
|
Packit |
67cb25 |
make_double_bigendian(&(u.d)) ;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* note that r->sign is signed, u.ieee.byte is unsigned */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (u.ieee.byte[7]>>7)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
r->sign = 1 ;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
r->sign = 0 ;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
e =(u.ieee.byte[7] & 0x7f)<<4 ^ (u.ieee.byte[6] & 0xf0)>>4 ;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
r->exponent = e - 1023 ;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
sprint_nybble(u.ieee.byte[6],r->mantissa) ;
|
|
Packit |
67cb25 |
sprint_byte(u.ieee.byte[5],r->mantissa + 4) ;
|
|
Packit |
67cb25 |
sprint_byte(u.ieee.byte[4],r->mantissa + 12) ;
|
|
Packit |
67cb25 |
sprint_byte(u.ieee.byte[3],r->mantissa + 20) ;
|
|
Packit |
67cb25 |
sprint_byte(u.ieee.byte[2],r->mantissa + 28) ;
|
|
Packit |
67cb25 |
sprint_byte(u.ieee.byte[1],r->mantissa + 36) ;
|
|
Packit |
67cb25 |
sprint_byte(u.ieee.byte[0],r->mantissa + 44) ;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
r->mantissa[52] = '\0' ;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
non_zero = (u.ieee.byte[0] || u.ieee.byte[1] || u.ieee.byte[2]
|
|
Packit |
67cb25 |
|| u.ieee.byte[3] || u.ieee.byte[4] || u.ieee.byte[5]
|
|
Packit |
67cb25 |
|| (u.ieee.byte[6] & 0x0f)) ;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
r->type = determine_ieee_type (non_zero, e, 2047) ;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* A table of character representations of nybbles */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static char nybble[16][5]={ /* include space for the \0 */
|
|
Packit |
67cb25 |
"0000", "0001", "0010", "0011",
|
|
Packit |
67cb25 |
"0100", "0101", "0110", "0111",
|
|
Packit |
67cb25 |
"1000", "1001", "1010", "1011",
|
|
Packit |
67cb25 |
"1100", "1101", "1110", "1111"
|
|
Packit |
67cb25 |
} ;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static void
|
|
Packit |
67cb25 |
sprint_nybble(int i, char *s)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
char *c ;
|
|
Packit |
67cb25 |
c=nybble[i & 0x0f ];
|
|
Packit |
67cb25 |
*s=c[0] ; *(s+1)=c[1] ; *(s+2)=c[2] ; *(s+3)=c[3] ;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static void
|
|
Packit |
67cb25 |
sprint_byte(int i, char *s)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
char *c ;
|
|
Packit |
67cb25 |
c=nybble[(i & 0xf0)>>4];
|
|
Packit |
67cb25 |
*s=c[0] ; *(s+1)=c[1] ; *(s+2)=c[2] ; *(s+3)=c[3] ;
|
|
Packit |
67cb25 |
c=nybble[i & 0x0f];
|
|
Packit |
67cb25 |
*(s+4)=c[0] ; *(s+5)=c[1] ; *(s+6)=c[2] ; *(s+7)=c[3] ;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static int
|
|
Packit |
67cb25 |
determine_ieee_type (int non_zero, int exponent, int max_exponent)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
if (exponent == max_exponent)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
if (non_zero)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return GSL_IEEE_TYPE_NAN ;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return GSL_IEEE_TYPE_INF ;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (exponent == 0)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
if (non_zero)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return GSL_IEEE_TYPE_DENORMAL ;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return GSL_IEEE_TYPE_ZERO ;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return GSL_IEEE_TYPE_NORMAL ;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|