github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/3rd_party/SoftFloat-3e/source/extF80M_roundToInt.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, 2017 The Regents of the University of
     8  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  #ifdef SOFTFLOAT_FAST_INT64
    45  
    46  void
    47   extF80M_roundToInt(
    48       const extFloat80_t *aPtr,
    49       uint_fast8_t roundingMode,
    50       bool exact,
    51       extFloat80_t *zPtr
    52   )
    53  {
    54  
    55      *zPtr = extF80_roundToInt( *aPtr, roundingMode, exact );
    56  
    57  }
    58  
    59  #else
    60  
    61  void
    62   extF80M_roundToInt(
    63       const extFloat80_t *aPtr,
    64       uint_fast8_t roundingMode,
    65       bool exact,
    66       extFloat80_t *zPtr
    67   )
    68  {
    69      const struct extFloat80M *aSPtr;
    70      struct extFloat80M *zSPtr;
    71      uint_fast16_t uiA64, signUI64;
    72      int32_t exp;
    73      uint64_t sigA;
    74      uint_fast16_t uiZ64;
    75      uint64_t sigZ, lastBitMask, roundBitsMask;
    76  
    77      /*------------------------------------------------------------------------
    78      *------------------------------------------------------------------------*/
    79      aSPtr = (const struct extFloat80M *) aPtr;
    80      zSPtr = (struct extFloat80M *) zPtr;
    81      /*------------------------------------------------------------------------
    82      *------------------------------------------------------------------------*/
    83      uiA64 = aSPtr->signExp;
    84      signUI64 = uiA64 & packToExtF80UI64( 1, 0 );
    85      exp = expExtF80UI64( uiA64 );
    86      sigA = aSPtr->signif;
    87      /*------------------------------------------------------------------------
    88      *------------------------------------------------------------------------*/
    89      if ( !(sigA & UINT64_C( 0x8000000000000000 )) && (exp != 0x7FFF) ) {
    90          if ( !sigA ) {
    91              uiZ64 = signUI64;
    92              sigZ = 0;
    93              goto uiZ;
    94          }
    95          exp += softfloat_normExtF80SigM( &sigA );
    96      }
    97      /*------------------------------------------------------------------------
    98      *------------------------------------------------------------------------*/
    99      if ( exp <= 0x3FFE ) {
   100          if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
   101          switch ( roundingMode ) {
   102           case softfloat_round_near_even:
   103              if ( !(sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) break;
   104           case softfloat_round_near_maxMag:
   105              if ( exp == 0x3FFE ) goto mag1;
   106              break;
   107           case softfloat_round_min:
   108              if ( signUI64 ) goto mag1;
   109              break;
   110           case softfloat_round_max:
   111              if ( !signUI64 ) goto mag1;
   112              break;
   113  #ifdef SOFTFLOAT_ROUND_ODD
   114           case softfloat_round_odd:
   115              goto mag1;
   116  #endif
   117          }
   118          uiZ64 = signUI64;
   119          sigZ = 0;
   120          goto uiZ;
   121       mag1:
   122          uiZ64 = signUI64 | 0x3FFF;
   123          sigZ = UINT64_C( 0x8000000000000000 );
   124          goto uiZ;
   125      }
   126      /*------------------------------------------------------------------------
   127      *------------------------------------------------------------------------*/
   128      if ( 0x403E <= exp ) {
   129          if ( exp == 0x7FFF ) {
   130              if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) {
   131                  softfloat_propagateNaNExtF80M( aSPtr, 0, zSPtr );
   132                  return;
   133              }
   134              sigZ = UINT64_C( 0x8000000000000000 );
   135          } else {
   136              sigZ = sigA;
   137          }
   138          uiZ64 = signUI64 | exp;
   139          goto uiZ;
   140      }
   141      /*------------------------------------------------------------------------
   142      *------------------------------------------------------------------------*/
   143      uiZ64 = signUI64 | exp;
   144      lastBitMask = (uint64_t) 1<<(0x403E - exp);
   145      roundBitsMask = lastBitMask - 1;
   146      sigZ = sigA;
   147      if ( roundingMode == softfloat_round_near_maxMag ) {
   148          sigZ += lastBitMask>>1;
   149      } else if ( roundingMode == softfloat_round_near_even ) {
   150          sigZ += lastBitMask>>1;
   151          if ( !(sigZ & roundBitsMask) ) sigZ &= ~lastBitMask;
   152      } else if (
   153          roundingMode == (signUI64 ? softfloat_round_min : softfloat_round_max)
   154      ) {
   155          sigZ += roundBitsMask;
   156      }
   157      sigZ &= ~roundBitsMask;
   158      if ( !sigZ ) {
   159          ++uiZ64;
   160          sigZ = UINT64_C( 0x8000000000000000 );
   161      }
   162      if ( sigZ != sigA ) {
   163  #ifdef SOFTFLOAT_ROUND_ODD
   164          if ( roundingMode == softfloat_round_odd ) sigZ |= lastBitMask;
   165  #endif
   166          if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
   167      }
   168   uiZ:
   169      zSPtr->signExp = uiZ64;
   170      zSPtr->signif = sigZ;
   171      return;
   172  
   173  }
   174  
   175  #endif
   176