⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch24safe.c

📁 稀疏矩阵、链表、图、队列、二叉树、多叉树、排序、遗传算法等的实现
💻 C
📖 第 1 页 / 共 3 页
字号:
      /* If we are raising errors, then raise the error, otherwise    */
      /* return to the caller with a zero value:                      */
      if ( RaiseError )
      {
         raise ( ARITHMETIC_PRECISION_BAD );
      } 

      /* return to caller with computed value:                        */
      return ( flpReturnValue );

   } else {

      /* All is well: set the return value to the computed value:     */
      flpReturnValue = flpLocalReturnValue;

      /* Look at the resultant precision and compare it in magnitude  */
      /* to the result. If better than ARITHMETIC_ACCEPT_PRECISION    */
      /* then accept it, otherwise raise an error:                    */
      /* In any case, return it to the caller:                        */
      if ( pflpResultPrecision != NULL )
          *pflpResultPrecision = flpLocalResultPrecision;

      /* Note that the following calculation is done as a multiplica- */
      /* tion to avoid having to do all the division tests. The cross-*/
      /* multiplication of the inequality                             */
      /*      (error / value) > acceptable_precision                  */
      /* works for all values of "value"                              */
      if ( flpLocalResultPrecision  >
           ( fabs ( flpReturnValue ) > DBL_EPSILON ?
               ( fabs ( flpReturnValue ) * ARITHMETIC_ACCEPT_PRECISION ) : 
               DBL_EPSILON ) )
      {

         /* Indicate the error we have detected:                      */
         if ( pErrorRaised != NULL )
             *pErrorRaised = ARITHMETIC_BEYOND_RANGE;
      
         /* If we are raising errors, then raise the error:           */
         if ( RaiseError )
         {
            raise ( ARITHMETIC_BEYOND_RANGE );
         }  /* end of "if/then" raising ARITHMETIC_BEYOND_RANGE error */ 
      }     /* end of "if/then" precision is bad                      */
   }        /* end of "if/else" result lies with acceptable range     */
   
   /* Return to caller with the computed value:                       */
   return ( flpReturnValue );

}

/***********************************************************************
 * This is the first ("simple") safe addition procedure for floating   *
 * (double) values. It calls the "complex" safe addition procedure     *
 * (flpSafeAddSensitive), indicating that no errors are to be          *
 * raised, to perform the body of the calculation.                     *
 ***********************************************************************/


/***********************************************************************
 * Name:          flpSafeAdd
 * 
 * Description:   This function performs a safe floating-point add
 *                operation, without signalling errors
 *                
 * Parameters: 
 *    flpFirstAddend        the first Addend
 *    flpSecondAddend       the second Addend
 * 
 * External/Global variables:
 *    N/A
 *
 * Returns:
 *    the sum, as a double
 * 
 **********************************************************************/

double flpSafeAdd (double flpFirstAddend,
                   double flpSecondAddend)
{
  double flpReturnValue = 0.0;
   
  flpReturnValue =  flpSafeAddSensitive ( flpFirstAddend, 0.0,
                                          flpSecondAddend, 0.0,
                                          NULL, FALSE, NULL);
  
  return (flpReturnValue);
 
} 

/***********************************************************************/

/***********************************************************************
 * This is the second ("complex") level Safe Subtraction function for  *
 * double operands, which may raise error conditions, and indicates to *
 * the caller the precision of the result.                             *
 ***********************************************************************/

/***********************************************************************
 * Name:          flpSafeSubtractSensitive
 * 
 * Description:   This function performs a safe floating-point subtract
 *                operation, with detection and signalling of errors
 *                
 * Parameters: 
 *    flpMinuend              the Minuend
 *    flpMinuendPrecision     precision of the minuend
 *    flpSubtrahend           the Subtrahend
 *    flpSubtrahendPrecision  precision of the subtrahend
 *    pflpResultPrecision     pointer to a double which will contain
 *                            the resultant precision after the subtract.
 *                            If this pointer is NULL it is not used
 *    RaiseError              An int containing a logical value. 
 *                            If TRUE then errors will be Raised, if
 *                            FALSE they will not, even if detected
 *    pErrorRaised            An int * pointing to a word containing
 *                            error indication. If this pointer is NULL
 *                            then it is not used
 * 
 * External/Global variables:
 *    N/A
 *
 * Returns:
 *    the difference, as a double
 *    the result precision, if requested
 *    the error condition, if requested
 *    Raises a signal error, if requested, and required
 * 
 **********************************************************************/

double flpSafeSubtractSensitive ( double flpMinuend,
                                  double flpMinuendPrecision,
                                  double flpSubtrahend,
                                  double flpSubtrahendPrecision,
                                  double * pflpResultPrecision,
                                  int RaiseError, int * pErrorRaised )
{
  double flpReturnValue           = 0.0;
  
  /* Since subtraction is simply the reverse of addition, we call the */
  /* Safe Addition function to perform the body:                      */
  flpReturnValue = flpSafeAddSensitive ( 
                          flpMinuend,  flpMinuendPrecision,
                        - flpSubtrahend, flpSubtrahendPrecision,
                          pflpResultPrecision, RaiseError, pErrorRaised );
  
  return (flpReturnValue);
 
} 

