19888Sandreas@sandberg.pp.se/* 29888Sandreas@sandberg.pp.se * Copyright (c) 2013, Andreas Sandberg 39888Sandreas@sandberg.pp.se * All rights reserved. 49888Sandreas@sandberg.pp.se * 59888Sandreas@sandberg.pp.se * Redistribution and use in source and binary forms, with or without 69888Sandreas@sandberg.pp.se * modification, are permitted provided that the following conditions 79888Sandreas@sandberg.pp.se * are met: 89888Sandreas@sandberg.pp.se * 99888Sandreas@sandberg.pp.se * 1. Redistributions of source code must retain the above copyright 109888Sandreas@sandberg.pp.se * notice, this list of conditions and the following disclaimer. 119888Sandreas@sandberg.pp.se * 2. Redistributions in binary form must reproduce the above 129888Sandreas@sandberg.pp.se * copyright notice, this list of conditions and the following 139888Sandreas@sandberg.pp.se * disclaimer in the documentation and/or other materials provided 149888Sandreas@sandberg.pp.se * with the distribution. 159888Sandreas@sandberg.pp.se * 169888Sandreas@sandberg.pp.se * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 179888Sandreas@sandberg.pp.se * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 189888Sandreas@sandberg.pp.se * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 199888Sandreas@sandberg.pp.se * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 209888Sandreas@sandberg.pp.se * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 219888Sandreas@sandberg.pp.se * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 229888Sandreas@sandberg.pp.se * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 239888Sandreas@sandberg.pp.se * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 249888Sandreas@sandberg.pp.se * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 259888Sandreas@sandberg.pp.se * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 269888Sandreas@sandberg.pp.se * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 279888Sandreas@sandberg.pp.se * OF THE POSSIBILITY OF SUCH DAMAGE. 289888Sandreas@sandberg.pp.se */ 299888Sandreas@sandberg.pp.se 309888Sandreas@sandberg.pp.se#ifndef _FP80_H 319888Sandreas@sandberg.pp.se#define _FP80_H 1 329888Sandreas@sandberg.pp.se 3310480SAndreas.Sandberg@ARM.com#include <math.h> /* FP_NAN et al. */ 349888Sandreas@sandberg.pp.se#include <stdio.h> 359888Sandreas@sandberg.pp.se 3610480SAndreas.Sandberg@ARM.com#include <fputils/fptypes.h> 3710480SAndreas.Sandberg@ARM.com 3810480SAndreas.Sandberg@ARM.com 399888Sandreas@sandberg.pp.se#ifdef __cplusplus 409888Sandreas@sandberg.pp.seextern "C" { 419888Sandreas@sandberg.pp.se#endif 429888Sandreas@sandberg.pp.se 439888Sandreas@sandberg.pp.se/** 449888Sandreas@sandberg.pp.se * @defgroup fp80 80-bit Floats 459888Sandreas@sandberg.pp.se * Functions handling 80-bit floats. 469888Sandreas@sandberg.pp.se * 479888Sandreas@sandberg.pp.se * @{ 489888Sandreas@sandberg.pp.se */ 499888Sandreas@sandberg.pp.se 509888Sandreas@sandberg.pp.se/** Constant representing +inf */ 519888Sandreas@sandberg.pp.seextern const fp80_t fp80_pinf; 529888Sandreas@sandberg.pp.se/** Constant representing -inf */ 539888Sandreas@sandberg.pp.seextern const fp80_t fp80_ninf; 549888Sandreas@sandberg.pp.se/** Constant representing a quiet NaN */ 559888Sandreas@sandberg.pp.seextern const fp80_t fp80_qnan; 569888Sandreas@sandberg.pp.se/** Constant representing a quiet indefinite NaN */ 579888Sandreas@sandberg.pp.seextern const fp80_t fp80_qnani; 589888Sandreas@sandberg.pp.se/** Constant representing a signaling NaN */ 599888Sandreas@sandberg.pp.seextern const fp80_t fp80_snan; 609888Sandreas@sandberg.pp.se/** Alias for fp80_qnan */ 619888Sandreas@sandberg.pp.seextern const fp80_t fp80_nan; 629888Sandreas@sandberg.pp.se 639888Sandreas@sandberg.pp.se/** 649888Sandreas@sandberg.pp.se * Is the value a special floating point value? 659888Sandreas@sandberg.pp.se * 669888Sandreas@sandberg.pp.se * Determine if a floating point value is one of the special values 679888Sandreas@sandberg.pp.se * (i.e., one of the infinities or NaNs). In practice, this function 689888Sandreas@sandberg.pp.se * only checks if the exponent is set to the maximum value supported 699888Sandreas@sandberg.pp.se * by the binary representation, which is a reserved value used for 709888Sandreas@sandberg.pp.se * such special numbers. 719888Sandreas@sandberg.pp.se * 729888Sandreas@sandberg.pp.se * @param fp80 value to analyze. 739888Sandreas@sandberg.pp.se * @return 1 if the value is special, 0 otherwise. 749888Sandreas@sandberg.pp.se */ 759888Sandreas@sandberg.pp.seint fp80_isspecial(fp80_t fp80); 769888Sandreas@sandberg.pp.se/** 779888Sandreas@sandberg.pp.se * Is the value a quiet NaN? 789888Sandreas@sandberg.pp.se * 799888Sandreas@sandberg.pp.se * @param fp80 value to analyze. 809888Sandreas@sandberg.pp.se * @return 1 if true, 0 otherwise. 819888Sandreas@sandberg.pp.se */ 829888Sandreas@sandberg.pp.seint fp80_isqnan(fp80_t fp80); 839888Sandreas@sandberg.pp.se/** 849888Sandreas@sandberg.pp.se * Is the value an indefinite quiet NaN? 859888Sandreas@sandberg.pp.se * 869888Sandreas@sandberg.pp.se * @param fp80 value to analyze. 879888Sandreas@sandberg.pp.se * @return 1 if true, 0 otherwise. 889888Sandreas@sandberg.pp.se */ 899888Sandreas@sandberg.pp.seint fp80_isqnani(fp80_t fp80); 909888Sandreas@sandberg.pp.se/** 919888Sandreas@sandberg.pp.se * Is the value a signaling NaN? 929888Sandreas@sandberg.pp.se * 939888Sandreas@sandberg.pp.se * @param fp80 value to analyze. 949888Sandreas@sandberg.pp.se * @return 1 if true, 0 otherwise. 959888Sandreas@sandberg.pp.se */ 969888Sandreas@sandberg.pp.seint fp80_issnan(fp80_t fp80); 979888Sandreas@sandberg.pp.se 989888Sandreas@sandberg.pp.se/** 999888Sandreas@sandberg.pp.se * Classify a floating point number. 1009888Sandreas@sandberg.pp.se * 1019888Sandreas@sandberg.pp.se * This function implements the same classification as the standard 1029888Sandreas@sandberg.pp.se * fpclassify() function. It returns one of the following floating 1039888Sandreas@sandberg.pp.se * point classes: 1049888Sandreas@sandberg.pp.se * <ul> 1059888Sandreas@sandberg.pp.se * <li>FP_NAN - The value is NaN. 1069888Sandreas@sandberg.pp.se * <li>FP_INFINITE - The value is either +inf or -inf. 1079888Sandreas@sandberg.pp.se * <li>FP_ZERO - The value is either +0 or -0. 1089888Sandreas@sandberg.pp.se * <li>FP_SUBNORMAL - The value is to small to be represented as a 1099888Sandreas@sandberg.pp.se * normalized float. See fp80_issubnormal(). 1109888Sandreas@sandberg.pp.se * <li>FP_NORMAL - The value is neither of above. 1119888Sandreas@sandberg.pp.se * </ul> 1129888Sandreas@sandberg.pp.se * 1139888Sandreas@sandberg.pp.se * @param fp80 value to analyze. 1149888Sandreas@sandberg.pp.se * @return Floating point classification. 1159888Sandreas@sandberg.pp.se */ 1169888Sandreas@sandberg.pp.seint fp80_classify(fp80_t fp80); 1179888Sandreas@sandberg.pp.se 1189888Sandreas@sandberg.pp.se/** 1199888Sandreas@sandberg.pp.se * Is a value finite? 1209888Sandreas@sandberg.pp.se * 1219888Sandreas@sandberg.pp.se * Check if a value is a finite value. That is, not one of the 1229888Sandreas@sandberg.pp.se * infinities or NaNs. 1239888Sandreas@sandberg.pp.se * 1249888Sandreas@sandberg.pp.se * @param fp80 value to analyze. 1259888Sandreas@sandberg.pp.se * @return -1 if negative finite, +1 if positive finite, 0 otherwise. 1269888Sandreas@sandberg.pp.se */ 1279888Sandreas@sandberg.pp.seint fp80_isfinite(fp80_t fp80); 1289888Sandreas@sandberg.pp.se/** 1299888Sandreas@sandberg.pp.se * Is the value a non-zero normal? 1309888Sandreas@sandberg.pp.se * 1319888Sandreas@sandberg.pp.se * This function checks if a floating point value is a normal (having 1329888Sandreas@sandberg.pp.se * an exponent larger or equal to 1) or not. See fp80_issubnormal() 1339888Sandreas@sandberg.pp.se * for a description of what a denormal value is. 1349888Sandreas@sandberg.pp.se * 1359888Sandreas@sandberg.pp.se * @see fp80_issubnormal() 1369888Sandreas@sandberg.pp.se * 1379888Sandreas@sandberg.pp.se * @param fp80 value to analyze. 1389888Sandreas@sandberg.pp.se * @return -1 if negative normal, +1 if positive normal, 0 otherwise. 1399888Sandreas@sandberg.pp.se */ 1409888Sandreas@sandberg.pp.seint fp80_isnormal(fp80_t fp80); 1419888Sandreas@sandberg.pp.se/** 1429888Sandreas@sandberg.pp.se * Is the value a NaN of any kind? 1439888Sandreas@sandberg.pp.se * 1449888Sandreas@sandberg.pp.se * @param fp80 value to analyze. 1459888Sandreas@sandberg.pp.se * @return -1 if negative NaN, +1 if positive NaN, 0 otherwise. 1469888Sandreas@sandberg.pp.se */ 1479888Sandreas@sandberg.pp.seint fp80_isnan(fp80_t fp80); 1489888Sandreas@sandberg.pp.se/** 1499888Sandreas@sandberg.pp.se * Is the value one of the infinities? 1509888Sandreas@sandberg.pp.se * 1519888Sandreas@sandberg.pp.se * @param fp80 value to analyze. 1529888Sandreas@sandberg.pp.se * @return -1 if -inf, +1 if +inf, 0 otherwise. 1539888Sandreas@sandberg.pp.se */ 1549888Sandreas@sandberg.pp.seint fp80_isinf(fp80_t fp80); 1559888Sandreas@sandberg.pp.se/** 1569888Sandreas@sandberg.pp.se * Determine value of the sign-bit of a floating point number. 1579888Sandreas@sandberg.pp.se * 1589888Sandreas@sandberg.pp.se * @note Floats can represent both positive and negative zeros. 1599888Sandreas@sandberg.pp.se * 1609888Sandreas@sandberg.pp.se * @param fp80 value to analyze. 1619888Sandreas@sandberg.pp.se * @return -1 if negative, +1 if positive. 1629888Sandreas@sandberg.pp.se */ 1639888Sandreas@sandberg.pp.seint fp80_sgn(fp80_t fp80); 1649888Sandreas@sandberg.pp.se/** 1659888Sandreas@sandberg.pp.se * Is the value zero? 1669888Sandreas@sandberg.pp.se * 1679888Sandreas@sandberg.pp.se * @param fp80 value to analyze. 1689888Sandreas@sandberg.pp.se * @return -1 if negative zero, +1 if positive zero, 0 otherwise. 1699888Sandreas@sandberg.pp.se */ 1709888Sandreas@sandberg.pp.seint fp80_iszero(fp80_t fp80); 1719888Sandreas@sandberg.pp.se/** 1729888Sandreas@sandberg.pp.se * Is the value a denormal? 1739888Sandreas@sandberg.pp.se * 1749888Sandreas@sandberg.pp.se * Numbers that are close to the minimum of what can be stored in a 1759888Sandreas@sandberg.pp.se * floating point number start loosing precision because bits in the 1769888Sandreas@sandberg.pp.se * fraction get used (implicitly) to store parts of the negative 1779888Sandreas@sandberg.pp.se * exponent (i.e., the exponent is saturated and the fraction is less 1789888Sandreas@sandberg.pp.se * than 1). Such numbers are known as denormals. This function checks 1799888Sandreas@sandberg.pp.se * whether a float is a denormal or not. 1809888Sandreas@sandberg.pp.se * 1819888Sandreas@sandberg.pp.se * @param fp80 value to analyze. 1829888Sandreas@sandberg.pp.se * @return -1 if negative denormal, +1 if positive denormal, 0 otherwise. 1839888Sandreas@sandberg.pp.se */ 1849888Sandreas@sandberg.pp.seint fp80_issubnormal(fp80_t fp80); 1859888Sandreas@sandberg.pp.se 18610480SAndreas.Sandberg@ARM.com 18710480SAndreas.Sandberg@ARM.com/** 18810480SAndreas.Sandberg@ARM.com * Convert an 80-bit float to a 64-bit double. 18910480SAndreas.Sandberg@ARM.com * 19010480SAndreas.Sandberg@ARM.com * Convenience wrapper around fp80_cvtfp64() that returns a double 19110480SAndreas.Sandberg@ARM.com * instead of the internal fp64_t representation. 19210480SAndreas.Sandberg@ARM.com * 19310480SAndreas.Sandberg@ARM.com * Note that this conversion is lossy, see fp80_cvtfp64() for details 19410480SAndreas.Sandberg@ARM.com * of the conversion. 19510480SAndreas.Sandberg@ARM.com * 19610480SAndreas.Sandberg@ARM.com * @param fp80 Source value to convert. 19710480SAndreas.Sandberg@ARM.com * @return value represented as double. 19810480SAndreas.Sandberg@ARM.com */ 19910480SAndreas.Sandberg@ARM.comdouble fp80_cvtd(fp80_t fp80); 20010480SAndreas.Sandberg@ARM.com 2019888Sandreas@sandberg.pp.se/** 2029888Sandreas@sandberg.pp.se * Convert an 80-bit float to a 64-bit double. 2039888Sandreas@sandberg.pp.se * 2049888Sandreas@sandberg.pp.se * This function converts an 80-bit float into a standard 64-bit 2059888Sandreas@sandberg.pp.se * double. This conversion is inherently lossy since a double can only 2069888Sandreas@sandberg.pp.se * represent a subset of what an 80-bit float can represent. The 2079888Sandreas@sandberg.pp.se * fraction of the source value will always be truncated to fit the 2089888Sandreas@sandberg.pp.se * lower precision. If a value falls outside of the range that can be 2099888Sandreas@sandberg.pp.se * accurately represented by double by truncating the fraction, one of 2109888Sandreas@sandberg.pp.se * the following happens: 2119888Sandreas@sandberg.pp.se * <ul> 2129888Sandreas@sandberg.pp.se * <li>A denormal will be generated if that can approximate the 2139888Sandreas@sandberg.pp.se * value. 2149888Sandreas@sandberg.pp.se * <li>[-]0 will be generated if the magnitude of the value is too 2159888Sandreas@sandberg.pp.se * small to be represented at all. 2169888Sandreas@sandberg.pp.se * <li>+-Inf will be generated if the magnitude of the value is too 2179888Sandreas@sandberg.pp.se * large to be represented. 2189888Sandreas@sandberg.pp.se * </ul> 2199888Sandreas@sandberg.pp.se * 2209888Sandreas@sandberg.pp.se * NaN values will be preserved across the conversion. 2219888Sandreas@sandberg.pp.se * 2229888Sandreas@sandberg.pp.se * @param fp80 Source value to convert. 2239888Sandreas@sandberg.pp.se * @return 64-bit version of the float. 2249888Sandreas@sandberg.pp.se */ 22510480SAndreas.Sandberg@ARM.comfp64_t fp80_cvtfp64(fp80_t fp80); 2269888Sandreas@sandberg.pp.se 2279888Sandreas@sandberg.pp.se/** 22810480SAndreas.Sandberg@ARM.com * Convert a double to an 80-bit float. 2299888Sandreas@sandberg.pp.se * 23010480SAndreas.Sandberg@ARM.com * This is a convenience wrapper around fp80_cvffp64() and provides a 23110480SAndreas.Sandberg@ARM.com * convenient way of using the native double type instead of the 23210480SAndreas.Sandberg@ARM.com * internal fp64_t representation. 23310480SAndreas.Sandberg@ARM.com * 23410480SAndreas.Sandberg@ARM.com * @param fpd Source value to convert. 23510480SAndreas.Sandberg@ARM.com * @return 80-bit version of the float. 23610480SAndreas.Sandberg@ARM.com */ 23710480SAndreas.Sandberg@ARM.comfp80_t fp80_cvfd(double fpd); 23810480SAndreas.Sandberg@ARM.com 23910480SAndreas.Sandberg@ARM.com/** 24010480SAndreas.Sandberg@ARM.com * Convert a 64-bit float to an 80-bit float. 24110480SAndreas.Sandberg@ARM.com * 24210480SAndreas.Sandberg@ARM.com * This function converts the internal representation of a 64-bit 24310480SAndreas.Sandberg@ARM.com * float into an 80-bit float. This conversion is completely lossless 24410480SAndreas.Sandberg@ARM.com * since the 80-bit float represents a superset of what a 64-bit 24510480SAndreas.Sandberg@ARM.com * float can represent. 2469888Sandreas@sandberg.pp.se * 2479888Sandreas@sandberg.pp.se * @note Denormals will be converted to normalized values. 2489888Sandreas@sandberg.pp.se * 24910480SAndreas.Sandberg@ARM.com * @param fp64 64-bit float to convert. 25010480SAndreas.Sandberg@ARM.com * @return 80-bit version of the float. 2519888Sandreas@sandberg.pp.se */ 25210480SAndreas.Sandberg@ARM.comfp80_t fp80_cvffp64(fp64_t fp64); 2539888Sandreas@sandberg.pp.se 2549888Sandreas@sandberg.pp.se/** 2559888Sandreas@sandberg.pp.se * Dump the components of an 80-bit float to a file. 2569888Sandreas@sandberg.pp.se * 2579888Sandreas@sandberg.pp.se * @warning This function is intended for debugging and the format of 2589888Sandreas@sandberg.pp.se * the output is not guaranteed to be stable. 2599888Sandreas@sandberg.pp.se * 2609888Sandreas@sandberg.pp.se * @param fout Output stream (e.g., stdout) 2619888Sandreas@sandberg.pp.se * @param fp80 value to dump. 2629888Sandreas@sandberg.pp.se */ 2639888Sandreas@sandberg.pp.sevoid fp80_debug_dump(FILE *fout, fp80_t fp80); 2649888Sandreas@sandberg.pp.se 2659888Sandreas@sandberg.pp.se/** @} */ 2669888Sandreas@sandberg.pp.se 2679888Sandreas@sandberg.pp.se#ifdef __cplusplus 2689888Sandreas@sandberg.pp.se} /* extern "C" */ 2699888Sandreas@sandberg.pp.se#endif 2709888Sandreas@sandberg.pp.se 2719888Sandreas@sandberg.pp.se#endif 272