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