/***********************************************************************
 * This is the first ("simple") safe Subtraction procedure for floating*
 * (double) values. It calls the "complex" safe Subtraction procedure  *
 * (flpSafeSubtractSensitive), indicating that no errors are to be     *
 * raised, to perform the body of the calculation.                     *
 ***********************************************************************/

/***********************************************************************
 * Name:          flpSafeSubtract
 * 
 * Description:   This function performs a safe floating-point subtract
 *                operation, without signalling any errors
 *                
 * Parameters: 
 *    flpMinuend        the Minuend
 *    flpSubtrahend     the Subtrahend
 * 
 * External/Global variables:
 *    N/A
 *
 * Returns:
 *    the difference, as a double
 * 
 **********************************************************************/

double flpSafeSubtract (double flpMinuend,
                        double flpSubtrahend)
{
  double flpReturnValue = 0.0;
   
  flpReturnValue =  flpSafeSubtractSensitive ( flpMinuend, 0.0,
                                               flpSubtrahend, 0.0,
                                               NULL, FALSE, NULL);
  
  return (flpReturnValue);
 
} 

/***********************************************************************/

/***********************************************************************
 * Name: flpcmp
 *
 * Description:
 *  Tests two real numbers (doubles) according to the conditional
 *  operator provided. The inequality is checked using a defined epsilon
 *  value to determine if the values are equivalent if not exactly equal
 *  to reduce the risk of errors in floating point calculations.
 *  If an invalid conditional operator is specified SIGILL will be raised.
 *
 * Parameters:
 *  dA (in)       - Value to test.
 *  sCond (in)    - String containing the conditional operator, may be
 *                  "==", "!=", "<=", ">=", "<", or ">".
 *  dB (in)       - Value to test.
 *
 * External/Global variables:
 *    N/A
 *
 * Returns:
 *  TRUE  - Condition is true.
 *  FALSE - condition is false.
 *
 ***********************************************************************/

int flpcmp( double dA, char *sCond, double dB )
{
   /* Variable declarations. */
   int iStatus = -1;
   int iEqual = -1;
   int iALargerThanB = -1;
   double dBig, dAbsDiff, dDelta;

   /* Get the input value with the largest absolute value. We want the largest
      of the two values  as this will minimize the introduction of any further
      errors to the inequality when we multiply by epsilon. */
   dBig = fabs( ( fabs( dA ) > fabs( dB ) ) ? dA : dB );

   /* Apply epsilon to the largest absolute value to get the value delta which
      is maximum difference between the two values which can be considered to
      be the same value. */
   dDelta = dBig * COMPARE_EPSILON;

   /* Get the absolute difference between the two values. */
   dAbsDiff = fabs( dA - dB );

   /* Test the absolute difference against the delta value to determine if
      'dA' and 'dB' are equivalent. */
   iEqual = ( dAbsDiff <= dDelta ) ? TRUE : FALSE;

   /* Determine if 'a' is larger than 'b' regardless of epsilon. */
   iALargerThanB = dA > dB;

   /* Set the return status of the function according to the equality operator
      provided. */
   if ( 0 == strcmp( sCond, "==" ) )
   {
      iStatus = iEqual;
   }
   else if ( 0 == strcmp( sCond, "!=" ) )
   {
      iStatus = !iEqual;
   }
   else if ( 0 == strcmp( sCond, "<=" ) )
   {
      iStatus = ( !iALargerThanB ) || iEqual;
   }
   else if ( 0 == strcmp( sCond, ">=" ) )
   {
      iStatus = iALargerThanB || iEqual;
   }
   else if ( 0 == strcmp( sCond, "<" ) )
   {
      iStatus = ( !iALargerThanB ) && ( !iEqual );
   }
   else if ( 0 == strcmp( sCond, ">" ) )
   {
      iStatus = iALargerThanB && ( !iEqual );
   }
   else
   {
      /* Error condition.
         This case should never arise with correct use of this function, if it
         does we will treat this as an illegal instruction. */
      raise( ARITHMETIC_ILLEGAL_COMPARE );
   }

   /* Return the status of the conditional operation. */
   return iStatus;
}

/***********************************************************************
 * Name: flpSetEquivalent;
 *
 * Description:
 *  If the variables provided are equivalent according to epsilon both
 *  are set to the variable with the highest absolute value. If the
 *  variables are not equivalent then the function returns false.
 *
 * Parameters:
 *  dA (in/out) - 
 *  dB (in/out) - 
 *
 * External/Global variables:
 *  N/A
 *
 * Returns:
 *  TRUE  - Variables are equivalent.
 *  FALSE - Variables provided are not equivalent.
 *
 ***********************************************************************/

int flpSetEquivalent( double *dA, double *dB )
{
   /* Variable declarations. */
   int iStatus = FALSE;

   /* Determine if the two values are equivalent. */
   iStatus = flpcmp( *dA, "==", *dB );

   /* If the values are equivalent set both values to the value with the
      highest absolute value of the two. */
   if ( TRUE == iStatus )
   {
      if ( fabs( *dA ) > fabs( *dB ) )
      {
         *dB = *dA;
      }
      else
      {
         *dA = *dB;
      }
   }

   return iStatus;
}

/***********************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -