github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/3rd_party/SoftFloat-3e/source/extF80_rem.c (about)

     1  
     2  /*============================================================================
     3  
     4  This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
     5  Package, Release 3e, by John R. Hauser.
     6  
     7  Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
     8  University of California.  All rights reserved.
     9  
    10  Redistribution and use in source and binary forms, with or without
    11  modification, are permitted provided that the following conditions are met:
    12  
    13   1. Redistributions of source code must retain the above copyright notice,
    14      this list of conditions, and the following disclaimer.
    15  
    16   2. Redistributions in binary form must reproduce the above copyright notice,
    17      this list of conditions, and the following disclaimer in the documentation
    18      and/or other materials provided with the distribution.
    19  
    20   3. Neither the name of the University nor the names of its contributors may
    21      be used to endorse or promote products derived from this software without
    22      specific prior written permission.
    23  
    24  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
    25  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    26  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
    27  DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
    28  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    29  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    30  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    31  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    32  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    33  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    34  
    35  =============================================================================*/
    36  
    37  #include <stdbool.h>
    38  #include <stdint.h>
    39  #include "platform.h"
    40  #include "internals.h"
    41  #include "specialize.h"
    42  #include "softfloat.h"
    43  
    44  extFloat80_t extF80_rem( extFloat80_t a, extFloat80_t b )
    45  {
    46      union { struct extFloat80M s; extFloat80_t f; } uA;
    47      uint_fast16_t uiA64;
    48      uint_fast64_t uiA0;
    49      bool signA;
    50      int_fast32_t expA;
    51      uint_fast64_t sigA;
    52      union { struct extFloat80M s; extFloat80_t f; } uB;
    53      uint_fast16_t uiB64;
    54      uint_fast64_t uiB0;
    55      int_fast32_t expB;
    56      uint_fast64_t sigB;
    57      struct exp32_sig64 normExpSig;
    58      int_fast32_t expDiff;
    59      struct uint128 rem, shiftedSigB;
    60      uint_fast32_t q, recip32;
    61      uint_fast64_t q64;
    62      struct uint128 term, altRem, meanRem;
    63      bool signRem;
    64      struct uint128 uiZ;
    65      uint_fast16_t uiZ64;
    66      uint_fast64_t uiZ0;
    67      union { struct extFloat80M s; extFloat80_t f; } uZ;
    68  
    69      /*------------------------------------------------------------------------
    70      *------------------------------------------------------------------------*/
    71      uA.f = a;
    72      uiA64 = uA.s.signExp;
    73      uiA0  = uA.s.signif;
    74      signA = signExtF80UI64( uiA64 );
    75      expA  = expExtF80UI64( uiA64 );
    76      sigA  = uiA0;
    77      uB.f = b;
    78      uiB64 = uB.s.signExp;
    79      uiB0  = uB.s.signif;
    80      expB  = expExtF80UI64( uiB64 );
    81      sigB  = uiB0;
    82      /*------------------------------------------------------------------------
    83      *------------------------------------------------------------------------*/
    84      if ( expA == 0x7FFF ) {
    85          if (
    86                 (sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
    87              || ((expB == 0x7FFF) && (sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF )))
    88          ) {
    89              goto propagateNaN;
    90          }
    91          goto invalid;
    92      }
    93      if ( expB == 0x7FFF ) {
    94          if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN;
    95          /*--------------------------------------------------------------------
    96          | Argument b is an infinity.  Doubling `expB' is an easy way to ensure
    97          | that `expDiff' later is less than -1, which will result in returning
    98          | a canonicalized version of argument a.
    99          *--------------------------------------------------------------------*/
   100          expB += expB;
   101      }
   102      /*------------------------------------------------------------------------
   103      *------------------------------------------------------------------------*/
   104      if ( ! expB ) expB = 1;
   105      if ( ! (sigB & UINT64_C( 0x8000000000000000 )) ) {
   106          if ( ! sigB ) goto invalid;
   107          normExpSig = softfloat_normSubnormalExtF80Sig( sigB );
   108          expB += normExpSig.exp;
   109          sigB = normExpSig.sig;
   110      }
   111      if ( ! expA ) expA = 1;
   112      if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) {
   113          if ( ! sigA ) {
   114              expA = 0;
   115              goto copyA;
   116          }
   117          normExpSig = softfloat_normSubnormalExtF80Sig( sigA );
   118          expA += normExpSig.exp;
   119          sigA = normExpSig.sig;
   120      }
   121      /*------------------------------------------------------------------------
   122      *------------------------------------------------------------------------*/
   123      expDiff = expA - expB;
   124      if ( expDiff < -1 ) goto copyA;
   125      rem = softfloat_shortShiftLeft128( 0, sigA, 32 );
   126      shiftedSigB = softfloat_shortShiftLeft128( 0, sigB, 32 );
   127      if ( expDiff < 1 ) {
   128          if ( expDiff ) {
   129              --expB;
   130              shiftedSigB = softfloat_shortShiftLeft128( 0, sigB, 33 );
   131              q = 0;
   132          } else {
   133              q = (sigB <= sigA);
   134              if ( q ) {
   135                  rem =
   136                      softfloat_sub128(
   137                          rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0 );
   138              }
   139          }
   140      } else {
   141          recip32 = softfloat_approxRecip32_1( sigB>>32 );
   142          expDiff -= 30;
   143          for (;;) {
   144              q64 = (uint_fast64_t) (uint32_t) (rem.v64>>2) * recip32;
   145              if ( expDiff < 0 ) break;
   146              q = (q64 + 0x80000000)>>32;
   147              rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
   148              term = softfloat_mul64ByShifted32To128( sigB, q );
   149              rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
   150              if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
   151                  rem =
   152                      softfloat_add128(
   153                          rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0 );
   154              }
   155              expDiff -= 29;
   156          }
   157          /*--------------------------------------------------------------------
   158          | (`expDiff' cannot be less than -29 here.)
   159          *--------------------------------------------------------------------*/
   160          q = (uint32_t) (q64>>32)>>(~expDiff & 31);
   161          rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, expDiff + 30 );
   162          term = softfloat_mul64ByShifted32To128( sigB, q );
   163          rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
   164          if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
   165              altRem =
   166                  softfloat_add128(
   167                      rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0 );
   168              goto selectRem;
   169          }
   170      }
   171      /*------------------------------------------------------------------------
   172      *------------------------------------------------------------------------*/
   173      do {
   174          altRem = rem;
   175          ++q;
   176          rem =
   177              softfloat_sub128(
   178                  rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0 );
   179      } while ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) );
   180   selectRem:
   181      meanRem = softfloat_add128( rem.v64, rem.v0, altRem.v64, altRem.v0 );
   182      if (
   183          (meanRem.v64 & UINT64_C( 0x8000000000000000 ))
   184              || (! (meanRem.v64 | meanRem.v0) && (q & 1))
   185      ) {
   186          rem = altRem;
   187      }
   188      signRem = signA;
   189      if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
   190          signRem = ! signRem;
   191          rem = softfloat_sub128( 0, 0, rem.v64, rem.v0 );
   192      }
   193      return
   194          softfloat_normRoundPackToExtF80(
   195              signRem, rem.v64 | rem.v0 ? expB + 32 : 0, rem.v64, rem.v0, 80 );
   196      /*------------------------------------------------------------------------
   197      *------------------------------------------------------------------------*/
   198   propagateNaN:
   199      uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 );
   200      uiZ64 = uiZ.v64;
   201      uiZ0  = uiZ.v0;
   202      goto uiZ;
   203      /*------------------------------------------------------------------------
   204      *------------------------------------------------------------------------*/
   205   invalid:
   206      softfloat_raiseFlags( softfloat_flag_invalid );
   207      uiZ64 = defaultNaNExtF80UI64;
   208      uiZ0  = defaultNaNExtF80UI0;
   209      goto uiZ;
   210      /*------------------------------------------------------------------------
   211      *------------------------------------------------------------------------*/
   212   copyA:
   213      if ( expA < 1 ) {
   214          sigA >>= 1 - expA;
   215          expA = 0;
   216      }
   217      uiZ64 = packToExtF80UI64( signA, expA );
   218      uiZ0  = sigA;
   219   uiZ:
   220      uZ.s.signExp = uiZ64;
   221      uZ.s.signif  = uiZ0;
   222      return uZ.f;
   223  
   224  }
   225