|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* rpf.c: Conversion of float to reduced precision format values
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* Written by: Stefan Frank
|
|
Packit |
78deda |
* Richard Krampfl
|
|
Packit |
78deda |
* Ullrich Hafner
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec)
|
|
Packit |
78deda |
* Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de>
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* $Date: 2000/06/14 20:49:37 $
|
|
Packit |
78deda |
* $Author: hafner $
|
|
Packit |
78deda |
* $Revision: 5.1 $
|
|
Packit |
78deda |
* $State: Exp $
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include "pm_config.h"
|
|
Packit |
78deda |
#include "config.h"
|
|
Packit |
78deda |
#include "mallocvar.h"
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include "types.h"
|
|
Packit |
78deda |
#include "macros.h"
|
|
Packit |
78deda |
#include "error.h"
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include "misc.h"
|
|
Packit |
78deda |
#include "rpf.h"
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int const RPF_ZERO = -1;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*****************************************************************************
|
|
Packit |
78deda |
|
|
Packit |
78deda |
private code
|
|
Packit |
78deda |
|
|
Packit |
78deda |
*****************************************************************************/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
typedef struct {
|
|
Packit |
78deda |
double fraction;
|
|
Packit |
78deda |
int exponent;
|
|
Packit |
78deda |
} FracExp;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static FracExp
|
|
Packit |
78deda |
fracExpFromDouble(double const x) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
FracExp retval;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
retval.fraction = frexp(x, &retval.exponent);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return retval;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int
|
|
Packit |
78deda |
rtob (real_t const f,
|
|
Packit |
78deda |
const rpf_t * const rpfP)
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Convert real number 'f' into fixed point format.
|
|
Packit |
78deda |
* The real number in [-'range'; +'range'] is scaled to [-1 ; +1].
|
|
Packit |
78deda |
* Sign and the first 'precision' - 1 bits of the mantissa are
|
|
Packit |
78deda |
* packed into one integer.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* Return value:
|
|
Packit |
78deda |
* real value in reduced precision format
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Extract mantissa (23 Bits), exponent (8 Bits) and sign (1 Bit)
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
double const normalized = f / rpfP->range;
|
|
Packit |
78deda |
/* 'f' scaled to [-1,+1] */
|
|
Packit |
78deda |
FracExp const fracExp = fracExpFromDouble(normalized);
|
|
Packit |
78deda |
unsigned int const signedMantissa =
|
|
Packit |
78deda |
(unsigned int) (fracExp.fraction * (1<<23));
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int mantissa;
|
|
Packit |
78deda |
unsigned int sign; /* 0 for positive; 1 for negative */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (signedMantissa < 0) {
|
|
Packit |
78deda |
mantissa = -signedMantissa;
|
|
Packit |
78deda |
sign = 1;
|
|
Packit |
78deda |
} else {
|
|
Packit |
78deda |
mantissa = +signedMantissa;
|
|
Packit |
78deda |
sign = 0;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Generate reduced precision mantissa.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
if (fracExp.exponent > 0)
|
|
Packit |
78deda |
mantissa <<= fracExp.exponent;
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
mantissa >>= -fracExp.exponent;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
mantissa >>= (23 - rpfP->mantissa_bits - 1);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
mantissa += 1; /* Round last bit. */
|
|
Packit |
78deda |
mantissa >>= 1;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (mantissa == 0) /* close to zero */
|
|
Packit |
78deda |
return RPF_ZERO;
|
|
Packit |
78deda |
else if (mantissa >= (1U << rpfP->mantissa_bits)) /* overflow */
|
|
Packit |
78deda |
return sign;
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
return ((mantissa & ((1U << rpfP->mantissa_bits) - 1)) << 1) | sign;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
float
|
|
Packit |
78deda |
btor (int const binary,
|
|
Packit |
78deda |
const rpf_t * const rpfP)
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Convert value 'binary' in reduced precision format to a real value.
|
|
Packit |
78deda |
* For more information refer to function rtob() above.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* Return value:
|
|
Packit |
78deda |
* converted value
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
unsigned int mantissa;
|
|
Packit |
78deda |
float sign;
|
|
Packit |
78deda |
float f;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (binary == RPF_ZERO)
|
|
Packit |
78deda |
return 0;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (binary < 0 || binary >= 1 << (rpfP->mantissa_bits + 1))
|
|
Packit |
78deda |
error ("Reduced precision format: value %d out of range.", binary);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Restore IEEE float format:
|
|
Packit |
78deda |
* mantissa (23 Bits), exponent (8 Bits) and sign (1 Bit)
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
sign = (binary & 0x1) == 0 ? 1.0 : -1.0;
|
|
Packit |
78deda |
mantissa = (binary & ((0x1 << (rpfP->mantissa_bits + 1)) - 1)) >> 1;
|
|
Packit |
78deda |
mantissa <<= (23 - rpfP->mantissa_bits);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (mantissa == 0)
|
|
Packit |
78deda |
f = sign;
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
f = sign * (float) mantissa / 8388608;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return f * rpfP->range; /* expand [ -1 ; +1 ] to
|
|
Packit |
78deda |
[ -range ; +range ] */
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
rpf_t *
|
|
Packit |
78deda |
alloc_rpf (unsigned const mantissa,
|
|
Packit |
78deda |
fiasco_rpf_range_e const range)
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Reduced precision format constructor.
|
|
Packit |
78deda |
* Allocate memory for the rpf_t structure.
|
|
Packit |
78deda |
* Number of mantissa bits is given by `mantissa'.
|
|
Packit |
78deda |
* The range of the real values is in the interval [-`range', +`range'].
|
|
Packit |
78deda |
* In case of invalid parameters, a structure with default values is
|
|
Packit |
78deda |
* returned.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* Return value
|
|
Packit |
78deda |
* pointer to the new rpf structure
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
rpf_t * rpfP;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCVAR(rpfP);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (mantissa < 2) {
|
|
Packit |
78deda |
warning (_("Size of RPF mantissa has to be in the interval [2,8]. "
|
|
Packit |
78deda |
"Using minimum value 2.\n"));
|
|
Packit |
78deda |
rpfP->mantissa_bits = 2;
|
|
Packit |
78deda |
} else if (mantissa > 8) {
|
|
Packit |
78deda |
warning (_("Size of RPF mantissa has to be in the interval [2,8]. "
|
|
Packit |
78deda |
"Using maximum value 8.\n"));
|
|
Packit |
78deda |
rpfP->mantissa_bits = 2;
|
|
Packit |
78deda |
} else
|
|
Packit |
78deda |
rpfP->mantissa_bits = mantissa;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
switch (range) {
|
|
Packit |
78deda |
case FIASCO_RPF_RANGE_0_75:
|
|
Packit |
78deda |
rpfP->range = 0.75;
|
|
Packit |
78deda |
rpfP->range_e = range;
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case FIASCO_RPF_RANGE_1_50:
|
|
Packit |
78deda |
rpfP->range = 1.50;
|
|
Packit |
78deda |
rpfP->range_e = range;
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case FIASCO_RPF_RANGE_2_00:
|
|
Packit |
78deda |
rpfP->range = 2.00;
|
|
Packit |
78deda |
rpfP->range_e = range;
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case FIASCO_RPF_RANGE_1_00:
|
|
Packit |
78deda |
rpfP->range = 1.00;
|
|
Packit |
78deda |
rpfP->range_e = range;
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
default:
|
|
Packit |
78deda |
warning (_("Invalid RPF range specified. Using default value 1.0."));
|
|
Packit |
78deda |
rpfP->range = 1.00;
|
|
Packit |
78deda |
rpfP->range_e = FIASCO_RPF_RANGE_1_00;
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
return rpfP;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|