Skip to content

Commit

Permalink
WIP: skeleton for elastic floating-point
Browse files Browse the repository at this point in the history
  • Loading branch information
Ravenwater committed Sep 15, 2024
1 parent 8a92658 commit d6f1ea9
Show file tree
Hide file tree
Showing 7 changed files with 334 additions and 220 deletions.
14 changes: 12 additions & 2 deletions elastic/efloat/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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}")
130 changes: 130 additions & 0 deletions elastic/efloat/api/api.cpp
Original file line number Diff line number Diff line change
@@ -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 <universal/utility/directives.hpp>

// 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 <universal/number/efloat/efloat.hpp>
#include <universal/verification/test_suite.hpp>

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<TestType>();
}

// 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<float>::infinity()) : " << efloat(std::numeric_limits<float>::infinity()) << "\n";
std::cout << "efloat(-std::numeric_limits<float>::infinity()) : " << efloat(-std::numeric_limits<float>::infinity()) << "\n";

std::cout << " 2 * std::numeric_limits<float>::infinity() : " << 2 * std::numeric_limits<float>::infinity() << "\n";
std::cout << " 2 * std::numeric_limits<efloat>::infinity() : " << 2 * std::numeric_limits<efloat>::infinity() << "\n";
std::cout << "-2 * std::numeric_limits<efloat>::infinity() : " << -2 * std::numeric_limits<efloat>::infinity() << "\n";

// std::cout << "sw::universal::nextafter(efloat(0), std::numeric_limits<efloat>::infinity()) : " << sw::universal::nextafter(efloat(-0), std::numeric_limits<efloat>::infinity()) << "\n";
// std::cout << "std::nextafter(float(0), std::numeric_limits<float>::infinity()) : " << std::nextafter(float(-0), std::numeric_limits<float>::infinity()) << "\n";
// std::cout << "sw::universal::nextafter(efloat(0), -std::numeric_limits<efloat>::infinity()) : " << sw::universal::nextafter(efloat(0), -std::numeric_limits<efloat>::infinity()) << "\n";
// std::cout << "std::nextafter(float(0), -std::numeric_limits<float>::infinity()) : " << std::nextafter(float(0), -std::numeric_limits<float>::infinity()) << "\n";

// std::cout << "efloat(std::numeric_limits<float>::signaling_NaN()).isnan(sw::universal::NAN_TYPE_QUIET) : " << efloat(std::numeric_limits<float>::signaling_NaN()).isnan(sw::universal::NAN_TYPE_QUIET) << "\n";
// std::cout << "efloat(std::numeric_limits<float>::signaling_NaN()).isnan(sw::universal::NAN_TYPE_SIGNALLING) : " << efloat(std::numeric_limits<float>::signaling_NaN()).isnan(sw::universal::NAN_TYPE_SIGNALLING) << "\n";
}

std::cout << "+------------ Serialization of a efloat ----------+\n";
{

}

std::cout << "+------------ Horner's Rule ----------+\n";
{
// std::vector<efloat> 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;
}
107 changes: 33 additions & 74 deletions elastic/efloat/add.cpp → elastic/efloat/arithmetic/addition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

// minimum set of include files to reflect source code dependencies
#include <universal/number/efloat/efloat.hpp>
#include <universal/verification/test_status.hpp> // ReportTestResult
#include <universal/verification/test_suite.hpp>

// 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
Expand All @@ -35,100 +35,59 @@ 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<BlockType> 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;

// generate individual testcases to hand trace/debug
GenerateTestCase(INFINITY, INFINITY);

efloat f;
f = 0;
std::cout << f << '\n';

std::vector<uint32_t> 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;
Expand Down
99 changes: 99 additions & 0 deletions elastic/efloat/math/pow.cpp
Original file line number Diff line number Diff line change
@@ -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 <universal/utility/directives.hpp>
#include <universal/number/bfloat/bfloat.hpp>
#include <universal/verification/test_suite.hpp>
//#include <universal/verification/bfloat_math_test_suite.hpp>

// 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<typename Ty,
typename = typename std::enable_if<std::is_floating_point<Ty>::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<float>(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;
}
Loading

0 comments on commit d6f1ea9

Please sign in to comment.