--- a/QuadFloat.st Sun Nov 24 16:16:50 2019 +0100
+++ b/QuadFloat.st Sun Nov 24 16:17:26 2019 +0100
@@ -1,5 +1,3 @@
-"{ Encoding: utf8 }"
-
"{ Package: 'stx:libbasic2' }"
"{ NameSpace: Smalltalk }"
@@ -14,2169 +12,95 @@
!QuadFloat primitiveDefinitions!
%{
-#if __POINTER_SIZE__ == 8
-# define SUPPORT_QUADFLOAT
-#endif
+#define SUPPORT_QUADFLOAT
-#if defined(__MSBFIRST__) || defined(__MSB_FIRST__) || defined(MSBFIRST)
-# undef LITTLEENDIAN
-#else
-# define LITTLEENDIAN
-#endif
-
-#ifdef SUPPORT_QUADFLOAT
-# include <stdint.h>
+#include <math.h>
-// The following code is adapted from the Softfloat-3e package,
-// which includes the following license/copyright statement:
-//
-// License for Berkeley SoftFloat Release 3e
-//
-// John R. Hauser
-// 2018 January 20
-//
-// The following applies to the whole of SoftFloat Release 3e as well as to
-// each source file individually.
-//
-// Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the
-// University of California. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions, and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions, and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the University nor the names of its contributors
-// may be used to endorse or promote products derived from this software
-// without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
-// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
-// DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
-// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-
-/*----------------------------------------------------------------------------
-| Software floating-point underflow tininess-detection mode.
-*----------------------------------------------------------------------------*/
-enum {
- softfloat_tininess_beforeRounding = 0,
- softfloat_tininess_afterRounding = 1
-};
+extern float128_t STX_addq(float128_t, float128_t, int);
+extern float128_t STX_mulq(float128_t, float128_t);
+extern float128_t STX_divq(float128_t, float128_t);
+extern float128_t STX_negq(float128_t);
+extern float128_t STX_absq(float128_t);
+extern float128_t STX_floorq(float128_t);
+extern float128_t STX_frexpq(float128_t, int*);
+extern float128_t STX_ceilq(float128_t);
+extern float128_t STX_logq(float128_t);
+extern float128_t STX_log10q(float128_t);
+extern float128_t STX_log2q(float128_t);
+extern float128_t STX_expq(float128_t);
+extern float128_t STX_sinq(float128_t);
+extern float128_t STX_cosq(float128_t);
+extern float128_t STX_tanq(float128_t);
+extern float128_t STX_sinhq(float128_t);
+extern float128_t STX_coshq(float128_t);
+extern float128_t STX_tanhq(float128_t);
+extern float128_t STX_asinq(float128_t);
+extern float128_t STX_acosq(float128_t);
+extern float128_t STX_atanq(float128_t);
+extern float128_t STX_asinhq(float128_t);
+extern float128_t STX_acoshq(float128_t);
+extern float128_t STX_atanhq(float128_t);
+extern float128_t STX_qZero;
+extern float128_t STX_dbltoq(double);
+extern float128_t STX_inttoq(long);
+extern double STX_qtodbl(float128_t);
+extern int STX_isNanq(float128_t*);
+extern int STX_prcmpq(float128_t*, float128_t*);
-/*----------------------------------------------------------------------------
-| Software floating-point exception flags.
-*----------------------------------------------------------------------------*/
-enum {
- softfloat_flag_inexact = 1,
- softfloat_flag_underflow = 2,
- softfloat_flag_overflow = 4,
- softfloat_flag_infinite = 8,
- softfloat_flag_invalid = 16
-};
-/*----------------------------------------------------------------------------
-| Software floating-point rounding mode. (Mode "odd" is supported only if
-| SoftFloat is compiled with macro 'SOFTFLOAT_ROUND_ODD' defined.)
-*----------------------------------------------------------------------------*/
-enum {
- softfloat_round_near_even = 0,
- softfloat_round_minMag = 1,
- softfloat_round_min = 2,
- softfloat_round_max = 3,
- softfloat_round_near_maxMag = 4,
- softfloat_round_odd = 6
-};
-#define init_detectTininess softfloat_tininess_afterRounding
+#define STX_isfiniteq(q) (!STX_isNanq(&(q)) && !STX_isInfq(&(q)))
+#define STX_eqq(x1, x2) (STX_prcmpq (&(x1), &(x2)) == 0)
+#define STX_neqq(x1, x2) (STX_prcmpq (&(x1), &(x2)) != 0)
+#define STX_gtq(x1, x2) (STX_prcmpq (&(x1), &(x2)) > 0)
+#define STX_geq(x1, x2) (STX_prcmpq (&(x1), &(x2)) >= 0)
+#define STX_ltq(x1, x2) (STX_prcmpq (&(x1), &(x2)) < 0)
+#define STX_leq(x1, x2) (STX_prcmpq (&(x1), &(x2)) <= 0)
-typedef unsigned char bool;
-typedef double float64_t;
-
-#if defined(LITTLEENDIAN)
-struct uint128 { uint64_t v0, v64; };
-struct uint64_extra { uint64_t extra, v; };
-struct uint128_extra { uint64_t extra; struct uint128 v; };
-struct extFloat80M { uint64_t signif; uint16_t signExp; };
-#else
-struct uint128 { uint64_t v64, v0; };
-struct uint64_extra { uint64_t v, extra; };
-struct uint128_extra { struct uint128 v; uint64_t extra; };
-struct extFloat80M { uint16_t signExp; uint64_t signif; };
-#endif
+#ifdef __win32__
+/*
+ * no finite(x) ?
+ * no isnan(x) ?
+ */
+# ifndef isnan
+# define isnan(x) \
+ ((((unsigned int *)(&x))[0] == 0x00000000) && \
+ (((unsigned int *)(&x))[1] == 0xFFF80000))
+# endif
-union ui64_f64 { uint64_t ui; float64_t f; };
-union ui128_f128 { struct uint128 ui; float128_t f; };
-struct exp32_sig128 { int_fast32_t exp; struct uint128 sig; };
-
-typedef struct extFloat80M extFloat80_t;
+# ifndef isPositiveInfinity
+# define isPositiveInfinity(x) \
+ ((((unsigned int *)(&x))[0] == 0x00000000) && \
+ (((unsigned int *)(&x))[1] == 0x7FF00000))
+# endif
-/*----------------------------------------------------------------------------
-| The bit pattern for a default generated 128-bit floating-point NaN.
-*----------------------------------------------------------------------------*/
-#define defaultNaNF128UI96_32 0xFFFF8000
-#define defaultNaNF128UI64_32 0
-#define defaultNaNF128UI32_32 0
-#define defaultNaNF128UI0_32 0
-
-// #define defaultNaNF128UI64_64 UINT64_C( 0x7FFF800000000000 )
-// #define defaultNaNF128UI0_64 UINT64_C( 0 )
+# ifndef isNegativeInfinity
+# define isNegativeInfinity(x) \
+ ((((unsigned int *)(&x))[0] == 0x00000000) && \
+ (((unsigned int *)(&x))[1] == 0xFFF00000))
+# endif
-/*----------------------------------------------------------------------------
-| The bit pattern for a default generated 128-bit floating-point +INF.
-*----------------------------------------------------------------------------*/
-#define defaultPInfF128UI96_32 0x7FFF0000
-#define defaultPInfF128UI64_32 0
-#define defaultPInfF128UI32_32 0
-#define defaultPInfF128UI0_32 0
-/*----------------------------------------------------------------------------
-| The bit pattern for a default generated 128-bit floating-point -INF.
-*----------------------------------------------------------------------------*/
-#define defaultNInfF128UI96_32 0xFFFF0000
-#define defaultNInfF128UI64_32 0
-#define defaultNInfF128UI32_32 0
-#define defaultNInfF128UI0_32 0
+# ifndef isinf
+# define isinf(x) \
+ ((((unsigned int *)(&x))[0] == 0x00000000) && \
+ ((((unsigned int *)(&x))[1] & 0x7FF00000) == 0x7FF00000))
+# endif
-struct commonNaN {
- bool sign;
-#ifdef LITTLEENDIAN
- uint64_t v0, v64;
-#else
- uint64_t v64, v0;
+# ifndef isfinite
+# define isfinite(x) (!isinf(x) && !isnan(x))
+# endif
+
+#else // not win32
#endif
-};
-struct exp16_sig64 { int_fast16_t exp; uint_fast64_t sig; };
-
-#endif // SUPPORT_QUADFLOAT
%}
! !
!QuadFloat primitiveVariables!
%{
-#ifdef SUPPORT_QUADFLOAT
-
-uint_fast8_t softfloat_exceptionFlags;
-uint_fast8_t softfloat_roundingMode = softfloat_round_near_even;
-uint_fast8_t softfloat_detectTininess = init_detectTininess;
-uint_fast8_t softfloat_exceptionFlags = 0;
-
-const uint_least8_t softfloat_countLeadingZeros8[256] = {
- 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-#endif // SUPPORT_QUADFLOAT
-
%}
! !
!QuadFloat primitiveFunctions!
%{
-#ifdef SUPPORT_QUADFLOAT
-
-#if defined(LITTLEENDIAN) || defined(__LSBFIRST__)
-#define wordIncr 1
-#define indexWord( total, n ) (n)
-#define indexWordHi( total ) ((total) - 1)
-#define indexWordLo( total ) 0
-#define indexMultiword( total, m, n ) (n)
-#define indexMultiwordHi( total, n ) ((total) - (n))
-#define indexMultiwordLo( total, n ) 0
-#define indexMultiwordHiBut( total, n ) (n)
-#define indexMultiwordLoBut( total, n ) 0
-#define INIT_UINTM4( v3, v2, v1, v0 ) { v0, v1, v2, v3 }
-#else
-#define wordIncr -1
-#define indexWord( total, n ) ((total) - 1 - (n))
-#define indexWordHi( total ) 0
-#define indexWordLo( total ) ((total) - 1)
-#define indexMultiword( total, m, n ) ((total) - 1 - (m))
-#define indexMultiwordHi( total, n ) 0
-#define indexMultiwordLo( total, n ) ((total) - (n))
-#define indexMultiwordHiBut( total, n ) 0
-#define indexMultiwordLoBut( total, n ) (n)
-#define INIT_UINTM4( v3, v2, v1, v0 ) { v3, v2, v1, v0 }
-#endif
-
-#define signF64UI( a ) ((bool) ((uint64_t) (a)>>63))
-#define expF64UI( a ) ((int_fast16_t) ((a)>>52) & 0x7FF)
-#define fracF64UI( a ) ((a) & UINT64_C( 0x000FFFFFFFFFFFFF ))
-#define softfloat_f64UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & UINT64_C( 0x0008000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
-
-#define signF128UI64( a64 ) ((bool) ((uint64_t) (a64)>>63))
-#define expF128UI64( a64 ) ((int_fast32_t) ((a64)>>48) & 0x7FFF)
-#define fracF128UI64( a64 ) ((a64) & UINT64_C( 0x0000FFFFFFFFFFFF ))
-#define packToF128UI64( sign, exp, sig64 ) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<48) + (sig64))
-
-#define signF128UI96( a96 ) ((bool) ((uint32_t) (a96)>>31))
-#define expF128UI96( a96 ) ((int32_t) ((a96)>>16) & 0x7FFF)
-#define fracF128UI96( a96 ) ((a96) & 0x0000FFFF)
-#define packToF128UI96( sign, exp, sig96 ) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<16) + (sig96))
-
-#define isNaNF128UI( a64, a0 ) (((~(a64) & UINT64_C( 0x7FFF000000000000 )) == 0) && (a0 || ((a64) & UINT64_C( 0x0000FFFFFFFFFFFF ))))
-#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF ))))
-#define softfloat_approxRecip32_1( a ) ((uint32_t) (UINT64_C( 0x7FFFFFFFFFFFFFFF ) / (uint32_t) (a)))
-#define isInfF128UI( a64, a0 ) (((a64) & UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000))
-
-#define signExtF80UI64( a64 ) ((bool) ((uint16_t) (a64)>>15))
-#define expExtF80UI64( a64 ) ((a64) & 0x7FFF)
-#define packToExtF80UI64( sign, exp ) ((uint_fast16_t) (sign)<<15 | (exp))
-
-#define isNaNExtF80UI( a64, a0 ) ((((a64) & 0x7FFF) == 0x7FFF) && ((a0) & UINT64_C( 0x7FFFFFFFFFFFFFFF )))
-
-/*----------------------------------------------------------------------------
-| This function or macro is the same as 'softfloat_shortShiftLeftM' with
-| 'size_words' = 5 (N = 160).
-*----------------------------------------------------------------------------*/
-#define softfloat_shortShiftLeft160M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 5, aPtr, dist, zPtr )
-/*----------------------------------------------------------------------------
-| This function or macro is the same as 'softfloat_shiftRightJamM' with
-| 'size_words' = 5 (N = 160).
-*----------------------------------------------------------------------------*/
-#define softfloat_shiftRightJam160M( aPtr, dist, zPtr ) softfloat_shiftRightJamM( 5, aPtr, dist, zPtr )
-/*----------------------------------------------------------------------------
-| This function or macro is the same as 'softfloat_shortShiftLeftM' with
-| 'size_words' = 4 (N = 128).
-*----------------------------------------------------------------------------*/
-#define softfloat_shortShiftLeft128M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 4, aPtr, dist, zPtr )
-/*----------------------------------------------------------------------------
-| This function or macro is the same as 'softfloat_shortShiftLeftM' with
-| 'size_words' = 3 (N = 96).
-*----------------------------------------------------------------------------*/
-#define softfloat_shortShiftLeft96M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 3, aPtr, dist, zPtr )
-
-static inline void
-softfloat_raiseFlags( uint_fast8_t flags ) {
- softfloat_exceptionFlags |= flags;
-}
-
-#if 1
-static inline void
-softfloat_commonNaNToF128M( uint32_t *zWPtr )
-{
- zWPtr[indexWord( 4, 3 )] = defaultNaNF128UI96_32;
- zWPtr[indexWord( 4, 2 )] = defaultNaNF128UI64_32;
- zWPtr[indexWord( 4, 1 )] = defaultNaNF128UI32_32;
- zWPtr[indexWord( 4, 0 )] = defaultNaNF128UI0_32;
-}
-#else
-# define softfloat_commonNaNToF128M( zWPtr ) \
-{ \
- (zWPtr)[indexWord( 4, 3 )] = defaultNaNF128UI96_32; \
- (zWPtr)[indexWord( 4, 2 )] = defaultNaNF128UI64_32; \
- (zWPtr)[indexWord( 4, 1 )] = defaultNaNF128UI32_32; \
- (zWPtr)[indexWord( 4, 0 )] = defaultNaNF128UI0_32; \
-}
-#endif
-
-/*----------------------------------------------------------------------------
-| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
-| has the bit pattern of an 80-bit extended floating-point NaN, converts
-| this NaN to the common NaN form, and stores the resulting common NaN at the
-| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
-| exception is raised.
-*----------------------------------------------------------------------------*/
-#define softfloat_extF80UIToCommonNaN( uiA64, uiA0, zPtr ) if ( ! ((uiA0) & UINT64_C( 0x4000000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
-
-static inline void
-softfloat_invalidF128M( uint32_t *zWPtr ) {
- softfloat_raiseFlags( softfloat_flag_invalid );
- softfloat_commonNaNToF128M( zWPtr );
-}
-
-static bool
-f128M_isSignalingNaN( const float128_t *aPtr )
-{
- const uint32_t *aWPtr;
- uint32_t uiA96;
-
- aWPtr = (const uint32_t *) aPtr;
- uiA96 = aWPtr[indexWordHi( 4 )];
- if ( (uiA96 & 0x7FFF8000) != 0x7FFF0000 ) return 0;
- return
- ((uiA96 & 0x00007FFF) != 0)
- || ((aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )]
- | aWPtr[indexWord( 4, 0 )])
- != 0);
-}
-
-static void
-softfloat_shortShiftRightJamM(
- uint_fast8_t size_words,
- const uint32_t *aPtr,
- uint_fast8_t dist,
- uint32_t *zPtr
- )
-{
- uint_fast8_t uNegDist;
- unsigned int index, lastIndex;
- uint32_t partWordZ, wordA;
-
- uNegDist = -dist;
- index = indexWordLo( size_words );
- lastIndex = indexWordHi( size_words );
- wordA = aPtr[index];
- partWordZ = wordA>>dist;
- if ( partWordZ<<dist != wordA ) partWordZ |= 1;
- while ( index != lastIndex ) {
- wordA = aPtr[index + wordIncr];
- zPtr[index] = wordA<<(uNegDist & 31) | partWordZ;
- index += wordIncr;
- partWordZ = wordA>>dist;
- }
- zPtr[index] = partWordZ;
-
-}
-
-void
-softfloat_shiftRightJamM(
- uint_fast8_t size_words,
- const uint32_t *aPtr,
- uint32_t dist,
- uint32_t *zPtr
- )
-{
- uint32_t wordJam, wordDist, *ptr;
- uint_fast8_t i, innerDist;
-
- wordJam = 0;
- wordDist = dist>>5;
- if ( wordDist ) {
- if ( size_words < wordDist ) wordDist = size_words;
- ptr = (uint32_t *) (aPtr + indexMultiwordLo( size_words, wordDist ));
- i = wordDist;
- do {
- wordJam = *ptr++;
- if ( wordJam ) break;
- --i;
- } while ( i );
- ptr = zPtr;
- }
- if ( wordDist < size_words ) {
- aPtr += indexMultiwordHiBut( size_words, wordDist );
- innerDist = dist & 31;
- if ( innerDist ) {
- softfloat_shortShiftRightJamM(
- size_words - wordDist,
- aPtr,
- innerDist,
- (zPtr + indexMultiwordLoBut( size_words, wordDist ))
- );
- if ( ! wordDist ) goto wordJam;
- } else {
- aPtr += indexWordLo( size_words - wordDist );
- ptr = zPtr + indexWordLo( size_words );
- for ( i = size_words - wordDist; i; --i ) {
- *ptr = *aPtr;
- aPtr += wordIncr;
- ptr += wordIncr;
- }
- }
- ptr = zPtr + indexMultiwordHi( size_words, wordDist );
- }
- do {
- *ptr++ = 0;
- --wordDist;
- } while ( wordDist );
- wordJam:
- if ( wordJam ) zPtr[indexWordLo( size_words )] |= 1;
-
-}
-
-void
- softfloat_shortShiftLeftM(
- uint_fast8_t size_words,
- const uint32_t *aPtr,
- uint_fast8_t dist,
- uint32_t *zPtr
- )
-{
- uint_fast8_t uNegDist;
- unsigned int index, lastIndex;
- uint32_t partWordZ, wordA;
-
- uNegDist = -dist;
- index = indexWordHi( size_words );
- lastIndex = indexWordLo( size_words );
- partWordZ = aPtr[index]<<dist;
- while ( index != lastIndex ) {
- wordA = aPtr[index - wordIncr];
- zPtr[index] = partWordZ | wordA>>(uNegDist & 31);
- index -= wordIncr;
- partWordZ = wordA<<dist;
- }
- zPtr[index] = partWordZ;
-}
-
-static void
-softfloat_shiftLeftM(
- uint_fast8_t size_words,
- const uint32_t *aPtr,
- uint32_t dist,
- uint32_t *zPtr
- )
-{
- uint32_t wordDist;
- uint_fast8_t innerDist;
- uint32_t *destPtr;
- uint_fast8_t i;
-
- wordDist = dist>>5;
- if ( wordDist < size_words ) {
- aPtr += indexMultiwordLoBut( size_words, wordDist );
- innerDist = dist & 31;
- if ( innerDist ) {
- softfloat_shortShiftLeftM(
- size_words - wordDist,
- aPtr,
- innerDist,
- zPtr + indexMultiwordHiBut( size_words, wordDist )
- );
- if ( ! wordDist ) return;
- } else {
- aPtr += indexWordHi( size_words - wordDist );
- destPtr = zPtr + indexWordHi( size_words );
- for ( i = size_words - wordDist; i; --i ) {
- *destPtr = *aPtr;
- aPtr -= wordIncr;
- destPtr -= wordIncr;
- }
- }
- zPtr += indexMultiwordLo( size_words, wordDist );
- } else {
- wordDist = size_words;
- }
- do {
- *zPtr++ = 0;
- --wordDist;
- } while ( wordDist );
-}
-
-/*----------------------------------------------------------------------------
-| This function or macro is the same as 'softfloat_shiftLeftM' with
-| 'size_words' = 4 (N = 128).
-*----------------------------------------------------------------------------*/
-#define softfloat_shiftLeft128M( aPtr, dist, zPtr ) softfloat_shiftLeftM( 4, aPtr, dist, zPtr )
-
-bool
-softfloat_isNaNF128M( const uint32_t *aWPtr )
-{
- uint32_t uiA96;
-
- uiA96 = aWPtr[indexWordHi( 4 )];
- if ( (~uiA96 & 0x7FFF0000) != 0 ) return 0;
- return
- ((uiA96 & 0x0000FFFF) != 0)
- || ((aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )]
- | aWPtr[indexWord( 4, 0 )])
- != 0);
-}
-
-static inline uint_fast8_t
-softfloat_countLeadingZeros32( uint32_t a ) {
- return a ? __builtin_clz( a ) : 32;
-}
-
-static inline bool
-softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ){
- return (a64 == b64) && (a0 == b0);
-}
-
-static inline bool
-softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ){
- return (a64 < b64) || ((a64 == b64) && (a0 < b0));
-}
-
-static inline bool
-softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ){
- return (a64 < b64) || ((a64 == b64) && (a0 <= b0));
-}
-
-void
-softfloat_propagateNaNF128M(
- const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr )
-{
- bool isSigNaNA;
- const uint32_t *ptr;
- bool isSigNaNB;
- uint32_t uiA96, uiB96, wordMagA, wordMagB;
-
- isSigNaNA = f128M_isSignalingNaN( (const float128_t *) aWPtr );
- ptr = aWPtr;
- if ( ! bWPtr ) {
- if ( isSigNaNA ) softfloat_raiseFlags( softfloat_flag_invalid );
- goto copy;
- }
- isSigNaNB = f128M_isSignalingNaN( (const float128_t *) bWPtr );
- if ( isSigNaNA | isSigNaNB ) {
- softfloat_raiseFlags( softfloat_flag_invalid );
- if ( isSigNaNA ) {
- if ( isSigNaNB ) goto returnLargerUIMag;
- if ( softfloat_isNaNF128M( bWPtr ) ) goto copyB;
- goto copy;
- } else {
- if ( softfloat_isNaNF128M( aWPtr ) ) goto copy;
- goto copyB;
- }
- }
- returnLargerUIMag:
- uiA96 = aWPtr[indexWordHi( 4 )];
- uiB96 = bWPtr[indexWordHi( 4 )];
- wordMagA = uiA96 & 0x7FFFFFFF;
- wordMagB = uiB96 & 0x7FFFFFFF;
- if ( wordMagA < wordMagB ) goto copyB;
- if ( wordMagB < wordMagA ) goto copy;
- wordMagA = aWPtr[indexWord( 4, 2 )];
- wordMagB = bWPtr[indexWord( 4, 2 )];
- if ( wordMagA < wordMagB ) goto copyB;
- if ( wordMagB < wordMagA ) goto copy;
- wordMagA = aWPtr[indexWord( 4, 1 )];
- wordMagB = bWPtr[indexWord( 4, 1 )];
- if ( wordMagA < wordMagB ) goto copyB;
- if ( wordMagB < wordMagA ) goto copy;
- wordMagA = aWPtr[indexWord( 4, 0 )];
- wordMagB = bWPtr[indexWord( 4, 0 )];
- if ( wordMagA < wordMagB ) goto copyB;
- if ( wordMagB < wordMagA ) goto copy;
- if ( uiA96 < uiB96 ) goto copy;
- copyB:
- ptr = bWPtr;
- copy:
- zWPtr[indexWordHi( 4 )] = ptr[indexWordHi( 4 )] | 0x00008000;
- zWPtr[indexWord( 4, 2 )] = ptr[indexWord( 4, 2 )];
- zWPtr[indexWord( 4, 1 )] = ptr[indexWord( 4, 1 )];
- zWPtr[indexWord( 4, 0 )] = ptr[indexWord( 4, 0 )];
-}
-
-static inline uint_fast8_t
-softfloat_countLeadingZeros64( uint64_t a )
-{
- uint_fast8_t count;
- uint32_t a32;
-
- count = 0;
- a32 = a>>32;
- if ( ! a32 ) {
- count = 32;
- a32 = a;
- }
- /*------------------------------------------------------------------------
- | From here, result is current count + count leading zeros of `a32'.
- *------------------------------------------------------------------------*/
- if ( a32 < 0x10000 ) {
- count += 16;
- a32 <<= 16;
- }
- if ( a32 < 0x1000000 ) {
- count += 8;
- a32 <<= 8;
- }
- count += softfloat_countLeadingZeros8[a32>>24];
- return count;
-}
-
-static inline struct exp16_sig64
-softfloat_normSubnormalF64Sig( uint_fast64_t sig )
-{
- int_fast8_t shiftDist;
- struct exp16_sig64 z;
-
- shiftDist = softfloat_countLeadingZeros64( sig ) - 11;
- z.exp = 1 - shiftDist;
- z.sig = sig<<shiftDist;
- return z;
-}
-
-static inline struct uint128_extra
-softfloat_shiftRightJam128Extra(
- uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t dist )
-{
- uint_fast8_t u8NegDist;
- struct uint128_extra z;
-
- u8NegDist = -dist;
- if ( dist < 64 ) {
- z.v.v64 = a64>>dist;
- z.v.v0 = a64<<(u8NegDist & 63) | a0>>dist;
- z.extra = a0<<(u8NegDist & 63);
- } else {
- z.v.v64 = 0;
- if ( dist == 64 ) {
- z.v.v0 = a64;
- z.extra = a0;
- } else {
- extra |= a0;
- if ( dist < 128 ) {
- z.v.v0 = a64>>(dist & 63);
- z.extra = a64<<(u8NegDist & 63);
- } else {
- z.v.v0 = 0;
- z.extra = (dist == 128) ? a64 : (a64 != 0);
- }
- }
- }
- z.extra |= (extra != 0);
- return z;
-}
-
-static inline struct uint128_extra
-softfloat_shortShiftRightJam128Extra(
- uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist )
-{
- uint_fast8_t negDist = -dist;
- struct uint128_extra z;
- z.v.v64 = a64>>dist;
- z.v.v0 = a64<<(negDist & 63) | a0>>dist;
- z.extra = a0<<(negDist & 63) | (extra != 0);
- return z;
-}
-
-static inline struct uint128
-softfloat_shiftRightJam128( uint64_t a64, uint64_t a0, uint_fast32_t dist )
-{
- uint_fast8_t u8NegDist;
- struct uint128 z;
-
- if ( dist < 64 ) {
- u8NegDist = -dist;
- z.v64 = a64>>dist;
- z.v0 =
- a64<<(u8NegDist & 63) | a0>>dist
- | ((uint64_t) (a0<<(u8NegDist & 63)) != 0);
- } else {
- z.v64 = 0;
- z.v0 =
- (dist < 127)
- ? a64>>(dist & 63)
- | (((a64 & (((uint_fast64_t) 1<<(dist & 63)) - 1)) | a0)
- != 0)
- : ((a64 | a0) != 0);
- }
- return z;
-}
-
-static inline struct uint128
-softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist )
-{
- struct uint128 z;
- z.v64 = a64<<dist | a0>>(-dist & 63);
- z.v0 = a0<<dist;
- return z;
-}
-
-static int_fast8_t
-softfloat_compare128M( const uint32_t *aPtr, const uint32_t *bPtr )
-{
- unsigned int index, lastIndex;
- uint32_t wordA, wordB;
-
- index = indexWordHi( 4 );
- lastIndex = indexWordLo( 4 );
- for (;;) {
- wordA = aPtr[index];
- wordB = bPtr[index];
- if ( wordA != wordB ) return (wordA < wordB) ? -1 : 1;
- if ( index == lastIndex ) break;
- index -= wordIncr;
- }
- return 0;
-}
-
-static void
-softfloat_roundPackMToF128M(
- bool sign, int32_t exp, uint32_t *extSigPtr, uint32_t *zWPtr )
-{
- uint_fast8_t roundingMode;
- bool roundNearEven;
- uint32_t sigExtra;
- bool doIncrement, isTiny;
- static const uint32_t maxSig[4] =
- INIT_UINTM4( 0x0001FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF );
- uint32_t ui, uj;
-
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- roundingMode = softfloat_roundingMode;
- roundNearEven = (roundingMode == softfloat_round_near_even);
- sigExtra = extSigPtr[indexWordLo( 5 )];
- doIncrement = (0x80000000 <= sigExtra);
- if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
- doIncrement =
- (roundingMode
- == (sign ? softfloat_round_min : softfloat_round_max))
- && sigExtra;
- }
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- if ( 0x7FFD <= (uint32_t) exp ) {
- if ( exp < 0 ) {
- /*----------------------------------------------------------------
- *----------------------------------------------------------------*/
- isTiny =
- (softfloat_detectTininess
- == softfloat_tininess_beforeRounding)
- || (exp < -1)
- || ! doIncrement
- || (softfloat_compare128M(
- extSigPtr + indexMultiwordHi( 5, 4 ), maxSig )
- < 0);
- softfloat_shiftRightJam160M( extSigPtr, -exp, extSigPtr );
- exp = 0;
- sigExtra = extSigPtr[indexWordLo( 5 )];
- if ( isTiny && sigExtra ) {
- softfloat_raiseFlags( softfloat_flag_underflow );
- }
- doIncrement = (0x80000000 <= sigExtra);
- if (
- ! roundNearEven
- && (roundingMode != softfloat_round_near_maxMag)
- ) {
- doIncrement =
- (roundingMode
- == (sign ? softfloat_round_min : softfloat_round_max))
- && sigExtra;
- }
- } else if (
- (0x7FFD < exp)
- || ((exp == 0x7FFD) && doIncrement
- && (softfloat_compare128M(
- extSigPtr + indexMultiwordHi( 5, 4 ), maxSig )
- == 0))
- ) {
- /*----------------------------------------------------------------
- *----------------------------------------------------------------*/
- softfloat_raiseFlags(
- softfloat_flag_overflow | softfloat_flag_inexact );
- if (
- roundNearEven
- || (roundingMode == softfloat_round_near_maxMag)
- || (roundingMode
- == (sign ? softfloat_round_min : softfloat_round_max))
- ) {
- ui = packToF128UI96( sign, 0x7FFF, 0 );
- uj = 0;
- } else {
- ui = packToF128UI96( sign, 0x7FFE, 0x0000FFFF );
- uj = 0xFFFFFFFF;
- }
- zWPtr[indexWordHi( 4 )] = ui;
- zWPtr[indexWord( 4, 2 )] = uj;
- zWPtr[indexWord( 4, 1 )] = uj;
- zWPtr[indexWord( 4, 0 )] = uj;
- return;
- }
- }
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- uj = extSigPtr[indexWord( 5, 1 )];
- if ( sigExtra ) {
- softfloat_exceptionFlags |= softfloat_flag_inexact;
-#ifdef SOFTFLOAT_ROUND_ODD
- if ( roundingMode == softfloat_round_odd ) {
- uj |= 1;
- goto noIncrementPackReturn;
- }
-#endif
- }
- if ( doIncrement ) {
- ++uj;
- if ( uj ) {
- if ( ! (sigExtra & 0x7FFFFFFF) && roundNearEven ) uj &= ~1;
- zWPtr[indexWord( 4, 2 )] = extSigPtr[indexWord( 5, 3 )];
- zWPtr[indexWord( 4, 1 )] = extSigPtr[indexWord( 5, 2 )];
- zWPtr[indexWord( 4, 0 )] = uj;
- ui = extSigPtr[indexWordHi( 5 )];
- } else {
- zWPtr[indexWord( 4, 0 )] = uj;
- ui = extSigPtr[indexWord( 5, 2 )] + 1;
- zWPtr[indexWord( 4, 1 )] = ui;
- uj = extSigPtr[indexWord( 5, 3 )];
- if ( ui ) {
- zWPtr[indexWord( 4, 2 )] = uj;
- ui = extSigPtr[indexWordHi( 5 )];
- } else {
- ++uj;
- zWPtr[indexWord( 4, 2 )] = uj;
- ui = extSigPtr[indexWordHi( 5 )];
- if ( ! uj ) ++ui;
- }
- }
- } else {
- noIncrementPackReturn:
- zWPtr[indexWord( 4, 0 )] = uj;
- ui = extSigPtr[indexWord( 5, 2 )];
- zWPtr[indexWord( 4, 1 )] = ui;
- uj |= ui;
- ui = extSigPtr[indexWord( 5, 3 )];
- zWPtr[indexWord( 4, 2 )] = ui;
- uj |= ui;
- ui = extSigPtr[indexWordHi( 5 )];
- uj |= ui;
- if ( ! uj ) exp = 0;
- }
- zWPtr[indexWordHi( 4 )] = packToF128UI96( sign, exp, ui );
-}
-
-static int
-softfloat_shiftNormSigF128M(
- const uint32_t *wPtr, uint_fast8_t shiftDist, uint32_t *sigPtr )
-{
- uint32_t wordSig;
- int32_t exp;
- uint32_t leadingBit;
-
- wordSig = wPtr[indexWordHi( 4 )];
- exp = expF128UI96( wordSig );
- if ( exp ) {
- softfloat_shortShiftLeft128M( wPtr, shiftDist, sigPtr );
- leadingBit = 0x00010000<<shiftDist;
- sigPtr[indexWordHi( 4 )] =
- (sigPtr[indexWordHi( 4 )] & (leadingBit - 1)) | leadingBit;
- } else {
- exp = 16;
- wordSig &= 0x7FFFFFFF;
- if ( ! wordSig ) {
- exp = -16;
- wordSig = wPtr[indexWord( 4, 2 )];
- if ( ! wordSig ) {
- exp = -48;
- wordSig = wPtr[indexWord( 4, 1 )];
- if ( ! wordSig ) {
- wordSig = wPtr[indexWord( 4, 0 )];
- if ( ! wordSig ) return -128;
- exp = -80;
- }
- }
- }
- exp -= softfloat_countLeadingZeros32( wordSig );
- softfloat_shiftLeft128M( wPtr, 1 - exp + shiftDist, sigPtr );
- }
- return exp;
-}
-
-bool
-softfloat_tryPropagateNaNF128M(
- const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr )
-{
-
- if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) {
- softfloat_propagateNaNF128M( aWPtr, bWPtr, zWPtr );
- return 1;
- }
- return 0;
-}
-
-static inline struct uint128
-softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
-{
- struct uint128 z;
- z.v0 = a0 + b0;
- z.v64 = a64 + b64 + (z.v0 < a0);
- return z;
-}
-
-static inline struct uint128
-softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
-{
- struct uint128 z;
- z.v0 = a0 - b0;
- z.v64 = a64 - b64;
- z.v64 -= (a0 < b0);
- return z;
-}
-
-static inline struct uint128
-softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b )
-{
- union { unsigned __int128 ui; struct uint128 s; } uZ;
- uZ.ui = ((unsigned __int128) a64<<64 | a0) * b;
- return uZ.s;
-}
-
-static void
-softfloat_mul128MTo256M(
- const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr )
-{
- uint32_t *lastZPtr, wordB;
- uint64_t dwordProd;
- uint32_t wordZ;
- uint_fast8_t carry;
-
- bPtr += indexWordLo( 4 );
- lastZPtr = zPtr + indexMultiwordHi( 8, 5 );
- zPtr += indexMultiwordLo( 8, 5 );
- wordB = *bPtr;
- dwordProd = (uint64_t) aPtr[indexWord( 4, 0 )] * wordB;
- zPtr[indexWord( 5, 0 )] = dwordProd;
- dwordProd = (uint64_t) aPtr[indexWord( 4, 1 )] * wordB + (dwordProd>>32);
- zPtr[indexWord( 5, 1 )] = dwordProd;
- dwordProd = (uint64_t) aPtr[indexWord( 4, 2 )] * wordB + (dwordProd>>32);
- zPtr[indexWord( 5, 2 )] = dwordProd;
- dwordProd = (uint64_t) aPtr[indexWord( 4, 3 )] * wordB + (dwordProd>>32);
- zPtr[indexWord( 5, 3 )] = dwordProd;
- zPtr[indexWord( 5, 4 )] = dwordProd>>32;
- do {
- bPtr += wordIncr;
- zPtr += wordIncr;
- wordB = *bPtr;
- dwordProd = (uint64_t) aPtr[indexWord( 4, 0 )] * wordB;
- wordZ = zPtr[indexWord( 5, 0 )] + (uint32_t) dwordProd;
- zPtr[indexWord( 5, 0 )] = wordZ;
- carry = (wordZ < (uint32_t) dwordProd);
- dwordProd =
- (uint64_t) aPtr[indexWord( 4, 1 )] * wordB + (dwordProd>>32);
- wordZ = zPtr[indexWord( 5, 1 )] + (uint32_t) dwordProd + carry;
- zPtr[indexWord( 5, 1 )] = wordZ;
- if ( wordZ != (uint32_t) dwordProd ) {
- carry = (wordZ < (uint32_t) dwordProd);
- }
- dwordProd =
- (uint64_t) aPtr[indexWord( 4, 2 )] * wordB + (dwordProd>>32);
- wordZ = zPtr[indexWord( 5, 2 )] + (uint32_t) dwordProd + carry;
- zPtr[indexWord( 5, 2 )] = wordZ;
- if ( wordZ != (uint32_t) dwordProd ) {
- carry = (wordZ < (uint32_t) dwordProd);
- }
- dwordProd =
- (uint64_t) aPtr[indexWord( 4, 3 )] * wordB + (dwordProd>>32);
- wordZ = zPtr[indexWord( 5, 3 )] + (uint32_t) dwordProd + carry;
- zPtr[indexWord( 5, 3 )] = wordZ;
- if ( wordZ != (uint32_t) dwordProd ) {
- carry = (wordZ < (uint32_t) dwordProd);
- }
- zPtr[indexWord( 5, 4 )] = (dwordProd>>32) + carry;
- } while ( zPtr != lastZPtr );
-}
-
-float128_t
-softfloat_roundPackToF128(
- bool sign,
- int_fast32_t exp,
- uint_fast64_t sig64,
- uint_fast64_t sig0,
- uint_fast64_t sigExtra
- )
-{
- uint_fast8_t roundingMode;
- bool roundNearEven, doIncrement, isTiny;
- struct uint128_extra sig128Extra;
- uint_fast64_t uiZ64, uiZ0;
- struct uint128 sig128;
- union ui128_f128 uZ;
-
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- roundingMode = softfloat_roundingMode;
- roundNearEven = (roundingMode == softfloat_round_near_even);
- doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
- if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
- doIncrement =
- (roundingMode
- == (sign ? softfloat_round_min : softfloat_round_max))
- && sigExtra;
- }
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- if ( 0x7FFD <= (uint32_t) exp ) {
- if ( exp < 0 ) {
- /*----------------------------------------------------------------
- *----------------------------------------------------------------*/
- isTiny =
- (softfloat_detectTininess
- == softfloat_tininess_beforeRounding)
- || (exp < -1)
- || ! doIncrement
- || softfloat_lt128(
- sig64,
- sig0,
- UINT64_C( 0x0001FFFFFFFFFFFF ),
- UINT64_C( 0xFFFFFFFFFFFFFFFF )
- );
- sig128Extra =
- softfloat_shiftRightJam128Extra( sig64, sig0, sigExtra, -exp );
- sig64 = sig128Extra.v.v64;
- sig0 = sig128Extra.v.v0;
- sigExtra = sig128Extra.extra;
- exp = 0;
- if ( isTiny && sigExtra ) {
- softfloat_raiseFlags( softfloat_flag_underflow );
- }
- doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
- if (
- ! roundNearEven
- && (roundingMode != softfloat_round_near_maxMag)
- ) {
- doIncrement =
- (roundingMode
- == (sign ? softfloat_round_min : softfloat_round_max))
- && sigExtra;
- }
- } else if (
- (0x7FFD < exp)
- || ((exp == 0x7FFD)
- && softfloat_eq128(
- sig64,
- sig0,
- UINT64_C( 0x0001FFFFFFFFFFFF ),
- UINT64_C( 0xFFFFFFFFFFFFFFFF )
- )
- && doIncrement)
- ) {
- /*----------------------------------------------------------------
- *----------------------------------------------------------------*/
- softfloat_raiseFlags(
- softfloat_flag_overflow | softfloat_flag_inexact );
- if (
- roundNearEven
- || (roundingMode == softfloat_round_near_maxMag)
- || (roundingMode
- == (sign ? softfloat_round_min : softfloat_round_max))
- ) {
- uiZ64 = packToF128UI64( sign, 0x7FFF, 0 );
- uiZ0 = 0;
- } else {
- uiZ64 = packToF128UI64( sign, 0x7FFE, UINT64_C( 0x0000FFFFFFFFFFFF ) );
- uiZ0 = UINT64_C( 0xFFFFFFFFFFFFFFFF );
- }
- goto uiZ;
- }
- }
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- if ( sigExtra ) {
- softfloat_exceptionFlags |= softfloat_flag_inexact;
-#ifdef SOFTFLOAT_ROUND_ODD
- if ( roundingMode == softfloat_round_odd ) {
- sig0 |= 1;
- goto packReturn;
- }
-#endif
- }
- if ( doIncrement ) {
- sig128 = softfloat_add128( sig64, sig0, 0, 1 );
- sig64 = sig128.v64;
- sig0 =
- sig128.v0
- & ~(uint64_t)
- (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
- & roundNearEven);
- } else {
- if ( ! (sig64 | sig0) ) exp = 0;
- }
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- packReturn:
- uiZ64 = packToF128UI64( sign, exp, sig64 );
- uiZ0 = sig0;
- uiZ:
- uZ.ui.v64 = uiZ64;
- uZ.ui.v0 = uiZ0;
- return uZ.f;
-}
-
-float128_t
-softfloat_normRoundPackToF128(
- bool sign, int_fast32_t exp, uint_fast64_t sig64, uint_fast64_t sig0 )
-{
- int_fast8_t shiftDist;
- struct uint128 sig128;
- union ui128_f128 uZ;
- uint_fast64_t sigExtra;
- struct uint128_extra sig128Extra;
-
- if ( ! sig64 ) {
- exp -= 64;
- sig64 = sig0;
- sig0 = 0;
- }
- shiftDist = softfloat_countLeadingZeros64( sig64 ) - 15;
- exp -= shiftDist;
- if ( 0 <= shiftDist ) {
- if ( shiftDist ) {
- sig128 = softfloat_shortShiftLeft128( sig64, sig0, shiftDist );
- sig64 = sig128.v64;
- sig0 = sig128.v0;
- }
- if ( (uint32_t) exp < 0x7FFD ) {
- uZ.ui.v64 = packToF128UI64( sign, sig64 | sig0 ? exp : 0, sig64 );
- uZ.ui.v0 = sig0;
- return uZ.f;
- }
- sigExtra = 0;
- } else {
- sig128Extra =
- softfloat_shortShiftRightJam128Extra( sig64, sig0, 0, -shiftDist );
- sig64 = sig128Extra.v.v64;
- sig0 = sig128Extra.v.v0;
- sigExtra = sig128Extra.extra;
- }
- return softfloat_roundPackToF128( sign, exp, sig64, sig0, sigExtra );
-}
-
-struct exp32_sig128
-softfloat_normSubnormalF128Sig( uint_fast64_t sig64, uint_fast64_t sig0 )
-{
- int_fast8_t shiftDist;
- struct exp32_sig128 z;
-
- if ( ! sig64 ) {
- shiftDist = softfloat_countLeadingZeros64( sig0 ) - 15;
- z.exp = -63 - shiftDist;
- if ( shiftDist < 0 ) {
- z.sig.v64 = sig0>>-shiftDist;
- z.sig.v0 = sig0<<(shiftDist & 63);
- } else {
- z.sig.v64 = sig0<<shiftDist;
- z.sig.v0 = 0;
- }
- } else {
- shiftDist = softfloat_countLeadingZeros64( sig64 ) - 15;
- z.exp = 1 - shiftDist;
- z.sig = softfloat_shortShiftLeft128( sig64, sig0, shiftDist );
- }
- return z;
-}
-
-struct uint128
-softfloat_propagateNaNF128UI(
- uint_fast64_t uiA64,
- uint_fast64_t uiA0,
- uint_fast64_t uiB64,
- uint_fast64_t uiB0
- )
-{
- bool isSigNaNA, isSigNaNB;
- uint_fast64_t uiNonsigA64, uiNonsigB64, uiMagA64, uiMagB64;
- struct uint128 uiZ;
-
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- isSigNaNA = softfloat_isSigNaNF128UI( uiA64, uiA0 );
- isSigNaNB = softfloat_isSigNaNF128UI( uiB64, uiB0 );
- /*------------------------------------------------------------------------
- | Make NaNs non-signaling.
- *------------------------------------------------------------------------*/
- uiNonsigA64 = uiA64 | UINT64_C( 0x0000800000000000 );
- uiNonsigB64 = uiB64 | UINT64_C( 0x0000800000000000 );
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- if ( isSigNaNA | isSigNaNB ) {
- softfloat_raiseFlags( softfloat_flag_invalid );
- if ( isSigNaNA ) {
- if ( isSigNaNB ) goto returnLargerMag;
- if ( isNaNF128UI( uiB64, uiB0 ) ) goto returnB;
- goto returnA;
- } else {
- if ( isNaNF128UI( uiA64, uiA0 ) ) goto returnA;
- goto returnB;
- }
- }
- returnLargerMag:
- uiMagA64 = uiA64 & UINT64_C( 0x7FFFFFFFFFFFFFFF );
- uiMagB64 = uiB64 & UINT64_C( 0x7FFFFFFFFFFFFFFF );
- if ( uiMagA64 < uiMagB64 ) goto returnB;
- if ( uiMagB64 < uiMagA64 ) goto returnA;
- if ( uiA0 < uiB0 ) goto returnB;
- if ( uiB0 < uiA0 ) goto returnA;
- if ( uiNonsigA64 < uiNonsigB64 ) goto returnA;
- returnB:
- uiZ.v64 = uiNonsigB64;
- uiZ.v0 = uiB0;
- return uiZ;
- returnA:
- uiZ.v64 = uiNonsigA64;
- uiZ.v0 = uiA0;
- return uiZ;
-
-}
-
-#if __POINTER_SIZE__ == 4
-
-void
-i32_to_f128M( int32_t a, float128_t *zPtr )
-{
- uint32_t *zWPtr;
- uint32_t uiZ96, uiZ64;
- bool sign;
- uint32_t absA;
- int_fast8_t shiftDist;
- uint64_t normAbsA;
-
- zWPtr = (uint32_t *) zPtr;
- uiZ96 = 0;
- uiZ64 = 0;
- if ( a ) {
- sign = (a < 0);
- absA = sign ? -(uint32_t) a : (uint32_t) a;
- shiftDist = softfloat_countLeadingZeros32( absA ) + 17;
- normAbsA = (uint64_t) absA<<shiftDist;
- uiZ96 = packToF128UI96( sign, 0x402E - shiftDist, normAbsA>>32 );
- uiZ64 = normAbsA;
- }
- zWPtr[indexWord( 4, 3 )] = uiZ96;
- zWPtr[indexWord( 4, 2 )] = uiZ64;
- zWPtr[indexWord( 4, 1 )] = 0;
- zWPtr[indexWord( 4, 0 )] = 0;
-}
-
-#else
-
-void
-i64_to_f128M( int64_t a, float128_t *zPtr )
-{
- uint32_t *zWPtr;
- uint32_t uiZ96, uiZ64;
- bool sign;
- uint64_t absA;
- uint_fast8_t shiftDist;
- uint32_t *ptr;
-
- zWPtr = (uint32_t *) zPtr;
- uiZ96 = 0;
- uiZ64 = 0;
- zWPtr[indexWord( 4, 1 )] = 0;
- zWPtr[indexWord( 4, 0 )] = 0;
- if ( a ) {
- sign = (a < 0);
- absA = sign ? -(uint64_t) a : (uint64_t) a;
- shiftDist = softfloat_countLeadingZeros64( absA ) + 17;
- if ( shiftDist < 32 ) {
- ptr = zWPtr + indexMultiwordHi( 4, 3 );
- ptr[indexWord( 3, 2 )] = 0;
- ptr[indexWord( 3, 1 )] = absA>>32;
- ptr[indexWord( 3, 0 )] = absA;
- softfloat_shortShiftLeft96M( ptr, shiftDist, ptr );
- ptr[indexWordHi( 3 )] =
- packToF128UI96(
- sign, 0x404E - shiftDist, ptr[indexWordHi( 3 )] );
- return;
- }
- absA <<= shiftDist - 32;
- uiZ96 = packToF128UI96( sign, 0x404E - shiftDist, absA>>32 );
- uiZ64 = absA;
- }
- zWPtr[indexWord( 4, 3 )] = uiZ96;
- zWPtr[indexWord( 4, 2 )] = uiZ64;
-}
-
-#endif
-
-void
-f64_to_f128M( float64_t a, float128_t *zPtr )
-{
- uint32_t *zWPtr;
- union ui64_f64 uA;
- uint64_t uiA;
- bool sign;
- int_fast16_t exp;
- uint64_t frac;
- struct commonNaN commonNaN;
- uint32_t uiZ96;
- struct exp16_sig64 normExpSig;
-
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- zWPtr = (uint32_t *) zPtr;
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- uA.f = a;
- uiA = uA.ui;
- sign = signF64UI( uiA );
- exp = expF64UI( uiA );
- frac = fracF64UI( uiA );
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- zWPtr[indexWord( 4, 0 )] = 0;
- if ( exp == 0x7FF ) {
- if ( frac ) {
- // NaN
- softfloat_commonNaNToF128M( zWPtr );
- return;
- }
- uiZ96 = packToF128UI96( sign, 0x7FFF, 0 );
- goto uiZ;
- }
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- if ( ! exp ) {
- if ( ! frac ) {
- uiZ96 = packToF128UI96( sign, 0, 0 );
- goto uiZ;
- }
- normExpSig = softfloat_normSubnormalF64Sig( frac );
- exp = normExpSig.exp - 1;
- frac = normExpSig.sig;
- }
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- zWPtr[indexWord( 4, 1 )] = (uint32_t) frac<<28;
- frac >>= 4;
- zWPtr[indexWordHi( 4 )] = packToF128UI96( sign, exp + 0x3C00, frac>>32 );
- zWPtr[indexWord( 4, 2 )] = frac;
- return;
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- uiZ:
- zWPtr[indexWord( 4, 3 )] = uiZ96;
- zWPtr[indexWord( 4, 2 )] = 0;
- zWPtr[indexWord( 4, 1 )] = 0;
-
-}
-
-float128_t
-extF80_to_f128( extFloat80_t a )
-{
- union { struct extFloat80M s; extFloat80_t f; } uA;
- uint_fast16_t uiA64;
- uint_fast64_t uiA0;
- uint_fast16_t exp;
- uint_fast64_t frac;
- struct commonNaN commonNaN;
- struct uint128 uiZ;
- bool sign;
- struct uint128 frac128;
- union ui128_f128 uZ;
-
- uA.f = a;
- uiA64 = uA.s.signExp;
- uiA0 = uA.s.signif;
- exp = expExtF80UI64( uiA64 );
- frac = uiA0 & UINT64_C( 0x7FFFFFFFFFFFFFFF );
- if ( (exp == 0x7FFF) && frac ) {
- softfloat_extF80UIToCommonNaN( uiA64, uiA0, &commonNaN );
- softfloat_commonNaNToF128M( (uint32_t*) &uiZ );
- } else {
- sign = signExtF80UI64( uiA64 );
- frac128 = softfloat_shortShiftLeft128( 0, frac, 49 );
- uiZ.v64 = packToF128UI64( sign, exp, frac128.v64 );
- uiZ.v0 = frac128.v0;
- }
- uZ.ui = uiZ;
- return uZ.f;
-
-}
-
-static float128_t
-softfloat_addMagsF128(
- uint64_t uiA64,
- uint64_t uiA0,
- uint64_t uiB64,
- uint64_t uiB0,
- bool signZ
- )
-{
- int32_t expA;
- struct uint128 sigA;
- int32_t expB;
- struct uint128 sigB;
- int32_t expDiff;
- struct uint128 uiZ, sigZ;
- int32_t expZ;
- uint64_t sigZExtra;
- struct uint128_extra sig128Extra;
- union ui128_f128 uZ;
-
- expA = expF128UI64( uiA64 );
- sigA.v64 = fracF128UI64( uiA64 );
- sigA.v0 = uiA0;
- expB = expF128UI64( uiB64 );
- sigB.v64 = fracF128UI64( uiB64 );
- sigB.v0 = uiB0;
- expDiff = expA - expB;
- if ( ! expDiff ) {
- if ( expA == 0x7FFF ) {
- if ( sigA.v64 | sigA.v0 | sigB.v64 | sigB.v0 ) goto propagateNaN;
- uiZ.v64 = uiA64;
- uiZ.v0 = uiA0;
- goto uiZ;
- }
- sigZ = softfloat_add128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 );
- if ( ! expA ) {
- uiZ.v64 = packToF128UI64( signZ, 0, sigZ.v64 );
- uiZ.v0 = sigZ.v0;
- goto uiZ;
- }
- expZ = expA;
- sigZ.v64 |= UINT64_C( 0x0002000000000000 );
- sigZExtra = 0;
- goto shiftRight1;
- }
- if ( expDiff < 0 ) {
- if ( expB == 0x7FFF ) {
- if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
- uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 );
- uiZ.v0 = 0;
- goto uiZ;
- }
- expZ = expB;
- if ( expA ) {
- sigA.v64 |= UINT64_C( 0x0001000000000000 );
- } else {
- ++expDiff;
- sigZExtra = 0;
- if ( ! expDiff ) goto newlyAligned;
- }
- sig128Extra =
- softfloat_shiftRightJam128Extra( sigA.v64, sigA.v0, 0, -expDiff );
- sigA = sig128Extra.v;
- sigZExtra = sig128Extra.extra;
- } else {
- if ( expA == 0x7FFF ) {
- if ( sigA.v64 | sigA.v0 ) goto propagateNaN;
- uiZ.v64 = uiA64;
- uiZ.v0 = uiA0;
- goto uiZ;
- }
- expZ = expA;
- if ( expB ) {
- sigB.v64 |= UINT64_C( 0x0001000000000000 );
- } else {
- --expDiff;
- sigZExtra = 0;
- if ( ! expDiff ) goto newlyAligned;
- }
- sig128Extra =
- softfloat_shiftRightJam128Extra( sigB.v64, sigB.v0, 0, expDiff );
- sigB = sig128Extra.v;
- sigZExtra = sig128Extra.extra;
- }
- newlyAligned:
- sigZ =
- softfloat_add128(
- sigA.v64 | UINT64_C( 0x0001000000000000 ),
- sigA.v0,
- sigB.v64,
- sigB.v0
- );
- --expZ;
- if ( sigZ.v64 < UINT64_C( 0x0002000000000000 ) ) goto roundAndPack;
- ++expZ;
- shiftRight1:
- sig128Extra =
- softfloat_shortShiftRightJam128Extra(
- sigZ.v64, sigZ.v0, sigZExtra, 1 );
- sigZ = sig128Extra.v;
- sigZExtra = sig128Extra.extra;
- roundAndPack:
- return
- softfloat_roundPackToF128( signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra );
- propagateNaN:
- uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 );
- uiZ:
- uZ.ui = uiZ;
- return uZ.f;
-
-}
-
-float128_t
-softfloat_subMagsF128(
- uint_fast64_t uiA64,
- uint_fast64_t uiA0,
- uint_fast64_t uiB64,
- uint_fast64_t uiB0,
- bool signZ
- )
-{
- int_fast32_t expA;
- struct uint128 sigA;
- int_fast32_t expB;
- struct uint128 sigB, sigZ;
- int_fast32_t expDiff, expZ;
- struct uint128 uiZ;
- union ui128_f128 uZ;
-
- expA = expF128UI64( uiA64 );
- sigA.v64 = fracF128UI64( uiA64 );
- sigA.v0 = uiA0;
- expB = expF128UI64( uiB64 );
- sigB.v64 = fracF128UI64( uiB64 );
- sigB.v0 = uiB0;
- sigA = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 4 );
- sigB = softfloat_shortShiftLeft128( sigB.v64, sigB.v0, 4 );
- expDiff = expA - expB;
- if ( 0 < expDiff ) goto expABigger;
- if ( expDiff < 0 ) goto expBBigger;
- if ( expA == 0x7FFF ) {
- if ( sigA.v64 | sigA.v0 | sigB.v64 | sigB.v0 ) goto propagateNaN;
- softfloat_raiseFlags( softfloat_flag_invalid );
- softfloat_commonNaNToF128M( (uint32_t*)&uiZ );
- // uiZ.v64 = defaultNaNF128UI64;
- // uiZ.v0 = defaultNaNF128UI0;
- goto uiZ;
- }
- expZ = expA;
- if ( ! expZ ) expZ = 1;
- if ( sigB.v64 < sigA.v64 ) goto aBigger;
- if ( sigA.v64 < sigB.v64 ) goto bBigger;
- if ( sigB.v0 < sigA.v0 ) goto aBigger;
- if ( sigA.v0 < sigB.v0 ) goto bBigger;
- uiZ.v64 =
- packToF128UI64(
- (softfloat_roundingMode == softfloat_round_min), 0, 0 );
- uiZ.v0 = 0;
- goto uiZ;
- expBBigger:
- if ( expB == 0x7FFF ) {
- if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
- uiZ.v64 = packToF128UI64( signZ ^ 1, 0x7FFF, 0 );
- uiZ.v0 = 0;
- goto uiZ;
- }
- if ( expA ) {
- sigA.v64 |= UINT64_C( 0x0010000000000000 );
- } else {
- ++expDiff;
- if ( ! expDiff ) goto newlyAlignedBBigger;
- }
- sigA = softfloat_shiftRightJam128( sigA.v64, sigA.v0, -expDiff );
- newlyAlignedBBigger:
- expZ = expB;
- sigB.v64 |= UINT64_C( 0x0010000000000000 );
- bBigger:
- signZ = ! signZ;
- sigZ = softfloat_sub128( sigB.v64, sigB.v0, sigA.v64, sigA.v0 );
- goto normRoundPack;
- expABigger:
- if ( expA == 0x7FFF ) {
- if ( sigA.v64 | sigA.v0 ) goto propagateNaN;
- uiZ.v64 = uiA64;
- uiZ.v0 = uiA0;
- goto uiZ;
- }
- if ( expB ) {
- sigB.v64 |= UINT64_C( 0x0010000000000000 );
- } else {
- --expDiff;
- if ( ! expDiff ) goto newlyAlignedABigger;
- }
- sigB = softfloat_shiftRightJam128( sigB.v64, sigB.v0, expDiff );
- newlyAlignedABigger:
- expZ = expA;
- sigA.v64 |= UINT64_C( 0x0010000000000000 );
- aBigger:
- sigZ = softfloat_sub128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 );
- normRoundPack:
- return softfloat_normRoundPackToF128( signZ, expZ - 5, sigZ.v64, sigZ.v0 );
- propagateNaN:
- uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 );
- uiZ:
- uZ.ui = uiZ;
- return uZ.f;
-}
-
-void
-f128M_add( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
-{
- const uint64_t *aWPtr, *bWPtr;
- uint64_t uiA64, uiA0;
- int signA;
- uint64_t uiB64, uiB0;
- int signB;
-
- aWPtr = (const uint64_t *) aPtr;
- bWPtr = (const uint64_t *) bPtr;
- uiA64 = aWPtr[indexWord( 2, 1 )];
- uiA0 = aWPtr[indexWord( 2, 0 )];
- signA = signF128UI64( uiA64 );
- uiB64 = bWPtr[indexWord( 2, 1 )];
- uiB0 = bWPtr[indexWord( 2, 0 )];
- signB = signF128UI64( uiB64 );
-
- if ( signA == signB ) {
- *zPtr = softfloat_addMagsF128( uiA64, uiA0, uiB64, uiB0, signA );
- } else {
- *zPtr = softfloat_subMagsF128( uiA64, uiA0, uiB64, uiB0, signA );
- }
-}
-
-void
-f128M_sub( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
-{
- const uint64_t *aWPtr, *bWPtr;
- uint_fast64_t uiA64, uiA0;
- bool signA;
- uint_fast64_t uiB64, uiB0;
- bool signB;
-
- aWPtr = (const uint64_t *) aPtr;
- bWPtr = (const uint64_t *) bPtr;
- uiA64 = aWPtr[indexWord( 2, 1 )];
- uiA0 = aWPtr[indexWord( 2, 0 )];
- signA = signF128UI64( uiA64 );
- uiB64 = bWPtr[indexWord( 2, 1 )];
- uiB0 = bWPtr[indexWord( 2, 0 )];
- signB = signF128UI64( uiB64 );
- if ( signA == signB ) {
- *zPtr = softfloat_subMagsF128( uiA64, uiA0, uiB64, uiB0, signA );
- } else {
- *zPtr = softfloat_addMagsF128( uiA64, uiA0, uiB64, uiB0, signA );
- }
-}
-
-void
-f128M_mul( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
-{
- const uint32_t *aWPtr, *bWPtr;
- uint32_t *zWPtr;
- uint32_t uiA96;
- int32_t expA;
- uint32_t uiB96;
- int32_t expB;
- bool signZ;
- const uint32_t *ptr;
- uint32_t uiZ96, sigA[4];
- uint_fast8_t shiftDist;
- uint32_t sigB[4];
- int32_t expZ;
- uint32_t sigProd[8], *extSigZPtr;
-
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- aWPtr = (const uint32_t *) aPtr;
- bWPtr = (const uint32_t *) bPtr;
- zWPtr = (uint32_t *) zPtr;
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- uiA96 = aWPtr[indexWordHi( 4 )];
- expA = expF128UI96( uiA96 );
- uiB96 = bWPtr[indexWordHi( 4 )];
- expB = expF128UI96( uiB96 );
- signZ = signF128UI96( uiA96 ) ^ signF128UI96( uiB96 );
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) {
- if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr ) ) return;
- ptr = aWPtr;
- if ( ! expA ) goto possiblyInvalid;
- if ( ! expB ) {
- ptr = bWPtr;
- possiblyInvalid:
- if (
- ! fracF128UI96( ptr[indexWordHi( 4 )] )
- && ! (ptr[indexWord( 4, 2 )] | ptr[indexWord( 4, 1 )]
- | ptr[indexWord( 4, 0 )])
- ) {
- softfloat_invalidF128M( zWPtr );
- return;
- }
- }
- uiZ96 = packToF128UI96( signZ, 0x7FFF, 0 );
- goto uiZ96;
- }
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- if ( expA ) {
- sigA[indexWordHi( 4 )] = fracF128UI96( uiA96 ) | 0x00010000;
- sigA[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )];
- sigA[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )];
- sigA[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )];
- } else {
- expA = softfloat_shiftNormSigF128M( aWPtr, 0, sigA );
- if ( expA == -128 ) goto zero;
- }
- if ( expB ) {
- sigB[indexWordHi( 4 )] = fracF128UI96( uiB96 ) | 0x00010000;
- sigB[indexWord( 4, 2 )] = bWPtr[indexWord( 4, 2 )];
- sigB[indexWord( 4, 1 )] = bWPtr[indexWord( 4, 1 )];
- sigB[indexWord( 4, 0 )] = bWPtr[indexWord( 4, 0 )];
- } else {
- expB = softfloat_shiftNormSigF128M( bWPtr, 0, sigB );
- if ( expB == -128 ) goto zero;
- }
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- expZ = expA + expB - 0x4000;
- softfloat_mul128MTo256M( sigA, sigB, sigProd );
- if (
- sigProd[indexWord( 8, 2 )]
- || (sigProd[indexWord( 8, 1 )] | sigProd[indexWord( 8, 0 )])
- ) {
- sigProd[indexWord( 8, 3 )] |= 1;
- }
- extSigZPtr = &sigProd[indexMultiwordHi( 8, 5 )];
- shiftDist = 16;
- if ( extSigZPtr[indexWordHi( 5 )] & 2 ) {
- ++expZ;
- shiftDist = 15;
- }
- softfloat_shortShiftLeft160M( extSigZPtr, shiftDist, extSigZPtr );
- softfloat_roundPackMToF128M( signZ, expZ, extSigZPtr, zWPtr );
- return;
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- zero:
- uiZ96 = packToF128UI96( signZ, 0, 0 );
- uiZ96:
- zWPtr[indexWordHi( 4 )] = uiZ96;
- zWPtr[indexWord( 4, 2 )] = 0;
- zWPtr[indexWord( 4, 1 )] = 0;
- zWPtr[indexWord( 4, 0 )] = 0;
-}
-
-float128_t
-f128_div( float128_t a, float128_t b )
-{
- union ui128_f128 uA;
- uint_fast64_t uiA64, uiA0;
- bool signA;
- int_fast32_t expA;
- struct uint128 sigA;
- union ui128_f128 uB;
- uint_fast64_t uiB64, uiB0;
- bool signB;
- int_fast32_t expB;
- struct uint128 sigB;
- bool signZ;
- struct exp32_sig128 normExpSig;
- int_fast32_t expZ;
- struct uint128 rem;
- uint_fast32_t recip32;
- int ix;
- uint_fast64_t q64;
- uint_fast32_t q;
- struct uint128 term;
- uint_fast32_t qs[3];
- uint_fast64_t sigZExtra;
- struct uint128 sigZ, uiZ;
- union ui128_f128 uZ;
-
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- uA.f = a;
- uiA64 = uA.ui.v64;
- uiA0 = uA.ui.v0;
- signA = signF128UI64( uiA64 );
- expA = expF128UI64( uiA64 );
- sigA.v64 = fracF128UI64( uiA64 );
- sigA.v0 = uiA0;
- uB.f = b;
- uiB64 = uB.ui.v64;
- uiB0 = uB.ui.v0;
- signB = signF128UI64( uiB64 );
- expB = expF128UI64( uiB64 );
- sigB.v64 = fracF128UI64( uiB64 );
- sigB.v0 = uiB0;
- signZ = signA ^ signB;
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- if ( expA == 0x7FFF ) {
- if ( sigA.v64 | sigA.v0 ) goto propagateNaN;
- if ( expB == 0x7FFF ) {
- if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
- goto invalid;
- }
- goto infinity;
- }
- if ( expB == 0x7FFF ) {
- if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
- goto zero;
- }
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- if ( ! expB ) {
- if ( ! (sigB.v64 | sigB.v0) ) {
- if ( ! (expA | sigA.v64 | sigA.v0) ) goto invalid;
- softfloat_raiseFlags( softfloat_flag_infinite );
- goto infinity;
- }
- normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 );
- expB = normExpSig.exp;
- sigB = normExpSig.sig;
- }
- if ( ! expA ) {
- if ( ! (sigA.v64 | sigA.v0) ) goto zero;
- normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
- expA = normExpSig.exp;
- sigA = normExpSig.sig;
- }
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- expZ = expA - expB + 0x3FFE;
- sigA.v64 |= UINT64_C( 0x0001000000000000 );
- sigB.v64 |= UINT64_C( 0x0001000000000000 );
- rem = sigA;
- if ( softfloat_lt128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 ) ) {
- --expZ;
- rem = softfloat_add128( sigA.v64, sigA.v0, sigA.v64, sigA.v0 );
- }
- recip32 = softfloat_approxRecip32_1( sigB.v64>>17 );
- ix = 3;
- for (;;) {
- q64 = (uint_fast64_t) (uint32_t) (rem.v64>>19) * recip32;
- q = (q64 + 0x80000000)>>32;
- --ix;
- if ( ix < 0 ) break;
- rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
- term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
- rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
- if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
- --q;
- rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
- }
- qs[ix] = q;
- }
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- if ( ((q + 1) & 7) < 2 ) {
- rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
- term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
- rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
- if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
- --q;
- rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
- } else if ( softfloat_le128( sigB.v64, sigB.v0, rem.v64, rem.v0 ) ) {
- ++q;
- rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
- }
- if ( rem.v64 | rem.v0 ) q |= 1;
- }
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- sigZExtra = (uint64_t) ((uint_fast64_t) q<<60);
- term = softfloat_shortShiftLeft128( 0, qs[1], 54 );
- sigZ =
- softfloat_add128(
- (uint_fast64_t) qs[2]<<19, ((uint_fast64_t) qs[0]<<25) + (q>>4),
- term.v64, term.v0
- );
- return
- softfloat_roundPackToF128( signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra );
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- propagateNaN:
- uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 );
- goto uiZ;
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- invalid:
- softfloat_raiseFlags( softfloat_flag_invalid );
- softfloat_commonNaNToF128M( (uint32_t*)&uiZ );
- // uiZ.v64 = defaultNaNF128UI64;
- // uiZ.v0 = defaultNaNF128UI0;
- goto uiZ;
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- infinity:
- uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 );
- goto uiZ0;
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- zero:
- uiZ.v64 = packToF128UI64( signZ, 0, 0 );
- uiZ0:
- uiZ.v0 = 0;
- uiZ:
- uZ.ui = uiZ;
- return uZ.f;
-}
-
-static float128_t
-f128_rem( float128_t a, float128_t b )
-{
- union ui128_f128 uA;
- uint_fast64_t uiA64, uiA0;
- bool signA;
- int_fast32_t expA;
- struct uint128 sigA;
- union ui128_f128 uB;
- uint_fast64_t uiB64, uiB0;
- int_fast32_t expB;
- struct uint128 sigB;
- struct exp32_sig128 normExpSig;
- struct uint128 rem;
- int_fast32_t expDiff;
- uint_fast32_t q, recip32;
- uint_fast64_t q64;
- struct uint128 term, altRem, meanRem;
- bool signRem;
- struct uint128 uiZ;
- union ui128_f128 uZ;
-
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- uA.f = a;
- uiA64 = uA.ui.v64;
- uiA0 = uA.ui.v0;
- signA = signF128UI64( uiA64 );
- expA = expF128UI64( uiA64 );
- sigA.v64 = fracF128UI64( uiA64 );
- sigA.v0 = uiA0;
- uB.f = b;
- uiB64 = uB.ui.v64;
- uiB0 = uB.ui.v0;
- expB = expF128UI64( uiB64 );
- sigB.v64 = fracF128UI64( uiB64 );
- sigB.v0 = uiB0;
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- if ( expA == 0x7FFF ) {
- if (
- (sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))
- ) {
- goto propagateNaN;
- }
- goto invalid;
- }
- if ( expB == 0x7FFF ) {
- if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
- return a;
- }
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- if ( ! expB ) {
- if ( ! (sigB.v64 | sigB.v0) ) goto invalid;
- normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 );
- expB = normExpSig.exp;
- sigB = normExpSig.sig;
- }
- if ( ! expA ) {
- if ( ! (sigA.v64 | sigA.v0) ) return a;
- normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
- expA = normExpSig.exp;
- sigA = normExpSig.sig;
- }
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- sigA.v64 |= UINT64_C( 0x0001000000000000 );
- sigB.v64 |= UINT64_C( 0x0001000000000000 );
- rem = sigA;
- expDiff = expA - expB;
- if ( expDiff < 1 ) {
- if ( expDiff < -1 ) return a;
- if ( expDiff ) {
- --expB;
- sigB = softfloat_add128( sigB.v64, sigB.v0, sigB.v64, sigB.v0 );
- q = 0;
- } else {
- q = softfloat_le128( sigB.v64, sigB.v0, rem.v64, rem.v0 );
- if ( q ) {
- rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
- }
- }
- } else {
- recip32 = softfloat_approxRecip32_1( sigB.v64>>17 );
- expDiff -= 30;
- for (;;) {
- q64 = (uint_fast64_t) (uint32_t) (rem.v64>>19) * recip32;
- if ( expDiff < 0 ) break;
- q = (q64 + 0x80000000)>>32;
- rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
- term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
- rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
- if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
- rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
- }
- expDiff -= 29;
- }
- /*--------------------------------------------------------------------
- | (`expDiff' cannot be less than -29 here.)
- *--------------------------------------------------------------------*/
- q = (uint32_t) (q64>>32)>>(~expDiff & 31);
- rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, expDiff + 30 );
- term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
- rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
- if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
- altRem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
- goto selectRem;
- }
- }
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- do {
- altRem = rem;
- ++q;
- rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
- } while ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) );
- selectRem:
- meanRem = softfloat_add128( rem.v64, rem.v0, altRem.v64, altRem.v0 );
- if (
- (meanRem.v64 & UINT64_C( 0x8000000000000000 ))
- || (! (meanRem.v64 | meanRem.v0) && (q & 1))
- ) {
- rem = altRem;
- }
- signRem = signA;
- if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
- signRem = ! signRem;
- rem = softfloat_sub128( 0, 0, rem.v64, rem.v0 );
- }
- return softfloat_normRoundPackToF128( signRem, expB - 1, rem.v64, rem.v0 );
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- propagateNaN:
- uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 );
- goto uiZ;
- /*------------------------------------------------------------------------
- *------------------------------------------------------------------------*/
- invalid:
- softfloat_raiseFlags( softfloat_flag_invalid );
- softfloat_commonNaNToF128M( (uint32_t*)&uiZ );
- // uiZ.v64 = defaultNaNF128UI64;
- // uiZ.v0 = defaultNaNF128UI0;
- uiZ:
- uZ.ui = uiZ;
- return uZ.f;
-}
-
-bool
-f128_isNan( float128_t a) {
- int_fast32_t expA;
- struct uint128 sigA;
- uint_fast64_t uiA64, uiA0;
- union ui128_f128 uA;
-
- uA.f = a;
- uiA64 = uA.ui.v64;
- uiA0 = uA.ui.v0;
- return isNaNF128UI( uiA64, uiA0 );
-}
-
-bool
-f128_isInf( float128_t a) {
- int_fast32_t expA;
- struct uint128 sigA;
- uint_fast64_t uiA64, uiA0;
- union ui128_f128 uA;
-
- uA.f = a;
- uiA64 = uA.ui.v64;
- uiA0 = uA.ui.v0;
- return isInfF128UI( uiA64, uiA0 );
-// expA = expF128UI64( uiA64 );
-// sigA.v64 = fracF128UI64( uiA64 );
-// sigA.v0 = uiA0;
-//
-// if ( expA == 0x7FFF ) {
-// if ( sigA.v64 == 0 ) return 1;
-// }
-// return 0;
-}
-
-static bool
-f128M_eq( float128_t* aPtr, float128_t* bPtr )
-{
- union ui128_f128 uA;
- uint_fast64_t uiA64, uiA0;
- union ui128_f128 uB;
- uint_fast64_t uiB64, uiB0;
-
- uA.f = *aPtr;
- uiA64 = uA.ui.v64;
- uiA0 = uA.ui.v0;
- uB.f = *bPtr;
- uiB64 = uB.ui.v64;
- uiB0 = uB.ui.v0;
-
- // fprintf(stderr, "isNaNF128UI(a): %d\n", isNaNF128UI( uiA64, uiA0 ));
- // fprintf(stderr, "isNaNF128UI(a): %d\n", isNaNF128UI( uiB64, uiB0 ));
-
- if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
- if (
- softfloat_isSigNaNF128UI( uiA64, uiA0 )
- || softfloat_isSigNaNF128UI( uiB64, uiB0 )
- ) {
- softfloat_raiseFlags( softfloat_flag_invalid );
- }
- return 0;
- }
-
- // fprintf(stderr, "uiA0 == uiB0: %d\n", (uiA0 == uiB0));
- // fprintf(stderr, "uiA64 == uiB64: %d\n", (uiA64 == uiB64));
-
- return
- (uiA0 == uiB0)
- && ( (uiA64 == uiB64)
- || (! uiA0 && ! ((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF )))
- );
-}
-
-static bool
-f128M_lt( float128_t* aPtr, float128_t* bPtr )
-{
- union ui128_f128 uA;
- uint_fast64_t uiA64, uiA0;
- union ui128_f128 uB;
- uint_fast64_t uiB64, uiB0;
- bool signA, signB;
-
- uA.f = *aPtr;
- uiA64 = uA.ui.v64;
- uiA0 = uA.ui.v0;
- uB.f = *bPtr;
- uiB64 = uB.ui.v64;
- uiB0 = uB.ui.v0;
- if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
- softfloat_raiseFlags( softfloat_flag_invalid );
- return 0;
- }
- signA = signF128UI64( uiA64 );
- signB = signF128UI64( uiB64 );
- return
- (signA != signB)
- ? signA
- && (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
- | uiA0 | uiB0)
- : ((uiA64 != uiB64) || (uiA0 != uiB0))
- && (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
-}
-
-static inline void
-f128M_div( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
-{
- *zPtr = f128_div( *aPtr, *bPtr );
-}
-
-static inline void
-f128M_rem( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
-{
- *zPtr = f128_rem( *aPtr, *bPtr );
-}
-
-static inline float128_t
-f128_negate( float128_t a) {
- struct uint128 sigA;
- uint_fast64_t uiA64, uiA0;
- union ui128_f128 uA;
-
- uA.f = a;
- uiA64 = uA.ui.v64;
- uiA0 = uA.ui.v0;
- if (isNaNF128UI( uiA64, uiA0 )) return a;
- uA.ui.v64 ^= UINT64_C(0x8000000000000000);
- return uA.f;
-}
-
-static inline void
-f128M_negate( const float128_t *aPtr, float128_t *zPtr )
-{
- *zPtr = f128_negate( *aPtr );
-}
-
-#endif // SUPPORT_QUADFLOAT
-
%}
! !
@@ -2240,8 +164,7 @@
if (sizeof(long double) == sizeof(float128_t)) {
__qMKLFLOAT(newFloat, 0.0); /* OBJECT ALLOCATION */
} else {
- float128_t qf;
- f64_to_f128M(0.0, &qf);
+ float128_t qf = STX_qZero;
__qMKQFLOAT(newFloat, qf); /* OBJECT ALLOCATION */
}
RETURN (newFloat);
@@ -2260,10 +183,10 @@
OBJ newFloat;
if (__isFloatLike(aFloat)) {
- float64_t f = __floatVal(aFloat);
+ double f = __floatVal(aFloat);
float128_t qf;
- f64_to_f128M(f, &qf);
+ qf = STX_dbltoq (f);
__qMKQFLOAT(newFloat, qf); /* OBJECT ALLOCATION */
RETURN (newFloat);
}
@@ -2294,11 +217,7 @@
INT iVal = __intVal(anInteger);
float128_t qf;
-#if __POINTER_SIZE__ == 4
- i32_to_f128M( iVal, &qf );
-else
- i64_to_f128M( iVal, &qf );
-#endif
+ qf = STX_inttoq( (long)iVal );
__qMKQFLOAT(newFloat, qf); /* OBJECT ALLOCATION */
RETURN (newFloat);
}
@@ -2316,7 +235,7 @@
"return a new quadFloat, given a long float value"
%{ /* NOCONTEXT */
-#ifdef SUPPORT_QUADFLOAT
+#ifdef xSUPPORT_QUADFLOAT
OBJ newFloat;
union {
LONGFLOAT_t lf; // is long double
@@ -2383,7 +302,7 @@
NaN isNil ifTrue:[
%{ /* NOCONTEXT */
-#ifdef SUPPORT_QUADFLOAT
+#ifdef xSUPPORT_QUADFLOAT
{
OBJ newFloat;
float128_t qf;
@@ -2419,7 +338,7 @@
PositiveInfinity isNil ifTrue:[
%{ /* NOCONTEXT */
-#ifdef SUPPORT_QUADFLOAT
+#ifdef xSUPPORT_QUADFLOAT
{
OBJ newFloat;
struct uint128 uiZ;
@@ -2449,7 +368,7 @@
NegativeInfinity isNil ifTrue:[
%{ /* NOCONTEXT */
-#ifdef SUPPORT_QUADFLOAT
+#ifdef xSUPPORT_QUADFLOAT
{
OBJ newFloat;
struct uint128 uiZ;
@@ -2476,9 +395,9 @@
"return the constant phi as quadFloat"
Phi isNil ifTrue:[
- "/ phiDigits has enough digits for 128bit IEEE quads
- "/ do not use as a literal constant here - we cannot depend on the underlying C-compiler here...
- Phi := self readFrom:(Number phiDigits)
+ "/ phiDigits has enough digits for 128bit IEEE quads
+ "/ do not use as a literal constant here - we cannot depend on the underlying C-compiler here...
+ Phi := self readFrom:(Number phiDigits)
].
^ Phi
@@ -2556,12 +475,9 @@
!
numBitsInExponent
- "answer the number of bits in the exponent
- the hidden bit is not counted here:
-
- This is an 128bit quadfloat,
- where 15 bits are available in the exponent:
- seeeeeee eeeeeeee mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm...
+ "answer the number of bits in the exponent.
+ This is an IEEE 128bit quadfloat, where 15 bits are available in the exponent:
+ seeeeeee eeeeeeee mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm...
"
^ 15
@@ -2612,7 +528,7 @@
"return the product of the receiver and the argument."
aNumber class == QuadFloat ifTrue:[
- ^ aNumber productFromQuadFloat:self
+ ^ aNumber productFromQuadFloat:self
].
thisContext isReallyRecursive ifTrue:[self error].
@@ -2643,6 +559,321 @@
^ aNumber quotientFromQuadFloat:self
!
+abs
+ "return the absolute value of the receiver
+ reimplemented here for speed"
+
+%{ /* NOCONTEXT */
+#ifdef SUPPORT_QUADFLOAT
+ OBJ newFloat;
+ float128_t result, myVal;
+
+ myVal = __quadFloatVal(self);
+ result = STX_absq(myVal);
+ __qMKQFLOAT(newFloat, result);
+ RETURN ( newFloat );
+#endif
+%}.
+!
+
+ceiling
+ "return the smallest integer which is greater or equal to the receiver."
+
+ |val|
+
+%{
+ float128_t qVal;
+ float128_t qMinInt;
+ float128_t qMaxInt;
+
+ qVal = __quadFloatVal(self);
+ qVal = STX_ceilq(qVal);
+
+ qMinInt = STX_dbltoq((double)_MIN_INT);
+ qMaxInt = STX_dbltoq((double)_MAX_INT);
+ if (STX_geq(qVal, qMinInt) && STX_leq(qVal, qMaxInt)) {
+ double dVal = STX_qtodbl(qVal);
+ RETURN ( __mkSmallInteger( (INT) dVal ) );
+ }
+ __qMKQFLOAT(val, qVal);
+%}.
+ ^ val asInteger
+
+ "
+ 0.5 asQuadFloat ceiling
+ 0.5 asQuadFloat ceilingAsFloat
+ -0.5 asQuadFloat ceiling
+ -0.5 asQuadFloat ceilingAsFloat
+ "
+!
+
+ceilingAsFloat
+ "return the smallest integer-valued float greater or equal to the receiver.
+ This is much like #ceiling, but avoids a (possibly expensive) conversion
+ of the result to an integer.
+ It may be useful, if the result is to be further used in another float-operation."
+
+%{ /* NOCONTEXT */
+#ifdef SUPPORT_QUADFLOAT
+ OBJ newFloat;
+ float128_t result, myVal;
+
+ myVal = __quadFloatVal(self);
+ result = STX_ceilq(myVal);
+ __qMKQFLOAT(newFloat, result);
+ RETURN ( newFloat );
+#endif
+%}.
+!
+
+cos
+ "return the cosine of the receiver (interpreted as radians)"
+
+%{ /* NOCONTEXT */
+#ifdef SUPPORT_QUADFLOAT
+ OBJ newFloat;
+ float128_t result, myVal;
+
+ myVal = __quadFloatVal(self);
+ result = STX_cosq(myVal);
+ __qMKQFLOAT(newFloat, result);
+ RETURN ( newFloat );
+#endif
+%}.
+!
+
+cosh
+ "return the hyperbolic cosine of the receiver (interpreted as radians)"
+
+%{ /* NOCONTEXT */
+#ifdef SUPPORT_QUADFLOAT
+ OBJ newFloat;
+ float128_t result, myVal;
+
+ myVal = __quadFloatVal(self);
+ result = STX_coshq(myVal);
+ __qMKQFLOAT(newFloat, result);
+ RETURN ( newFloat );
+#endif
+%}.
+!
+
+exp
+ "return e raised to the power of the receiver"
+
+%{ /* NOCONTEXT */
+#ifdef SUPPORT_QUADFLOAT
+ OBJ newFloat;
+ float128_t result, myVal;
+
+ myVal = __quadFloatVal(self);
+ result = STX_expq(myVal);
+ __qMKQFLOAT(newFloat, result);
+ RETURN ( newFloat );
+#endif
+%}.
+!
+
+exponent
+ "extract a normalized float's (unbiased) exponent.
+ The returned value depends on the float-representation of
+ the underlying machine and is therefore highly unportable.
+ This is not for general use.
+ This assumes that the mantissa is normalized to
+ 0.5 .. 1.0 and the float's value is: mantissa * 2^exp"
+
+%{ /* NOCONTEXT */
+ float128_t myVal;
+ float128_t frac;
+ int exp;
+
+ myVal = __quadFloatVal(self);
+#if 1
+ // should we?
+ if (! (STX_isNanq(&myVal) || STX_isInfq(&myVal)))
+#endif
+ {
+ frac = STX_frexpq(myVal, &exp);
+ RETURN (__mkSmallInteger(exp));
+ }
+%}.
+ ^ super exponent
+
+ "
+ 1.0 exponent
+ 1.0 asQuadFloat exponent
+ 2.0 exponent
+ 2.0 asQuadFloat exponent
+ 3.0 exponent
+ 3.0 asQuadFloat exponent
+ 4.0 exponent
+ 4.0 asQuadFloat exponent
+ 0.5 exponent
+ 0.5 asQuadFloat exponent
+ 0.4 exponent
+ 0.4 asQuadFloat exponent
+ 0.25 exponent
+ 0.25 asQuadFloat exponent
+ 0.2 exponent
+ 0.2 asQuadFloat exponent
+ 0.00000011111 exponent
+ 0.00000011111 asQuadFloat exponent
+ 0.0 exponent
+ 0.0 asQuadFloat exponent
+
+ 1e1000 exponent -> error (INF)
+ 1e1000 asQuadFloat exponent -> error (INF)
+ "
+!
+
+floor
+ "return the integer nearest the receiver towards negative infinity."
+
+ |val|
+
+%{
+ float128_t qVal;
+ float128_t qMinInt;
+ float128_t qMaxInt;
+
+ qVal = __quadFloatVal(self);
+ qVal = STX_floorq(qVal);
+
+ qMinInt = STX_dbltoq((double)_MIN_INT);
+ qMaxInt = STX_dbltoq((double)_MAX_INT);
+ if (STX_geq(qVal, qMinInt) && STX_leq(qVal, qMaxInt)) {
+ double dVal = STX_qtodbl(qVal);
+ RETURN ( __mkSmallInteger( (INT) dVal ) );
+ }
+ __qMKQFLOAT(val, qVal);
+%}.
+ ^ val asInteger
+
+ "
+ 0.5 asQuadFloat floor
+ 0.5 asQuadFloat floorAsFloat
+ -0.5 asQuadFloat floor
+ -0.5 asQuadFloat floorAsFloat
+ "
+!
+
+floorAsFloat
+ "return the integer nearest the receiver towards negative infinity as a float.
+ This is much like #floor, but avoids a (possibly expensive) conversion
+ of the result to an integer.
+ It may be useful, if the result is to be further used in another float-operation."
+
+%{ /* NOCONTEXT */
+#ifdef SUPPORT_QUADFLOAT
+ OBJ newFloat;
+ float128_t result, myVal;
+
+ myVal = __quadFloatVal(self);
+ result = STX_floorq(myVal);
+ __qMKQFLOAT(newFloat, result);
+ RETURN ( newFloat );
+#endif
+%}.
+!
+
+ln
+ "return natural logarithm of the receiver."
+
+%{ /* NOCONTEXT */
+#ifdef SUPPORT_QUADFLOAT
+ OBJ newFloat;
+ float128_t result, myVal;
+
+ myVal = __quadFloatVal(self);
+ result = STX_logq(myVal);
+ __qMKQFLOAT(newFloat, result);
+ RETURN ( newFloat );
+#endif
+%}.
+!
+
+log
+ "return log base 10 of the receiver.
+ Alias for log:10."
+
+%{ /* NOCONTEXT */
+#ifdef SUPPORT_QUADFLOAT
+ OBJ newFloat;
+ float128_t result, myVal;
+
+ myVal = __quadFloatVal(self);
+ result = STX_log10q(myVal);
+ __qMKQFLOAT(newFloat, result);
+ RETURN ( newFloat );
+#endif
+%}.
+!
+
+log2
+ "return logarithm dualis of the receiver."
+
+%{ /* NOCONTEXT */
+#ifdef SUPPORT_QUADFLOAT
+ OBJ newFloat;
+ float128_t result, myVal;
+
+ myVal = __quadFloatVal(self);
+ result = STX_log2q(myVal);
+ __qMKQFLOAT(newFloat, result);
+ RETURN ( newFloat );
+#endif
+%}.
+!
+
+mantissa
+ "extract a normalized float's mantissa.
+ The returned value depends on the float-representation of
+ the underlying machine and is therefore highly unportable.
+ This is not for general use.
+ This assumes that the mantissa is normalized to
+ 0.5 .. 1.0 and the float's value is mantissa * 2^exp"
+
+%{ /* NOCONTEXT */
+ float128_t myVal;
+ float128_t frac;
+ int exp;
+ OBJ newFloat;
+
+ myVal = __quadFloatVal(self);
+ // ouch: math libs seem to not care for NaN here;
+#if 1
+ // should we?
+ if (! (STX_isNanq(&myVal) || STX_isInfq(&myVal)))
+#endif
+ {
+ frac = STX_frexpq(myVal, &exp);
+ __qMKQFLOAT(newFloat, frac);
+ RETURN ( newFloat );
+ }
+%}.
+ ^ super mantissa
+
+ "
+ 1.0 exponent
+ 1.0 asQuadFloat exponent
+ 1.0 mantissa
+ 1.0 asQuadFloat mantissa
+
+ 0.25 exponent
+ 0.25 asQuadFloat exponent
+ 0.25 mantissa
+ 0.25 asQuadFloat mantissa
+
+ 0.00000011111 exponent
+ 0.00000011111 mantissa
+
+ 1e1000 mantissa
+ "
+
+ "Modified: / 20-06-2017 / 11:37:13 / cg"
+ "Modified (comment): / 26-05-2019 / 03:12:55 / Claus Gittinger"
+!
+
negated
"return the receiver negated"
@@ -2652,7 +883,7 @@
float128_t result, myVal;
myVal = __quadFloatVal(self);
- f128M_negate( &myVal, &result );
+ result = STX_negq(myVal);
__qMKQFLOAT(newFloat, result);
RETURN ( newFloat );
#endif
@@ -2669,10 +900,106 @@
^ ZeroDivide raiseRequestWith:thisContext.
].
^ aNumber remainderFromLongFloat:self
+!
+
+sin
+ "return the sine of the receiver (interpreted as radians)"
+
+%{ /* NOCONTEXT */
+#ifdef SUPPORT_QUADFLOAT
+ OBJ newFloat;
+ float128_t result, myVal;
+
+ myVal = __quadFloatVal(self);
+ result = STX_sinq(myVal);
+ __qMKQFLOAT(newFloat, result);
+ RETURN ( newFloat );
+#endif
+%}.
+!
+
+sinh
+ "return the hyperbolic sine of the receiver (interpreted as radians)"
+
+%{ /* NOCONTEXT */
+#ifdef SUPPORT_QUADFLOAT
+ OBJ newFloat;
+ float128_t result, myVal;
+
+ myVal = __quadFloatVal(self);
+ result = STX_sinhq(myVal);
+ __qMKQFLOAT(newFloat, result);
+ RETURN ( newFloat );
+#endif
+%}.
+!
+
+tan
+ "return the tangent of the receiver (interpreted as radians)"
+
+%{ /* NOCONTEXT */
+#ifdef SUPPORT_QUADFLOAT
+ OBJ newFloat;
+ float128_t result, myVal;
+
+ myVal = __quadFloatVal(self);
+ result = STX_tanq(myVal);
+ __qMKQFLOAT(newFloat, result);
+ RETURN ( newFloat );
+#endif
+%}.
+!
+
+tanh
+ "return the hyperbolic tangent of the receiver (interpreted as radians)"
+
+%{ /* NOCONTEXT */
+#ifdef SUPPORT_QUADFLOAT
+ OBJ newFloat;
+ float128_t result, myVal;
+
+ myVal = __quadFloatVal(self);
+ result = STX_tanhq(myVal);
+ __qMKQFLOAT(newFloat, result);
+ RETURN ( newFloat );
+#endif
+%}.
! !
!QuadFloat methodsFor:'coercing & converting'!
+asFloat
+ "return a Float with same value as the receiver.
+ Raises an error if the receiver exceeds the float range."
+
+%{ /* NOCONTEXT */
+#ifdef SUPPORT_QUADFLOAT
+ OBJ newFloat;
+ float128_t qVal = __quadFloatVal(self);
+ double dVal = STX_qtodbl(qVal);
+
+ if (isfinite(dVal) || !STX_isfiniteq(qVal)) {
+ __qMKFLOAT(newFloat, dVal);
+ RETURN ( newFloat );
+ }
+#endif
+%}.
+ "
+ value out of range
+ if you need -INF for a zero receiver, try Number trapInfinity:[...]
+ "
+ ^ self class
+ raise:#infiniteResultSignal
+ receiver:self
+ selector:#asFloat
+ arguments:#()
+ errorString:'receiver is out of the double-precision float range'
+
+ "
+ 1.0 asQuadFloat asFloat
+ "
+!
+
generality
"return the generality value - see ArithmeticValue>>retry:coercing:"
@@ -2751,7 +1078,7 @@
myVal = __quadFloatVal(self);
argVal = __quadFloatVal(aQuadFloat);
- f128M_sub( &myVal, &argVal, &result );
+ result = STX_addq( argVal, myVal, 1 );
__qMKQFLOAT(newFloat, result);
RETURN ( newFloat );
#endif // SUPPORT_QUADFLOAT
@@ -2769,7 +1096,7 @@
myVal = __quadFloatVal(self);
argVal = __quadFloatVal(aQuadFloat);
- RETURN (f128M_eq( &argVal, &myVal ) ? true : false);
+ RETURN (STX_eqq(argVal, myVal) ? true : false);
#endif // SUPPORT_QUADFLOAT
%}.
self errorUnsupported
@@ -2787,7 +1114,7 @@
myVal = __quadFloatVal(self);
argVal = __quadFloatVal(aQuadFloat);
- RETURN (f128M_lt( &argVal, &myVal ) ? true : false);
+ RETURN (STX_ltq(argVal, myVal) ? true : false);
#endif // SUPPORT_QUADFLOAT
%}.
self errorUnsupported
@@ -2803,7 +1130,7 @@
myVal = __quadFloatVal(self);
argVal = __quadFloatVal(aQuadFloat);
- f128M_mul( &myVal, &argVal, &result );
+ result = STX_mulq(myVal, argVal);
__qMKQFLOAT(newFloat, result);
RETURN ( newFloat );
#endif // SUPPORT_QUADFLOAT
@@ -2821,7 +1148,7 @@
myVal = __quadFloatVal(self);
argVal = __quadFloatVal(aQuadFloat);
- f128M_div( &myVal, &argVal, &result );
+ result = STX_divq(argVal, myVal);
__qMKQFLOAT(newFloat, result);
RETURN ( newFloat );
#endif // SUPPORT_QUADFLOAT
@@ -2839,7 +1166,7 @@
myVal = __quadFloatVal(self);
argVal = __quadFloatVal(aQuadFloat);
- f128M_add( &myVal, &argVal, &result );
+ result = STX_addq( myVal, argVal, 0 );
__qMKQFLOAT(newFloat, result);
RETURN ( newFloat );
#endif // SUPPORT_QUADFLOAT
@@ -2899,17 +1226,17 @@
float128_t myVal;
myVal = __quadFloatVal(self);
- RETURN ((f128_isInf(myVal) || f128_isNan(myVal)) ? false : true);
+ RETURN (STX_isfiniteq(myVal) ? true : false);
#endif // SUPPORT_QUADFLOAT
%}.
"
- 1.0 isFinite
- self NaN isFinite
- self infinity isFinite
- self negativeInfinity isFinite
- (0.0 uncheckedDivide: 0.0) isFinite
- (1.0 uncheckedDivide: 0.0) isFinite
+ 1.0 isFinite
+ self NaN isFinite
+ self infinity isFinite
+ self negativeInfinity isFinite
+ (0.0 uncheckedDivide: 0.0) isFinite
+ (1.0 uncheckedDivide: 0.0) isFinite
"
!
@@ -2921,21 +1248,21 @@
float128_t myVal;
myVal = __quadFloatVal(self);
- RETURN (f128_isInf(myVal) ? true : false);
+ RETURN (STX_isInfq(&myVal) ? true : false);
#endif // SUPPORT_QUADFLOAT
%}.
"
- 1.0 isFinite
- 1.0 isInfinite
- self NaN isFinite
- self NaN isInfinite
- self infinity isFinite
- self infinity isInfinite
- self negativeInfinity isFinite
- self negativeInfinity isInfinite
- (0.0 uncheckedDivide: 0.0) isFinite
- (1.0 uncheckedDivide: 0.0) isFinite
+ 1.0 asQuadFloat isFinite
+ 1.0 asQuadFloat isInfinite
+ self NaN isFinite
+ self NaN isInfinite
+ self infinity isFinite
+ self infinity isInfinite
+ self negativeInfinity isFinite
+ self negativeInfinity isInfinite
+ (0.0 uncheckedDivide: 0.0) isFinite
+ (1.0 uncheckedDivide: 0.0) isFinite
"
!
@@ -2949,19 +1276,27 @@
float128_t myVal;
myVal = __quadFloatVal(self);
- RETURN (f128_isNan(myVal) ? true : false);
+ RETURN (STX_isNanq(&myVal) ? true : false);
#endif // SUPPORT_QUADFLOAT
%}.
"
- 1.0 isFinite
- self NaN isFinite
- self infinity isFinite
- (0.0 uncheckedDivide: 0.0) isFinite
- (1.0 uncheckedDivide: 0.0) isFinite
+ 1.0 asQuadFloat isFinite
+ self NaN isFinite
+ self infinity isFinite
+ (0.0 uncheckedDivide: 0.0) isFinite
+ (1.0 uncheckedDivide: 0.0) isFinite
"
! !
+!QuadFloat methodsFor:'testing'!
+
+isQuadFloat
+ "return true, if the receiver is some kind of quad floating point number (iee quad precision)"
+
+ ^ true
+! !
+
!QuadFloat class methodsFor:'documentation'!
version_CVS