diff --git a/elastic/efloat/CMakeLists.txt b/elastic/efloat/CMakeLists.txt index 4546376e9..b32963790 100644 --- a/elastic/efloat/CMakeLists.txt +++ b/elastic/efloat/CMakeLists.txt @@ -1,3 +1,13 @@ -file (GLOB SOURCES "./*.cpp") +file (GLOB API_SRCS "./api/*.cpp") +file (GLOB CONVERSION_SRCS "./conversion/*.cpp") +file (GLOB ARITHMETIC_SRCS "./arithmetic/*.cpp") +file (GLOB LOGIC_SRCS "./logic/*.cpp") +file (GLOB MATHLIB_SRCS "./math/*.cpp") +file (GLOB PERFORMANCE_SRCS "./performance/*.cpp") -compile_all("true" "efloat" "Number Systems/elastic/floating-point/binary/efloat" "${SOURCES}") +compile_all("true" "efloat" "Number Systems/elastic/floating-point/binary/efloat/api" "${API_SRCS}") +compile_all("true" "efloat" "Number Systems/elastic/floating-point/binary/efloat/conversion" "${CONVERSION_SRCS}") +compile_all("true" "efloat" "Number Systems/elastic/floating-point/binary/efloat/arithmetic" "${ARITHMETIC_SRCS}") +compile_all("true" "efloat" "Number Systems/elastic/floating-point/binary/efloat/logic" "${LOGIC_SRCS}") +compile_all("true" "efloat" "Number Systems/elastic/floating-point/binary/efloat/mathlib" "${MATHLIB_SRCS}") +compile_all("true" "efloat" "Number Systems/elastic/floating-point/binary/efloat/performance" "${PERFORMANCE_SRCS}") diff --git a/elastic/efloat/api/api.cpp b/elastic/efloat/api/api.cpp new file mode 100644 index 000000000..7bc81b0be --- /dev/null +++ b/elastic/efloat/api/api.cpp @@ -0,0 +1,130 @@ +// api.cpp: application programming interface tests for efloat number system +// +// Copyright (C) 2017 Stillwater Supercomputing, Inc. +// SPDX-License-Identifier: MIT +// +// This file is part of the universal numbers project, which is released under an MIT Open Source license. +#include + +// minimum set of include files to reflect source code dependencies +// Configure the efloat template environment +// : enable/disable arithmetic exceptions +#define EFLOAT_THROW_ARITHMETIC_EXCEPTION 0 +// : enable trace conversion +#define TRACE_CONVERSION 0 +#include +#include + +int main() +try { + using namespace sw::universal; + + std::string test_suite = "efloat<> Application Programming Interface demonstration"; + int nrOfFailedTestCases = 0; + + // important behavioral traits + { + using TestType = float; + ReportTrivialityOfType(); + } + + // construction, initialization, and copy construction + { + + } + + // default behavior + std::cout << "+--------- Default efloat has no subnormals, no supernormals and is not saturating\n"; + { + + } + + // explicit configuration + std::cout << "+--------- Explicit configuration of a efloat\n"; + { + + } + +/* + // constexpr and specific values + std::cout << "+--------- constexpr and specific values --------+\n"; + { + using Real = efloat; + + CONSTEXPRESSION Real a{}; // zero constexpr + std::cout << type_tag(a) << '\n'; + + CONSTEXPRESSION Real b(1.0f); // constexpr of a native type conversion + std::cout << to_binary(b) << " : " << b << '\n'; + + CONSTEXPRESSION Real c(SpecificValue::minpos); // constexpr of a special value in the encoding + std::cout << to_binary(c) << " : " << c << " == minpos" << '\n'; + + CONSTEXPRESSION Real d(SpecificValue::maxpos); // constexpr of a special value in the encoding + std::cout << to_binary(d) << " : " << d << " == maxpos" << '\n'; + } +*/ + + std::cout << "+--------- human-readable output for large efloats --------+\n"; + { + + } + + std::cout << "+------------ numeric limits of a Cfloat ----------+\n"; + { + // using efloat = sw::universal::efloat<32, 8, uint32_t, true, false, false>; + + std::cout << "efloat(INFINITY): " << efloat(INFINITY) << "\n"; + std::cout << "efloat(-INFINITY): " << efloat(-INFINITY) << "\n"; + + std::cout << "efloat(std::numeric_limits::infinity()) : " << efloat(std::numeric_limits::infinity()) << "\n"; + std::cout << "efloat(-std::numeric_limits::infinity()) : " << efloat(-std::numeric_limits::infinity()) << "\n"; + + std::cout << " 2 * std::numeric_limits::infinity() : " << 2 * std::numeric_limits::infinity() << "\n"; + std::cout << " 2 * std::numeric_limits::infinity() : " << 2 * std::numeric_limits::infinity() << "\n"; + std::cout << "-2 * std::numeric_limits::infinity() : " << -2 * std::numeric_limits::infinity() << "\n"; + +// std::cout << "sw::universal::nextafter(efloat(0), std::numeric_limits::infinity()) : " << sw::universal::nextafter(efloat(-0), std::numeric_limits::infinity()) << "\n"; +// std::cout << "std::nextafter(float(0), std::numeric_limits::infinity()) : " << std::nextafter(float(-0), std::numeric_limits::infinity()) << "\n"; +// std::cout << "sw::universal::nextafter(efloat(0), -std::numeric_limits::infinity()) : " << sw::universal::nextafter(efloat(0), -std::numeric_limits::infinity()) << "\n"; +// std::cout << "std::nextafter(float(0), -std::numeric_limits::infinity()) : " << std::nextafter(float(0), -std::numeric_limits::infinity()) << "\n"; + +// std::cout << "efloat(std::numeric_limits::signaling_NaN()).isnan(sw::universal::NAN_TYPE_QUIET) : " << efloat(std::numeric_limits::signaling_NaN()).isnan(sw::universal::NAN_TYPE_QUIET) << "\n"; +// std::cout << "efloat(std::numeric_limits::signaling_NaN()).isnan(sw::universal::NAN_TYPE_SIGNALLING) : " << efloat(std::numeric_limits::signaling_NaN()).isnan(sw::universal::NAN_TYPE_SIGNALLING) << "\n"; + } + + std::cout << "+------------ Serialization of a efloat ----------+\n"; + { + + } + + std::cout << "+------------ Horner's Rule ----------+\n"; + { +// std::vector polynomial = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; + +// std::cout << "polynomial(1.0) = " << polyeval(polynomial, 5, efloat(1.0f)) << '\n'; + } + + ReportTestSuiteResults(test_suite, nrOfFailedTestCases); + return (nrOfFailedTestCases > 0 ? EXIT_FAILURE : EXIT_SUCCESS); +} +catch (char const* msg) { + std::cerr << "Caught ad-hoc exception: " << msg << std::endl; + return EXIT_FAILURE; +} +catch (const sw::universal::universal_arithmetic_exception& err) { + std::cerr << "Caught unexpected universal arithmetic exception : " << err.what() << std::endl; + return EXIT_FAILURE; +} +catch (const sw::universal::universal_internal_exception& err) { + std::cerr << "Caught unexpected universal internal exception: " << err.what() << std::endl; + return EXIT_FAILURE; +} +catch (const std::runtime_error& err) { + std::cerr << "Caught runtime exception: " << err.what() << std::endl; + return EXIT_FAILURE; +} +catch (...) { + std::cerr << "caught unknown exception" << std::endl; + return EXIT_FAILURE; +} diff --git a/elastic/efloat/add.cpp b/elastic/efloat/arithmetic/addition.cpp similarity index 50% rename from elastic/efloat/add.cpp rename to elastic/efloat/arithmetic/addition.cpp index bfafcb5cc..6f221a357 100644 --- a/elastic/efloat/add.cpp +++ b/elastic/efloat/arithmetic/addition.cpp @@ -12,7 +12,7 @@ // minimum set of include files to reflect source code dependencies #include -#include // ReportTestResult +#include // generate specific test case that you can trace with the trace conditions in mpreal.hpp // for most bugs they are traceable with _trace_conversion and _trace_add @@ -35,49 +35,33 @@ void GenerateTestCase(Ty _a, Ty _b) { std::cout << std::setprecision(precision); } -// progressions -void Progressions(uint32_t digit) { - using BlockType = uint32_t; - sw::universal::efloat f; - std::vector coef; - - constexpr size_t digitsInWord = 9; - coef.clear(); - coef.push_back(digit); - for (size_t i = 0; i < digitsInWord; ++i) { - f.test(false, -1, coef); - std::cout << "(+, exp = -1, coef = " << coef[0] << ") = " << f << '\n'; - coef[0] *= 10; - coef[0] += digit; - } - coef.clear(); - coef.push_back(digit); - for (size_t i = 0; i < digitsInWord; ++i) { - f.test(false, 0, coef); - std::cout << "(+, exp = 0, coef = " << coef[0] << ") = " << f << '\n'; - coef[0] *= 10; - coef[0] += digit; - } - coef.clear(); - coef.push_back(digit); - for (size_t i = 0; i < digitsInWord; ++i) { - f.test(false, 1, coef); - std::cout << "(+, exp = 1, coef = " << coef[0] << ") = " << f << '\n'; - coef[0] *= 10; - coef[0] += digit; - } -} -#define MANUAL_TESTING 1 -#define STRESS_TESTING 0 +// Regression testing guards: typically set by the cmake configuration, but MANUAL_TESTING is an override +#define MANUAL_TESTING 0 +// REGRESSION_LEVEL_OVERRIDE is set by the cmake file to drive a specific regression intensity +// It is the responsibility of the regression test to organize the tests in a quartile progression. +//#undef REGRESSION_LEVEL_OVERRIDE +#ifndef REGRESSION_LEVEL_OVERRIDE +#undef REGRESSION_LEVEL_1 +#undef REGRESSION_LEVEL_2 +#undef REGRESSION_LEVEL_3 +#undef REGRESSION_LEVEL_4 +#define REGRESSION_LEVEL_1 1 +#define REGRESSION_LEVEL_2 1 +#define REGRESSION_LEVEL_3 1 +#define REGRESSION_LEVEL_4 1 +#endif int main(int argc, char** argv) try { using namespace sw::universal; + std::string test_suite = "elastic precision floating-point arithmetic validation"; + std::string test_tag = "efloat addition"; + bool reportTestCases = false; int nrOfFailedTestCases = 0; - std::string tag = "adaptive precision linear float addition failed: "; + ReportTestSuiteHeader(test_suite, reportTestCases); #if MANUAL_TESTING // bool bReportIndividualTestCases = false; @@ -85,50 +69,25 @@ try { // generate individual testcases to hand trace/debug GenerateTestCase(INFINITY, INFINITY); - efloat f; - f = 0; - std::cout << f << '\n'; - - std::vector coef; - - Progressions(1); - Progressions(9); - - coef.clear(); - coef.push_back(0); - f.test(false, 0, coef); - for (int i = 0; i < 13; ++i) { - coef[0] += 1; - f.test(false, 0, coef); - std::cout << "(+, exp = 0, coef = " << coef[0] << ") = " << f << '\n'; - } - coef[0] = 999999999; - f.test(false, 0, coef); - std::cout << "(+, exp = 0, coef = " << coef[0] << ") = " << f << '\n'; - coef.push_back(0); - for (int i = 0; i < 13; ++i) { - coef[0] = 0; - coef[1] += 1; - f.test(false, 0, coef); - std::cout << "(+, exp = 0, coef = " << coef[0] << ", " << coef[1] << ") = " << f << '\n'; - coef[0] = 999999999; - f.test(false, 0, coef); - std::cout << "(+, exp = 0, coef = " << coef[0] << ", " << coef[1] << ") = " << f << '\n'; - - } + ReportTestSuiteResults(test_suite, nrOfFailedTestCases); + return EXIT_SUCCESS; // ignore failures +#else // !MANUAL_TESTING -#else +#if REGRESSION_LEVEL_1 +#endif - cout << "adaptive precision linear float addition validation" << endl; +#if REGRESSION_LEVEL_2 +#endif +#if REGRESSION_LEVEL_3 +#endif -#if STRESS_TESTING - -#endif // STRESS_TESTING - -#endif // MANUAL_TESTING +#if REGRESSION_LEVEL_4 +#endif + ReportTestSuiteResults(test_suite, nrOfFailedTestCases); return (nrOfFailedTestCases > 0 ? EXIT_FAILURE : EXIT_SUCCESS); +#endif // MANUAL_TESTING } catch (char const* msg) { std::cerr << "Caught exception: " << msg << std::endl; diff --git a/elastic/efloat/math/pow.cpp b/elastic/efloat/math/pow.cpp new file mode 100644 index 000000000..c43cdcdc2 --- /dev/null +++ b/elastic/efloat/math/pow.cpp @@ -0,0 +1,99 @@ +// pow.cpp: test suite runner for pow function +// +// Copyright (C) 2017 Stillwater Supercomputing, Inc. +// SPDX-License-Identifier: MIT +// +// This file is part of the universal numbers project, which is released under an MIT Open Source license. +#include +#include +#include +//#include + +// generate specific test case that you can trace with the trace conditions in cfloat.h +// for most bugs they are traceable with _trace_conversion and _trace_add +template::type, Ty>::value +> +void GenerateTestCase(Ty fa, Ty fb) { + constexpr unsigned nbits = 16; + Ty fref; + sw::universal::bfloat16 a, b, ref, power; + a = fa; + b = fb; + fref = std::pow(fa, fb); + ref = fref; + power = sw::universal::pow(a, b); + std::cout << std::setprecision(nbits - 2); + std::cout << std::setw(nbits) << " -> pow(" << fa << "," << fb << ") = " << std::setw(nbits) << fref << std::endl; + std::cout << " -> pow( " << a << "," << b << ") = " << to_binary(power) << " (reference: " << to_binary(ref) << ") " ; + std::cout << (ref == power ? "PASS" : "FAIL") << std::endl << std::endl; + std::cout << std::setprecision(5); +} + +#define MANUAL_TESTING 0 +#define STRESS_TESTING 0 + +int main() +try { + using namespace sw::universal; + + std::string test_suite = "bfloat16 mathlib power function validation"; + std::string test_tag = "pow"; + bool reportTestCases = false; + int nrOfFailedTestCases = 0; + + ReportTestSuiteHeader(test_suite, reportTestCases); + +#if MANUAL_TESTING + // generate individual testcases to hand trace/debug + GenerateTestCase(4.0f, 2.0f); + + cout << endl; + + //nrOfFailedTestCases += ReportTestResult(VerifyPowerFunction<16, 1>("Manual Testing", reportTestCases), "cfloat<16,1>", test_tag); + + ReportTestSuiteResults(test_suite, nrOfFailedTestCases); + return EXIT_SUCCESS; // ignore errors +#else + +#ifdef LATER + std::cout << "Integer power function\n"; + int a = 2; + unsigned b = 32; + std::cout << "2 ^ 32 = " << ipow(a, b) << '\n'; + std::cout << "2 ^ 32 = " << fastipow(a, uint8_t(b)) << '\n'; + + int64_t c = 1024; + uint8_t d = 2; + std::cout << "1024 ^ 2 = " << ipow(c, d) << '\n'; + std::cout << "1M ^ 2 = " << ipow(ipow(c, d), d) << '\n'; + + std::cout << "bfloat16 Power function validation\n"; + //nrOfFailedTestCases += ReportTestResult(VerifyPowerFunction< cfloat<8, 2, uint8_t> >(reportTestCases), "cfloat<8,2>", "pow"); +#endif // LATER + + ReportTestSuiteResults(test_suite, nrOfFailedTestCases); + return (nrOfFailedTestCases > 0 ? EXIT_FAILURE : EXIT_SUCCESS); + +#endif // MANUAL_TESTING +} +catch (char const* msg) { + std::cerr << "Caught ad-hoc exception: " << msg << std::endl; + return EXIT_FAILURE; +} +catch (const sw::universal::universal_arithmetic_exception& err) { + std::cerr << "Caught unexpected universal arithmetic exception : " << err.what() << std::endl; + return EXIT_FAILURE; +} +catch (const sw::universal::universal_internal_exception& err) { + std::cerr << "Caught unexpected universal internal exception: " << err.what() << std::endl; + return EXIT_FAILURE; +} +catch (const std::runtime_error& err) { + std::cerr << "Caught runtime exception: " << err.what() << std::endl; + return EXIT_FAILURE; +} +catch (...) { + std::cerr << "Caught unknown exception" << std::endl; + return EXIT_FAILURE; +} diff --git a/include/universal/number/bfloat/bfloat16_impl.hpp b/include/universal/number/bfloat/bfloat16_impl.hpp index 696da86e8..97984e204 100644 --- a/include/universal/number/bfloat/bfloat16_impl.hpp +++ b/include/universal/number/bfloat/bfloat16_impl.hpp @@ -61,7 +61,7 @@ class bfloat16 { _bits = pun[1]; return *this; } - template::value, Real >::type> constexpr Real convert_to_ieee754() const noexcept { float f; @@ -150,7 +150,6 @@ class bfloat16 { explicit operator float() const noexcept { return convert_to_ieee754(); } explicit operator double() const noexcept { return convert_to_ieee754(); } - #if LONG_DOUBLE_SUPPORT constexpr bfloat16(long double iv) noexcept : _bits{} { *this = iv; } constexpr bfloat16& operator=(long double rhs) noexcept { return convert_ieee754(rhs); } diff --git a/include/universal/number/efloat/efloat.hpp b/include/universal/number/efloat/efloat.hpp index d18db34af..79cea5f4f 100644 --- a/include/universal/number/efloat/efloat.hpp +++ b/include/universal/number/efloat/efloat.hpp @@ -1,6 +1,7 @@ // elastic floating-point arithmetic type standard header // -// Copyright (C) 2017-2022 Stillwater Supercomputing, Inc. +// Copyright (C) 2017 Stillwater Supercomputing, Inc. +// SPDX-License-Identifier: MIT // // This file is part of the universal numbers project, which is released under an MIT Open Source license. #ifndef _EFLOAT_STANDARD_HEADER_ diff --git a/include/universal/number/efloat/efloat_impl.hpp b/include/universal/number/efloat/efloat_impl.hpp index 66bb28b70..4844f719f 100644 --- a/include/universal/number/efloat/efloat_impl.hpp +++ b/include/universal/number/efloat/efloat_impl.hpp @@ -35,45 +35,51 @@ class efloat { efloat& operator=(efloat&&) = default; // initializers for native types - explicit efloat(const signed char initial_value) { *this = initial_value; } - explicit efloat(const short initial_value) { *this = initial_value; } - explicit efloat(const int initial_value) { *this = initial_value; } - explicit efloat(const long initial_value) { *this = initial_value; } - explicit efloat(const long long initial_value) { *this = initial_value; } - explicit efloat(const char initial_value) { *this = initial_value; } - explicit efloat(const unsigned short initial_value) { *this = initial_value; } - explicit efloat(const unsigned int initial_value) { *this = initial_value; } - explicit efloat(const unsigned long initial_value) { *this = initial_value; } - explicit efloat(const unsigned long long initial_value) { *this = initial_value; } - explicit efloat(const float initial_value) { *this = initial_value; } - explicit efloat(const double initial_value) { *this = initial_value; } - explicit efloat(const long double initial_value) { *this = initial_value; } + constexpr efloat(signed char iv) noexcept { *this = iv; } + constexpr efloat(short iv) noexcept { *this = iv; } + constexpr efloat(int iv) noexcept { *this = iv; } + constexpr efloat(long iv) noexcept { *this = iv; } + constexpr efloat(long long iv) noexcept { *this = iv; } + constexpr efloat(char iv) noexcept { *this = iv; } + constexpr efloat(unsigned short iv) noexcept { *this = iv; } + constexpr efloat(unsigned int iv) noexcept { *this = iv; } + constexpr efloat(unsigned long iv) noexcept { *this = iv; } + constexpr efloat(unsigned long long iv) noexcept { *this = iv; } + constexpr efloat(float iv) noexcept { *this = iv; } + constexpr efloat(double iv) noexcept { *this = iv; } + // assignment operators for native types - efloat& operator=(const signed char rhs) { return convert(rhs, *this); } - efloat& operator=(const short rhs) { return convert(rhs, *this); } - efloat& operator=(const int rhs) { return convert(rhs, *this); } - efloat& operator=(const long rhs) { return convert(rhs, *this); } - efloat& operator=(const long long rhs) { return convert(rhs, *this); } - efloat& operator=(const char rhs) { return convert_unsigned(rhs, *this); } - efloat& operator=(const unsigned short rhs) { return convert_unsigned(rhs, *this); } - efloat& operator=(const unsigned int rhs) { return convert_unsigned(rhs, *this); } - efloat& operator=(const unsigned long rhs) { return convert_unsigned(rhs, *this); } - efloat& operator=(const unsigned long long rhs) { return convert_unsigned(rhs, *this); } - efloat& operator=(const float rhs) { return convert_ieee754(rhs); } - efloat& operator=(const double rhs) { return convert_ieee754(rhs); } - efloat& operator=(const long double rhs) { return convert_ieee754(rhs); } + constexpr efloat& operator=(signed char rhs) noexcept { return *this = convert(rhs); } + constexpr efloat& operator=(short rhs) noexcept { return *this = convert(rhs); } + constexpr efloat& operator=(int rhs) noexcept { return *this = convert(rhs); } + constexpr efloat& operator=(long rhs) noexcept { return *this = convert(rhs); } + constexpr efloat& operator=(long long rhs) noexcept { return *this = convert(rhs); } + constexpr efloat& operator=(char rhs) noexcept { return *this = convert(rhs); } + constexpr efloat& operator=(unsigned short rhs) noexcept { return *this = convert(rhs); } + constexpr efloat& operator=(unsigned int rhs) noexcept { return *this = convert(rhs); } + constexpr efloat& operator=(unsigned long rhs) noexcept { return *this = convert(rhs); } + constexpr efloat& operator=(unsigned long long rhs) noexcept { return *this = convert(rhs); } + constexpr efloat& operator=(float rhs) noexcept { return *this = convert(rhs); } + constexpr efloat& operator=(double rhs) noexcept { return *this = convert(rhs); } + constexpr efloat& operator=(long double rhs) noexcept { return *this = convert(rhs); } + + // conversion operators + explicit operator float() const noexcept { return convert_to_ieee754(); } + explicit operator double() const noexcept { return convert_to_ieee754(); } + explicit operator long double() const noexcept { return convert_to_ieee754(); } + +#if LONG_DOUBLE_SUPPORT + constexpr efloat(long double iv) noexcept : _bits{} { *this = iv; } + constexpr efloat& operator=(long double rhs) noexcept { return convert(rhs); } + explicit operator long double() const noexcept { return convert_to_ieee754(); } +#endif // prefix operators efloat operator-() const { efloat negated(*this); return negated; - } - - // conversion operators - explicit operator float() const { return float(toNativeFloatingPoint()); } - explicit operator double() const { return float(toNativeFloatingPoint()); } - explicit operator long double() const { return toNativeFloatingPoint(); } +} // arithmetic operators efloat& operator+=(const efloat& rhs) { @@ -92,10 +98,7 @@ class efloat { // modifiers inline void clear() { sign = false; exp = 0; coef.clear(); } inline void setzero() { clear(); } - // use un-interpreted raw bits to set the bits of the efloat - inline void setBits(unsigned long long value) { - clear(); - } + inline efloat& assign(const std::string& txt) { return *this; } @@ -109,50 +112,13 @@ class efloat { inline bool ineg() const { return sign; } inline int64_t scale() const { return exp + int64_t(coef.size()); } - // convert to string containing digits number of digits - std::string str(size_t nrDigits = 0) const { - if (iszero()) return std::string("0.0"); - - int64_t magnitude = scale(); - if (magnitude > 1 || magnitude < 0) { - // use scientific notation for non-trivial exponent values - return sci_notation(nrDigits); - } - - std::string str; - int64_t exponent = trimmed(nrDigits, str); - - if (magnitude == 0) { - if (sign) - return std::string("-0.0") + str; - else - return std::string("0.0") + str; - } - - std::string before_decimal = std::to_string(coef.back()); - - if (exponent >= 0) { - if (sign) - return std::string("-") + before_decimal + ".0"; - else - return before_decimal + ".0"; - } - - // now the digits after the radix point - std::string after_decimal = str.substr((size_t)(str.size() + exponent), (size_t)-exponent); - if (sign) - return std::string("-") + before_decimal + "." + after_decimal; - else - return before_decimal + "." + after_decimal; - - return std::string("bad"); - } void test(bool _sign, int _exp, std::vector& _coef) { sign = _sign; coef = _coef; exp = _exp; } + protected: bool sign; // sign of the number: -1 if true, +1 if false, zero is positive int64_t exp; // exponent of the number @@ -160,77 +126,27 @@ class efloat { // HELPER methods - // convert to native floating-point, use conversion rules to cast down to float and double - long double toNativeFloatingPoint() const { - long double ld = 0; - return ld; - } - - template - efloat& convert_ieee754(Ty& rhs) { - clear(); - long long base = (long long)rhs; - *this = base; - return *this; - } - - // convert to string with nrDigits of significant digits and return the scale - // value = str + "10^" + scale - int64_t trimmed(size_t nrDigits, std::string& number) const { - if (coef.size() == 0) return 0; - int64_t exponent = exp; - size_t length = coef.size(); - size_t index = 0; - if (nrDigits == 0) { - nrDigits = length * 9; - } - else { - size_t nrSegments = (nrDigits + 17) / 9; - if (nrSegments < length) { - index = length - nrSegments; - exponent += index; - length = nrSegments; - } + // convert arithmetic types into an elastic floating-point + template + static constexpr efloat convert(Arith v) noexcept { + static_assert(std::is_arithmetic_v); + efloat f; + f.clear(); + if constexpr (std::is_integral_v && std::is_signed_v) { } - exponent *= 9; - char segment[] = "012345678"; - number.clear(); - size_t i = length; - while (i-- > 0) { - BlockType w = coef[i]; - for (int i = 8; i >= 0; --i) { - segment[i] = w % 10 + '0'; - w /= 10; - } - number += segment; + else if constexpr (std::is_unsigned_v) { } - - // process leading zeros - size_t lz = 0; - while (number[lz] == '0') ++lz; - nrDigits += lz; - if (nrDigits < number.size()) { - exponent += number.size() - nrDigits; - number.resize(nrDigits); + else if constexpr (std::is_floating_point_v) { } - - return exponent; + return f; } - std::string sci_notation(size_t nrDigits) const { - if (coef.size() == 0) return std::string("0.0"); - std::string str; - int64_t exponent = trimmed(nrDigits, str); - // remove leading zeros - str.erase(str.begin(), std::find_if(str.begin(), str.end(), [](int ch) { return (ch != '0'); })); - exponent += str.size() - 1; - str = str.substr(0, 1) + "." + &str[1]; - if (exponent != 0) { - str += "*10^"; - str += std::to_string(exponent); - } - if (sign) str = std::string("-") + str; - return str; + template::value, Real >::type> + constexpr Real convert_to_ieee754() const noexcept { + float f{ 0 }; + + return Real(f); } private: @@ -310,7 +226,7 @@ inline std::ostream& operator<<(std::ostream& ostr, const efloat& i) { std::ios_base::fmtflags ff; ff = ostr.flags(); ss.flags(ff); - ss << std::setw(width) << std::setprecision(prec) << i.str(size_t(prec)); +// ss << std::setw(width) << std::setprecision(prec) << i.str(size_t(prec)); return ostr << ss.str(); }