Use Ashok's IEEE-float-to-long code as the basis for

IEEE-float-to-native-float code, and use that as the basis for
IEEE-double-to-native-double code.  Use that code on VAXes.

Eliminate "ieee-float.h", as we no longer use it; instead, we use the
tvbuff routines for extracting IEEE floating-point numbers.

svn path=/trunk/; revision=5243
This commit is contained in:
Guy Harris 2002-04-24 21:19:38 +00:00
parent 6c12522f42
commit 7d96eec76b
3 changed files with 171 additions and 115 deletions

View File

@ -1,7 +1,7 @@
# Makefile.am
# Automake file for Ethereal
#
# $Id: Makefile.am,v 1.422 2002/04/18 00:29:16 guy Exp $
# $Id: Makefile.am,v 1.423 2002/04/24 21:19:37 guy Exp $
#
# Ethereal - Network traffic analyzer
# By Gerald Combs <gerald@ethereal.com>
@ -841,7 +841,6 @@ EXTRA_DIST = \
getopt.c \
getopt.h \
idl2eth.sh \
ieee-float.h \
image/Makefile.nmake \
image/README.image \
image/clist_ascend.xpm \

View File

@ -9,10 +9,13 @@
* the data of a backing tvbuff, or can be a composite of
* other tvbuffs.
*
* $Id: tvbuff.c,v 1.32 2002/04/12 23:25:24 guy Exp $
* $Id: tvbuff.c,v 1.33 2002/04/24 21:19:38 guy Exp $
*
* Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
*
* Code to convert IEEE floating point formats to native floating point
* derived from code Copyright (c) Ashok Narayanan, 2000
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
@ -1005,6 +1008,152 @@ tvb_get_ntohl(tvbuff_t *tvb, gint offset)
return pntohl(ptr);
}
/*
* Stuff for IEEE float handling on platforms that don't have IEEE
* format as the native floating-point format.
*
* For now, we treat only the VAX as such a platform.
*
* XXX - other non-IEEE boxes that can run UNIX include some Crays,
* and possibly other machines.
*
* It appears that the official Linux port to System/390 and
* zArchitecture uses IEEE format floating point (not a
* huge surprise).
*
* I don't know whether there are any other machines that
* could run Ethereal and that don't use IEEE format.
* As far as I know, all of the main commercial microprocessor
* families on which OSes that support Ethereal can run
* use IEEE format (x86, 68k, SPARC, MIPS, PA-RISC, Alpha,
* IA-64, and so on).
*/
#if defined(vax)
#include <math.h>
/*
* Single-precision.
*/
#define IEEE_SP_NUMBER_WIDTH 32 /* bits in number */
#define IEEE_SP_EXP_WIDTH 8 /* bits in exponent */
#define IEEE_SP_MANTISSA_WIDTH 23 /* IEEE_SP_NUMBER_WIDTH - 1 - IEEE_SP_EXP_WIDTH */
#define IEEE_SP_SIGN_MASK 0x80000000
#define IEEE_SP_EXPONENT_MASK 0x7F800000
#define IEEE_SP_MANTISSA_MASK 0x007FFFFF
#define IEEE_SP_INFINITY IEEE_SP_EXPONENT_MASK
#define IEEE_SP_IMPLIED_BIT (1 << IEEE_SP_MANTISSA_WIDTH)
#define IEEE_SP_INFINITE ((1 << IEEE_SP_EXP_WIDTH) - 1)
#define IEEE_SP_BIAS ((1 << (IEEE_SP_EXP_WIDTH - 1)) - 1)
static int
ieee_float_is_zero(guint32 w)
{
return ((w & ~IEEE_SP_SIGN_MASK) == 0);
}
static float
get_ieee_float(guint32 w)
{
long sign;
long exponent;
long mantissa;
sign = w & IEEE_SP_SIGN_MASK;
exponent = w & IEEE_SP_EXPONENT_MASK;
mantissa = w & IEEE_SP_MANTISSA_MASK;
if (ieee_float_is_zero(w)) {
/* number is zero, unnormalized, or not-a-number */
return 0.0;
}
#if 0
/*
* XXX - how to handle this?
*/
if (IEEE_SP_INFINITY == exponent) {
/*
* number is positive or negative infinity, or a special value
*/
return (sign? MINUS_INFINITY: PLUS_INFINITY);
}
#endif
exponent = ((exponent >> IEEE_SP_MANTISSA_WIDTH) - IEEE_SP_BIAS) -
IEEE_SP_MANTISSA_WIDTH;
mantissa |= IEEE_SP_IMPLIED_BIT;
if (sign)
return -mantissa * pow(2, exponent);
else
return mantissa * pow(2, exponent);
}
/*
* Double-precision.
* We assume that if you don't have IEEE floating-point, you have a
* compiler that understands 64-bit integral quantities.
*/
#define IEEE_DP_NUMBER_WIDTH 64 /* bits in number */
#define IEEE_DP_EXP_WIDTH 11 /* bits in exponent */
#define IEEE_DP_MANTISSA_WIDTH 52 /* IEEE_DP_NUMBER_WIDTH - 1 - IEEE_DP_EXP_WIDTH */
#define IEEE_DP_SIGN_MASK 0x8000000000000000LL
#define IEEE_DP_EXPONENT_MASK 0x7FF0000000000000LL
#define IEEE_DP_MANTISSA_MASK 0x000FFFFFFFFFFFFFLL
#define IEEE_DP_INFINITY IEEE_DP_EXPONENT_MASK
#define IEEE_DP_IMPLIED_BIT (1LL << IEEE_DP_MANTISSA_WIDTH)
#define IEEE_DP_INFINITE ((1 << IEEE_DP_EXP_WIDTH) - 1)
#define IEEE_DP_BIAS ((1 << (IEEE_DP_EXP_WIDTH - 1)) - 1)
static int
ieee_double_is_zero(guint64 w)
{
return ((w & ~IEEE_SP_SIGN_MASK) == 0);
}
static double
get_ieee_double(guint64 w)
{
gint64 sign;
gint64 exponent;
gint64 mantissa;
sign = w & IEEE_DP_SIGN_MASK;
exponent = w & IEEE_DP_EXPONENT_MASK;
mantissa = w & IEEE_DP_MANTISSA_MASK;
if (ieee_double_is_zero(w)) {
/* number is zero, unnormalized, or not-a-number */
return 0.0;
}
#if 0
/*
* XXX - how to handle this?
*/
if (IEEE_DP_INFINITY == exponent) {
/*
* number is positive or negative infinity, or a special value
*/
return (sign? MINUS_INFINITY: PLUS_INFINITY);
}
#endif
exponent = ((exponent >> IEEE_DP_MANTISSA_WIDTH) - IEEE_DP_BIAS) -
IEEE_DP_MANTISSA_WIDTH;
mantissa |= IEEE_DP_IMPLIED_BIT;
if (sign)
return -mantissa * pow(2, exponent);
else
return mantissa * pow(2, exponent);
}
#endif
/*
* Fetches an IEEE single-precision floating-point number, in
* big-endian form, and returns a "float".
@ -1016,23 +1165,8 @@ tvb_get_ntohl(tvbuff_t *tvb, gint offset)
float
tvb_get_ntohieee_float(tvbuff_t *tvb, int offset)
{
/*
* XXX - other non-IEEE boxes that can run UNIX include some
* Crays, and possibly other machines.
*
* It appears that the official Linux port to System/390 and
* zArchitecture uses IEEE format floating point (not a
* huge surprise).
*
* I don't know whether there are any other machines that
* could run Ethereal and that don't use IEEE format.
* As far as I know, all of the main commercial microprocessor
* families on which OSes that support Ethereal can run
* use IEEE format (x86, 68k, SPARC, MIPS, PA-RISC, Alpha,
* IA-64, and so on).
*/
#if defined(vax)
#error "Sorry, you'll have to write code to translate to VAX format"
return get_ieee_float(tvb_get_ntohl(tvb, offset));
#else
union {
float f;
@ -1052,12 +1186,17 @@ double
tvb_get_ntohieee_double(tvbuff_t *tvb, int offset)
{
#if defined(vax)
#error "Sorry, you'll have to write code to translate to VAX format"
union {
double d;
guint32 w[2];
guint64 dw;
} ieee_fp_union;
#else
union {
double d;
guint32 w[2];
} ieee_fp_union;
#endif
#ifdef WORDS_BIGENDIAN
ieee_fp_union.w[0] = tvb_get_ntohl(tvb, offset);
@ -1066,6 +1205,9 @@ tvb_get_ntohieee_double(tvbuff_t *tvb, int offset)
ieee_fp_union.w[0] = tvb_get_ntohl(tvb, offset+4);
ieee_fp_union.w[1] = tvb_get_ntohl(tvb, offset);
#endif
#if defined(vax)
return get_ieee_double(dw);
#else
return ieee_fp_union.d;
#endif
}
@ -1108,17 +1250,8 @@ tvb_get_letohl(tvbuff_t *tvb, gint offset)
float
tvb_get_letohieee_float(tvbuff_t *tvb, int offset)
{
/*
* XXX - other non-IEEE boxes that can run UNIX include Crays
* and System/3x0 and zArchitecture, although later S/390
* and zArchitecture machines also support IEEE floating
* point; I don't know what the compilers used by Linux
* for S/390 and zArchitecture use - they might have chosen
* to support only machines with IEEE format, and used IEEE
* format to avoid portability headaches.
*/
#if defined(vax)
#error "Sorry, you'll have to write code to translate to VAX format"
return get_ieee_float(tvb_get_letohl(tvb, offset));
#else
union {
float f;
@ -1138,12 +1271,17 @@ double
tvb_get_letohieee_double(tvbuff_t *tvb, int offset)
{
#if defined(vax)
#error "Sorry, you'll have to write code to translate to VAX format"
union {
double d;
guint32 w[2];
guint64 dw;
} ieee_fp_union;
#else
union {
double d;
guint32 w[2];
} ieee_fp_union;
#endif
#ifdef WORDS_BIGENDIAN
ieee_fp_union.w[0] = tvb_get_letohl(tvb, offset+4);
@ -1152,6 +1290,9 @@ tvb_get_letohieee_double(tvbuff_t *tvb, int offset)
ieee_fp_union.w[0] = tvb_get_letohl(tvb, offset);
ieee_fp_union.w[1] = tvb_get_letohl(tvb, offset+4);
#endif
#if defined(vax)
return get_ieee_double(dw);
#else
return ieee_fp_union.d;
#endif
}

View File

@ -1,84 +0,0 @@
/**********************************************************************
*
* ieee-float.h
*
* Implements simple stuff to convert from IEEE float types
* to 32-bit longs
*
* (C) Ashok Narayanan, 2000
*
* $Id: ieee-float.h,v 1.2 2001/02/04 08:21:35 guy Exp $
*
* For license details, see the COPYING file with this distribution
*
**********************************************************************/
#ifndef IEEE_FLOAT_H
#define IEEE_FLOAT_H
/* Stuff for IEEE float handling */
#define IEEE_NUMBER_WIDTH 32 /* bits in number */
#define IEEE_EXP_WIDTH 8 /* bits in exponent */
#define IEEE_MANTISSA_WIDTH 23 /* IEEE_NUMBER_WIDTH - 1 - IEEE_EXP_WIDTH */
#define IEEE_SIGN_MASK 0x80000000
#define IEEE_EXPONENT_MASK 0x7F800000
#define IEEE_MANTISSA_MASK 0x007FFFFF
#define IEEE_INFINITY IEEE_EXPONENT_MASK
#define IEEE_IMPLIED_BIT (1 << IEEE_MANTISSA_WIDTH)
#define IEEE_INFINITE ((1 << IEEE_EXP_WIDTH) - 1)
#define IEEE_BIAS ((1 << (IEEE_EXP_WIDTH - 1)) - 1)
#define MINUS_INFINITY (signed)0x80000000L
#define PLUS_INFINITY 0x7FFFFFFF
static inline int ieee_float_is_zero (long number)
{
return(!(number & ~IEEE_SIGN_MASK));
}
/*
* simple conversion: ieee floating point to long
*/
static long tvb_ieee_to_long (tvbuff_t *tvb, int offset)
{
long number;
long sign;
long exponent;
long mantissa;
number = tvb_get_ntohl(tvb, offset);
sign = number & IEEE_SIGN_MASK;
exponent = number & IEEE_EXPONENT_MASK;
mantissa = number & IEEE_MANTISSA_MASK;
if (ieee_float_is_zero(number)) {
/* number is zero, unnormalized, or not-a-number */
return 0;
}
if (IEEE_INFINITY == exponent) {
/* number is positive or negative infinity, or a special value */
return (sign? MINUS_INFINITY: PLUS_INFINITY);
}
exponent = (exponent >> IEEE_MANTISSA_WIDTH) - IEEE_BIAS;
if (exponent < 0) {
/* number is between zero and one */
return 0;
}
mantissa |= IEEE_IMPLIED_BIT;
if (exponent <= IEEE_MANTISSA_WIDTH)
mantissa >>= IEEE_MANTISSA_WIDTH - exponent;
else
mantissa <<= exponent - IEEE_MANTISSA_WIDTH;
if (sign)
return -mantissa;
else
return mantissa;
}
#endif