You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							1053 lines
						
					
					
						
							22 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							1053 lines
						
					
					
						
							22 KiB
						
					
					
				| /** | |
|   @file | |
|  | |
|   @ingroup epd | |
|  | |
|   @brief Arithmetic functions with extended double precision. | |
|  | |
|   @author In-Ho Moon | |
|  | |
|   @copyright@parblock | |
|   Copyright (c) 1995-2015, Regents of the University of Colorado | |
|  | |
|   All rights reserved. | |
|  | |
|   Redistribution and use in source and binary forms, with or without | |
|   modification, are permitted provided that the following conditions | |
|   are met: | |
|  | |
|   Redistributions of source code must retain the above copyright | |
|   notice, this list of conditions and the following disclaimer. | |
|  | |
|   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. | |
|  | |
|   Neither the name of the University of Colorado 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 COPYRIGHT HOLDERS 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 | |
|   COPYRIGHT OWNER 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. | |
|   @endparblock | |
|  | |
| */ | |
| 
 | |
| #include <math.h> | |
| #include "util.h" | |
| #include "epdInt.h" | |
|  | |
| 
 | |
| /** | |
|   @brief Allocates an EpDouble struct. | |
| */ | |
| EpDouble * | |
| EpdAlloc(void) | |
| { | |
|   EpDouble	*epd; | |
| 
 | |
|   epd = ALLOC(EpDouble, 1); | |
|   return(epd); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Compares two EpDouble struct. | |
|  | |
|   @return 0 if the two structures hold the same value; 1 otherwise. | |
| */ | |
| int | |
| EpdCmp(const void *key1, const void *key2) | |
| { | |
|   EpDouble const *epd1 = (EpDouble const *) key1; | |
|   EpDouble const *epd2 = (EpDouble const *) key2; | |
|   if (epd1->type.value != epd2->type.value || | |
|       epd1->exponent != epd2->exponent) { | |
|     return(1); | |
|   } | |
|   return(0); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Frees an EpDouble struct. | |
| */ | |
| void | |
| EpdFree(EpDouble *epd) | |
| { | |
|   FREE(epd); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Converts an extended precision double value to a string. | |
|  | |
|   @sideeffect The string is written at the address passed in `str`. | |
| */ | |
| void | |
| EpdGetString(EpDouble const *epd, char *str) | |
| { | |
|   double	value; | |
|   int		exponent; | |
|   char		*pos; | |
| 
 | |
|   if (!str) return; | |
| 
 | |
|   if (IsNanDouble(epd->type.value)) { | |
|     sprintf(str, "NaN"); | |
|     return; | |
|   } else if (IsInfDouble(epd->type.value)) { | |
|     if (epd->type.bits.sign == 1) | |
|       sprintf(str, "-inf"); | |
|     else | |
|       sprintf(str, "inf"); | |
|     return; | |
|   } | |
| 
 | |
|   assert(epd->type.bits.exponent == EPD_MAX_BIN || | |
| 	 epd->type.bits.exponent == 0); | |
| 
 | |
|   EpdGetValueAndDecimalExponent(epd, &value, &exponent); | |
|   sprintf(str, "%e", value); | |
|   pos = strstr(str, "e"); | |
|   if (exponent >= 0) { | |
|     if (exponent < 10) | |
|       sprintf(pos + 1, "+0%d", exponent); | |
|     else | |
|       sprintf(pos + 1, "+%d", exponent); | |
|   } else { | |
|     exponent *= -1; | |
|     if (exponent < 10) | |
|       sprintf(pos + 1, "-0%d", exponent); | |
|     else | |
|       sprintf(pos + 1, "-%d", exponent); | |
|   } | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Converts double to EpDouble struct. | |
| */ | |
| void | |
| EpdConvert(double value, EpDouble *epd) | |
| { | |
|   epd->type.value = value; | |
|   epd->exponent = 0; | |
|   EpdNormalize(epd); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Multiplies an extended precision double by a double. | |
| */ | |
| void | |
| EpdMultiply(EpDouble *epd1, double value) | |
| { | |
|   EpDouble	epd2; | |
|   double	tmp; | |
|   int		exponent; | |
| 
 | |
|   if (EpdIsNan(epd1) || IsNanDouble(value)) { | |
|     EpdMakeNan(epd1); | |
|     return; | |
|   } else if (EpdIsInf(epd1) || IsInfDouble(value)) { | |
|     int	sign; | |
| 
 | |
|     EpdConvert(value, &epd2); | |
|     sign = epd1->type.bits.sign ^ epd2.type.bits.sign; | |
|     EpdMakeInf(epd1, sign); | |
|     return; | |
|   } | |
| 
 | |
|   assert(epd1->type.bits.exponent == EPD_MAX_BIN); | |
| 
 | |
|   EpdConvert(value, &epd2); | |
|   tmp = epd1->type.value * epd2.type.value; | |
|   exponent = epd1->exponent + epd2.exponent; | |
|   epd1->type.value = tmp; | |
|   epd1->exponent = exponent; | |
|   EpdNormalize(epd1); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Multiplies an extended precision double by another. | |
| */ | |
| void | |
| EpdMultiply2(EpDouble *epd1, EpDouble const *epd2) | |
| { | |
|   double	value; | |
|   int		exponent; | |
| 
 | |
|   if (EpdIsNan(epd1) || EpdIsNan(epd2)) { | |
|     EpdMakeNan(epd1); | |
|     return; | |
|   } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { | |
|     int	sign; | |
| 
 | |
|     sign = epd1->type.bits.sign ^ epd2->type.bits.sign; | |
|     EpdMakeInf(epd1, sign); | |
|     return; | |
|   } | |
| 
 | |
|   assert(epd1->type.bits.exponent == EPD_MAX_BIN); | |
|   assert(epd2->type.bits.exponent == EPD_MAX_BIN); | |
| 
 | |
|   value = epd1->type.value * epd2->type.value; | |
|   exponent = epd1->exponent + epd2->exponent; | |
|   epd1->type.value = value; | |
|   epd1->exponent = exponent; | |
|   EpdNormalize(epd1); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Multiplies two extended precision double values. | |
| */ | |
| void | |
| EpdMultiply2Decimal(EpDouble *epd1, EpDouble const *epd2) | |
| { | |
|   double	value; | |
|   int		exponent; | |
| 
 | |
|   if (EpdIsNan(epd1) || EpdIsNan(epd2)) { | |
|     EpdMakeNan(epd1); | |
|     return; | |
|   } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { | |
|     int	sign; | |
| 
 | |
|     sign = epd1->type.bits.sign ^ epd2->type.bits.sign; | |
|     EpdMakeInf(epd1, sign); | |
|     return; | |
|   } | |
| 
 | |
|   value = epd1->type.value * epd2->type.value; | |
|   exponent = epd1->exponent + epd2->exponent; | |
|   epd1->type.value = value; | |
|   epd1->exponent = exponent; | |
|   EpdNormalizeDecimal(epd1); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Multiplies two extended precision double values. | |
|  | |
|   @details The result goes in the third operand. | |
| */ | |
| void | |
| EpdMultiply3(EpDouble const *epd1, EpDouble const *epd2, EpDouble *epd3) | |
| { | |
|   if (EpdIsNan(epd1) || EpdIsNan(epd2)) { | |
|     EpdMakeNan(epd3); | |
|     return; | |
|   } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { | |
|     int	sign; | |
| 
 | |
|     sign = epd1->type.bits.sign ^ epd2->type.bits.sign; | |
|     EpdMakeInf(epd3, sign); | |
|     return; | |
|   } | |
| 
 | |
|   assert(epd1->type.bits.exponent == EPD_MAX_BIN); | |
|   assert(epd2->type.bits.exponent == EPD_MAX_BIN); | |
| 
 | |
|   epd3->type.value = epd1->type.value * epd2->type.value; | |
|   epd3->exponent = epd1->exponent + epd2->exponent; | |
|   EpdNormalize(epd3); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Multiplies two extended precision double values. | |
| */ | |
| void | |
| EpdMultiply3Decimal(EpDouble const *epd1, EpDouble const *epd2, EpDouble *epd3) | |
| { | |
|   if (EpdIsNan(epd1) || EpdIsNan(epd2)) { | |
|     EpdMakeNan(epd3); | |
|     return; | |
|   } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { | |
|     int	sign; | |
| 
 | |
|     sign = epd1->type.bits.sign ^ epd2->type.bits.sign; | |
|     EpdMakeInf(epd3, sign); | |
|     return; | |
|   } | |
| 
 | |
|   epd3->type.value = epd1->type.value * epd2->type.value; | |
|   epd3->exponent = epd1->exponent + epd2->exponent; | |
|   EpdNormalizeDecimal(epd3); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Divides an extended precision double by a double. | |
| */ | |
| void | |
| EpdDivide(EpDouble *epd1, double value) | |
| { | |
|   EpDouble	epd2; | |
|   double	tmp; | |
|   int		exponent; | |
| 
 | |
|   if (EpdIsNan(epd1) || IsNanDouble(value)) { | |
|     EpdMakeNan(epd1); | |
|     return; | |
|   } else if (EpdIsInf(epd1) || IsInfDouble(value)) { | |
|     int	sign; | |
| 
 | |
|     EpdConvert(value, &epd2); | |
|     if (EpdIsInf(epd1) && IsInfDouble(value)) { | |
|       EpdMakeNan(epd1); | |
|     } else if (EpdIsInf(epd1)) { | |
|       sign = epd1->type.bits.sign ^ epd2.type.bits.sign; | |
|       EpdMakeInf(epd1, sign); | |
|     } else { | |
|       sign = epd1->type.bits.sign ^ epd2.type.bits.sign; | |
|       EpdMakeZero(epd1, sign); | |
|     } | |
|     return; | |
|   } | |
| 
 | |
|   if (value == 0.0) { | |
|     EpdMakeNan(epd1); | |
|     return; | |
|   } | |
| 
 | |
|   assert(epd1->type.bits.exponent == EPD_MAX_BIN); | |
| 
 | |
|   EpdConvert(value, &epd2); | |
|   tmp = epd1->type.value / epd2.type.value; | |
|   exponent = epd1->exponent - epd2.exponent; | |
|   epd1->type.value = tmp; | |
|   epd1->exponent = exponent; | |
|   EpdNormalize(epd1); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Divides an extended precision double by another. | |
| */ | |
| void | |
| EpdDivide2(EpDouble *epd1, EpDouble const *epd2) | |
| { | |
|   double	value; | |
|   int		exponent; | |
| 
 | |
|   if (EpdIsNan(epd1) || EpdIsNan(epd2)) { | |
|     EpdMakeNan(epd1); | |
|     return; | |
|   } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { | |
|     int	sign; | |
| 
 | |
|     if (EpdIsInf(epd1) && EpdIsInf(epd2)) { | |
|       EpdMakeNan(epd1); | |
|     } else if (EpdIsInf(epd1)) { | |
|       sign = epd1->type.bits.sign ^ epd2->type.bits.sign; | |
|       EpdMakeInf(epd1, sign); | |
|     } else { | |
|       sign = epd1->type.bits.sign ^ epd2->type.bits.sign; | |
|       EpdMakeZero(epd1, sign); | |
|     } | |
|     return; | |
|   } | |
| 
 | |
|   if (epd2->type.value == 0.0) { | |
|     EpdMakeNan(epd1); | |
|     return; | |
|   } | |
| 
 | |
|   assert(epd1->type.bits.exponent == EPD_MAX_BIN); | |
|   assert(epd2->type.bits.exponent == EPD_MAX_BIN); | |
| 
 | |
|   value = epd1->type.value / epd2->type.value; | |
|   exponent = epd1->exponent - epd2->exponent; | |
|   epd1->type.value = value; | |
|   epd1->exponent = exponent; | |
|   EpdNormalize(epd1); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Divides two extended precision double values. | |
| */ | |
| void | |
| EpdDivide3(EpDouble const *epd1, EpDouble const *epd2, EpDouble *epd3) | |
| { | |
|   if (EpdIsNan(epd1) || EpdIsNan(epd2)) { | |
|     EpdMakeNan(epd3); | |
|     return; | |
|   } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { | |
|     int	sign; | |
| 
 | |
|     if (EpdIsInf(epd1) && EpdIsInf(epd2)) { | |
|       EpdMakeNan(epd3); | |
|     } else if (EpdIsInf(epd1)) { | |
|       sign = epd1->type.bits.sign ^ epd2->type.bits.sign; | |
|       EpdMakeInf(epd3, sign); | |
|     } else { | |
|       sign = epd1->type.bits.sign ^ epd2->type.bits.sign; | |
|       EpdMakeZero(epd3, sign); | |
|     } | |
|     return; | |
|   } | |
| 
 | |
|   if (epd2->type.value == 0.0) { | |
|     EpdMakeNan(epd3); | |
|     return; | |
|   } | |
| 
 | |
|   assert(epd1->type.bits.exponent == EPD_MAX_BIN); | |
|   assert(epd2->type.bits.exponent == EPD_MAX_BIN); | |
| 
 | |
|   epd3->type.value = epd1->type.value / epd2->type.value; | |
|   epd3->exponent = epd1->exponent - epd2->exponent; | |
|   EpdNormalize(epd3); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Adds a double to an extended precision double. | |
| */ | |
| void | |
| EpdAdd(EpDouble *epd1, double value) | |
| { | |
|   EpDouble	epd2; | |
|   double	tmp; | |
|   int		exponent, diff; | |
| 
 | |
|   if (EpdIsNan(epd1) || IsNanDouble(value)) { | |
|     EpdMakeNan(epd1); | |
|     return; | |
|   } else if (EpdIsInf(epd1) || IsInfDouble(value)) { | |
|     int	sign; | |
| 
 | |
|     EpdConvert(value, &epd2); | |
|     if (EpdIsInf(epd1) && IsInfDouble(value)) { | |
|       sign = epd1->type.bits.sign ^ epd2.type.bits.sign; | |
|       if (sign == 1) | |
| 	EpdMakeNan(epd1); | |
|     } else if (EpdIsInf(&epd2)) { | |
|       EpdCopy(&epd2, epd1); | |
|     } | |
|     return; | |
|   } | |
| 
 | |
|   assert(epd1->type.bits.exponent == EPD_MAX_BIN); | |
| 
 | |
|   EpdConvert(value, &epd2); | |
|   if (epd1->exponent > epd2.exponent) { | |
|     diff = epd1->exponent - epd2.exponent; | |
|     if (diff <= EPD_MAX_BIN) | |
|       tmp = epd1->type.value + epd2.type.value / pow((double)2.0, (double)diff); | |
|     else | |
|       tmp = epd1->type.value; | |
|     exponent = epd1->exponent; | |
|   } else if (epd1->exponent < epd2.exponent) { | |
|     diff = epd2.exponent - epd1->exponent; | |
|     if (diff <= EPD_MAX_BIN) | |
|       tmp = epd1->type.value / pow((double)2.0, (double)diff) + epd2.type.value; | |
|     else | |
|       tmp = epd2.type.value; | |
|     exponent = epd2.exponent; | |
|   } else { | |
|     tmp = epd1->type.value + epd2.type.value; | |
|     exponent = epd1->exponent; | |
|   } | |
|   epd1->type.value = tmp; | |
|   epd1->exponent = exponent; | |
|   EpdNormalize(epd1); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Adds an extended precision double to another. | |
|  | |
|   @details The sum goes in the first argument. | |
| */ | |
| void | |
| EpdAdd2(EpDouble *epd1, EpDouble const *epd2) | |
| { | |
|   double	value; | |
|   int		exponent, diff; | |
| 
 | |
|   if (EpdIsNan(epd1) || EpdIsNan(epd2)) { | |
|     EpdMakeNan(epd1); | |
|     return; | |
|   } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { | |
|     int	sign; | |
| 
 | |
|     if (EpdIsInf(epd1) && EpdIsInf(epd2)) { | |
|       sign = epd1->type.bits.sign ^ epd2->type.bits.sign; | |
|       if (sign == 1) | |
| 	EpdMakeNan(epd1); | |
|     } else if (EpdIsInf(epd2)) { | |
|       EpdCopy(epd2, epd1); | |
|     } | |
|     return; | |
|   } | |
| 
 | |
|   assert(epd1->type.bits.exponent == EPD_MAX_BIN); | |
|   assert(epd2->type.bits.exponent == EPD_MAX_BIN); | |
| 
 | |
|   if (epd1->exponent > epd2->exponent) { | |
|     diff = epd1->exponent - epd2->exponent; | |
|     if (diff <= EPD_MAX_BIN) { | |
|       value = epd1->type.value + | |
| 		epd2->type.value / pow((double)2.0, (double)diff); | |
|     } else | |
|       value = epd1->type.value; | |
|     exponent = epd1->exponent; | |
|   } else if (epd1->exponent < epd2->exponent) { | |
|     diff = epd2->exponent - epd1->exponent; | |
|     if (diff <= EPD_MAX_BIN) { | |
|       value = epd1->type.value / pow((double)2.0, (double)diff) + | |
| 		epd2->type.value; | |
|     } else | |
|       value = epd2->type.value; | |
|     exponent = epd2->exponent; | |
|   } else { | |
|     value = epd1->type.value + epd2->type.value; | |
|     exponent = epd1->exponent; | |
|   } | |
|   epd1->type.value = value; | |
|   epd1->exponent = exponent; | |
|   EpdNormalize(epd1); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Adds two extended precision double values. | |
| */ | |
| void | |
| EpdAdd3(EpDouble const *epd1, EpDouble const *epd2, EpDouble *epd3) | |
| { | |
|   double	value; | |
|   int		exponent, diff; | |
| 
 | |
|   if (EpdIsNan(epd1) || EpdIsNan(epd2)) { | |
|     EpdMakeNan(epd3); | |
|     return; | |
|   } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { | |
|     int	sign; | |
| 
 | |
|     if (EpdIsInf(epd1) && EpdIsInf(epd2)) { | |
|       sign = epd1->type.bits.sign ^ epd2->type.bits.sign; | |
|       if (sign == 1) | |
| 	EpdMakeNan(epd3); | |
|       else | |
| 	EpdCopy(epd1, epd3); | |
|     } else if (EpdIsInf(epd1)) { | |
|       EpdCopy(epd1, epd3); | |
|     } else { | |
|       EpdCopy(epd2, epd3); | |
|     } | |
|     return; | |
|   } | |
| 
 | |
|   assert(epd1->type.bits.exponent == EPD_MAX_BIN); | |
|   assert(epd2->type.bits.exponent == EPD_MAX_BIN); | |
| 
 | |
|   if (epd1->exponent > epd2->exponent) { | |
|     diff = epd1->exponent - epd2->exponent; | |
|     if (diff <= EPD_MAX_BIN) { | |
|       value = epd1->type.value + | |
| 		epd2->type.value / pow((double)2.0, (double)diff); | |
|     } else | |
|       value = epd1->type.value; | |
|     exponent = epd1->exponent; | |
|   } else if (epd1->exponent < epd2->exponent) { | |
|     diff = epd2->exponent - epd1->exponent; | |
|     if (diff <= EPD_MAX_BIN) { | |
|       value = epd1->type.value / pow((double)2.0, (double)diff) + | |
| 		epd2->type.value; | |
|     } else | |
|       value = epd2->type.value; | |
|     exponent = epd2->exponent; | |
|   } else { | |
|     value = epd1->type.value + epd2->type.value; | |
|     exponent = epd1->exponent; | |
|   } | |
|   epd3->type.value = value; | |
|   epd3->exponent = exponent; | |
|   EpdNormalize(epd3); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Subtracts a double from an extended precision double. | |
| */ | |
| void | |
| EpdSubtract(EpDouble *epd1, double value) | |
| { | |
|   EpDouble	epd2; | |
|   double	tmp; | |
|   int		exponent, diff; | |
| 
 | |
|   if (EpdIsNan(epd1) || IsNanDouble(value)) { | |
|     EpdMakeNan(epd1); | |
|     return; | |
|   } else if (EpdIsInf(epd1) || IsInfDouble(value)) { | |
|     int	sign; | |
| 
 | |
|     EpdConvert(value, &epd2); | |
|     if (EpdIsInf(epd1) && IsInfDouble(value)) { | |
|       sign = epd1->type.bits.sign ^ epd2.type.bits.sign; | |
|       if (sign == 0) | |
| 	EpdMakeNan(epd1); | |
|     } else if (EpdIsInf(&epd2)) { | |
|       EpdCopy(&epd2, epd1); | |
|     } | |
|     return; | |
|   } | |
| 
 | |
|   assert(epd1->type.bits.exponent == EPD_MAX_BIN); | |
| 
 | |
|   EpdConvert(value, &epd2); | |
|   if (epd1->exponent > epd2.exponent) { | |
|     diff = epd1->exponent - epd2.exponent; | |
|     if (diff <= EPD_MAX_BIN) | |
|       tmp = epd1->type.value - epd2.type.value / pow((double)2.0, (double)diff); | |
|     else | |
|       tmp = epd1->type.value; | |
|     exponent = epd1->exponent; | |
|   } else if (epd1->exponent < epd2.exponent) { | |
|     diff = epd2.exponent - epd1->exponent; | |
|     if (diff <= EPD_MAX_BIN) | |
|       tmp = epd1->type.value / pow((double)2.0, (double)diff) - epd2.type.value; | |
|     else | |
|       tmp = epd2.type.value * (double)(-1.0); | |
|     exponent = epd2.exponent; | |
|   } else { | |
|     tmp = epd1->type.value - epd2.type.value; | |
|     exponent = epd1->exponent; | |
|   } | |
|   epd1->type.value = tmp; | |
|   epd1->exponent = exponent; | |
|   EpdNormalize(epd1); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Subtracts an extended precision double from another. | |
| */ | |
| void | |
| EpdSubtract2(EpDouble *epd1, EpDouble const *epd2) | |
| { | |
|   double	value; | |
|   int		exponent, diff; | |
| 
 | |
|   if (EpdIsNan(epd1) || EpdIsNan(epd2)) { | |
|     EpdMakeNan(epd1); | |
|     return; | |
|   } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { | |
|     int	sign; | |
| 
 | |
|     if (EpdIsInf(epd1) && EpdIsInf(epd2)) { | |
|       sign = epd1->type.bits.sign ^ epd2->type.bits.sign; | |
|       if (sign == 0) | |
| 	EpdMakeNan(epd1); | |
|     } else if (EpdIsInf(epd2)) { | |
|       EpdCopy(epd2, epd1); | |
|     } | |
|     return; | |
|   } | |
| 
 | |
|   assert(epd1->type.bits.exponent == EPD_MAX_BIN); | |
|   assert(epd2->type.bits.exponent == EPD_MAX_BIN); | |
| 
 | |
|   if (epd1->exponent > epd2->exponent) { | |
|     diff = epd1->exponent - epd2->exponent; | |
|     if (diff <= EPD_MAX_BIN) { | |
|       value = epd1->type.value - | |
| 		epd2->type.value / pow((double)2.0, (double)diff); | |
|     } else | |
|       value = epd1->type.value; | |
|     exponent = epd1->exponent; | |
|   } else if (epd1->exponent < epd2->exponent) { | |
|     diff = epd2->exponent - epd1->exponent; | |
|     if (diff <= EPD_MAX_BIN) { | |
|       value = epd1->type.value / pow((double)2.0, (double)diff) - | |
| 		epd2->type.value; | |
|     } else | |
|       value = epd2->type.value * (double)(-1.0); | |
|     exponent = epd2->exponent; | |
|   } else { | |
|     value = epd1->type.value - epd2->type.value; | |
|     exponent = epd1->exponent; | |
|   } | |
|   epd1->type.value = value; | |
|   epd1->exponent = exponent; | |
|   EpdNormalize(epd1); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Subtracts two extended precision double values. | |
| */ | |
| void | |
| EpdSubtract3(EpDouble const *epd1, EpDouble const *epd2, EpDouble *epd3) | |
| { | |
|   double	value; | |
|   int		exponent, diff; | |
| 
 | |
|   if (EpdIsNan(epd1) || EpdIsNan(epd2)) { | |
|     EpdMakeNan(epd3); | |
|     return; | |
|   } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { | |
|     int	sign; | |
| 
 | |
|     if (EpdIsInf(epd1) && EpdIsInf(epd2)) { | |
|       sign = epd1->type.bits.sign ^ epd2->type.bits.sign; | |
|       if (sign == 0) | |
| 	EpdCopy(epd1, epd3); | |
|       else | |
| 	EpdMakeNan(epd3); | |
|     } else if (EpdIsInf(epd1)) { | |
|       EpdCopy(epd1, epd3); | |
|     } else { | |
|       sign = epd2->type.bits.sign ^ 0x1; | |
|       EpdMakeInf(epd3, sign); | |
|     } | |
|     return; | |
|   } | |
| 
 | |
|   assert(epd1->type.bits.exponent == EPD_MAX_BIN); | |
|   assert(epd2->type.bits.exponent == EPD_MAX_BIN); | |
| 
 | |
|   if (epd1->exponent > epd2->exponent) { | |
|     diff = epd1->exponent - epd2->exponent; | |
|     if (diff <= EPD_MAX_BIN) { | |
|       value = epd1->type.value - | |
| 		epd2->type.value / pow((double)2.0, (double)diff); | |
|     } else | |
|       value = epd1->type.value; | |
|     exponent = epd1->exponent; | |
|   } else if (epd1->exponent < epd2->exponent) { | |
|     diff = epd2->exponent - epd1->exponent; | |
|     if (diff <= EPD_MAX_BIN) { | |
|       value = epd1->type.value / pow((double)2.0, (double)diff) - | |
| 		epd2->type.value; | |
|     } else | |
|       value = epd2->type.value * (double)(-1.0); | |
|     exponent = epd2->exponent; | |
|   } else { | |
|     value = epd1->type.value - epd2->type.value; | |
|     exponent = epd1->exponent; | |
|   } | |
|   epd3->type.value = value; | |
|   epd3->exponent = exponent; | |
|   EpdNormalize(epd3); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Computes extended precision pow of base 2. | |
| */ | |
| void | |
| EpdPow2(int n, EpDouble *epd) | |
| { | |
|   if (n <= EPD_MAX_BIN) { | |
|     EpdConvert(pow((double)2.0, (double)n), epd); | |
|   } else { | |
|     EpDouble	epd1, epd2; | |
|     int		n1, n2; | |
| 
 | |
|     n1 = n / 2; | |
|     n2 = n - n1; | |
|     EpdPow2(n1, &epd1); | |
|     EpdPow2(n2, &epd2); | |
|     EpdMultiply3(&epd1, &epd2, epd); | |
|   } | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Computes extended precision pow of base 2. | |
| */ | |
| void | |
| EpdPow2Decimal(int n, EpDouble *epd) | |
| { | |
|   if (n <= EPD_MAX_BIN) { | |
|     epd->type.value = pow((double)2.0, (double)n); | |
|     epd->exponent = 0; | |
|     EpdNormalizeDecimal(epd); | |
|   } else { | |
|     EpDouble	epd1, epd2; | |
|     int		n1, n2; | |
| 
 | |
|     n1 = n / 2; | |
|     n2 = n - n1; | |
|     EpdPow2Decimal(n1, &epd1); | |
|     EpdPow2Decimal(n2, &epd2); | |
|     EpdMultiply3Decimal(&epd1, &epd2, epd); | |
|   } | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Normalize an extended precision double value. | |
| */ | |
| void | |
| EpdNormalize(EpDouble *epd) | |
| { | |
|   int		exponent; | |
| 
 | |
|   if (IsNanOrInfDouble(epd->type.value)) { | |
|     epd->exponent = 0; | |
|     return; | |
|   } | |
| 
 | |
|   exponent = EpdGetExponent(epd->type.value); | |
|   if (exponent == EPD_MAX_BIN) | |
|     return; | |
|   exponent -= EPD_MAX_BIN; | |
|   epd->type.bits.exponent = EPD_MAX_BIN; | |
|   epd->exponent += exponent; | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Normalize an extended precision double value. | |
| */ | |
| void | |
| EpdNormalizeDecimal(EpDouble *epd) | |
| { | |
|   int		exponent; | |
| 
 | |
|   if (IsNanOrInfDouble(epd->type.value)) { | |
|     epd->exponent = 0; | |
|     return; | |
|   } | |
| 
 | |
|   exponent = EpdGetExponentDecimal(epd->type.value); | |
|   epd->type.value /= pow((double)10.0, (double)exponent); | |
|   epd->exponent += exponent; | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Returns value and decimal exponent of EpDouble. | |
| */ | |
| void | |
| EpdGetValueAndDecimalExponent(EpDouble const *epd, double *value, int *exponent) | |
| { | |
|   EpDouble	epd1, epd2; | |
| 
 | |
|   if (EpdIsNanOrInf(epd)) { | |
|     *exponent = EPD_EXP_INF; | |
|     *value = 0.0; | |
|     return; | |
|   } | |
| 
 | |
|   if (EpdIsZero(epd)) { | |
|     *value = 0.0; | |
|     *exponent = 0; | |
|     return; | |
|   } | |
| 
 | |
|   epd1.type.value = epd->type.value; | |
|   epd1.exponent = 0; | |
|   EpdPow2Decimal(epd->exponent, &epd2); | |
|   EpdMultiply2Decimal(&epd1, &epd2); | |
| 
 | |
|   *value = epd1.type.value; | |
|   *exponent = epd1.exponent; | |
| } | |
| 
 | |
| /** | |
|   @brief Returns the exponent value of a double. | |
| */ | |
| int | |
| EpdGetExponent(double value) | |
| { | |
|   int		exponent; | |
|   EpDouble	epd; | |
| 
 | |
|   epd.type.value = value; | |
|   exponent = epd.type.bits.exponent; | |
|   return(exponent); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Returns the decimal exponent value of a double. | |
| */ | |
| int | |
| EpdGetExponentDecimal(double value) | |
| { | |
|   char	*pos, str[24]; | |
|   int	exponent; | |
| 
 | |
|   sprintf(str, "%E", value); | |
|   pos = strstr(str, "E"); | |
|   sscanf(pos, "E%d", &exponent); | |
|   return(exponent); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Makes EpDouble Inf. | |
| */ | |
| void | |
| EpdMakeInf(EpDouble *epd, int sign) | |
| { | |
|   epd->type.bits.mantissa1 = 0; | |
|   epd->type.bits.mantissa0 = 0; | |
|   epd->type.bits.exponent = EPD_EXP_INF; | |
|   epd->type.bits.sign = sign; | |
|   epd->exponent = 0; | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Makes EpDouble Zero. | |
| */ | |
| void | |
| EpdMakeZero(EpDouble *epd, int sign) | |
| { | |
|   epd->type.bits.mantissa1 = 0; | |
|   epd->type.bits.mantissa0 = 0; | |
|   epd->type.bits.exponent = 0; | |
|   epd->type.bits.sign = sign; | |
|   epd->exponent = 0; | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Makes EpDouble NaN. | |
| */ | |
| void | |
| EpdMakeNan(EpDouble *epd) | |
| { | |
|   epd->type.nan.mantissa1 = 0; | |
|   epd->type.nan.mantissa0 = 0; | |
|   epd->type.nan.quiet_bit = 1; | |
|   epd->type.nan.exponent = EPD_EXP_INF; | |
|   epd->type.nan.sign = 1; | |
|   epd->exponent = 0; | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Copies an EpDouble struct. | |
| */ | |
| void | |
| EpdCopy(EpDouble const *from, EpDouble *to) | |
| { | |
|   to->type.value = from->type.value; | |
|   to->exponent = from->exponent; | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Checks whether the value is Inf. | |
| */ | |
| int | |
| EpdIsInf(EpDouble const *epd) | |
| { | |
|   return(IsInfDouble(epd->type.value)); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Checks whether the value is Zero. | |
| */ | |
| int | |
| EpdIsZero(EpDouble const *epd) | |
| { | |
|   if (epd->type.value == 0.0) | |
|     return(1); | |
|   else | |
|     return(0); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Checks whether the value is NaN. | |
| */ | |
| int | |
| EpdIsNan(EpDouble const *epd) | |
| { | |
|   return(IsNanDouble(epd->type.value)); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Checks whether the value is NaN or Inf. | |
| */ | |
| int | |
| EpdIsNanOrInf(EpDouble const *epd) | |
| { | |
|   return(IsNanOrInfDouble(epd->type.value)); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Checks whether the value is Inf. | |
| */ | |
| int | |
| IsInfDouble(double value) | |
| { | |
|   EpType val; | |
| 
 | |
|   val.value = value; | |
|   if (val.bits.exponent == EPD_EXP_INF && | |
|       val.bits.mantissa0 == 0 && | |
|       val.bits.mantissa1 == 0) { | |
|     if (val.bits.sign == 0) | |
|       return(1); | |
|     else | |
|       return(-1); | |
|   } | |
|   return(0); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Checks whether the value is NaN. | |
| */ | |
| int | |
| IsNanDouble(double value) | |
| { | |
|   EpType	val; | |
|    | |
|   val.value = value; | |
|   if (val.nan.exponent == EPD_EXP_INF && | |
|       val.nan.sign == 1 && | |
|       val.nan.quiet_bit == 1 && | |
|       val.nan.mantissa0 == 0 && | |
|       val.nan.mantissa1 == 0) { | |
|     return(1); | |
|   } | |
|   return(0); | |
| } | |
| 
 | |
| 
 | |
| /** | |
|   @brief Checks whether the value is NaN or Inf. | |
| */ | |
| int | |
| IsNanOrInfDouble(double value) | |
| { | |
|   EpType	val; | |
| 
 | |
|   val.value = value; | |
|   if (val.nan.exponent == EPD_EXP_INF && | |
|       val.nan.mantissa0 == 0 && | |
|       val.nan.mantissa1 == 0 && | |
|       (val.nan.sign == 1 || val.nan.quiet_bit == 0)) { | |
|     return(1); | |
|   } | |
|   return(0); | |
| }
 |