mirror of
https://github.com/holub/mame
synced 2025-05-31 10:01:51 +03:00
SoftFloat changes for last CL and x07 tape format from MESS (no whatsnew)
This commit is contained in:
parent
bbddee4a75
commit
70718f506e
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -1601,6 +1601,8 @@ src/lib/formats/vtech1_dsk.c svneol=native#text/plain
|
||||
src/lib/formats/vtech1_dsk.h svneol=native#text/plain
|
||||
src/lib/formats/wavfile.c svneol=native#text/plain
|
||||
src/lib/formats/wavfile.h svneol=native#text/plain
|
||||
src/lib/formats/x07_cas.c svneol=native#text/plain
|
||||
src/lib/formats/x07_cas.h svneol=native#text/plain
|
||||
src/lib/formats/x1_tap.c svneol=native#text/plain
|
||||
src/lib/formats/x1_tap.h svneol=native#text/plain
|
||||
src/lib/formats/z80ne_dsk.c svneol=native#text/plain
|
||||
@ -1800,6 +1802,7 @@ src/lib/libjpeg/libjpeg.txt svneol=native#text/plain
|
||||
src/lib/softfloat/README.txt svneol=native#text/plain
|
||||
src/lib/softfloat/fpu_constant.h svneol=native#text/plain
|
||||
src/lib/softfloat/fsincos.c svneol=native#text/plain
|
||||
src/lib/softfloat/fyl2x.c svneol=native#text/plain
|
||||
src/lib/softfloat/mamesf.h svneol=native#text/plain
|
||||
src/lib/softfloat/milieu.h svneol=native#text/plain
|
||||
src/lib/softfloat/softfloat-macros svneol=native#text/plain
|
||||
|
170
src/lib/formats/x07_cas.c
Normal file
170
src/lib/formats/x07_cas.c
Normal file
@ -0,0 +1,170 @@
|
||||
/********************************************************************
|
||||
|
||||
Support for Canon X-07 cassette images
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include "x07_cas.h"
|
||||
|
||||
#define WAVEENTRY_LOW -32768
|
||||
#define WAVEENTRY_HIGH 32767
|
||||
|
||||
#define X07_WAV_FREQUENCY 4800
|
||||
#define X07_TIMER_FREQUENCY 1200
|
||||
#define X07_BIT_LENGTH (X07_WAV_FREQUENCY/X07_TIMER_FREQUENCY)
|
||||
#define X07_HEADER_BYTES 16
|
||||
|
||||
// image size
|
||||
static int x07_image_size;
|
||||
|
||||
static int x07_put_samples(INT16 *buffer, int sample_pos, int count, int level)
|
||||
{
|
||||
if (buffer)
|
||||
{
|
||||
for (int i=0; i<count; i++)
|
||||
buffer[sample_pos + i] = level;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int x07_output_bit(INT16 *buffer, int sample_pos, UINT8 bit)
|
||||
{
|
||||
int samples = 0;
|
||||
|
||||
if (bit)
|
||||
{
|
||||
samples += x07_put_samples(buffer, sample_pos + samples, X07_BIT_LENGTH/4, WAVEENTRY_HIGH);
|
||||
samples += x07_put_samples(buffer, sample_pos + samples, X07_BIT_LENGTH/4, WAVEENTRY_LOW);
|
||||
samples += x07_put_samples(buffer, sample_pos + samples, X07_BIT_LENGTH/4, WAVEENTRY_HIGH);
|
||||
samples += x07_put_samples(buffer, sample_pos + samples, X07_BIT_LENGTH/4, WAVEENTRY_LOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
samples += x07_put_samples(buffer, sample_pos + samples, X07_BIT_LENGTH/2, WAVEENTRY_HIGH);
|
||||
samples += x07_put_samples(buffer, sample_pos + samples, X07_BIT_LENGTH/2, WAVEENTRY_LOW);
|
||||
}
|
||||
|
||||
return samples;
|
||||
}
|
||||
|
||||
static int x07_output_byte(INT16 *buffer, int sample_pos, UINT8 byte)
|
||||
{
|
||||
int samples = 0;
|
||||
|
||||
/* start */
|
||||
samples += x07_output_bit (buffer, sample_pos + samples, 0);
|
||||
|
||||
/* data */
|
||||
for (int i=0; i<8; i++)
|
||||
samples += x07_output_bit(buffer,sample_pos + samples, (byte>>i) & 0x01);
|
||||
|
||||
/* stop */
|
||||
samples += x07_output_bit (buffer, sample_pos + samples, 1);
|
||||
samples += x07_output_bit (buffer, sample_pos + samples, 1);
|
||||
samples += x07_output_bit (buffer, sample_pos + samples, 1);
|
||||
|
||||
return samples;
|
||||
}
|
||||
|
||||
static int x07_handle_cassette(INT16 *buffer, const UINT8 *bytes)
|
||||
{
|
||||
int sample_count = 0;
|
||||
int img_start = 0;
|
||||
|
||||
/* start */
|
||||
for (int i=0; i<X07_WAV_FREQUENCY; i++)
|
||||
sample_count += x07_output_bit(buffer, sample_count, 1);
|
||||
|
||||
/* header */
|
||||
if (bytes[0] == 0xd3 && bytes[1] == 0xd3 && bytes[2] == 0xd3 && bytes[3] == 0xd3)
|
||||
{
|
||||
// valid header
|
||||
for (int i=0; i<X07_HEADER_BYTES; i++)
|
||||
sample_count += x07_output_byte(buffer, sample_count, bytes[i]);
|
||||
|
||||
img_start = X07_HEADER_BYTES;
|
||||
}
|
||||
else
|
||||
{
|
||||
// remove the NULL chars at start
|
||||
while (!bytes[img_start])
|
||||
img_start++;
|
||||
|
||||
// insert 0xd3 bytes
|
||||
for (int i=0; i<10; i++)
|
||||
sample_count += x07_output_byte(buffer, sample_count, 0xd3);
|
||||
|
||||
// fake filename
|
||||
for (int i=0; i<6; i++)
|
||||
sample_count += x07_output_byte(buffer, sample_count, 'A');
|
||||
}
|
||||
|
||||
/* pause */
|
||||
for (int i=0; i<X07_WAV_FREQUENCY/16; i++)
|
||||
sample_count += x07_output_bit(buffer, sample_count, 1);
|
||||
|
||||
/* data */
|
||||
for (int i=img_start; i<x07_image_size; i++)
|
||||
sample_count += x07_output_byte(buffer, sample_count, bytes[i]);
|
||||
|
||||
/* end */
|
||||
for (int i=0; i<X07_WAV_FREQUENCY/8; i++)
|
||||
sample_count += x07_output_bit(buffer, sample_count, 1);
|
||||
|
||||
return sample_count;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
Generate samples for the tape image
|
||||
********************************************************************/
|
||||
|
||||
static int x07_cassette_fill_wave(INT16 *buffer, int length, UINT8 *bytes)
|
||||
{
|
||||
return x07_handle_cassette(buffer, bytes);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Calculate the number of samples needed for this tape image
|
||||
********************************************************************/
|
||||
|
||||
static int x07_cassette_calculate_size_in_samples(const UINT8 *bytes, int length)
|
||||
{
|
||||
x07_image_size = length;
|
||||
|
||||
return x07_handle_cassette(NULL, bytes);
|
||||
}
|
||||
|
||||
static const struct CassetteLegacyWaveFiller x07_legacy_fill_wave =
|
||||
{
|
||||
x07_cassette_fill_wave, /* fill_wave */
|
||||
-1, /* chunk_size */
|
||||
0, /* chunk_samples */
|
||||
x07_cassette_calculate_size_in_samples, /* chunk_sample_calc */
|
||||
X07_WAV_FREQUENCY, /* sample_frequency */
|
||||
0, /* header_samples */
|
||||
0 /* trailer_samples */
|
||||
};
|
||||
|
||||
static casserr_t x07_cassette_identify(cassette_image *cassette, struct CassetteOptions *opts)
|
||||
{
|
||||
return cassette_legacy_identify(cassette, opts, &x07_legacy_fill_wave);
|
||||
}
|
||||
|
||||
static casserr_t x07_cassette_load(cassette_image *cassette)
|
||||
{
|
||||
return cassette_legacy_construct(cassette, &x07_legacy_fill_wave);
|
||||
}
|
||||
|
||||
static const struct CassetteFormat x07_cassette_image_format =
|
||||
{
|
||||
"k7,lst,cas",
|
||||
x07_cassette_identify,
|
||||
x07_cassette_load,
|
||||
NULL
|
||||
};
|
||||
|
||||
CASSETTE_FORMATLIST_START(x07_cassette_formats)
|
||||
CASSETTE_FORMAT(x07_cassette_image_format)
|
||||
CASSETTE_FORMATLIST_END
|
16
src/lib/formats/x07_cas.h
Normal file
16
src/lib/formats/x07_cas.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*********************************************************************
|
||||
|
||||
x07_cas.h
|
||||
|
||||
Format code for Canon X-07 casette images
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef X07_CAS_H
|
||||
#define X07_CAS_H
|
||||
|
||||
#include "cassimg.h"
|
||||
|
||||
CASSETTE_FORMATLIST_EXTERN(x07_cassette_formats);
|
||||
|
||||
#endif /* X07_CAS_H */
|
490
src/lib/softfloat/fyl2x.c
Normal file
490
src/lib/softfloat/fyl2x.c
Normal file
@ -0,0 +1,490 @@
|
||||
/*============================================================================
|
||||
This source file is an extension to the SoftFloat IEC/IEEE Floating-point
|
||||
Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator)
|
||||
floating point emulation.
|
||||
float_raise(float_flag_invalid)
|
||||
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
|
||||
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
|
||||
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
|
||||
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
|
||||
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
|
||||
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
|
||||
INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
|
||||
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
|
||||
|
||||
Derivative works are acceptable, even for commercial purposes, so long as
|
||||
(1) the source code for the derivative work includes prominent notice that
|
||||
the work is derivative, and (2) the source code includes prominent notice with
|
||||
these four paragraphs for those parts of this code that are retained.
|
||||
=============================================================================*/
|
||||
|
||||
/*============================================================================
|
||||
* Written for Bochs (x86 achitecture simulator) by
|
||||
* Stanislav Shwartsman [sshwarts at sourceforge net]
|
||||
* Adapted for lib/softfloat in MESS by Hans Ostermeyer (03/2012)
|
||||
* ==========================================================================*/
|
||||
|
||||
#define FLOAT128
|
||||
|
||||
#define USE_estimateDiv128To64
|
||||
#include "mamesf.h"
|
||||
#include "softfloat.h"
|
||||
//#include "softfloat-specialize"
|
||||
#include "fpu_constant.h"
|
||||
|
||||
// FIXME:
|
||||
#define float_flag_denormal float_flag_invalid
|
||||
|
||||
static const floatx80 floatx80_log10_2 = packFloatx80(0, 0x3ffd, U64(0x9a209a84fbcff798));
|
||||
static const floatx80 floatx80_ln_2 = packFloatx80(0, 0x3ffe, U64(0xb17217f7d1cf79ac));
|
||||
static const floatx80 floatx80_one = packFloatx80(0, 0x3fff, U64(0x8000000000000000));
|
||||
static const floatx80 floatx80_default_nan = packFloatx80(0, 0xffff, U64(0xffffffffffffffff));
|
||||
|
||||
#define packFloat_128(zHi, zLo) {(zHi), (zLo)}
|
||||
#define PACK_FLOAT_128(hi,lo) packFloat_128(LIT64(hi),LIT64(lo))
|
||||
|
||||
#define EXP_BIAS 0x3FFF
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the fraction bits of the extended double-precision floating-point
|
||||
| value `a'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE bits64 extractFloatx80Frac( floatx80 a )
|
||||
{
|
||||
|
||||
return a.low;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the exponent bits of the extended double-precision floating-point
|
||||
| value `a'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE int32 extractFloatx80Exp( floatx80 a )
|
||||
{
|
||||
|
||||
return a.high & 0x7FFF;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the sign bit of the extended double-precision floating-point value
|
||||
| `a'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE flag extractFloatx80Sign( floatx80 a )
|
||||
{
|
||||
|
||||
return a.high>>15;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Takes extended double-precision floating-point NaN `a' and returns the
|
||||
| appropriate NaN result. If `a' is a signaling NaN, the invalid exception
|
||||
| is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE floatx80 propagateFloatx80NaNOneArg(floatx80 a)
|
||||
{
|
||||
if (floatx80_is_signaling_nan(a))
|
||||
float_raise(float_flag_invalid);
|
||||
|
||||
a.low |= U64(0xC000000000000000);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Normalizes the subnormal extended double-precision floating-point value
|
||||
| represented by the denormalized significand `aSig'. The normalized exponent
|
||||
| and significand are stored at the locations pointed to by `zExpPtr' and
|
||||
| `zSigPtr', respectively.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE void normalizeFloatx80Subnormal(UINT64 aSig, INT32 *zExpPtr, UINT64 *zSigPtr)
|
||||
{
|
||||
int shiftCount = countLeadingZeros64(aSig);
|
||||
*zSigPtr = aSig<<shiftCount;
|
||||
*zExpPtr = 1 - shiftCount;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the extended double-precision floating-point value `a' is a
|
||||
| NaN; otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE int floatx80_is_nan(floatx80 a)
|
||||
{
|
||||
return ((a.high & 0x7FFF) == 0x7FFF) && (INT64) (a.low<<1);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Takes two extended double-precision floating-point values `a' and `b', one
|
||||
| of which is a NaN, and returns the appropriate NaN result. If either `a' or
|
||||
| `b' is a signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b)
|
||||
{
|
||||
int aIsNaN = floatx80_is_nan(a);
|
||||
int aIsSignalingNaN = floatx80_is_signaling_nan(a);
|
||||
int bIsNaN = floatx80_is_nan(b);
|
||||
int bIsSignalingNaN = floatx80_is_signaling_nan(b);
|
||||
a.low |= U64(0xC000000000000000);
|
||||
b.low |= U64(0xC000000000000000);
|
||||
if (aIsSignalingNaN | bIsSignalingNaN) float_raise(float_flag_invalid);
|
||||
if (aIsSignalingNaN) {
|
||||
if (bIsSignalingNaN) goto returnLargerSignificand;
|
||||
return bIsNaN ? b : a;
|
||||
}
|
||||
else if (aIsNaN) {
|
||||
if (bIsSignalingNaN | ! bIsNaN) return a;
|
||||
returnLargerSignificand:
|
||||
if (a.low < b.low) return b;
|
||||
if (b.low < a.low) return a;
|
||||
return (a.high < b.high) ? a : b;
|
||||
}
|
||||
else {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
static const float128 float128_one =
|
||||
packFloat_128(U64(0x3fff000000000000), U64(0x0000000000000000));
|
||||
static const float128 float128_two =
|
||||
packFloat_128(U64(0x4000000000000000), U64(0x0000000000000000));
|
||||
|
||||
static const float128 float128_ln2inv2 =
|
||||
packFloat_128(U64(0x400071547652b82f), U64(0xe1777d0ffda0d23a));
|
||||
|
||||
#define SQRT2_HALF_SIG U64(0xb504f333f9de6484)
|
||||
|
||||
extern float128 OddPoly(float128 x, float128 *arr, unsigned n);
|
||||
|
||||
#define L2_ARR_SIZE 9
|
||||
|
||||
static float128 ln_arr[L2_ARR_SIZE] =
|
||||
{
|
||||
PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */
|
||||
PACK_FLOAT_128(0x3ffd555555555555, 0x5555555555555555), /* 3 */
|
||||
PACK_FLOAT_128(0x3ffc999999999999, 0x999999999999999a), /* 5 */
|
||||
PACK_FLOAT_128(0x3ffc249249249249, 0x2492492492492492), /* 7 */
|
||||
PACK_FLOAT_128(0x3ffbc71c71c71c71, 0xc71c71c71c71c71c), /* 9 */
|
||||
PACK_FLOAT_128(0x3ffb745d1745d174, 0x5d1745d1745d1746), /* 11 */
|
||||
PACK_FLOAT_128(0x3ffb3b13b13b13b1, 0x3b13b13b13b13b14), /* 13 */
|
||||
PACK_FLOAT_128(0x3ffb111111111111, 0x1111111111111111), /* 15 */
|
||||
PACK_FLOAT_128(0x3ffae1e1e1e1e1e1, 0xe1e1e1e1e1e1e1e2) /* 17 */
|
||||
};
|
||||
|
||||
static float128 poly_ln(float128 x1)
|
||||
{
|
||||
/*
|
||||
//
|
||||
// 3 5 7 9 11 13 15
|
||||
// 1+u u u u u u u u
|
||||
// 1/2 ln --- ~ u + --- + --- + --- + --- + ---- + ---- + ---- =
|
||||
// 1-u 3 5 7 9 11 13 15
|
||||
//
|
||||
// 2 4 6 8 10 12 14
|
||||
// u u u u u u u
|
||||
// = u * [ 1 + --- + --- + --- + --- + ---- + ---- + ---- ] =
|
||||
// 3 5 7 9 11 13 15
|
||||
//
|
||||
// 3 3
|
||||
// -- 4k -- 4k+2
|
||||
// p(u) = > C * u q(u) = > C * u
|
||||
// -- 2k -- 2k+1
|
||||
// k=0 k=0
|
||||
//
|
||||
// 1+u 2
|
||||
// 1/2 ln --- ~ u * [ p(u) + u * q(u) ]
|
||||
// 1-u
|
||||
//
|
||||
*/
|
||||
return OddPoly(x1, ln_arr, L2_ARR_SIZE);
|
||||
}
|
||||
|
||||
/* required sqrt(2)/2 < x < sqrt(2) */
|
||||
static float128 poly_l2(float128 x)
|
||||
{
|
||||
/* using float128 for approximation */
|
||||
float128 x_p1 = float128_add(x, float128_one);
|
||||
float128 x_m1 = float128_sub(x, float128_one);
|
||||
x = float128_div(x_m1, x_p1);
|
||||
x = poly_ln(x);
|
||||
x = float128_mul(x, float128_ln2inv2);
|
||||
return x;
|
||||
}
|
||||
|
||||
static float128 poly_l2p1(float128 x)
|
||||
{
|
||||
/* using float128 for approximation */
|
||||
float128 x_p2 = float128_add(x, float128_two);
|
||||
x = float128_div(x, x_p2);
|
||||
x = poly_ln(x);
|
||||
x = float128_mul(x, float128_ln2inv2);
|
||||
return x;
|
||||
}
|
||||
|
||||
// =================================================
|
||||
// FYL2X Compute y * log (x)
|
||||
// 2
|
||||
// =================================================
|
||||
|
||||
//
|
||||
// Uses the following identities:
|
||||
//
|
||||
// 1. ----------------------------------------------------------
|
||||
// ln(x)
|
||||
// log (x) = -------, ln (x*y) = ln(x) + ln(y)
|
||||
// 2 ln(2)
|
||||
//
|
||||
// 2. ----------------------------------------------------------
|
||||
// 1+u x-1
|
||||
// ln (x) = ln -----, when u = -----
|
||||
// 1-u x+1
|
||||
//
|
||||
// 3. ----------------------------------------------------------
|
||||
// 3 5 7 2n+1
|
||||
// 1+u u u u u
|
||||
// ln ----- = 2 [ u + --- + --- + --- + ... + ------ + ... ]
|
||||
// 1-u 3 5 7 2n+1
|
||||
//
|
||||
|
||||
static floatx80 fyl2x(floatx80 a, floatx80 b)
|
||||
{
|
||||
UINT64 aSig = extractFloatx80Frac(a);
|
||||
INT32 aExp = extractFloatx80Exp(a);
|
||||
int aSign = extractFloatx80Sign(a);
|
||||
UINT64 bSig = extractFloatx80Frac(b);
|
||||
INT32 bExp = extractFloatx80Exp(b);
|
||||
int bSign = extractFloatx80Sign(b);
|
||||
|
||||
int zSign = bSign ^ 1;
|
||||
|
||||
if (aExp == 0x7FFF) {
|
||||
if ((UINT64) (aSig<<1)
|
||||
|| ((bExp == 0x7FFF) && (UINT64) (bSig<<1)))
|
||||
{
|
||||
return propagateFloatx80NaN(a, b);
|
||||
}
|
||||
if (aSign)
|
||||
{
|
||||
invalid:
|
||||
float_raise(float_flag_invalid);
|
||||
return floatx80_default_nan;
|
||||
}
|
||||
else {
|
||||
if (bExp == 0) {
|
||||
if (bSig == 0) goto invalid;
|
||||
float_raise(float_flag_denormal);
|
||||
}
|
||||
return packFloatx80(bSign, 0x7FFF, U64(0x8000000000000000));
|
||||
}
|
||||
}
|
||||
if (bExp == 0x7FFF)
|
||||
{
|
||||
if ((UINT64) (bSig<<1)) return propagateFloatx80NaN(a, b);
|
||||
if (aSign && (UINT64)(aExp | aSig)) goto invalid;
|
||||
if (aSig && (aExp == 0))
|
||||
float_raise(float_flag_denormal);
|
||||
if (aExp < 0x3FFF) {
|
||||
return packFloatx80(zSign, 0x7FFF, U64(0x8000000000000000));
|
||||
}
|
||||
if (aExp == 0x3FFF && ((UINT64) (aSig<<1) == 0)) goto invalid;
|
||||
return packFloatx80(bSign, 0x7FFF, U64(0x8000000000000000));
|
||||
}
|
||||
if (aExp == 0) {
|
||||
if (aSig == 0) {
|
||||
if ((bExp | bSig) == 0) goto invalid;
|
||||
float_raise(float_flag_divbyzero);
|
||||
return packFloatx80(zSign, 0x7FFF, U64(0x8000000000000000));
|
||||
}
|
||||
if (aSign) goto invalid;
|
||||
float_raise(float_flag_denormal);
|
||||
normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
|
||||
}
|
||||
if (aSign) goto invalid;
|
||||
if (bExp == 0) {
|
||||
if (bSig == 0) {
|
||||
if (aExp < 0x3FFF) return packFloatx80(zSign, 0, 0);
|
||||
return packFloatx80(bSign, 0, 0);
|
||||
}
|
||||
float_raise(float_flag_denormal);
|
||||
normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
|
||||
}
|
||||
if (aExp == 0x3FFF && ((UINT64) (aSig<<1) == 0))
|
||||
return packFloatx80(bSign, 0, 0);
|
||||
|
||||
float_raise(float_flag_inexact);
|
||||
|
||||
int ExpDiff = aExp - 0x3FFF;
|
||||
aExp = 0;
|
||||
if (aSig >= SQRT2_HALF_SIG) {
|
||||
ExpDiff++;
|
||||
aExp--;
|
||||
}
|
||||
|
||||
/* ******************************** */
|
||||
/* using float128 for approximation */
|
||||
/* ******************************** */
|
||||
|
||||
UINT64 zSig0, zSig1;
|
||||
shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1);
|
||||
float128 x = packFloat128(0, aExp+0x3FFF, zSig0, zSig1);
|
||||
x = poly_l2(x);
|
||||
x = float128_add(x, int64_to_float128((INT64) ExpDiff));
|
||||
return floatx80_mul(b, float128_to_floatx80(x));
|
||||
}
|
||||
|
||||
// =================================================
|
||||
// FYL2XP1 Compute y * log (x + 1)
|
||||
// 2
|
||||
// =================================================
|
||||
|
||||
//
|
||||
// Uses the following identities:
|
||||
//
|
||||
// 1. ----------------------------------------------------------
|
||||
// ln(x)
|
||||
// log (x) = -------
|
||||
// 2 ln(2)
|
||||
//
|
||||
// 2. ----------------------------------------------------------
|
||||
// 1+u x
|
||||
// ln (x+1) = ln -----, when u = -----
|
||||
// 1-u x+2
|
||||
//
|
||||
// 3. ----------------------------------------------------------
|
||||
// 3 5 7 2n+1
|
||||
// 1+u u u u u
|
||||
// ln ----- = 2 [ u + --- + --- + --- + ... + ------ + ... ]
|
||||
// 1-u 3 5 7 2n+1
|
||||
//
|
||||
|
||||
floatx80 fyl2xp1(floatx80 a, floatx80 b)
|
||||
{
|
||||
INT32 aExp, bExp;
|
||||
UINT64 aSig, bSig, zSig0, zSig1, zSig2;
|
||||
int aSign, bSign;
|
||||
|
||||
aSig = extractFloatx80Frac(a);
|
||||
aExp = extractFloatx80Exp(a);
|
||||
aSign = extractFloatx80Sign(a);
|
||||
bSig = extractFloatx80Frac(b);
|
||||
bExp = extractFloatx80Exp(b);
|
||||
bSign = extractFloatx80Sign(b);
|
||||
int zSign = aSign ^ bSign;
|
||||
|
||||
if (aExp == 0x7FFF) {
|
||||
if ((UINT64) (aSig<<1)
|
||||
|| ((bExp == 0x7FFF) && (UINT64) (bSig<<1)))
|
||||
{
|
||||
return propagateFloatx80NaN(a, b);
|
||||
}
|
||||
if (aSign)
|
||||
{
|
||||
invalid:
|
||||
float_raise(float_flag_invalid);
|
||||
return floatx80_default_nan;
|
||||
}
|
||||
else {
|
||||
if (bExp == 0) {
|
||||
if (bSig == 0) goto invalid;
|
||||
float_raise(float_flag_denormal);
|
||||
}
|
||||
return packFloatx80(bSign, 0x7FFF, U64(0x8000000000000000));
|
||||
}
|
||||
}
|
||||
if (bExp == 0x7FFF)
|
||||
{
|
||||
if ((UINT64) (bSig<<1))
|
||||
return propagateFloatx80NaN(a, b);
|
||||
|
||||
if (aExp == 0) {
|
||||
if (aSig == 0) goto invalid;
|
||||
float_raise(float_flag_denormal);
|
||||
}
|
||||
|
||||
return packFloatx80(zSign, 0x7FFF, U64(0x8000000000000000));
|
||||
}
|
||||
if (aExp == 0) {
|
||||
if (aSig == 0) {
|
||||
if (bSig && (bExp == 0)) float_raise(float_flag_denormal);
|
||||
return packFloatx80(zSign, 0, 0);
|
||||
}
|
||||
float_raise(float_flag_denormal);
|
||||
normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
|
||||
}
|
||||
if (bExp == 0) {
|
||||
if (bSig == 0) return packFloatx80(zSign, 0, 0);
|
||||
float_raise(float_flag_denormal);
|
||||
normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
|
||||
}
|
||||
|
||||
float_raise(float_flag_inexact);
|
||||
|
||||
if (aSign && aExp >= 0x3FFF)
|
||||
return a;
|
||||
|
||||
if (aExp >= 0x3FFC) // big argument
|
||||
{
|
||||
return fyl2x(floatx80_add(a, floatx80_one), b);
|
||||
}
|
||||
|
||||
// handle tiny argument
|
||||
if (aExp < EXP_BIAS-70)
|
||||
{
|
||||
// first order approximation, return (a*b)/ln(2)
|
||||
INT32 zExp = aExp + FLOAT_LN2INV_EXP - 0x3FFE;
|
||||
|
||||
mul128By64To192(FLOAT_LN2INV_HI, FLOAT_LN2INV_LO, aSig, &zSig0, &zSig1, &zSig2);
|
||||
if (0 < (INT64) zSig0) {
|
||||
shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1);
|
||||
--zExp;
|
||||
}
|
||||
|
||||
zExp = zExp + bExp - 0x3FFE;
|
||||
mul128By64To192(zSig0, zSig1, bSig, &zSig0, &zSig1, &zSig2);
|
||||
if (0 < (INT64) zSig0) {
|
||||
shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1);
|
||||
--zExp;
|
||||
}
|
||||
|
||||
return
|
||||
roundAndPackFloatx80(80, aSign ^ bSign, zExp, zSig0, zSig1);
|
||||
}
|
||||
|
||||
/* ******************************** */
|
||||
/* using float128 for approximation */
|
||||
/* ******************************** */
|
||||
|
||||
shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1);
|
||||
float128 x = packFloat128(aSign, aExp, zSig0, zSig1);
|
||||
x = poly_l2p1(x);
|
||||
return floatx80_mul(b, float128_to_floatx80(x));
|
||||
}
|
||||
|
||||
floatx80 floatx80_flognp1(floatx80 a)
|
||||
{
|
||||
return fyl2xp1(a, floatx80_ln_2);
|
||||
}
|
||||
|
||||
floatx80 floatx80_flogn(floatx80 a)
|
||||
{
|
||||
return fyl2x(a, floatx80_ln_2);
|
||||
}
|
||||
|
||||
floatx80 floatx80_flog2(floatx80 a)
|
||||
{
|
||||
return fyl2x(a, floatx80_one);
|
||||
}
|
||||
|
||||
floatx80 floatx80_flog10(floatx80 a)
|
||||
{
|
||||
return fyl2x(a, floatx80_log10_2);
|
||||
}
|
@ -524,7 +524,9 @@ static void
|
||||
| Floating-Point Arithmetic.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static floatx80
|
||||
// roundAndPackFloatx80 is now also used in fyl2x.c
|
||||
|
||||
/* static */ floatx80
|
||||
roundAndPackFloatx80(
|
||||
int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
|
||||
)
|
||||
|
@ -246,6 +246,14 @@ int floatx80_fsin(floatx80 &a);
|
||||
int floatx80_fcos(floatx80 &a);
|
||||
int floatx80_ftan(floatx80 &a);
|
||||
|
||||
floatx80 floatx80_flognp1(floatx80 a);
|
||||
floatx80 floatx80_flogn(floatx80 a);
|
||||
floatx80 floatx80_flog2(floatx80 a);
|
||||
floatx80 floatx80_flog10(floatx80 a);
|
||||
|
||||
// roundAndPackFloatx80 used to be in softfloat-round-pack, is now in softfloat.c
|
||||
floatx80 roundAndPackFloatx80(int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FLOAT128
|
||||
|
Loading…
Reference in New Issue
Block a user