diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..c5391c1 --- /dev/null +++ b/.envrc @@ -0,0 +1,3 @@ +export VIRTUAL_ENV=".venv" +layout python .venv/bin/python3 + diff --git a/.github/workflows/golden.yml b/.github/workflows/golden.yml new file mode 100644 index 0000000..11b44ce --- /dev/null +++ b/.github/workflows/golden.yml @@ -0,0 +1,71 @@ +name: Golden testing +on: + push: + branches: + - "main" + pull_request: + merge_group: + +permissions: + contents: write + +jobs: + build: + name: Golden testing against FloatX + SymFPU + permissions: + pull-requests: write + # Exclude expensive self-hosted runner. Reserved for performance benchmarking. + # https://docs.github.com/en/enterprise-cloud@latest/actions/writing-workflows/choosing-where-your-workflow-runs/choosing-the-runner-for-a-job#choosing-github-hosted-runners + runs-on: ubuntu-latest + steps: + - name: Checkout 🛎️ + uses: actions/checkout@v3 + + - name: Install elan đź•‘ + run: | + set -o pipefail + curl https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh -sSf | sh -s -- --default-toolchain none -y + ~/.elan/bin/lean --version + echo "$HOME/.elan/bin" >> $GITHUB_PATH + + - name: Cache `.lake` folder + id: cache-lake + uses: actions/cache@v4 + with: + path: .lake + key: ${{ runner.os }}-lake-${{ hashFiles('lake-manifest.json') }}-4 + + - name: Install C++ build tools (if needed) + run: | + sudo apt-get update + sudo apt-get install -y build-essential cmake # Add other C++ deps if needed + + # - name: Get mathlib cache (only if no cache available) + # if: steps.cache-lake.outputs.cache-hit != 'true' + # run: | + # lake -R exe cache get # download cache of mathlib docs. + # + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.10' # Specify your desired Python version + + - name: Cache Python dependencies + uses: actions/cache@v4 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Install Python dependencies + run: pip install -r requirements.txt + + - name: Run golden test for FloatX + run: | + ./test/ci/compare-floatx-fplean.sh + + - name: Run golden test for SymFPU + run: | + ./test/ci/compare-symfpu-fplean.sh + diff --git a/.gitignore b/.gitignore index ee65081..2fba523 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ +*.csv +.venv/ /.lake *.out *.o -*.a \ No newline at end of file +*.a diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..64b77df --- /dev/null +++ b/requirements.txt @@ -0,0 +1,20 @@ +contourpy==1.3.1 +cycler==0.12.1 +duckdb==1.2.2 +fonttools==4.56.0 +importlib_metadata==8.6.1 +kiwisolver==1.4.8 +matplotlib==3.10.1 +numpy==2.2.2 +packaging==24.2 +pandas==2.2.3 +pillow==11.1.0 +polars==1.24.0 +pyparsing==3.2.1 +python-dateutil==2.9.0.post0 +pytz==2025.1 +six==1.17.0 +tabulate==0.9.0 +tzdata==2025.1 +visidata==3.1.1 +zipp==3.21.0 diff --git a/test/against-floatx/.gitignore b/test/against-floatx/.gitignore new file mode 100644 index 0000000..c9c6b85 --- /dev/null +++ b/test/against-floatx/.gitignore @@ -0,0 +1,3 @@ +*.o +*.out + diff --git a/test/against-floatx/makefile b/test/against-floatx/makefile new file mode 100644 index 0000000..f8150cb --- /dev/null +++ b/test/against-floatx/makefile @@ -0,0 +1,13 @@ +.PHONY: clean all + +all: test.out + +test.o: test.cpp + g++ -std=c++11 test.cpp -I../../third-party/FloatX/src -g -c -o test.o + +test.out: test.o + g++ -std=c++11 test.o -o test.out + +clean: + rm test.o test.out + diff --git a/test/against-floatx/test.cpp b/test/against-floatx/test.cpp new file mode 100644 index 0000000..5518a5f --- /dev/null +++ b/test/against-floatx/test.cpp @@ -0,0 +1,55 @@ +#include "floatx.hpp" +#include +#include + +typedef flx::floatx<5,2> e5m2; +typedef flx::float_traits::backend_float bf; + +e5m2 cons_fp8(uint8_t arg) { + return flx::detail::construct_number<5,2>(std::bitset<8>(arg)); +} + +constexpr std::bitset<8> nanBits{0b01111110}; +std::bitset<8> to_bits(e5m2 arg, bool normNaN = false) { + std::bitset<8> argBits = flx::detail::get_fullbit_representation_BS<5,2>(bf(arg)); + if (normNaN && + ((argBits.to_ulong() >> 2) & 0b11111) == 0b11111 && + ((argBits.to_ulong() & 3) != 0)) { + return nanBits; + } + return argBits; +} + +void test_binop(std::string name, std::function f) { + for (uint16_t i = 0; i < (1<<8); i++) { + for (uint16_t j = 0; j < (1<<8); j++) { + e5m2 a = cons_fp8(static_cast(i)); + e5m2 b = cons_fp8(static_cast(j)); + e5m2 c = f(a,b); + std::cout << name << "," << "RNE" << "," << \ + to_bits(a) << "," << to_bits(b) << "," << \ + to_bits(c, true) << "\n"; + } + } +} + +void test_predi(std::string name, std::function f) { + for (uint16_t i = 0; i < (1<<8); i++) { + for (uint16_t j = 0; j < (1<<8); j++) { + e5m2 a = cons_fp8(static_cast(i)); + e5m2 b = cons_fp8(static_cast(j)); + bool c = f(a,b); + std::cout << name << "," << "RNE" << "," << \ + to_bits(a) << "," << to_bits(b) << "," << \ + (c ? "1" : "0") << "\n"; + } + } +} + +int main() { + test_binop("add", [](e5m2 a, e5m2 b) { return a + b; }); + test_predi("lt" , [](e5m2 a, e5m2 b) { return a < b; }); + test_binop("mul", [](e5m2 a, e5m2 b) { return a * b; }); + test_binop("div", [](e5m2 a, e5m2 b) { return a / b; }); + return 0; +} diff --git a/test/against-symfpu/.gitignore b/test/against-symfpu/.gitignore new file mode 100644 index 0000000..c9c6b85 --- /dev/null +++ b/test/against-symfpu/.gitignore @@ -0,0 +1,3 @@ +*.o +*.out + diff --git a/test/against-symfpu/README.md b/test/against-symfpu/README.md new file mode 100644 index 0000000..316e6a3 --- /dev/null +++ b/test/against-symfpu/README.md @@ -0,0 +1,5 @@ +# Golden Testing against SymFPU + +We generate golden CSV outputs to compare against SymFPU +for our own floating point implementation. + diff --git a/test/against-symfpu/makefile b/test/against-symfpu/makefile new file mode 100644 index 0000000..5a4ce98 --- /dev/null +++ b/test/against-symfpu/makefile @@ -0,0 +1,16 @@ +.PHONY: clean all + +all: test.out + +test.o: test.cpp + g++ -std=c++11 test.cpp -I../../third-party/ -g -c -o test.o + +test.out: test.o ../../third-party/symfpu/symfpu.a + g++ -std=c++11 ../../third-party/symfpu/symfpu.a ../../third-party/symfpu/baseTypes/simpleExecutable.o test.o -o test.out + +../../third-party/symfpu/symfpu.a: + cd ../../third-party/symfpu && make + +clean: + rm test.o test.out + diff --git a/test/against-symfpu/test.cpp b/test/against-symfpu/test.cpp new file mode 100644 index 0000000..91ef804 --- /dev/null +++ b/test/against-symfpu/test.cpp @@ -0,0 +1,130 @@ +#include +#include "symfpu/baseTypes/simpleExecutable.h" +#include "symfpu/core/unpackedFloat.h" +#include "symfpu/core/packing.h" +#include "symfpu/core/add.h" +#include "symfpu/core/compare.h" +#include "symfpu/core/multiply.h" +#include "symfpu/core/divide.h" +#include +#include + +using namespace symfpu::simpleExecutable; +typedef symfpu::unpackedFloat uf; +typedef traits::ubv ubv; +traits::rm modes[5] = { + traits::RNA(), + traits::RNE(), + traits::RTN(), + traits::RTP(), + traits::RTZ() +}; + +// Note: This fails assertions because symfpu assumes the exponent is shorter than the +// mantissa +void test_rounding(void) { + // 10-bit E5M4 float + traits::fpt inFormat(5,5); + // 8-bit E5M2 float + traits::fpt outFormat(5,3); + for (traits::rm mode : modes) { + for (uint64_t i = 0; i < (1 << 1); i++) { + traits::ubv packed(10, i); + uf unpacked(symfpu::unpack(inFormat, packed)); + + uf rounded(symfpu::rounder(outFormat, mode, unpacked)); + traits::ubv repacked(symfpu::pack(outFormat, rounded)); + printf("%d\n", repacked.contents()); + } + } +} + +std::string to_mode(traits::rm mode) { + if (mode == traits::RNA()) return "RNA"; + if (mode == traits::RNE()) return "RNE"; + if (mode == traits::RTN()) return "RTN"; + if (mode == traits::RTP()) return "RTP"; + if (mode == traits::RTZ()) return "RTZ"; + return "???"; +} + +// SymFPU already performs NaN normalisation +std::bitset<8> to_bits(ubv bitvec, bool normNaN = false) { + std::bitset<8> result; + uint64_t c = bitvec.contents(); + for (int i = 0; i < 8; i++) { + result[7-i] = (c >> (7-i)) & 1; + } + return result; +} + +// Test binary operation on 8 bits. +void test_binop(std::string name, + std::function f) { + for (traits::rm mode : modes) { + for (uint64_t i = 0; i < (1<<8); i++) { + for (uint64_t j = 0; j < (1<<8); j++) { + ubv packed1(8, i), packed2(8, j); + ubv result = f(mode, packed1, packed2); + std::cout << name << "," << to_mode(mode) << "," << \ + to_bits(packed1) << "," << to_bits(packed2) << "," << \ + to_bits(result, true) << "\n"; + } + } + } +} + +// Test binary predicate on 8 bits. +void test_predi(std::string name, + std::function f) { + for (traits::rm mode : modes) { + for (uint64_t i = 0; i < (1<<8); i++) { + for (uint64_t j = 0; j < (1<<8); j++) { + ubv packed1(8, i), packed2(8, j); + bool result = f(mode, packed1, packed2); + std::cout << name << "," << to_mode(mode) << "," << \ + to_bits(packed1) << "," << to_bits(packed2) << "," << \ + (result ? 1 : 0) << "\n"; + } + } + } +} + +traits::fpt e3m4(3,5); +int main() { + test_binop("add", [](traits::rm mode, ubv a, ubv b) { + uf ua(symfpu::unpack(e3m4, a)), + ub(symfpu::unpack(e3m4, b)); + + uf uc(symfpu::add(e3m4, mode, ua, ub, traits::prop(true))); + + return symfpu::pack(e3m4, uc); + }); + + test_predi("lt", [](traits::rm mode, ubv a, ubv b) { + uf ua(symfpu::unpack(e3m4, a)), + ub(symfpu::unpack(e3m4, b)); + + return symfpu::lessThan(e3m4, ua, ub); + }); + + test_binop("mul", [](traits::rm mode, ubv a, ubv b) { + uf ua(symfpu::unpack(e3m4, a)), + ub(symfpu::unpack(e3m4, b)); + + uf uc(symfpu::multiply(e3m4, mode, ua, ub)); + + return symfpu::pack(e3m4, uc); + }); + + test_binop("div", [](traits::rm mode, ubv a, ubv b) { + uf ua(symfpu::unpack(e3m4, a)), + ub(symfpu::unpack(e3m4, b)); + + uf uc(symfpu::divide(e3m4, mode, ua, ub)); + + return symfpu::pack(e3m4, uc); + }); + return 0; +} + diff --git a/test/ci/compare-against-golden.py b/test/ci/compare-against-golden.py new file mode 100755 index 0000000..dfb7c4e --- /dev/null +++ b/test/ci/compare-against-golden.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python3 + +import duckdb +import argparse +import sys +import os + +# Helper for colored output +class Colors: + HEADER = '\033[95m' + OKBLUE = '\033[94m' + OKGREEN = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + ENDC = '\033[0m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + + @staticmethod + def supports_color(): + """ + Returns True if the running system's terminal supports color, + and False otherwise. + From: https://stackoverflow.com/a/22254892 + """ + is_a_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty() + return is_a_tty + +# Disable colors if not supported +if not Colors.supports_color(): + for attr_name in dir(Colors): + if attr_name.isupper(): # Heuristic: color codes are uppercase class attributes + setattr(Colors, attr_name, "") + + +def main(): + parser = argparse.ArgumentParser( + description="Compare reference golden (e.g. floatx-golden) against fplean-golden CSV files. \n" + "Checks that every row (based on op, mode, op1, op2) in the first file (e.g. floatx-golden) \n" + "exists in the second file (fplean-golden) with the same result column. \n" + "Reports mismatches grouped by rounding mode and operation type.", + formatter_class=argparse.RawTextHelpFormatter + ) + parser.add_argument("floatx_golden_path", help="Path to the floatx-golden CSV file (expected values).") + parser.add_argument("fplean_golden_path", help="Path to the fplean-golden CSV file (actual values).") + args = parser.parse_args() + + fx_path = args.floatx_golden_path + fp_path = args.fplean_golden_path + + if not os.path.exists(fx_path): + print(f"{Colors.FAIL}Error: Expected values file not found at {fx_path}{Colors.ENDC}") + sys.exit(2) + if not os.path.exists(fp_path): + print(f"{Colors.FAIL}Error: Actual values file not found at {fp_path}{Colors.ENDC}") + sys.exit(2) + + # Column names based on the example: operation, rounding_mode, operand1, operand2, result + # Ensure this list of strings is correctly formatted for the SQL query + col_names_list_str = "['operation', 'rounding_mode', 'operand1', 'operand2', 'result']" + + con = None # Initialize con to None for the finally block + try: + con = duckdb.connect(database=':memory:', read_only=False) + + # The query joins floatx (fx) with fplean (fp) on the input columns. + # We are looking for rows in floatx where: + # 1. The input combination (op, rm, op1, op2) does NOT exist in fplean + # (fp.operation IS NULL after LEFT JOIN) + # OR + # 2. The input combination exists, but the result is different (fx.result != fp.result) + query = f""" + SELECT + fx.operation, + fx.rounding_mode, + fx.operand1, + fx.operand2, + fx.result AS expected_result, + fp.result AS actual_result -- This will be NULL if the input combo wasn't in fplean + FROM + read_csv_auto('{fx_path}', names={col_names_list_str}, header=False, all_varchar=true) AS fx + LEFT JOIN + read_csv_auto('{fp_path}', names={col_names_list_str}, header=False, all_varchar=true) AS fp + ON + fx.operation = fp.operation AND + fx.rounding_mode = fp.rounding_mode AND + fx.operand1 = fp.operand1 AND + fx.operand2 = fp.operand2 + WHERE + fp.operation IS NULL OR fx.result != fp.result -- Mismatch condition + ORDER BY + fx.rounding_mode, fx.operation, fx.operand1, fx.operand2; + """ + # print(f"Debug SQL Query:\n{query}") # For debugging + + mismatches = con.execute(query).fetchall() + + except Exception as e: + print(f"{Colors.FAIL}An error occurred during DuckDB processing: {e}{Colors.ENDC}") + sys.exit(3) + finally: + if con: + con.close() + + if mismatches: + print(f"{Colors.FAIL}{Colors.BOLD}Mismatches found:{Colors.ENDC}") + current_rm = None + current_op = None + + fx_basename = os.path.basename(fx_path) + fp_basename = os.path.basename(fp_path) + + for row_idx, row_data in enumerate(mismatches): + op, rm, op1, op2, expected, actual = row_data + + if rm != current_rm or op != current_op: + if current_rm is not None: # Print a newline between groups + print() + print(f"{Colors.HEADER}--- Group: Rounding Mode = {Colors.BOLD}{rm}{Colors.ENDC}{Colors.HEADER}, Operation = {Colors.BOLD}{op}{Colors.ENDC}{Colors.HEADER} ---{Colors.ENDC}") + current_rm = rm + current_op = op + + if actual is None: # This means the input combination was not found in fplean-golden + actual_display = f"{Colors.FAIL}{Colors.BOLD}NOT FOUND in {fp_basename}{Colors.ENDC}" + else: # Input combination found, but result differs + actual_display = f"{Colors.FAIL}{actual}{Colors.ENDC}" + + print(f" Mismatch for inputs: (op1={Colors.OKBLUE}{op1}{Colors.ENDC}, op2={Colors.OKBLUE}{op2}{Colors.ENDC})") + print(f" Expected (from {fx_basename}): {Colors.OKGREEN}{expected}{Colors.ENDC}") + print(f" Actual (from {fp_basename}): {actual_display}") + + print(f"\n{Colors.FAIL}{Colors.BOLD}Found {len(mismatches)} mismatch(es). Script FAILED.{Colors.ENDC}") + sys.exit(1) + else: + print(f"{Colors.OKGREEN}{Colors.BOLD}All checks passed. No mismatches found between {os.path.basename(fx_path)} and {os.path.basename(fp_path)}.{Colors.ENDC}") + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/test/ci/compare-floatx-fplean.sh b/test/ci/compare-floatx-fplean.sh new file mode 100755 index 0000000..0699b78 --- /dev/null +++ b/test/ci/compare-floatx-fplean.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -e +set -o xtrace + +TOPLEVEL="$(git rev-parse --show-toplevel)" + +cd "$TOPLEVEL" +shellcheck test/ci/compare-floatx-fplean.sh +make -C test/against-floatx all +./test/against-floatx/test.out > "$TOPLEVEL/golden-floatx.csv" +lake exec fp-lean e5m2 > "$TOPLEVEL/golden-fplean-against-floatx.csv" +test/ci/compare-against-golden.py "$TOPLEVEL/golden-floatx.csv" "$TOPLEVEL/golden-fplean-against-floatx.csv" + diff --git a/test/ci/compare-symfpu-fplean.sh b/test/ci/compare-symfpu-fplean.sh new file mode 100755 index 0000000..f03857c --- /dev/null +++ b/test/ci/compare-symfpu-fplean.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -e +set -o xtrace + +TOPLEVEL="$(git rev-parse --show-toplevel)" + +cd "$TOPLEVEL" +shellcheck test/ci/compare-symfpu-fplean.sh +make -C test/against-symfpu all +./test/against-symfpu/test.out > "$TOPLEVEL/golden-symfpu.csv" +lake exec fp-lean e3m4 > "$TOPLEVEL/golden-fplean-against-symfpu.csv" +test/ci/compare-against-golden.py "$TOPLEVEL/golden-symfpu.csv" "$TOPLEVEL/golden-fplean-against-symfpu.csv" + diff --git a/third-party/FloatX/.gitignore b/third-party/FloatX/.gitignore new file mode 100644 index 0000000..ee6d40f --- /dev/null +++ b/third-party/FloatX/.gitignore @@ -0,0 +1,34 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +build/ \ No newline at end of file diff --git a/third-party/FloatX/AUTHORS.md b/third-party/FloatX/AUTHORS.md new file mode 100644 index 0000000..c6c65ca --- /dev/null +++ b/third-party/FloatX/AUTHORS.md @@ -0,0 +1,3 @@ +Goran Flegar, Universitat Jaume I, +Florian Scheidegger, IBM Research GmbH, +Vedran Novakovic, Universitat Jaume I, diff --git a/third-party/FloatX/CMakeLists.txt b/third-party/FloatX/CMakeLists.txt new file mode 100644 index 0000000..fec8372 --- /dev/null +++ b/third-party/FloatX/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.1) +project(FloatX) + +option(BUILD_TESTS "Generate build files for unit tests" OFF) +option(BUILD_EXHAUSTIVE_TESTS "Generate build files for exhaustive tests" OFF) +option(DEVEL_TOOLS "Include development tools in build system" ON) +option(BUILD_EXAMPLES "Build examples in the example/ directory" ON) + +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_STANDARD 11) + +add_subdirectory(third_party) # third party tools and libraries + +add_library(floatx INTERFACE) +target_include_directories(floatx INTERFACE src/) + +if(BUILD_TESTS OR BUILD_EXHAUSTIVE_TESTS) + enable_testing() +endif() + +if(BUILD_TESTS) + add_subdirectory(test) +endif() + +if(BUILD_EXHAUSTIVE_TESTS) + add_subdirectory(testx) +endif() + +if(BUILD_EXAMPLES) + add_subdirectory(examples) +endif() diff --git a/third-party/FloatX/LICENSE b/third-party/FloatX/LICENSE new file mode 100644 index 0000000..6c841e2 --- /dev/null +++ b/third-party/FloatX/LICENSE @@ -0,0 +1,178 @@ +Copyright 2018 - The OPRECOMP Project Consortium, IBM Research GmbH, University Jaume I. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/third-party/FloatX/README.md b/third-party/FloatX/README.md new file mode 100644 index 0000000..befc590 --- /dev/null +++ b/third-party/FloatX/README.md @@ -0,0 +1,191 @@ +FloatX (Float eXtended) +======================= + +FloatX is a header-only C++ library which extends floating point types beyond +the native single and double (and on some hardware half) precision types. It +provides template types which allow the user to select the number of bits used +for the exponent and significand parts of the floating point number. +The idea of FloatX is based on the FlexFloat library, but, instead of +implementing the functionality in C and providing C++ wrappers, FloatX is +written completely in C++, which makes it more natural to the end user. +In addition, FloatX provides a superset of FlexFloat's functionalities. + + +![](./floatx.png) + + +Features +-------- + +This section lists the functionalities provided by FloatX. Functionalities that +are also provided by FlexFloat have (_flexfloat_) appended to the description. + +* header-only library, without a compiled component, and heavy inlining, + resulting in relatively high performance +* `floatx` class template, which allows + emulation of non-native types with `exp_bits` exponent bits and `sig_bits` + significand bits using a natively supported `backend_float` type to perform + arithmetic operations (_flexfloat_ - provides a similar functionality in + the C++ wrapper, but the memory consumption of the flexfloat C++ class was + suboptimal). +* `floatxr` class template, which provides the same + functionality as `floatx`, but allows changing the precision of the type + at runtime. This class is easier to experiment with, but is not as + efficient as `floatx` in both the performance, as well as the memory + consumption. (_flexfloat_ - provides a type that has a comparable memory + consumption with the precision selectable at runtime in the C library only) +* conversions between builtin types and `floatx` + (_flexfloat_ - had a bug where NaN can be cast to Inf during conversion) +* assignments on `floatx` and `floatxr` types (_flexfloat_) +* relational operations on `floatx` and `floatxr` types + (_flexfloat_ - did not handle NaN properly) +* relational operations between different types +* arithmetic operations on `floatx` and `floatxr` types (_flexfloat_) +* arithmetic operations between different types with implicit type promotion +* `std::ostream& operator <<(std::ostream&, floatx[r])` (_flexfloat_) +* `std::istream& operator >>(std::istream&, floatx[r])` +* CUDA support + + +What FloatX is NOT +------------------ + +FloatX does not implement arbitrary floating point types. The only supported +types are "subtypes" of those natively supported by the hardware. +In case you need implementations of larger types, consider using the SoftFloat +library. + +FloatX __emulates__ the types of custom precision, subject to the constraints +above, and, while trying to achieve as high performance as possible, it is +__not__ capable of magically delivering better performance than natively +supported types. Thus, do not expect `floatx<3, 3>` to consume less memory, or +be faster than e.g. `float`, though `floatx<11, 52>` should deliver similar +performance as `double`. + +That being said, it is not likely that FloatX will be useful in production +codes. On the other hand, it can be handy in research projects which aim to +study the effects of using different precisions. + +Installation +------------ + +To use the library, just make sure that a directory containing `floatx.hpp` is +in your include path (here, it is in `src/` subdirectory). + +Alternatively, if you are using CMake, a `CMakeLists.txt` file is provided. +You can download the repository into your project and use the following code to +depend on the floatx target: + +``` +add_subdirectory(floatx) +target_add_library(my_target PRIVATE floatx) +``` + +### Building the examples / unit tests + +A standard CMake command line sequence should do: + +``` +mkdir build && cd build && cmake .. && make +``` + +To run all the tests: + +``` +make test +``` + +This will (hopefully) output a summary of the form: + +``` +test_............ Passed +``` + +To run only one of the tests (and see more detail output): + +``` +./test/ +``` + + +Examples +-------- + +Some sample code using floatx: +``` +1: flx::floatx<7, 12> a = 1.2; // 7 exponent bits , 12 sign . bits +2: flx::floatx<7, 12> b = 3; // 7 exponent bits , 12 sign . bits +3: flx::floatx<10, 9> c; // 10 exponent bits , 9 sign . bits +4: float d = 3.2; +5: double e = 5.2; +6: +7: std :: cin >> c; +8: c = a + b; // decltype (a + b) == floatx <7, 12> +9: bool t = a < b; +10: a += c; +11: d = a / c; // decltype (a / c) == floatx <10 , 12> +12: e = c - d; // decltype (c - d) == floatx <10 , 23> +13: c = a * e; // decltype (a * e) == floatx <11 , 52> +14: std :: cout << c; +``` + +Lines 1, 2, and 3 show how floatx numbers can be constructed +from built-in types (floating-point numbers and integers) and read +from C++ streams. Lines 8 and 9 show how these objects are used +to perform basic arithmetic and relational operations. Lines 10-13 +demonstrate the interoperability between different floatx and built-in +types. The comments on the right specify the return type of the +operation. Note, that T == U, where T and U are types, is used to +convey that these two types are the same, i.e., that std::is_same::value evaluates to true. Lines 8 and 11-13 also show that floatx +types can be implicitly converted to other floatx types or built-in +types. Finally, line 14 shows how floatx types can be written to an +output stream. + + +## Authors and contacts + - Goran Flegar, Departamento de IngenierĂ­a y Ciencia de Computadores, Universidad Jaime I, Spain, flegar@uji.es + - Florian Scheidegger, IBM Research - Zurich, eid@zurich.ibm.com + - Vedran Novakovic, Departamento de IngenierĂ­a y Ciencia de Computadores, Universidad Jaime I, Spain + - Giovani Mariani, IBM Research - Zurich, + - Andres E. Tomas, Departamento de IngenierĂ­a y Ciencia de Computadores, Universidad Jaime I, Spain,tomasan@uji.es + - A. Cristiano I. Malossi, IBM Research - Zurich, acm@zurich.ibm.com + - Enrique S. Quintana-Orti, Departamento de Informática de Sistemas y Computadores,Universitat Politècnica de València, Spain, quintana@icc.uji.es + + +## Reference + +The full text of our paper explaining floatx in datail is available under the following link: https://dl.acm.org/doi/pdf/10.1145/3368086?download=true. + +Please, if you like and use our work, cite our paper as follows: + +``` +@article{flegar2019floatx, +author={Flegar, Goran and Scheidegger, Florian and Novakovi{\'c}, Vedran and Mariani, Giovani and Tom{\'{}} s, Andr{\'e}s E and Malossi, A Cristiano I and Quintana-Ort{\'\i}, Enrique S}, + title = {FloatX: A C++ Library for Customized Floating-Point Arithmetic}, + year = {2019}, + issue_date = {December 2019}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + volume = {45}, + number = {4}, + issn = {0098-3500}, + url = {https://doi.org/10.1145/3368086}, + doi = {10.1145/3368086}, + journal={ACM Transactions on Mathematical Software (TOMS)}, + month = dec, + articleno = {Article 40}, + numpages = {23}, +} +``` + +## Acknowledgments + +This work was funded by the European Union’s H2020 research and innovation program under grant +agreement No 732631, project OPRECOMP. + +For details visit http://oprecomp.eu/. + + + + diff --git a/third-party/FloatX/examples/CMakeLists.txt b/third-party/FloatX/examples/CMakeLists.txt new file mode 100644 index 0000000..89f164f --- /dev/null +++ b/third-party/FloatX/examples/CMakeLists.txt @@ -0,0 +1,11 @@ +add_executable(example example.cpp) +target_link_libraries(example PRIVATE floatx) + +add_executable(example2 example2.cpp) +target_link_libraries(example2 PRIVATE floatx) + +add_executable(common_type common_type.cpp) +target_link_libraries(common_type PRIVATE floatx) + +add_executable(DemoNewton DemoNewton.cpp) +target_link_libraries(DemoNewton PRIVATE floatx) \ No newline at end of file diff --git a/third-party/FloatX/examples/DemoNewton.cpp b/third-party/FloatX/examples/DemoNewton.cpp new file mode 100644 index 0000000..95170d0 --- /dev/null +++ b/third-party/FloatX/examples/DemoNewton.cpp @@ -0,0 +1,107 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * compile that file + * g++ -std=c++11 -Wall -o DemoNewton -I. DemoNewton.cpp + */ + +#include +#include + +// Babylonian method: +// Derived from Netwon +// See: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Example +// based on float type +float myroot(float a, float a0, float tol) +{ + float x = a0; + float xnext; + float err; + + int k = 0; + do { + xnext = 0.5 * (x + a / x); + err = fabs(x - xnext); + printf("[k=%i]: %f %e\n", k++, xnext, err); + x = xnext; + } while (err > tol); + return xnext; +} + +// general routine based on type T +// note, if T is float that routine is the same as above. +template +T myroot_general(T a, T a0, T tol) +{ + T x = a0; + T xnext; + T err; + + int k = 0; + do { + xnext = 0.5 * (x + a / x); + // for example fabs(...) is not defined for the floatx type + // hence, we use a cast to double and back to our type + err = (T)fabs(double(x - xnext)); + printf("[k=%i]: %f %e\n", k++, double(xnext), double(err)); + x = xnext; + } while (err > tol); + return xnext; +} + +int main(int argc, char** argv) +{ + printf( + "floatx working " + "example\n==============================================\n"); + printf("Iteratively compute the square root of a\n"); + + if (argc != 3) { + printf("Usage: %s \n computes root(a) by Newton Iterations.\n", + argv[0]); + printf("Example: \n %s 2 1\n", argv[0]); + exit(-1); + } + + float a = atof(argv[1]); + float a0 = atof(argv[2]); + + float res = myroot(a, a0, 1e-6); + + printf("\n\nBaseline version (float)\n\n"); + + printf("==============================================\n"); + printf("Result Computed (float): %.20f\n", res); + float ref = sqrt(a); + printf("Reference: %.20f\n", ref); + printf("==============================================\n"); + printf("Error: %e\n", ref - res); + printf("==============================================\n"); + + + printf("\n\nFloatx Version IEEE 16bit, e.g., floatx<5,10>\n\n"); + res = myroot_general>(a, a0, 1e-6); + printf("==============================================\n"); + printf("Result Computed (floatx: %.20f\n", res); + printf("Reference: %.20f\n", ref); + printf("==============================================\n"); + printf("Error: %e\n", ref - res); + printf("==============================================\n"); + + return 0; +} \ No newline at end of file diff --git a/third-party/FloatX/examples/common_type.cpp b/third-party/FloatX/examples/common_type.cpp new file mode 100644 index 0000000..3e3c599 --- /dev/null +++ b/third-party/FloatX/examples/common_type.cpp @@ -0,0 +1,32 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include + + +// Uncoment to disable common type resolution. +// #define FLOATX_NO_TYPE_RESOLUTION +#include + + +int main() +{ + using float1 = flx::floatx<5, 7>; + using float2 = flx::floatx<4, 8>; + std::cout << float1(2.6) + float1(6.2) << std::endl; // always works + std::cout << float1(2.6) + float2(6.2) << std::endl; // fails with flag +} diff --git a/third-party/FloatX/examples/example.cpp b/third-party/FloatX/examples/example.cpp new file mode 100644 index 0000000..a804e56 --- /dev/null +++ b/third-party/FloatX/examples/example.cpp @@ -0,0 +1,58 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * Example of using the FloatX library. Compile with + * g++ -std=c++11 -I ../src test.cpp + */ +#include + + +#include + + +int main() +{ + std::cout << "sizeof(floatx) = " << sizeof(flx::floatx<11, 52>) + << "\nsizeof(floatxr) = " << sizeof(flx::floatxr<>) << std::endl; + // compile-time types + flx::floatx<11, 52> f; // double + flx::floatx<7, 22> g(5.3); // float with 7 exp and 22 significand bits + + // runtime types + flx::floatxr<> fr(11, 52); + flx::floatxr<> gr(7, 22, 5.3); + + std::cout << std::scientific; + + // conversion to double + std::cout << double(f) << std::endl + << double(g) << std::endl + << double(fr) << std::endl + << double(gr) << std::endl; + + // conversion to flexfloat + flx::floatx<3, 2> lg(g); + flx::floatx<3, 2> lgr(gr); + + std::cout << double(lg) << ", precision = " + << "(" << get_exp_bits(lg) << ", " << get_sig_bits(lg) << ")\n" + << double(lgr) << ", precision = " + << "(" << get_exp_bits(lgr) << ", " << get_sig_bits(lgr) << ")" + << std::endl; + return 0; +} diff --git a/third-party/FloatX/examples/example2.cpp b/third-party/FloatX/examples/example2.cpp new file mode 100644 index 0000000..82fa02a --- /dev/null +++ b/third-party/FloatX/examples/example2.cpp @@ -0,0 +1,189 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + * Example of using the FloatX library. Compile with + * g++ -std=c++11 -I ../src test.cpp + */ +#include + + +#include + +template +void foo(T* a, int n) +{ + printf("HI FOO ROUTINE\n"); + for (unsigned i = 0; i < n; ++i) { + if (i == 0 || i == 1) { + a[i] = 1; + } else { + a[i] = a[i - 1] + a[i - 2]; + } + } +} + +void compileExample() +{ + typedef flx::floatx<11, 48> T; + T res = 0; + + double a = 3.1; + double b = 5.2; + + res = (T)a * b; // ERROR + + std::cout << "[cout] res = " << res << std::endl; +} + +void compileExample2() +{ + typedef flx::floatx<11, 48> T; + T res = 33.45; + int i = 4; + + std::cout << "[cout] res = " << res << " and i = " << i << std::endl; + + // TODO (withouth double does not yet work) + if (res == (double)i) { + std::cout << "TRUE\n"; + } else { + std::cout << "FALSE\n"; + } + + if (res == 3.0) { + std::cout << "TRUE 2\n"; + } else { + std::cout << "FALSE 2\n"; + } +} + +int main() +{ + compileExample(); + compileExample2(); + printf("--------------------------\n"); + // Double-precision variables + + // simple use case + // flx::floatx<11, 52> ff_a, ff_b, ff_c; + // flx::floatx<5, 30> ff_a, ff_b, ff_c; + + // other use case + flx::floatx<11, 48> ff_a; + flx::floatx<5, 5> ff_b; + flx::floatx<11, 30> ff_c; + + // Assigment with cast (from double literal) + ff_a = 10.4; + ff_b = 11.5; + // Overloaded operators + // ff_b += 2; // DOES NOT WORK (cast from int not defined) + ff_b += 2.0; // WORKS. + + // ff_b = ff_b + 2; // DOES NOT WORK (cast from int not defined) + ff_b = ff_b + 2.0; // DOES NOT WORK (except flex is as double) + // ff_b = double( ff_b + flx::floatx<11, 32>(2)); //WORKS + + ff_c = ff_a + ff_b; + + // C++ output stream + // Explicit output as double. + std::cout << "output after double cast:\n"; + std::cout << "[cout] ff_a = " << double(ff_a) << std::endl; + std::cout << "[cout] ff_b = " << double(ff_b) << std::endl; + std::cout << "[cout] ff_c = " << double(ff_c) << std::endl; + + // Implicit output works as well. + std::cout << "Output:\n"; + std::cout << "[cout] ff_a = " << ff_a << std::endl; + std::cout << "[cout] ff_b = " << ff_b << std::endl; + std::cout << "[cout] ff_c = " << ff_c << std::endl; + + std::cout << "Get information about type:\n"; + std::cout << "[cout] ff_a = " << ff_a << " <" << get_exp_bits(ff_a) << "," + << get_sig_bits(ff_a) << ">" << std::endl; + std::cout << "[cout] ff_b = " << ff_b << " <" << get_exp_bits(ff_b) << "," + << get_sig_bits(ff_b) << ">" << std::endl; + std::cout << "[cout] ff_c = " << ff_c << " <" << get_exp_bits(ff_c) << "," + << get_sig_bits(ff_c) << ">" << std::endl; + + std::cout << "Sizeof Results (it is the static case):\n"; + std::cout << "sizeof( ff_a ) = " << sizeof(ff_a) << "\n"; + std::cout << "sizeof( ff_b ) = " << sizeof(ff_b) << "\n"; + std::cout << "sizeof( ff_c ) = " << sizeof(ff_c) << "\n"; + + // get_exp_bits() + // Binary output. + // std::cout << "[cout] ff_a = " << ff_a << " (" << flexfloat_as_bits << + // ff_a << flexfloat_as_double << ")" << std::endl; std::cout << "[cout] + // ff_b = " << ff_b << " (" << flexfloat_as_bits << ff_b << + // flexfloat_as_double << ")" << std::endl; std::cout << "[cout] ff_c = " << + // ff_c << " (" << flexfloat_as_bits << ff_c << flexfloat_as_double << ")" + // << std::endl; + + // generate arrays of data + // flexfloat<11, 52> ff_a + int n = 100; + // double* a = new double[n]; + flx::floatx<5, 12>* a = new flx::floatx<5, 12>[n]; + + for (unsigned i = 0; i < n; ++i) { + a[i] = i; + } + + // foo< flx::floatx<5, 12> >( a, n); // OK + // foo< flx::floatx<5, 52> >( a, n); //wrong type + foo(a, n); // infers type, ok + + for (unsigned i = 0; i < n; ++i) { + // std::cout << i << ":\t" << a[i] << " (" << flexfloat_as_bits << a[i] + // << flexfloat_as_double << ")" << std::endl; + std::cout << i << ":\t" << double(a[i]) << std::endl; + } + delete[] a; + + // std::cout << "sizeof(floatx) = " << sizeof(flx::floatx<11, 52>) + // << "\nsizeof(floatxr) = " << sizeof(flx::floatxr<>) + // << std::endl; + // // compile-time types + // flx::floatx<11, 52> f; // double + // flx::floatx<7, 22> g(5.3); // float with 7 exp and 22 significand bits + + // // runtime types + // flx::floatxr<> fr(11, 52); + // flx::floatxr<> gr(7, 22, 5.3); + + // std::cout << std::scientific; + + // // conversion to double + // std::cout << double(f) << std::endl + // << double(g) << std::endl + // << double(fr) << std::endl + // << double(gr) << std::endl; + + // // conversion to flexfloat + // flx::floatx<3, 2> lg(g); + // flx::floatx<3, 2> lgr(gr); + + // std::cout << double(lg) << ", precision = " + // << "(" << get_exp_bits(lg) << ", " << get_sig_bits(lg) << ")\n" + // << double(lgr) << ", precision = " + // << "(" << get_exp_bits(lgr) << ", " << get_sig_bits(lgr) << ")" + // << std::endl; + // return 0; +} diff --git a/third-party/FloatX/floatx.png b/third-party/FloatX/floatx.png new file mode 100644 index 0000000..17937e5 Binary files /dev/null and b/third-party/FloatX/floatx.png differ diff --git a/third-party/FloatX/src/floatx.hpp b/third-party/FloatX/src/floatx.hpp new file mode 100644 index 0000000..b82e340 --- /dev/null +++ b/third-party/FloatX/src/floatx.hpp @@ -0,0 +1,1101 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef FLOATX_FLOATX_HPP_ +#define FLOATX_FLOATX_HPP_ + + +#ifdef __CUDA_ARCH__ +#include "cuda_runtime.h" +#endif // __CUDA_ARCH__ + +#include + +#if CHAR_BIT != 8 +#error Expecting 8 bits in a char! +#endif // ?CHAR_BIT + +#include +#include +#include + +#include +#include +#include +#include +#include + + +#ifdef __CUDA_ARCH__ +#define FLOATX_ATTRIBUTES __host__ __device__ +#define FLOATX_INLINE __forceinline__ +#else // __CUDA_ARCH__ +#define FLOATX_ATTRIBUTES +#define FLOATX_INLINE inline +#endif // __CUDA_ARCH__ + + +#define USE_BUILTINS + + +namespace flx { + + +namespace detail { + + +static constexpr int bits_in_byte = CHAR_BIT; + + +template +class floatx_base; + + +template +struct bits_type {}; + + +#define ENABLE_STANDARD_BITS_TYPE(_size) \ + template <> \ + struct bits_type<_size / bits_in_byte> { \ + using type = std::uint##_size##_t; \ + } + +ENABLE_STANDARD_BITS_TYPE(8); +ENABLE_STANDARD_BITS_TYPE(16); +ENABLE_STANDARD_BITS_TYPE(32); +ENABLE_STANDARD_BITS_TYPE(64); + +#undef ENABLE_STANDARD_BITS_TYPE + + +} // namespace detail + + +#define FLOATX_USE_DEFAULT_TRAITS(_type) \ + static const auto sig_pos = 0; \ + static const auto exp_pos = float_traits<_type>::sig_bits; \ + static const auto sgn_pos = exp_pos + float_traits<_type>::exp_bits; \ + static const auto sig_mask = \ + (UINT64_C(1) << float_traits<_type>::sig_bits) - UINT64_C(1); \ + static const auto exp_mask = \ + (UINT64_C(1) << float_traits<_type>::exp_bits) - UINT64_C(1); \ + static const auto sgn_mask = UINT64_C(1); \ + static const auto bias = exp_mask >> 1; \ + using bits_type = typename detail::bits_type::type + + +template +struct float_traits {}; + +template +struct float_traits::value>::type> { + static const bool is_floatx = false; + static const bool is_runtime = false; + static const int exp_bits = 0; + static const int sig_bits = 0; + using backend_float = T; + + FLOATX_USE_DEFAULT_TRAITS(T); +}; + +template <> +struct float_traits { + static const bool is_floatx = false; + static const bool is_runtime = false; + static const int exp_bits = 8; + static const int sig_bits = 23; + using backend_float = float; + + FLOATX_USE_DEFAULT_TRAITS(float); +}; + +template <> +struct float_traits { + static const bool is_floatx = false; + static const bool is_runtime = false; + static const int exp_bits = 11; + static const int sig_bits = 52; + using backend_float = double; + + FLOATX_USE_DEFAULT_TRAITS(double); +}; + + +#define ENABLE_PROPERTY(_prop) \ + template \ + FLOATX_ATTRIBUTES FLOATX_INLINE constexpr auto get_##_prop( \ + const Float&) noexcept-> \ + typename std::enable_if::is_runtime, \ + decltype(float_traits::_prop)>::type \ + { \ + return float_traits::_prop; \ + } \ + template \ + FLOATX_ATTRIBUTES FLOATX_INLINE constexpr auto get_##_prop( \ + const RuntimeFloat& f) noexcept-> \ + typename std::enable_if::is_runtime, \ + decltype(f.get_##_prop())>::type \ + { \ + return f.get_##_prop(); \ + } + +ENABLE_PROPERTY(exp_bits); // get_exp_bits(f) +ENABLE_PROPERTY(sig_bits); // get_sig_bits(f) + +#undef ENABLE_PROPERTY + + +template +class floatx + : public detail::floatx_base> { +private: + using backend_float = typename float_traits::backend_float; + +public: + FLOATX_ATTRIBUTES floatx() noexcept + : detail::floatx_base(backend_float(0.0)) + { + this->initialize(); + } + + template + FLOATX_ATTRIBUTES floatx(const T& other) noexcept + : detail::floatx_base(backend_float(other)) + { + this->initialize(); + } + + // Default copy/move constructors/assignment operators are OK here + + template + FLOATX_ATTRIBUTES floatx& operator=(const T& other) noexcept + { + return *this = floatx(other); + } +}; + + +template +struct float_traits, void> { + static const bool is_floatx = true; + static const bool is_runtime = false; + static const int exp_bits = ExpBits; + static const int sig_bits = SigBits; + using backend_float = BackendFloat; + + FLOATX_USE_DEFAULT_TRAITS(backend_float); +}; + + +template +class floatxr + : public detail::floatx_base> { +private: + using backend_float = typename float_traits::backend_float; + +public: + using metadata_type = MetadataType; + + FLOATX_ATTRIBUTES + floatxr(metadata_type exp_bits, metadata_type sig_bits) noexcept + : detail::floatx_base(backend_float(0.0)), + exp_bits_(exp_bits), + sig_bits_(sig_bits) + { + this->initialize(); + } + + // Default copy/move constructors are OK + + template + FLOATX_ATTRIBUTES floatxr(metadata_type exp_bits, metadata_type sig_bits, + const T& other) noexcept + : detail::floatx_base(backend_float(other)), + exp_bits_(exp_bits), + sig_bits_(sig_bits) + { + this->initialize(); + } + + template + FLOATX_ATTRIBUTES floatxr(const T& other) noexcept + : detail::floatx_base(backend_float(other)), + exp_bits_(flx::get_exp_bits(other)), + sig_bits_(flx::get_sig_bits(other)) + { + /* already initialized */ + } + + // Assignment needs to preserve the format of the result + template + FLOATX_ATTRIBUTES floatxr& operator=(const T& other) noexcept + { + return *this = floatxr(flx::get_exp_bits(*this), + flx::get_sig_bits(*this), backend_float(other)); + } + + FLOATX_ATTRIBUTES void set_precision(metadata_type exp_bits, + metadata_type sig_bits) + { + exp_bits_ = exp_bits; + sig_bits_ = sig_bits; + this->initialize(); + } + + FLOATX_ATTRIBUTES constexpr metadata_type get_exp_bits() const noexcept + { + return exp_bits_; + } + + FLOATX_ATTRIBUTES constexpr metadata_type get_sig_bits() const noexcept + { + return sig_bits_; + } + +private: + metadata_type exp_bits_; + metadata_type sig_bits_; +}; + + +template +struct float_traits, void> { + static const bool is_floatx = true; + static const bool is_runtime = true; + static const int exp_bits = float_traits::exp_bits; + static const int sig_bits = float_traits::sig_bits; + using backend_float = BackendFloat; + + FLOATX_USE_DEFAULT_TRAITS(backend_float); +}; + + +template +struct supertype { +private: + static constexpr int max(int x, int y) { return (x > y) ? x : y; } + +public: +#ifdef FLOATX_NO_TYPE_RESOLUTION + static_assert(std::is_same::value, + "Common type detection is disabled by the user" + " [FLOATX_NO_TYPE_RESOLUTION]"); +#endif // FLOATX_NO_TYPE_RESOLUTION + + using type = typename std::enable_if< + float_traits::is_floatx || float_traits::is_floatx, + typename std::conditional::is_runtime || + float_traits::is_runtime, + floatxr, + floatx::exp_bits, + float_traits::exp_bits), + max(float_traits::sig_bits, + float_traits::sig_bits), + BackendFloat>>::type>::type; + static constexpr int max_exp_bits(FloatX1 x, FloatX2 y) + { + return max(get_exp_bits(x), get_exp_bits(y)); + } + static constexpr int max_sig_bits(FloatX1 x, FloatX2 y) + { + return max(get_sig_bits(x), get_sig_bits(y)); + } +}; + + +#define ENABLE_RELATIONAL_OPERATOR(_op) \ + template \ + FLOATX_ATTRIBUTES FLOATX_INLINE \ + typename std::enable_if::is_floatx || \ + float_traits::is_floatx, \ + bool>::type \ + operator _op(const Float1& x, const Float2& y) \ + { \ + return typename float_traits::backend_float(x) _op \ + typename float_traits::backend_float(y); \ + } + +ENABLE_RELATIONAL_OPERATOR(==) +ENABLE_RELATIONAL_OPERATOR(!=) +ENABLE_RELATIONAL_OPERATOR(<) +ENABLE_RELATIONAL_OPERATOR(>) +ENABLE_RELATIONAL_OPERATOR(<=) +ENABLE_RELATIONAL_OPERATOR(>=) + +#undef ENABLE_RELATIONAL_OPERATOR + + +#define ENABLE_ARITHMETIC_OPERATOR(_op) \ + template \ + FLOATX_ATTRIBUTES FLOATX_INLINE typename std::enable_if< \ + (float_traits::is_floatx || \ + float_traits::is_floatx) && \ + !float_traits::is_runtime && \ + !float_traits::is_runtime, \ + typename supertype< \ + Float1, Float2, \ + decltype(typename float_traits::backend_float() _op \ + typename float_traits::backend_float())>::type>:: \ + type \ + operator _op(const Float1& x, const Float2& y) \ + { \ + using bf = decltype(typename float_traits::backend_float( \ + x) _op typename float_traits::backend_float(y)); \ + using st = typename supertype::type; \ + return st(bf(x) _op bf(y)); \ + } \ + \ + template \ + FLOATX_ATTRIBUTES FLOATX_INLINE typename std::enable_if< \ + float_traits::is_runtime || float_traits::is_runtime, \ + typename supertype< \ + Float1, Float2, \ + decltype(typename float_traits::backend_float() _op \ + typename float_traits::backend_float())>::type>:: \ + type \ + operator _op(const Float1& x, const Float2& y) \ + { \ + using bf = decltype(typename float_traits::backend_float( \ + x) _op typename float_traits::backend_float(y)); \ + using st = supertype; \ + return typename st::type(st::max_exp_bits(x, y), \ + st::max_sig_bits(x, y), bf(x) _op bf(y)); \ + } \ + \ + template \ + FLOATX_ATTRIBUTES FLOATX_INLINE \ + typename std::enable_if::is_floatx || \ + float_traits::is_floatx, \ + Float1&>::type \ + operator _op##=(Float1& x, const Float2& y) \ + { \ + return x = Float1(x _op y); \ + } + +ENABLE_ARITHMETIC_OPERATOR(+) +ENABLE_ARITHMETIC_OPERATOR(-) +ENABLE_ARITHMETIC_OPERATOR(*) +ENABLE_ARITHMETIC_OPERATOR(/) + +#undef ENABLE_ARITHMETIC_OPERATOR + + +template +FLOATX_INLINE typename std::enable_if::is_floatx, + std::ostream&>::type& +operator<<(std::ostream& os, const FloatX& f) noexcept +{ + return os << typename float_traits::backend_float(f); +} + + +template +FLOATX_INLINE typename std::enable_if::is_floatx, + std::istream&>::type +operator>>(std::istream& is, FloatX& f) noexcept +{ + typename float_traits::backend_float tmp; + is >> tmp; + f = tmp; + return is; +} + + +template +FLOATX_ATTRIBUTES FLOATX_INLINE + std::bitset::backend_float)> + bits(const Float& x) noexcept +{ + using bf = typename float_traits::backend_float; + using bitset = std::bitset; + bf val = bf(x); + return *reinterpret_cast(&val); +} + + +namespace detail { + + +template +constexpr FLOATX_ATTRIBUTES FLOATX_INLINE + typename float_traits::bits_type + reinterpret_as_bits(Float val) +{ + return *reinterpret_cast::bits_type*>( + &val); +} + + +template +constexpr FLOATX_ATTRIBUTES FLOATX_INLINE Float +reinterpret_bits_as(typename float_traits::bits_type bits) +{ + return *reinterpret_cast(&bits); +} + + +template +constexpr FLOATX_ATTRIBUTES FLOATX_INLINE SignificandType +get_round_nearest_correction(SignificandType sig, SignificandType lsb_mask, + SignificandType after_lsb_mask, + SignificandType rest_mask) +{ + return (sig & after_lsb_mask) && ((sig & rest_mask) || (sig & lsb_mask)); +} + + +FLOATX_ATTRIBUTES FLOATX_INLINE constexpr uint64_t +generate_rest_mask_fast_shift_less64(uint64_t MASK_AFTER_LSB) +{ + return (MASK_AFTER_LSB >= 1) ? (MASK_AFTER_LSB - UINT64_C(0x1)) + : UINT64_C(0x0000000000000000); +} + + +FLOATX_ATTRIBUTES FLOATX_INLINE uint64_t round_nearest(uint64_t mant, + uint16_t SHIFT) +{ + if (SHIFT >= 64) + SHIFT = 63; // that works to cover the case of down-shifts if the bit + // number 63 is never set. (since DATA >> 64 is all zero + // which is in that case equivalent to DATA >> 63) + assert(!(mant & (UINT64_C(0x1) << 63))); + + // fast, no additional cases and simpler MASK generation. + const uint64_t MASK_LSB = UINT64_C(0x0000000000000001) << SHIFT; + const uint64_t MASK_AFTER_LSB = UINT64_C(0x0000000000000001) << (SHIFT - 1); + const uint64_t MASK_REST = + generate_rest_mask_fast_shift_less64(MASK_AFTER_LSB); + + uint64_t mant_res = mant >> SHIFT; + + if ((mant & MASK_AFTER_LSB) && ((mant & MASK_REST) || (mant & MASK_LSB))) { + // round up if the bit after the lsb is set (>=0.5) and the number is + // indeed bigger than >0.5 or if it is =0.5 and the TiesToEven rule + // requires to round up. + mant_res += 0x1; + } + + mant_res = mant_res << SHIFT; + + return mant_res; +} + + +// CONSTANTS USED FOR BACKEND = DOUBLE +const uint64_t MASK_MANTISSA = UINT64_C(0x000FFFFFFFFFFFFF); +const uint64_t MASK_EXPONENT = UINT64_C(0x7FF0000000000000); +const uint64_t MASK_SIGN = UINT64_C(0x8000000000000000); +const uint64_t MASK_MANTISSA_OVERFLOW = UINT64_C(0x0010000000000000); +const uint64_t POS_INF_PATTERN = UINT64_C(0x7ff0000000000000); +const uint64_t NEG_INF_PATTERN = UINT64_C(0xfff0000000000000); +const uint64_t BACKEND_BIAS = + UINT64_C(1023); // that value is 2^(BACKEND_E-1)-1. +const int BACKEND_E = 11; +const int BACKEND_M = 52; + + +template +constexpr FLOATX_ATTRIBUTES FLOATX_INLINE bool is_nan_or_inf(BitsType number) +{ + return (number & MASK_EXPONENT) == MASK_EXPONENT; +} + + +template +constexpr FLOATX_ATTRIBUTES FLOATX_INLINE bool is_small(BitsType e, + ExpType emin) +{ + return e < emin; +} + + +FLOATX_ATTRIBUTES FLOATX_INLINE uint64_t +convert_nan_or_inf_to_backend(const uint64_t number, const uint8_t M) +{ + // The following line delets any additional information that might be coded + // in NAN bits. NAN bits towards the MSB of the mantissa that fit into the + // target type are preserved. + const uint64_t MASK_DELETE = UINT64_C(0xFFFFFFFFFFFFFFFF) + << (BACKEND_M - M); + + // fix the nan (note that the following line does not affects +INF and -INF + // by construction) + return (number & MASK_DELETE); +} + +FLOATX_ATTRIBUTES FLOATX_INLINE void convert_subnormal_mantissa_and_exp( + const uint64_t number, const uint8_t M, const int16_t emin, const int e, + uint64_t& mant, uint64_t& exp) +{ + int t = emin - e; + + // the hidden one might have a influence in rounding, hence add the hidden + // one to the mantissa. + mant = mant | MASK_MANTISSA_OVERFLOW; + + // Perform IEEE 754 rounding with TiesToEven. + mant = round_nearest(mant, BACKEND_M - M + t); + + // Handle the case where the number is rounded to exact 0 + // since it is smaller (after rounding) than the smallest Subnormal / 2 + if (mant == 0x0) { + exp = 0x0; + } + + // remove the hidden one from the mantissa + mant = mant & ~MASK_MANTISSA_OVERFLOW; +} + +FLOATX_ATTRIBUTES FLOATX_INLINE void fix_too_large_mantissa(const int M, int& e, + uint64_t& mant, + uint64_t& exp) +{ + e += 1; + // The following is the formula for the new exponent in the case the + // mantissa was rounded up to a value that does not fit into the MANTISSA + // field. + exp = ((uint64_t)e + BACKEND_BIAS) << BACKEND_M; + mant = UINT64_C(0x0000000000000000); +} + +FLOATX_ATTRIBUTES FLOATX_INLINE uint64_t assemble_regular_number( + const uint64_t sign_pattern, const uint64_t mant, const uint64_t exp) +{ + // ensure that the mantissa and exp fields to not contain bits at wrong + // locations. + assert((mant & ~MASK_MANTISSA) == 0x0); + assert((exp & ~MASK_EXPONENT) == 0x0); + + // Assemble the number from the original sign and the current exp and mant + // field. + return (sign_pattern | exp | mant); +} + +FLOATX_ATTRIBUTES FLOATX_INLINE uint64_t +assemble_inf_number(const uint64_t sign_pattern) +{ + // The code of rounding operates on the magnitude, here we still need to at + // the right sign for the final number + return sign_pattern | POS_INF_PATTERN; +} + +// // functionality to get bit representations. +// bool get_sign_from_backend(const double d); + +// // That functions return the bit representation embedded in a data word. A +// backend representation of type +// // will return the full representation of 1+E+M bits in the LSB : LSB+1+E+M +// bit positions of the embedding dataword (e.g. uint64_t). uint16_t +// get_exponent_from_backend(const double d, const uint8_t E, const uint8_t M); +// uint64_t get_mantissa_from_backend(const double d, const uint8_t E, const +// uint8_t M); uint64_t get_fullbit_representation(const double d, const uint8_t +// E, const uint8_t M); + +// // The reverse operation generates constructs a given number of exponent and +// mantissa bits. +// // Note, that the input is encoded into the embedding type as follows: +// // exp: bits (E-1) downto 0 +// // mant: bits (M-1) downto 0 +// // -> bits at higher positions are required to be 0. (?) or neglected? +// double construct_number(bool sign, uint16_t exp, uint64_t mant, const uint8_t +// E, const uint8_t M); + +// functionality to get bit representations. +FLOATX_ATTRIBUTES FLOATX_INLINE bool get_sign_from_backend(const double d) +{ + uint64_t number = flx::detail::reinterpret_as_bits(d); + return (number & MASK_SIGN); +} + +FLOATX_ATTRIBUTES FLOATX_INLINE constexpr bool is_zero_or_nan_or_inf_exp( + const uint64_t exp) +{ + return ((exp == 0x0) || (exp == MASK_EXPONENT)); +} + +FLOATX_ATTRIBUTES FLOATX_INLINE uint16_t +get_exponent_zero_or_nan_or_inf_exp(const uint64_t exp, const uint8_t E) +{ + uint16_t target_exp = (uint16_t)(exp >> BACKEND_M); + // if it is an inf or nan delete any additional ones in the format. + // (exponent requires E 1's) + target_exp = target_exp & ((0x1 << E) - 1); + + // assert no bits are set at positions 15:E. + // information is encoded only at positons E-1:0. + assert(target_exp < (0x1 << E)); + return target_exp; +} + +FLOATX_ATTRIBUTES FLOATX_INLINE uint16_t +get_exponent_regular_backend_exp(const uint64_t exp, const uint8_t E) +{ + // That is the double exponent. + // Interpret the exponent. + uint16_t target_exp = 0x0; + int e = (exp >> BACKEND_M) - BACKEND_BIAS; + + // TARGET FORMAT (emax and emin depends on E) + // IEEE 754 STANDARD + int16_t emax = (0x1 << (E - 1)) - 1; + int16_t emin = 1 - emax; + + // Target bias is the same as emax. + if (e < emin) { + // a regular case in the backend, but a subnormal in the target format. + target_exp = 0x0; // subnormals have a zero exponent. + } else { + // Encode the exponent in target format. + target_exp = (uint16_t)(e + emax); + } + + // assert no bits are set at positions 15:E. + // information is encoded only at positons E-1:0. + assert(target_exp < (0x1 << E)); + return target_exp; +} + +FLOATX_ATTRIBUTES FLOATX_INLINE uint64_t +get_mantissa_zero_or_nan_or_inf_exp(const uint64_t mant, const uint8_t M) +{ + uint64_t ret = mant >> (BACKEND_M - M); + + assert(ret < (UINT64_C(0x1) << M)); + return ret; +} + +FLOATX_ATTRIBUTES FLOATX_INLINE uint64_t get_mantissa_regular_backend_exp( + const uint64_t exp, const uint64_t mant, const uint8_t E, const uint8_t M) +{ + // That is the double exponent. + // Interpret the exponent. + int e = (exp >> BACKEND_M) - BACKEND_BIAS; + + // TARGET FORMAT (emax and emin depends on E) + // IEEE 754 STANDARD + int16_t emax = (0x1 << (E - 1)) - 1; + int16_t emin = 1 - emax; + // Target bias is the same as emax. + + uint64_t ret; + + if (e < emin) { + int t = emin - e; + // Subnormal. The backend mantissa needs the hidden 1 that is visible in + // the subnormal representation of the target format. + ret = (mant | MASK_MANTISSA_OVERFLOW) >> (BACKEND_M - M + t); + } else { + ret = mant >> (BACKEND_M - M); + } + + assert(ret < (UINT64_C(0x1) << M)); + return ret; +} + +FLOATX_ATTRIBUTES FLOATX_INLINE uint16_t +get_exponent_from_backend(const double d, const uint8_t E) +{ + uint64_t number = flx::detail::reinterpret_as_bits(d); + uint64_t exp = number & MASK_EXPONENT; + + // detects, zero, denormals, infs and nans in the backend double. + if (is_zero_or_nan_or_inf_exp(exp)) { + return get_exponent_zero_or_nan_or_inf_exp(exp, E); + } else { + return get_exponent_regular_backend_exp(exp, E); + } +} + +FLOATX_ATTRIBUTES FLOATX_INLINE uint64_t +get_mantissa_from_backend(const double d, const uint8_t E, const uint8_t M) +{ + uint64_t number = flx::detail::reinterpret_as_bits(d); + uint64_t exp = number & MASK_EXPONENT; + uint64_t mant = number & MASK_MANTISSA; + + if (is_zero_or_nan_or_inf_exp(exp)) { + return get_mantissa_zero_or_nan_or_inf_exp(mant, M); + } else { + return get_mantissa_regular_backend_exp(exp, mant, E, M); + } +} + +FLOATX_ATTRIBUTES FLOATX_INLINE uint8_t +count_leading_zeros(const uint64_t data) noexcept +{ +#ifdef USE_BUILTINS +#ifdef __CUDA_ARCH__ + return __clzll(data); +#else // !__CUDA_ARCH__ + return __builtin_clzl(data); +#endif // ?__CUDA_ARCH__ +#else // !USE_BUILTINS + uint8_t t = 0u; // t will be the number of zero bits on the left + for (t = 0u; t < 64u; ++t) { + if (data & (UINT64_C(0x1) << (63u - t))) { + break; + } + } + return t; +#endif // ?USE_BUILTINS +} + + +FLOATX_ATTRIBUTES FLOATX_INLINE void construct_number_subormal( + uint64_t& backend_exp, uint64_t& mant, const int16_t emin, const uint8_t M) +{ + // Zero and Subnormal. + if (mant == UINT64_C(0x0)) { + // real zero. + backend_exp = 0x0; + mant = 0x0; + } else { + // a subnormal in the target fromat, but result in a regular number in + // the backend fromat. + uint8_t t = count_leading_zeros(mant); + t = t - (63 - M); + + // interpret exponent in the format. + + int e = emin - t; + + // rewrite the exponent in the backend format. + backend_exp = ((uint64_t)e + BACKEND_BIAS) << BACKEND_M; + + // mantissa. + mant = mant << (BACKEND_M - M + t); + mant = mant & ~MASK_MANTISSA_OVERFLOW; + } +} + +FLOATX_ATTRIBUTES FLOATX_INLINE void construct_number_nan_or_inf( + uint64_t& backend_exp, uint64_t& mant, const uint8_t M) +{ + if (mant == 0x0) { + // Inf + backend_exp = MASK_EXPONENT; // encode a backend inf. + } else { + // Nan + backend_exp = MASK_EXPONENT; // encode nan + mant = mant << (BACKEND_M - M); + } +} + +FLOATX_ATTRIBUTES FLOATX_INLINE void construct_number_regular( + uint64_t& backend_exp, uint64_t& mant, uint16_t const exp, int16_t emax, + const uint8_t M) +{ + mant = mant << (BACKEND_M - M); + + // interpret exponent in the format. + int e = exp - emax; + + // rewrite the exponent in the backend format. + backend_exp = ((uint64_t)e + BACKEND_BIAS) << BACKEND_M; +} + +FLOATX_ATTRIBUTES FLOATX_INLINE double construct_number(bool sign, uint16_t exp, + uint64_t mant, + const uint8_t E, + const uint8_t M) +{ + uint64_t backend_exp = 0x0; + + // use emax as bias for the format. + int16_t emax = (0x1 << (E - 1)) - 1; + int16_t emin = 1 - emax; + + if (exp == 0x0) { + construct_number_subormal(backend_exp, mant, emin, M); + } else if (exp == ((0x1 << E) - 0x1)) { + construct_number_nan_or_inf(backend_exp, mant, M); + } else { + construct_number_regular(backend_exp, mant, exp, emax, M); + } + + uint64_t sign_bit = MASK_SIGN; + sign_bit *= sign; + + uint64_t number = sign_bit | backend_exp | mant; + double res = reinterpret_bits_as(number); + return res; +} + +FLOATX_ATTRIBUTES FLOATX_INLINE double construct_number( + uint64_t fullbit_representation, const uint8_t E, const uint8_t M) +{ + bool sign = (fullbit_representation & (UINT64_C(0x1) << (E + M))); + uint64_t exp = + fullbit_representation & (((UINT64_C(0x1) << E) - UINT64_C(1)) << M); + exp = exp >> M; + uint64_t mant = + fullbit_representation & ((UINT64_C(0x1) << M) - UINT64_C(1)); + return construct_number(sign, (uint16_t)exp, mant, E, M); +} + +FLOATX_ATTRIBUTES FLOATX_INLINE uint64_t construct_fullbit_representation( + bool sign, uint16_t exp, uint64_t mant, const uint8_t E, const uint8_t M) +{ + assert(exp < (0x1 << E)); + assert(mant < (UINT64_C(0x1) << M)); + + uint64_t sign_bit = UINT64_C(0x1) << (E + M); + sign_bit *= sign; + + uint64_t target_exp = (uint64_t)exp; + target_exp = target_exp << M; + + // Note that the words have information encoded at different positions + // [63:E+M+1] free + // E+M sign_bit + // E+M-1:M target_exp + // M-1:0 mantissa + mant = sign_bit | target_exp | mant; + + return mant; +} + +// That functions return the bit representation embedded in a data word. A +// backend representation of type will return the full representation of +// 1+E+M bits in the LSB : LSB+1+E+M bit positions of the embedding dataword +// (e.g. uint64_t). Encoding of the result: [63:E+M+1] free E+M +// sign_bit E+M-1:M target_exp M-1:0 mantissa +FLOATX_ATTRIBUTES FLOATX_INLINE uint64_t +get_fullbit_representation(const double d, const uint8_t E, const uint8_t M) +{ + return construct_fullbit_representation( + get_sign_from_backend(d), get_exponent_from_backend(d, E), + get_mantissa_from_backend(d, E, M), E, M); +} + +// Bitset wrappers. +template +FLOATX_ATTRIBUTES FLOATX_INLINE std::bitset get_exponent_from_backend_BS( + const double d) +{ + return std::bitset(get_exponent_from_backend(d, E)); +} + +template +FLOATX_ATTRIBUTES FLOATX_INLINE std::bitset get_mantissa_from_backend_BS( + const double d) +{ + return std::bitset(get_mantissa_from_backend(d, E, M)); +} + +template +FLOATX_ATTRIBUTES FLOATX_INLINE std::bitset<1 + E + M> +get_fullbit_representation_BS(const double d) +{ + return std::bitset<1 + E + M>(get_fullbit_representation(d, E, M)); +} + +template +FLOATX_ATTRIBUTES FLOATX_INLINE double construct_number(bool sign, + std::bitset exp, + std::bitset mant) +{ + return construct_number(sign, exp.to_ulong(), mant.to_ulong(), E, M); +} + +template +FLOATX_ATTRIBUTES FLOATX_INLINE double construct_number( + std::bitset<1 + E + M> fullbit_representation) +{ + return construct_number(fullbit_representation.to_ulong(), E, M); +} + +#define ENABLE_EXTRACT_PART(_part) \ + template \ + FLOATX_ATTRIBUTES FLOATX_INLINE uint64_t extract_##_part##_bits( \ + const T& val) noexcept \ + { \ + return (*reinterpret_cast(&val) >> \ + float_traits::_part##_pos) & \ + float_traits::_part##_mask; \ + } + +ENABLE_EXTRACT_PART(sgn); +ENABLE_EXTRACT_PART(exp); +ENABLE_EXTRACT_PART(sig); + +#undef ENABLE_EXTRACT_PART + +template +class floatx_base { +private: + using backend_float = typename float_traits::backend_float; + using bits_type = typename float_traits::bits_type; + +public: + FLOATX_ATTRIBUTES floatx_base(const backend_float& value) noexcept + : value_(value) + {} + + FLOATX_ATTRIBUTES void initialize() noexcept + { + value_ = this->enforce_rounding(value_); + } + + FLOATX_ATTRIBUTES constexpr operator backend_float() const noexcept + { + return value_; + } + + template + FLOATX_ATTRIBUTES constexpr operator T() const noexcept + { + return T(value_); + } + +private: + FLOATX_ATTRIBUTES const ConcreteFloatX& self() const noexcept + { + return *static_cast(this); + } + + FLOATX_ATTRIBUTES ConcreteFloatX& self() noexcept + { + return *static_cast(this); + } + + static constexpr auto backend_sig_pos = + float_traits::sig_pos; + static constexpr auto backend_exp_pos = + float_traits::exp_pos; + static constexpr auto backend_sgn_pos = + float_traits::sgn_pos; + static constexpr auto backend_sig_mask = + float_traits::sig_mask << backend_sig_pos; + static constexpr auto backend_exp_mask = + float_traits::exp_mask << backend_exp_pos; + static constexpr auto backend_sig_bits = + float_traits::sig_bits; + static constexpr auto backend_exp_bits = + float_traits::exp_bits; + static constexpr auto backend_bias = float_traits::bias; + static constexpr auto backend_sig_overflow_mask = + (float_traits::sig_mask + 1) << backend_sig_pos; + static constexpr auto backend_sgn_mask = + float_traits::sgn_mask << backend_sgn_pos; + + FLOATX_ATTRIBUTES + backend_float enforce_rounding(backend_float value) const noexcept + { + const auto exp_bits = get_exp_bits(self()); + const auto sig_bits = get_sig_bits(self()); + bits_type bits = reinterpret_as_bits(value); + auto sig = (bits & backend_sig_mask) >> backend_sig_pos; + auto raw_exp = bits & backend_exp_mask; + const auto sgn = bits & backend_sgn_mask; + + int exp = (raw_exp >> backend_exp_pos) - backend_bias; + + const int emax = (1 << (exp_bits - 1)) - 1; + const int emin = 1 - emax; + + if (is_nan_or_inf(bits)) { + bits = convert_nan_or_inf_to_backend(bits, sig_bits); + } else { + if (is_small(exp, emin)) { + convert_subnormal_mantissa_and_exp(bits, sig_bits, emin, exp, + sig, raw_exp); + } else { + sig = round_nearest(sig, backend_sig_bits - sig_bits); + } + if (significand_is_out_of_range(sig)) { + fix_too_large_mantissa(sig_bits, exp, sig, raw_exp); + } + if (exponent_is_out_of_range(exp, emax)) { + bits = assemble_inf_number(sgn); + } else { + bits = assemble_regular_number(sgn, sig, raw_exp); + } + } + + return reinterpret_bits_as(bits); + } + + static constexpr FLOATX_ATTRIBUTES bits_type + reinterpret_as_bits(backend_float val) + { + return *reinterpret_cast(&val); + } + + static constexpr FLOATX_ATTRIBUTES bool significand_is_out_of_range( + bits_type sig) + { + return sig >= backend_sig_overflow_mask; + } + + static constexpr FLOATX_ATTRIBUTES bool exponent_is_out_of_range(int exp, + int emax) + { + return exp > emax; + } + +protected: + backend_float value_; +}; + + +} // namespace detail + + +template +FLOATX_ATTRIBUTES FLOATX_INLINE std::string bitstring(const Float& x) noexcept +{ + using bf = typename float_traits::backend_float; + const uint64_t one = UINT64_C(1); + const char map[] = {'0', '1'}; + const int eb = get_exp_bits(x); + const int sb = get_sig_bits(x); + const int beb = get_exp_bits(bf(x)); + const int bsb = get_sig_bits(bf(x)); + + std::string s(sb + eb + 3, '-'); + auto sgn = detail::extract_sgn_bits(bf(x)); + auto exp = detail::extract_exp_bits(bf(x)); + auto sig = detail::extract_sig_bits(bf(x)); + + int i = 0; + s[i++] = map[bool(sgn & UINT64_C(1))]; // sign bit + ++i; // leave '-' between sign and exponent parts + s[i++] = map[bool(exp & (one << (beb - 1)))]; // bias bit + for (auto mask = (one << (eb - 2)); mask > 0; mask >>= 1) { + s[i++] = map[bool(exp & mask)]; + } + ++i; // leave '-' between exponent and significand parts + for (auto mask = (one << (bsb - 1)); i < s.size(); mask >>= 1) { + s[i++] = map[bool(sig & mask)]; + } + return s; +} + + +}; // namespace flx + + +#undef FLOATX_ATTRIBUTES +#undef FLOATX_INLINE +#undef USE_BUILTINS + + +#endif // FLOATX_FLOATX_HPP_ diff --git a/third-party/FloatX/test/CMakeLists.txt b/third-party/FloatX/test/CMakeLists.txt new file mode 100644 index 0000000..f0a44fd --- /dev/null +++ b/third-party/FloatX/test/CMakeLists.txt @@ -0,0 +1,24 @@ +function(create_test test_name) + add_executable(${test_name} ${test_name}.cpp) + target_link_libraries(${test_name} PRIVATE floatx gtest_main) + file(RELATIVE_PATH REL_BINARY_DIR + ${PROJECT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + add_test(NAME ${REL_BINARY_DIR}/${test_name} COMMAND ${test_name}) +endfunction(create_test) + +add_library(ieee_helper STATIC IEEEHelper.cpp) + +create_test(conversion) +create_test(assignment) +create_test(rel_ops) +create_test(arithmetic) +create_test(stream) +create_test(std_integration) +create_test(NanInf) +create_test(round_nearest) +create_test(value_representation) +target_link_libraries(value_representation PRIVATE ieee_helper) +create_test(value_representation_half) +target_link_libraries(value_representation_half PRIVATE ieee_helper) +create_test(value_representation_bits) +target_link_libraries(value_representation_bits PRIVATE ieee_helper) diff --git a/third-party/FloatX/test/IEEEHelper.cpp b/third-party/FloatX/test/IEEEHelper.cpp new file mode 100644 index 0000000..02a1dc6 --- /dev/null +++ b/third-party/FloatX/test/IEEEHelper.cpp @@ -0,0 +1,131 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "IEEEHelper.h" + + +#include +#include +#include +#include +#include +#include + + +void IEEEHelper::showConfig() +{ + printf("Configuration of format<%u,%u>:\n", _e, _m); + printf(" p = %u\n", _m + 1); + printf(" emax = %i\n", getEmax()); + printf(" emin = %i\n", getEmin()); + printf(" bias = %i\n", getBias()); + printf("Limits:\n"); + printf(" max: %5e \t = %.20f\n", maxValue(), maxValue()); + printf(" sNr: %5e \t = %.20f\n", smallestNormalValue(), + smallestNormalValue()); + printf(" lSN: %5e \t = %.20f\n", maxSubnormalValue(), maxSubnormalValue()); + printf(" sSN: %5e \t = %.20f\n", minSubnormalValue(), minSubnormalValue()); + printf("Cases (one-sided):\n"); + printf(" Normal: %i \t = %u*%u\n", countNormalRange(), countExpRange(), + countSubnormalRange()); + printf(" Subnormal: %i\n", countSubnormalRange()); + printf(" NAN/INFs: %i\n", countSubnormalRange()); + printf(" 2^(E+M) = %i = (sum over #cases one side) = %u\n", + (int)pow(2, _e + _m), + countNormalRange() + 2 * countSubnormalRange()); + printf("\n"); +} + +double IEEEHelper::iterateNormalRange(int ie, int im) +{ + assert(ie >= 0); + assert(ie < _NnormalExp); + assert(im >= 0); + assert(im < _Nsubnormal); + + double m = 1.0 + im * pow(2.0, -_m); + // printf("im = %i, m = %f\n", im, m ); + return pow(2.0, ie + getEmin()) * m; +} + +double IEEEHelper::iterateSubnormalRange(int im) +{ + assert(im >= 0); + assert(im < _Nsubnormal); + + double m = 0.0 + im * pow(2.0, -_m); + return pow(2.0, getEmin()) * m; +} + +void show(uint64_t u) +{ + printf("%016llx\t", u); + std::cout << std::bitset<64>(u) << std::endl; +} + +#define CAST_DOUBLE_TO_UINT64(d) (*((uint64_t*)(&(d)))) +#define CAST_UINT64_TO_DOUBLE(d) (*((double*)(&(d)))) + +void show(double d) +{ + printf("%.20e\t", d); + uint64_t u = CAST_DOUBLE_TO_UINT64(d); + printf("0x%016llx\t", u); + std::cout << std::bitset<64>(u) << std::endl; +} + +void showTable(IEEEHelper& h) +{ + int ne = h.countExpRange(); + int nm = h.countSubnormalRange(); + + printf("Subnormal Range:\n"); + + for (int im = 0; im < nm; ++im) { + double d = h.iterateSubnormalRange(im); + printf("%5i/%5i: \t %.20e \t %f \n", im, nm, d, d); + } + + printf("Normal Range:\n"); + for (int ie = 0; ie < ne; ++ie) { + for (int im = 0; im < nm; ++im) { + double d = h.iterateNormalRange(ie, im); + printf("(%5i,%5i)/(%5i,%5i): \t %.20e \t %f \n", ie, im, ne, nm, d, + d); + } + } +} + + +// int main(int argc, char **argv) +// { +// if( argc != 2+1 ) +// { +// printf("Usage: %s \n", argv[0]); +// exit(1); +// } + +// int e = atoi( argv[1]); +// int m = atoi( argv[2]); + +// IEEEHelper h = IEEEHelper(e,m); + +// h.showConfig(); +// show( h ); + +// return 0; +// } diff --git a/third-party/FloatX/test/IEEEHelper.h b/third-party/FloatX/test/IEEEHelper.h new file mode 100644 index 0000000..0772387 --- /dev/null +++ b/third-party/FloatX/test/IEEEHelper.h @@ -0,0 +1,62 @@ +#pragma once + +#include + +// ### IEEE 754 HELPER FUNCITONS + +class IEEEHelper { +private: + int _e; + int _m; + int _emax; + int _emin; + + long long int _Nnormal; + long long int _NnormalExp; + long long int _Nsubnormal; + +public: + IEEEHelper(int e, int m) + { + _e = e; + _m = m; + + _Nnormal = (getEmax() - getEmin() + 1) * pow(2.0, _m); + _NnormalExp = (getEmax() - getEmin() + 1); + _Nsubnormal = pow(2.0, _m); + } + + inline int getEmax() { return pow(2.0, _e - 1) - 1; } + inline int getEmin() { return 1 - getEmax(); } + inline int getBias() { return getEmax(); } + + inline double getMmin() { return pow(2.0, -_m); } // use p = m+1 + inline double getMmaxNormal() { return 2 - pow(2.0, -_m); } // use p = m+1 + inline double getMmaxSubnormal() + { + return 1 - pow(2.0, -_m); + } // use p = m+1 + + inline double maxValue() { return pow(2.0, getEmax()) * getMmaxNormal(); } + inline double smallestNormalValue() { return pow(2.0, getEmin()); } + inline double maxSubnormalValue() + { + return pow(2.0, getEmin()) * getMmaxSubnormal(); + } + inline double minSubnormalValue() + { + return pow(2.0, getEmin()) * getMmin(); + } + + void showConfig(); + + int countNormalRange() { return _Nnormal; } + int countExpRange() { return _NnormalExp; } + int countSubnormalRange() { return _Nsubnormal; } + + double iterateNormalRange(int ie, int im); + double iterateSubnormalRange(int i); +}; + +void show(double d); +void showTable(IEEEHelper& h); diff --git a/third-party/FloatX/test/NanInf.cpp b/third-party/FloatX/test/NanInf.cpp new file mode 100644 index 0000000..f90ad0d --- /dev/null +++ b/third-party/FloatX/test/NanInf.cpp @@ -0,0 +1,154 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include +#include + +// #include // defines NAN +// #define nan NAN +#define nan double(0.0 / 0.0) +#define inf double(1.0 / 0.0) + +namespace { + +void show(double d) +{ + printf("%.20e\t", d); + uint64_t u = flx::detail::reinterpret_as_bits(d); + printf("0x%016llx\t", u); + std::cout << std::bitset<64>(u) << std::endl; +} + + +// System representation of nan's. +TEST(FloatxNanInfTest, system_nans) +{ + double constnan = 0.0 / 0.0; + printf("constnan: "); + show((double)constnan); + + double zero; + // try to prevent the compiler to figure out what + // dynamicnan should be in the compile time + *(double*)memset(&zero, ~0, sizeof(zero)) = 0.0; + double dynamicnan = zero / zero; + printf("dynamicnan: "); + show((double)dynamicnan); + + EXPECT_NE(constnan, dynamicnan); // holds only for NANs + EXPECT_NE(constnan, nan); // holds only for NANs + EXPECT_NE(dynamicnan, nan); // holds only for NANs +} + +// See Intel 64 and IA-32 Architectures Software Developer's Manual +// Vol. 1, Appendix E Sect. 4.2.2 Table E-1 for a discussion of a +// type of NaN returned for an invalid operation (e.g., 0/0). It +// seems that always a particular encoding ("QNaN indefinite") is +// used in such cases, but what happens generally (see TODOs below)? + +// A NAN CASE +TEST(FloatxNanInfTest, cast_nans) +{ + using T1 = flx::floatx<2, 3>; + using T2 = flx::floatx<10, 50>; + T1 a = 0.0 / 0.0; + T2 b = 0.0; + b = a; + + double constnan = + nan; // note, the way how that nan is generated is relevant! + + EXPECT_NE(a, a); // holds only for NANs + EXPECT_NE(a, nan); // holds only for NANs + // TODO: is the following expectation true generally? + EXPECT_EQ(*reinterpret_cast(&a), + *reinterpret_cast(&constnan)); + + EXPECT_NE(b, b); // holds only for NANs + EXPECT_NE(b, nan); // holds only for NANs + // TODO: is the following expectation true generally? + EXPECT_EQ(*reinterpret_cast(&b), + *reinterpret_cast(&constnan)); + + // Differnt bit represenations for nans + // TODO: is the following expectation true generally? + EXPECT_EQ(*reinterpret_cast(&b), + *reinterpret_cast(&a)); +} + +// A NAN CASE +TEST(FloatxNanInfTest, DIV_2_47_simple) +{ + using T = flx::floatx<2, 47>; + T a = -( + 7.105427e-15 / 2 - + 1e-17); // a bit smaller than half of the smallest subnormal in <2,47> + T b = -(7.105427e-15 / 12.0); + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.00000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_NE(c, c); // holds only for NANs + EXPECT_NE(c, nan); // holds only for NANs + + double zero; + // try to prevent the compiler to figure out what + // dynamicnan should be in the compile time + *(double*)memset(&zero, ~0, sizeof(zero)) = 0.0; + double dynamicnan = zero / zero; + + EXPECT_NE(c, dynamicnan); // holds only for NANs + // TODO: is the following expectation true generally? + EXPECT_EQ(*reinterpret_cast(&c), + *reinterpret_cast(&dynamicnan)); +} + +// A REGULAR CASE (fixing in subnormal does not cause the inf case here) +TEST(FloatxNanInfTest, DIV_3_3_simple) +{ + using T = flx::floatx<3, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 3.43750000000000000000e-01); + EXPECT_EQ(double(b), 1.25000000000000000000e-01); + EXPECT_EQ(double(c), 2.7500000000000000000e-00); +} + +// A INF CASE. +TEST(FloatxNanInfTest, DIV_3_3_simple_inf) +{ + using T = flx::floatx<3, 3>; + T a = 0.33333333333333331483; + T b = + (0.03125000000000000000 / 2 - + 1e-17); // a bit smaller than half of the smallest subnormal in <3,3> + T c = 0; + c = a / b; + + // printf("a: "); show((double)a); + // printf("b: "); show((double)b); + // printf("c: "); show((double)c); + // printf("inf: "); show((double)inf); + + EXPECT_EQ(double(a), 3.43750000000000000000e-01); + EXPECT_EQ(double(b), 00000000000000000000); + EXPECT_EQ(double(c), inf); +} + +} // namespace diff --git a/third-party/FloatX/test/arithmetic.cpp b/third-party/FloatX/test/arithmetic.cpp new file mode 100644 index 0000000..564b306 --- /dev/null +++ b/third-party/FloatX/test/arithmetic.cpp @@ -0,0 +1,164 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include +#include + + +namespace { + + +TEST(FloatxArithmeticTest, ResultHasCorrectType) +{ + using doublex = flx::floatx<11, 52>; + using floatx = flx::floatx<8, 23>; + + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + + doublex dlhs; + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + floatx flhs; + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); +} + + +TEST(FloatxArithmeticTest, PromotesTypes) +{ + using flx1 = flx::floatx<9, 7>; + using flx2 = flx::floatx<6, 13>; + using supertype = flx::floatx<9, 13>; + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + + flx1 flhs; + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + + using flx3 = flx::floatx<9, 23>; + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + + using doublex = flx::floatx<11, 52>; + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); + ::testing::StaticAssertTypeEq(); +} + + +TEST(FloatxrArithmeticTest, ResultHasCorrectType) +{ + auto fxr = []() { return flx::floatxr<>(8, 23); }; + ::testing::StaticAssertTypeEq, decltype(fxr() + fxr())>(); + ::testing::StaticAssertTypeEq, decltype(fxr() - fxr())>(); + ::testing::StaticAssertTypeEq, decltype(fxr() * fxr())>(); + ::testing::StaticAssertTypeEq, decltype(fxr() / fxr())>(); + + flx::floatxr<> dlhs(8, 23); + ::testing::StaticAssertTypeEq&, decltype(dlhs += fxr())>(); + ::testing::StaticAssertTypeEq&, decltype(dlhs -= fxr())>(); + ::testing::StaticAssertTypeEq&, decltype(dlhs *= fxr())>(); + ::testing::StaticAssertTypeEq&, decltype(dlhs /= fxr())>(); +} + + +TEST(FloatxrArithmeticTest, PromotesTypes) +{ + auto fxr = []() { return flx::floatxr<>(8, 23); }; + using floatx = flx::floatx<9, 12>; + ::testing::StaticAssertTypeEq, decltype(fxr() + floatx())>(); + ::testing::StaticAssertTypeEq, decltype(fxr() - floatx())>(); + ::testing::StaticAssertTypeEq, decltype(fxr() * floatx())>(); + ::testing::StaticAssertTypeEq, decltype(fxr() / floatx())>(); + + flx::floatxr<> dlhs(8, 23); + ::testing::StaticAssertTypeEq&, + decltype(dlhs += floatx())>(); + ::testing::StaticAssertTypeEq&, + decltype(dlhs -= floatx())>(); + ::testing::StaticAssertTypeEq&, + decltype(dlhs *= floatx())>(); + ::testing::StaticAssertTypeEq&, + decltype(dlhs /= floatx())>(); + + ::testing::StaticAssertTypeEq, decltype(fxr() + double())>(); + ::testing::StaticAssertTypeEq, decltype(fxr() - double())>(); + ::testing::StaticAssertTypeEq, decltype(fxr() * double())>(); + ::testing::StaticAssertTypeEq, decltype(fxr() / double())>(); + + ::testing::StaticAssertTypeEq&, + decltype(dlhs += double())>(); + ::testing::StaticAssertTypeEq&, + decltype(dlhs -= double())>(); + ::testing::StaticAssertTypeEq&, + decltype(dlhs *= double())>(); + ::testing::StaticAssertTypeEq&, + decltype(dlhs /= double())>(); + + ::testing::StaticAssertTypeEq, decltype(fxr() + int())>(); + ::testing::StaticAssertTypeEq, decltype(fxr() - int())>(); + ::testing::StaticAssertTypeEq, decltype(fxr() * int())>(); + ::testing::StaticAssertTypeEq, decltype(fxr() / int())>(); + + ::testing::StaticAssertTypeEq&, decltype(dlhs += int())>(); + ::testing::StaticAssertTypeEq&, decltype(dlhs -= int())>(); + ::testing::StaticAssertTypeEq&, decltype(dlhs *= int())>(); + ::testing::StaticAssertTypeEq&, decltype(dlhs /= int())>(); +} + + +} // namespace diff --git a/third-party/FloatX/test/assignment.cpp b/third-party/FloatX/test/assignment.cpp new file mode 100644 index 0000000..ea30f46 --- /dev/null +++ b/third-party/FloatX/test/assignment.cpp @@ -0,0 +1,81 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include +#include + + +namespace { + + +TEST(FloatxAssignmentTest, PreservesPrecision) +{ + const double val = 1.0 + 1e-15; + flx::floatx<11, 52> fx_val; + fx_val = val; + EXPECT_EQ(val, double(fx_val)); +} + +TEST(FloatxAssignmentTest, LowersPrecision) +{ + const double val = 1.0 + 1e-15; + flx::floatx<8, 23> fx_val; + fx_val = val; + EXPECT_NE(val, double(fx_val)); // round to float +} + + +TEST(FloatxAssignmentTest, AssignsBetweenFormats) +{ + const double val = 1.0 + 1e-15; + flx::floatx<11, 52> d_val(val); + flx::floatx<8, 23> s_val; + s_val = d_val; + EXPECT_NE(val, double(s_val)); + EXPECT_EQ(float(val), float(s_val)); +} + + +TEST(FloatxrAssignmentTest, PreservesPrecision) +{ + const double val = 1.0 + 1e-15; + flx::floatxr<> fx_val(11, 52); + fx_val = val; + EXPECT_EQ(val, double(fx_val)); +} + +TEST(FloatxrAssignmentTest, LowersPrecision) +{ + const double val = 1.0 + 1e-15; + flx::floatxr<> fx_val(8, 23); + fx_val = val; + EXPECT_NE(val, double(fx_val)); // round to float +} + + +TEST(FloatxrAssignmentTest, AssignsBetweenFormats) +{ + const double val = 1.0 + 1e-15; + flx::floatx<11, 52> d_val(val); + flx::floatxr<> s_val(8, 23); + s_val = d_val; + EXPECT_NE(val, double(s_val)); + EXPECT_EQ(float(val), float(s_val)); +} + + +} // namespace diff --git a/third-party/FloatX/test/conversion.cpp b/third-party/FloatX/test/conversion.cpp new file mode 100644 index 0000000..0267df9 --- /dev/null +++ b/third-party/FloatX/test/conversion.cpp @@ -0,0 +1,134 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include + + +#include +#include + + +namespace { + + +TEST(FloatxConversionTest, PreservesDoublePrecision) +{ + const double val = 1.0 + 1e-15; + EXPECT_EQ(val, double(flx::floatx<11, 52>(val))); +} + +TEST(FloatxConversionTest, LowersPrecision) +{ + const double val = 1.0 + 1e-15; + EXPECT_NE(val, double(flx::floatx<8, 23>(val))); // round to float +} + + +TEST(FloatxConversionTest, HandlesDenormals) +{ + EXPECT_EQ(0.25, double(flx::floatx<2, 3>(0.25))); + EXPECT_EQ(0.75, double(flx::floatx<2, 3>(0.75))); +} + + +TEST(FloatxConversionTest, ConvertsBetweenFloatX) +{ + const double val = 1.0 + 1e-15; + flx::floatx<11, 52> d_val(val); + flx::floatx<8, 23> s_val(d_val); + EXPECT_NE(val, double(s_val)); + EXPECT_EQ(float(val), float(s_val)); +} + +TEST(FloatxConversionTest, ConvertsToBits) +{ + const double val = 1.0 + 1e-15; + ::testing::StaticAssertTypeEq, + decltype(bits(flx::floatx<11, 52>(val)))>(); + ::testing::StaticAssertTypeEq, + decltype(bits(flx::floatx<8, 23>(val)))>(); + EXPECT_EQ(flx::bits(val), bits(flx::floatx<11, 52>(val))); + EXPECT_NE(flx::bits(val), bits(flx::floatx<8, 23>(val))); +} + +TEST(FloatxConversionTest, ConvertsToString) +{ + flx::floatx<4, 5> val1 = 1.0; + EXPECT_EQ("0-0111-00000", bitstring(val1)); + flx::floatx<3, 2> val2 = 1.75; + EXPECT_EQ("0-011-11", bitstring(val2)); + flx::floatx<5, 7> val3 = 0.0; + EXPECT_EQ("0-00000-0000000", bitstring(val3)); +} + +TEST(FloatxrConversionTest, PreservesDoublePrecision) +{ + const double val = 1.0 + 1e-15; + EXPECT_EQ(val, double(flx::floatxr<>(11, 52, val))); +} + +TEST(FloatxrConversionTest, LowersPrecision) +{ + const double val = 1.0 + 1e-15; + EXPECT_NE(val, double(flx::floatxr<>(8, 23, val))); // round to float +} + +TEST(FloatxrConversionTest, InheritsPrecision) +{ + const double val = 1.0 + 1e-15; + EXPECT_EQ(val, double(flx::floatxr<>(val))); +} + +TEST(FloatxrConversionTest, ChangesPrecision) +{ + const double val = 1.0 + 1e-15; + flx::floatxr<> fxr_val(val); + fxr_val.set_precision(8, 23); + EXPECT_NE(val, double(fxr_val)); + EXPECT_EQ(float(val), float(fxr_val)); +} + +TEST(FloatxrConversionTest, ConvertsBetweenFloatX) +{ + const double val = 1.0 + 1e-15; + flx::floatx<11, 52> d_val(val); + flx::floatxr<> s_val(8, 23, d_val); + EXPECT_NE(val, double(s_val)); + EXPECT_EQ(float(val), float(s_val)); +} + +TEST(FloatxrConversionTest, ConvertsToBits) +{ + const double val = 1.0 + 1e-15; + ::testing::StaticAssertTypeEq, + decltype(bits(flx::floatxr<>(val)))>(); + EXPECT_EQ(flx::bits(val), bits(flx::floatxr<>(val))); + EXPECT_NE(flx::bits(val), bits(flx::floatxr<>(8, 23, val))); +} + + +TEST(FloatxrConversionTest, ConvertsToString) +{ + flx::floatxr<> val1(4, 5, 1.0); + EXPECT_EQ("0-0111-00000", bitstring(val1)); + flx::floatxr<> val2(3, 2, 1.75); + EXPECT_EQ("0-011-11", bitstring(val2)); + flx::floatxr<> val3(5, 7, 0.0); + EXPECT_EQ("0-00000-0000000", bitstring(val3)); +} + +} // namespace diff --git a/third-party/FloatX/test/rel_ops.cpp b/third-party/FloatX/test/rel_ops.cpp new file mode 100644 index 0000000..fb78015 --- /dev/null +++ b/third-party/FloatX/test/rel_ops.cpp @@ -0,0 +1,229 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include +#include + + +namespace { + + +TEST(FloatxRelOpsTest, Equal) +{ + using doublex = flx::floatx<11, 52>; + using floatx = flx::floatx<8, 23>; + const double val1 = 1.0 + 1e-15; + const double val2 = 1.0 + 2e-15; + EXPECT_TRUE(doublex(val1) == doublex(val1)); + EXPECT_FALSE(doublex(val1) == doublex(val2)); + EXPECT_TRUE(floatx(val1) == floatx(val1)); + EXPECT_TRUE(floatx(val1) == floatx(val2)); // due to rounding + EXPECT_FALSE(floatx(val1) == doublex(val1)); // due to rounding + EXPECT_FALSE(floatx(val1) == doublex(val2)); // due to rounding +} + + +TEST(FloatxRelOpsTest, NotEqual) +{ + using doublex = flx::floatx<11, 52>; + using floatx = flx::floatx<8, 23>; + const double val1 = 1.0 + 1e-15; + const double val2 = 1.0 + 2e-15; + EXPECT_FALSE(doublex(val1) != doublex(val1)); + EXPECT_TRUE(doublex(val1) != doublex(val2)); + EXPECT_FALSE(floatx(val1) != floatx(val1)); + EXPECT_FALSE(floatx(val1) != floatx(val2)); // due to rounding + EXPECT_TRUE(floatx(val1) != doublex(val1)); // due to rounding + EXPECT_TRUE(floatx(val1) != doublex(val2)); // due to rounding +} + + +TEST(FloatxRelOpsTest, LessThan) +{ + using doublex = flx::floatx<11, 52>; + using floatx = flx::floatx<8, 23>; + const double val1 = 1.0 + 1e-15; + const double val2 = 1.0 + 2e-15; + EXPECT_FALSE(doublex(val1) < doublex(val1)); + EXPECT_FALSE(doublex(val2) < doublex(val1)); + EXPECT_TRUE(doublex(val1) < doublex(val2)); + EXPECT_FALSE(floatx(val1) < floatx(val1)); + EXPECT_FALSE(floatx(val2) < floatx(val1)); + EXPECT_FALSE(floatx(val1) < floatx(val2)); // due to rounding + EXPECT_TRUE(floatx(val1) < doublex(val1)); // due to rounding + EXPECT_TRUE(floatx(val2) < doublex(val1)); // due to rounding + EXPECT_TRUE(floatx(val1) < doublex(val2)); // due to rounding +} + + +TEST(FloatxRelOpsTest, LessOrEqual) +{ + using doublex = flx::floatx<11, 52>; + using floatx = flx::floatx<8, 23>; + const double val1 = 1.0 + 1e-15; + const double val2 = 1.0 + 2e-15; + EXPECT_TRUE(doublex(val1) <= doublex(val1)); + EXPECT_FALSE(doublex(val2) <= doublex(val1)); + EXPECT_TRUE(doublex(val1) <= doublex(val2)); + EXPECT_TRUE(floatx(val1) <= floatx(val1)); + EXPECT_TRUE(floatx(val2) <= floatx(val1)); // due to rounding + EXPECT_TRUE(floatx(val1) <= floatx(val2)); + EXPECT_TRUE(floatx(val1) <= doublex(val1)); + EXPECT_TRUE(floatx(val2) <= doublex(val1)); // due to rounding + EXPECT_TRUE(floatx(val1) <= doublex(val2)); +} + + +TEST(FloatxRelOpsTest, GreaterThan) +{ + using doublex = flx::floatx<11, 52>; + using floatx = flx::floatx<8, 23>; + const double val1 = 1.0 + 1e-15; + const double val2 = 1.0 + 2e-15; + EXPECT_FALSE(doublex(val1) > doublex(val1)); + EXPECT_TRUE(doublex(val2) > doublex(val1)); + EXPECT_FALSE(doublex(val1) > doublex(val2)); + EXPECT_FALSE(floatx(val1) > floatx(val1)); + EXPECT_FALSE(floatx(val2) > floatx(val1)); // due to rounding + EXPECT_FALSE(floatx(val1) > floatx(val2)); + EXPECT_FALSE(floatx(val1) > doublex(val1)); + EXPECT_FALSE(floatx(val2) > doublex(val1)); // due to rounding + EXPECT_FALSE(floatx(val1) > doublex(val2)); +} + + +TEST(FloatxRelOpsTest, GreaterOrEqual) +{ + using doublex = flx::floatx<11, 52>; + using floatx = flx::floatx<8, 23>; + const double val1 = 1.0 + 1e-15; + const double val2 = 1.0 + 2e-15; + EXPECT_TRUE(doublex(val1) >= doublex(val1)); + EXPECT_TRUE(doublex(val2) >= doublex(val1)); + EXPECT_FALSE(doublex(val1) >= doublex(val2)); + EXPECT_TRUE(floatx(val1) >= floatx(val1)); + EXPECT_TRUE(floatx(val2) >= floatx(val1)); // due to rounding + EXPECT_TRUE(floatx(val1) >= floatx(val2)); // due to rounding + EXPECT_FALSE(floatx(val1) >= doublex(val1)); // due to rounding + EXPECT_FALSE(floatx(val2) >= doublex(val1)); // due to rounding + EXPECT_FALSE(floatx(val1) >= doublex(val2)); +} + + +TEST(FloatxrRelOpsTest, Equal) +{ + auto doublex = [](double a) { return flx::floatxr<>(11, 52, a); }; + auto floatx = [](double a) { return flx::floatxr<>(8, 23, a); }; + const double val1 = 1.0 + 1e-15; + const double val2 = 1.0 + 2e-15; + EXPECT_TRUE(doublex(val1) == doublex(val1)); + EXPECT_FALSE(doublex(val1) == doublex(val2)); + EXPECT_TRUE(floatx(val1) == floatx(val1)); + EXPECT_TRUE(floatx(val1) == floatx(val2)); // due to rounding + EXPECT_FALSE(floatx(val1) == doublex(val1)); // due to rounding + EXPECT_FALSE(floatx(val1) == doublex(val2)); // due to rounding +} + + +TEST(FloatxrRelOpsTest, NotEqual) +{ + auto doublex = [](double a) { return flx::floatxr<>(11, 52, a); }; + auto floatx = [](double a) { return flx::floatxr<>(8, 23, a); }; + const double val1 = 1.0 + 1e-15; + const double val2 = 1.0 + 2e-15; + EXPECT_FALSE(doublex(val1) != doublex(val1)); + EXPECT_TRUE(doublex(val1) != doublex(val2)); + EXPECT_FALSE(floatx(val1) != floatx(val1)); + EXPECT_FALSE(floatx(val1) != floatx(val2)); // due to rounding + EXPECT_TRUE(floatx(val1) != doublex(val1)); // due to rounding + EXPECT_TRUE(floatx(val1) != doublex(val2)); // due to rounding +} + + +TEST(FloatxrRelOpsTest, LessThan) +{ + auto doublex = [](double a) { return flx::floatxr<>(11, 52, a); }; + auto floatx = [](double a) { return flx::floatxr<>(8, 23, a); }; + const double val1 = 1.0 + 1e-15; + const double val2 = 1.0 + 2e-15; + EXPECT_FALSE(doublex(val1) < doublex(val1)); + EXPECT_FALSE(doublex(val2) < doublex(val1)); + EXPECT_TRUE(doublex(val1) < doublex(val2)); + EXPECT_FALSE(floatx(val1) < floatx(val1)); + EXPECT_FALSE(floatx(val2) < floatx(val1)); + EXPECT_FALSE(floatx(val1) < floatx(val2)); // due to rounding + EXPECT_TRUE(floatx(val1) < doublex(val1)); // due to rounding + EXPECT_TRUE(floatx(val2) < doublex(val1)); // due to rounding + EXPECT_TRUE(floatx(val1) < doublex(val2)); // due to rounding +} + + +TEST(FloatxrRelOpsTest, LessOrEqual) +{ + auto doublex = [](double a) { return flx::floatxr<>(11, 52, a); }; + auto floatx = [](double a) { return flx::floatxr<>(8, 23, a); }; + const double val1 = 1.0 + 1e-15; + const double val2 = 1.0 + 2e-15; + EXPECT_TRUE(doublex(val1) <= doublex(val1)); + EXPECT_FALSE(doublex(val2) <= doublex(val1)); + EXPECT_TRUE(doublex(val1) <= doublex(val2)); + EXPECT_TRUE(floatx(val1) <= floatx(val1)); + EXPECT_TRUE(floatx(val2) <= floatx(val1)); // due to rounding + EXPECT_TRUE(floatx(val1) <= floatx(val2)); + EXPECT_TRUE(floatx(val1) <= doublex(val1)); + EXPECT_TRUE(floatx(val2) <= doublex(val1)); // due to rounding + EXPECT_TRUE(floatx(val1) <= doublex(val2)); +} + + +TEST(FloatxrRelOpsTest, GreaterThan) +{ + auto doublex = [](double a) { return flx::floatxr<>(11, 52, a); }; + auto floatx = [](double a) { return flx::floatxr<>(8, 23, a); }; + const double val1 = 1.0 + 1e-15; + const double val2 = 1.0 + 2e-15; + EXPECT_FALSE(doublex(val1) > doublex(val1)); + EXPECT_TRUE(doublex(val2) > doublex(val1)); + EXPECT_FALSE(doublex(val1) > doublex(val2)); + EXPECT_FALSE(floatx(val1) > floatx(val1)); + EXPECT_FALSE(floatx(val2) > floatx(val1)); // due to rounding + EXPECT_FALSE(floatx(val1) > floatx(val2)); + EXPECT_FALSE(floatx(val1) > doublex(val1)); + EXPECT_FALSE(floatx(val2) > doublex(val1)); // due to rounding + EXPECT_FALSE(floatx(val1) > doublex(val2)); +} + + +TEST(FloatxrRelOpsTest, GreaterOrEqual) +{ + auto doublex = [](double a) { return flx::floatxr<>(11, 52, a); }; + auto floatx = [](double a) { return flx::floatxr<>(8, 23, a); }; + const double val1 = 1.0 + 1e-15; + const double val2 = 1.0 + 2e-15; + EXPECT_TRUE(doublex(val1) >= doublex(val1)); + EXPECT_TRUE(doublex(val2) >= doublex(val1)); + EXPECT_FALSE(doublex(val1) >= doublex(val2)); + EXPECT_TRUE(floatx(val1) >= floatx(val1)); + EXPECT_TRUE(floatx(val2) >= floatx(val1)); // due to rounding + EXPECT_TRUE(floatx(val1) >= floatx(val2)); // due to rounding + EXPECT_FALSE(floatx(val1) >= doublex(val1)); // due to rounding + EXPECT_FALSE(floatx(val2) >= doublex(val1)); // due to rounding + EXPECT_FALSE(floatx(val1) >= doublex(val2)); +} + + +} // namespace diff --git a/third-party/FloatX/test/round_nearest.cpp b/third-party/FloatX/test/round_nearest.cpp new file mode 100644 index 0000000..5e605fa --- /dev/null +++ b/third-party/FloatX/test/round_nearest.cpp @@ -0,0 +1,90 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include +#include + +// Check internal functions. +// Rounding of a uint64_t type value. +// Checks the following routine: +// inline uint64_t SHIFT_RIGHT_ROUND_NEAREST(uint64_t mant, uint16_t SHIFT) +// IMPLEMENTS rounding according the IEEE 754 standard with a NEAREST policy and +// ties are resolved to even. + +TEST(RoundNearest, down) +{ + // RRRRRRRRRR + // number: 0x3e6999999999999a + // 0011111001101001100110011001100110011001100110011001100110011010 + // >> 10 : 0x000f9a6666666666 + // 0000000000001111100110100110011001100110011001100110011001100110 RND 10: + // 0x000f9a6666666666 + // 0000000000001111100110100110011001100110011001100110011001100110 + uint64_t number = 0x3e6999999999999a; + int shift_amount = 10; + uint64_t expected = 0x000f9a6666666666 << shift_amount; + + EXPECT_EQ(expected, flx::detail::round_nearest(number, shift_amount)); +} + +TEST(RoundNearest, up) +{ + // RRRRRRRRRRRR + // number: 0x3e6999999999999a + // 0011111001101001100110011001100110011001100110011001100110011010 + // >> 12 : 0x0003e69999999999 + // 0000000000000011111001101001100110011001100110011001100110011001 RND 12: + // 0x0003e6999999999a + // 0000000000000011111001101001100110011001100110011001100110011010 + uint64_t number = 0x3e6999999999999a; + int shift_amount = 12; + uint64_t expected = 0x0003e6999999999a << shift_amount; + + EXPECT_EQ(expected, flx::detail::round_nearest(number, shift_amount)); +} + +TEST(RoundNearest, RoundNearestWithTiesToEvenRoundsUp) +{ + // RRRR + // number: 0x0ffffffff00000f8 + // 0000111111111111111111111111111111110000000000000000000011111000 + // >> 4 : 0x00ffffffff00000f + // 0000000011111111111111111111111111111111000000000000000000001111 RND 4: + // 0x00ffffffff000010 + // 0000000011111111111111111111111111111111000000000000000000010000 + uint64_t number = 0x0ffffffff00000f8; + int shift_amount = 4; + uint64_t expected = 0x00ffffffff000010 << shift_amount; + + EXPECT_EQ(expected, flx::detail::round_nearest(number, shift_amount)); +} + +TEST(RoundNearest, RoundNearestWithTiesToEvenRoundsDown) +{ + // RRRR + // number: 0x0ffffffff00000e8 + // 0000111111111111111111111111111111110000000000000000000011101000 + // >> 4 : 0x00ffffffff00000e + // 0000000011111111111111111111111111111111000000000000000000001110 RND 4: + // 0x00ffffffff00000e + // 0000000011111111111111111111111111111111000000000000000000001110 + uint64_t number = 0x0ffffffff00000e8; + int shift_amount = 4; + uint64_t expected = 0x00ffffffff00000e << shift_amount; + + EXPECT_EQ(expected, flx::detail::round_nearest(number, shift_amount)); +} diff --git a/third-party/FloatX/test/std_integration.cpp b/third-party/FloatX/test/std_integration.cpp new file mode 100644 index 0000000..229a256 --- /dev/null +++ b/third-party/FloatX/test/std_integration.cpp @@ -0,0 +1,148 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include +#include + + +#include +#include +#include +#include + + +namespace { + + +using doublex = flx::floatx<11, 52>; +using floatx = flx::floatx<8, 23>; + + +TEST(Tuple, CanCreateFloatXTuple) +{ + auto tpl = std::make_tuple(doublex{3.2}, floatx{5.2}); + + ASSERT_NEAR(std::get<0>(tpl), 3.2, 1e-15); + ASSERT_NEAR(std::get<1>(tpl), 5.2, 1e-6); +} + + +TEST(TupleVector, CanCreateVectorOfTuples) +{ + std::vector> vec{ + std::make_tuple(doublex{3.2}, floatx{5.2}), + std::make_tuple(doublex{0.5}, floatx{1.2})}; + + ASSERT_NEAR(std::get<0>(vec[0]), 3.2, 1e-15); + ASSERT_NEAR(std::get<1>(vec[0]), 5.2, 1e-6); + ASSERT_NEAR(std::get<0>(vec[1]), 0.5, 1e-15); + ASSERT_NEAR(std::get<1>(vec[1]), 1.2, 1e-6); +} + + +TEST(TupleVector, CanIterateThroughVector) +{ + std::vector> vec{ + std::make_tuple(doublex{3.2}, floatx{5.2}), + std::make_tuple(doublex{0.5}, floatx{1.2})}; + + for (auto& elem : vec) { + std::get<0>(elem) += 1; + } + + ASSERT_NEAR(std::get<0>(vec[0]), 4.2, 1e-15); + ASSERT_NEAR(std::get<1>(vec[0]), 5.2, 1e-6); + ASSERT_NEAR(std::get<0>(vec[1]), 1.5, 1e-15); + ASSERT_NEAR(std::get<1>(vec[1]), 1.2, 1e-6); +} + + +TEST(TupleVector, CanSortTupleVector) +{ + std::vector> vec{ + std::make_tuple(doublex{3.2}, floatx{5.2}), + std::make_tuple(doublex{0.5}, floatx{1.2})}; + + std::sort(begin(vec), end(vec)); + + ASSERT_NEAR(std::get<0>(vec[0]), 0.5, 1e-15); + ASSERT_NEAR(std::get<1>(vec[0]), 1.2, 1e-6); + ASSERT_NEAR(std::get<0>(vec[1]), 3.2, 1e-15); + ASSERT_NEAR(std::get<1>(vec[1]), 5.2, 1e-6); +} + + +// NOTE: this is non-standard behavior, a conformant implementation is allowed +// to have undefined behavior for std::complex> +TEST(Complex, CanCreateComplexFloatX) +{ + std::complex a(3.2, 2.5); + + ASSERT_NEAR(a.real(), 3.2, 1e-7); + ASSERT_NEAR(a.imag(), 2.5, 1e-7); +} + + +TEST(Complex, CanAddComplexFloatX) +{ + std::complex a(3.2, 2.5); + std::complex b(2.3, 1.4); + + auto res = a + b; + + ASSERT_NEAR(res.real(), 5.5, 1e-7); + ASSERT_NEAR(res.imag(), 3.9, 1e-7); +} + + +TEST(Complex, CanSubstractComplexFloatX) +{ + std::complex a(3.2, 2.5); + std::complex b(2.3, 1.4); + + auto res = a - b; + + ASSERT_NEAR(res.real(), 0.9, 1e-7); + ASSERT_NEAR(res.imag(), 1.1, 1e-7); +} + + +TEST(Complex, CanMultiplyComplexFloatX) +{ + std::complex a(3.0, 2.0); + std::complex b(2.0, 1.0); + + auto res = a * b; + + ASSERT_NEAR(res.real(), 4.0, 1e-7); + ASSERT_NEAR(res.imag(), 7.0, 1e-7); +} + + +TEST(Complex, CanDivideComplexFloatX) +{ + std::complex a(3.0, 2.0); + std::complex b(2.0, 1.0); + + auto res = a / b; + + ASSERT_NEAR(res.real(), 1.6, 1e-7); + ASSERT_NEAR(res.imag(), 0.2, 1e-7); +} + + +} // namespace diff --git a/third-party/FloatX/test/stream.cpp b/third-party/FloatX/test/stream.cpp new file mode 100644 index 0000000..5ffcf71 --- /dev/null +++ b/third-party/FloatX/test/stream.cpp @@ -0,0 +1,65 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include + + +#include +#include + + +namespace { + + +TEST(FloatxStreamTest, WritesToOutputStream) +{ + flx::floatx<8, 23> val = 1.0 + 1e-15; + std::stringstream os; + os << val; + EXPECT_EQ("1", os.str()); +} + + +TEST(FloatxStreamTest, ReadsFromOutputStream) +{ + flx::floatx<8, 23> val; + std::stringstream is("1.00000000000001"); + is >> val; + EXPECT_EQ(1.0, val); +} + + +TEST(FloatxrStreamTest, WritesToOutputStream) +{ + flx::floatxr<> val = 1.0 + 1e-15; + val.set_precision(8, 23); + std::stringstream os; + os << val; + EXPECT_EQ("1", os.str()); +} + + +TEST(FloatxrStreamTest, ReadsFromOutputStream) +{ + flx::floatxr<> val(8, 23); + std::stringstream is("1.00000000000001"); + is >> val; + EXPECT_EQ(1.0, val); +} + + +} // namespace diff --git a/third-party/FloatX/test/value_representation.cpp b/third-party/FloatX/test/value_representation.cpp new file mode 100644 index 0000000..ac377f0 --- /dev/null +++ b/third-party/FloatX/test/value_representation.cpp @@ -0,0 +1,140 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include +#include + +#include "IEEEHelper.h" + +// TEST(IEEE_helper, demonstrate ) { +// uint16_t e = 3; +// uint16_t m = 5; +// IEEEHelper h = IEEEHelper(e,m); +// h.showConfig(); +// EXPECT_EQ(1, 1); +// } + +class CheckValidRepresentationOfFloatx5_10 + : public ::testing::TestWithParam> {}; + +class CheckValidRepresentationOfFloatx4_8 + : public ::testing::TestWithParam> {}; + +template +void test(double d) +{ + // Test value d. + T fx = d; + double recoverd = (double)(fx); + + // the recoverd and the original value are required to be the same. + ASSERT_EQ(recoverd, d); +} + +TEST_P(CheckValidRepresentationOfFloatx5_10, subnormal) +{ + uint16_t const e = std::get<0>(GetParam()); + uint16_t const m = std::get<1>(GetParam()); + + IEEEHelper h = IEEEHelper(e, m); + // h.showConfig(); + // printf("Subnormal Range:\n"); + + int nm = h.countSubnormalRange(); + for (int im = 0; im < nm; ++im) { + double d = h.iterateSubnormalRange(im); + test>(d); + } +} + +TEST_P(CheckValidRepresentationOfFloatx5_10, regular) +{ + uint16_t const e = std::get<0>(GetParam()); + uint16_t const m = std::get<1>(GetParam()); + + IEEEHelper h = IEEEHelper(e, m); + // h.showConfig(); + // printf("Normal Range:\n"); + + int ne = h.countExpRange(); + int nm = h.countSubnormalRange(); + + for (int ie = 0; ie < ne; ++ie) { + for (int im = 0; im < nm; ++im) { + double d = h.iterateNormalRange(ie, im); + test>(d); + } + } +} + +TEST_P(CheckValidRepresentationOfFloatx4_8, subnormal) +{ + uint16_t const e = std::get<0>(GetParam()); + uint16_t const m = std::get<1>(GetParam()); + + IEEEHelper h = IEEEHelper(e, m); + // h.showConfig(); + // printf("Subnormal Range:\n"); + + int nm = h.countSubnormalRange(); + for (int im = 0; im < nm; ++im) { + double d = h.iterateSubnormalRange(im); + test>(d); + } +} + +TEST_P(CheckValidRepresentationOfFloatx4_8, regular) +{ + uint16_t const e = std::get<0>(GetParam()); + uint16_t const m = std::get<1>(GetParam()); + + IEEEHelper h = IEEEHelper(e, m); + // h.showConfig(); + // printf("Normal Range:\n"); + + int ne = h.countExpRange(); + int nm = h.countSubnormalRange(); + + for (int ie = 0; ie < ne; ++ie) { + for (int im = 0; im < nm; ++im) { + double d = h.iterateNormalRange(ie, im); + test>(d); + } + } +} + +// SUBSET TEST ON FLOATX TYPE HALF <5,10> +INSTANTIATE_TEST_CASE_P(TestParams_full_subnormal_range, + CheckValidRepresentationOfFloatx5_10, + testing::Values(::testing::make_tuple(5, 10))); + +INSTANTIATE_TEST_CASE_P( + TestParams_subset_subnormal_range, CheckValidRepresentationOfFloatx5_10, + testing::Values(::testing::make_tuple(2, 3), ::testing::make_tuple(3, 4), + ::testing::make_tuple(4, 2), ::testing::make_tuple(4, 8), + ::testing::make_tuple(5, 8), ::testing::make_tuple(2, 10))); + +// SUBSET TEST ON FLOATX TYPE HALF <4,8> +INSTANTIATE_TEST_CASE_P(TestParams_full_subnormal_range, + CheckValidRepresentationOfFloatx4_8, + testing::Values(::testing::make_tuple(4, 8))); + +INSTANTIATE_TEST_CASE_P(TestParams_subset_subnormal_range, + CheckValidRepresentationOfFloatx4_8, + testing::Values(::testing::make_tuple(2, 3), + ::testing::make_tuple(3, 8), + ::testing::make_tuple(4, 3))); diff --git a/third-party/FloatX/test/value_representation_bits.cpp b/third-party/FloatX/test/value_representation_bits.cpp new file mode 100644 index 0000000..a62267a --- /dev/null +++ b/third-party/FloatX/test/value_representation_bits.cpp @@ -0,0 +1,115 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include +#include + +TEST(MyTestBF, BF_3_5) +{ + const uint8_t E = 3; + const uint8_t M = 3; + + uint64_t mx = ((uint64_t)0x1) << (1 + E + M); + for (uint64_t cnt = 0x0; cnt < mx; ++cnt) { + // define input pattern + std::bitset<1 + E + M> pattern(cnt); + + // get a backend number + double bd = flx::detail::construct_number(pattern); + + // check that the backend number is valid. + // e.g. cast to fx and back to double (that should not change its value) + flx::floatx fx = bd; + double r = double(fx); + EXPECT_EQ(*reinterpret_cast(&r), + *reinterpret_cast(&bd)); + + // get the reverse functionallity + std::bitset<1 + E + M> out = + flx::detail::get_fullbit_representation_BS(r); + + // printf("value: %.20e\n", r ); + // std::cout << "IN: " << pattern << std::endl; + // std::cout << "OUT: " << out << std::endl; + + EXPECT_EQ(pattern, out); + } +} + +TEST(MyTestBF, BF_5_2) +{ + const uint8_t E = 5; + const uint8_t M = 2; + + uint64_t mx = ((uint64_t)0x1) << (1 + E + M); + for (uint64_t cnt = 0x0; cnt < mx; ++cnt) { + // define input pattern + std::bitset<1 + E + M> pattern(cnt); + + // get a backend number + double bd = flx::detail::construct_number(pattern); + + // check that the backend number is valid. + // e.g. cast to fx and back to double (that should not change its value) + flx::floatx fx = bd; + double r = double(fx); + EXPECT_EQ(*reinterpret_cast(&r), + *reinterpret_cast(&bd)); + + // get the reverse functionallity + std::bitset<1 + E + M> out = + flx::detail::get_fullbit_representation_BS(r); + + // printf("value: %.20e\n", r ); + // std::cout << "IN: " << pattern << std::endl; + // std::cout << "OUT: " << out << std::endl; + + EXPECT_EQ(pattern, out); + } +} + +TEST(MyTestBF, BF_5_10) +{ + const uint8_t E = 5; + const uint8_t M = 10; + + uint64_t mx = ((uint64_t)0x1) << (1 + E + M); + for (uint64_t cnt = 0x0; cnt < mx; ++cnt) { + // define input pattern + std::bitset<1 + E + M> pattern(cnt); + + // get a backend number + double bd = flx::detail::construct_number(pattern); + + // check that the backend number is valid. + // e.g. cast to fx and back to double (that should not change its value) + flx::floatx fx = bd; + double r = double(fx); + EXPECT_EQ(*reinterpret_cast(&r), + *reinterpret_cast(&bd)); + + // get the reverse functionallity + std::bitset<1 + E + M> out = + flx::detail::get_fullbit_representation_BS(r); + + // printf("value: %.20e\n", r ); + // std::cout << "IN: " << pattern << std::endl; + // std::cout << "OUT: " << out << std::endl; + + EXPECT_EQ(pattern, out); + } +} \ No newline at end of file diff --git a/third-party/FloatX/test/value_representation_half.cpp b/third-party/FloatX/test/value_representation_half.cpp new file mode 100644 index 0000000..f6677ea --- /dev/null +++ b/third-party/FloatX/test/value_representation_half.cpp @@ -0,0 +1,473 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include +#include + +void show(double d) +{ + printf("%.20e\t", d); + uint64_t u = flx::detail::reinterpret_as_bits(d); + printf("0x%016llx\t", u); + std::cout << std::bitset<64>(u) << std::endl; +} + +class MyTest : public ::testing::TestWithParam> { +}; + +TEST_P(MyTest, TestFormula) +{ + uint64_t const in_number = std::get<0>(GetParam()); + uint64_t const out_number = std::get<1>(GetParam()); + + double d = flx::detail::reinterpret_bits_as(in_number); + double expected = flx::detail::reinterpret_bits_as(out_number); + + // IEEE half. + flx::floatx<5, 10> fx = d; + double recoverd_fx = (double)(fx); + + // printf("number: \t"); show(d); + // printf("recoverd_fx:\t"); show(recoverd_fx); + // printf("expected: \t"); show(expected); + + // Enforces the same reprsentation for nan's. + uint64_t out = flx::detail::reinterpret_as_bits(recoverd_fx); + ASSERT_EQ(out, out_number); + // ASSERT_EQ(recoverd_fx, expected); // does not work for NAN's. +} + +INSTANTIATE_TEST_CASE_P( + TestWithParameters_manual_sampels, MyTest, + testing::Values( + + // Case triggering >> 64 (does generates wrong masks) + // number: 6.09397888183593736447e-05 0x3f0ff33333333333 + // 0011111100001111111100110011001100110011001100110011001100110011 + // recoverd_sf: 6.09159469604492187500e-05 0x3f0ff00000000000 + // 0011111100001111111100000000000000000000000000000000000000000000 + ::testing::make_tuple(0x3f0ff33333333333, 0x3f0ff00000000000), + + // Case, triggering rounding twice after each other not the same ase + // rounding once (sticky bit) + // number: 6.09517097473144544803e-05 0x3f0ff4cccccccccd + // 0011111100001111111101001100110011001100110011001100110011001101 + // recoverd_sf: 6.09755516052246093750e-05 0x3f0ff80000000000 + // 0011111100001111111110000000000000000000000000000000000000000000 + ::testing::make_tuple(0x3f0ff4cccccccccd, 0x3f0ff80000000000), + + // Case that triggers a MANTISSA overflow due rounding, requires the + // exponent to be changed. + // number: 3.05056571960449225526e-05 0x3efffccccccccccd + // 0011111011111111111111001100110011001100110011001100110011001101 + // recoverd_sf: 3.05175781250000000000e-05 0x3f00000000000000 + // 0011111100000000000000000000000000000000000000000000000000000000 + ::testing::make_tuple(0x3efffccccccccccd, 0x3f00000000000000), + + // Super ugly (and rare) case! A very small sub-normal number requires + // the mantissa bits almost to be moved out of the storage range. + // Henceforth, the correct rounding should go either up / or down. In + // that case, the rounding depends on the hidden 1, not explicitly + // stored in the mantissa. (BUGFIX) add the hidden one, perform correct + // rounding and go furhter in the routine. That requires to change the + // exponent due rounding at a later point. + // number: 4.76837158203125026470e-08 0x3e6999999999999a + // 0011111001101001100110011001100110011001100110011001100110011010 + // recoverd_sf: 5.96046447753906250000e-08 0x3e70000000000000 + // 0011111001110000000000000000000000000000000000000000000000000000 + ::testing::make_tuple(0x3e6999999999999a, 0x3e70000000000000), + + // A number smaller than the smallest subnormal, requires a full flush + // to 0. + // number: 2.38418579101562513235e-08 0x3e5999999999999a + // 0011111001011001100110011001100110011001100110011001100110011010 + // recoverd_sf: 0.00000000000000000000e+00 0x0000000000000000 + // 0000000000000000000000000000000000000000000000000000000000000000 + ::testing::make_tuple(0x3e5999999999999a, 0x0000000000000000))); + + +INSTANTIATE_TEST_CASE_P( + // Cases showing failuers during a float - Half - float brute force test! + TestWithParameters_manual_sampels_002, MyTest, + testing::Values( + // number: 1.58346726468704329014e-43 0x370c400000000000 + // 0011011100001100010000000000000000000000000000000000000000000000 + // recoverd_sf: 0.00000000000000000000e+00 0x0000000000000000 + // 0000000000000000000000000000000000000000000000000000000000000000 + ::testing::make_tuple(0x370c400000000000, 0x0000000000000000), + // number: 4.88279038108885288239e-04 0x3f3ffff680000000 + // 0011111100111111111111111111011010000000000000000000000000000000 + // recoverd_sf: 4.88281250000000000000e-04 0x3f40000000000000 + // 0011111101000000000000000000000000000000000000000000000000000000 + ::testing::make_tuple(0x3f3ffff680000000, 0x3f40000000000000), + // number: 6.60882968750000000000e+04 0x40f02284c0000000 + // 0100000011110000001000101000010011000000000000000000000000000000 + // recoverd_sf: inf 0x7ff0000000000000 + // 0111111111110000000000000000000000000000000000000000000000000000 + ::testing::make_tuple(0x40f02284c0000000, 0x7ff0000000000000), + // number: nan 0x7ff80e1780000000 + // 0111111111111000000011100001011110000000000000000000000000000000 + // recoverd_sf: nan 0x7ff80c0000000000 + // 0111111111111000000011000000000000000000000000000000000000000000 + ::testing::make_tuple(0x7ff80e1780000000, 0x7ff80c0000000000), + // number: nan 0x7ff80eeeeeeeeeee + // 0111111111111000000011101110111011101110111011101110111011101110 + // recoverd_sf: nan 0x7ff80c0000000000 + // 0111111111111000000011000000000000000000000000000000000000000000 + ::testing::make_tuple(0x7ff80eeeeeeeeeee, 0x7ff80c0000000000), + // number: -2.98454239100465201773e-08 0xbe6005ec80000000 + // 1011111001100000000001011110110010000000000000000000000000000000 + // recoverd_sf: -5.96046447753906250000e-08 0xbe70000000000000 + // 1011111001110000000000000000000000000000000000000000000000000000 + ::testing::make_tuple(0xbe6005ec80000000, 0xbe70000000000000))); + + +INSTANTIATE_TEST_CASE_P( + TestWithParametersC1, MyTest, + testing::Values( + // number: 1.00000000000000000000e+00 0x3ff0000000000000 + // 0011111111110000000000000000000000000000000000000000000000000000 + // recoverd_sf: 1.00000000000000000000e+00 0x3ff0000000000000 + // 0011111111110000000000000000000000000000000000000000000000000000 + ::testing::make_tuple(0x3ff0000000000000, 0x3ff0000000000000), + // number: 5.00000000000000000000e-01 0x3fe0000000000000 + // 0011111111100000000000000000000000000000000000000000000000000000 + // recoverd_sf: 5.00000000000000000000e-01 0x3fe0000000000000 + // 0011111111100000000000000000000000000000000000000000000000000000 + ::testing::make_tuple(0x3fe0000000000000, 0x3fe0000000000000), + // number: 3.33333333333333314830e-01 0x3fd5555555555555 + // 0011111111010101010101010101010101010101010101010101010101010101 + // recoverd_sf: 3.33251953125000000000e-01 0x3fd5540000000000 + // 0011111111010101010101000000000000000000000000000000000000000000 + ::testing::make_tuple(0x3fd5555555555555, 0x3fd5540000000000), + // number: 2.50000000000000000000e-01 0x3fd0000000000000 + // 0011111111010000000000000000000000000000000000000000000000000000 + // recoverd_sf: 2.50000000000000000000e-01 0x3fd0000000000000 + // 0011111111010000000000000000000000000000000000000000000000000000 + ::testing::make_tuple(0x3fd0000000000000, 0x3fd0000000000000), + // number: 2.00000000000000011102e-01 0x3fc999999999999a + // 0011111111001001100110011001100110011001100110011001100110011010 + // recoverd_sf: 1.99951171875000000000e-01 0x3fc9980000000000 + // 0011111111001001100110000000000000000000000000000000000000000000 + ::testing::make_tuple(0x3fc999999999999a, 0x3fc9980000000000), + // number: 1.66666666666666657415e-01 0x3fc5555555555555 + // 0011111111000101010101010101010101010101010101010101010101010101 + // recoverd_sf: 1.66625976562500000000e-01 0x3fc5540000000000 + // 0011111111000101010101000000000000000000000000000000000000000000 + ::testing::make_tuple(0x3fc5555555555555, 0x3fc5540000000000), + // number: 1.42857142857142849213e-01 0x3fc2492492492492 + // 0011111111000010010010010010010010010010010010010010010010010010 + // recoverd_sf: 1.42822265625000000000e-01 0x3fc2480000000000 + // 0011111111000010010010000000000000000000000000000000000000000000 + ::testing::make_tuple(0x3fc2492492492492, 0x3fc2480000000000), + // number: 1.25000000000000000000e-01 0x3fc0000000000000 + // 0011111111000000000000000000000000000000000000000000000000000000 + // recoverd_sf: 1.25000000000000000000e-01 0x3fc0000000000000 + // 0011111111000000000000000000000000000000000000000000000000000000 + ::testing::make_tuple(0x3fc0000000000000, 0x3fc0000000000000), + // number: 1.11111111111111104943e-01 0x3fbc71c71c71c71c + // 0011111110111100011100011100011100011100011100011100011100011100 + // recoverd_sf: 1.11083984375000000000e-01 0x3fbc700000000000 + // 0011111110111100011100000000000000000000000000000000000000000000 + ::testing::make_tuple(0x3fbc71c71c71c71c, 0x3fbc700000000000))); + +// Brute force snippsets from extracted from softlow +INSTANTIATE_TEST_CASE_P( + TestWithParameters_BF_001, MyTest, + testing::Values( + // start: 0 + // stop: 50 + // inc: 1 + ::testing::make_tuple(0x0000000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36a0000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36b0000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36b8000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36c0000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36c4000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36c8000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36cc000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36d0000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36d2000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36d4000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36d6000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36d8000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36da000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36dc000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36de000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36e0000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36e1000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36e2000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36e3000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36e4000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36e5000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36e6000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36e7000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36e8000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36e9000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36ea000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36eb000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36ec000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36ed000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36ee000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36ef000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36f0000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36f0800000000000, 0x0000000000000000), + ::testing::make_tuple(0x36f1000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36f1800000000000, 0x0000000000000000), + ::testing::make_tuple(0x36f2000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36f2800000000000, 0x0000000000000000), + ::testing::make_tuple(0x36f3000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36f3800000000000, 0x0000000000000000), + ::testing::make_tuple(0x36f4000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36f4800000000000, 0x0000000000000000), + ::testing::make_tuple(0x36f5000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36f5800000000000, 0x0000000000000000), + ::testing::make_tuple(0x36f6000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36f6800000000000, 0x0000000000000000), + ::testing::make_tuple(0x36f7000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36f7800000000000, 0x0000000000000000), + ::testing::make_tuple(0x36f8000000000000, 0x0000000000000000), + ::testing::make_tuple(0x36f8800000000000, 0x0000000000000000))); + +INSTANTIATE_TEST_CASE_P( + TestWithParameters_BF_002, MyTest, + testing::Values( + // start: 97495757619 + // stop: 97495757669 + // inc: 1 + ::testing::make_tuple(0xbe66666660000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666680000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe666666a0000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe666666c0000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe666666e0000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666700000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666720000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666740000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666760000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666780000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe666667a0000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe666667c0000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe666667e0000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666800000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666820000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666840000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666860000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666880000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe666668a0000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe666668c0000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe666668e0000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666900000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666920000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666940000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666960000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666980000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe666669a0000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe666669c0000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe666669e0000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666a00000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666a20000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666a40000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666a60000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666a80000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666aa0000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666ac0000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666ae0000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666b00000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666b20000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666b40000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666b60000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666b80000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666ba0000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666bc0000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666be0000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666c00000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666c20000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666c40000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666c60000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe66666c80000000, 0xbe70000000000000))); + +INSTANTIATE_TEST_CASE_P( + TestWithParameters_BF_003, MyTest, + testing::Values( + // start: 214318868070 + // stop: 214318868120 + // inc: 1 + ::testing::make_tuple(0xc4ccccccc0000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4cccccce0000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4cccccd00000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4cccccd20000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4cccccd40000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4cccccd60000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4cccccd80000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4cccccda0000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4cccccdc0000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4cccccde0000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccce00000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccce20000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccce40000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccce60000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccce80000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4cccccea0000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4cccccec0000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4cccccee0000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4cccccf00000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4cccccf20000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4cccccf40000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4cccccf60000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4cccccf80000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4cccccfa0000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4cccccfc0000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4cccccfe0000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd000000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd020000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd040000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd060000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd080000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd0a0000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd0c0000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd0e0000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd100000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd120000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd140000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd160000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd180000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd1a0000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd1c0000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd1e0000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd200000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd220000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd240000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd260000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd280000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd2a0000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd2c0000000, 0xfff0000000000000), + ::testing::make_tuple(0xc4ccccd2e0000000, 0xfff0000000000000))); + +INSTANTIATE_TEST_CASE_P( + TestWithParameters_BF_004, MyTest, + testing::Values( + // start: 429492434632 + // stop: 429492434682 + // inc: 1 + ::testing::make_tuple(0xffffced900000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffced920000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffced940000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffced960000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffced980000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffced9a0000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffced9c0000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffced9e0000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffceda00000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffceda20000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffceda40000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffceda60000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffceda80000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedaa0000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedac0000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedae0000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedb00000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedb20000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedb40000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedb60000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedb80000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedba0000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedbc0000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedbe0000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedc00000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedc20000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedc40000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedc60000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedc80000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedca0000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedcc0000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedce0000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedd00000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedd20000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedd40000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedd60000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedd80000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedda0000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffceddc0000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedde0000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcede00000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcede20000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcede40000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcede60000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcede80000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedea0000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedec0000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedee0000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedf00000000, 0xffffcc0000000000), + ::testing::make_tuple(0xffffcedf20000000, 0xffffcc0000000000))); + + +INSTANTIATE_TEST_CASE_P( + TestWithParameters_BF_005, MyTest, + testing::Values( + // start: 97495757619 + // stop: 97548186419 + // inc: 1048576 + ::testing::make_tuple(0xbe66666660000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe68666660000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe6a666660000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe6c666660000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe6e666660000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe70666660000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe72666660000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe74666660000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe76666660000000, 0xbe70000000000000), + ::testing::make_tuple(0xbe78666660000000, 0xbe80000000000000), + ::testing::make_tuple(0xbe7a666660000000, 0xbe80000000000000), + ::testing::make_tuple(0xbe7c666660000000, 0xbe80000000000000), + ::testing::make_tuple(0xbe7e666660000000, 0xbe80000000000000), + ::testing::make_tuple(0xbe80666660000000, 0xbe80000000000000), + ::testing::make_tuple(0xbe82666660000000, 0xbe80000000000000), + ::testing::make_tuple(0xbe84666660000000, 0xbe88000000000000), + ::testing::make_tuple(0xbe86666660000000, 0xbe88000000000000), + ::testing::make_tuple(0xbe88666660000000, 0xbe88000000000000), + ::testing::make_tuple(0xbe8a666660000000, 0xbe88000000000000), + ::testing::make_tuple(0xbe8c666660000000, 0xbe90000000000000), + ::testing::make_tuple(0xbe8e666660000000, 0xbe90000000000000), + ::testing::make_tuple(0xbe90666660000000, 0xbe90000000000000), + ::testing::make_tuple(0xbe92666660000000, 0xbe94000000000000), + ::testing::make_tuple(0xbe94666660000000, 0xbe94000000000000), + ::testing::make_tuple(0xbe96666660000000, 0xbe98000000000000), + ::testing::make_tuple(0xbe98666660000000, 0xbe98000000000000), + ::testing::make_tuple(0xbe9a666660000000, 0xbe9c000000000000), + ::testing::make_tuple(0xbe9c666660000000, 0xbe9c000000000000), + ::testing::make_tuple(0xbe9e666660000000, 0xbea0000000000000), + ::testing::make_tuple(0xbea0666660000000, 0xbea0000000000000), + ::testing::make_tuple(0xbea2666660000000, 0xbea2000000000000), + ::testing::make_tuple(0xbea4666660000000, 0xbea4000000000000), + ::testing::make_tuple(0xbea6666660000000, 0xbea6000000000000), + ::testing::make_tuple(0xbea8666660000000, 0xbea8000000000000), + ::testing::make_tuple(0xbeaa666660000000, 0xbeaa000000000000), + ::testing::make_tuple(0xbeac666660000000, 0xbeac000000000000), + ::testing::make_tuple(0xbeae666660000000, 0xbeae000000000000), + ::testing::make_tuple(0xbeb0666660000000, 0xbeb0000000000000), + ::testing::make_tuple(0xbeb2666660000000, 0xbeb2000000000000), + ::testing::make_tuple(0xbeb4666660000000, 0xbeb4000000000000), + ::testing::make_tuple(0xbeb6666660000000, 0xbeb6000000000000), + ::testing::make_tuple(0xbeb8666660000000, 0xbeb8000000000000), + ::testing::make_tuple(0xbeba666660000000, 0xbeba000000000000), + ::testing::make_tuple(0xbebc666660000000, 0xbebc000000000000), + ::testing::make_tuple(0xbebe666660000000, 0xbebe000000000000), + ::testing::make_tuple(0xbec0666660000000, 0xbec0800000000000), + ::testing::make_tuple(0xbec2666660000000, 0xbec2800000000000), + ::testing::make_tuple(0xbec4666660000000, 0xbec4800000000000), + ::testing::make_tuple(0xbec6666660000000, 0xbec6800000000000), + ::testing::make_tuple(0xbec8666660000000, 0xbec8800000000000))); diff --git a/third-party/FloatX/testx/CMakeLists.txt b/third-party/FloatX/testx/CMakeLists.txt new file mode 100644 index 0000000..55d40ce --- /dev/null +++ b/third-party/FloatX/testx/CMakeLists.txt @@ -0,0 +1,12 @@ +function(create_test test_name) + add_executable(${test_name} ${test_name}.cpp) + target_link_libraries(${test_name} PRIVATE floatx gtest_main) + file(RELATIVE_PATH REL_BINARY_DIR + ${PROJECT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + add_test(NAME ${REL_BINARY_DIR}/${test_name} COMMAND ${test_name}) +endfunction(create_test) + +create_test(add_000) +create_test(sub_000) +create_test(mul_000) +create_test(div_000) diff --git a/third-party/FloatX/testx/add_000.cpp b/third-party/FloatX/testx/add_000.cpp new file mode 100644 index 0000000..2df9624 --- /dev/null +++ b/third-party/FloatX/testx/add_000.cpp @@ -0,0 +1,6891 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include +#include + +#define nan double(0.0 / 0.0) +#define inf double(1.0 / 0.0) + +namespace { + +TEST(FloatxOperationsTest, ADD_1_1_simple) +{ + using T = flx::floatx<1, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.00000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_EQ(double(c), 0.00000000000000000000); +} + +TEST(FloatxOperationsTest, ADD_1_2_simple) +{ + using T = flx::floatx<1, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.50000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_EQ(double(c), 0.50000000000000000000); +} + +TEST(FloatxOperationsTest, ADD_1_3_simple) +{ + using T = flx::floatx<1, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.25000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_EQ(double(c), 0.25000000000000000000); +} + +TEST(FloatxOperationsTest, ADD_1_4_simple) +{ + using T = flx::floatx<1, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.50000000000000000000); +} + +TEST(FloatxOperationsTest, ADD_1_5_simple) +{ + using T = flx::floatx<1, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_1_6_simple) +{ + using T = flx::floatx<1, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.46875000000000000000); +} + +TEST(FloatxOperationsTest, ADD_1_7_simple) +{ + using T = flx::floatx<1, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_1_8_simple) +{ + using T = flx::floatx<1, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_1_9_simple) +{ + using T = flx::floatx<1, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.44140625000000000000); +} + +TEST(FloatxOperationsTest, ADD_1_10_simple) +{ + using T = flx::floatx<1, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_1_11_simple) +{ + using T = flx::floatx<1, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_1_12_simple) +{ + using T = flx::floatx<1, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44482421875000000000); +} + +TEST(FloatxOperationsTest, ADD_1_13_simple) +{ + using T = flx::floatx<1, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_1_14_simple) +{ + using T = flx::floatx<1, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_1_15_simple) +{ + using T = flx::floatx<1, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44439697265625000000); +} + +TEST(FloatxOperationsTest, ADD_1_16_simple) +{ + using T = flx::floatx<1, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_1_17_simple) +{ + using T = flx::floatx<1, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_1_18_simple) +{ + using T = flx::floatx<1, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445037841796875000); +} + +TEST(FloatxOperationsTest, ADD_1_19_simple) +{ + using T = flx::floatx<1, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_1_20_simple) +{ + using T = flx::floatx<1, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_1_21_simple) +{ + using T = flx::floatx<1, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444370269775390625); +} + +TEST(FloatxOperationsTest, ADD_1_22_simple) +{ + using T = flx::floatx<1, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_1_23_simple) +{ + using T = flx::floatx<1, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_1_24_simple) +{ + using T = flx::floatx<1, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444453716278076172); +} + +TEST(FloatxOperationsTest, ADD_1_25_simple) +{ + using T = flx::floatx<1, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_1_26_simple) +{ + using T = flx::floatx<1, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_1_27_simple) +{ + using T = flx::floatx<1, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444443285465240479); +} + +TEST(FloatxOperationsTest, ADD_1_28_simple) +{ + using T = flx::floatx<1, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_1_29_simple) +{ + using T = flx::floatx<1, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_1_30_simple) +{ + using T = flx::floatx<1, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444589316844940); +} + +TEST(FloatxOperationsTest, ADD_1_31_simple) +{ + using T = flx::floatx<1, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_1_32_simple) +{ + using T = flx::floatx<1, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_1_33_simple) +{ + using T = flx::floatx<1, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444426335394382); +} + +TEST(FloatxOperationsTest, ADD_1_34_simple) +{ + using T = flx::floatx<1, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_1_35_simple) +{ + using T = flx::floatx<1, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_1_36_simple) +{ + using T = flx::floatx<1, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444446708075702); +} + +TEST(FloatxOperationsTest, ADD_1_37_simple) +{ + using T = flx::floatx<1, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_1_38_simple) +{ + using T = flx::floatx<1, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_1_39_simple) +{ + using T = flx::floatx<1, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444444161490537); +} + +TEST(FloatxOperationsTest, ADD_1_40_simple) +{ + using T = flx::floatx<1, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_1_41_simple) +{ + using T = flx::floatx<1, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_1_42_simple) +{ + using T = flx::floatx<1, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444479813683); +} + +TEST(FloatxOperationsTest, ADD_1_43_simple) +{ + using T = flx::floatx<1, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_1_44_simple) +{ + using T = flx::floatx<1, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_1_45_simple) +{ + using T = flx::floatx<1, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444440023290); +} + +TEST(FloatxOperationsTest, ADD_1_46_simple) +{ + using T = flx::floatx<1, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_1_47_simple) +{ + using T = flx::floatx<1, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_1_48_simple) +{ + using T = flx::floatx<1, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444444997089); +} + +TEST(FloatxOperationsTest, ADD_1_49_simple) +{ + using T = flx::floatx<1, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_1_50_simple) +{ + using T = flx::floatx<1, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_1_51_simple) +{ + using T = flx::floatx<1, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444375364); +} + +TEST(FloatxOperationsTest, ADD_1_52_simple) +{ + using T = flx::floatx<1, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_2_1_simple) +{ + using T = flx::floatx<2, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.50000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_EQ(double(c), 0.50000000000000000000); +} + +TEST(FloatxOperationsTest, ADD_2_2_simple) +{ + using T = flx::floatx<2, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.25000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_EQ(double(c), 0.25000000000000000000); +} + +TEST(FloatxOperationsTest, ADD_2_3_simple) +{ + using T = flx::floatx<2, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.50000000000000000000); +} + +TEST(FloatxOperationsTest, ADD_2_4_simple) +{ + using T = flx::floatx<2, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_2_5_simple) +{ + using T = flx::floatx<2, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.46875000000000000000); +} + +TEST(FloatxOperationsTest, ADD_2_6_simple) +{ + using T = flx::floatx<2, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_2_7_simple) +{ + using T = flx::floatx<2, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_2_8_simple) +{ + using T = flx::floatx<2, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.44140625000000000000); +} + +TEST(FloatxOperationsTest, ADD_2_9_simple) +{ + using T = flx::floatx<2, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_2_10_simple) +{ + using T = flx::floatx<2, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_2_11_simple) +{ + using T = flx::floatx<2, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44482421875000000000); +} + +TEST(FloatxOperationsTest, ADD_2_12_simple) +{ + using T = flx::floatx<2, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_2_13_simple) +{ + using T = flx::floatx<2, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_2_14_simple) +{ + using T = flx::floatx<2, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44439697265625000000); +} + +TEST(FloatxOperationsTest, ADD_2_15_simple) +{ + using T = flx::floatx<2, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_2_16_simple) +{ + using T = flx::floatx<2, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_2_17_simple) +{ + using T = flx::floatx<2, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445037841796875000); +} + +TEST(FloatxOperationsTest, ADD_2_18_simple) +{ + using T = flx::floatx<2, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_2_19_simple) +{ + using T = flx::floatx<2, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_2_20_simple) +{ + using T = flx::floatx<2, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444370269775390625); +} + +TEST(FloatxOperationsTest, ADD_2_21_simple) +{ + using T = flx::floatx<2, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_2_22_simple) +{ + using T = flx::floatx<2, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_2_23_simple) +{ + using T = flx::floatx<2, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444453716278076172); +} + +TEST(FloatxOperationsTest, ADD_2_24_simple) +{ + using T = flx::floatx<2, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_2_25_simple) +{ + using T = flx::floatx<2, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_2_26_simple) +{ + using T = flx::floatx<2, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444443285465240479); +} + +TEST(FloatxOperationsTest, ADD_2_27_simple) +{ + using T = flx::floatx<2, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_2_28_simple) +{ + using T = flx::floatx<2, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_2_29_simple) +{ + using T = flx::floatx<2, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444589316844940); +} + +TEST(FloatxOperationsTest, ADD_2_30_simple) +{ + using T = flx::floatx<2, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_2_31_simple) +{ + using T = flx::floatx<2, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_2_32_simple) +{ + using T = flx::floatx<2, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444426335394382); +} + +TEST(FloatxOperationsTest, ADD_2_33_simple) +{ + using T = flx::floatx<2, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_2_34_simple) +{ + using T = flx::floatx<2, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_2_35_simple) +{ + using T = flx::floatx<2, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444446708075702); +} + +TEST(FloatxOperationsTest, ADD_2_36_simple) +{ + using T = flx::floatx<2, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_2_37_simple) +{ + using T = flx::floatx<2, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_2_38_simple) +{ + using T = flx::floatx<2, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444444161490537); +} + +TEST(FloatxOperationsTest, ADD_2_39_simple) +{ + using T = flx::floatx<2, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_2_40_simple) +{ + using T = flx::floatx<2, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_2_41_simple) +{ + using T = flx::floatx<2, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444479813683); +} + +TEST(FloatxOperationsTest, ADD_2_42_simple) +{ + using T = flx::floatx<2, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_2_43_simple) +{ + using T = flx::floatx<2, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_2_44_simple) +{ + using T = flx::floatx<2, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444440023290); +} + +TEST(FloatxOperationsTest, ADD_2_45_simple) +{ + using T = flx::floatx<2, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_2_46_simple) +{ + using T = flx::floatx<2, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_2_47_simple) +{ + using T = flx::floatx<2, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444444997089); +} + +TEST(FloatxOperationsTest, ADD_2_48_simple) +{ + using T = flx::floatx<2, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_2_49_simple) +{ + using T = flx::floatx<2, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_2_50_simple) +{ + using T = flx::floatx<2, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444375364); +} + +TEST(FloatxOperationsTest, ADD_2_51_simple) +{ + using T = flx::floatx<2, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_2_52_simple) +{ + using T = flx::floatx<2, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_3_1_simple) +{ + using T = flx::floatx<3, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.50000000000000000000); +} + +TEST(FloatxOperationsTest, ADD_3_2_simple) +{ + using T = flx::floatx<3, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_3_3_simple) +{ + using T = flx::floatx<3, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.46875000000000000000); +} + +TEST(FloatxOperationsTest, ADD_3_4_simple) +{ + using T = flx::floatx<3, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_3_5_simple) +{ + using T = flx::floatx<3, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_3_6_simple) +{ + using T = flx::floatx<3, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.44140625000000000000); +} + +TEST(FloatxOperationsTest, ADD_3_7_simple) +{ + using T = flx::floatx<3, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_3_8_simple) +{ + using T = flx::floatx<3, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_3_9_simple) +{ + using T = flx::floatx<3, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44482421875000000000); +} + +TEST(FloatxOperationsTest, ADD_3_10_simple) +{ + using T = flx::floatx<3, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_3_11_simple) +{ + using T = flx::floatx<3, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_3_12_simple) +{ + using T = flx::floatx<3, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44439697265625000000); +} + +TEST(FloatxOperationsTest, ADD_3_13_simple) +{ + using T = flx::floatx<3, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_3_14_simple) +{ + using T = flx::floatx<3, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_3_15_simple) +{ + using T = flx::floatx<3, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445037841796875000); +} + +TEST(FloatxOperationsTest, ADD_3_16_simple) +{ + using T = flx::floatx<3, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_3_17_simple) +{ + using T = flx::floatx<3, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_3_18_simple) +{ + using T = flx::floatx<3, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444370269775390625); +} + +TEST(FloatxOperationsTest, ADD_3_19_simple) +{ + using T = flx::floatx<3, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_3_20_simple) +{ + using T = flx::floatx<3, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_3_21_simple) +{ + using T = flx::floatx<3, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444453716278076172); +} + +TEST(FloatxOperationsTest, ADD_3_22_simple) +{ + using T = flx::floatx<3, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_3_23_simple) +{ + using T = flx::floatx<3, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_3_24_simple) +{ + using T = flx::floatx<3, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444443285465240479); +} + +TEST(FloatxOperationsTest, ADD_3_25_simple) +{ + using T = flx::floatx<3, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_3_26_simple) +{ + using T = flx::floatx<3, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_3_27_simple) +{ + using T = flx::floatx<3, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444589316844940); +} + +TEST(FloatxOperationsTest, ADD_3_28_simple) +{ + using T = flx::floatx<3, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_3_29_simple) +{ + using T = flx::floatx<3, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_3_30_simple) +{ + using T = flx::floatx<3, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444426335394382); +} + +TEST(FloatxOperationsTest, ADD_3_31_simple) +{ + using T = flx::floatx<3, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_3_32_simple) +{ + using T = flx::floatx<3, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_3_33_simple) +{ + using T = flx::floatx<3, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444446708075702); +} + +TEST(FloatxOperationsTest, ADD_3_34_simple) +{ + using T = flx::floatx<3, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_3_35_simple) +{ + using T = flx::floatx<3, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_3_36_simple) +{ + using T = flx::floatx<3, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444444161490537); +} + +TEST(FloatxOperationsTest, ADD_3_37_simple) +{ + using T = flx::floatx<3, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_3_38_simple) +{ + using T = flx::floatx<3, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_3_39_simple) +{ + using T = flx::floatx<3, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444479813683); +} + +TEST(FloatxOperationsTest, ADD_3_40_simple) +{ + using T = flx::floatx<3, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_3_41_simple) +{ + using T = flx::floatx<3, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_3_42_simple) +{ + using T = flx::floatx<3, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444440023290); +} + +TEST(FloatxOperationsTest, ADD_3_43_simple) +{ + using T = flx::floatx<3, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_3_44_simple) +{ + using T = flx::floatx<3, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_3_45_simple) +{ + using T = flx::floatx<3, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444444997089); +} + +TEST(FloatxOperationsTest, ADD_3_46_simple) +{ + using T = flx::floatx<3, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_3_47_simple) +{ + using T = flx::floatx<3, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_3_48_simple) +{ + using T = flx::floatx<3, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444375364); +} + +TEST(FloatxOperationsTest, ADD_3_49_simple) +{ + using T = flx::floatx<3, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_3_50_simple) +{ + using T = flx::floatx<3, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_3_51_simple) +{ + using T = flx::floatx<3, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_3_52_simple) +{ + using T = flx::floatx<3, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_4_1_simple) +{ + using T = flx::floatx<4, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.50000000000000000000); +} + +TEST(FloatxOperationsTest, ADD_4_2_simple) +{ + using T = flx::floatx<4, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_4_3_simple) +{ + using T = flx::floatx<4, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_4_4_simple) +{ + using T = flx::floatx<4, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_4_5_simple) +{ + using T = flx::floatx<4, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_4_6_simple) +{ + using T = flx::floatx<4, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_4_7_simple) +{ + using T = flx::floatx<4, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_4_8_simple) +{ + using T = flx::floatx<4, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_4_9_simple) +{ + using T = flx::floatx<4, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_4_10_simple) +{ + using T = flx::floatx<4, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_4_11_simple) +{ + using T = flx::floatx<4, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_4_12_simple) +{ + using T = flx::floatx<4, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_4_13_simple) +{ + using T = flx::floatx<4, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_4_14_simple) +{ + using T = flx::floatx<4, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_4_15_simple) +{ + using T = flx::floatx<4, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_4_16_simple) +{ + using T = flx::floatx<4, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_4_17_simple) +{ + using T = flx::floatx<4, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_4_18_simple) +{ + using T = flx::floatx<4, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_4_19_simple) +{ + using T = flx::floatx<4, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_4_20_simple) +{ + using T = flx::floatx<4, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_4_21_simple) +{ + using T = flx::floatx<4, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_4_22_simple) +{ + using T = flx::floatx<4, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_4_23_simple) +{ + using T = flx::floatx<4, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_4_24_simple) +{ + using T = flx::floatx<4, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_4_25_simple) +{ + using T = flx::floatx<4, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_4_26_simple) +{ + using T = flx::floatx<4, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_4_27_simple) +{ + using T = flx::floatx<4, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_4_28_simple) +{ + using T = flx::floatx<4, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_4_29_simple) +{ + using T = flx::floatx<4, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_4_30_simple) +{ + using T = flx::floatx<4, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_4_31_simple) +{ + using T = flx::floatx<4, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_4_32_simple) +{ + using T = flx::floatx<4, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_4_33_simple) +{ + using T = flx::floatx<4, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_4_34_simple) +{ + using T = flx::floatx<4, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_4_35_simple) +{ + using T = flx::floatx<4, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_4_36_simple) +{ + using T = flx::floatx<4, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_4_37_simple) +{ + using T = flx::floatx<4, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_4_38_simple) +{ + using T = flx::floatx<4, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_4_39_simple) +{ + using T = flx::floatx<4, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_4_40_simple) +{ + using T = flx::floatx<4, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_4_41_simple) +{ + using T = flx::floatx<4, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_4_42_simple) +{ + using T = flx::floatx<4, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_4_43_simple) +{ + using T = flx::floatx<4, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_4_44_simple) +{ + using T = flx::floatx<4, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_4_45_simple) +{ + using T = flx::floatx<4, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_4_46_simple) +{ + using T = flx::floatx<4, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_4_47_simple) +{ + using T = flx::floatx<4, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_4_48_simple) +{ + using T = flx::floatx<4, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_4_49_simple) +{ + using T = flx::floatx<4, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_4_50_simple) +{ + using T = flx::floatx<4, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_4_51_simple) +{ + using T = flx::floatx<4, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_4_52_simple) +{ + using T = flx::floatx<4, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_5_1_simple) +{ + using T = flx::floatx<5, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.50000000000000000000); +} + +TEST(FloatxOperationsTest, ADD_5_2_simple) +{ + using T = flx::floatx<5, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_5_3_simple) +{ + using T = flx::floatx<5, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_5_4_simple) +{ + using T = flx::floatx<5, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_5_5_simple) +{ + using T = flx::floatx<5, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_5_6_simple) +{ + using T = flx::floatx<5, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_5_7_simple) +{ + using T = flx::floatx<5, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_5_8_simple) +{ + using T = flx::floatx<5, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_5_9_simple) +{ + using T = flx::floatx<5, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_5_10_simple) +{ + using T = flx::floatx<5, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_5_11_simple) +{ + using T = flx::floatx<5, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_5_12_simple) +{ + using T = flx::floatx<5, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_5_13_simple) +{ + using T = flx::floatx<5, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_5_14_simple) +{ + using T = flx::floatx<5, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_5_15_simple) +{ + using T = flx::floatx<5, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_5_16_simple) +{ + using T = flx::floatx<5, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_5_17_simple) +{ + using T = flx::floatx<5, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_5_18_simple) +{ + using T = flx::floatx<5, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_5_19_simple) +{ + using T = flx::floatx<5, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_5_20_simple) +{ + using T = flx::floatx<5, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_5_21_simple) +{ + using T = flx::floatx<5, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_5_22_simple) +{ + using T = flx::floatx<5, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_5_23_simple) +{ + using T = flx::floatx<5, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_5_24_simple) +{ + using T = flx::floatx<5, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_5_25_simple) +{ + using T = flx::floatx<5, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_5_26_simple) +{ + using T = flx::floatx<5, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_5_27_simple) +{ + using T = flx::floatx<5, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_5_28_simple) +{ + using T = flx::floatx<5, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_5_29_simple) +{ + using T = flx::floatx<5, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_5_30_simple) +{ + using T = flx::floatx<5, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_5_31_simple) +{ + using T = flx::floatx<5, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_5_32_simple) +{ + using T = flx::floatx<5, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_5_33_simple) +{ + using T = flx::floatx<5, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_5_34_simple) +{ + using T = flx::floatx<5, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_5_35_simple) +{ + using T = flx::floatx<5, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_5_36_simple) +{ + using T = flx::floatx<5, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_5_37_simple) +{ + using T = flx::floatx<5, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_5_38_simple) +{ + using T = flx::floatx<5, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_5_39_simple) +{ + using T = flx::floatx<5, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_5_40_simple) +{ + using T = flx::floatx<5, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_5_41_simple) +{ + using T = flx::floatx<5, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_5_42_simple) +{ + using T = flx::floatx<5, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_5_43_simple) +{ + using T = flx::floatx<5, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_5_44_simple) +{ + using T = flx::floatx<5, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_5_45_simple) +{ + using T = flx::floatx<5, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_5_46_simple) +{ + using T = flx::floatx<5, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_5_47_simple) +{ + using T = flx::floatx<5, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_5_48_simple) +{ + using T = flx::floatx<5, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_5_49_simple) +{ + using T = flx::floatx<5, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_5_50_simple) +{ + using T = flx::floatx<5, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_5_51_simple) +{ + using T = flx::floatx<5, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_5_52_simple) +{ + using T = flx::floatx<5, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_6_1_simple) +{ + using T = flx::floatx<6, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.50000000000000000000); +} + +TEST(FloatxOperationsTest, ADD_6_2_simple) +{ + using T = flx::floatx<6, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_6_3_simple) +{ + using T = flx::floatx<6, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_6_4_simple) +{ + using T = flx::floatx<6, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_6_5_simple) +{ + using T = flx::floatx<6, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_6_6_simple) +{ + using T = flx::floatx<6, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_6_7_simple) +{ + using T = flx::floatx<6, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_6_8_simple) +{ + using T = flx::floatx<6, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_6_9_simple) +{ + using T = flx::floatx<6, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_6_10_simple) +{ + using T = flx::floatx<6, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_6_11_simple) +{ + using T = flx::floatx<6, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_6_12_simple) +{ + using T = flx::floatx<6, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_6_13_simple) +{ + using T = flx::floatx<6, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_6_14_simple) +{ + using T = flx::floatx<6, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_6_15_simple) +{ + using T = flx::floatx<6, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_6_16_simple) +{ + using T = flx::floatx<6, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_6_17_simple) +{ + using T = flx::floatx<6, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_6_18_simple) +{ + using T = flx::floatx<6, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_6_19_simple) +{ + using T = flx::floatx<6, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_6_20_simple) +{ + using T = flx::floatx<6, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_6_21_simple) +{ + using T = flx::floatx<6, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_6_22_simple) +{ + using T = flx::floatx<6, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_6_23_simple) +{ + using T = flx::floatx<6, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_6_24_simple) +{ + using T = flx::floatx<6, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_6_25_simple) +{ + using T = flx::floatx<6, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_6_26_simple) +{ + using T = flx::floatx<6, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_6_27_simple) +{ + using T = flx::floatx<6, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_6_28_simple) +{ + using T = flx::floatx<6, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_6_29_simple) +{ + using T = flx::floatx<6, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_6_30_simple) +{ + using T = flx::floatx<6, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_6_31_simple) +{ + using T = flx::floatx<6, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_6_32_simple) +{ + using T = flx::floatx<6, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_6_33_simple) +{ + using T = flx::floatx<6, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_6_34_simple) +{ + using T = flx::floatx<6, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_6_35_simple) +{ + using T = flx::floatx<6, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_6_36_simple) +{ + using T = flx::floatx<6, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_6_37_simple) +{ + using T = flx::floatx<6, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_6_38_simple) +{ + using T = flx::floatx<6, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_6_39_simple) +{ + using T = flx::floatx<6, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_6_40_simple) +{ + using T = flx::floatx<6, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_6_41_simple) +{ + using T = flx::floatx<6, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_6_42_simple) +{ + using T = flx::floatx<6, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_6_43_simple) +{ + using T = flx::floatx<6, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_6_44_simple) +{ + using T = flx::floatx<6, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_6_45_simple) +{ + using T = flx::floatx<6, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_6_46_simple) +{ + using T = flx::floatx<6, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_6_47_simple) +{ + using T = flx::floatx<6, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_6_48_simple) +{ + using T = flx::floatx<6, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_6_49_simple) +{ + using T = flx::floatx<6, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_6_50_simple) +{ + using T = flx::floatx<6, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_6_51_simple) +{ + using T = flx::floatx<6, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_6_52_simple) +{ + using T = flx::floatx<6, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_7_1_simple) +{ + using T = flx::floatx<7, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.50000000000000000000); +} + +TEST(FloatxOperationsTest, ADD_7_2_simple) +{ + using T = flx::floatx<7, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_7_3_simple) +{ + using T = flx::floatx<7, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_7_4_simple) +{ + using T = flx::floatx<7, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_7_5_simple) +{ + using T = flx::floatx<7, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_7_6_simple) +{ + using T = flx::floatx<7, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_7_7_simple) +{ + using T = flx::floatx<7, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_7_8_simple) +{ + using T = flx::floatx<7, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_7_9_simple) +{ + using T = flx::floatx<7, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_7_10_simple) +{ + using T = flx::floatx<7, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_7_11_simple) +{ + using T = flx::floatx<7, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_7_12_simple) +{ + using T = flx::floatx<7, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_7_13_simple) +{ + using T = flx::floatx<7, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_7_14_simple) +{ + using T = flx::floatx<7, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_7_15_simple) +{ + using T = flx::floatx<7, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_7_16_simple) +{ + using T = flx::floatx<7, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_7_17_simple) +{ + using T = flx::floatx<7, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_7_18_simple) +{ + using T = flx::floatx<7, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_7_19_simple) +{ + using T = flx::floatx<7, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_7_20_simple) +{ + using T = flx::floatx<7, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_7_21_simple) +{ + using T = flx::floatx<7, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_7_22_simple) +{ + using T = flx::floatx<7, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_7_23_simple) +{ + using T = flx::floatx<7, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_7_24_simple) +{ + using T = flx::floatx<7, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_7_25_simple) +{ + using T = flx::floatx<7, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_7_26_simple) +{ + using T = flx::floatx<7, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_7_27_simple) +{ + using T = flx::floatx<7, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_7_28_simple) +{ + using T = flx::floatx<7, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_7_29_simple) +{ + using T = flx::floatx<7, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_7_30_simple) +{ + using T = flx::floatx<7, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_7_31_simple) +{ + using T = flx::floatx<7, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_7_32_simple) +{ + using T = flx::floatx<7, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_7_33_simple) +{ + using T = flx::floatx<7, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_7_34_simple) +{ + using T = flx::floatx<7, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_7_35_simple) +{ + using T = flx::floatx<7, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_7_36_simple) +{ + using T = flx::floatx<7, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_7_37_simple) +{ + using T = flx::floatx<7, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_7_38_simple) +{ + using T = flx::floatx<7, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_7_39_simple) +{ + using T = flx::floatx<7, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_7_40_simple) +{ + using T = flx::floatx<7, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_7_41_simple) +{ + using T = flx::floatx<7, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_7_42_simple) +{ + using T = flx::floatx<7, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_7_43_simple) +{ + using T = flx::floatx<7, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_7_44_simple) +{ + using T = flx::floatx<7, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_7_45_simple) +{ + using T = flx::floatx<7, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_7_46_simple) +{ + using T = flx::floatx<7, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_7_47_simple) +{ + using T = flx::floatx<7, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_7_48_simple) +{ + using T = flx::floatx<7, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_7_49_simple) +{ + using T = flx::floatx<7, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_7_50_simple) +{ + using T = flx::floatx<7, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_7_51_simple) +{ + using T = flx::floatx<7, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_7_52_simple) +{ + using T = flx::floatx<7, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_8_1_simple) +{ + using T = flx::floatx<8, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.50000000000000000000); +} + +TEST(FloatxOperationsTest, ADD_8_2_simple) +{ + using T = flx::floatx<8, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_8_3_simple) +{ + using T = flx::floatx<8, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_8_4_simple) +{ + using T = flx::floatx<8, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_8_5_simple) +{ + using T = flx::floatx<8, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_8_6_simple) +{ + using T = flx::floatx<8, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_8_7_simple) +{ + using T = flx::floatx<8, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_8_8_simple) +{ + using T = flx::floatx<8, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_8_9_simple) +{ + using T = flx::floatx<8, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_8_10_simple) +{ + using T = flx::floatx<8, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_8_11_simple) +{ + using T = flx::floatx<8, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_8_12_simple) +{ + using T = flx::floatx<8, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_8_13_simple) +{ + using T = flx::floatx<8, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_8_14_simple) +{ + using T = flx::floatx<8, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_8_15_simple) +{ + using T = flx::floatx<8, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_8_16_simple) +{ + using T = flx::floatx<8, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_8_17_simple) +{ + using T = flx::floatx<8, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_8_18_simple) +{ + using T = flx::floatx<8, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_8_19_simple) +{ + using T = flx::floatx<8, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_8_20_simple) +{ + using T = flx::floatx<8, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_8_21_simple) +{ + using T = flx::floatx<8, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_8_22_simple) +{ + using T = flx::floatx<8, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_8_23_simple) +{ + using T = flx::floatx<8, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_8_24_simple) +{ + using T = flx::floatx<8, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_8_25_simple) +{ + using T = flx::floatx<8, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_8_26_simple) +{ + using T = flx::floatx<8, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_8_27_simple) +{ + using T = flx::floatx<8, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_8_28_simple) +{ + using T = flx::floatx<8, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_8_29_simple) +{ + using T = flx::floatx<8, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_8_30_simple) +{ + using T = flx::floatx<8, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_8_31_simple) +{ + using T = flx::floatx<8, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_8_32_simple) +{ + using T = flx::floatx<8, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_8_33_simple) +{ + using T = flx::floatx<8, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_8_34_simple) +{ + using T = flx::floatx<8, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_8_35_simple) +{ + using T = flx::floatx<8, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_8_36_simple) +{ + using T = flx::floatx<8, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_8_37_simple) +{ + using T = flx::floatx<8, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_8_38_simple) +{ + using T = flx::floatx<8, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_8_39_simple) +{ + using T = flx::floatx<8, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_8_40_simple) +{ + using T = flx::floatx<8, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_8_41_simple) +{ + using T = flx::floatx<8, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_8_42_simple) +{ + using T = flx::floatx<8, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_8_43_simple) +{ + using T = flx::floatx<8, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_8_44_simple) +{ + using T = flx::floatx<8, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_8_45_simple) +{ + using T = flx::floatx<8, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_8_46_simple) +{ + using T = flx::floatx<8, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_8_47_simple) +{ + using T = flx::floatx<8, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_8_48_simple) +{ + using T = flx::floatx<8, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_8_49_simple) +{ + using T = flx::floatx<8, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_8_50_simple) +{ + using T = flx::floatx<8, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_8_51_simple) +{ + using T = flx::floatx<8, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_8_52_simple) +{ + using T = flx::floatx<8, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_9_1_simple) +{ + using T = flx::floatx<9, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.50000000000000000000); +} + +TEST(FloatxOperationsTest, ADD_9_2_simple) +{ + using T = flx::floatx<9, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_9_3_simple) +{ + using T = flx::floatx<9, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_9_4_simple) +{ + using T = flx::floatx<9, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_9_5_simple) +{ + using T = flx::floatx<9, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_9_6_simple) +{ + using T = flx::floatx<9, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_9_7_simple) +{ + using T = flx::floatx<9, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_9_8_simple) +{ + using T = flx::floatx<9, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_9_9_simple) +{ + using T = flx::floatx<9, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_9_10_simple) +{ + using T = flx::floatx<9, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_9_11_simple) +{ + using T = flx::floatx<9, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_9_12_simple) +{ + using T = flx::floatx<9, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_9_13_simple) +{ + using T = flx::floatx<9, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_9_14_simple) +{ + using T = flx::floatx<9, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_9_15_simple) +{ + using T = flx::floatx<9, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_9_16_simple) +{ + using T = flx::floatx<9, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_9_17_simple) +{ + using T = flx::floatx<9, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_9_18_simple) +{ + using T = flx::floatx<9, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_9_19_simple) +{ + using T = flx::floatx<9, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_9_20_simple) +{ + using T = flx::floatx<9, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_9_21_simple) +{ + using T = flx::floatx<9, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_9_22_simple) +{ + using T = flx::floatx<9, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_9_23_simple) +{ + using T = flx::floatx<9, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_9_24_simple) +{ + using T = flx::floatx<9, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_9_25_simple) +{ + using T = flx::floatx<9, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_9_26_simple) +{ + using T = flx::floatx<9, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_9_27_simple) +{ + using T = flx::floatx<9, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_9_28_simple) +{ + using T = flx::floatx<9, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_9_29_simple) +{ + using T = flx::floatx<9, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_9_30_simple) +{ + using T = flx::floatx<9, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_9_31_simple) +{ + using T = flx::floatx<9, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_9_32_simple) +{ + using T = flx::floatx<9, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_9_33_simple) +{ + using T = flx::floatx<9, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_9_34_simple) +{ + using T = flx::floatx<9, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_9_35_simple) +{ + using T = flx::floatx<9, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_9_36_simple) +{ + using T = flx::floatx<9, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_9_37_simple) +{ + using T = flx::floatx<9, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_9_38_simple) +{ + using T = flx::floatx<9, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_9_39_simple) +{ + using T = flx::floatx<9, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_9_40_simple) +{ + using T = flx::floatx<9, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_9_41_simple) +{ + using T = flx::floatx<9, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_9_42_simple) +{ + using T = flx::floatx<9, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_9_43_simple) +{ + using T = flx::floatx<9, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_9_44_simple) +{ + using T = flx::floatx<9, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_9_45_simple) +{ + using T = flx::floatx<9, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_9_46_simple) +{ + using T = flx::floatx<9, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_9_47_simple) +{ + using T = flx::floatx<9, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_9_48_simple) +{ + using T = flx::floatx<9, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_9_49_simple) +{ + using T = flx::floatx<9, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_9_50_simple) +{ + using T = flx::floatx<9, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_9_51_simple) +{ + using T = flx::floatx<9, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_9_52_simple) +{ + using T = flx::floatx<9, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_10_1_simple) +{ + using T = flx::floatx<10, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.50000000000000000000); +} + +TEST(FloatxOperationsTest, ADD_10_2_simple) +{ + using T = flx::floatx<10, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_10_3_simple) +{ + using T = flx::floatx<10, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_10_4_simple) +{ + using T = flx::floatx<10, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_10_5_simple) +{ + using T = flx::floatx<10, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_10_6_simple) +{ + using T = flx::floatx<10, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_10_7_simple) +{ + using T = flx::floatx<10, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_10_8_simple) +{ + using T = flx::floatx<10, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_10_9_simple) +{ + using T = flx::floatx<10, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_10_10_simple) +{ + using T = flx::floatx<10, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_10_11_simple) +{ + using T = flx::floatx<10, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_10_12_simple) +{ + using T = flx::floatx<10, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_10_13_simple) +{ + using T = flx::floatx<10, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_10_14_simple) +{ + using T = flx::floatx<10, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_10_15_simple) +{ + using T = flx::floatx<10, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_10_16_simple) +{ + using T = flx::floatx<10, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_10_17_simple) +{ + using T = flx::floatx<10, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_10_18_simple) +{ + using T = flx::floatx<10, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_10_19_simple) +{ + using T = flx::floatx<10, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_10_20_simple) +{ + using T = flx::floatx<10, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_10_21_simple) +{ + using T = flx::floatx<10, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_10_22_simple) +{ + using T = flx::floatx<10, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_10_23_simple) +{ + using T = flx::floatx<10, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_10_24_simple) +{ + using T = flx::floatx<10, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_10_25_simple) +{ + using T = flx::floatx<10, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_10_26_simple) +{ + using T = flx::floatx<10, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_10_27_simple) +{ + using T = flx::floatx<10, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_10_28_simple) +{ + using T = flx::floatx<10, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_10_29_simple) +{ + using T = flx::floatx<10, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_10_30_simple) +{ + using T = flx::floatx<10, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_10_31_simple) +{ + using T = flx::floatx<10, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_10_32_simple) +{ + using T = flx::floatx<10, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_10_33_simple) +{ + using T = flx::floatx<10, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_10_34_simple) +{ + using T = flx::floatx<10, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_10_35_simple) +{ + using T = flx::floatx<10, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_10_36_simple) +{ + using T = flx::floatx<10, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_10_37_simple) +{ + using T = flx::floatx<10, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_10_38_simple) +{ + using T = flx::floatx<10, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_10_39_simple) +{ + using T = flx::floatx<10, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_10_40_simple) +{ + using T = flx::floatx<10, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_10_41_simple) +{ + using T = flx::floatx<10, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_10_42_simple) +{ + using T = flx::floatx<10, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_10_43_simple) +{ + using T = flx::floatx<10, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_10_44_simple) +{ + using T = flx::floatx<10, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_10_45_simple) +{ + using T = flx::floatx<10, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_10_46_simple) +{ + using T = flx::floatx<10, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_10_47_simple) +{ + using T = flx::floatx<10, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_10_48_simple) +{ + using T = flx::floatx<10, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_10_49_simple) +{ + using T = flx::floatx<10, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_10_50_simple) +{ + using T = flx::floatx<10, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_10_51_simple) +{ + using T = flx::floatx<10, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_10_52_simple) +{ + using T = flx::floatx<10, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_11_1_simple) +{ + using T = flx::floatx<11, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.50000000000000000000); +} + +TEST(FloatxOperationsTest, ADD_11_2_simple) +{ + using T = flx::floatx<11, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_11_3_simple) +{ + using T = flx::floatx<11, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_11_4_simple) +{ + using T = flx::floatx<11, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.43750000000000000000); +} + +TEST(FloatxOperationsTest, ADD_11_5_simple) +{ + using T = flx::floatx<11, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_11_6_simple) +{ + using T = flx::floatx<11, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_11_7_simple) +{ + using T = flx::floatx<11, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.44531250000000000000); +} + +TEST(FloatxOperationsTest, ADD_11_8_simple) +{ + using T = flx::floatx<11, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_11_9_simple) +{ + using T = flx::floatx<11, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_11_10_simple) +{ + using T = flx::floatx<11, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.44433593750000000000); +} + +TEST(FloatxOperationsTest, ADD_11_11_simple) +{ + using T = flx::floatx<11, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_11_12_simple) +{ + using T = flx::floatx<11, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_11_13_simple) +{ + using T = flx::floatx<11, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.44445800781250000000); +} + +TEST(FloatxOperationsTest, ADD_11_14_simple) +{ + using T = flx::floatx<11, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_11_15_simple) +{ + using T = flx::floatx<11, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_11_16_simple) +{ + using T = flx::floatx<11, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.44444274902343750000); +} + +TEST(FloatxOperationsTest, ADD_11_17_simple) +{ + using T = flx::floatx<11, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_11_18_simple) +{ + using T = flx::floatx<11, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_11_19_simple) +{ + using T = flx::floatx<11, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.44444465637207031250); +} + +TEST(FloatxOperationsTest, ADD_11_20_simple) +{ + using T = flx::floatx<11, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_11_21_simple) +{ + using T = flx::floatx<11, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_11_22_simple) +{ + using T = flx::floatx<11, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.44444441795349121094); +} + +TEST(FloatxOperationsTest, ADD_11_23_simple) +{ + using T = flx::floatx<11, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_11_24_simple) +{ + using T = flx::floatx<11, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_11_25_simple) +{ + using T = flx::floatx<11, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.44444444775581359863); +} + +TEST(FloatxOperationsTest, ADD_11_26_simple) +{ + using T = flx::floatx<11, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_11_27_simple) +{ + using T = flx::floatx<11, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_11_28_simple) +{ + using T = flx::floatx<11, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.44444444403052330017); +} + +TEST(FloatxOperationsTest, ADD_11_29_simple) +{ + using T = flx::floatx<11, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_11_30_simple) +{ + using T = flx::floatx<11, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_11_31_simple) +{ + using T = flx::floatx<11, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.44444444449618458748); +} + +TEST(FloatxOperationsTest, ADD_11_32_simple) +{ + using T = flx::floatx<11, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_11_33_simple) +{ + using T = flx::floatx<11, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_11_34_simple) +{ + using T = flx::floatx<11, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.44444444443797692657); +} + +TEST(FloatxOperationsTest, ADD_11_35_simple) +{ + using T = flx::floatx<11, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_11_36_simple) +{ + using T = flx::floatx<11, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_11_37_simple) +{ + using T = flx::floatx<11, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.44444444444525288418); +} + +TEST(FloatxOperationsTest, ADD_11_38_simple) +{ + using T = flx::floatx<11, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_11_39_simple) +{ + using T = flx::floatx<11, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_11_40_simple) +{ + using T = flx::floatx<11, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.44444444444434338948); +} + +TEST(FloatxOperationsTest, ADD_11_41_simple) +{ + using T = flx::floatx<11, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_11_42_simple) +{ + using T = flx::floatx<11, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_11_43_simple) +{ + using T = flx::floatx<11, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.44444444444445707632); +} + +TEST(FloatxOperationsTest, ADD_11_44_simple) +{ + using T = flx::floatx<11, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_11_45_simple) +{ + using T = flx::floatx<11, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_11_46_simple) +{ + using T = flx::floatx<11, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.44444444444444286546); +} + +TEST(FloatxOperationsTest, ADD_11_47_simple) +{ + using T = flx::floatx<11, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_11_48_simple) +{ + using T = flx::floatx<11, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_11_49_simple) +{ + using T = flx::floatx<11, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.44444444444444464182); +} + +TEST(FloatxOperationsTest, ADD_11_50_simple) +{ + using T = flx::floatx<11, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_11_51_simple) +{ + using T = flx::floatx<11, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + +TEST(FloatxOperationsTest, ADD_11_52_simple) +{ + using T = flx::floatx<11, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a + b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.44444444444444441977); +} + + +} // namespace diff --git a/third-party/FloatX/testx/div_000.cpp b/third-party/FloatX/testx/div_000.cpp new file mode 100644 index 0000000..d702765 --- /dev/null +++ b/third-party/FloatX/testx/div_000.cpp @@ -0,0 +1,6891 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include +#include + +#define nan double(0.0 / 0.0) +#define inf double(1.0 / 0.0) + +namespace { + +TEST(FloatxOperationsTest, DIV_1_1_simple) +{ + using T = flx::floatx<1, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.00000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_NE(c, c); // holds only for NANs +} + +TEST(FloatxOperationsTest, DIV_1_2_simple) +{ + using T = flx::floatx<1, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.50000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_3_simple) +{ + using T = flx::floatx<1, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.25000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_4_simple) +{ + using T = flx::floatx<1, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_5_simple) +{ + using T = flx::floatx<1, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_6_simple) +{ + using T = flx::floatx<1, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_7_simple) +{ + using T = flx::floatx<1, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_8_simple) +{ + using T = flx::floatx<1, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_9_simple) +{ + using T = flx::floatx<1, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_10_simple) +{ + using T = flx::floatx<1, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_11_simple) +{ + using T = flx::floatx<1, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_12_simple) +{ + using T = flx::floatx<1, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_13_simple) +{ + using T = flx::floatx<1, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_14_simple) +{ + using T = flx::floatx<1, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_15_simple) +{ + using T = flx::floatx<1, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_16_simple) +{ + using T = flx::floatx<1, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_17_simple) +{ + using T = flx::floatx<1, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_18_simple) +{ + using T = flx::floatx<1, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_19_simple) +{ + using T = flx::floatx<1, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_20_simple) +{ + using T = flx::floatx<1, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_21_simple) +{ + using T = flx::floatx<1, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_22_simple) +{ + using T = flx::floatx<1, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_23_simple) +{ + using T = flx::floatx<1, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_24_simple) +{ + using T = flx::floatx<1, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_25_simple) +{ + using T = flx::floatx<1, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_26_simple) +{ + using T = flx::floatx<1, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_27_simple) +{ + using T = flx::floatx<1, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_28_simple) +{ + using T = flx::floatx<1, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_29_simple) +{ + using T = flx::floatx<1, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_30_simple) +{ + using T = flx::floatx<1, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_31_simple) +{ + using T = flx::floatx<1, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_32_simple) +{ + using T = flx::floatx<1, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_33_simple) +{ + using T = flx::floatx<1, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_34_simple) +{ + using T = flx::floatx<1, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_35_simple) +{ + using T = flx::floatx<1, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_36_simple) +{ + using T = flx::floatx<1, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_37_simple) +{ + using T = flx::floatx<1, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_38_simple) +{ + using T = flx::floatx<1, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_39_simple) +{ + using T = flx::floatx<1, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_40_simple) +{ + using T = flx::floatx<1, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_41_simple) +{ + using T = flx::floatx<1, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_42_simple) +{ + using T = flx::floatx<1, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_43_simple) +{ + using T = flx::floatx<1, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_44_simple) +{ + using T = flx::floatx<1, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_45_simple) +{ + using T = flx::floatx<1, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_46_simple) +{ + using T = flx::floatx<1, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_47_simple) +{ + using T = flx::floatx<1, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_48_simple) +{ + using T = flx::floatx<1, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_49_simple) +{ + using T = flx::floatx<1, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_50_simple) +{ + using T = flx::floatx<1, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_51_simple) +{ + using T = flx::floatx<1, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_1_52_simple) +{ + using T = flx::floatx<1, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_2_1_simple) +{ + using T = flx::floatx<2, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.50000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_2_2_simple) +{ + using T = flx::floatx<2, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.25000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_EQ(double(c), inf); +} + +TEST(FloatxOperationsTest, DIV_2_3_simple) +{ + using T = flx::floatx<2, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_4_simple) +{ + using T = flx::floatx<2, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 2.50000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_5_simple) +{ + using T = flx::floatx<2, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 2.75000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_6_simple) +{ + using T = flx::floatx<2, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_7_simple) +{ + using T = flx::floatx<2, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.07812500000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_8_simple) +{ + using T = flx::floatx<2, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.03906250000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_9_simple) +{ + using T = flx::floatx<2, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_10_simple) +{ + using T = flx::floatx<2, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 2.99218750000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_11_simple) +{ + using T = flx::floatx<2, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 2.99609375000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_12_simple) +{ + using T = flx::floatx<2, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_13_simple) +{ + using T = flx::floatx<2, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00122070312500000000); +} + +TEST(FloatxOperationsTest, DIV_2_14_simple) +{ + using T = flx::floatx<2, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00061035156250000000); +} + +TEST(FloatxOperationsTest, DIV_2_15_simple) +{ + using T = flx::floatx<2, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_16_simple) +{ + using T = flx::floatx<2, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 2.99987792968750000000); +} + +TEST(FloatxOperationsTest, DIV_2_17_simple) +{ + using T = flx::floatx<2, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 2.99993896484375000000); +} + +TEST(FloatxOperationsTest, DIV_2_18_simple) +{ + using T = flx::floatx<2, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_19_simple) +{ + using T = flx::floatx<2, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00001907348632812500); +} + +TEST(FloatxOperationsTest, DIV_2_20_simple) +{ + using T = flx::floatx<2, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00000953674316406250); +} + +TEST(FloatxOperationsTest, DIV_2_21_simple) +{ + using T = flx::floatx<2, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_22_simple) +{ + using T = flx::floatx<2, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 2.99999809265136718750); +} + +TEST(FloatxOperationsTest, DIV_2_23_simple) +{ + using T = flx::floatx<2, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 2.99999904632568359375); +} + +TEST(FloatxOperationsTest, DIV_2_24_simple) +{ + using T = flx::floatx<2, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_25_simple) +{ + using T = flx::floatx<2, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000029802322387695); +} + +TEST(FloatxOperationsTest, DIV_2_26_simple) +{ + using T = flx::floatx<2, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000014901161193848); +} + +TEST(FloatxOperationsTest, DIV_2_27_simple) +{ + using T = flx::floatx<2, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_28_simple) +{ + using T = flx::floatx<2, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 2.99999997019767761230); +} + +TEST(FloatxOperationsTest, DIV_2_29_simple) +{ + using T = flx::floatx<2, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 2.99999998509883880615); +} + +TEST(FloatxOperationsTest, DIV_2_30_simple) +{ + using T = flx::floatx<2, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_31_simple) +{ + using T = flx::floatx<2, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000372529029846); +} + +TEST(FloatxOperationsTest, DIV_2_32_simple) +{ + using T = flx::floatx<2, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000186264514923); +} + +TEST(FloatxOperationsTest, DIV_2_33_simple) +{ + using T = flx::floatx<2, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_34_simple) +{ + using T = flx::floatx<2, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 2.99999999953433871269); +} + +TEST(FloatxOperationsTest, DIV_2_35_simple) +{ + using T = flx::floatx<2, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 2.99999999976716935635); +} + +TEST(FloatxOperationsTest, DIV_2_36_simple) +{ + using T = flx::floatx<2, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_37_simple) +{ + using T = flx::floatx<2, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000005820766091); +} + +TEST(FloatxOperationsTest, DIV_2_38_simple) +{ + using T = flx::floatx<2, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000002910383046); +} + +TEST(FloatxOperationsTest, DIV_2_39_simple) +{ + using T = flx::floatx<2, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_40_simple) +{ + using T = flx::floatx<2, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 2.99999999999272404239); +} + +TEST(FloatxOperationsTest, DIV_2_41_simple) +{ + using T = flx::floatx<2, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 2.99999999999636202119); +} + +TEST(FloatxOperationsTest, DIV_2_42_simple) +{ + using T = flx::floatx<2, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_43_simple) +{ + using T = flx::floatx<2, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000090949470); +} + +TEST(FloatxOperationsTest, DIV_2_44_simple) +{ + using T = flx::floatx<2, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000045474735); +} + +TEST(FloatxOperationsTest, DIV_2_45_simple) +{ + using T = flx::floatx<2, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_46_simple) +{ + using T = flx::floatx<2, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 2.99999999999988631316); +} + +TEST(FloatxOperationsTest, DIV_2_47_simple) +{ + using T = flx::floatx<2, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 2.99999999999994315658); +} + +TEST(FloatxOperationsTest, DIV_2_48_simple) +{ + using T = flx::floatx<2, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_49_simple) +{ + using T = flx::floatx<2, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000001421085); +} + +TEST(FloatxOperationsTest, DIV_2_50_simple) +{ + using T = flx::floatx<2, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000000710543); +} + +TEST(FloatxOperationsTest, DIV_2_51_simple) +{ + using T = flx::floatx<2, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_2_52_simple) +{ + using T = flx::floatx<2, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 2.99999999999999822364); +} + +TEST(FloatxOperationsTest, DIV_3_1_simple) +{ + using T = flx::floatx<3, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_2_simple) +{ + using T = flx::floatx<3, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 2.50000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_3_simple) +{ + using T = flx::floatx<3, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 2.75000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_4_simple) +{ + using T = flx::floatx<3, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_5_simple) +{ + using T = flx::floatx<3, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.06250000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_6_simple) +{ + using T = flx::floatx<3, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.03125000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_7_simple) +{ + using T = flx::floatx<3, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_8_simple) +{ + using T = flx::floatx<3, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 2.99218750000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_9_simple) +{ + using T = flx::floatx<3, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 2.99609375000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_10_simple) +{ + using T = flx::floatx<3, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_11_simple) +{ + using T = flx::floatx<3, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00097656250000000000); +} + +TEST(FloatxOperationsTest, DIV_3_12_simple) +{ + using T = flx::floatx<3, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00048828125000000000); +} + +TEST(FloatxOperationsTest, DIV_3_13_simple) +{ + using T = flx::floatx<3, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_14_simple) +{ + using T = flx::floatx<3, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 2.99987792968750000000); +} + +TEST(FloatxOperationsTest, DIV_3_15_simple) +{ + using T = flx::floatx<3, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 2.99993896484375000000); +} + +TEST(FloatxOperationsTest, DIV_3_16_simple) +{ + using T = flx::floatx<3, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_17_simple) +{ + using T = flx::floatx<3, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00001525878906250000); +} + +TEST(FloatxOperationsTest, DIV_3_18_simple) +{ + using T = flx::floatx<3, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00000762939453125000); +} + +TEST(FloatxOperationsTest, DIV_3_19_simple) +{ + using T = flx::floatx<3, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_20_simple) +{ + using T = flx::floatx<3, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 2.99999809265136718750); +} + +TEST(FloatxOperationsTest, DIV_3_21_simple) +{ + using T = flx::floatx<3, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 2.99999904632568359375); +} + +TEST(FloatxOperationsTest, DIV_3_22_simple) +{ + using T = flx::floatx<3, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_23_simple) +{ + using T = flx::floatx<3, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000023841857910156); +} + +TEST(FloatxOperationsTest, DIV_3_24_simple) +{ + using T = flx::floatx<3, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000011920928955078); +} + +TEST(FloatxOperationsTest, DIV_3_25_simple) +{ + using T = flx::floatx<3, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_26_simple) +{ + using T = flx::floatx<3, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 2.99999997019767761230); +} + +TEST(FloatxOperationsTest, DIV_3_27_simple) +{ + using T = flx::floatx<3, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 2.99999998509883880615); +} + +TEST(FloatxOperationsTest, DIV_3_28_simple) +{ + using T = flx::floatx<3, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_29_simple) +{ + using T = flx::floatx<3, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000372529029846); +} + +TEST(FloatxOperationsTest, DIV_3_30_simple) +{ + using T = flx::floatx<3, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000186264514923); +} + +TEST(FloatxOperationsTest, DIV_3_31_simple) +{ + using T = flx::floatx<3, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_32_simple) +{ + using T = flx::floatx<3, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 2.99999999953433871269); +} + +TEST(FloatxOperationsTest, DIV_3_33_simple) +{ + using T = flx::floatx<3, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 2.99999999976716935635); +} + +TEST(FloatxOperationsTest, DIV_3_34_simple) +{ + using T = flx::floatx<3, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_35_simple) +{ + using T = flx::floatx<3, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000005820766091); +} + +TEST(FloatxOperationsTest, DIV_3_36_simple) +{ + using T = flx::floatx<3, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000002910383046); +} + +TEST(FloatxOperationsTest, DIV_3_37_simple) +{ + using T = flx::floatx<3, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_38_simple) +{ + using T = flx::floatx<3, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 2.99999999999272404239); +} + +TEST(FloatxOperationsTest, DIV_3_39_simple) +{ + using T = flx::floatx<3, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 2.99999999999636202119); +} + +TEST(FloatxOperationsTest, DIV_3_40_simple) +{ + using T = flx::floatx<3, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_41_simple) +{ + using T = flx::floatx<3, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000090949470); +} + +TEST(FloatxOperationsTest, DIV_3_42_simple) +{ + using T = flx::floatx<3, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000045474735); +} + +TEST(FloatxOperationsTest, DIV_3_43_simple) +{ + using T = flx::floatx<3, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_44_simple) +{ + using T = flx::floatx<3, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 2.99999999999988631316); +} + +TEST(FloatxOperationsTest, DIV_3_45_simple) +{ + using T = flx::floatx<3, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 2.99999999999994315658); +} + +TEST(FloatxOperationsTest, DIV_3_46_simple) +{ + using T = flx::floatx<3, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_47_simple) +{ + using T = flx::floatx<3, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000001421085); +} + +TEST(FloatxOperationsTest, DIV_3_48_simple) +{ + using T = flx::floatx<3, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000000710543); +} + +TEST(FloatxOperationsTest, DIV_3_49_simple) +{ + using T = flx::floatx<3, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_3_50_simple) +{ + using T = flx::floatx<3, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 2.99999999999999822364); +} + +TEST(FloatxOperationsTest, DIV_3_51_simple) +{ + using T = flx::floatx<3, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 2.99999999999999822364); +} + +TEST(FloatxOperationsTest, DIV_3_52_simple) +{ + using T = flx::floatx<3, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_1_simple) +{ + using T = flx::floatx<4, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_2_simple) +{ + using T = flx::floatx<4, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_3_simple) +{ + using T = flx::floatx<4, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.25000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_4_simple) +{ + using T = flx::floatx<4, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_5_simple) +{ + using T = flx::floatx<4, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_6_simple) +{ + using T = flx::floatx<4, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 2.96875000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_7_simple) +{ + using T = flx::floatx<4, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_8_simple) +{ + using T = flx::floatx<4, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_9_simple) +{ + using T = flx::floatx<4, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00390625000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_10_simple) +{ + using T = flx::floatx<4, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_11_simple) +{ + using T = flx::floatx<4, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_12_simple) +{ + using T = flx::floatx<4, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 2.99951171875000000000); +} + +TEST(FloatxOperationsTest, DIV_4_13_simple) +{ + using T = flx::floatx<4, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_14_simple) +{ + using T = flx::floatx<4, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_15_simple) +{ + using T = flx::floatx<4, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00006103515625000000); +} + +TEST(FloatxOperationsTest, DIV_4_16_simple) +{ + using T = flx::floatx<4, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_17_simple) +{ + using T = flx::floatx<4, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_18_simple) +{ + using T = flx::floatx<4, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 2.99999237060546875000); +} + +TEST(FloatxOperationsTest, DIV_4_19_simple) +{ + using T = flx::floatx<4, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_20_simple) +{ + using T = flx::floatx<4, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_21_simple) +{ + using T = flx::floatx<4, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000095367431640625); +} + +TEST(FloatxOperationsTest, DIV_4_22_simple) +{ + using T = flx::floatx<4, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_23_simple) +{ + using T = flx::floatx<4, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_24_simple) +{ + using T = flx::floatx<4, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 2.99999988079071044922); +} + +TEST(FloatxOperationsTest, DIV_4_25_simple) +{ + using T = flx::floatx<4, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_26_simple) +{ + using T = flx::floatx<4, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_27_simple) +{ + using T = flx::floatx<4, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000001490116119385); +} + +TEST(FloatxOperationsTest, DIV_4_28_simple) +{ + using T = flx::floatx<4, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_29_simple) +{ + using T = flx::floatx<4, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_30_simple) +{ + using T = flx::floatx<4, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 2.99999999813735485077); +} + +TEST(FloatxOperationsTest, DIV_4_31_simple) +{ + using T = flx::floatx<4, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_32_simple) +{ + using T = flx::floatx<4, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_33_simple) +{ + using T = flx::floatx<4, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000023283064365); +} + +TEST(FloatxOperationsTest, DIV_4_34_simple) +{ + using T = flx::floatx<4, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_35_simple) +{ + using T = flx::floatx<4, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_36_simple) +{ + using T = flx::floatx<4, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 2.99999999997089616954); +} + +TEST(FloatxOperationsTest, DIV_4_37_simple) +{ + using T = flx::floatx<4, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_38_simple) +{ + using T = flx::floatx<4, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_39_simple) +{ + using T = flx::floatx<4, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000363797881); +} + +TEST(FloatxOperationsTest, DIV_4_40_simple) +{ + using T = flx::floatx<4, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_41_simple) +{ + using T = flx::floatx<4, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_42_simple) +{ + using T = flx::floatx<4, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 2.99999999999954525265); +} + +TEST(FloatxOperationsTest, DIV_4_43_simple) +{ + using T = flx::floatx<4, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_44_simple) +{ + using T = flx::floatx<4, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_45_simple) +{ + using T = flx::floatx<4, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000005684342); +} + +TEST(FloatxOperationsTest, DIV_4_46_simple) +{ + using T = flx::floatx<4, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_47_simple) +{ + using T = flx::floatx<4, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_48_simple) +{ + using T = flx::floatx<4, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 2.99999999999999289457); +} + +TEST(FloatxOperationsTest, DIV_4_49_simple) +{ + using T = flx::floatx<4, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_50_simple) +{ + using T = flx::floatx<4, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_51_simple) +{ + using T = flx::floatx<4, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_4_52_simple) +{ + using T = flx::floatx<4, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_1_simple) +{ + using T = flx::floatx<5, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_2_simple) +{ + using T = flx::floatx<5, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_3_simple) +{ + using T = flx::floatx<5, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.25000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_4_simple) +{ + using T = flx::floatx<5, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_5_simple) +{ + using T = flx::floatx<5, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_6_simple) +{ + using T = flx::floatx<5, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 2.96875000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_7_simple) +{ + using T = flx::floatx<5, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_8_simple) +{ + using T = flx::floatx<5, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_9_simple) +{ + using T = flx::floatx<5, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00390625000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_10_simple) +{ + using T = flx::floatx<5, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_11_simple) +{ + using T = flx::floatx<5, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_12_simple) +{ + using T = flx::floatx<5, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 2.99951171875000000000); +} + +TEST(FloatxOperationsTest, DIV_5_13_simple) +{ + using T = flx::floatx<5, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_14_simple) +{ + using T = flx::floatx<5, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_15_simple) +{ + using T = flx::floatx<5, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00006103515625000000); +} + +TEST(FloatxOperationsTest, DIV_5_16_simple) +{ + using T = flx::floatx<5, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_17_simple) +{ + using T = flx::floatx<5, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_18_simple) +{ + using T = flx::floatx<5, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 2.99999237060546875000); +} + +TEST(FloatxOperationsTest, DIV_5_19_simple) +{ + using T = flx::floatx<5, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_20_simple) +{ + using T = flx::floatx<5, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_21_simple) +{ + using T = flx::floatx<5, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000095367431640625); +} + +TEST(FloatxOperationsTest, DIV_5_22_simple) +{ + using T = flx::floatx<5, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_23_simple) +{ + using T = flx::floatx<5, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_24_simple) +{ + using T = flx::floatx<5, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 2.99999988079071044922); +} + +TEST(FloatxOperationsTest, DIV_5_25_simple) +{ + using T = flx::floatx<5, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_26_simple) +{ + using T = flx::floatx<5, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_27_simple) +{ + using T = flx::floatx<5, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000001490116119385); +} + +TEST(FloatxOperationsTest, DIV_5_28_simple) +{ + using T = flx::floatx<5, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_29_simple) +{ + using T = flx::floatx<5, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_30_simple) +{ + using T = flx::floatx<5, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 2.99999999813735485077); +} + +TEST(FloatxOperationsTest, DIV_5_31_simple) +{ + using T = flx::floatx<5, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_32_simple) +{ + using T = flx::floatx<5, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_33_simple) +{ + using T = flx::floatx<5, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000023283064365); +} + +TEST(FloatxOperationsTest, DIV_5_34_simple) +{ + using T = flx::floatx<5, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_35_simple) +{ + using T = flx::floatx<5, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_36_simple) +{ + using T = flx::floatx<5, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 2.99999999997089616954); +} + +TEST(FloatxOperationsTest, DIV_5_37_simple) +{ + using T = flx::floatx<5, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_38_simple) +{ + using T = flx::floatx<5, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_39_simple) +{ + using T = flx::floatx<5, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000363797881); +} + +TEST(FloatxOperationsTest, DIV_5_40_simple) +{ + using T = flx::floatx<5, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_41_simple) +{ + using T = flx::floatx<5, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_42_simple) +{ + using T = flx::floatx<5, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 2.99999999999954525265); +} + +TEST(FloatxOperationsTest, DIV_5_43_simple) +{ + using T = flx::floatx<5, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_44_simple) +{ + using T = flx::floatx<5, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_45_simple) +{ + using T = flx::floatx<5, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000005684342); +} + +TEST(FloatxOperationsTest, DIV_5_46_simple) +{ + using T = flx::floatx<5, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_47_simple) +{ + using T = flx::floatx<5, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_48_simple) +{ + using T = flx::floatx<5, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 2.99999999999999289457); +} + +TEST(FloatxOperationsTest, DIV_5_49_simple) +{ + using T = flx::floatx<5, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_50_simple) +{ + using T = flx::floatx<5, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_51_simple) +{ + using T = flx::floatx<5, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_5_52_simple) +{ + using T = flx::floatx<5, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_1_simple) +{ + using T = flx::floatx<6, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_2_simple) +{ + using T = flx::floatx<6, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_3_simple) +{ + using T = flx::floatx<6, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.25000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_4_simple) +{ + using T = flx::floatx<6, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_5_simple) +{ + using T = flx::floatx<6, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_6_simple) +{ + using T = flx::floatx<6, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 2.96875000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_7_simple) +{ + using T = flx::floatx<6, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_8_simple) +{ + using T = flx::floatx<6, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_9_simple) +{ + using T = flx::floatx<6, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00390625000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_10_simple) +{ + using T = flx::floatx<6, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_11_simple) +{ + using T = flx::floatx<6, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_12_simple) +{ + using T = flx::floatx<6, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 2.99951171875000000000); +} + +TEST(FloatxOperationsTest, DIV_6_13_simple) +{ + using T = flx::floatx<6, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_14_simple) +{ + using T = flx::floatx<6, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_15_simple) +{ + using T = flx::floatx<6, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00006103515625000000); +} + +TEST(FloatxOperationsTest, DIV_6_16_simple) +{ + using T = flx::floatx<6, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_17_simple) +{ + using T = flx::floatx<6, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_18_simple) +{ + using T = flx::floatx<6, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 2.99999237060546875000); +} + +TEST(FloatxOperationsTest, DIV_6_19_simple) +{ + using T = flx::floatx<6, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_20_simple) +{ + using T = flx::floatx<6, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_21_simple) +{ + using T = flx::floatx<6, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000095367431640625); +} + +TEST(FloatxOperationsTest, DIV_6_22_simple) +{ + using T = flx::floatx<6, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_23_simple) +{ + using T = flx::floatx<6, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_24_simple) +{ + using T = flx::floatx<6, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 2.99999988079071044922); +} + +TEST(FloatxOperationsTest, DIV_6_25_simple) +{ + using T = flx::floatx<6, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_26_simple) +{ + using T = flx::floatx<6, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_27_simple) +{ + using T = flx::floatx<6, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000001490116119385); +} + +TEST(FloatxOperationsTest, DIV_6_28_simple) +{ + using T = flx::floatx<6, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_29_simple) +{ + using T = flx::floatx<6, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_30_simple) +{ + using T = flx::floatx<6, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 2.99999999813735485077); +} + +TEST(FloatxOperationsTest, DIV_6_31_simple) +{ + using T = flx::floatx<6, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_32_simple) +{ + using T = flx::floatx<6, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_33_simple) +{ + using T = flx::floatx<6, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000023283064365); +} + +TEST(FloatxOperationsTest, DIV_6_34_simple) +{ + using T = flx::floatx<6, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_35_simple) +{ + using T = flx::floatx<6, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_36_simple) +{ + using T = flx::floatx<6, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 2.99999999997089616954); +} + +TEST(FloatxOperationsTest, DIV_6_37_simple) +{ + using T = flx::floatx<6, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_38_simple) +{ + using T = flx::floatx<6, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_39_simple) +{ + using T = flx::floatx<6, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000363797881); +} + +TEST(FloatxOperationsTest, DIV_6_40_simple) +{ + using T = flx::floatx<6, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_41_simple) +{ + using T = flx::floatx<6, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_42_simple) +{ + using T = flx::floatx<6, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 2.99999999999954525265); +} + +TEST(FloatxOperationsTest, DIV_6_43_simple) +{ + using T = flx::floatx<6, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_44_simple) +{ + using T = flx::floatx<6, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_45_simple) +{ + using T = flx::floatx<6, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000005684342); +} + +TEST(FloatxOperationsTest, DIV_6_46_simple) +{ + using T = flx::floatx<6, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_47_simple) +{ + using T = flx::floatx<6, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_48_simple) +{ + using T = flx::floatx<6, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 2.99999999999999289457); +} + +TEST(FloatxOperationsTest, DIV_6_49_simple) +{ + using T = flx::floatx<6, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_50_simple) +{ + using T = flx::floatx<6, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_51_simple) +{ + using T = flx::floatx<6, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_6_52_simple) +{ + using T = flx::floatx<6, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_1_simple) +{ + using T = flx::floatx<7, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_2_simple) +{ + using T = flx::floatx<7, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_3_simple) +{ + using T = flx::floatx<7, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.25000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_4_simple) +{ + using T = flx::floatx<7, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_5_simple) +{ + using T = flx::floatx<7, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_6_simple) +{ + using T = flx::floatx<7, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 2.96875000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_7_simple) +{ + using T = flx::floatx<7, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_8_simple) +{ + using T = flx::floatx<7, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_9_simple) +{ + using T = flx::floatx<7, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00390625000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_10_simple) +{ + using T = flx::floatx<7, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_11_simple) +{ + using T = flx::floatx<7, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_12_simple) +{ + using T = flx::floatx<7, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 2.99951171875000000000); +} + +TEST(FloatxOperationsTest, DIV_7_13_simple) +{ + using T = flx::floatx<7, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_14_simple) +{ + using T = flx::floatx<7, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_15_simple) +{ + using T = flx::floatx<7, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00006103515625000000); +} + +TEST(FloatxOperationsTest, DIV_7_16_simple) +{ + using T = flx::floatx<7, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_17_simple) +{ + using T = flx::floatx<7, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_18_simple) +{ + using T = flx::floatx<7, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 2.99999237060546875000); +} + +TEST(FloatxOperationsTest, DIV_7_19_simple) +{ + using T = flx::floatx<7, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_20_simple) +{ + using T = flx::floatx<7, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_21_simple) +{ + using T = flx::floatx<7, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000095367431640625); +} + +TEST(FloatxOperationsTest, DIV_7_22_simple) +{ + using T = flx::floatx<7, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_23_simple) +{ + using T = flx::floatx<7, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_24_simple) +{ + using T = flx::floatx<7, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 2.99999988079071044922); +} + +TEST(FloatxOperationsTest, DIV_7_25_simple) +{ + using T = flx::floatx<7, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_26_simple) +{ + using T = flx::floatx<7, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_27_simple) +{ + using T = flx::floatx<7, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000001490116119385); +} + +TEST(FloatxOperationsTest, DIV_7_28_simple) +{ + using T = flx::floatx<7, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_29_simple) +{ + using T = flx::floatx<7, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_30_simple) +{ + using T = flx::floatx<7, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 2.99999999813735485077); +} + +TEST(FloatxOperationsTest, DIV_7_31_simple) +{ + using T = flx::floatx<7, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_32_simple) +{ + using T = flx::floatx<7, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_33_simple) +{ + using T = flx::floatx<7, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000023283064365); +} + +TEST(FloatxOperationsTest, DIV_7_34_simple) +{ + using T = flx::floatx<7, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_35_simple) +{ + using T = flx::floatx<7, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_36_simple) +{ + using T = flx::floatx<7, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 2.99999999997089616954); +} + +TEST(FloatxOperationsTest, DIV_7_37_simple) +{ + using T = flx::floatx<7, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_38_simple) +{ + using T = flx::floatx<7, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_39_simple) +{ + using T = flx::floatx<7, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000363797881); +} + +TEST(FloatxOperationsTest, DIV_7_40_simple) +{ + using T = flx::floatx<7, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_41_simple) +{ + using T = flx::floatx<7, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_42_simple) +{ + using T = flx::floatx<7, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 2.99999999999954525265); +} + +TEST(FloatxOperationsTest, DIV_7_43_simple) +{ + using T = flx::floatx<7, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_44_simple) +{ + using T = flx::floatx<7, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_45_simple) +{ + using T = flx::floatx<7, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000005684342); +} + +TEST(FloatxOperationsTest, DIV_7_46_simple) +{ + using T = flx::floatx<7, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_47_simple) +{ + using T = flx::floatx<7, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_48_simple) +{ + using T = flx::floatx<7, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 2.99999999999999289457); +} + +TEST(FloatxOperationsTest, DIV_7_49_simple) +{ + using T = flx::floatx<7, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_50_simple) +{ + using T = flx::floatx<7, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_51_simple) +{ + using T = flx::floatx<7, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_7_52_simple) +{ + using T = flx::floatx<7, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_1_simple) +{ + using T = flx::floatx<8, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_2_simple) +{ + using T = flx::floatx<8, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_3_simple) +{ + using T = flx::floatx<8, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.25000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_4_simple) +{ + using T = flx::floatx<8, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_5_simple) +{ + using T = flx::floatx<8, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_6_simple) +{ + using T = flx::floatx<8, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 2.96875000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_7_simple) +{ + using T = flx::floatx<8, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_8_simple) +{ + using T = flx::floatx<8, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_9_simple) +{ + using T = flx::floatx<8, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00390625000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_10_simple) +{ + using T = flx::floatx<8, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_11_simple) +{ + using T = flx::floatx<8, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_12_simple) +{ + using T = flx::floatx<8, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 2.99951171875000000000); +} + +TEST(FloatxOperationsTest, DIV_8_13_simple) +{ + using T = flx::floatx<8, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_14_simple) +{ + using T = flx::floatx<8, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_15_simple) +{ + using T = flx::floatx<8, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00006103515625000000); +} + +TEST(FloatxOperationsTest, DIV_8_16_simple) +{ + using T = flx::floatx<8, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_17_simple) +{ + using T = flx::floatx<8, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_18_simple) +{ + using T = flx::floatx<8, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 2.99999237060546875000); +} + +TEST(FloatxOperationsTest, DIV_8_19_simple) +{ + using T = flx::floatx<8, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_20_simple) +{ + using T = flx::floatx<8, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_21_simple) +{ + using T = flx::floatx<8, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000095367431640625); +} + +TEST(FloatxOperationsTest, DIV_8_22_simple) +{ + using T = flx::floatx<8, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_23_simple) +{ + using T = flx::floatx<8, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_24_simple) +{ + using T = flx::floatx<8, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 2.99999988079071044922); +} + +TEST(FloatxOperationsTest, DIV_8_25_simple) +{ + using T = flx::floatx<8, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_26_simple) +{ + using T = flx::floatx<8, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_27_simple) +{ + using T = flx::floatx<8, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000001490116119385); +} + +TEST(FloatxOperationsTest, DIV_8_28_simple) +{ + using T = flx::floatx<8, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_29_simple) +{ + using T = flx::floatx<8, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_30_simple) +{ + using T = flx::floatx<8, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 2.99999999813735485077); +} + +TEST(FloatxOperationsTest, DIV_8_31_simple) +{ + using T = flx::floatx<8, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_32_simple) +{ + using T = flx::floatx<8, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_33_simple) +{ + using T = flx::floatx<8, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000023283064365); +} + +TEST(FloatxOperationsTest, DIV_8_34_simple) +{ + using T = flx::floatx<8, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_35_simple) +{ + using T = flx::floatx<8, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_36_simple) +{ + using T = flx::floatx<8, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 2.99999999997089616954); +} + +TEST(FloatxOperationsTest, DIV_8_37_simple) +{ + using T = flx::floatx<8, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_38_simple) +{ + using T = flx::floatx<8, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_39_simple) +{ + using T = flx::floatx<8, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000363797881); +} + +TEST(FloatxOperationsTest, DIV_8_40_simple) +{ + using T = flx::floatx<8, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_41_simple) +{ + using T = flx::floatx<8, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_42_simple) +{ + using T = flx::floatx<8, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 2.99999999999954525265); +} + +TEST(FloatxOperationsTest, DIV_8_43_simple) +{ + using T = flx::floatx<8, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_44_simple) +{ + using T = flx::floatx<8, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_45_simple) +{ + using T = flx::floatx<8, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000005684342); +} + +TEST(FloatxOperationsTest, DIV_8_46_simple) +{ + using T = flx::floatx<8, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_47_simple) +{ + using T = flx::floatx<8, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_48_simple) +{ + using T = flx::floatx<8, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 2.99999999999999289457); +} + +TEST(FloatxOperationsTest, DIV_8_49_simple) +{ + using T = flx::floatx<8, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_50_simple) +{ + using T = flx::floatx<8, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_51_simple) +{ + using T = flx::floatx<8, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_8_52_simple) +{ + using T = flx::floatx<8, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_1_simple) +{ + using T = flx::floatx<9, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_2_simple) +{ + using T = flx::floatx<9, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_3_simple) +{ + using T = flx::floatx<9, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.25000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_4_simple) +{ + using T = flx::floatx<9, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_5_simple) +{ + using T = flx::floatx<9, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_6_simple) +{ + using T = flx::floatx<9, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 2.96875000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_7_simple) +{ + using T = flx::floatx<9, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_8_simple) +{ + using T = flx::floatx<9, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_9_simple) +{ + using T = flx::floatx<9, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00390625000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_10_simple) +{ + using T = flx::floatx<9, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_11_simple) +{ + using T = flx::floatx<9, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_12_simple) +{ + using T = flx::floatx<9, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 2.99951171875000000000); +} + +TEST(FloatxOperationsTest, DIV_9_13_simple) +{ + using T = flx::floatx<9, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_14_simple) +{ + using T = flx::floatx<9, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_15_simple) +{ + using T = flx::floatx<9, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00006103515625000000); +} + +TEST(FloatxOperationsTest, DIV_9_16_simple) +{ + using T = flx::floatx<9, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_17_simple) +{ + using T = flx::floatx<9, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_18_simple) +{ + using T = flx::floatx<9, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 2.99999237060546875000); +} + +TEST(FloatxOperationsTest, DIV_9_19_simple) +{ + using T = flx::floatx<9, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_20_simple) +{ + using T = flx::floatx<9, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_21_simple) +{ + using T = flx::floatx<9, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000095367431640625); +} + +TEST(FloatxOperationsTest, DIV_9_22_simple) +{ + using T = flx::floatx<9, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_23_simple) +{ + using T = flx::floatx<9, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_24_simple) +{ + using T = flx::floatx<9, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 2.99999988079071044922); +} + +TEST(FloatxOperationsTest, DIV_9_25_simple) +{ + using T = flx::floatx<9, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_26_simple) +{ + using T = flx::floatx<9, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_27_simple) +{ + using T = flx::floatx<9, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000001490116119385); +} + +TEST(FloatxOperationsTest, DIV_9_28_simple) +{ + using T = flx::floatx<9, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_29_simple) +{ + using T = flx::floatx<9, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_30_simple) +{ + using T = flx::floatx<9, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 2.99999999813735485077); +} + +TEST(FloatxOperationsTest, DIV_9_31_simple) +{ + using T = flx::floatx<9, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_32_simple) +{ + using T = flx::floatx<9, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_33_simple) +{ + using T = flx::floatx<9, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000023283064365); +} + +TEST(FloatxOperationsTest, DIV_9_34_simple) +{ + using T = flx::floatx<9, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_35_simple) +{ + using T = flx::floatx<9, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_36_simple) +{ + using T = flx::floatx<9, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 2.99999999997089616954); +} + +TEST(FloatxOperationsTest, DIV_9_37_simple) +{ + using T = flx::floatx<9, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_38_simple) +{ + using T = flx::floatx<9, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_39_simple) +{ + using T = flx::floatx<9, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000363797881); +} + +TEST(FloatxOperationsTest, DIV_9_40_simple) +{ + using T = flx::floatx<9, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_41_simple) +{ + using T = flx::floatx<9, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_42_simple) +{ + using T = flx::floatx<9, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 2.99999999999954525265); +} + +TEST(FloatxOperationsTest, DIV_9_43_simple) +{ + using T = flx::floatx<9, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_44_simple) +{ + using T = flx::floatx<9, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_45_simple) +{ + using T = flx::floatx<9, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000005684342); +} + +TEST(FloatxOperationsTest, DIV_9_46_simple) +{ + using T = flx::floatx<9, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_47_simple) +{ + using T = flx::floatx<9, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_48_simple) +{ + using T = flx::floatx<9, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 2.99999999999999289457); +} + +TEST(FloatxOperationsTest, DIV_9_49_simple) +{ + using T = flx::floatx<9, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_50_simple) +{ + using T = flx::floatx<9, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_51_simple) +{ + using T = flx::floatx<9, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_9_52_simple) +{ + using T = flx::floatx<9, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_1_simple) +{ + using T = flx::floatx<10, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_2_simple) +{ + using T = flx::floatx<10, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_3_simple) +{ + using T = flx::floatx<10, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.25000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_4_simple) +{ + using T = flx::floatx<10, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_5_simple) +{ + using T = flx::floatx<10, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_6_simple) +{ + using T = flx::floatx<10, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 2.96875000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_7_simple) +{ + using T = flx::floatx<10, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_8_simple) +{ + using T = flx::floatx<10, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_9_simple) +{ + using T = flx::floatx<10, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00390625000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_10_simple) +{ + using T = flx::floatx<10, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_11_simple) +{ + using T = flx::floatx<10, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_12_simple) +{ + using T = flx::floatx<10, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 2.99951171875000000000); +} + +TEST(FloatxOperationsTest, DIV_10_13_simple) +{ + using T = flx::floatx<10, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_14_simple) +{ + using T = flx::floatx<10, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_15_simple) +{ + using T = flx::floatx<10, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00006103515625000000); +} + +TEST(FloatxOperationsTest, DIV_10_16_simple) +{ + using T = flx::floatx<10, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_17_simple) +{ + using T = flx::floatx<10, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_18_simple) +{ + using T = flx::floatx<10, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 2.99999237060546875000); +} + +TEST(FloatxOperationsTest, DIV_10_19_simple) +{ + using T = flx::floatx<10, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_20_simple) +{ + using T = flx::floatx<10, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_21_simple) +{ + using T = flx::floatx<10, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000095367431640625); +} + +TEST(FloatxOperationsTest, DIV_10_22_simple) +{ + using T = flx::floatx<10, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_23_simple) +{ + using T = flx::floatx<10, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_24_simple) +{ + using T = flx::floatx<10, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 2.99999988079071044922); +} + +TEST(FloatxOperationsTest, DIV_10_25_simple) +{ + using T = flx::floatx<10, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_26_simple) +{ + using T = flx::floatx<10, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_27_simple) +{ + using T = flx::floatx<10, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000001490116119385); +} + +TEST(FloatxOperationsTest, DIV_10_28_simple) +{ + using T = flx::floatx<10, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_29_simple) +{ + using T = flx::floatx<10, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_30_simple) +{ + using T = flx::floatx<10, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 2.99999999813735485077); +} + +TEST(FloatxOperationsTest, DIV_10_31_simple) +{ + using T = flx::floatx<10, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_32_simple) +{ + using T = flx::floatx<10, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_33_simple) +{ + using T = flx::floatx<10, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000023283064365); +} + +TEST(FloatxOperationsTest, DIV_10_34_simple) +{ + using T = flx::floatx<10, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_35_simple) +{ + using T = flx::floatx<10, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_36_simple) +{ + using T = flx::floatx<10, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 2.99999999997089616954); +} + +TEST(FloatxOperationsTest, DIV_10_37_simple) +{ + using T = flx::floatx<10, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_38_simple) +{ + using T = flx::floatx<10, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_39_simple) +{ + using T = flx::floatx<10, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000363797881); +} + +TEST(FloatxOperationsTest, DIV_10_40_simple) +{ + using T = flx::floatx<10, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_41_simple) +{ + using T = flx::floatx<10, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_42_simple) +{ + using T = flx::floatx<10, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 2.99999999999954525265); +} + +TEST(FloatxOperationsTest, DIV_10_43_simple) +{ + using T = flx::floatx<10, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_44_simple) +{ + using T = flx::floatx<10, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_45_simple) +{ + using T = flx::floatx<10, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000005684342); +} + +TEST(FloatxOperationsTest, DIV_10_46_simple) +{ + using T = flx::floatx<10, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_47_simple) +{ + using T = flx::floatx<10, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_48_simple) +{ + using T = flx::floatx<10, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 2.99999999999999289457); +} + +TEST(FloatxOperationsTest, DIV_10_49_simple) +{ + using T = flx::floatx<10, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_50_simple) +{ + using T = flx::floatx<10, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_51_simple) +{ + using T = flx::floatx<10, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_10_52_simple) +{ + using T = flx::floatx<10, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_1_simple) +{ + using T = flx::floatx<11, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_2_simple) +{ + using T = flx::floatx<11, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_3_simple) +{ + using T = flx::floatx<11, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.25000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_4_simple) +{ + using T = flx::floatx<11, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_5_simple) +{ + using T = flx::floatx<11, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_6_simple) +{ + using T = flx::floatx<11, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 2.96875000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_7_simple) +{ + using T = flx::floatx<11, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_8_simple) +{ + using T = flx::floatx<11, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_9_simple) +{ + using T = flx::floatx<11, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00390625000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_10_simple) +{ + using T = flx::floatx<11, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_11_simple) +{ + using T = flx::floatx<11, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_12_simple) +{ + using T = flx::floatx<11, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 2.99951171875000000000); +} + +TEST(FloatxOperationsTest, DIV_11_13_simple) +{ + using T = flx::floatx<11, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_14_simple) +{ + using T = flx::floatx<11, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_15_simple) +{ + using T = flx::floatx<11, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00006103515625000000); +} + +TEST(FloatxOperationsTest, DIV_11_16_simple) +{ + using T = flx::floatx<11, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_17_simple) +{ + using T = flx::floatx<11, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_18_simple) +{ + using T = flx::floatx<11, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 2.99999237060546875000); +} + +TEST(FloatxOperationsTest, DIV_11_19_simple) +{ + using T = flx::floatx<11, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_20_simple) +{ + using T = flx::floatx<11, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_21_simple) +{ + using T = flx::floatx<11, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000095367431640625); +} + +TEST(FloatxOperationsTest, DIV_11_22_simple) +{ + using T = flx::floatx<11, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_23_simple) +{ + using T = flx::floatx<11, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_24_simple) +{ + using T = flx::floatx<11, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 2.99999988079071044922); +} + +TEST(FloatxOperationsTest, DIV_11_25_simple) +{ + using T = flx::floatx<11, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_26_simple) +{ + using T = flx::floatx<11, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_27_simple) +{ + using T = flx::floatx<11, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000001490116119385); +} + +TEST(FloatxOperationsTest, DIV_11_28_simple) +{ + using T = flx::floatx<11, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_29_simple) +{ + using T = flx::floatx<11, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_30_simple) +{ + using T = flx::floatx<11, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 2.99999999813735485077); +} + +TEST(FloatxOperationsTest, DIV_11_31_simple) +{ + using T = flx::floatx<11, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_32_simple) +{ + using T = flx::floatx<11, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_33_simple) +{ + using T = flx::floatx<11, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000023283064365); +} + +TEST(FloatxOperationsTest, DIV_11_34_simple) +{ + using T = flx::floatx<11, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_35_simple) +{ + using T = flx::floatx<11, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_36_simple) +{ + using T = flx::floatx<11, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 2.99999999997089616954); +} + +TEST(FloatxOperationsTest, DIV_11_37_simple) +{ + using T = flx::floatx<11, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_38_simple) +{ + using T = flx::floatx<11, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_39_simple) +{ + using T = flx::floatx<11, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000363797881); +} + +TEST(FloatxOperationsTest, DIV_11_40_simple) +{ + using T = flx::floatx<11, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_41_simple) +{ + using T = flx::floatx<11, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_42_simple) +{ + using T = flx::floatx<11, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 2.99999999999954525265); +} + +TEST(FloatxOperationsTest, DIV_11_43_simple) +{ + using T = flx::floatx<11, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_44_simple) +{ + using T = flx::floatx<11, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_45_simple) +{ + using T = flx::floatx<11, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000005684342); +} + +TEST(FloatxOperationsTest, DIV_11_46_simple) +{ + using T = flx::floatx<11, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_47_simple) +{ + using T = flx::floatx<11, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_48_simple) +{ + using T = flx::floatx<11, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 2.99999999999999289457); +} + +TEST(FloatxOperationsTest, DIV_11_49_simple) +{ + using T = flx::floatx<11, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_50_simple) +{ + using T = flx::floatx<11, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_51_simple) +{ + using T = flx::floatx<11, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + +TEST(FloatxOperationsTest, DIV_11_52_simple) +{ + using T = flx::floatx<11, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a / b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 3.00000000000000000000); +} + + +} // namespace diff --git a/third-party/FloatX/testx/mul_000.cpp b/third-party/FloatX/testx/mul_000.cpp new file mode 100644 index 0000000..95efa64 --- /dev/null +++ b/third-party/FloatX/testx/mul_000.cpp @@ -0,0 +1,6891 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include +#include + +#define nan double(0.0 / 0.0) +#define inf double(1.0 / 0.0) + +namespace { + +TEST(FloatxOperationsTest, MUL_1_1_simple) +{ + using T = flx::floatx<1, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.00000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_EQ(double(c), 0.00000000000000000000); +} + +TEST(FloatxOperationsTest, MUL_1_2_simple) +{ + using T = flx::floatx<1, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.50000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_EQ(double(c), 0.00000000000000000000); +} + +TEST(FloatxOperationsTest, MUL_1_3_simple) +{ + using T = flx::floatx<1, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.25000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_EQ(double(c), 0.00000000000000000000); +} + +TEST(FloatxOperationsTest, MUL_1_4_simple) +{ + using T = flx::floatx<1, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.00000000000000000000); +} + +TEST(FloatxOperationsTest, MUL_1_5_simple) +{ + using T = flx::floatx<1, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.06250000000000000000); +} + +TEST(FloatxOperationsTest, MUL_1_6_simple) +{ + using T = flx::floatx<1, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.03125000000000000000); +} + +TEST(FloatxOperationsTest, MUL_1_7_simple) +{ + using T = flx::floatx<1, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03125000000000000000); +} + +TEST(FloatxOperationsTest, MUL_1_8_simple) +{ + using T = flx::floatx<1, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03906250000000000000); +} + +TEST(FloatxOperationsTest, MUL_1_9_simple) +{ + using T = flx::floatx<1, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03515625000000000000); +} + +TEST(FloatxOperationsTest, MUL_1_10_simple) +{ + using T = flx::floatx<1, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_1_11_simple) +{ + using T = flx::floatx<1, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_1_12_simple) +{ + using T = flx::floatx<1, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_1_13_simple) +{ + using T = flx::floatx<1, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_1_14_simple) +{ + using T = flx::floatx<1, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03698730468750000000); +} + +TEST(FloatxOperationsTest, MUL_1_15_simple) +{ + using T = flx::floatx<1, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_1_16_simple) +{ + using T = flx::floatx<1, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_1_17_simple) +{ + using T = flx::floatx<1, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03703308105468750000); +} + +TEST(FloatxOperationsTest, MUL_1_18_simple) +{ + using T = flx::floatx<1, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704071044921875000); +} + +TEST(FloatxOperationsTest, MUL_1_19_simple) +{ + using T = flx::floatx<1, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_1_20_simple) +{ + using T = flx::floatx<1, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_1_21_simple) +{ + using T = flx::floatx<1, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_1_22_simple) +{ + using T = flx::floatx<1, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_1_23_simple) +{ + using T = flx::floatx<1, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703713417053222656); +} + +TEST(FloatxOperationsTest, MUL_1_24_simple) +{ + using T = flx::floatx<1, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_1_25_simple) +{ + using T = flx::floatx<1, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_1_26_simple) +{ + using T = flx::floatx<1, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703704476356506348); +} + +TEST(FloatxOperationsTest, MUL_1_27_simple) +{ + using T = flx::floatx<1, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703702986240386963); +} + +TEST(FloatxOperationsTest, MUL_1_28_simple) +{ + using T = flx::floatx<1, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_1_29_simple) +{ + using T = flx::floatx<1, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_1_30_simple) +{ + using T = flx::floatx<1, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_1_31_simple) +{ + using T = flx::floatx<1, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_1_32_simple) +{ + using T = flx::floatx<1, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703684732317924); +} + +TEST(FloatxOperationsTest, MUL_1_33_simple) +{ + using T = flx::floatx<1, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_1_34_simple) +{ + using T = flx::floatx<1, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_1_35_simple) +{ + using T = flx::floatx<1, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703702194616199); +} + +TEST(FloatxOperationsTest, MUL_1_36_simple) +{ + using T = flx::floatx<1, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703705104999244); +} + +TEST(FloatxOperationsTest, MUL_1_37_simple) +{ + using T = flx::floatx<1, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_1_38_simple) +{ + using T = flx::floatx<1, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_1_39_simple) +{ + using T = flx::floatx<1, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_1_40_simple) +{ + using T = flx::floatx<1, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_1_41_simple) +{ + using T = flx::floatx<1, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703740757192); +} + +TEST(FloatxOperationsTest, MUL_1_42_simple) +{ + using T = flx::floatx<1, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_1_43_simple) +{ + using T = flx::floatx<1, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_1_44_simple) +{ + using T = flx::floatx<1, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703706651140); +} + +TEST(FloatxOperationsTest, MUL_1_45_simple) +{ + using T = flx::floatx<1, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703700966798); +} + +TEST(FloatxOperationsTest, MUL_1_46_simple) +{ + using T = flx::floatx<1, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_1_47_simple) +{ + using T = flx::floatx<1, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_1_48_simple) +{ + using T = flx::floatx<1, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_1_49_simple) +{ + using T = flx::floatx<1, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_1_50_simple) +{ + using T = flx::floatx<1, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703631334); +} + +TEST(FloatxOperationsTest, MUL_1_51_simple) +{ + using T = flx::floatx<1, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_1_52_simple) +{ + using T = flx::floatx<1, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_2_1_simple) +{ + using T = flx::floatx<2, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.50000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_EQ(double(c), 0.00000000000000000000); +} + +TEST(FloatxOperationsTest, MUL_2_2_simple) +{ + using T = flx::floatx<2, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.25000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_EQ(double(c), 0.00000000000000000000); +} + +TEST(FloatxOperationsTest, MUL_2_3_simple) +{ + using T = flx::floatx<2, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.00000000000000000000); +} + +TEST(FloatxOperationsTest, MUL_2_4_simple) +{ + using T = flx::floatx<2, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.06250000000000000000); +} + +TEST(FloatxOperationsTest, MUL_2_5_simple) +{ + using T = flx::floatx<2, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.03125000000000000000); +} + +TEST(FloatxOperationsTest, MUL_2_6_simple) +{ + using T = flx::floatx<2, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03125000000000000000); +} + +TEST(FloatxOperationsTest, MUL_2_7_simple) +{ + using T = flx::floatx<2, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03906250000000000000); +} + +TEST(FloatxOperationsTest, MUL_2_8_simple) +{ + using T = flx::floatx<2, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03515625000000000000); +} + +TEST(FloatxOperationsTest, MUL_2_9_simple) +{ + using T = flx::floatx<2, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_2_10_simple) +{ + using T = flx::floatx<2, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_2_11_simple) +{ + using T = flx::floatx<2, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_2_12_simple) +{ + using T = flx::floatx<2, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_2_13_simple) +{ + using T = flx::floatx<2, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03698730468750000000); +} + +TEST(FloatxOperationsTest, MUL_2_14_simple) +{ + using T = flx::floatx<2, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_2_15_simple) +{ + using T = flx::floatx<2, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_2_16_simple) +{ + using T = flx::floatx<2, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03703308105468750000); +} + +TEST(FloatxOperationsTest, MUL_2_17_simple) +{ + using T = flx::floatx<2, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704071044921875000); +} + +TEST(FloatxOperationsTest, MUL_2_18_simple) +{ + using T = flx::floatx<2, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_2_19_simple) +{ + using T = flx::floatx<2, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_2_20_simple) +{ + using T = flx::floatx<2, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_2_21_simple) +{ + using T = flx::floatx<2, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_2_22_simple) +{ + using T = flx::floatx<2, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703713417053222656); +} + +TEST(FloatxOperationsTest, MUL_2_23_simple) +{ + using T = flx::floatx<2, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_2_24_simple) +{ + using T = flx::floatx<2, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_2_25_simple) +{ + using T = flx::floatx<2, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703704476356506348); +} + +TEST(FloatxOperationsTest, MUL_2_26_simple) +{ + using T = flx::floatx<2, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703702986240386963); +} + +TEST(FloatxOperationsTest, MUL_2_27_simple) +{ + using T = flx::floatx<2, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_2_28_simple) +{ + using T = flx::floatx<2, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_2_29_simple) +{ + using T = flx::floatx<2, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_2_30_simple) +{ + using T = flx::floatx<2, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_2_31_simple) +{ + using T = flx::floatx<2, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703684732317924); +} + +TEST(FloatxOperationsTest, MUL_2_32_simple) +{ + using T = flx::floatx<2, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_2_33_simple) +{ + using T = flx::floatx<2, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_2_34_simple) +{ + using T = flx::floatx<2, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703702194616199); +} + +TEST(FloatxOperationsTest, MUL_2_35_simple) +{ + using T = flx::floatx<2, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703705104999244); +} + +TEST(FloatxOperationsTest, MUL_2_36_simple) +{ + using T = flx::floatx<2, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_2_37_simple) +{ + using T = flx::floatx<2, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_2_38_simple) +{ + using T = flx::floatx<2, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_2_39_simple) +{ + using T = flx::floatx<2, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_2_40_simple) +{ + using T = flx::floatx<2, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703740757192); +} + +TEST(FloatxOperationsTest, MUL_2_41_simple) +{ + using T = flx::floatx<2, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_2_42_simple) +{ + using T = flx::floatx<2, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_2_43_simple) +{ + using T = flx::floatx<2, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703706651140); +} + +TEST(FloatxOperationsTest, MUL_2_44_simple) +{ + using T = flx::floatx<2, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703700966798); +} + +TEST(FloatxOperationsTest, MUL_2_45_simple) +{ + using T = flx::floatx<2, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_2_46_simple) +{ + using T = flx::floatx<2, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_2_47_simple) +{ + using T = flx::floatx<2, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_2_48_simple) +{ + using T = flx::floatx<2, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_2_49_simple) +{ + using T = flx::floatx<2, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703631334); +} + +TEST(FloatxOperationsTest, MUL_2_50_simple) +{ + using T = flx::floatx<2, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_2_51_simple) +{ + using T = flx::floatx<2, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_2_52_simple) +{ + using T = flx::floatx<2, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703697947); +} + +TEST(FloatxOperationsTest, MUL_3_1_simple) +{ + using T = flx::floatx<3, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.00000000000000000000); +} + +TEST(FloatxOperationsTest, MUL_3_2_simple) +{ + using T = flx::floatx<3, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.06250000000000000000); +} + +TEST(FloatxOperationsTest, MUL_3_3_simple) +{ + using T = flx::floatx<3, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.03125000000000000000); +} + +TEST(FloatxOperationsTest, MUL_3_4_simple) +{ + using T = flx::floatx<3, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03125000000000000000); +} + +TEST(FloatxOperationsTest, MUL_3_5_simple) +{ + using T = flx::floatx<3, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03906250000000000000); +} + +TEST(FloatxOperationsTest, MUL_3_6_simple) +{ + using T = flx::floatx<3, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03515625000000000000); +} + +TEST(FloatxOperationsTest, MUL_3_7_simple) +{ + using T = flx::floatx<3, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_3_8_simple) +{ + using T = flx::floatx<3, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_3_9_simple) +{ + using T = flx::floatx<3, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_3_10_simple) +{ + using T = flx::floatx<3, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_3_11_simple) +{ + using T = flx::floatx<3, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03698730468750000000); +} + +TEST(FloatxOperationsTest, MUL_3_12_simple) +{ + using T = flx::floatx<3, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_3_13_simple) +{ + using T = flx::floatx<3, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_3_14_simple) +{ + using T = flx::floatx<3, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03703308105468750000); +} + +TEST(FloatxOperationsTest, MUL_3_15_simple) +{ + using T = flx::floatx<3, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704071044921875000); +} + +TEST(FloatxOperationsTest, MUL_3_16_simple) +{ + using T = flx::floatx<3, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_3_17_simple) +{ + using T = flx::floatx<3, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_3_18_simple) +{ + using T = flx::floatx<3, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_3_19_simple) +{ + using T = flx::floatx<3, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_3_20_simple) +{ + using T = flx::floatx<3, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703713417053222656); +} + +TEST(FloatxOperationsTest, MUL_3_21_simple) +{ + using T = flx::floatx<3, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_3_22_simple) +{ + using T = flx::floatx<3, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_3_23_simple) +{ + using T = flx::floatx<3, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703704476356506348); +} + +TEST(FloatxOperationsTest, MUL_3_24_simple) +{ + using T = flx::floatx<3, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703702986240386963); +} + +TEST(FloatxOperationsTest, MUL_3_25_simple) +{ + using T = flx::floatx<3, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_3_26_simple) +{ + using T = flx::floatx<3, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_3_27_simple) +{ + using T = flx::floatx<3, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_3_28_simple) +{ + using T = flx::floatx<3, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_3_29_simple) +{ + using T = flx::floatx<3, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703684732317924); +} + +TEST(FloatxOperationsTest, MUL_3_30_simple) +{ + using T = flx::floatx<3, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_3_31_simple) +{ + using T = flx::floatx<3, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_3_32_simple) +{ + using T = flx::floatx<3, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703702194616199); +} + +TEST(FloatxOperationsTest, MUL_3_33_simple) +{ + using T = flx::floatx<3, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703705104999244); +} + +TEST(FloatxOperationsTest, MUL_3_34_simple) +{ + using T = flx::floatx<3, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_3_35_simple) +{ + using T = flx::floatx<3, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_3_36_simple) +{ + using T = flx::floatx<3, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_3_37_simple) +{ + using T = flx::floatx<3, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_3_38_simple) +{ + using T = flx::floatx<3, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703740757192); +} + +TEST(FloatxOperationsTest, MUL_3_39_simple) +{ + using T = flx::floatx<3, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_3_40_simple) +{ + using T = flx::floatx<3, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_3_41_simple) +{ + using T = flx::floatx<3, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703706651140); +} + +TEST(FloatxOperationsTest, MUL_3_42_simple) +{ + using T = flx::floatx<3, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703700966798); +} + +TEST(FloatxOperationsTest, MUL_3_43_simple) +{ + using T = flx::floatx<3, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_3_44_simple) +{ + using T = flx::floatx<3, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_3_45_simple) +{ + using T = flx::floatx<3, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_3_46_simple) +{ + using T = flx::floatx<3, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_3_47_simple) +{ + using T = flx::floatx<3, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703631334); +} + +TEST(FloatxOperationsTest, MUL_3_48_simple) +{ + using T = flx::floatx<3, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_3_49_simple) +{ + using T = flx::floatx<3, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_3_50_simple) +{ + using T = flx::floatx<3, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703697947); +} + +TEST(FloatxOperationsTest, MUL_3_51_simple) +{ + using T = flx::floatx<3, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703709049); +} + +TEST(FloatxOperationsTest, MUL_3_52_simple) +{ + using T = flx::floatx<3, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_4_1_simple) +{ + using T = flx::floatx<4, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.04687500000000000000); +} + +TEST(FloatxOperationsTest, MUL_4_2_simple) +{ + using T = flx::floatx<4, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03125000000000000000); +} + +TEST(FloatxOperationsTest, MUL_4_3_simple) +{ + using T = flx::floatx<4, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03906250000000000000); +} + +TEST(FloatxOperationsTest, MUL_4_4_simple) +{ + using T = flx::floatx<4, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03515625000000000000); +} + +TEST(FloatxOperationsTest, MUL_4_5_simple) +{ + using T = flx::floatx<4, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_4_6_simple) +{ + using T = flx::floatx<4, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_4_7_simple) +{ + using T = flx::floatx<4, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_4_8_simple) +{ + using T = flx::floatx<4, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03698730468750000000); +} + +TEST(FloatxOperationsTest, MUL_4_9_simple) +{ + using T = flx::floatx<4, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_4_10_simple) +{ + using T = flx::floatx<4, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03701782226562500000); +} + +TEST(FloatxOperationsTest, MUL_4_11_simple) +{ + using T = flx::floatx<4, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_4_12_simple) +{ + using T = flx::floatx<4, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03703308105468750000); +} + +TEST(FloatxOperationsTest, MUL_4_13_simple) +{ + using T = flx::floatx<4, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704071044921875000); +} + +TEST(FloatxOperationsTest, MUL_4_14_simple) +{ + using T = flx::floatx<4, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_4_15_simple) +{ + using T = flx::floatx<4, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_4_16_simple) +{ + using T = flx::floatx<4, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_4_17_simple) +{ + using T = flx::floatx<4, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703713417053222656); +} + +TEST(FloatxOperationsTest, MUL_4_18_simple) +{ + using T = flx::floatx<4, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_4_19_simple) +{ + using T = flx::floatx<4, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703707456588745117); +} + +TEST(FloatxOperationsTest, MUL_4_20_simple) +{ + using T = flx::floatx<4, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_4_21_simple) +{ + using T = flx::floatx<4, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703704476356506348); +} + +TEST(FloatxOperationsTest, MUL_4_22_simple) +{ + using T = flx::floatx<4, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703702986240386963); +} + +TEST(FloatxOperationsTest, MUL_4_23_simple) +{ + using T = flx::floatx<4, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_4_24_simple) +{ + using T = flx::floatx<4, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_4_25_simple) +{ + using T = flx::floatx<4, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_4_26_simple) +{ + using T = flx::floatx<4, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703684732317924); +} + +TEST(FloatxOperationsTest, MUL_4_27_simple) +{ + using T = flx::floatx<4, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_4_28_simple) +{ + using T = flx::floatx<4, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703696373850107); +} + +TEST(FloatxOperationsTest, MUL_4_29_simple) +{ + using T = flx::floatx<4, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_4_30_simple) +{ + using T = flx::floatx<4, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703702194616199); +} + +TEST(FloatxOperationsTest, MUL_4_31_simple) +{ + using T = flx::floatx<4, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703705104999244); +} + +TEST(FloatxOperationsTest, MUL_4_32_simple) +{ + using T = flx::floatx<4, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_4_33_simple) +{ + using T = flx::floatx<4, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_4_34_simple) +{ + using T = flx::floatx<4, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_4_35_simple) +{ + using T = flx::floatx<4, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703740757192); +} + +TEST(FloatxOperationsTest, MUL_4_36_simple) +{ + using T = flx::floatx<4, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_4_37_simple) +{ + using T = flx::floatx<4, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703718019824); +} + +TEST(FloatxOperationsTest, MUL_4_38_simple) +{ + using T = flx::floatx<4, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_4_39_simple) +{ + using T = flx::floatx<4, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703706651140); +} + +TEST(FloatxOperationsTest, MUL_4_40_simple) +{ + using T = flx::floatx<4, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703700966798); +} + +TEST(FloatxOperationsTest, MUL_4_41_simple) +{ + using T = flx::floatx<4, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_4_42_simple) +{ + using T = flx::floatx<4, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_4_43_simple) +{ + using T = flx::floatx<4, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_4_44_simple) +{ + using T = flx::floatx<4, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703631334); +} + +TEST(FloatxOperationsTest, MUL_4_45_simple) +{ + using T = flx::floatx<4, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_4_46_simple) +{ + using T = flx::floatx<4, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703675743); +} + +TEST(FloatxOperationsTest, MUL_4_47_simple) +{ + using T = flx::floatx<4, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_4_48_simple) +{ + using T = flx::floatx<4, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703697947); +} + +TEST(FloatxOperationsTest, MUL_4_49_simple) +{ + using T = flx::floatx<4, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703709049); +} + +TEST(FloatxOperationsTest, MUL_4_50_simple) +{ + using T = flx::floatx<4, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_4_51_simple) +{ + using T = flx::floatx<4, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_4_52_simple) +{ + using T = flx::floatx<4, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_5_1_simple) +{ + using T = flx::floatx<5, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.04687500000000000000); +} + +TEST(FloatxOperationsTest, MUL_5_2_simple) +{ + using T = flx::floatx<5, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03125000000000000000); +} + +TEST(FloatxOperationsTest, MUL_5_3_simple) +{ + using T = flx::floatx<5, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03906250000000000000); +} + +TEST(FloatxOperationsTest, MUL_5_4_simple) +{ + using T = flx::floatx<5, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03515625000000000000); +} + +TEST(FloatxOperationsTest, MUL_5_5_simple) +{ + using T = flx::floatx<5, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_5_6_simple) +{ + using T = flx::floatx<5, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_5_7_simple) +{ + using T = flx::floatx<5, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_5_8_simple) +{ + using T = flx::floatx<5, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03698730468750000000); +} + +TEST(FloatxOperationsTest, MUL_5_9_simple) +{ + using T = flx::floatx<5, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_5_10_simple) +{ + using T = flx::floatx<5, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03701782226562500000); +} + +TEST(FloatxOperationsTest, MUL_5_11_simple) +{ + using T = flx::floatx<5, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_5_12_simple) +{ + using T = flx::floatx<5, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03703308105468750000); +} + +TEST(FloatxOperationsTest, MUL_5_13_simple) +{ + using T = flx::floatx<5, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704071044921875000); +} + +TEST(FloatxOperationsTest, MUL_5_14_simple) +{ + using T = flx::floatx<5, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_5_15_simple) +{ + using T = flx::floatx<5, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_5_16_simple) +{ + using T = flx::floatx<5, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_5_17_simple) +{ + using T = flx::floatx<5, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703713417053222656); +} + +TEST(FloatxOperationsTest, MUL_5_18_simple) +{ + using T = flx::floatx<5, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_5_19_simple) +{ + using T = flx::floatx<5, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703707456588745117); +} + +TEST(FloatxOperationsTest, MUL_5_20_simple) +{ + using T = flx::floatx<5, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_5_21_simple) +{ + using T = flx::floatx<5, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703704476356506348); +} + +TEST(FloatxOperationsTest, MUL_5_22_simple) +{ + using T = flx::floatx<5, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703702986240386963); +} + +TEST(FloatxOperationsTest, MUL_5_23_simple) +{ + using T = flx::floatx<5, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_5_24_simple) +{ + using T = flx::floatx<5, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_5_25_simple) +{ + using T = flx::floatx<5, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_5_26_simple) +{ + using T = flx::floatx<5, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703684732317924); +} + +TEST(FloatxOperationsTest, MUL_5_27_simple) +{ + using T = flx::floatx<5, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_5_28_simple) +{ + using T = flx::floatx<5, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703696373850107); +} + +TEST(FloatxOperationsTest, MUL_5_29_simple) +{ + using T = flx::floatx<5, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_5_30_simple) +{ + using T = flx::floatx<5, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703702194616199); +} + +TEST(FloatxOperationsTest, MUL_5_31_simple) +{ + using T = flx::floatx<5, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703705104999244); +} + +TEST(FloatxOperationsTest, MUL_5_32_simple) +{ + using T = flx::floatx<5, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_5_33_simple) +{ + using T = flx::floatx<5, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_5_34_simple) +{ + using T = flx::floatx<5, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_5_35_simple) +{ + using T = flx::floatx<5, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703740757192); +} + +TEST(FloatxOperationsTest, MUL_5_36_simple) +{ + using T = flx::floatx<5, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_5_37_simple) +{ + using T = flx::floatx<5, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703718019824); +} + +TEST(FloatxOperationsTest, MUL_5_38_simple) +{ + using T = flx::floatx<5, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_5_39_simple) +{ + using T = flx::floatx<5, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703706651140); +} + +TEST(FloatxOperationsTest, MUL_5_40_simple) +{ + using T = flx::floatx<5, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703700966798); +} + +TEST(FloatxOperationsTest, MUL_5_41_simple) +{ + using T = flx::floatx<5, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_5_42_simple) +{ + using T = flx::floatx<5, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_5_43_simple) +{ + using T = flx::floatx<5, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_5_44_simple) +{ + using T = flx::floatx<5, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703631334); +} + +TEST(FloatxOperationsTest, MUL_5_45_simple) +{ + using T = flx::floatx<5, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_5_46_simple) +{ + using T = flx::floatx<5, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703675743); +} + +TEST(FloatxOperationsTest, MUL_5_47_simple) +{ + using T = flx::floatx<5, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_5_48_simple) +{ + using T = flx::floatx<5, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703697947); +} + +TEST(FloatxOperationsTest, MUL_5_49_simple) +{ + using T = flx::floatx<5, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703709049); +} + +TEST(FloatxOperationsTest, MUL_5_50_simple) +{ + using T = flx::floatx<5, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_5_51_simple) +{ + using T = flx::floatx<5, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_5_52_simple) +{ + using T = flx::floatx<5, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_6_1_simple) +{ + using T = flx::floatx<6, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.04687500000000000000); +} + +TEST(FloatxOperationsTest, MUL_6_2_simple) +{ + using T = flx::floatx<6, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03125000000000000000); +} + +TEST(FloatxOperationsTest, MUL_6_3_simple) +{ + using T = flx::floatx<6, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03906250000000000000); +} + +TEST(FloatxOperationsTest, MUL_6_4_simple) +{ + using T = flx::floatx<6, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03515625000000000000); +} + +TEST(FloatxOperationsTest, MUL_6_5_simple) +{ + using T = flx::floatx<6, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_6_6_simple) +{ + using T = flx::floatx<6, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_6_7_simple) +{ + using T = flx::floatx<6, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_6_8_simple) +{ + using T = flx::floatx<6, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03698730468750000000); +} + +TEST(FloatxOperationsTest, MUL_6_9_simple) +{ + using T = flx::floatx<6, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_6_10_simple) +{ + using T = flx::floatx<6, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03701782226562500000); +} + +TEST(FloatxOperationsTest, MUL_6_11_simple) +{ + using T = flx::floatx<6, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_6_12_simple) +{ + using T = flx::floatx<6, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03703308105468750000); +} + +TEST(FloatxOperationsTest, MUL_6_13_simple) +{ + using T = flx::floatx<6, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704071044921875000); +} + +TEST(FloatxOperationsTest, MUL_6_14_simple) +{ + using T = flx::floatx<6, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_6_15_simple) +{ + using T = flx::floatx<6, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_6_16_simple) +{ + using T = flx::floatx<6, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_6_17_simple) +{ + using T = flx::floatx<6, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703713417053222656); +} + +TEST(FloatxOperationsTest, MUL_6_18_simple) +{ + using T = flx::floatx<6, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_6_19_simple) +{ + using T = flx::floatx<6, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703707456588745117); +} + +TEST(FloatxOperationsTest, MUL_6_20_simple) +{ + using T = flx::floatx<6, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_6_21_simple) +{ + using T = flx::floatx<6, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703704476356506348); +} + +TEST(FloatxOperationsTest, MUL_6_22_simple) +{ + using T = flx::floatx<6, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703702986240386963); +} + +TEST(FloatxOperationsTest, MUL_6_23_simple) +{ + using T = flx::floatx<6, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_6_24_simple) +{ + using T = flx::floatx<6, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_6_25_simple) +{ + using T = flx::floatx<6, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_6_26_simple) +{ + using T = flx::floatx<6, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703684732317924); +} + +TEST(FloatxOperationsTest, MUL_6_27_simple) +{ + using T = flx::floatx<6, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_6_28_simple) +{ + using T = flx::floatx<6, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703696373850107); +} + +TEST(FloatxOperationsTest, MUL_6_29_simple) +{ + using T = flx::floatx<6, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_6_30_simple) +{ + using T = flx::floatx<6, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703702194616199); +} + +TEST(FloatxOperationsTest, MUL_6_31_simple) +{ + using T = flx::floatx<6, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703705104999244); +} + +TEST(FloatxOperationsTest, MUL_6_32_simple) +{ + using T = flx::floatx<6, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_6_33_simple) +{ + using T = flx::floatx<6, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_6_34_simple) +{ + using T = flx::floatx<6, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_6_35_simple) +{ + using T = flx::floatx<6, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703740757192); +} + +TEST(FloatxOperationsTest, MUL_6_36_simple) +{ + using T = flx::floatx<6, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_6_37_simple) +{ + using T = flx::floatx<6, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703718019824); +} + +TEST(FloatxOperationsTest, MUL_6_38_simple) +{ + using T = flx::floatx<6, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_6_39_simple) +{ + using T = flx::floatx<6, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703706651140); +} + +TEST(FloatxOperationsTest, MUL_6_40_simple) +{ + using T = flx::floatx<6, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703700966798); +} + +TEST(FloatxOperationsTest, MUL_6_41_simple) +{ + using T = flx::floatx<6, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_6_42_simple) +{ + using T = flx::floatx<6, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_6_43_simple) +{ + using T = flx::floatx<6, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_6_44_simple) +{ + using T = flx::floatx<6, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703631334); +} + +TEST(FloatxOperationsTest, MUL_6_45_simple) +{ + using T = flx::floatx<6, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_6_46_simple) +{ + using T = flx::floatx<6, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703675743); +} + +TEST(FloatxOperationsTest, MUL_6_47_simple) +{ + using T = flx::floatx<6, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_6_48_simple) +{ + using T = flx::floatx<6, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703697947); +} + +TEST(FloatxOperationsTest, MUL_6_49_simple) +{ + using T = flx::floatx<6, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703709049); +} + +TEST(FloatxOperationsTest, MUL_6_50_simple) +{ + using T = flx::floatx<6, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_6_51_simple) +{ + using T = flx::floatx<6, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_6_52_simple) +{ + using T = flx::floatx<6, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_7_1_simple) +{ + using T = flx::floatx<7, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.04687500000000000000); +} + +TEST(FloatxOperationsTest, MUL_7_2_simple) +{ + using T = flx::floatx<7, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03125000000000000000); +} + +TEST(FloatxOperationsTest, MUL_7_3_simple) +{ + using T = flx::floatx<7, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03906250000000000000); +} + +TEST(FloatxOperationsTest, MUL_7_4_simple) +{ + using T = flx::floatx<7, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03515625000000000000); +} + +TEST(FloatxOperationsTest, MUL_7_5_simple) +{ + using T = flx::floatx<7, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_7_6_simple) +{ + using T = flx::floatx<7, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_7_7_simple) +{ + using T = flx::floatx<7, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_7_8_simple) +{ + using T = flx::floatx<7, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03698730468750000000); +} + +TEST(FloatxOperationsTest, MUL_7_9_simple) +{ + using T = flx::floatx<7, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_7_10_simple) +{ + using T = flx::floatx<7, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03701782226562500000); +} + +TEST(FloatxOperationsTest, MUL_7_11_simple) +{ + using T = flx::floatx<7, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_7_12_simple) +{ + using T = flx::floatx<7, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03703308105468750000); +} + +TEST(FloatxOperationsTest, MUL_7_13_simple) +{ + using T = flx::floatx<7, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704071044921875000); +} + +TEST(FloatxOperationsTest, MUL_7_14_simple) +{ + using T = flx::floatx<7, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_7_15_simple) +{ + using T = flx::floatx<7, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_7_16_simple) +{ + using T = flx::floatx<7, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_7_17_simple) +{ + using T = flx::floatx<7, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703713417053222656); +} + +TEST(FloatxOperationsTest, MUL_7_18_simple) +{ + using T = flx::floatx<7, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_7_19_simple) +{ + using T = flx::floatx<7, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703707456588745117); +} + +TEST(FloatxOperationsTest, MUL_7_20_simple) +{ + using T = flx::floatx<7, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_7_21_simple) +{ + using T = flx::floatx<7, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703704476356506348); +} + +TEST(FloatxOperationsTest, MUL_7_22_simple) +{ + using T = flx::floatx<7, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703702986240386963); +} + +TEST(FloatxOperationsTest, MUL_7_23_simple) +{ + using T = flx::floatx<7, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_7_24_simple) +{ + using T = flx::floatx<7, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_7_25_simple) +{ + using T = flx::floatx<7, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_7_26_simple) +{ + using T = flx::floatx<7, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703684732317924); +} + +TEST(FloatxOperationsTest, MUL_7_27_simple) +{ + using T = flx::floatx<7, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_7_28_simple) +{ + using T = flx::floatx<7, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703696373850107); +} + +TEST(FloatxOperationsTest, MUL_7_29_simple) +{ + using T = flx::floatx<7, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_7_30_simple) +{ + using T = flx::floatx<7, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703702194616199); +} + +TEST(FloatxOperationsTest, MUL_7_31_simple) +{ + using T = flx::floatx<7, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703705104999244); +} + +TEST(FloatxOperationsTest, MUL_7_32_simple) +{ + using T = flx::floatx<7, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_7_33_simple) +{ + using T = flx::floatx<7, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_7_34_simple) +{ + using T = flx::floatx<7, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_7_35_simple) +{ + using T = flx::floatx<7, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703740757192); +} + +TEST(FloatxOperationsTest, MUL_7_36_simple) +{ + using T = flx::floatx<7, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_7_37_simple) +{ + using T = flx::floatx<7, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703718019824); +} + +TEST(FloatxOperationsTest, MUL_7_38_simple) +{ + using T = flx::floatx<7, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_7_39_simple) +{ + using T = flx::floatx<7, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703706651140); +} + +TEST(FloatxOperationsTest, MUL_7_40_simple) +{ + using T = flx::floatx<7, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703700966798); +} + +TEST(FloatxOperationsTest, MUL_7_41_simple) +{ + using T = flx::floatx<7, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_7_42_simple) +{ + using T = flx::floatx<7, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_7_43_simple) +{ + using T = flx::floatx<7, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_7_44_simple) +{ + using T = flx::floatx<7, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703631334); +} + +TEST(FloatxOperationsTest, MUL_7_45_simple) +{ + using T = flx::floatx<7, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_7_46_simple) +{ + using T = flx::floatx<7, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703675743); +} + +TEST(FloatxOperationsTest, MUL_7_47_simple) +{ + using T = flx::floatx<7, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_7_48_simple) +{ + using T = flx::floatx<7, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703697947); +} + +TEST(FloatxOperationsTest, MUL_7_49_simple) +{ + using T = flx::floatx<7, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703709049); +} + +TEST(FloatxOperationsTest, MUL_7_50_simple) +{ + using T = flx::floatx<7, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_7_51_simple) +{ + using T = flx::floatx<7, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_7_52_simple) +{ + using T = flx::floatx<7, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_8_1_simple) +{ + using T = flx::floatx<8, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.04687500000000000000); +} + +TEST(FloatxOperationsTest, MUL_8_2_simple) +{ + using T = flx::floatx<8, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03125000000000000000); +} + +TEST(FloatxOperationsTest, MUL_8_3_simple) +{ + using T = flx::floatx<8, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03906250000000000000); +} + +TEST(FloatxOperationsTest, MUL_8_4_simple) +{ + using T = flx::floatx<8, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03515625000000000000); +} + +TEST(FloatxOperationsTest, MUL_8_5_simple) +{ + using T = flx::floatx<8, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_8_6_simple) +{ + using T = flx::floatx<8, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_8_7_simple) +{ + using T = flx::floatx<8, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_8_8_simple) +{ + using T = flx::floatx<8, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03698730468750000000); +} + +TEST(FloatxOperationsTest, MUL_8_9_simple) +{ + using T = flx::floatx<8, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_8_10_simple) +{ + using T = flx::floatx<8, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03701782226562500000); +} + +TEST(FloatxOperationsTest, MUL_8_11_simple) +{ + using T = flx::floatx<8, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_8_12_simple) +{ + using T = flx::floatx<8, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03703308105468750000); +} + +TEST(FloatxOperationsTest, MUL_8_13_simple) +{ + using T = flx::floatx<8, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704071044921875000); +} + +TEST(FloatxOperationsTest, MUL_8_14_simple) +{ + using T = flx::floatx<8, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_8_15_simple) +{ + using T = flx::floatx<8, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_8_16_simple) +{ + using T = flx::floatx<8, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_8_17_simple) +{ + using T = flx::floatx<8, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703713417053222656); +} + +TEST(FloatxOperationsTest, MUL_8_18_simple) +{ + using T = flx::floatx<8, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_8_19_simple) +{ + using T = flx::floatx<8, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703707456588745117); +} + +TEST(FloatxOperationsTest, MUL_8_20_simple) +{ + using T = flx::floatx<8, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_8_21_simple) +{ + using T = flx::floatx<8, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703704476356506348); +} + +TEST(FloatxOperationsTest, MUL_8_22_simple) +{ + using T = flx::floatx<8, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703702986240386963); +} + +TEST(FloatxOperationsTest, MUL_8_23_simple) +{ + using T = flx::floatx<8, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_8_24_simple) +{ + using T = flx::floatx<8, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_8_25_simple) +{ + using T = flx::floatx<8, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_8_26_simple) +{ + using T = flx::floatx<8, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703684732317924); +} + +TEST(FloatxOperationsTest, MUL_8_27_simple) +{ + using T = flx::floatx<8, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_8_28_simple) +{ + using T = flx::floatx<8, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703696373850107); +} + +TEST(FloatxOperationsTest, MUL_8_29_simple) +{ + using T = flx::floatx<8, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_8_30_simple) +{ + using T = flx::floatx<8, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703702194616199); +} + +TEST(FloatxOperationsTest, MUL_8_31_simple) +{ + using T = flx::floatx<8, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703705104999244); +} + +TEST(FloatxOperationsTest, MUL_8_32_simple) +{ + using T = flx::floatx<8, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_8_33_simple) +{ + using T = flx::floatx<8, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_8_34_simple) +{ + using T = flx::floatx<8, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_8_35_simple) +{ + using T = flx::floatx<8, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703740757192); +} + +TEST(FloatxOperationsTest, MUL_8_36_simple) +{ + using T = flx::floatx<8, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_8_37_simple) +{ + using T = flx::floatx<8, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703718019824); +} + +TEST(FloatxOperationsTest, MUL_8_38_simple) +{ + using T = flx::floatx<8, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_8_39_simple) +{ + using T = flx::floatx<8, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703706651140); +} + +TEST(FloatxOperationsTest, MUL_8_40_simple) +{ + using T = flx::floatx<8, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703700966798); +} + +TEST(FloatxOperationsTest, MUL_8_41_simple) +{ + using T = flx::floatx<8, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_8_42_simple) +{ + using T = flx::floatx<8, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_8_43_simple) +{ + using T = flx::floatx<8, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_8_44_simple) +{ + using T = flx::floatx<8, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703631334); +} + +TEST(FloatxOperationsTest, MUL_8_45_simple) +{ + using T = flx::floatx<8, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_8_46_simple) +{ + using T = flx::floatx<8, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703675743); +} + +TEST(FloatxOperationsTest, MUL_8_47_simple) +{ + using T = flx::floatx<8, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_8_48_simple) +{ + using T = flx::floatx<8, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703697947); +} + +TEST(FloatxOperationsTest, MUL_8_49_simple) +{ + using T = flx::floatx<8, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703709049); +} + +TEST(FloatxOperationsTest, MUL_8_50_simple) +{ + using T = flx::floatx<8, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_8_51_simple) +{ + using T = flx::floatx<8, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_8_52_simple) +{ + using T = flx::floatx<8, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_9_1_simple) +{ + using T = flx::floatx<9, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.04687500000000000000); +} + +TEST(FloatxOperationsTest, MUL_9_2_simple) +{ + using T = flx::floatx<9, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03125000000000000000); +} + +TEST(FloatxOperationsTest, MUL_9_3_simple) +{ + using T = flx::floatx<9, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03906250000000000000); +} + +TEST(FloatxOperationsTest, MUL_9_4_simple) +{ + using T = flx::floatx<9, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03515625000000000000); +} + +TEST(FloatxOperationsTest, MUL_9_5_simple) +{ + using T = flx::floatx<9, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_9_6_simple) +{ + using T = flx::floatx<9, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_9_7_simple) +{ + using T = flx::floatx<9, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_9_8_simple) +{ + using T = flx::floatx<9, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03698730468750000000); +} + +TEST(FloatxOperationsTest, MUL_9_9_simple) +{ + using T = flx::floatx<9, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_9_10_simple) +{ + using T = flx::floatx<9, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03701782226562500000); +} + +TEST(FloatxOperationsTest, MUL_9_11_simple) +{ + using T = flx::floatx<9, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_9_12_simple) +{ + using T = flx::floatx<9, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03703308105468750000); +} + +TEST(FloatxOperationsTest, MUL_9_13_simple) +{ + using T = flx::floatx<9, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704071044921875000); +} + +TEST(FloatxOperationsTest, MUL_9_14_simple) +{ + using T = flx::floatx<9, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_9_15_simple) +{ + using T = flx::floatx<9, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_9_16_simple) +{ + using T = flx::floatx<9, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_9_17_simple) +{ + using T = flx::floatx<9, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703713417053222656); +} + +TEST(FloatxOperationsTest, MUL_9_18_simple) +{ + using T = flx::floatx<9, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_9_19_simple) +{ + using T = flx::floatx<9, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703707456588745117); +} + +TEST(FloatxOperationsTest, MUL_9_20_simple) +{ + using T = flx::floatx<9, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_9_21_simple) +{ + using T = flx::floatx<9, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703704476356506348); +} + +TEST(FloatxOperationsTest, MUL_9_22_simple) +{ + using T = flx::floatx<9, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703702986240386963); +} + +TEST(FloatxOperationsTest, MUL_9_23_simple) +{ + using T = flx::floatx<9, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_9_24_simple) +{ + using T = flx::floatx<9, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_9_25_simple) +{ + using T = flx::floatx<9, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_9_26_simple) +{ + using T = flx::floatx<9, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703684732317924); +} + +TEST(FloatxOperationsTest, MUL_9_27_simple) +{ + using T = flx::floatx<9, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_9_28_simple) +{ + using T = flx::floatx<9, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703696373850107); +} + +TEST(FloatxOperationsTest, MUL_9_29_simple) +{ + using T = flx::floatx<9, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_9_30_simple) +{ + using T = flx::floatx<9, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703702194616199); +} + +TEST(FloatxOperationsTest, MUL_9_31_simple) +{ + using T = flx::floatx<9, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703705104999244); +} + +TEST(FloatxOperationsTest, MUL_9_32_simple) +{ + using T = flx::floatx<9, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_9_33_simple) +{ + using T = flx::floatx<9, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_9_34_simple) +{ + using T = flx::floatx<9, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_9_35_simple) +{ + using T = flx::floatx<9, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703740757192); +} + +TEST(FloatxOperationsTest, MUL_9_36_simple) +{ + using T = flx::floatx<9, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_9_37_simple) +{ + using T = flx::floatx<9, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703718019824); +} + +TEST(FloatxOperationsTest, MUL_9_38_simple) +{ + using T = flx::floatx<9, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_9_39_simple) +{ + using T = flx::floatx<9, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703706651140); +} + +TEST(FloatxOperationsTest, MUL_9_40_simple) +{ + using T = flx::floatx<9, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703700966798); +} + +TEST(FloatxOperationsTest, MUL_9_41_simple) +{ + using T = flx::floatx<9, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_9_42_simple) +{ + using T = flx::floatx<9, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_9_43_simple) +{ + using T = flx::floatx<9, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_9_44_simple) +{ + using T = flx::floatx<9, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703631334); +} + +TEST(FloatxOperationsTest, MUL_9_45_simple) +{ + using T = flx::floatx<9, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_9_46_simple) +{ + using T = flx::floatx<9, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703675743); +} + +TEST(FloatxOperationsTest, MUL_9_47_simple) +{ + using T = flx::floatx<9, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_9_48_simple) +{ + using T = flx::floatx<9, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703697947); +} + +TEST(FloatxOperationsTest, MUL_9_49_simple) +{ + using T = flx::floatx<9, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703709049); +} + +TEST(FloatxOperationsTest, MUL_9_50_simple) +{ + using T = flx::floatx<9, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_9_51_simple) +{ + using T = flx::floatx<9, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_9_52_simple) +{ + using T = flx::floatx<9, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_10_1_simple) +{ + using T = flx::floatx<10, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.04687500000000000000); +} + +TEST(FloatxOperationsTest, MUL_10_2_simple) +{ + using T = flx::floatx<10, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03125000000000000000); +} + +TEST(FloatxOperationsTest, MUL_10_3_simple) +{ + using T = flx::floatx<10, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03906250000000000000); +} + +TEST(FloatxOperationsTest, MUL_10_4_simple) +{ + using T = flx::floatx<10, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03515625000000000000); +} + +TEST(FloatxOperationsTest, MUL_10_5_simple) +{ + using T = flx::floatx<10, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_10_6_simple) +{ + using T = flx::floatx<10, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_10_7_simple) +{ + using T = flx::floatx<10, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_10_8_simple) +{ + using T = flx::floatx<10, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03698730468750000000); +} + +TEST(FloatxOperationsTest, MUL_10_9_simple) +{ + using T = flx::floatx<10, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_10_10_simple) +{ + using T = flx::floatx<10, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03701782226562500000); +} + +TEST(FloatxOperationsTest, MUL_10_11_simple) +{ + using T = flx::floatx<10, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_10_12_simple) +{ + using T = flx::floatx<10, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03703308105468750000); +} + +TEST(FloatxOperationsTest, MUL_10_13_simple) +{ + using T = flx::floatx<10, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704071044921875000); +} + +TEST(FloatxOperationsTest, MUL_10_14_simple) +{ + using T = flx::floatx<10, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_10_15_simple) +{ + using T = flx::floatx<10, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_10_16_simple) +{ + using T = flx::floatx<10, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_10_17_simple) +{ + using T = flx::floatx<10, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703713417053222656); +} + +TEST(FloatxOperationsTest, MUL_10_18_simple) +{ + using T = flx::floatx<10, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_10_19_simple) +{ + using T = flx::floatx<10, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703707456588745117); +} + +TEST(FloatxOperationsTest, MUL_10_20_simple) +{ + using T = flx::floatx<10, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_10_21_simple) +{ + using T = flx::floatx<10, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703704476356506348); +} + +TEST(FloatxOperationsTest, MUL_10_22_simple) +{ + using T = flx::floatx<10, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703702986240386963); +} + +TEST(FloatxOperationsTest, MUL_10_23_simple) +{ + using T = flx::floatx<10, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_10_24_simple) +{ + using T = flx::floatx<10, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_10_25_simple) +{ + using T = flx::floatx<10, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_10_26_simple) +{ + using T = flx::floatx<10, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703684732317924); +} + +TEST(FloatxOperationsTest, MUL_10_27_simple) +{ + using T = flx::floatx<10, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_10_28_simple) +{ + using T = flx::floatx<10, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703696373850107); +} + +TEST(FloatxOperationsTest, MUL_10_29_simple) +{ + using T = flx::floatx<10, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_10_30_simple) +{ + using T = flx::floatx<10, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703702194616199); +} + +TEST(FloatxOperationsTest, MUL_10_31_simple) +{ + using T = flx::floatx<10, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703705104999244); +} + +TEST(FloatxOperationsTest, MUL_10_32_simple) +{ + using T = flx::floatx<10, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_10_33_simple) +{ + using T = flx::floatx<10, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_10_34_simple) +{ + using T = flx::floatx<10, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_10_35_simple) +{ + using T = flx::floatx<10, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703740757192); +} + +TEST(FloatxOperationsTest, MUL_10_36_simple) +{ + using T = flx::floatx<10, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_10_37_simple) +{ + using T = flx::floatx<10, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703718019824); +} + +TEST(FloatxOperationsTest, MUL_10_38_simple) +{ + using T = flx::floatx<10, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_10_39_simple) +{ + using T = flx::floatx<10, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703706651140); +} + +TEST(FloatxOperationsTest, MUL_10_40_simple) +{ + using T = flx::floatx<10, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703700966798); +} + +TEST(FloatxOperationsTest, MUL_10_41_simple) +{ + using T = flx::floatx<10, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_10_42_simple) +{ + using T = flx::floatx<10, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_10_43_simple) +{ + using T = flx::floatx<10, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_10_44_simple) +{ + using T = flx::floatx<10, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703631334); +} + +TEST(FloatxOperationsTest, MUL_10_45_simple) +{ + using T = flx::floatx<10, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_10_46_simple) +{ + using T = flx::floatx<10, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703675743); +} + +TEST(FloatxOperationsTest, MUL_10_47_simple) +{ + using T = flx::floatx<10, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_10_48_simple) +{ + using T = flx::floatx<10, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703697947); +} + +TEST(FloatxOperationsTest, MUL_10_49_simple) +{ + using T = flx::floatx<10, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703709049); +} + +TEST(FloatxOperationsTest, MUL_10_50_simple) +{ + using T = flx::floatx<10, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_10_51_simple) +{ + using T = flx::floatx<10, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_10_52_simple) +{ + using T = flx::floatx<10, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_11_1_simple) +{ + using T = flx::floatx<11, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.04687500000000000000); +} + +TEST(FloatxOperationsTest, MUL_11_2_simple) +{ + using T = flx::floatx<11, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03125000000000000000); +} + +TEST(FloatxOperationsTest, MUL_11_3_simple) +{ + using T = flx::floatx<11, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03906250000000000000); +} + +TEST(FloatxOperationsTest, MUL_11_4_simple) +{ + using T = flx::floatx<11, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.03515625000000000000); +} + +TEST(FloatxOperationsTest, MUL_11_5_simple) +{ + using T = flx::floatx<11, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_11_6_simple) +{ + using T = flx::floatx<11, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_11_7_simple) +{ + using T = flx::floatx<11, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.03710937500000000000); +} + +TEST(FloatxOperationsTest, MUL_11_8_simple) +{ + using T = flx::floatx<11, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03698730468750000000); +} + +TEST(FloatxOperationsTest, MUL_11_9_simple) +{ + using T = flx::floatx<11, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_11_10_simple) +{ + using T = flx::floatx<11, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.03701782226562500000); +} + +TEST(FloatxOperationsTest, MUL_11_11_simple) +{ + using T = flx::floatx<11, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704833984375000000); +} + +TEST(FloatxOperationsTest, MUL_11_12_simple) +{ + using T = flx::floatx<11, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03703308105468750000); +} + +TEST(FloatxOperationsTest, MUL_11_13_simple) +{ + using T = flx::floatx<11, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.03704071044921875000); +} + +TEST(FloatxOperationsTest, MUL_11_14_simple) +{ + using T = flx::floatx<11, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_11_15_simple) +{ + using T = flx::floatx<11, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_11_16_simple) +{ + using T = flx::floatx<11, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.03703689575195312500); +} + +TEST(FloatxOperationsTest, MUL_11_17_simple) +{ + using T = flx::floatx<11, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703713417053222656); +} + +TEST(FloatxOperationsTest, MUL_11_18_simple) +{ + using T = flx::floatx<11, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_11_19_simple) +{ + using T = flx::floatx<11, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.03703707456588745117); +} + +TEST(FloatxOperationsTest, MUL_11_20_simple) +{ + using T = flx::floatx<11, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703701496124267578); +} + +TEST(FloatxOperationsTest, MUL_11_21_simple) +{ + using T = flx::floatx<11, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703704476356506348); +} + +TEST(FloatxOperationsTest, MUL_11_22_simple) +{ + using T = flx::floatx<11, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.03703702986240386963); +} + +TEST(FloatxOperationsTest, MUL_11_23_simple) +{ + using T = flx::floatx<11, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_11_24_simple) +{ + using T = flx::floatx<11, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_11_25_simple) +{ + using T = flx::floatx<11, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.03703703731298446655); +} + +TEST(FloatxOperationsTest, MUL_11_26_simple) +{ + using T = flx::floatx<11, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703684732317924); +} + +TEST(FloatxOperationsTest, MUL_11_27_simple) +{ + using T = flx::floatx<11, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_11_28_simple) +{ + using T = flx::floatx<11, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.03703703696373850107); +} + +TEST(FloatxOperationsTest, MUL_11_29_simple) +{ + using T = flx::floatx<11, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703708015382290); +} + +TEST(FloatxOperationsTest, MUL_11_30_simple) +{ + using T = flx::floatx<11, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703702194616199); +} + +TEST(FloatxOperationsTest, MUL_11_31_simple) +{ + using T = flx::floatx<11, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.03703703705104999244); +} + +TEST(FloatxOperationsTest, MUL_11_32_simple) +{ + using T = flx::floatx<11, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_11_33_simple) +{ + using T = flx::floatx<11, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_11_34_simple) +{ + using T = flx::floatx<11, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.03703703703649807721); +} + +TEST(FloatxOperationsTest, MUL_11_35_simple) +{ + using T = flx::floatx<11, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703740757192); +} + +TEST(FloatxOperationsTest, MUL_11_36_simple) +{ + using T = flx::floatx<11, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_11_37_simple) +{ + using T = flx::floatx<11, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.03703703703718019824); +} + +TEST(FloatxOperationsTest, MUL_11_38_simple) +{ + using T = flx::floatx<11, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703695282456); +} + +TEST(FloatxOperationsTest, MUL_11_39_simple) +{ + using T = flx::floatx<11, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703706651140); +} + +TEST(FloatxOperationsTest, MUL_11_40_simple) +{ + using T = flx::floatx<11, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.03703703703700966798); +} + +TEST(FloatxOperationsTest, MUL_11_41_simple) +{ + using T = flx::floatx<11, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_11_42_simple) +{ + using T = flx::floatx<11, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_11_43_simple) +{ + using T = flx::floatx<11, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.03703703703703808969); +} + +TEST(FloatxOperationsTest, MUL_11_44_simple) +{ + using T = flx::floatx<11, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703631334); +} + +TEST(FloatxOperationsTest, MUL_11_45_simple) +{ + using T = flx::floatx<11, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_11_46_simple) +{ + using T = flx::floatx<11, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.03703703703703675743); +} + +TEST(FloatxOperationsTest, MUL_11_47_simple) +{ + using T = flx::floatx<11, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703720151); +} + +TEST(FloatxOperationsTest, MUL_11_48_simple) +{ + using T = flx::floatx<11, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703697947); +} + +TEST(FloatxOperationsTest, MUL_11_49_simple) +{ + using T = flx::floatx<11, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.03703703703703709049); +} + +TEST(FloatxOperationsTest, MUL_11_50_simple) +{ + using T = flx::floatx<11, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_11_51_simple) +{ + using T = flx::floatx<11, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + +TEST(FloatxOperationsTest, MUL_11_52_simple) +{ + using T = flx::floatx<11, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a * b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.03703703703703703498); +} + + +} // namespace diff --git a/third-party/FloatX/testx/sub_000.cpp b/third-party/FloatX/testx/sub_000.cpp new file mode 100644 index 0000000..c037f9e --- /dev/null +++ b/third-party/FloatX/testx/sub_000.cpp @@ -0,0 +1,6891 @@ +/* + Copyright 2018 - The OPRECOMP Project Consortium, Universitat Jaume I, + IBM Research GmbH. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include +#include + +#define nan double(0.0 / 0.0) +#define inf double(1.0 / 0.0) + +namespace { + +TEST(FloatxOperationsTest, SUB_1_1_simple) +{ + using T = flx::floatx<1, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.00000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_EQ(double(c), 0.00000000000000000000); +} + +TEST(FloatxOperationsTest, SUB_1_2_simple) +{ + using T = flx::floatx<1, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.50000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_EQ(double(c), 0.50000000000000000000); +} + +TEST(FloatxOperationsTest, SUB_1_3_simple) +{ + using T = flx::floatx<1, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.25000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_EQ(double(c), 0.25000000000000000000); +} + +TEST(FloatxOperationsTest, SUB_1_4_simple) +{ + using T = flx::floatx<1, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.25000000000000000000); +} + +TEST(FloatxOperationsTest, SUB_1_5_simple) +{ + using T = flx::floatx<1, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.18750000000000000000); +} + +TEST(FloatxOperationsTest, SUB_1_6_simple) +{ + using T = flx::floatx<1, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.21875000000000000000); +} + +TEST(FloatxOperationsTest, SUB_1_7_simple) +{ + using T = flx::floatx<1, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.21875000000000000000); +} + +TEST(FloatxOperationsTest, SUB_1_8_simple) +{ + using T = flx::floatx<1, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.22656250000000000000); +} + +TEST(FloatxOperationsTest, SUB_1_9_simple) +{ + using T = flx::floatx<1, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.22265625000000000000); +} + +TEST(FloatxOperationsTest, SUB_1_10_simple) +{ + using T = flx::floatx<1, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22265625000000000000); +} + +TEST(FloatxOperationsTest, SUB_1_11_simple) +{ + using T = flx::floatx<1, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22167968750000000000); +} + +TEST(FloatxOperationsTest, SUB_1_12_simple) +{ + using T = flx::floatx<1, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22216796875000000000); +} + +TEST(FloatxOperationsTest, SUB_1_13_simple) +{ + using T = flx::floatx<1, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22216796875000000000); +} + +TEST(FloatxOperationsTest, SUB_1_14_simple) +{ + using T = flx::floatx<1, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22229003906250000000); +} + +TEST(FloatxOperationsTest, SUB_1_15_simple) +{ + using T = flx::floatx<1, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22222900390625000000); +} + +TEST(FloatxOperationsTest, SUB_1_16_simple) +{ + using T = flx::floatx<1, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22222900390625000000); +} + +TEST(FloatxOperationsTest, SUB_1_17_simple) +{ + using T = flx::floatx<1, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22221374511718750000); +} + +TEST(FloatxOperationsTest, SUB_1_18_simple) +{ + using T = flx::floatx<1, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22222137451171875000); +} + +TEST(FloatxOperationsTest, SUB_1_19_simple) +{ + using T = flx::floatx<1, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222137451171875000); +} + +TEST(FloatxOperationsTest, SUB_1_20_simple) +{ + using T = flx::floatx<1, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222328186035156250); +} + +TEST(FloatxOperationsTest, SUB_1_21_simple) +{ + using T = flx::floatx<1, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222232818603515625); +} + +TEST(FloatxOperationsTest, SUB_1_22_simple) +{ + using T = flx::floatx<1, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222232818603515625); +} + +TEST(FloatxOperationsTest, SUB_1_23_simple) +{ + using T = flx::floatx<1, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222208976745605469); +} + +TEST(FloatxOperationsTest, SUB_1_24_simple) +{ + using T = flx::floatx<1, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222220897674560547); +} + +TEST(FloatxOperationsTest, SUB_1_25_simple) +{ + using T = flx::floatx<1, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222220897674560547); +} + +TEST(FloatxOperationsTest, SUB_1_26_simple) +{ + using T = flx::floatx<1, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222223877906799316); +} + +TEST(FloatxOperationsTest, SUB_1_27_simple) +{ + using T = flx::floatx<1, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222222387790679932); +} + +TEST(FloatxOperationsTest, SUB_1_28_simple) +{ + using T = flx::floatx<1, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222222387790679932); +} + +TEST(FloatxOperationsTest, SUB_1_29_simple) +{ + using T = flx::floatx<1, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222222015261650085); +} + +TEST(FloatxOperationsTest, SUB_1_30_simple) +{ + using T = flx::floatx<1, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222222201526165009); +} + +TEST(FloatxOperationsTest, SUB_1_31_simple) +{ + using T = flx::floatx<1, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222201526165009); +} + +TEST(FloatxOperationsTest, SUB_1_32_simple) +{ + using T = flx::floatx<1, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222248092293739); +} + +TEST(FloatxOperationsTest, SUB_1_33_simple) +{ + using T = flx::floatx<1, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222224809229374); +} + +TEST(FloatxOperationsTest, SUB_1_34_simple) +{ + using T = flx::floatx<1, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222224809229374); +} + +TEST(FloatxOperationsTest, SUB_1_35_simple) +{ + using T = flx::floatx<1, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222218988463283); +} + +TEST(FloatxOperationsTest, SUB_1_36_simple) +{ + using T = flx::floatx<1, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222221898846328); +} + +TEST(FloatxOperationsTest, SUB_1_37_simple) +{ + using T = flx::floatx<1, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222221898846328); +} + +TEST(FloatxOperationsTest, SUB_1_38_simple) +{ + using T = flx::floatx<1, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222222626442090); +} + +TEST(FloatxOperationsTest, SUB_1_39_simple) +{ + using T = flx::floatx<1, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222222262644209); +} + +TEST(FloatxOperationsTest, SUB_1_40_simple) +{ + using T = flx::floatx<1, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222262644209); +} + +TEST(FloatxOperationsTest, SUB_1_41_simple) +{ + using T = flx::floatx<1, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222171694739); +} + +TEST(FloatxOperationsTest, SUB_1_42_simple) +{ + using T = flx::floatx<1, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222217169474); +} + +TEST(FloatxOperationsTest, SUB_1_43_simple) +{ + using T = flx::floatx<1, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222217169474); +} + +TEST(FloatxOperationsTest, SUB_1_44_simple) +{ + using T = flx::floatx<1, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222228538158); +} + +TEST(FloatxOperationsTest, SUB_1_45_simple) +{ + using T = flx::floatx<1, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222222853816); +} + +TEST(FloatxOperationsTest, SUB_1_46_simple) +{ + using T = flx::floatx<1, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222222853816); +} + +TEST(FloatxOperationsTest, SUB_1_47_simple) +{ + using T = flx::floatx<1, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222221432730); +} + +TEST(FloatxOperationsTest, SUB_1_48_simple) +{ + using T = flx::floatx<1, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222222143273); +} + +TEST(FloatxOperationsTest, SUB_1_49_simple) +{ + using T = flx::floatx<1, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222143273); +} + +TEST(FloatxOperationsTest, SUB_1_50_simple) +{ + using T = flx::floatx<1, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222320909); +} + +TEST(FloatxOperationsTest, SUB_1_51_simple) +{ + using T = flx::floatx<1, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222232091); +} + +TEST(FloatxOperationsTest, SUB_1_52_simple) +{ + using T = flx::floatx<1, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222232091); +} + +TEST(FloatxOperationsTest, SUB_2_1_simple) +{ + using T = flx::floatx<2, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.50000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_EQ(double(c), 0.50000000000000000000); +} + +TEST(FloatxOperationsTest, SUB_2_2_simple) +{ + using T = flx::floatx<2, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.25000000000000000000); + EXPECT_EQ(double(b), 0.00000000000000000000); + EXPECT_EQ(double(c), 0.25000000000000000000); +} + +TEST(FloatxOperationsTest, SUB_2_3_simple) +{ + using T = flx::floatx<2, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.25000000000000000000); +} + +TEST(FloatxOperationsTest, SUB_2_4_simple) +{ + using T = flx::floatx<2, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.18750000000000000000); +} + +TEST(FloatxOperationsTest, SUB_2_5_simple) +{ + using T = flx::floatx<2, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.21875000000000000000); +} + +TEST(FloatxOperationsTest, SUB_2_6_simple) +{ + using T = flx::floatx<2, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.21875000000000000000); +} + +TEST(FloatxOperationsTest, SUB_2_7_simple) +{ + using T = flx::floatx<2, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.22656250000000000000); +} + +TEST(FloatxOperationsTest, SUB_2_8_simple) +{ + using T = flx::floatx<2, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.22265625000000000000); +} + +TEST(FloatxOperationsTest, SUB_2_9_simple) +{ + using T = flx::floatx<2, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22265625000000000000); +} + +TEST(FloatxOperationsTest, SUB_2_10_simple) +{ + using T = flx::floatx<2, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22167968750000000000); +} + +TEST(FloatxOperationsTest, SUB_2_11_simple) +{ + using T = flx::floatx<2, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22216796875000000000); +} + +TEST(FloatxOperationsTest, SUB_2_12_simple) +{ + using T = flx::floatx<2, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22216796875000000000); +} + +TEST(FloatxOperationsTest, SUB_2_13_simple) +{ + using T = flx::floatx<2, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22229003906250000000); +} + +TEST(FloatxOperationsTest, SUB_2_14_simple) +{ + using T = flx::floatx<2, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22222900390625000000); +} + +TEST(FloatxOperationsTest, SUB_2_15_simple) +{ + using T = flx::floatx<2, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22222900390625000000); +} + +TEST(FloatxOperationsTest, SUB_2_16_simple) +{ + using T = flx::floatx<2, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22221374511718750000); +} + +TEST(FloatxOperationsTest, SUB_2_17_simple) +{ + using T = flx::floatx<2, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22222137451171875000); +} + +TEST(FloatxOperationsTest, SUB_2_18_simple) +{ + using T = flx::floatx<2, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222137451171875000); +} + +TEST(FloatxOperationsTest, SUB_2_19_simple) +{ + using T = flx::floatx<2, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222328186035156250); +} + +TEST(FloatxOperationsTest, SUB_2_20_simple) +{ + using T = flx::floatx<2, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222232818603515625); +} + +TEST(FloatxOperationsTest, SUB_2_21_simple) +{ + using T = flx::floatx<2, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222232818603515625); +} + +TEST(FloatxOperationsTest, SUB_2_22_simple) +{ + using T = flx::floatx<2, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222208976745605469); +} + +TEST(FloatxOperationsTest, SUB_2_23_simple) +{ + using T = flx::floatx<2, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222220897674560547); +} + +TEST(FloatxOperationsTest, SUB_2_24_simple) +{ + using T = flx::floatx<2, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222220897674560547); +} + +TEST(FloatxOperationsTest, SUB_2_25_simple) +{ + using T = flx::floatx<2, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222223877906799316); +} + +TEST(FloatxOperationsTest, SUB_2_26_simple) +{ + using T = flx::floatx<2, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222222387790679932); +} + +TEST(FloatxOperationsTest, SUB_2_27_simple) +{ + using T = flx::floatx<2, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222222387790679932); +} + +TEST(FloatxOperationsTest, SUB_2_28_simple) +{ + using T = flx::floatx<2, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222222015261650085); +} + +TEST(FloatxOperationsTest, SUB_2_29_simple) +{ + using T = flx::floatx<2, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222222201526165009); +} + +TEST(FloatxOperationsTest, SUB_2_30_simple) +{ + using T = flx::floatx<2, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222201526165009); +} + +TEST(FloatxOperationsTest, SUB_2_31_simple) +{ + using T = flx::floatx<2, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222248092293739); +} + +TEST(FloatxOperationsTest, SUB_2_32_simple) +{ + using T = flx::floatx<2, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222224809229374); +} + +TEST(FloatxOperationsTest, SUB_2_33_simple) +{ + using T = flx::floatx<2, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222224809229374); +} + +TEST(FloatxOperationsTest, SUB_2_34_simple) +{ + using T = flx::floatx<2, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222218988463283); +} + +TEST(FloatxOperationsTest, SUB_2_35_simple) +{ + using T = flx::floatx<2, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222221898846328); +} + +TEST(FloatxOperationsTest, SUB_2_36_simple) +{ + using T = flx::floatx<2, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222221898846328); +} + +TEST(FloatxOperationsTest, SUB_2_37_simple) +{ + using T = flx::floatx<2, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222222626442090); +} + +TEST(FloatxOperationsTest, SUB_2_38_simple) +{ + using T = flx::floatx<2, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222222262644209); +} + +TEST(FloatxOperationsTest, SUB_2_39_simple) +{ + using T = flx::floatx<2, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222262644209); +} + +TEST(FloatxOperationsTest, SUB_2_40_simple) +{ + using T = flx::floatx<2, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222171694739); +} + +TEST(FloatxOperationsTest, SUB_2_41_simple) +{ + using T = flx::floatx<2, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222217169474); +} + +TEST(FloatxOperationsTest, SUB_2_42_simple) +{ + using T = flx::floatx<2, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222217169474); +} + +TEST(FloatxOperationsTest, SUB_2_43_simple) +{ + using T = flx::floatx<2, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222228538158); +} + +TEST(FloatxOperationsTest, SUB_2_44_simple) +{ + using T = flx::floatx<2, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222222853816); +} + +TEST(FloatxOperationsTest, SUB_2_45_simple) +{ + using T = flx::floatx<2, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222222853816); +} + +TEST(FloatxOperationsTest, SUB_2_46_simple) +{ + using T = flx::floatx<2, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222221432730); +} + +TEST(FloatxOperationsTest, SUB_2_47_simple) +{ + using T = flx::floatx<2, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222222143273); +} + +TEST(FloatxOperationsTest, SUB_2_48_simple) +{ + using T = flx::floatx<2, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222143273); +} + +TEST(FloatxOperationsTest, SUB_2_49_simple) +{ + using T = flx::floatx<2, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222320909); +} + +TEST(FloatxOperationsTest, SUB_2_50_simple) +{ + using T = flx::floatx<2, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222232091); +} + +TEST(FloatxOperationsTest, SUB_2_51_simple) +{ + using T = flx::floatx<2, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222232091); +} + +TEST(FloatxOperationsTest, SUB_2_52_simple) +{ + using T = flx::floatx<2, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222209886); +} + +TEST(FloatxOperationsTest, SUB_3_1_simple) +{ + using T = flx::floatx<3, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.25000000000000000000); +} + +TEST(FloatxOperationsTest, SUB_3_2_simple) +{ + using T = flx::floatx<3, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.18750000000000000000); +} + +TEST(FloatxOperationsTest, SUB_3_3_simple) +{ + using T = flx::floatx<3, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.21875000000000000000); +} + +TEST(FloatxOperationsTest, SUB_3_4_simple) +{ + using T = flx::floatx<3, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.21875000000000000000); +} + +TEST(FloatxOperationsTest, SUB_3_5_simple) +{ + using T = flx::floatx<3, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.22656250000000000000); +} + +TEST(FloatxOperationsTest, SUB_3_6_simple) +{ + using T = flx::floatx<3, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.22265625000000000000); +} + +TEST(FloatxOperationsTest, SUB_3_7_simple) +{ + using T = flx::floatx<3, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22265625000000000000); +} + +TEST(FloatxOperationsTest, SUB_3_8_simple) +{ + using T = flx::floatx<3, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22167968750000000000); +} + +TEST(FloatxOperationsTest, SUB_3_9_simple) +{ + using T = flx::floatx<3, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22216796875000000000); +} + +TEST(FloatxOperationsTest, SUB_3_10_simple) +{ + using T = flx::floatx<3, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22216796875000000000); +} + +TEST(FloatxOperationsTest, SUB_3_11_simple) +{ + using T = flx::floatx<3, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22229003906250000000); +} + +TEST(FloatxOperationsTest, SUB_3_12_simple) +{ + using T = flx::floatx<3, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22222900390625000000); +} + +TEST(FloatxOperationsTest, SUB_3_13_simple) +{ + using T = flx::floatx<3, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22222900390625000000); +} + +TEST(FloatxOperationsTest, SUB_3_14_simple) +{ + using T = flx::floatx<3, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22221374511718750000); +} + +TEST(FloatxOperationsTest, SUB_3_15_simple) +{ + using T = flx::floatx<3, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22222137451171875000); +} + +TEST(FloatxOperationsTest, SUB_3_16_simple) +{ + using T = flx::floatx<3, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222137451171875000); +} + +TEST(FloatxOperationsTest, SUB_3_17_simple) +{ + using T = flx::floatx<3, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222328186035156250); +} + +TEST(FloatxOperationsTest, SUB_3_18_simple) +{ + using T = flx::floatx<3, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222232818603515625); +} + +TEST(FloatxOperationsTest, SUB_3_19_simple) +{ + using T = flx::floatx<3, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222232818603515625); +} + +TEST(FloatxOperationsTest, SUB_3_20_simple) +{ + using T = flx::floatx<3, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222208976745605469); +} + +TEST(FloatxOperationsTest, SUB_3_21_simple) +{ + using T = flx::floatx<3, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222220897674560547); +} + +TEST(FloatxOperationsTest, SUB_3_22_simple) +{ + using T = flx::floatx<3, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222220897674560547); +} + +TEST(FloatxOperationsTest, SUB_3_23_simple) +{ + using T = flx::floatx<3, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222223877906799316); +} + +TEST(FloatxOperationsTest, SUB_3_24_simple) +{ + using T = flx::floatx<3, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222222387790679932); +} + +TEST(FloatxOperationsTest, SUB_3_25_simple) +{ + using T = flx::floatx<3, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222222387790679932); +} + +TEST(FloatxOperationsTest, SUB_3_26_simple) +{ + using T = flx::floatx<3, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222222015261650085); +} + +TEST(FloatxOperationsTest, SUB_3_27_simple) +{ + using T = flx::floatx<3, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222222201526165009); +} + +TEST(FloatxOperationsTest, SUB_3_28_simple) +{ + using T = flx::floatx<3, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222201526165009); +} + +TEST(FloatxOperationsTest, SUB_3_29_simple) +{ + using T = flx::floatx<3, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222248092293739); +} + +TEST(FloatxOperationsTest, SUB_3_30_simple) +{ + using T = flx::floatx<3, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222224809229374); +} + +TEST(FloatxOperationsTest, SUB_3_31_simple) +{ + using T = flx::floatx<3, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222224809229374); +} + +TEST(FloatxOperationsTest, SUB_3_32_simple) +{ + using T = flx::floatx<3, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222218988463283); +} + +TEST(FloatxOperationsTest, SUB_3_33_simple) +{ + using T = flx::floatx<3, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222221898846328); +} + +TEST(FloatxOperationsTest, SUB_3_34_simple) +{ + using T = flx::floatx<3, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222221898846328); +} + +TEST(FloatxOperationsTest, SUB_3_35_simple) +{ + using T = flx::floatx<3, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222222626442090); +} + +TEST(FloatxOperationsTest, SUB_3_36_simple) +{ + using T = flx::floatx<3, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222222262644209); +} + +TEST(FloatxOperationsTest, SUB_3_37_simple) +{ + using T = flx::floatx<3, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222262644209); +} + +TEST(FloatxOperationsTest, SUB_3_38_simple) +{ + using T = flx::floatx<3, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222171694739); +} + +TEST(FloatxOperationsTest, SUB_3_39_simple) +{ + using T = flx::floatx<3, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222217169474); +} + +TEST(FloatxOperationsTest, SUB_3_40_simple) +{ + using T = flx::floatx<3, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222217169474); +} + +TEST(FloatxOperationsTest, SUB_3_41_simple) +{ + using T = flx::floatx<3, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222228538158); +} + +TEST(FloatxOperationsTest, SUB_3_42_simple) +{ + using T = flx::floatx<3, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222222853816); +} + +TEST(FloatxOperationsTest, SUB_3_43_simple) +{ + using T = flx::floatx<3, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222222853816); +} + +TEST(FloatxOperationsTest, SUB_3_44_simple) +{ + using T = flx::floatx<3, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222221432730); +} + +TEST(FloatxOperationsTest, SUB_3_45_simple) +{ + using T = flx::floatx<3, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222222143273); +} + +TEST(FloatxOperationsTest, SUB_3_46_simple) +{ + using T = flx::floatx<3, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222143273); +} + +TEST(FloatxOperationsTest, SUB_3_47_simple) +{ + using T = flx::floatx<3, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222320909); +} + +TEST(FloatxOperationsTest, SUB_3_48_simple) +{ + using T = flx::floatx<3, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222232091); +} + +TEST(FloatxOperationsTest, SUB_3_49_simple) +{ + using T = flx::floatx<3, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222232091); +} + +TEST(FloatxOperationsTest, SUB_3_50_simple) +{ + using T = flx::floatx<3, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222209886); +} + +TEST(FloatxOperationsTest, SUB_3_51_simple) +{ + using T = flx::floatx<3, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222209886); +} + +TEST(FloatxOperationsTest, SUB_3_52_simple) +{ + using T = flx::floatx<3, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222220989); +} + +TEST(FloatxOperationsTest, SUB_4_1_simple) +{ + using T = flx::floatx<4, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.25000000000000000000); +} + +TEST(FloatxOperationsTest, SUB_4_2_simple) +{ + using T = flx::floatx<4, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.18750000000000000000); +} + +TEST(FloatxOperationsTest, SUB_4_3_simple) +{ + using T = flx::floatx<4, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.23437500000000000000); +} + +TEST(FloatxOperationsTest, SUB_4_4_simple) +{ + using T = flx::floatx<4, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.21875000000000000000); +} + +TEST(FloatxOperationsTest, SUB_4_5_simple) +{ + using T = flx::floatx<4, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22656250000000000000); +} + +TEST(FloatxOperationsTest, SUB_4_6_simple) +{ + using T = flx::floatx<4, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22070312500000000000); +} + +TEST(FloatxOperationsTest, SUB_4_7_simple) +{ + using T = flx::floatx<4, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22265625000000000000); +} + +TEST(FloatxOperationsTest, SUB_4_8_simple) +{ + using T = flx::floatx<4, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22167968750000000000); +} + +TEST(FloatxOperationsTest, SUB_4_9_simple) +{ + using T = flx::floatx<4, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22241210937500000000); +} + +TEST(FloatxOperationsTest, SUB_4_10_simple) +{ + using T = flx::floatx<4, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22216796875000000000); +} + +TEST(FloatxOperationsTest, SUB_4_11_simple) +{ + using T = flx::floatx<4, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22229003906250000000); +} + +TEST(FloatxOperationsTest, SUB_4_12_simple) +{ + using T = flx::floatx<4, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22219848632812500000); +} + +TEST(FloatxOperationsTest, SUB_4_13_simple) +{ + using T = flx::floatx<4, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22222900390625000000); +} + +TEST(FloatxOperationsTest, SUB_4_14_simple) +{ + using T = flx::floatx<4, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22221374511718750000); +} + +TEST(FloatxOperationsTest, SUB_4_15_simple) +{ + using T = flx::floatx<4, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222518920898437500); +} + +TEST(FloatxOperationsTest, SUB_4_16_simple) +{ + using T = flx::floatx<4, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222137451171875000); +} + +TEST(FloatxOperationsTest, SUB_4_17_simple) +{ + using T = flx::floatx<4, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222328186035156250); +} + +TEST(FloatxOperationsTest, SUB_4_18_simple) +{ + using T = flx::floatx<4, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222185134887695312); +} + +TEST(FloatxOperationsTest, SUB_4_19_simple) +{ + using T = flx::floatx<4, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222232818603515625); +} + +TEST(FloatxOperationsTest, SUB_4_20_simple) +{ + using T = flx::floatx<4, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222208976745605469); +} + +TEST(FloatxOperationsTest, SUB_4_21_simple) +{ + using T = flx::floatx<4, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222226858139038086); +} + +TEST(FloatxOperationsTest, SUB_4_22_simple) +{ + using T = flx::floatx<4, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222220897674560547); +} + +TEST(FloatxOperationsTest, SUB_4_23_simple) +{ + using T = flx::floatx<4, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222223877906799316); +} + +TEST(FloatxOperationsTest, SUB_4_24_simple) +{ + using T = flx::floatx<4, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222221642732620239); +} + +TEST(FloatxOperationsTest, SUB_4_25_simple) +{ + using T = flx::floatx<4, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222222387790679932); +} + +TEST(FloatxOperationsTest, SUB_4_26_simple) +{ + using T = flx::floatx<4, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222015261650085); +} + +TEST(FloatxOperationsTest, SUB_4_27_simple) +{ + using T = flx::floatx<4, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222294658422470); +} + +TEST(FloatxOperationsTest, SUB_4_28_simple) +{ + using T = flx::floatx<4, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222201526165009); +} + +TEST(FloatxOperationsTest, SUB_4_29_simple) +{ + using T = flx::floatx<4, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222248092293739); +} + +TEST(FloatxOperationsTest, SUB_4_30_simple) +{ + using T = flx::floatx<4, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222213167697191); +} + +TEST(FloatxOperationsTest, SUB_4_31_simple) +{ + using T = flx::floatx<4, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222224809229374); +} + +TEST(FloatxOperationsTest, SUB_4_32_simple) +{ + using T = flx::floatx<4, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222218988463283); +} + +TEST(FloatxOperationsTest, SUB_4_33_simple) +{ + using T = flx::floatx<4, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222223354037851); +} + +TEST(FloatxOperationsTest, SUB_4_34_simple) +{ + using T = flx::floatx<4, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222221898846328); +} + +TEST(FloatxOperationsTest, SUB_4_35_simple) +{ + using T = flx::floatx<4, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222626442090); +} + +TEST(FloatxOperationsTest, SUB_4_36_simple) +{ + using T = flx::floatx<4, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222080745269); +} + +TEST(FloatxOperationsTest, SUB_4_37_simple) +{ + using T = flx::floatx<4, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222262644209); +} + +TEST(FloatxOperationsTest, SUB_4_38_simple) +{ + using T = flx::floatx<4, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222171694739); +} + +TEST(FloatxOperationsTest, SUB_4_39_simple) +{ + using T = flx::floatx<4, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222239906841); +} + +TEST(FloatxOperationsTest, SUB_4_40_simple) +{ + using T = flx::floatx<4, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222217169474); +} + +TEST(FloatxOperationsTest, SUB_4_41_simple) +{ + using T = flx::floatx<4, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222228538158); +} + +TEST(FloatxOperationsTest, SUB_4_42_simple) +{ + using T = flx::floatx<4, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222220011645); +} + +TEST(FloatxOperationsTest, SUB_4_43_simple) +{ + using T = flx::floatx<4, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222222853816); +} + +TEST(FloatxOperationsTest, SUB_4_44_simple) +{ + using T = flx::floatx<4, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222221432730); +} + +TEST(FloatxOperationsTest, SUB_4_45_simple) +{ + using T = flx::floatx<4, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222498544); +} + +TEST(FloatxOperationsTest, SUB_4_46_simple) +{ + using T = flx::floatx<4, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222143273); +} + +TEST(FloatxOperationsTest, SUB_4_47_simple) +{ + using T = flx::floatx<4, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222320909); +} + +TEST(FloatxOperationsTest, SUB_4_48_simple) +{ + using T = flx::floatx<4, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222187682); +} + +TEST(FloatxOperationsTest, SUB_4_49_simple) +{ + using T = flx::floatx<4, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222232091); +} + +TEST(FloatxOperationsTest, SUB_4_50_simple) +{ + using T = flx::floatx<4, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222209886); +} + +TEST(FloatxOperationsTest, SUB_4_51_simple) +{ + using T = flx::floatx<4, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222215438); +} + +TEST(FloatxOperationsTest, SUB_4_52_simple) +{ + using T = flx::floatx<4, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222220989); +} + +TEST(FloatxOperationsTest, SUB_5_1_simple) +{ + using T = flx::floatx<5, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.25000000000000000000); +} + +TEST(FloatxOperationsTest, SUB_5_2_simple) +{ + using T = flx::floatx<5, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.18750000000000000000); +} + +TEST(FloatxOperationsTest, SUB_5_3_simple) +{ + using T = flx::floatx<5, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.23437500000000000000); +} + +TEST(FloatxOperationsTest, SUB_5_4_simple) +{ + using T = flx::floatx<5, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.21875000000000000000); +} + +TEST(FloatxOperationsTest, SUB_5_5_simple) +{ + using T = flx::floatx<5, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22656250000000000000); +} + +TEST(FloatxOperationsTest, SUB_5_6_simple) +{ + using T = flx::floatx<5, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22070312500000000000); +} + +TEST(FloatxOperationsTest, SUB_5_7_simple) +{ + using T = flx::floatx<5, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22265625000000000000); +} + +TEST(FloatxOperationsTest, SUB_5_8_simple) +{ + using T = flx::floatx<5, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22167968750000000000); +} + +TEST(FloatxOperationsTest, SUB_5_9_simple) +{ + using T = flx::floatx<5, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22241210937500000000); +} + +TEST(FloatxOperationsTest, SUB_5_10_simple) +{ + using T = flx::floatx<5, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22216796875000000000); +} + +TEST(FloatxOperationsTest, SUB_5_11_simple) +{ + using T = flx::floatx<5, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22229003906250000000); +} + +TEST(FloatxOperationsTest, SUB_5_12_simple) +{ + using T = flx::floatx<5, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22219848632812500000); +} + +TEST(FloatxOperationsTest, SUB_5_13_simple) +{ + using T = flx::floatx<5, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22222900390625000000); +} + +TEST(FloatxOperationsTest, SUB_5_14_simple) +{ + using T = flx::floatx<5, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22221374511718750000); +} + +TEST(FloatxOperationsTest, SUB_5_15_simple) +{ + using T = flx::floatx<5, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222518920898437500); +} + +TEST(FloatxOperationsTest, SUB_5_16_simple) +{ + using T = flx::floatx<5, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222137451171875000); +} + +TEST(FloatxOperationsTest, SUB_5_17_simple) +{ + using T = flx::floatx<5, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222328186035156250); +} + +TEST(FloatxOperationsTest, SUB_5_18_simple) +{ + using T = flx::floatx<5, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222185134887695312); +} + +TEST(FloatxOperationsTest, SUB_5_19_simple) +{ + using T = flx::floatx<5, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222232818603515625); +} + +TEST(FloatxOperationsTest, SUB_5_20_simple) +{ + using T = flx::floatx<5, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222208976745605469); +} + +TEST(FloatxOperationsTest, SUB_5_21_simple) +{ + using T = flx::floatx<5, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222226858139038086); +} + +TEST(FloatxOperationsTest, SUB_5_22_simple) +{ + using T = flx::floatx<5, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222220897674560547); +} + +TEST(FloatxOperationsTest, SUB_5_23_simple) +{ + using T = flx::floatx<5, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222223877906799316); +} + +TEST(FloatxOperationsTest, SUB_5_24_simple) +{ + using T = flx::floatx<5, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222221642732620239); +} + +TEST(FloatxOperationsTest, SUB_5_25_simple) +{ + using T = flx::floatx<5, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222222387790679932); +} + +TEST(FloatxOperationsTest, SUB_5_26_simple) +{ + using T = flx::floatx<5, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222015261650085); +} + +TEST(FloatxOperationsTest, SUB_5_27_simple) +{ + using T = flx::floatx<5, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222294658422470); +} + +TEST(FloatxOperationsTest, SUB_5_28_simple) +{ + using T = flx::floatx<5, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222201526165009); +} + +TEST(FloatxOperationsTest, SUB_5_29_simple) +{ + using T = flx::floatx<5, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222248092293739); +} + +TEST(FloatxOperationsTest, SUB_5_30_simple) +{ + using T = flx::floatx<5, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222213167697191); +} + +TEST(FloatxOperationsTest, SUB_5_31_simple) +{ + using T = flx::floatx<5, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222224809229374); +} + +TEST(FloatxOperationsTest, SUB_5_32_simple) +{ + using T = flx::floatx<5, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222218988463283); +} + +TEST(FloatxOperationsTest, SUB_5_33_simple) +{ + using T = flx::floatx<5, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222223354037851); +} + +TEST(FloatxOperationsTest, SUB_5_34_simple) +{ + using T = flx::floatx<5, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222221898846328); +} + +TEST(FloatxOperationsTest, SUB_5_35_simple) +{ + using T = flx::floatx<5, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222626442090); +} + +TEST(FloatxOperationsTest, SUB_5_36_simple) +{ + using T = flx::floatx<5, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222080745269); +} + +TEST(FloatxOperationsTest, SUB_5_37_simple) +{ + using T = flx::floatx<5, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222262644209); +} + +TEST(FloatxOperationsTest, SUB_5_38_simple) +{ + using T = flx::floatx<5, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222171694739); +} + +TEST(FloatxOperationsTest, SUB_5_39_simple) +{ + using T = flx::floatx<5, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222239906841); +} + +TEST(FloatxOperationsTest, SUB_5_40_simple) +{ + using T = flx::floatx<5, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222217169474); +} + +TEST(FloatxOperationsTest, SUB_5_41_simple) +{ + using T = flx::floatx<5, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222228538158); +} + +TEST(FloatxOperationsTest, SUB_5_42_simple) +{ + using T = flx::floatx<5, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222220011645); +} + +TEST(FloatxOperationsTest, SUB_5_43_simple) +{ + using T = flx::floatx<5, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222222853816); +} + +TEST(FloatxOperationsTest, SUB_5_44_simple) +{ + using T = flx::floatx<5, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222221432730); +} + +TEST(FloatxOperationsTest, SUB_5_45_simple) +{ + using T = flx::floatx<5, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222498544); +} + +TEST(FloatxOperationsTest, SUB_5_46_simple) +{ + using T = flx::floatx<5, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222143273); +} + +TEST(FloatxOperationsTest, SUB_5_47_simple) +{ + using T = flx::floatx<5, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222320909); +} + +TEST(FloatxOperationsTest, SUB_5_48_simple) +{ + using T = flx::floatx<5, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222187682); +} + +TEST(FloatxOperationsTest, SUB_5_49_simple) +{ + using T = flx::floatx<5, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222232091); +} + +TEST(FloatxOperationsTest, SUB_5_50_simple) +{ + using T = flx::floatx<5, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222209886); +} + +TEST(FloatxOperationsTest, SUB_5_51_simple) +{ + using T = flx::floatx<5, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222215438); +} + +TEST(FloatxOperationsTest, SUB_5_52_simple) +{ + using T = flx::floatx<5, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222220989); +} + +TEST(FloatxOperationsTest, SUB_6_1_simple) +{ + using T = flx::floatx<6, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.25000000000000000000); +} + +TEST(FloatxOperationsTest, SUB_6_2_simple) +{ + using T = flx::floatx<6, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.18750000000000000000); +} + +TEST(FloatxOperationsTest, SUB_6_3_simple) +{ + using T = flx::floatx<6, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.23437500000000000000); +} + +TEST(FloatxOperationsTest, SUB_6_4_simple) +{ + using T = flx::floatx<6, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.21875000000000000000); +} + +TEST(FloatxOperationsTest, SUB_6_5_simple) +{ + using T = flx::floatx<6, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22656250000000000000); +} + +TEST(FloatxOperationsTest, SUB_6_6_simple) +{ + using T = flx::floatx<6, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22070312500000000000); +} + +TEST(FloatxOperationsTest, SUB_6_7_simple) +{ + using T = flx::floatx<6, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22265625000000000000); +} + +TEST(FloatxOperationsTest, SUB_6_8_simple) +{ + using T = flx::floatx<6, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22167968750000000000); +} + +TEST(FloatxOperationsTest, SUB_6_9_simple) +{ + using T = flx::floatx<6, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22241210937500000000); +} + +TEST(FloatxOperationsTest, SUB_6_10_simple) +{ + using T = flx::floatx<6, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22216796875000000000); +} + +TEST(FloatxOperationsTest, SUB_6_11_simple) +{ + using T = flx::floatx<6, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22229003906250000000); +} + +TEST(FloatxOperationsTest, SUB_6_12_simple) +{ + using T = flx::floatx<6, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22219848632812500000); +} + +TEST(FloatxOperationsTest, SUB_6_13_simple) +{ + using T = flx::floatx<6, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22222900390625000000); +} + +TEST(FloatxOperationsTest, SUB_6_14_simple) +{ + using T = flx::floatx<6, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22221374511718750000); +} + +TEST(FloatxOperationsTest, SUB_6_15_simple) +{ + using T = flx::floatx<6, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222518920898437500); +} + +TEST(FloatxOperationsTest, SUB_6_16_simple) +{ + using T = flx::floatx<6, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222137451171875000); +} + +TEST(FloatxOperationsTest, SUB_6_17_simple) +{ + using T = flx::floatx<6, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222328186035156250); +} + +TEST(FloatxOperationsTest, SUB_6_18_simple) +{ + using T = flx::floatx<6, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222185134887695312); +} + +TEST(FloatxOperationsTest, SUB_6_19_simple) +{ + using T = flx::floatx<6, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222232818603515625); +} + +TEST(FloatxOperationsTest, SUB_6_20_simple) +{ + using T = flx::floatx<6, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222208976745605469); +} + +TEST(FloatxOperationsTest, SUB_6_21_simple) +{ + using T = flx::floatx<6, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222226858139038086); +} + +TEST(FloatxOperationsTest, SUB_6_22_simple) +{ + using T = flx::floatx<6, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222220897674560547); +} + +TEST(FloatxOperationsTest, SUB_6_23_simple) +{ + using T = flx::floatx<6, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222223877906799316); +} + +TEST(FloatxOperationsTest, SUB_6_24_simple) +{ + using T = flx::floatx<6, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222221642732620239); +} + +TEST(FloatxOperationsTest, SUB_6_25_simple) +{ + using T = flx::floatx<6, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222222387790679932); +} + +TEST(FloatxOperationsTest, SUB_6_26_simple) +{ + using T = flx::floatx<6, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222015261650085); +} + +TEST(FloatxOperationsTest, SUB_6_27_simple) +{ + using T = flx::floatx<6, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222294658422470); +} + +TEST(FloatxOperationsTest, SUB_6_28_simple) +{ + using T = flx::floatx<6, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222201526165009); +} + +TEST(FloatxOperationsTest, SUB_6_29_simple) +{ + using T = flx::floatx<6, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222248092293739); +} + +TEST(FloatxOperationsTest, SUB_6_30_simple) +{ + using T = flx::floatx<6, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222213167697191); +} + +TEST(FloatxOperationsTest, SUB_6_31_simple) +{ + using T = flx::floatx<6, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222224809229374); +} + +TEST(FloatxOperationsTest, SUB_6_32_simple) +{ + using T = flx::floatx<6, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222218988463283); +} + +TEST(FloatxOperationsTest, SUB_6_33_simple) +{ + using T = flx::floatx<6, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222223354037851); +} + +TEST(FloatxOperationsTest, SUB_6_34_simple) +{ + using T = flx::floatx<6, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222221898846328); +} + +TEST(FloatxOperationsTest, SUB_6_35_simple) +{ + using T = flx::floatx<6, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222626442090); +} + +TEST(FloatxOperationsTest, SUB_6_36_simple) +{ + using T = flx::floatx<6, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222080745269); +} + +TEST(FloatxOperationsTest, SUB_6_37_simple) +{ + using T = flx::floatx<6, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222262644209); +} + +TEST(FloatxOperationsTest, SUB_6_38_simple) +{ + using T = flx::floatx<6, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222171694739); +} + +TEST(FloatxOperationsTest, SUB_6_39_simple) +{ + using T = flx::floatx<6, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222239906841); +} + +TEST(FloatxOperationsTest, SUB_6_40_simple) +{ + using T = flx::floatx<6, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222217169474); +} + +TEST(FloatxOperationsTest, SUB_6_41_simple) +{ + using T = flx::floatx<6, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222228538158); +} + +TEST(FloatxOperationsTest, SUB_6_42_simple) +{ + using T = flx::floatx<6, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222220011645); +} + +TEST(FloatxOperationsTest, SUB_6_43_simple) +{ + using T = flx::floatx<6, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222222853816); +} + +TEST(FloatxOperationsTest, SUB_6_44_simple) +{ + using T = flx::floatx<6, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222221432730); +} + +TEST(FloatxOperationsTest, SUB_6_45_simple) +{ + using T = flx::floatx<6, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222498544); +} + +TEST(FloatxOperationsTest, SUB_6_46_simple) +{ + using T = flx::floatx<6, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222143273); +} + +TEST(FloatxOperationsTest, SUB_6_47_simple) +{ + using T = flx::floatx<6, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222320909); +} + +TEST(FloatxOperationsTest, SUB_6_48_simple) +{ + using T = flx::floatx<6, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222187682); +} + +TEST(FloatxOperationsTest, SUB_6_49_simple) +{ + using T = flx::floatx<6, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222232091); +} + +TEST(FloatxOperationsTest, SUB_6_50_simple) +{ + using T = flx::floatx<6, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222209886); +} + +TEST(FloatxOperationsTest, SUB_6_51_simple) +{ + using T = flx::floatx<6, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222215438); +} + +TEST(FloatxOperationsTest, SUB_6_52_simple) +{ + using T = flx::floatx<6, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222220989); +} + +TEST(FloatxOperationsTest, SUB_7_1_simple) +{ + using T = flx::floatx<7, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.25000000000000000000); +} + +TEST(FloatxOperationsTest, SUB_7_2_simple) +{ + using T = flx::floatx<7, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.18750000000000000000); +} + +TEST(FloatxOperationsTest, SUB_7_3_simple) +{ + using T = flx::floatx<7, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.23437500000000000000); +} + +TEST(FloatxOperationsTest, SUB_7_4_simple) +{ + using T = flx::floatx<7, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.21875000000000000000); +} + +TEST(FloatxOperationsTest, SUB_7_5_simple) +{ + using T = flx::floatx<7, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22656250000000000000); +} + +TEST(FloatxOperationsTest, SUB_7_6_simple) +{ + using T = flx::floatx<7, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22070312500000000000); +} + +TEST(FloatxOperationsTest, SUB_7_7_simple) +{ + using T = flx::floatx<7, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22265625000000000000); +} + +TEST(FloatxOperationsTest, SUB_7_8_simple) +{ + using T = flx::floatx<7, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22167968750000000000); +} + +TEST(FloatxOperationsTest, SUB_7_9_simple) +{ + using T = flx::floatx<7, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22241210937500000000); +} + +TEST(FloatxOperationsTest, SUB_7_10_simple) +{ + using T = flx::floatx<7, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22216796875000000000); +} + +TEST(FloatxOperationsTest, SUB_7_11_simple) +{ + using T = flx::floatx<7, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22229003906250000000); +} + +TEST(FloatxOperationsTest, SUB_7_12_simple) +{ + using T = flx::floatx<7, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22219848632812500000); +} + +TEST(FloatxOperationsTest, SUB_7_13_simple) +{ + using T = flx::floatx<7, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22222900390625000000); +} + +TEST(FloatxOperationsTest, SUB_7_14_simple) +{ + using T = flx::floatx<7, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22221374511718750000); +} + +TEST(FloatxOperationsTest, SUB_7_15_simple) +{ + using T = flx::floatx<7, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222518920898437500); +} + +TEST(FloatxOperationsTest, SUB_7_16_simple) +{ + using T = flx::floatx<7, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222137451171875000); +} + +TEST(FloatxOperationsTest, SUB_7_17_simple) +{ + using T = flx::floatx<7, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222328186035156250); +} + +TEST(FloatxOperationsTest, SUB_7_18_simple) +{ + using T = flx::floatx<7, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222185134887695312); +} + +TEST(FloatxOperationsTest, SUB_7_19_simple) +{ + using T = flx::floatx<7, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222232818603515625); +} + +TEST(FloatxOperationsTest, SUB_7_20_simple) +{ + using T = flx::floatx<7, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222208976745605469); +} + +TEST(FloatxOperationsTest, SUB_7_21_simple) +{ + using T = flx::floatx<7, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222226858139038086); +} + +TEST(FloatxOperationsTest, SUB_7_22_simple) +{ + using T = flx::floatx<7, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222220897674560547); +} + +TEST(FloatxOperationsTest, SUB_7_23_simple) +{ + using T = flx::floatx<7, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222223877906799316); +} + +TEST(FloatxOperationsTest, SUB_7_24_simple) +{ + using T = flx::floatx<7, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222221642732620239); +} + +TEST(FloatxOperationsTest, SUB_7_25_simple) +{ + using T = flx::floatx<7, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222222387790679932); +} + +TEST(FloatxOperationsTest, SUB_7_26_simple) +{ + using T = flx::floatx<7, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222015261650085); +} + +TEST(FloatxOperationsTest, SUB_7_27_simple) +{ + using T = flx::floatx<7, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222294658422470); +} + +TEST(FloatxOperationsTest, SUB_7_28_simple) +{ + using T = flx::floatx<7, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222201526165009); +} + +TEST(FloatxOperationsTest, SUB_7_29_simple) +{ + using T = flx::floatx<7, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222248092293739); +} + +TEST(FloatxOperationsTest, SUB_7_30_simple) +{ + using T = flx::floatx<7, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222213167697191); +} + +TEST(FloatxOperationsTest, SUB_7_31_simple) +{ + using T = flx::floatx<7, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222224809229374); +} + +TEST(FloatxOperationsTest, SUB_7_32_simple) +{ + using T = flx::floatx<7, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222218988463283); +} + +TEST(FloatxOperationsTest, SUB_7_33_simple) +{ + using T = flx::floatx<7, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222223354037851); +} + +TEST(FloatxOperationsTest, SUB_7_34_simple) +{ + using T = flx::floatx<7, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222221898846328); +} + +TEST(FloatxOperationsTest, SUB_7_35_simple) +{ + using T = flx::floatx<7, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222626442090); +} + +TEST(FloatxOperationsTest, SUB_7_36_simple) +{ + using T = flx::floatx<7, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222080745269); +} + +TEST(FloatxOperationsTest, SUB_7_37_simple) +{ + using T = flx::floatx<7, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222262644209); +} + +TEST(FloatxOperationsTest, SUB_7_38_simple) +{ + using T = flx::floatx<7, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222171694739); +} + +TEST(FloatxOperationsTest, SUB_7_39_simple) +{ + using T = flx::floatx<7, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222239906841); +} + +TEST(FloatxOperationsTest, SUB_7_40_simple) +{ + using T = flx::floatx<7, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222217169474); +} + +TEST(FloatxOperationsTest, SUB_7_41_simple) +{ + using T = flx::floatx<7, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222228538158); +} + +TEST(FloatxOperationsTest, SUB_7_42_simple) +{ + using T = flx::floatx<7, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222220011645); +} + +TEST(FloatxOperationsTest, SUB_7_43_simple) +{ + using T = flx::floatx<7, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222222853816); +} + +TEST(FloatxOperationsTest, SUB_7_44_simple) +{ + using T = flx::floatx<7, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222221432730); +} + +TEST(FloatxOperationsTest, SUB_7_45_simple) +{ + using T = flx::floatx<7, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222498544); +} + +TEST(FloatxOperationsTest, SUB_7_46_simple) +{ + using T = flx::floatx<7, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222143273); +} + +TEST(FloatxOperationsTest, SUB_7_47_simple) +{ + using T = flx::floatx<7, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222320909); +} + +TEST(FloatxOperationsTest, SUB_7_48_simple) +{ + using T = flx::floatx<7, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222187682); +} + +TEST(FloatxOperationsTest, SUB_7_49_simple) +{ + using T = flx::floatx<7, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222232091); +} + +TEST(FloatxOperationsTest, SUB_7_50_simple) +{ + using T = flx::floatx<7, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222209886); +} + +TEST(FloatxOperationsTest, SUB_7_51_simple) +{ + using T = flx::floatx<7, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222215438); +} + +TEST(FloatxOperationsTest, SUB_7_52_simple) +{ + using T = flx::floatx<7, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222220989); +} + +TEST(FloatxOperationsTest, SUB_8_1_simple) +{ + using T = flx::floatx<8, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.25000000000000000000); +} + +TEST(FloatxOperationsTest, SUB_8_2_simple) +{ + using T = flx::floatx<8, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.18750000000000000000); +} + +TEST(FloatxOperationsTest, SUB_8_3_simple) +{ + using T = flx::floatx<8, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.23437500000000000000); +} + +TEST(FloatxOperationsTest, SUB_8_4_simple) +{ + using T = flx::floatx<8, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.21875000000000000000); +} + +TEST(FloatxOperationsTest, SUB_8_5_simple) +{ + using T = flx::floatx<8, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22656250000000000000); +} + +TEST(FloatxOperationsTest, SUB_8_6_simple) +{ + using T = flx::floatx<8, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22070312500000000000); +} + +TEST(FloatxOperationsTest, SUB_8_7_simple) +{ + using T = flx::floatx<8, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22265625000000000000); +} + +TEST(FloatxOperationsTest, SUB_8_8_simple) +{ + using T = flx::floatx<8, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22167968750000000000); +} + +TEST(FloatxOperationsTest, SUB_8_9_simple) +{ + using T = flx::floatx<8, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22241210937500000000); +} + +TEST(FloatxOperationsTest, SUB_8_10_simple) +{ + using T = flx::floatx<8, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22216796875000000000); +} + +TEST(FloatxOperationsTest, SUB_8_11_simple) +{ + using T = flx::floatx<8, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22229003906250000000); +} + +TEST(FloatxOperationsTest, SUB_8_12_simple) +{ + using T = flx::floatx<8, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22219848632812500000); +} + +TEST(FloatxOperationsTest, SUB_8_13_simple) +{ + using T = flx::floatx<8, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22222900390625000000); +} + +TEST(FloatxOperationsTest, SUB_8_14_simple) +{ + using T = flx::floatx<8, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22221374511718750000); +} + +TEST(FloatxOperationsTest, SUB_8_15_simple) +{ + using T = flx::floatx<8, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222518920898437500); +} + +TEST(FloatxOperationsTest, SUB_8_16_simple) +{ + using T = flx::floatx<8, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222137451171875000); +} + +TEST(FloatxOperationsTest, SUB_8_17_simple) +{ + using T = flx::floatx<8, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222328186035156250); +} + +TEST(FloatxOperationsTest, SUB_8_18_simple) +{ + using T = flx::floatx<8, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222185134887695312); +} + +TEST(FloatxOperationsTest, SUB_8_19_simple) +{ + using T = flx::floatx<8, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222232818603515625); +} + +TEST(FloatxOperationsTest, SUB_8_20_simple) +{ + using T = flx::floatx<8, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222208976745605469); +} + +TEST(FloatxOperationsTest, SUB_8_21_simple) +{ + using T = flx::floatx<8, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222226858139038086); +} + +TEST(FloatxOperationsTest, SUB_8_22_simple) +{ + using T = flx::floatx<8, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222220897674560547); +} + +TEST(FloatxOperationsTest, SUB_8_23_simple) +{ + using T = flx::floatx<8, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222223877906799316); +} + +TEST(FloatxOperationsTest, SUB_8_24_simple) +{ + using T = flx::floatx<8, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222221642732620239); +} + +TEST(FloatxOperationsTest, SUB_8_25_simple) +{ + using T = flx::floatx<8, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222222387790679932); +} + +TEST(FloatxOperationsTest, SUB_8_26_simple) +{ + using T = flx::floatx<8, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222015261650085); +} + +TEST(FloatxOperationsTest, SUB_8_27_simple) +{ + using T = flx::floatx<8, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222294658422470); +} + +TEST(FloatxOperationsTest, SUB_8_28_simple) +{ + using T = flx::floatx<8, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222201526165009); +} + +TEST(FloatxOperationsTest, SUB_8_29_simple) +{ + using T = flx::floatx<8, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222248092293739); +} + +TEST(FloatxOperationsTest, SUB_8_30_simple) +{ + using T = flx::floatx<8, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222213167697191); +} + +TEST(FloatxOperationsTest, SUB_8_31_simple) +{ + using T = flx::floatx<8, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222224809229374); +} + +TEST(FloatxOperationsTest, SUB_8_32_simple) +{ + using T = flx::floatx<8, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222218988463283); +} + +TEST(FloatxOperationsTest, SUB_8_33_simple) +{ + using T = flx::floatx<8, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222223354037851); +} + +TEST(FloatxOperationsTest, SUB_8_34_simple) +{ + using T = flx::floatx<8, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222221898846328); +} + +TEST(FloatxOperationsTest, SUB_8_35_simple) +{ + using T = flx::floatx<8, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222626442090); +} + +TEST(FloatxOperationsTest, SUB_8_36_simple) +{ + using T = flx::floatx<8, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222080745269); +} + +TEST(FloatxOperationsTest, SUB_8_37_simple) +{ + using T = flx::floatx<8, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222262644209); +} + +TEST(FloatxOperationsTest, SUB_8_38_simple) +{ + using T = flx::floatx<8, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222171694739); +} + +TEST(FloatxOperationsTest, SUB_8_39_simple) +{ + using T = flx::floatx<8, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222239906841); +} + +TEST(FloatxOperationsTest, SUB_8_40_simple) +{ + using T = flx::floatx<8, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222217169474); +} + +TEST(FloatxOperationsTest, SUB_8_41_simple) +{ + using T = flx::floatx<8, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222228538158); +} + +TEST(FloatxOperationsTest, SUB_8_42_simple) +{ + using T = flx::floatx<8, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222220011645); +} + +TEST(FloatxOperationsTest, SUB_8_43_simple) +{ + using T = flx::floatx<8, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222222853816); +} + +TEST(FloatxOperationsTest, SUB_8_44_simple) +{ + using T = flx::floatx<8, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222221432730); +} + +TEST(FloatxOperationsTest, SUB_8_45_simple) +{ + using T = flx::floatx<8, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222498544); +} + +TEST(FloatxOperationsTest, SUB_8_46_simple) +{ + using T = flx::floatx<8, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222143273); +} + +TEST(FloatxOperationsTest, SUB_8_47_simple) +{ + using T = flx::floatx<8, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222320909); +} + +TEST(FloatxOperationsTest, SUB_8_48_simple) +{ + using T = flx::floatx<8, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222187682); +} + +TEST(FloatxOperationsTest, SUB_8_49_simple) +{ + using T = flx::floatx<8, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222232091); +} + +TEST(FloatxOperationsTest, SUB_8_50_simple) +{ + using T = flx::floatx<8, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222209886); +} + +TEST(FloatxOperationsTest, SUB_8_51_simple) +{ + using T = flx::floatx<8, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222215438); +} + +TEST(FloatxOperationsTest, SUB_8_52_simple) +{ + using T = flx::floatx<8, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222220989); +} + +TEST(FloatxOperationsTest, SUB_9_1_simple) +{ + using T = flx::floatx<9, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.25000000000000000000); +} + +TEST(FloatxOperationsTest, SUB_9_2_simple) +{ + using T = flx::floatx<9, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.18750000000000000000); +} + +TEST(FloatxOperationsTest, SUB_9_3_simple) +{ + using T = flx::floatx<9, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.23437500000000000000); +} + +TEST(FloatxOperationsTest, SUB_9_4_simple) +{ + using T = flx::floatx<9, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.21875000000000000000); +} + +TEST(FloatxOperationsTest, SUB_9_5_simple) +{ + using T = flx::floatx<9, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22656250000000000000); +} + +TEST(FloatxOperationsTest, SUB_9_6_simple) +{ + using T = flx::floatx<9, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22070312500000000000); +} + +TEST(FloatxOperationsTest, SUB_9_7_simple) +{ + using T = flx::floatx<9, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22265625000000000000); +} + +TEST(FloatxOperationsTest, SUB_9_8_simple) +{ + using T = flx::floatx<9, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22167968750000000000); +} + +TEST(FloatxOperationsTest, SUB_9_9_simple) +{ + using T = flx::floatx<9, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22241210937500000000); +} + +TEST(FloatxOperationsTest, SUB_9_10_simple) +{ + using T = flx::floatx<9, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22216796875000000000); +} + +TEST(FloatxOperationsTest, SUB_9_11_simple) +{ + using T = flx::floatx<9, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22229003906250000000); +} + +TEST(FloatxOperationsTest, SUB_9_12_simple) +{ + using T = flx::floatx<9, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22219848632812500000); +} + +TEST(FloatxOperationsTest, SUB_9_13_simple) +{ + using T = flx::floatx<9, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22222900390625000000); +} + +TEST(FloatxOperationsTest, SUB_9_14_simple) +{ + using T = flx::floatx<9, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22221374511718750000); +} + +TEST(FloatxOperationsTest, SUB_9_15_simple) +{ + using T = flx::floatx<9, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222518920898437500); +} + +TEST(FloatxOperationsTest, SUB_9_16_simple) +{ + using T = flx::floatx<9, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222137451171875000); +} + +TEST(FloatxOperationsTest, SUB_9_17_simple) +{ + using T = flx::floatx<9, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222328186035156250); +} + +TEST(FloatxOperationsTest, SUB_9_18_simple) +{ + using T = flx::floatx<9, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222185134887695312); +} + +TEST(FloatxOperationsTest, SUB_9_19_simple) +{ + using T = flx::floatx<9, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222232818603515625); +} + +TEST(FloatxOperationsTest, SUB_9_20_simple) +{ + using T = flx::floatx<9, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222208976745605469); +} + +TEST(FloatxOperationsTest, SUB_9_21_simple) +{ + using T = flx::floatx<9, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222226858139038086); +} + +TEST(FloatxOperationsTest, SUB_9_22_simple) +{ + using T = flx::floatx<9, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222220897674560547); +} + +TEST(FloatxOperationsTest, SUB_9_23_simple) +{ + using T = flx::floatx<9, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222223877906799316); +} + +TEST(FloatxOperationsTest, SUB_9_24_simple) +{ + using T = flx::floatx<9, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222221642732620239); +} + +TEST(FloatxOperationsTest, SUB_9_25_simple) +{ + using T = flx::floatx<9, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222222387790679932); +} + +TEST(FloatxOperationsTest, SUB_9_26_simple) +{ + using T = flx::floatx<9, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222015261650085); +} + +TEST(FloatxOperationsTest, SUB_9_27_simple) +{ + using T = flx::floatx<9, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222294658422470); +} + +TEST(FloatxOperationsTest, SUB_9_28_simple) +{ + using T = flx::floatx<9, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222201526165009); +} + +TEST(FloatxOperationsTest, SUB_9_29_simple) +{ + using T = flx::floatx<9, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222248092293739); +} + +TEST(FloatxOperationsTest, SUB_9_30_simple) +{ + using T = flx::floatx<9, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222213167697191); +} + +TEST(FloatxOperationsTest, SUB_9_31_simple) +{ + using T = flx::floatx<9, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222224809229374); +} + +TEST(FloatxOperationsTest, SUB_9_32_simple) +{ + using T = flx::floatx<9, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222218988463283); +} + +TEST(FloatxOperationsTest, SUB_9_33_simple) +{ + using T = flx::floatx<9, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222223354037851); +} + +TEST(FloatxOperationsTest, SUB_9_34_simple) +{ + using T = flx::floatx<9, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222221898846328); +} + +TEST(FloatxOperationsTest, SUB_9_35_simple) +{ + using T = flx::floatx<9, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222626442090); +} + +TEST(FloatxOperationsTest, SUB_9_36_simple) +{ + using T = flx::floatx<9, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222080745269); +} + +TEST(FloatxOperationsTest, SUB_9_37_simple) +{ + using T = flx::floatx<9, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222262644209); +} + +TEST(FloatxOperationsTest, SUB_9_38_simple) +{ + using T = flx::floatx<9, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222171694739); +} + +TEST(FloatxOperationsTest, SUB_9_39_simple) +{ + using T = flx::floatx<9, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222239906841); +} + +TEST(FloatxOperationsTest, SUB_9_40_simple) +{ + using T = flx::floatx<9, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222217169474); +} + +TEST(FloatxOperationsTest, SUB_9_41_simple) +{ + using T = flx::floatx<9, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222228538158); +} + +TEST(FloatxOperationsTest, SUB_9_42_simple) +{ + using T = flx::floatx<9, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222220011645); +} + +TEST(FloatxOperationsTest, SUB_9_43_simple) +{ + using T = flx::floatx<9, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222222853816); +} + +TEST(FloatxOperationsTest, SUB_9_44_simple) +{ + using T = flx::floatx<9, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222221432730); +} + +TEST(FloatxOperationsTest, SUB_9_45_simple) +{ + using T = flx::floatx<9, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222498544); +} + +TEST(FloatxOperationsTest, SUB_9_46_simple) +{ + using T = flx::floatx<9, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222143273); +} + +TEST(FloatxOperationsTest, SUB_9_47_simple) +{ + using T = flx::floatx<9, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222320909); +} + +TEST(FloatxOperationsTest, SUB_9_48_simple) +{ + using T = flx::floatx<9, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222187682); +} + +TEST(FloatxOperationsTest, SUB_9_49_simple) +{ + using T = flx::floatx<9, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222232091); +} + +TEST(FloatxOperationsTest, SUB_9_50_simple) +{ + using T = flx::floatx<9, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222209886); +} + +TEST(FloatxOperationsTest, SUB_9_51_simple) +{ + using T = flx::floatx<9, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222215438); +} + +TEST(FloatxOperationsTest, SUB_9_52_simple) +{ + using T = flx::floatx<9, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222220989); +} + +TEST(FloatxOperationsTest, SUB_10_1_simple) +{ + using T = flx::floatx<10, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.25000000000000000000); +} + +TEST(FloatxOperationsTest, SUB_10_2_simple) +{ + using T = flx::floatx<10, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.18750000000000000000); +} + +TEST(FloatxOperationsTest, SUB_10_3_simple) +{ + using T = flx::floatx<10, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.23437500000000000000); +} + +TEST(FloatxOperationsTest, SUB_10_4_simple) +{ + using T = flx::floatx<10, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.21875000000000000000); +} + +TEST(FloatxOperationsTest, SUB_10_5_simple) +{ + using T = flx::floatx<10, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22656250000000000000); +} + +TEST(FloatxOperationsTest, SUB_10_6_simple) +{ + using T = flx::floatx<10, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22070312500000000000); +} + +TEST(FloatxOperationsTest, SUB_10_7_simple) +{ + using T = flx::floatx<10, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22265625000000000000); +} + +TEST(FloatxOperationsTest, SUB_10_8_simple) +{ + using T = flx::floatx<10, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22167968750000000000); +} + +TEST(FloatxOperationsTest, SUB_10_9_simple) +{ + using T = flx::floatx<10, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22241210937500000000); +} + +TEST(FloatxOperationsTest, SUB_10_10_simple) +{ + using T = flx::floatx<10, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22216796875000000000); +} + +TEST(FloatxOperationsTest, SUB_10_11_simple) +{ + using T = flx::floatx<10, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22229003906250000000); +} + +TEST(FloatxOperationsTest, SUB_10_12_simple) +{ + using T = flx::floatx<10, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22219848632812500000); +} + +TEST(FloatxOperationsTest, SUB_10_13_simple) +{ + using T = flx::floatx<10, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22222900390625000000); +} + +TEST(FloatxOperationsTest, SUB_10_14_simple) +{ + using T = flx::floatx<10, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22221374511718750000); +} + +TEST(FloatxOperationsTest, SUB_10_15_simple) +{ + using T = flx::floatx<10, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222518920898437500); +} + +TEST(FloatxOperationsTest, SUB_10_16_simple) +{ + using T = flx::floatx<10, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222137451171875000); +} + +TEST(FloatxOperationsTest, SUB_10_17_simple) +{ + using T = flx::floatx<10, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222328186035156250); +} + +TEST(FloatxOperationsTest, SUB_10_18_simple) +{ + using T = flx::floatx<10, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222185134887695312); +} + +TEST(FloatxOperationsTest, SUB_10_19_simple) +{ + using T = flx::floatx<10, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222232818603515625); +} + +TEST(FloatxOperationsTest, SUB_10_20_simple) +{ + using T = flx::floatx<10, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222208976745605469); +} + +TEST(FloatxOperationsTest, SUB_10_21_simple) +{ + using T = flx::floatx<10, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222226858139038086); +} + +TEST(FloatxOperationsTest, SUB_10_22_simple) +{ + using T = flx::floatx<10, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222220897674560547); +} + +TEST(FloatxOperationsTest, SUB_10_23_simple) +{ + using T = flx::floatx<10, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222223877906799316); +} + +TEST(FloatxOperationsTest, SUB_10_24_simple) +{ + using T = flx::floatx<10, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222221642732620239); +} + +TEST(FloatxOperationsTest, SUB_10_25_simple) +{ + using T = flx::floatx<10, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222222387790679932); +} + +TEST(FloatxOperationsTest, SUB_10_26_simple) +{ + using T = flx::floatx<10, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222015261650085); +} + +TEST(FloatxOperationsTest, SUB_10_27_simple) +{ + using T = flx::floatx<10, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222294658422470); +} + +TEST(FloatxOperationsTest, SUB_10_28_simple) +{ + using T = flx::floatx<10, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222201526165009); +} + +TEST(FloatxOperationsTest, SUB_10_29_simple) +{ + using T = flx::floatx<10, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222248092293739); +} + +TEST(FloatxOperationsTest, SUB_10_30_simple) +{ + using T = flx::floatx<10, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222213167697191); +} + +TEST(FloatxOperationsTest, SUB_10_31_simple) +{ + using T = flx::floatx<10, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222224809229374); +} + +TEST(FloatxOperationsTest, SUB_10_32_simple) +{ + using T = flx::floatx<10, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222218988463283); +} + +TEST(FloatxOperationsTest, SUB_10_33_simple) +{ + using T = flx::floatx<10, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222223354037851); +} + +TEST(FloatxOperationsTest, SUB_10_34_simple) +{ + using T = flx::floatx<10, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222221898846328); +} + +TEST(FloatxOperationsTest, SUB_10_35_simple) +{ + using T = flx::floatx<10, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222626442090); +} + +TEST(FloatxOperationsTest, SUB_10_36_simple) +{ + using T = flx::floatx<10, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222080745269); +} + +TEST(FloatxOperationsTest, SUB_10_37_simple) +{ + using T = flx::floatx<10, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222262644209); +} + +TEST(FloatxOperationsTest, SUB_10_38_simple) +{ + using T = flx::floatx<10, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222171694739); +} + +TEST(FloatxOperationsTest, SUB_10_39_simple) +{ + using T = flx::floatx<10, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222239906841); +} + +TEST(FloatxOperationsTest, SUB_10_40_simple) +{ + using T = flx::floatx<10, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222217169474); +} + +TEST(FloatxOperationsTest, SUB_10_41_simple) +{ + using T = flx::floatx<10, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222228538158); +} + +TEST(FloatxOperationsTest, SUB_10_42_simple) +{ + using T = flx::floatx<10, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222220011645); +} + +TEST(FloatxOperationsTest, SUB_10_43_simple) +{ + using T = flx::floatx<10, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222222853816); +} + +TEST(FloatxOperationsTest, SUB_10_44_simple) +{ + using T = flx::floatx<10, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222221432730); +} + +TEST(FloatxOperationsTest, SUB_10_45_simple) +{ + using T = flx::floatx<10, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222498544); +} + +TEST(FloatxOperationsTest, SUB_10_46_simple) +{ + using T = flx::floatx<10, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222143273); +} + +TEST(FloatxOperationsTest, SUB_10_47_simple) +{ + using T = flx::floatx<10, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222320909); +} + +TEST(FloatxOperationsTest, SUB_10_48_simple) +{ + using T = flx::floatx<10, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222187682); +} + +TEST(FloatxOperationsTest, SUB_10_49_simple) +{ + using T = flx::floatx<10, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222232091); +} + +TEST(FloatxOperationsTest, SUB_10_50_simple) +{ + using T = flx::floatx<10, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222209886); +} + +TEST(FloatxOperationsTest, SUB_10_51_simple) +{ + using T = flx::floatx<10, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222215438); +} + +TEST(FloatxOperationsTest, SUB_10_52_simple) +{ + using T = flx::floatx<10, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222220989); +} + +TEST(FloatxOperationsTest, SUB_11_1_simple) +{ + using T = flx::floatx<11, 1>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.37500000000000000000); + EXPECT_EQ(double(b), 0.12500000000000000000); + EXPECT_EQ(double(c), 0.25000000000000000000); +} + +TEST(FloatxOperationsTest, SUB_11_2_simple) +{ + using T = flx::floatx<11, 2>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.31250000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.18750000000000000000); +} + +TEST(FloatxOperationsTest, SUB_11_3_simple) +{ + using T = flx::floatx<11, 3>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.34375000000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.23437500000000000000); +} + +TEST(FloatxOperationsTest, SUB_11_4_simple) +{ + using T = flx::floatx<11, 4>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.32812500000000000000); + EXPECT_EQ(double(b), 0.10937500000000000000); + EXPECT_EQ(double(c), 0.21875000000000000000); +} + +TEST(FloatxOperationsTest, SUB_11_5_simple) +{ + using T = flx::floatx<11, 5>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33593750000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22656250000000000000); +} + +TEST(FloatxOperationsTest, SUB_11_6_simple) +{ + using T = flx::floatx<11, 6>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33203125000000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22070312500000000000); +} + +TEST(FloatxOperationsTest, SUB_11_7_simple) +{ + using T = flx::floatx<11, 7>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33398437500000000000); + EXPECT_EQ(double(b), 0.11132812500000000000); + EXPECT_EQ(double(c), 0.22265625000000000000); +} + +TEST(FloatxOperationsTest, SUB_11_8_simple) +{ + using T = flx::floatx<11, 8>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33300781250000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22167968750000000000); +} + +TEST(FloatxOperationsTest, SUB_11_9_simple) +{ + using T = flx::floatx<11, 9>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33349609375000000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22241210937500000000); +} + +TEST(FloatxOperationsTest, SUB_11_10_simple) +{ + using T = flx::floatx<11, 10>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33325195312500000000); + EXPECT_EQ(double(b), 0.11108398437500000000); + EXPECT_EQ(double(c), 0.22216796875000000000); +} + +TEST(FloatxOperationsTest, SUB_11_11_simple) +{ + using T = flx::floatx<11, 11>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33337402343750000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22229003906250000000); +} + +TEST(FloatxOperationsTest, SUB_11_12_simple) +{ + using T = flx::floatx<11, 12>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33331298828125000000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22219848632812500000); +} + +TEST(FloatxOperationsTest, SUB_11_13_simple) +{ + using T = flx::floatx<11, 13>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33334350585937500000); + EXPECT_EQ(double(b), 0.11111450195312500000); + EXPECT_EQ(double(c), 0.22222900390625000000); +} + +TEST(FloatxOperationsTest, SUB_11_14_simple) +{ + using T = flx::floatx<11, 14>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33332824707031250000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22221374511718750000); +} + +TEST(FloatxOperationsTest, SUB_11_15_simple) +{ + using T = flx::floatx<11, 15>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333587646484375000); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222518920898437500); +} + +TEST(FloatxOperationsTest, SUB_11_16_simple) +{ + using T = flx::floatx<11, 16>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333206176757812500); + EXPECT_EQ(double(b), 0.11111068725585937500); + EXPECT_EQ(double(c), 0.22222137451171875000); +} + +TEST(FloatxOperationsTest, SUB_11_17_simple) +{ + using T = flx::floatx<11, 17>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333396911621093750); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222328186035156250); +} + +TEST(FloatxOperationsTest, SUB_11_18_simple) +{ + using T = flx::floatx<11, 18>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333301544189453125); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222185134887695312); +} + +TEST(FloatxOperationsTest, SUB_11_19_simple) +{ + using T = flx::floatx<11, 19>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333349227905273438); + EXPECT_EQ(double(b), 0.11111116409301757812); + EXPECT_EQ(double(c), 0.22222232818603515625); +} + +TEST(FloatxOperationsTest, SUB_11_20_simple) +{ + using T = flx::floatx<11, 20>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333325386047363281); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222208976745605469); +} + +TEST(FloatxOperationsTest, SUB_11_21_simple) +{ + using T = flx::floatx<11, 21>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333337306976318359); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222226858139038086); +} + +TEST(FloatxOperationsTest, SUB_11_22_simple) +{ + using T = flx::floatx<11, 22>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333331346511840820); + EXPECT_EQ(double(b), 0.11111110448837280273); + EXPECT_EQ(double(c), 0.22222220897674560547); +} + +TEST(FloatxOperationsTest, SUB_11_23_simple) +{ + using T = flx::floatx<11, 23>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333334326744079590); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222223877906799316); +} + +TEST(FloatxOperationsTest, SUB_11_24_simple) +{ + using T = flx::floatx<11, 24>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333332836627960205); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222221642732620239); +} + +TEST(FloatxOperationsTest, SUB_11_25_simple) +{ + using T = flx::floatx<11, 25>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333581686019897); + EXPECT_EQ(double(b), 0.11111111193895339966); + EXPECT_EQ(double(c), 0.22222222387790679932); +} + +TEST(FloatxOperationsTest, SUB_11_26_simple) +{ + using T = flx::floatx<11, 26>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333209156990051); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222015261650085); +} + +TEST(FloatxOperationsTest, SUB_11_27_simple) +{ + using T = flx::floatx<11, 27>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333395421504974); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222294658422470); +} + +TEST(FloatxOperationsTest, SUB_11_28_simple) +{ + using T = flx::floatx<11, 28>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333302289247513); + EXPECT_EQ(double(b), 0.11111111100763082504); + EXPECT_EQ(double(c), 0.22222222201526165009); +} + +TEST(FloatxOperationsTest, SUB_11_29_simple) +{ + using T = flx::floatx<11, 29>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333348855376244); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222248092293739); +} + +TEST(FloatxOperationsTest, SUB_11_30_simple) +{ + using T = flx::floatx<11, 30>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333325572311878); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222213167697191); +} + +TEST(FloatxOperationsTest, SUB_11_31_simple) +{ + using T = flx::floatx<11, 31>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333337213844061); + EXPECT_EQ(double(b), 0.11111111112404614687); + EXPECT_EQ(double(c), 0.22222222224809229374); +} + +TEST(FloatxOperationsTest, SUB_11_32_simple) +{ + using T = flx::floatx<11, 32>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333331393077970); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222218988463283); +} + +TEST(FloatxOperationsTest, SUB_11_33_simple) +{ + using T = flx::floatx<11, 33>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333334303461015); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222223354037851); +} + +TEST(FloatxOperationsTest, SUB_11_34_simple) +{ + using T = flx::floatx<11, 34>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333332848269492); + EXPECT_EQ(double(b), 0.11111111110949423164); + EXPECT_EQ(double(c), 0.22222222221898846328); +} + +TEST(FloatxOperationsTest, SUB_11_35_simple) +{ + using T = flx::floatx<11, 35>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333575865254); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222626442090); +} + +TEST(FloatxOperationsTest, SUB_11_36_simple) +{ + using T = flx::floatx<11, 36>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333212067373); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222080745269); +} + +TEST(FloatxOperationsTest, SUB_11_37_simple) +{ + using T = flx::floatx<11, 37>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333393966313); + EXPECT_EQ(double(b), 0.11111111111131322104); + EXPECT_EQ(double(c), 0.22222222222262644209); +} + +TEST(FloatxOperationsTest, SUB_11_38_simple) +{ + using T = flx::floatx<11, 38>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333303016843); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222171694739); +} + +TEST(FloatxOperationsTest, SUB_11_39_simple) +{ + using T = flx::floatx<11, 39>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333348491578); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222239906841); +} + +TEST(FloatxOperationsTest, SUB_11_40_simple) +{ + using T = flx::floatx<11, 40>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333325754211); + EXPECT_EQ(double(b), 0.11111111111108584737); + EXPECT_EQ(double(c), 0.22222222222217169474); +} + +TEST(FloatxOperationsTest, SUB_11_41_simple) +{ + using T = flx::floatx<11, 41>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333337122895); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222228538158); +} + +TEST(FloatxOperationsTest, SUB_11_42_simple) +{ + using T = flx::floatx<11, 42>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333331438553); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222220011645); +} + +TEST(FloatxOperationsTest, SUB_11_43_simple) +{ + using T = flx::floatx<11, 43>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333334280724); + EXPECT_EQ(double(b), 0.11111111111111426908); + EXPECT_EQ(double(c), 0.22222222222222853816); +} + +TEST(FloatxOperationsTest, SUB_11_44_simple) +{ + using T = flx::floatx<11, 44>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333332859638); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222221432730); +} + +TEST(FloatxOperationsTest, SUB_11_45_simple) +{ + using T = flx::floatx<11, 45>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333570181); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222498544); +} + +TEST(FloatxOperationsTest, SUB_11_46_simple) +{ + using T = flx::floatx<11, 46>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333214910); + EXPECT_EQ(double(b), 0.11111111111111071637); + EXPECT_EQ(double(c), 0.22222222222222143273); +} + +TEST(FloatxOperationsTest, SUB_11_47_simple) +{ + using T = flx::floatx<11, 47>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333392545); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222320909); +} + +TEST(FloatxOperationsTest, SUB_11_48_simple) +{ + using T = flx::floatx<11, 48>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333303727); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222187682); +} + +TEST(FloatxOperationsTest, SUB_11_49_simple) +{ + using T = flx::floatx<11, 49>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333348136); + EXPECT_EQ(double(b), 0.11111111111111116045); + EXPECT_EQ(double(c), 0.22222222222222232091); +} + +TEST(FloatxOperationsTest, SUB_11_50_simple) +{ + using T = flx::floatx<11, 50>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222209886); +} + +TEST(FloatxOperationsTest, SUB_11_51_simple) +{ + using T = flx::floatx<11, 51>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333325932); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222215438); +} + +TEST(FloatxOperationsTest, SUB_11_52_simple) +{ + using T = flx::floatx<11, 52>; + T a = 0.33333333333333331483; + T b = 0.11111111111111110494; + T c = 0; + c = a - b; + EXPECT_EQ(double(a), 0.33333333333333331483); + EXPECT_EQ(double(b), 0.11111111111111110494); + EXPECT_EQ(double(c), 0.22222222222222220989); +} + + +} // namespace diff --git a/third-party/FloatX/third_party/CMakeLists.txt b/third-party/FloatX/third_party/CMakeLists.txt new file mode 100644 index 0000000..dfacc6d --- /dev/null +++ b/third-party/FloatX/third_party/CMakeLists.txt @@ -0,0 +1,5 @@ +include(package_loader.cmake) + +if(BUILD_TESTS) + add_subdirectory(gtest) +endif() diff --git a/third-party/FloatX/third_party/DownloadCMakeLists.txt.in b/third-party/FloatX/third_party/DownloadCMakeLists.txt.in new file mode 100644 index 0000000..86388d5 --- /dev/null +++ b/third-party/FloatX/third_party/DownloadCMakeLists.txt.in @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 2.8) + +include(ExternalProject) +ExternalProject_Add(${package_name} + GIT_REPOSITORY "${package_url}" + GIT_TAG "${package_tag}" + SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/src" + BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/build" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" +) diff --git a/third-party/FloatX/third_party/gtest/CMakeLists.txt b/third-party/FloatX/third_party/gtest/CMakeLists.txt new file mode 100644 index 0000000..f33a4c2 --- /dev/null +++ b/third-party/FloatX/third_party/gtest/CMakeLists.txt @@ -0,0 +1,8 @@ +# Prevent overriding the parent project's compiler/linker +# settings on Windows +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +load_git_package(gtest + "https://github.com/google/googletest.git" + "master") + diff --git a/third-party/FloatX/third_party/package_loader.cmake b/third-party/FloatX/third_party/package_loader.cmake new file mode 100644 index 0000000..d235111 --- /dev/null +++ b/third-party/FloatX/third_party/package_loader.cmake @@ -0,0 +1,26 @@ +set(PACKAGE_DOWNLOADER_SCRIPT + "${CMAKE_CURRENT_LIST_DIR}/DownloadCMakeLists.txt.in") + +function(load_git_package package_name package_url package_tag) + # Download and unpack package at configure time + configure_file(${PACKAGE_DOWNLOADER_SCRIPT} + download/CMakeLists.txt) + execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/download) + if(result) + message(FATAL_ERROR + "CMake step for ${package_name}/download failed: ${result}") + endif() + execute_process(COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/download) + if(result) + message(FATAL_ERROR + "Build step for ${package_name}/download failed: ${result}") + endif() + + # Add package to the build + add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/src + ${CMAKE_CURRENT_BINARY_DIR}/build) +endfunction(load_git_package) diff --git a/third-party/symfpu/.gitignore b/third-party/symfpu/.gitignore new file mode 100644 index 0000000..c96329a --- /dev/null +++ b/third-party/symfpu/.gitignore @@ -0,0 +1,34 @@ +test + +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app \ No newline at end of file diff --git a/third-party/symfpu/COMMIT b/third-party/symfpu/COMMIT new file mode 100644 index 0000000..27f36f3 --- /dev/null +++ b/third-party/symfpu/COMMIT @@ -0,0 +1,2 @@ +c3acaf62b137c36aae5eb380f1d883bfa9095f60 + diff --git a/third-party/symfpu/LICENSE b/third-party/symfpu/LICENSE new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/third-party/symfpu/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/third-party/symfpu/Makefile b/third-party/symfpu/Makefile new file mode 100644 index 0000000..fc74140 --- /dev/null +++ b/third-party/symfpu/Makefile @@ -0,0 +1,32 @@ +include flags +SUBDIRS=applications/ baseTypes/ +OBJECTFILES=baseTypes/simpleExecutable.o +LIBFILES=symfpu.a +PROGS=test + + +.PHONY: all subdirs $(SUBDIRS) clean $(PROGS) + +all : subdirs $(LIBFILES) $(PROGS) + +subdirs: $(SUBDIRS) + +$(SUBDIRS): + $(MAKE) -C $@ + +symfpu.a : $(OBJECTFILES) + ar rcs $@ $^ + +clean : + find . -name '*.o' -exec rm {} \; + rm -f $(LIBFILES) $(PROGS) + +test : applications/test.o $(LIBFILES) + $(CXX) $(CXXFLAGS) $^ -o $@ + +cbmcverification : applications/cbmcverification.o $(LIBFILES) + $(CXX) $(CXXFLAGS) $^ -o $@ + +generate : applications/generate.o $(LIBFILES) + $(CXX) $(CXXFLAGS) $^ -o $@ + diff --git a/third-party/symfpu/README.md b/third-party/symfpu/README.md new file mode 100644 index 0000000..144f712 --- /dev/null +++ b/third-party/symfpu/README.md @@ -0,0 +1,88 @@ +SymFPU : The Symbolic Floating Point Unit +========================================= + +SymFPU is an implementation of the SMT-LIB / IEEE-754 operations in +terms of bit-vector operations. It is templated in terms of the +bit-vectors, propositions, floating-point formats and rounding mode +types used. This allow the same code to be executed as an arbitrary +precision "SoftFloat" library (although it's performance would not be +good) or to be used to build symbolic representation of floating-point +operations suitable for use in "bit-blasting" SMT solvers (you could +also generate circuits from them but again, performance will likely +not be good). + +A considerable amount of effort has gone in to checking that these +encodings are correct and so please do report any discrepancies you +see. + +The library is Free Software licensed under the GPL V3. If this poses +a particular challenge for your application, please contact the author. + + +A Quick Start +------------- + +1. Create a "back-end", a class with the following members: + +``` +class traits { + public : + // The base types to use. + // Must implement the SMT-LIB-like interfaces used by other back-ends + typedef YourBitWidthType bwt; + typedef YourRoundingMode rm; + typedef YourFloatingPointTypeInfo fpt; + typedef YourProposition prop; + typedef YourSignedBitVector sbv; + typedef YourUnsignedBitVector ubv; + + // Return an instance of each rounding mode. + static rm RNE(void); + static rm RNA(void); + static rm RTP(void); + static rm RTN(void); + static rm RTZ(void); + + // Handle various invariants. + // These can be empty to start with. + static void precondition(const bool b) { assert(b); } + static void postcondition(const bool b) { assert(b); } + static void invariant(const bool b) { assert(b); } + static void precondition(const prop &p) {} + static void postcondition(const prop &p) {} + static void invariant(const prop &p) {} +}; +``` + +If you are stuck; start from one of the existing (symbolic or literal) +ones. `baseTypes/shared.h` gives suitable implementations of `fpt` and +`bwt`, plus if it is executable, you can use bool for prop. + + +2. Make sure symfpu is on your path and include the following headers: + +``` +#include "symfpu/core/unpackedFloat.h" +#include "symfpu/core/packing.h" +#include "symfpu/core/add.h" +``` + +3. To generate a (32-bit) unsigned bit-vector containing the single +precision addition of two other 32-bit bit-vectors, use the following code: + +``` +fpt format(8,24); +ubv packed1 = ... // Must be 32-bit. +ubv packed2 = ... // Must be 32-bit. + +uf unpacked1(symfpu::unpack(format, packed1)); +uf unpacked2(symfpu::unpack(format, packed2)); + +uf added(symfpu::add(format, traits::RNE(), unpacked1, unpacked2, prop(true))); + +ubv repacked(symfpu::pack(format, added)); +``` + +See `applications/implementation.h` for examples of other operations +(although, really, it is pretty similar). + diff --git a/third-party/symfpu/applications/Makefile b/third-party/symfpu/applications/Makefile new file mode 100644 index 0000000..414dd84 --- /dev/null +++ b/third-party/symfpu/applications/Makefile @@ -0,0 +1,11 @@ +include ../flags +CXXFLAGS+=-I../../ +ALL=test.o + +.PHONY : all + +all : $(ALL) + +%.o : %.cpp + $(CXX) $(CXXFLAGS) -c $^ -o $@ + diff --git a/third-party/symfpu/applications/executable.h b/third-party/symfpu/applications/executable.h new file mode 100644 index 0000000..556960e --- /dev/null +++ b/third-party/symfpu/applications/executable.h @@ -0,0 +1,434 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +// DEPRECIATED : USE implementation.h instead + +/* +** executable.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 06/08/14 +** +** A set of basic functions constructed from the simple executable +** implementation of bit-vectors. +** +*/ + +#include +#include +#include + +#include "symfpu/core/unpackedFloat.h" +#include "symfpu/core/packing.h" +#include "symfpu/core/sign.h" +#include "symfpu/core/classify.h" +#include "symfpu/core/compare.h" +#include "symfpu/core/multiply.h" +#include "symfpu/core/add.h" + + + +#ifndef SYMFPU_EXECUTABLE +#define SYMFPU_EXECUTABLE + + + +template + class executableTests { + + public : + // Wrapped in a struct to make type scoping easier + // and to save on typenames. + // Object is stateless. + + typedef typename traits::rm rm; + typedef typename traits::bwt bwt; + typedef typename traits::fpt fpt; + typedef typename traits::ubv ubv; + typedef typename traits::prop prop; + typedef symfpu::unpackedFloat uf; + + static bwt bitsInExecBV () { + return sizeof(execBV) * CHAR_BIT; + } + + + + static execBV unpackPack (const fpt &format, const execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(format, packed)); + + ubv repacked(symfpu::pack(format, unpacked)); + + return repacked.contents(); + } + + static execBV unpackPackReference (const fpt &, execBV bv) { + return bv; + } + + + + static execBV negate (const fpt &format, execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(format, packed)); + + uf negated(symfpu::negate(format, unpacked)); + + ubv repacked(symfpu::pack(format, negated)); + + return repacked.contents(); + } + + static execBV negateReference (const fpt &, execBV bv) { + execFloat f = *((execFloat *)&bv); + + f = -f; + + return *((execBV *)&f); + } + + + + static execBV absolute (const fpt &format, execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(format, packed)); + + uf abs(symfpu::absolute(format, unpacked)); + + ubv repacked(symfpu::pack(format, abs)); + + return repacked.contents(); + } + + static execBV absoluteReference (const fpt &, execBV bv) { + execFloat f = *((execFloat *)&bv); + + f = nativeFunctions::abs(f); + + return *((execBV *)&f); + } + + + static bool isNormal (const fpt &format, execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(format, packed)); + + prop result(symfpu::isNormal(format, unpacked)); + + return result; + } + + static bool isNormalReference (const fpt &, execBV bv) { + execFloat f = *((execFloat *)&bv); + + return nativeFunctions::isNormal(f); + } + + + + static bool isSubnormal (const fpt &format, execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(format, packed)); + + prop result(symfpu::isSubnormal(format, unpacked)); + + return result; + } + + static bool isSubnormalReference (const fpt &, execBV bv) { + execFloat f = *((execFloat *)&bv); + + return nativeFunctions::isSubnormal(f); + } + + + + + static bool isZero (const fpt &format, execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(format, packed)); + + prop result(symfpu::isZero(format, unpacked)); + + return result; + } + + static bool isZeroReference (const fpt &, execBV bv) { + execFloat f = *((execFloat *)&bv); + + return nativeFunctions::isZero(f); + } + + + + static bool isInfinite (const fpt &format, execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(format, packed)); + + prop result(symfpu::isInfinite(format, unpacked)); + + return result; + } + + static bool isInfiniteReference (const fpt &, execBV bv) { + execFloat f = *((execFloat *)&bv); + + return nativeFunctions::isInf(f); + } + + + + static bool isNaN (const fpt &format, execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(format, packed)); + + prop result(symfpu::isNaN(format, unpacked)); + + return result; + } + + static bool isNaNReference (const fpt &, execBV bv) { + execFloat f = *((execFloat *)&bv); + + return nativeFunctions::isNaN(f); + } + + + + + static bool isPositive (const fpt &format, execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(format, packed)); + + prop result(symfpu::isPositive(format, unpacked)); + + return result; + } + + static bool isPositiveReference (const fpt &, execBV bv) { + execFloat f = *((execFloat *)&bv); + + return nativeFunctions::isPositive(f); + } + + + + static bool isNegative (const fpt &format, execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(format, packed)); + + prop result(symfpu::isNegative(format, unpacked)); + + return result; + } + + static bool isNegativeReference (const fpt &, execBV bv) { + execFloat f = *((execFloat *)&bv); + + return nativeFunctions::isNegative(f); + } + + + static bool smtlibEqual (const fpt &format, execBV bv1, execBV bv2) { + ubv packed1(bitsInExecBV(),bv1); + ubv packed2(bitsInExecBV(),bv2); + + uf unpacked1(symfpu::unpack(format, packed1)); + uf unpacked2(symfpu::unpack(format, packed2)); + + prop result(symfpu::smtlibEqual(format, unpacked1, unpacked2)); + + return result; + } + + static bool smtlibEqualReference (const fpt &, execBV bv1, execBV bv2) { + execFloat f = *((execFloat *)(&bv1)); + execFloat g = *((execFloat *)(&bv2)); + + return (bv1 == bv2) || (nativeFunctions::isNaN(f) && nativeFunctions::isNaN(g)); + } + + + + static bool ieee754Equal (const fpt &format, execBV bv1, execBV bv2) { + ubv packed1(bitsInExecBV(),bv1); + ubv packed2(bitsInExecBV(),bv2); + + uf unpacked1(symfpu::unpack(format, packed1)); + uf unpacked2(symfpu::unpack(format, packed2)); + + prop result(symfpu::ieee754Equal(format, unpacked1, unpacked2)); + + return result; + } + + + static bool ieee754EqualReference (const fpt &, execBV bv1, execBV bv2) { + execFloat f = *((execFloat *)(&bv1)); + execFloat g = *((execFloat *)(&bv2)); + + return (f == g); + } + + + + static bool lessThan (const fpt &format, execBV bv1, execBV bv2) { + ubv packed1(bitsInExecBV(),bv1); + ubv packed2(bitsInExecBV(),bv2); + + uf unpacked1(symfpu::unpack(format, packed1)); + uf unpacked2(symfpu::unpack(format, packed2)); + + prop result(symfpu::lessThan(format, unpacked1, unpacked2)); + + return result; + } + + static bool lessThanReference (const fpt &, execBV bv1, execBV bv2) { + execFloat f = *((execFloat *)(&bv1)); + execFloat g = *((execFloat *)(&bv2)); + + return (f < g); + } + + + + + + static bool lessThanOrEqual (const fpt &format, execBV bv1, execBV bv2) { + ubv packed1(bitsInExecBV(),bv1); + ubv packed2(bitsInExecBV(),bv2); + + uf unpacked1(symfpu::unpack(format, packed1)); + uf unpacked2(symfpu::unpack(format, packed2)); + + prop result(symfpu::lessThanOrEqual(format, unpacked1, unpacked2)); + + return result; + } + + + static bool lessThanOrEqualReference (const fpt &, execBV bv1, execBV bv2) { + execFloat f = *((execFloat *)(&bv1)); + execFloat g = *((execFloat *)(&bv2)); + + return (f <= g); + } + + + + + static execBV multiply (const fpt &format, const rm &roundingMode, execBV bv1, execBV bv2) { + ubv packed1(bitsInExecBV(),bv1); + ubv packed2(bitsInExecBV(),bv2); + + uf unpacked1(symfpu::unpack(format, packed1)); + uf unpacked2(symfpu::unpack(format, packed2)); + + uf multiplied(symfpu::multiply(format, roundingMode, unpacked1, unpacked2)); + + ubv repacked(symfpu::pack(format, multiplied)); + + return repacked.contents(); + } + + + static execBV multiplyReference (const fpt &, const rm &roundingMode, execBV bv1, execBV bv2) { + execFloat f = *((execFloat *)(&bv1)); + execFloat g = *((execFloat *)(&bv2)); + + fesetround(roundingMode.getValue()); + + execFloat h = f * g; + + return *((execBV *)&h); + } + + static execBV add (const fpt &format, const rm &roundingMode, execBV bv1, execBV bv2) { + ubv packed1(bitsInExecBV(),bv1); + ubv packed2(bitsInExecBV(),bv2); + + uf unpacked1(symfpu::unpack(format, packed1)); + uf unpacked2(symfpu::unpack(format, packed2)); + + uf added(symfpu::add(format, roundingMode, unpacked1, unpacked2, prop(true))); + + ubv repacked(symfpu::pack(format, added)); + + return repacked.contents(); + } + + + static execBV addReference (const fpt &, const rm &roundingMode, execBV bv1, execBV bv2) { + execFloat f = *((execFloat *)(&bv1)); + execFloat g = *((execFloat *)(&bv2)); + + fesetround(roundingMode.getValue()); + + execFloat h = f + g; + + return *((execBV *)&h); + } + + + static execBV sub (const fpt &format, const rm &roundingMode, execBV bv1, execBV bv2) { + ubv packed1(bitsInExecBV(),bv1); + ubv packed2(bitsInExecBV(),bv2); + + uf unpacked1(symfpu::unpack(format, packed1)); + uf unpacked2(symfpu::unpack(format, packed2)); + + uf added(symfpu::add(format, roundingMode, unpacked1, unpacked2, prop(false))); + + ubv repacked(symfpu::pack(format, added)); + + return repacked.contents(); + } + + + static execBV subReference (const fpt &, const rm &roundingMode, execBV bv1, execBV bv2) { + execFloat f = *((execFloat *)(&bv1)); + execFloat g = *((execFloat *)(&bv2)); + + fesetround(roundingMode.getValue()); + + execFloat h = f - g; + + return *((execBV *)&h); + } + + // The SMT-LIB notion of equality + //bool compareFloat (execBV bv1, execBV bv2); + + }; + + + + +#endif diff --git a/third-party/symfpu/applications/implementations.h b/third-party/symfpu/applications/implementations.h new file mode 100644 index 0000000..b5cb368 --- /dev/null +++ b/third-party/symfpu/applications/implementations.h @@ -0,0 +1,843 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** implementations.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 27/01/16 +** +** Several different implementations of the floating-point operations. +** Object should only have static functions so that function pointers +** can be used. This means thee significand and exponent width should +** be fixed by the templating. +** +*/ + +#include +#include +#include + +#include "symfpu/core/unpackedFloat.h" +#include "symfpu/core/packing.h" +#include "symfpu/core/sign.h" +#include "symfpu/core/classify.h" +#include "symfpu/core/compare.h" +#include "symfpu/core/multiply.h" +#include "symfpu/core/add.h" +#include "symfpu/core/divide.h" +#include "symfpu/core/sqrt.h" +#include "symfpu/core/fma.h" +#include "symfpu/core/remainder.h" + +#ifndef SYMFPU_IMPLEMENTATIONS +#define SYMFPU_IMPLEMENTATIONS + + +template +class nativeFunctions { + public : + static execFloat abs (execFloat f); + static execFloat max (execFloat f, execFloat g); + static execFloat min (execFloat f, execFloat g); + static execFloat sqrt (execFloat f); + static execFloat rti (execFloat f); + static execFloat fma (execFloat f, execFloat g, execFloat h); + static execFloat rem (execFloat f, execFloat g); + + + + // These will work for any inbuilt float-type, specialisations need for others + // Name changes because they are macros... + + static int fpClassify (execFloat f) { return fpclassify(f); } + static int isNormal (execFloat f) { return isnormal(f); } + static int isSubnormal (execFloat f) { return fpclassify(f) == FP_SUBNORMAL; } + static int isZero (execFloat f); + static int isInf (execFloat f) { return isinf(f); } + static int isNaN (execFloat f) { return isnan(f); } + static int isPositive (execFloat f) { return !isnan(f) && !signbit(f); } + static int isNegative (execFloat f) { return !isnan(f) && signbit(f); } + + +}; + +// Specialisations for the obvious execFloat types +// To use other types as the reference, more instantiations will be needed + +template <> +float nativeFunctions::abs (float f) { + return fabsf(f); +} + +template <> +double nativeFunctions::abs (double f) { + return fabs(f); +} + +template <> +long double nativeFunctions::abs (long double f) { + return fabsl(f); +} + + + +template <> +float nativeFunctions::min (float f, float g) { + return fminf(f,g); +} + +template <> +double nativeFunctions::min (double f, double g) { + return fmin(f,g); +} + +template <> +long double nativeFunctions::min (long double f, long double g) { + return fminl(f,g); +} + + + +template <> +float nativeFunctions::max (float f, float g) { + return fmaxf(f,g); +} + +template <> +double nativeFunctions::max (double f, double g) { + return fmax(f,g); +} + +template <> +long double nativeFunctions::max (long double f, long double g) { + return fmaxl(f,g); +} + + + +template <> +float nativeFunctions::sqrt (float f) { + return sqrtf(f); +} + +template <> +double nativeFunctions::sqrt (double f) { + return sqrt(f); +} + +template <> +long double nativeFunctions::sqrt (long double f) { + return sqrtl(f); +} + +template <> +float nativeFunctions::rti (float f) { + switch (fegetround()) { + case FE_TONEAREST : return rintf(f); break; + case FE_UPWARD : return ceilf(f); break; + case FE_DOWNWARD : return floorf(f); break; + case FE_TOWARDZERO : return truncf(f); break; + // case RNA : return roundf(f); break; + default : assert(0); break; + } + return 0.0f; +} + +template <> +double nativeFunctions::rti (double f) { + switch (fegetround()) { + case FE_TONEAREST : return rint(f); break; + case FE_UPWARD : return ceil(f); break; + case FE_DOWNWARD : return floor(f); break; + case FE_TOWARDZERO : return trunc(f); break; + // case RNA : return round(f); break; + default : assert(0); break; + } + return 0.0; +} + +template <> +long double nativeFunctions::rti (long double f) { + switch (fegetround()) { + case FE_TONEAREST : return rintl(f); break; + case FE_UPWARD : return ceill(f); break; + case FE_DOWNWARD : return floorl(f); break; + case FE_TOWARDZERO : return truncl(f); break; + // case RNA : return roundl(f); break; + default : assert(0); break; + } + return 0.0f; +} + + +// 1000000 tests +// libc fma 1739 bugs / 94 not sign of zero +// double 1861 bugs all not sign of zero +// float 1861 bugs all not sign of zero + +template <> +float nativeFunctions::fma (float f, float g, float h) { + + // vfmadd132ss + return __builtin_fmaf(f,g,h); + + /* + // Needs -mfma4 which is not the fma attribute in /proc/cpuinfo + typedef float v4sf __attribute__ ((vector_size (16))); + + v4sf vf = {f,f,f,f}; + v4sf vg = {g,g,g,g}; + v4sf vh = {h,h,h,h}; + + v4sf result = __builtin_ia32_vfmaddps (vf, vg, vh); + + return result[0]; + */ + + /* + float mult = f * g; + return mult + h; + */ + + /* + double df = f; + double dg = g; + double dh = h; + + double mult = f * g; + return (float)(mult + h); + */ + + //return fmaf(f,g,h); +} + +template <> +double nativeFunctions::fma (double f, double g, double h) { + return fma(f,g,h); +} + + +template <> +long double nativeFunctions::fma (long double f, long double g, long double h) { + return fmal(f,g,h); +} + + + +template <> +int nativeFunctions::isZero (float f) { + return f == 0.0f; +} + +template <> +int nativeFunctions::isZero (double f) { + return f == 0.0; +} + +template <> +int nativeFunctions::isZero (long double f) { + return f == 0.0l; +} + + +template <> +float nativeFunctions::rem (float f, float g) { + return remainderf(f,g); +} + +template <> +double nativeFunctions::rem (double f, double g) { + return remainder(f,g); +} + +template <> +long double nativeFunctions::rem (long double f, long double g) { + return remainderl(f,g); +} + + + + +template +class native { + public : + + static void setRoundingMode (const int roundingMode) { + fesetround(roundingMode); + } + + static execBV unpackPack (execBV bv) { + return bv; + } + + static execBV negate (execBV bv) { + execFloat f = *((execFloat *)&bv); + + f = -f; + + return *((execBV *)&f); + } + + static execBV absolute (execBV bv) { + execFloat f = *((execFloat *)&bv); + + f = nativeFunctions::abs(f); + + return *((execBV *)&f); + } + + static execBV sqrt (execBV bv) { + execFloat f = *((execFloat *)&bv); + + f = nativeFunctions::sqrt(f); + + return *((execBV *)&f); + } + + static execBV rti (execBV bv) { + execFloat f = *((execFloat *)&bv); + + f = nativeFunctions::rti(f); + + return *((execBV *)&f); + } + + static bool isNormal (execBV bv) { + execFloat f = *((execFloat *)&bv); + + return nativeFunctions::isNormal(f); + } + + static bool isSubnormal (execBV bv) { + execFloat f = *((execFloat *)&bv); + + return nativeFunctions::isSubnormal(f); + } + + static bool isZero (execBV bv) { + execFloat f = *((execFloat *)&bv); + + return nativeFunctions::isZero(f); + } + + static bool isInfinite (execBV bv) { + execFloat f = *((execFloat *)&bv); + + return nativeFunctions::isInf(f); + } + + static bool isNaN (execBV bv) { + execFloat f = *((execFloat *)&bv); + + return nativeFunctions::isNaN(f); + } + + static bool isPositive (execBV bv) { + execFloat f = *((execFloat *)&bv); + + return nativeFunctions::isPositive(f); + } + + static bool isNegative (execBV bv) { + execFloat f = *((execFloat *)&bv); + + return nativeFunctions::isNegative(f); + } + + static bool smtlibEqual (execBV bv1, execBV bv2) { + execFloat f = *((execFloat *)(&bv1)); + execFloat g = *((execFloat *)(&bv2)); + + return (bv1 == bv2) || (nativeFunctions::isNaN(f) && nativeFunctions::isNaN(g)); + } + + static bool ieee754Equal (execBV bv1, execBV bv2) { + execFloat f = *((execFloat *)(&bv1)); + execFloat g = *((execFloat *)(&bv2)); + + return (f == g); + } + + static bool lessThan (execBV bv1, execBV bv2) { + execFloat f = *((execFloat *)(&bv1)); + execFloat g = *((execFloat *)(&bv2)); + + return (f < g); + } + + static bool lessThanOrEqual (execBV bv1, execBV bv2) { + execFloat f = *((execFloat *)(&bv1)); + execFloat g = *((execFloat *)(&bv2)); + + return (f <= g); + } + + static execBV multiply (execBV bv1, execBV bv2) { + execFloat f = *((execFloat *)(&bv1)); + execFloat g = *((execFloat *)(&bv2)); + + execFloat h = f * g; + + return *((execBV *)&h); + } + + static execBV add (execBV bv1, execBV bv2) { + execFloat f = *((execFloat *)(&bv1)); + execFloat g = *((execFloat *)(&bv2)); + + execFloat h = f + g; + + return *((execBV *)&h); + } + + static execBV sub (execBV bv1, execBV bv2) { + execFloat f = *((execFloat *)(&bv1)); + execFloat g = *((execFloat *)(&bv2)); + + execFloat h = f - g; + + return *((execBV *)&h); + } + + static execBV div (execBV bv1, execBV bv2) { + execFloat f = *((execFloat *)(&bv1)); + execFloat g = *((execFloat *)(&bv2)); + + execFloat h = f / g; + + return *((execBV *)&h); + } + + static execBV max (execBV bv1, execBV bv2) { + execFloat f = *((execFloat *)(&bv1)); + execFloat g = *((execFloat *)(&bv2)); + + execFloat h = nativeFunctions::max(f,g); + + return *((execBV *)&h); + } + + static execBV min (execBV bv1, execBV bv2) { + execFloat f = *((execFloat *)(&bv1)); + execFloat g = *((execFloat *)(&bv2)); + + execFloat h = nativeFunctions::min(f,g); + + return *((execBV *)&h); + } + + static execBV fma (execBV bv1, execBV bv2, execBV bv3) { + execFloat f = *((execFloat *)(&bv1)); + execFloat g = *((execFloat *)(&bv2)); + execFloat h = *((execFloat *)(&bv3)); + + execFloat p = nativeFunctions::fma(f,g,h); + + return *((execBV *)&p); + } + + static execBV rem (execBV bv1, execBV bv2) { + execFloat f = *((execFloat *)(&bv1)); + execFloat g = *((execFloat *)(&bv2)); + + execFloat h = nativeFunctions::rem(f,g); + + return *((execBV *)&h); + } + +}; + + + + + +template +class sympfuImplementation { + + public : + // Wrapped in a struct to make type scoping easier + // and to save on typenames. + // Object is stateless. + + typedef typename traits::rm rm; + typedef typename traits::bwt bwt; + typedef typename traits::fpt fpt; + typedef typename traits::ubv ubv; + typedef typename traits::prop prop; + typedef symfpu::unpackedFloat uf; + + static bwt bitsInExecBV () { + return sizeof(execBV) * CHAR_BIT; + } + + protected : + static rm * mode; + static fpt * format; + + public : + + static void setRoundingMode (const int roundingMode) { + if (mode != NULL) { + delete mode; + } + + switch (roundingMode) { + case FE_TONEAREST : + mode = new rm(traits::RNE()); + break; + case FE_UPWARD : + mode = new rm(traits::RTP()); + break; + case FE_DOWNWARD : + mode = new rm(traits::RTN()); + break; + case FE_TOWARDZERO : + mode = new rm(traits::RTZ()); + break; + /* // Disabled until a suitable reference implementation is available + case ??? : + mode = new traits::rm(traits::RNA()); + break; + */ + default : + assert(0); + break; + } + } + + static void setFormat (const fpt &newFormat) { + if (format != NULL) { + delete format; + } + format = new fpt(newFormat); + return; + } + + static void destroyFormat() { + delete format; + return; + } + + static execBV unpackPack (const execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(*format, packed)); + + ubv repacked(symfpu::pack(*format, unpacked)); + + return repacked.contents(); + } + + static execBV negate (execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(*format, packed)); + + uf negated(symfpu::negate(*format, unpacked)); + + ubv repacked(symfpu::pack(*format, negated)); + + return repacked.contents(); + } + + static execBV absolute (execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(*format, packed)); + + uf abs(symfpu::absolute(*format, unpacked)); + + ubv repacked(symfpu::pack(*format, abs)); + + return repacked.contents(); + } + + static execBV sqrt (execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(*format, packed)); + + uf sqrt(symfpu::sqrt(*format, *mode, unpacked)); + + ubv repacked(symfpu::pack(*format, sqrt)); + + return repacked.contents(); + } + + static execBV rti (execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(*format, packed)); + + uf rti(symfpu::roundToIntegral(*format, *mode, unpacked)); + + ubv repacked(symfpu::pack(*format, rti)); + + return repacked.contents(); + } + + static bool isNormal (execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(*format, packed)); + + prop result(symfpu::isNormal(*format, unpacked)); + + return result; + } + + static bool isSubnormal (execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(*format, packed)); + + prop result(symfpu::isSubnormal(*format, unpacked)); + + return result; + } + + static bool isZero (execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(*format, packed)); + + prop result(symfpu::isZero(*format, unpacked)); + + return result; + } + + static bool isInfinite (execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(*format, packed)); + + prop result(symfpu::isInfinite(*format, unpacked)); + + return result; + } + + static bool isNaN (execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(*format, packed)); + + prop result(symfpu::isNaN(*format, unpacked)); + + return result; + } + + static bool isPositive (execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(*format, packed)); + + prop result(symfpu::isPositive(*format, unpacked)); + + return result; + } + + static bool isNegative (execBV bv) { + ubv packed(bitsInExecBV(),bv); + + uf unpacked(symfpu::unpack(*format, packed)); + + prop result(symfpu::isNegative(*format, unpacked)); + + return result; + } + + static bool smtlibEqual (execBV bv1, execBV bv2) { + ubv packed1(bitsInExecBV(),bv1); + ubv packed2(bitsInExecBV(),bv2); + + uf unpacked1(symfpu::unpack(*format, packed1)); + uf unpacked2(symfpu::unpack(*format, packed2)); + + prop result(symfpu::smtlibEqual(*format, unpacked1, unpacked2)); + + return result; + } + + static bool ieee754Equal (execBV bv1, execBV bv2) { + ubv packed1(bitsInExecBV(),bv1); + ubv packed2(bitsInExecBV(),bv2); + + uf unpacked1(symfpu::unpack(*format, packed1)); + uf unpacked2(symfpu::unpack(*format, packed2)); + + prop result(symfpu::ieee754Equal(*format, unpacked1, unpacked2)); + + return result; + } + + static bool lessThan (execBV bv1, execBV bv2) { + ubv packed1(bitsInExecBV(),bv1); + ubv packed2(bitsInExecBV(),bv2); + + uf unpacked1(symfpu::unpack(*format, packed1)); + uf unpacked2(symfpu::unpack(*format, packed2)); + + prop result(symfpu::lessThan(*format, unpacked1, unpacked2)); + + return result; + } + + static bool lessThanOrEqual (execBV bv1, execBV bv2) { + ubv packed1(bitsInExecBV(),bv1); + ubv packed2(bitsInExecBV(),bv2); + + uf unpacked1(symfpu::unpack(*format, packed1)); + uf unpacked2(symfpu::unpack(*format, packed2)); + + prop result(symfpu::lessThanOrEqual(*format, unpacked1, unpacked2)); + + return result; + } + + static execBV multiply (execBV bv1, execBV bv2) { + ubv packed1(bitsInExecBV(),bv1); + ubv packed2(bitsInExecBV(),bv2); + + uf unpacked1(symfpu::unpack(*format, packed1)); + uf unpacked2(symfpu::unpack(*format, packed2)); + + uf multiplied(symfpu::multiply(*format, *mode, unpacked1, unpacked2)); + + ubv repacked(symfpu::pack(*format, multiplied)); + + return repacked.contents(); + } + + static execBV add (execBV bv1, execBV bv2) { + ubv packed1(bitsInExecBV(),bv1); + ubv packed2(bitsInExecBV(),bv2); + + uf unpacked1(symfpu::unpack(*format, packed1)); + uf unpacked2(symfpu::unpack(*format, packed2)); + + uf added(symfpu::add(*format, *mode, unpacked1, unpacked2, prop(true))); + + ubv repacked(symfpu::pack(*format, added)); + + return repacked.contents(); + } + + static execBV sub (execBV bv1, execBV bv2) { + ubv packed1(bitsInExecBV(),bv1); + ubv packed2(bitsInExecBV(),bv2); + + uf unpacked1(symfpu::unpack(*format, packed1)); + uf unpacked2(symfpu::unpack(*format, packed2)); + + uf added(symfpu::add(*format, *mode, unpacked1, unpacked2, prop(false))); + + ubv repacked(symfpu::pack(*format, added)); + + return repacked.contents(); + } + + static execBV div (execBV bv1, execBV bv2) { + ubv packed1(bitsInExecBV(),bv1); + ubv packed2(bitsInExecBV(),bv2); + + uf unpacked1(symfpu::unpack(*format, packed1)); + uf unpacked2(symfpu::unpack(*format, packed2)); + + uf added(symfpu::divide(*format, *mode, unpacked1, unpacked2)); + + ubv repacked(symfpu::pack(*format, added)); + + return repacked.contents(); + } + + #define INTELSSEMAXSTYLE true + #define INTELSSEMINSTYLE false + + static execBV max (execBV bv1, execBV bv2) { + ubv packed1(bitsInExecBV(),bv1); + ubv packed2(bitsInExecBV(),bv2); + + uf unpacked1(symfpu::unpack(*format, packed1)); + uf unpacked2(symfpu::unpack(*format, packed2)); + + uf max(symfpu::max(*format, unpacked1, unpacked2, INTELSSEMAXSTYLE)); + + ubv repacked(symfpu::pack(*format, max)); + + return repacked.contents(); + } + + static execBV min (execBV bv1, execBV bv2) { + ubv packed1(bitsInExecBV(),bv1); + ubv packed2(bitsInExecBV(),bv2); + + uf unpacked1(symfpu::unpack(*format, packed1)); + uf unpacked2(symfpu::unpack(*format, packed2)); + + uf min(symfpu::min(*format, unpacked1, unpacked2, INTELSSEMINSTYLE)); + + ubv repacked(symfpu::pack(*format, min)); + + return repacked.contents(); + } + + static execBV fma (execBV bv1, execBV bv2, execBV bv3) { + ubv packed1(bitsInExecBV(),bv1); + ubv packed2(bitsInExecBV(),bv2); + ubv packed3(bitsInExecBV(),bv3); + + uf unpacked1(symfpu::unpack(*format, packed1)); + uf unpacked2(symfpu::unpack(*format, packed2)); + uf unpacked3(symfpu::unpack(*format, packed3)); + + uf fma(symfpu::fma(*format, *mode, unpacked1, unpacked2, unpacked3)); + + ubv repacked(symfpu::pack(*format, fma)); + + return repacked.contents(); + } + + static execBV rem (execBV bv1, execBV bv2) { + ubv packed1(bitsInExecBV(),bv1); + ubv packed2(bitsInExecBV(),bv2); + + uf unpacked1(symfpu::unpack(*format, packed1)); + uf unpacked2(symfpu::unpack(*format, packed2)); + + uf min(symfpu::remainder(*format, unpacked1, unpacked2)); + + ubv repacked(symfpu::pack(*format, min)); + + return repacked.contents(); + } + + + // The SMT-LIB notion of equality + //bool compareFloat (execBV bv1, execBV bv2); + +}; + +template +typename sympfuImplementation::rm * sympfuImplementation::mode = NULL; + +template +typename sympfuImplementation::fpt * sympfuImplementation::format = NULL; + + +#endif diff --git a/third-party/symfpu/applications/test.cpp b/third-party/symfpu/applications/test.cpp new file mode 100644 index 0000000..dabe604 --- /dev/null +++ b/third-party/symfpu/applications/test.cpp @@ -0,0 +1,1439 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** test.cpp +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 06/08/14 +** +** The main loop of the test program +** +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "symfpu/baseTypes/simpleExecutable.h" + +#include "symfpu/applications/implementations.h" + + +/*** Test Vector Generation ***/ + +#define NUMBER_OF_FLOAT_TESTS 124 +static float floatTestValue [NUMBER_OF_FLOAT_TESTS] = { + 0x0p+0f, -0x0p+0f, // Zeros + 0x1p+0f, -0x1p+0f, // Ones + INFINITY, -INFINITY, NAN, -NAN, // Special values + M_E, M_LOG2E, M_LOG10E, M_LN2, M_LN10, // Mathematical constants + M_PI, M_PI_2, M_PI_4, M_1_PI, M_2_PI, + M_2_SQRTPI, M_SQRT2, M_SQRT1_2, + 0x1.fffffcp-127, 0x1.000004p-127, 0x1p-127, 0x1p-148, 0x1p-149, // Subnormals + -0x1.fffffcp-127, -0x1.000004p-127, -0x1p-127, -0x1p-148, -0x1p-149, + 0x1.ffffffcp-103, 0x1.ffffffcp-99, 0x1.ffffffcp-75, // Normals + 0x1.ffffffcp-51, 0x1.ffffffcp-27, 0x1.ffffffcp-03, + 0x1.ffffffcp+51, 0x1.ffffffcp+27, 0x1.ffffffcp+03, + 0x1.ffffffcp+103, 0x1.ffffffcp+99, 0x1.ffffffcp+75, + -0x1.ffffffcp-103, -0x1.ffffffcp-99, -0x1.ffffffcp-75, + -0x1.ffffffcp-51, -0x1.ffffffcp-27, -0x1.ffffffcp-03, + -0x1.ffffffcp+51, -0x1.ffffffcp+27, -0x1.ffffffcp+03, + -0x1.ffffffcp+103, -0x1.ffffffcp+99, -0x1.ffffffcp+75, + 0x1.fffffep+127, // From the CBMC regression tests + 0x1.4p+4, + 0x1.fffffep-105f, + 0x1.0p-23, + 0x1.0p-126f, + 0x1.fffffep-3f, + 0x1.fffffep+123f, + 0x1.000002p+124f, + 0x1.0p+124f, + 0x1.fffffep-3f, + 0x1p+124f, + 0x1p-126f, + 0x1.000000p-63f, + 0x1.fffffep-64f, + 0x1.084c64p-63f, + 0x1.efec9ep-64f, + 0x1.47e8c2p-63f, + 0x1.8fb86cp-64f, + 0x1.1fcf1cp-63f, + 0x1.c769c0p-64f, + 0x1.b1fffcp-63f, + 0x1.2e025ep-64f, + 0x1.000000p-62f, + 0x1.fffffep-65f, + 0x1.000000p-61f, + 0x1.fffffep-66f, + 0x1.000000p-50f, + 0x1.fffffep-77f, + 0x1.000000p-30f, + 0x1.fffffep-97f, + 0x1.000000p-10f, + 0x1.fffffep-117f, + 0x1.000000p-1f, + 0x1.fffffep-126f, + 0x1.9e0c22p-101f, + -0x1.3c9014p-50f, + 0x1.8p-24, + 0x1.fffffep-1f, + 0x1.000002p+0f, + 0x1.7ffffep-24f, + 0x1.800002p-24f, + 0x1.800000p-24f, + -0x1.0p-127f, + -0x1.6b890ep+29, + 0x1.6b890ep+29, + 0x1.000002p+25f, + 0x1.000004p+25f, + 0x1.0017ecp+22f, // Divide! + 0x1.7ffff8p+21f, + 0x1.557542p+0f, + 0x1p+120f, // Distributivity + -0x1p+120f, + 0x1.46p+7f, // e^{pi * sqrt{163}} = 640320^3 + 744 + 0x1.38a8p+19f, + 0x1.74p+9f, + 0x1.79999ap+5f, // 47.2 + 0x1.99999ap-4f, // For the patriots.. + 0x1.5p+5f, + 0x1.7p+4f, + 0x1.fffffep+24, // To test carry on increment + 0x1.fffffcp+24, + 0x1.0p-1, // Half for a laugh + 0x1.000002p-75f, // To test rounding on multiply + 0x1.0p-75f, + 0x1.8p+0f, // Carry in to top bit of fraction when half is added + 0x1.fffffep+125f, // Hunt a specific bug + 0x1.fffffep+126f, + 0x1.8p+1f, + 0x1.000004p+125f +}; + +float getTestValue (uint64_t index) { + if (index < NUMBER_OF_FLOAT_TESTS) { + return floatTestValue[index]; + } else { + index -= NUMBER_OF_FLOAT_TESTS; + + ieee754_float c; + + // The low bits give the sign and exponent so that a wide range is covered quickly + c.ieee.negative = index & 0x1; + index >>= 1; + + c.ieee.exponent = ((index & 0xFE) >> 1) | ((index & 0x1) << 7); + index >>= 8; + + assert(index < (1 << 23)); + + // Use the next bit to optionally negates the word + //index = (index & 0x1) ? ~(index >> 1) : (index >> 1); + + // Even bits affect the MSBs of the significand, odd bits affect the LSBs of the significand + uint32_t lsb = 0x0; + uint32_t msb = 0x0; + + + for (uint32_t i = 0; i < 23; ++i) { + if (i & 0x1) { + lsb |= (((index >> i) & 0x1) << (i >> 1)); + } else { + msb <<= 1; + msb |= ((index >> i) & 0x1); + } + } + + assert((lsb & (msb << 11)) == 0); + + c.ieee.mantissa = lsb | (msb << 11); + + return c.f; + } +} + + + + +/*** Types ***/ + +// We are testing the 'simple executable' back-end +typedef symfpu::simpleExecutable::traits traits; +typedef traits::fpt fpt; + +// We are also testing it only for single precision +traits::fpt singlePrecisionFormatObject(8,24); + +// Thus we are using the functions in ... +typedef sympfuImplementation singlePrecisionExecutableSymfpu; + +// Which we then compare against +typedef native singlePrecisionHardware; + + + +/*** Output helpers ***/ + +#define BUFFERLENGTH 256 + +FILE * openOutputFile (const char *string, const char *name, const char *roundingMode, const uint64_t testNumber) { + char filename[BUFFERLENGTH]; + + snprintf(filename, BUFFERLENGTH, string, name, roundingMode, testNumber); + + FILE *out = fopen(filename, "w"); + if (out == NULL) { + fprintf(stderr,"Couldn't open %s\n", filename); + perror("Can't open file for writing"); + exit(1); + } + + return out; +} + +FILE * startOutputC (const char *name, const char *roundingMode, const uint64_t testNumber) { + FILE * out = openOutputFile("testC-%s-%s-%d.c", name, roundingMode, testNumber); + + // TODO : version and date + fprintf(out, "// Test case created by symfpu for operation %s, rounding mode %s, test %lx\n\n", name, roundingMode, testNumber); + fprintf(out, "#include \n"); + fprintf(out, "#include \n"); + fprintf(out, "#include \n\n"); + + fprintf(out, "int compare (float ref, float computed) {\n\n"); + + fprintf(out, "int isrefnan = isnan(ref);\n"); + fprintf(out, "int iscomputednan = isnan(computed);\n"); + fprintf(out, "int equal = (ref == computed);\n"); + fprintf(out, "int signref = signbit(ref);\n"); + fprintf(out, "int signcomp = signbit(computed);\n"); + + fprintf(out, "return ((isrefnan && iscomputednan) || \n"); + fprintf(out, " (equal && ((signref == 0 && signcomp == 0) || \n"); + fprintf(out, " (signref != 0 && signcomp != 0))));\n"); + fprintf(out, "}\n\n"); + + fprintf(out, "int main (void) {\n"); + + return out; +} + +void finishOutputC (FILE *out) { + fprintf(out,"return 1;\n"); + fprintf(out, "}\n\n"); + fclose(out); + return; +} + +void printFloatC (FILE *out, float f) { + if (isnan(f)) { + fprintf(out, "NAN"); + } else if (isinf(f)) { + fprintf(out, "%cINFINITY", (signbit(f) == 0) ? ' ' : '-'); + } else { + fprintf(out, "%af", f); + } + + return; +} + +void printFloatSMT (FILE *out, uint32_t f) { + fprintf(out, "(fp (_ bv%d 1) (_ bv%d 8) (_ bv%d 23))", + (f & 0x80000000) >> 31, + (f & 0x7F800000) >> 23, + (f & 0x007FFFFF) >> 0); + return; +} + +FILE * startOutputSMT (const char *name, const char *roundingMode, const uint64_t testNumber) { + FILE * out = openOutputFile("testSMT-%s-%s-%d.smt2", name, roundingMode, testNumber); + + // TODO : version and date + fprintf(out, "(set-logic ALL_SUPPORTED)\n"); + fprintf(out, "; Should be SAT\n"); + + return out; +} + +void finishOutputSMT (FILE *out) { + + fprintf(out, "(check-sat)\n"); + + fclose(out); + return; +} + + + + +/*** Test Execution ***/ + + +typedef uint32_t (*unaryFunctionTFP) (uint32_t); + +template +void unaryFunctionTest (const int verbose, const uint64_t start, const uint64_t end) { + uint64_t i; + + for (i = start; i < end; ++i) { + float f = getTestValue(i); + + uint32_t input = *((uint32_t *)(&f)); + + uint32_t reference = ref(input); + uint32_t computed = test(input); + + if (verbose || !singlePrecisionHardware::smtlibEqual(computed, reference)) { + fprintf(stdout,"vector[%d] ", (uint32_t)i); + fprintf(stdout,"input = 0x%x, computed = 0x%x, real = 0x%x\n", input, computed, reference); + fflush(stdout); + } + + if ((i & 0xFFFF) == 0) { + fprintf(stdout,"."); + fflush(stdout); + } + } + + return; +} + +template +void unaryFunctionPrintC (const int /*verbose*/, const uint64_t start, const uint64_t end, const char *name, const char *cPrintString, const char *) { + uint64_t i; + FILE * out; + + for (i = start; i < end; ++i) { + float f = getTestValue(i); + uint32_t input = *((uint32_t *)(&f)); + + uint32_t reference = ref(input); + float fref = *((float *)(&reference)); + + out = startOutputC(name, "NA", i); + + fprintf(out, "float f = "); + printFloatC(out, f); + fprintf(out,";\n"); + + fprintf(out, "float ref = "); + printFloatC(out, fref); + fprintf(out,";\n"); + + fprintf(out, "float computed = %s;\n", cPrintString); + fprintf(out, "assert(compare(ref, computed));\n"); + + finishOutputC(out); + + } + + return; +} + +template +void unaryFunctionPrintSMT (const int /*verbose*/, const uint64_t start, const uint64_t end, const char *name, const char *SMTPrintString, const char *) { + uint64_t i; + FILE * out; + + for (i = start; i < end; ++i) { + float f = getTestValue(i); + uint32_t input = *((uint32_t *)(&f)); + + uint32_t reference = ref(input); + //float fref = *((float *)(&reference)); + + out = startOutputSMT(name, "NA", i); + + fprintf(out, "(define-fun f () Float32 "); + printFloatSMT(out, input); + fprintf(out, ")\n"); + + fprintf(out, "(define-fun ref () Float32 "); + printFloatSMT(out, reference); + fprintf(out, ")\n"); + + fprintf(out, "(define-fun result () Float32 %s )\n", SMTPrintString); + fprintf(out, "(assert (= ref result))\n"); + + finishOutputSMT(out); + } + + return; +} + +typedef uint32_t (*unaryRoundedFunctionTFP) (uint32_t); + +template +void unaryRoundedFunctionTest (const int verbose, const uint64_t start, const uint64_t end) { + uint64_t i; + + for (i = start; i < end; ++i) { + float f = getTestValue(i); + + uint32_t input = *((uint32_t *)(&f)); + + uint32_t reference = ref(input); + uint32_t computed = test(input); + + if (verbose || !singlePrecisionHardware::smtlibEqual(computed, reference)) { + fprintf(stdout,"vector[%d] ", (uint32_t)i); + fprintf(stdout,"input = 0x%x, computed = 0x%x, real = 0x%x\n", input, computed, reference); + fflush(stdout); + } + + if ((i & 0xFFFF) == 0) { + fprintf(stdout,"."); + fflush(stdout); + } + } + + return; +} + +template +void unaryRoundedFunctionPrintC (const int /*verbose*/, const uint64_t start, const uint64_t end, const char *name, const char *cPrintString, const char *roundingModeString) { + uint64_t i; + FILE * out; + + for (i = start; i < end; ++i) { + float f = getTestValue(i); + uint32_t input = *((uint32_t *)(&f)); + + uint32_t reference = ref(input); + float fref = *((float *)(&reference)); + + out = startOutputC(name, roundingModeString, i); + + fprintf(out, "float f = "); + printFloatC(out, f); + fprintf(out,";\n"); + + fprintf(out, "float ref = "); + printFloatC(out, fref); + fprintf(out,";\n"); + + fprintf(out, "fesetround(%s);\n", roundingModeString); + fprintf(out, "float computed = %s;\n", cPrintString); + fprintf(out, "assert(compare(ref, computed));\n"); + + finishOutputC(out); + + } + + return; +} + +template +void unaryRoundedFunctionPrintSMT (const int /*verbose*/, const uint64_t start, const uint64_t end, const char *name, const char *SMTPrintString, const char *roundingModeString) { + uint64_t i; + FILE * out; + + for (i = start; i < end; ++i) { + float f = getTestValue(i); + uint32_t input = *((uint32_t *)(&f)); + + uint32_t reference = ref(input); + //float fref = *((float *)(&reference)); + + out = startOutputSMT(name, roundingModeString, i); + + fprintf(out, "(define-fun f () Float32 "); + printFloatSMT(out, input); + fprintf(out, ")\n"); + + fprintf(out, "(define-fun ref () Float32 "); + printFloatSMT(out, reference); + fprintf(out, ")\n"); + + fprintf(out, "(define-fun rm () RoundingMode %s )\n", roundingModeString); + + fprintf(out, "(define-fun result () Float32 %s )\n", SMTPrintString); + fprintf(out, "(assert (= ref result))\n"); + + finishOutputSMT(out); + } + + return; +} + + + + +typedef bool (*unaryPredicateTFP) (uint32_t); + +template +void unaryPredicateTest (const int verbose, const uint64_t start, const uint64_t end) { + uint64_t i; + + for (i = start; i < end; ++i) { + float f = getTestValue(i); + + uint32_t input = *((uint32_t *)(&f)); + + bool reference = ref(input); + bool computed = test(input); + + if (verbose || !(computed == reference)) { + fprintf(stdout,"vector[%d] ", (uint32_t)i); + fprintf(stdout,"input = 0x%x, computed = %d, real = %d\n", input, computed, reference); + fflush(stdout); + } + + if ((i & 0xFFFF) == 0) { + fprintf(stdout,"."); + fflush(stdout); + } + } + + return; +} + + +template +void unaryPredicatePrintC (const int /*verbose*/, const uint64_t start, const uint64_t end, const char *name, const char *cPrintString, const char *) { + uint64_t i; + FILE *out; + + for (i = start; i < end; ++i) { + float f = getTestValue(i); + + uint32_t input = *((uint32_t *)(&f)); + + bool reference = ref(input); + + out = startOutputC(name, "NA", i); + + fprintf(out, "float f = "); + printFloatC(out, f); + fprintf(out,";\n"); + + fprintf(out, "assert(%c(%s));\n", (reference) ? ' ' : '!', cPrintString); + + finishOutputC(out); + } + + return;} + +template +void unaryPredicatePrintSMT (const int /*verbose*/, const uint64_t start, const uint64_t end, const char *name, const char *SMTPrintString, const char *) { + uint64_t i; + FILE *out; + + for (i = start; i < end; ++i) { + float f = getTestValue(i); + + uint32_t input = *((uint32_t *)(&f)); + + bool reference = ref(input); + + out = startOutputSMT(name, "NA", i); + + fprintf(out, "(define-fun f () Float32 "); + printFloatSMT(out, input); + fprintf(out, ")\n"); + + fprintf(out, "(define-fun ref () Bool "); + if (reference) { + fprintf(out, "true"); + } else { + fprintf(out, "false"); + } + fprintf(out, ")\n"); + + fprintf(out, "(define-fun result () Bool %s )\n", SMTPrintString); + + fprintf(out, "(assert (= ref result))\n"); + + + finishOutputSMT(out); + } + + return; +} + + +uint64_t splitRight (uint64_t input) { + uint64_t output = 0; + + for (uint64_t i = 0; i <= 63; i +=2) { + output |= (input & (1ULL << i)) ? 1ULL << (i >> 1ULL) : 0; + } + + return output; +} + +uint64_t splitLeft (uint64_t input) { + uint64_t output = 0; + + for (uint64_t i = 1; i <= 63; i +=2) { + output |= (input & (1ULL << i)) ? 1ULL << (i >> 1ULL) : 0; + } + + return output; +} + + +typedef bool (*binaryPredicateTFP) (uint32_t, uint32_t); + +template +void binaryPredicateTest (const int verbose, const uint64_t start, const uint64_t end) { + uint64_t i; + + for (i = start; i < end; ++i) { + uint64_t right = splitRight(i); + uint64_t left = splitLeft(i); + + float f = getTestValue(right); + float g = getTestValue(left); + + uint32_t input1 = *((uint32_t *)(&f)); + uint32_t input2 = *((uint32_t *)(&g)); + + bool reference = ref(input1, input2); + bool computed = test(input1, input2); + + if (verbose || !(computed == reference)) { + fprintf(stdout,"vector[%d -> (%d,%d)] ", (uint32_t)i, (uint32_t)right, (uint32_t)left); + fprintf(stdout,"input1 = 0x%x, input2 = 0x%x, computed = %d, real = %d\n", input1, input2, computed, reference); + fflush(stdout); + } + + if ((i & 0xFFFF) == 0) { + fprintf(stdout,"."); + fflush(stdout); + } + } + + return; +} + +template +void binaryPredicatePrintC (const int /*verbose*/, const uint64_t start, const uint64_t end, const char *name, const char *cPrintString, const char *) { + uint64_t i; + FILE *out; + + for (i = start; i < end; ++i) { + uint64_t right = splitRight(i); + uint64_t left = splitLeft(i); + + float f = getTestValue(right); + float g = getTestValue(left); + + uint32_t input1 = *((uint32_t *)(&f)); + uint32_t input2 = *((uint32_t *)(&g)); + + bool reference = ref(input1, input2); + + out = startOutputC(name, "NA", i); + + fprintf(out, "float f = "); + printFloatC(out, f); + fprintf(out,";\n"); + + fprintf(out, "float g = "); + printFloatC(out, g); + fprintf(out,";\n"); + + fprintf(out, "assert(%c(%s));\n", (reference) ? ' ' : '!', cPrintString); + + finishOutputC(out); + } + + return; +} + +template +void binaryPredicatePrintSMT (const int /*verbose*/, const uint64_t start, const uint64_t end, const char *name, const char *SMTPrintString, const char *) { + uint64_t i; + FILE *out; + + for (i = start; i < end; ++i) { + uint64_t right = splitRight(i); + uint64_t left = splitLeft(i); + + float f = getTestValue(right); + float g = getTestValue(left); + + uint32_t input1 = *((uint32_t *)(&f)); + uint32_t input2 = *((uint32_t *)(&g)); + + bool reference = ref(input1, input2); + + out = startOutputSMT(name, "NA", i); + + fprintf(out, "(define-fun f () Float32 "); + printFloatSMT(out, input1); + fprintf(out, ")\n"); + + fprintf(out, "(define-fun g () Float32 "); + printFloatSMT(out, input2); + fprintf(out, ")\n"); + + fprintf(out, "(define-fun ref () Bool "); + if (reference) { + fprintf(out, "true"); + } else { + fprintf(out, "false"); + } + fprintf(out, ")\n"); + + fprintf(out, "(define-fun result () Bool %s )\n", SMTPrintString); + + fprintf(out, "(assert (= ref result))\n"); + + + + finishOutputSMT(out); + } + + return; +} + + + + + + + + +typedef uint32_t (*binaryFunctionTFP) (uint32_t, uint32_t); + +template +void binaryFunctionTest (const int verbose, const uint64_t start, const uint64_t end) { + uint64_t i; + + for (i = start; i < end; ++i) { + uint64_t right = splitRight(i); + uint64_t left = splitLeft(i); + + float f = getTestValue(right); + float g = getTestValue(left); + + uint32_t input1 = *((uint32_t *)(&f)); + uint32_t input2 = *((uint32_t *)(&g)); + + uint32_t reference = ref(input1, input2); + uint32_t computed = test(input1, input2); + + if (verbose || !singlePrecisionHardware::smtlibEqual(computed, reference)) { + fprintf(stdout,"vector[%d -> (%d,%d)] ", (uint32_t)i, (uint32_t)right, (uint32_t)left); + fprintf(stdout,"input1 = 0x%x, input2 = 0x%x, computed = 0x%x, real = 0x%x\n", input1, input2, computed, reference); + fflush(stdout); + } + + if ((i & 0xFFFF) == 0) { + fprintf(stdout,"."); + fflush(stdout); + } + } + + return; +} + +template +void binaryFunctionPrintC (const int /*verbose*/, const uint64_t start, const uint64_t end, const char *name, const char *cPrintString, const char */*roundingModeString*/) { + uint64_t i; + FILE *out; + + for (i = start; i < end; ++i) { + uint64_t right = splitRight(i); + uint64_t left = splitLeft(i); + + float f = getTestValue(right); + float g = getTestValue(left); + + uint32_t input1 = *((uint32_t *)(&f)); + uint32_t input2 = *((uint32_t *)(&g)); + + uint32_t reference = ref(input1, input2); + float fref = *((float *)(&reference)); + + out = startOutputC(name, "NA", i); + + fprintf(out, "float f = "); + printFloatC(out, f); + fprintf(out,";\n"); + + fprintf(out, "float g = "); + printFloatC(out, g); + fprintf(out,";\n"); + + fprintf(out, "float ref = "); + printFloatC(out, fref); + fprintf(out,";\n"); + + fprintf(out, "float computed = %s;\n", cPrintString); + fprintf(out, "assert(compare(ref, computed));\n"); + + finishOutputC(out); + + } + + return; +} + +template +void binaryFunctionPrintSMT (const int /*verbose*/, const uint64_t start, const uint64_t end, const char *name, const char *SMTPrintString, const char */*roundingModeString*/) { + uint64_t i; + FILE *out; + + for (i = start; i < end; ++i) { + uint64_t right = splitRight(i); + uint64_t left = splitLeft(i); + + float f = getTestValue(right); + float g = getTestValue(left); + + uint32_t input1 = *((uint32_t *)(&f)); + uint32_t input2 = *((uint32_t *)(&g)); + + uint32_t reference = ref(input1, input2); + //uint32_t fref = *((float *)(&reference)); + + out = startOutputSMT(name, "NA", i); + + fprintf(out, "(define-fun f () Float32 "); + printFloatSMT(out, input1); + fprintf(out, ")\n"); + + fprintf(out, "(define-fun g () Float32 "); + printFloatSMT(out, input2); + fprintf(out, ")\n"); + + fprintf(out, "(define-fun ref () Float32 "); + printFloatSMT(out, reference); + fprintf(out, ")\n"); + + fprintf(out, "(define-fun result () Float32 %s )\n", SMTPrintString); + + fprintf(out, "(assert (= ref result))\n"); + + + finishOutputSMT(out); + + } + + return; +} + + + + +typedef uint32_t (*binaryRoundedFunctionTFP) (uint32_t, uint32_t); + +template +void binaryRoundedFunctionTest (const int verbose, const uint64_t start, const uint64_t end) { + uint64_t i; + + for (i = start; i < end; ++i) { + uint64_t right = splitRight(i); + uint64_t left = splitLeft(i); + + float f = getTestValue(right); + float g = getTestValue(left); + + uint32_t input1 = *((uint32_t *)(&f)); + uint32_t input2 = *((uint32_t *)(&g)); + + uint32_t reference = ref(input1, input2); + uint32_t computed = test(input1, input2); + + if (verbose || !singlePrecisionHardware::smtlibEqual(computed, reference)) { + fprintf(stdout,"vector[%d -> (%d,%d)] ", (uint32_t)i, (uint32_t)right, (uint32_t)left); + fprintf(stdout,"input1 = 0x%x, input2 = 0x%x, computed = 0x%x, real = 0x%x\n", input1, input2, computed, reference); + fflush(stdout); + } + + if ((i & 0xFFFF) == 0) { + fprintf(stdout,"."); + fflush(stdout); + } + } + + return; +} + +template +void binaryRoundedFunctionPrintC (const int /*verbose*/, const uint64_t start, const uint64_t end, const char *name, const char *cPrintString, const char *roundingModeString) { + uint64_t i; + FILE *out; + + for (i = start; i < end; ++i) { + uint64_t right = splitRight(i); + uint64_t left = splitLeft(i); + + float f = getTestValue(right); + float g = getTestValue(left); + + uint32_t input1 = *((uint32_t *)(&f)); + uint32_t input2 = *((uint32_t *)(&g)); + + uint32_t reference = ref(input1, input2); + float fref = *((float *)(&reference)); + + out = startOutputC(name, roundingModeString, i); + + fprintf(out, "float f = "); + printFloatC(out, f); + fprintf(out,";\n"); + + fprintf(out, "float g = "); + printFloatC(out, g); + fprintf(out,";\n"); + + fprintf(out, "float ref = "); + printFloatC(out, fref); + fprintf(out,";\n"); + + fprintf(out, "fesetround(%s);\n", roundingModeString); + fprintf(out, "float computed = %s;\n", cPrintString); + fprintf(out, "assert(compare(ref, computed));\n"); + + finishOutputC(out); + + } + + return; +} + +template +void binaryRoundedFunctionPrintSMT (const int /*verbose*/, const uint64_t start, const uint64_t end, const char *name, const char *SMTPrintString, const char *roundingModeString) { + uint64_t i; + FILE *out; + + for (i = start; i < end; ++i) { + uint64_t right = splitRight(i); + uint64_t left = splitLeft(i); + + float f = getTestValue(right); + float g = getTestValue(left); + + uint32_t input1 = *((uint32_t *)(&f)); + uint32_t input2 = *((uint32_t *)(&g)); + + uint32_t reference = ref(input1, input2); + //uint32_t fref = *((float *)(&reference)); + + out = startOutputSMT(name, roundingModeString, i); + + fprintf(out, "(define-fun f () Float32 "); + printFloatSMT(out, input1); + fprintf(out, ")\n"); + + fprintf(out, "(define-fun g () Float32 "); + printFloatSMT(out, input2); + fprintf(out, ")\n"); + + fprintf(out, "(define-fun ref () Float32 "); + printFloatSMT(out, reference); + fprintf(out, ")\n"); + + fprintf(out, "(define-fun rm () RoundingMode %s )\n", roundingModeString); + + fprintf(out, "(define-fun result () Float32 %s )\n", SMTPrintString); + + fprintf(out, "(assert (= ref result))\n"); + + + finishOutputSMT(out); + + } + + return; +} + + + + + + + +uint64_t splitOneOfThree (uint64_t input) { + uint64_t output = 0; + + for (uint64_t i = 0; i <= 63; i +=3) { + output |= (input & (1ULL << i)) ? 1ULL << (i >> 1ULL) : 0; + } + + return output; +} + +uint64_t splitTwoOfThree (uint64_t input) { + uint64_t output = 0; + + for (uint64_t i = 1; i <= 63; i +=3) { + output |= (input & (1ULL << i)) ? 1ULL << (i >> 1ULL) : 0; + } + + return output; +} + +uint64_t splitThreeOfThree (uint64_t input) { + uint64_t output = 0; + + for (uint64_t i = 2; i <= 63; i +=3) { + output |= (input & (1ULL << i)) ? 1ULL << (i >> 1ULL) : 0; + } + + return output; +} + +typedef uint32_t (*ternaryRoundedFunctionTFP) (uint32_t, uint32_t, uint32_t); + +template +void ternaryRoundedFunctionTest (const int verbose, const uint64_t start, const uint64_t end) { + uint64_t i; + + for (i = start; i < end; ++i) { + uint64_t right = splitOneOfThree(i); + uint64_t middle = splitTwoOfThree(i); + uint64_t left = splitThreeOfThree(i); + + float f = getTestValue(right); + float g = getTestValue(middle); + float h = getTestValue(left); + + uint32_t input1 = *((uint32_t *)(&f)); + uint32_t input2 = *((uint32_t *)(&g)); + uint32_t input3 = *((uint32_t *)(&h)); + + uint32_t reference = ref(input1, input2, input3); + uint32_t computed = test(input1, input2, input3); + + if (verbose || !singlePrecisionHardware::smtlibEqual(computed, reference)) { + fprintf(stdout,"vector[%d -> (%d,%d,%d)] ", (uint32_t)i, (uint32_t)right, (uint32_t)middle, (uint32_t)left); + fprintf(stdout,"input1 = 0x%x, input2 = 0x%x, input3 = 0x%x, computed = 0x%x, real = 0x%x\n", input1, input2, input3, computed, reference); + fflush(stdout); + } + + if ((i & 0xFFFF) == 0) { + fprintf(stdout,"."); + fflush(stdout); + } + } + + return; +} + +template +void ternaryRoundedFunctionPrintC (const int /*verbose*/, const uint64_t start, const uint64_t end, const char *name, const char *cPrintString, const char *roundingModeString) { + uint64_t i; + FILE *out; + + for (i = start; i < end; ++i) { + uint64_t right = splitOneOfThree(i); + uint64_t middle = splitTwoOfThree(i); + uint64_t left = splitThreeOfThree(i); + + float f = getTestValue(right); + float g = getTestValue(middle); + float h = getTestValue(left); + + uint32_t input1 = *((uint32_t *)(&f)); + uint32_t input2 = *((uint32_t *)(&g)); + uint32_t input3 = *((uint32_t *)(&h)); + + uint32_t reference = ref(input1, input2, input3); + float fref = *((float *)(&reference)); + + out = startOutputC(name, roundingModeString, i); + + fprintf(out, "float f = "); + printFloatC(out, f); + fprintf(out,";\n"); + + fprintf(out, "float g = "); + printFloatC(out, g); + fprintf(out,";\n"); + + fprintf(out, "float h = "); + printFloatC(out, g); + fprintf(out,";\n"); + + fprintf(out, "float ref = "); + printFloatC(out, fref); + fprintf(out,";\n"); + + fprintf(out, "fesetround(%s);\n", roundingModeString); + fprintf(out, "float computed = %s;\n", cPrintString); + fprintf(out, "assert(compare(ref, computed));\n"); + + finishOutputC(out); + } + + return; +} + +template +void ternaryRoundedFunctionPrintSMT (const int /*verbose*/, const uint64_t start, const uint64_t end, const char *name, const char *SMTPrintString, const char *roundingModeString) { + uint64_t i; + FILE *out; + + for (i = start; i < end; ++i) { + uint64_t right = splitOneOfThree(i); + uint64_t middle = splitTwoOfThree(i); + uint64_t left = splitThreeOfThree(i); + + float f = getTestValue(right); + float g = getTestValue(middle); + float h = getTestValue(left); + + uint32_t input1 = *((uint32_t *)(&f)); + uint32_t input2 = *((uint32_t *)(&g)); + uint32_t input3 = *((uint32_t *)(&h)); + + uint32_t reference = ref(input1, input2, input3); + // float fref = *((float *)(&reference)); + + out = startOutputSMT(name, roundingModeString, i); + + fprintf(out, "(define-fun f () Float32 "); + printFloatSMT(out, input1); + fprintf(out, ")\n"); + + fprintf(out, "(define-fun g () Float32 "); + printFloatSMT(out, input2); + fprintf(out, ")\n"); + + fprintf(out, "(define-fun h () Float32 "); + printFloatSMT(out, input2); + fprintf(out, ")\n"); + + fprintf(out, "(define-fun ref () Float32 "); + printFloatSMT(out, reference); + fprintf(out, ")\n"); + + fprintf(out, "(define-fun rm () RoundingMode %s )\n", roundingModeString); + + fprintf(out, "(define-fun result () Float32 %s )\n", SMTPrintString); + + fprintf(out, "(assert (= ref result))\n"); + + + finishOutputSMT(out); + } + + return; +} + + + +typedef void (*testFunction) (const int, const uint64_t, const uint64_t); +typedef void (*printFunction) (const int, const uint64_t, const uint64_t, const char *, const char *, const char *); + +struct testStruct { + int enable; + const int usesRounding; + const char *name; + const testFunction run; + const printFunction printC; + const printFunction printSMT; + const char *cPrintString; + const char *SMTPrintString; +}; + +struct roundingModeTestStruct { + int enable; + const char *name; + const int value; + const char *cPrintString; +}; + + + + + +/*** Application ***/ + + + +#define INCREMENT 0xFFFFFF + +#define TEST 0 +#define PRINTC 1 +#define PRINTSMT 2 + +// Save on typing! +#define INST(T,F) T##Test, T##PrintC, T##PrintSMT + +int main (int argc, char **argv) { + struct testStruct tests[] = { + {0,0, "unpackPack", INST( unaryFunction, unpackPack), "f", "f"}, + {0,0, "negate", INST( unaryFunction, negate), "-f", "(fp.neg f)"}, + {0,0, "absolute", INST( unaryFunction, absolute), "fabsf(f)", "(fp.abs f)"}, + {0,0, "isNormal", INST(unaryPredicate, isNormal), "isnormal(f)", "(fp.isNormal f)"}, + {0,0, "isSubnormal", INST(unaryPredicate, isSubnormal), "fpclassify(f) == FP_SUBNORMAL", "(fp.isSubnormal f)"}, + {0,0, "isZero", INST(unaryPredicate, isZero), "(f) == 0.0f", "(fp.isZero f)"}, + {0,0, "isInfinite", INST(unaryPredicate, isInfinite), "isinf(f)", "(fp.isInfinite f)"}, + {0,0, "isNaN", INST(unaryPredicate, isNaN), "isnan(f)", "(fp.isNaN f)"}, + {0,0, "isPositive", INST(unaryPredicate, isPositive), "!isnan(f) && signbit(f) == 0", "(fp.isPositive f)"}, + {0,0, "isNegative", INST(unaryPredicate, isNegative), "!isnan(f) && signbit(f) != 0", "(fp.isNegative f)"}, + {0,0, "SMT-LIB_equal", INST(binaryPredicate, smtlibEqual), "compare(f,g)", "(= f g)"}, + {0,0, "IEE754_equal", INST(binaryPredicate, ieee754Equal), "f == g", "(fp.eq f g)"}, + {0,0, "less_than", INST(binaryPredicate, lessThan), "f < g", "(fp.lt f g)"}, + {0,0, "less_than_or_equal", INST(binaryPredicate, lessThanOrEqual), "f <= g", "(fp.leq f g)"}, + {0,1, "multiply", INST(binaryRoundedFunction, multiply), "f * g", "(fp.mul rm f g)"}, + {0,1, "add", INST(binaryRoundedFunction, add), "f + g", "(fp.add rm f g)"}, + {0,1, "subtract", INST(binaryRoundedFunction, sub), "f - g", "(fp.sub rm f g)"}, + {0,1, "divide", INST(binaryRoundedFunction, div), "f / g", "(fp.div rm f g)"}, + {0,0, "max", INST(binaryFunction, max), "fmaxf(f,g)", "(fp.max f g)"}, + {0,0, "min", INST(binaryFunction, min), "fminf(f,g)", "(fp.min f g)"}, + {0,1, "sqrt", INST(unaryRoundedFunction, sqrt), "sqrtf(f)", "(fp.sqrt rm f)"}, + {0,1, "round_to_integral", INST(unaryRoundedFunction, rti), "(fegetround()==FE_TONEAREST) ? rintf(f) : (fegetround()==FE_UPWARD) ? ceilf(f) : (fegetround()==FE_DOWNWARD) ? floorf(f) : truncf(f)", "(fp.roundToIntegral rm f)"}, + {0,1, "fma", INST(ternaryRoundedFunction, fma), "fmaf(f,g)", "(fp.fma rm f g h)"}, + {0,0, "remainder", INST(binaryFunction, rem), "remainderf(f,g)", "(fp.remainder f g)"}, + {0,0, NULL, NULL, NULL, NULL, NULL, NULL} + }; + + struct roundingModeTestStruct roundingModeTests[] = { + {0, "RNE", FE_TONEAREST, "FE_TONEAREST"}, + {0, "RTP", FE_UPWARD, "FE_UPWARD"}, + {0, "RTN", FE_DOWNWARD, "FE_DOWNWARD"}, + {0, "RTZ", FE_TOWARDZERO, "FE_TOWARDZERO"}, + //{0, "RNA", FE_???, "FE_???"}, // Disabled until a suitable reference is available + {0, NULL, 0, NULL} + }; + + uint64_t start = 0; + uint64_t end = INCREMENT; + int verbose = 0; + int help = 0; + int enableAllTests = 0; + int enableAllRoundingModes = 0; + int continuous = 0; + int action = TEST; + + struct option options[] = { + { "verbose", no_argument, &verbose, 1 }, + { "help", no_argument, &help, 1 }, + + { "start", required_argument, NULL, 's'}, + { "end", required_argument, NULL, 'e'}, + { "specialValues", no_argument, NULL, 't'}, + { "continuous", no_argument, &continuous, 1 }, + + { "allTests", no_argument, &enableAllTests, 1 }, + {"allRoundingModes", no_argument, &enableAllRoundingModes, 1 }, + + { "printC", no_argument, &action, PRINTC }, + { "printSMT", no_argument, &action, PRINTSMT }, + + { "unpackPack", no_argument, &(tests[0].enable), 1 }, + { "negate", no_argument, &(tests[1].enable), 1 }, + { "absolute", no_argument, &(tests[2].enable), 1 }, + { "isNormal", no_argument, &(tests[3].enable), 1 }, + { "isSubnormal", no_argument, &(tests[4].enable), 1 }, + { "isZero", no_argument, &(tests[5].enable), 1 }, + { "isInfinite", no_argument, &(tests[6].enable), 1 }, + { "isNaN", no_argument, &(tests[7].enable), 1 }, + { "isPositive", no_argument, &(tests[8].enable), 1 }, + { "isNegative", no_argument, &(tests[9].enable), 1 }, + { "smtlibEqual", no_argument, &(tests[10].enable), 1 }, + { "ieee754Equal", no_argument, &(tests[11].enable), 1 }, + { "lessThan", no_argument, &(tests[12].enable), 1 }, + { "lessThanOrEqual", no_argument, &(tests[13].enable), 1 }, + { "multiply", no_argument, &(tests[14].enable), 1 }, + { "add", no_argument, &(tests[15].enable), 1 }, + { "subtract", no_argument, &(tests[16].enable), 1 }, + { "divide", no_argument, &(tests[17].enable), 1 }, + { "max", no_argument, &(tests[18].enable), 1 }, + { "min", no_argument, &(tests[19].enable), 1 }, + { "sqrt", no_argument, &(tests[20].enable), 1 }, + { "rti", no_argument, &(tests[21].enable), 1 }, + { "fma", no_argument, &(tests[22].enable), 1 }, + { "remainder", no_argument, &(tests[23].enable), 1 }, + { "rne", no_argument, &(roundingModeTests[0].enable), 1 }, + { "rtp", no_argument, &(roundingModeTests[1].enable), 1 }, + { "rtn", no_argument, &(roundingModeTests[2].enable), 1 }, + { "rtz", no_argument, &(roundingModeTests[3].enable), 1 }, + //{ "rna", no_argument, &(roundingModeTests[4].enable), 1 }, + { "RNE", no_argument, &(roundingModeTests[0].enable), 1 }, + { "RTP", no_argument, &(roundingModeTests[1].enable), 1 }, + { "RTN", no_argument, &(roundingModeTests[2].enable), 1 }, + { "RTZ", no_argument, &(roundingModeTests[3].enable), 1 }, + //{ "RNA", no_argument, &(roundingModeTests[4].enable), 1 }, + { NULL, 0, NULL, 0 } + + + }; + + bool parseOptions = true; + while (parseOptions) { + int currentOption = 0; + int response = getopt_long(argc, argv, "vs:e:t", options, ¤tOption); + + switch(response) { + case 'v' : + verbose = 1; + break; + + case 's' : + start = strtoull(optarg,NULL,0); + break; + + case 'e' : + end = strtoull(optarg,NULL,0); + break; + + case 't' : + end = NUMBER_OF_FLOAT_TESTS * NUMBER_OF_FLOAT_TESTS; // TODO : split doesn't work like this so this isn't quite right + break; + + case 0 : /* Flag set */ + break; + + case -1 : /* End of options */ + parseOptions = false; + break; + + case '?' : /* Unknown option */ + fprintf(stderr,"Unknown option : \"%s\"\n", optarg); + return 1; + break; + + default : /* Unrecognised getopt response */ + fprintf(stderr,"Unrecognised getopt response \'%d\' from \"%s\"\n",response, optarg); + return 1; + break; + } + } + + /* Help text */ + if (help) { + fprintf(stderr, "TODO: Super helpful message here!\n"); + + fprintf(stderr, "Options : \n"); + struct option *opt = &(options[0]); + while (opt->name != NULL) { + switch (opt->has_arg) { + case no_argument : fprintf(stderr, "\t--%s\n", opt->name); break; + case required_argument : fprintf(stderr, "\t--%s\t argument\n", opt->name); break; + case optional_argument : fprintf(stderr, "\t--%s\t[ argument ]\n", opt->name); break; + default : fprintf(stderr, "\t--%s\t???\n", opt->name); break; + } + + ++opt; + } + + return 0; + } + + int roundingModeSet = 0; + uint64_t j = 0; + while (roundingModeTests[j].name != NULL) { + roundingModeSet |= roundingModeTests[j].enable; + ++j; + } + if (!roundingModeSet && !enableAllRoundingModes) { + // Set default rounding mode of RNE + roundingModeTests[0].enable = 1; + } + + + singlePrecisionExecutableSymfpu::setFormat(singlePrecisionFormatObject); + + top : + + /* Run the tests */ + int i = 0; + while (tests[i].name != NULL) { + if (enableAllTests || tests[i].enable) { + if (tests[i].usesRounding) { + + int j = 0; + while (roundingModeTests[j].name != NULL) { + if (enableAllRoundingModes || roundingModeTests[j].enable) { + fprintf(stdout, "Running test for %s %s : ", tests[i].name, roundingModeTests[j].name); + fflush(stdout); + + singlePrecisionExecutableSymfpu::setRoundingMode(roundingModeTests[j].value); + singlePrecisionHardware::setRoundingMode(roundingModeTests[j].value); + + switch (action) { + case TEST : + tests[i].run(verbose, start, end); + break; + + case PRINTC : + tests[i].printC(verbose, start, end, tests[i].name, tests[i].cPrintString, roundingModeTests[j].cPrintString); + break; + + case PRINTSMT : + tests[i].printSMT(verbose, start, end, tests[i].name, tests[i].SMTPrintString, roundingModeTests[j].name); + break; + + default : + assert(0); + break; + } + + fprintf(stdout, "\n"); + fflush(stdout); + } + ++j; + } + + + } else { + fprintf(stdout, "Running test for %s : ", tests[i].name); + fflush(stdout); + + switch (action) { + case TEST : + tests[i].run(verbose, start, end); + break; + + case PRINTC : + tests[i].printC(verbose, start, end, tests[i].name, tests[i].cPrintString, NULL); + break; + + case PRINTSMT : + tests[i].printSMT(verbose, start, end, tests[i].name, tests[i].SMTPrintString, NULL); + break; + + default : + assert(0); + break; + } + + fprintf(stdout, "\n"); + fflush(stdout); + + } + + } + i++; + + } + + if (continuous) { + uint64_t oldEnd = end; + end += (end - start); + start = oldEnd; + goto top; + } + + singlePrecisionExecutableSymfpu::destroyFormat(); + + return 1; +} diff --git a/third-party/symfpu/baseTypes/Makefile b/third-party/symfpu/baseTypes/Makefile new file mode 100644 index 0000000..0b69808 --- /dev/null +++ b/third-party/symfpu/baseTypes/Makefile @@ -0,0 +1,11 @@ +include ../flags +CXXFLAGS+=-I../../ +ALL=simpleExecutable.o + +.PHONY : all + +all : $(ALL) + +%.o : %.cpp + $(CXX) $(CXXFLAGS) -g -c $^ -o $@ + diff --git a/third-party/symfpu/baseTypes/cprover_bvt.cpp b/third-party/symfpu/baseTypes/cprover_bvt.cpp new file mode 100644 index 0000000..2b730b1 --- /dev/null +++ b/third-party/symfpu/baseTypes/cprover_bvt.cpp @@ -0,0 +1,47 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +#include "symfpu/baseTypes/cprover_bvt.h" + +namespace symfpu { + namespace cprover_bvt { + bv_utilst *solver = NULL; + + #define BITS 32 + + roundingMode traits::RNE (void) { + return roundingMode(solver->build_constant(0/*ieee_floatt::ROUND_TO_EVEN*/, BITS)); + } + + roundingMode traits::RNA (void) { + return roundingMode(solver->build_constant(4, BITS)); + } + + roundingMode traits::RTP (void) { + return roundingMode(solver->build_constant(2/*ieee_floatt::ROUND_TO_PLUS_INF*/, BITS)); + } + + roundingMode traits::RTN (void) { + return roundingMode(solver->build_constant(1/*ieee_floatt::ROUND_TO_MINUS_INF*/, BITS)); + } + + roundingMode traits::RTZ (void) { + return roundingMode(solver->build_constant(3/*ieee_floatt::ROUND_TO_ZERO*/, BITS)); + } + + } +} diff --git a/third-party/symfpu/baseTypes/cprover_bvt.h b/third-party/symfpu/baseTypes/cprover_bvt.h new file mode 100644 index 0000000..49e73b5 --- /dev/null +++ b/third-party/symfpu/baseTypes/cprover_bvt.h @@ -0,0 +1,422 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** cprover_bvt.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 12/04/17 +** +** Implement bit-vectors by generating CPROVER bit-vectors (bvt) +** +*/ + +// Symfpu headers +#include "../utils/properties.h" +#include "../utils/numberOfRoundingModes.h" +#include "../core/ite.h" + +// CPROVER headers +#include +#include + +// Common components +#include "cprover_common.h" + +#ifndef SYMFPU_CPROVER_BVT +#define SYMFPU_CPROVER_BVT + +namespace symfpu { + namespace cprover_bvt { + + typedef symfpu::cprover_common::bitWidthType bitWidthType; + typedef symfpu::cprover_common::floatingPointTypeInfo floatingPointTypeInfo; + + // Forward declarations + class roundingMode; + class proposition; + template class bitVector; + + // Wrap up the types into one template parameter + class traits { + public : + typedef bitWidthType bwt; + typedef roundingMode rm; + typedef floatingPointTypeInfo fpt; + typedef proposition prop; + typedef bitVector< true> sbv; + typedef bitVector ubv; + + static roundingMode RNE (void); + static roundingMode RNA (void); + static roundingMode RTP (void); + static roundingMode RTN (void); + static roundingMode RTZ (void); + + // Literal invariants + inline static void precondition (const bool b) { assert(b); return; } + inline static void postcondition (const bool b) { assert(b); return; } + inline static void invariant (const bool b) { assert(b); return; } + + // Symbolic invariants + // TODO : Add to the solver + inline static void precondition(const prop &p) { return; } + inline static void postcondition(const prop &p) { return; } + inline static void invariant(const prop &p) { return; } + + }; + + // To simplify the property macros + typedef traits t; + + // TODO : Fix this hack + extern bv_utilst *solver; + + // (_ BitVec 1) version + class proposition : public literalt { + protected : + friend ite; // For ITE + + public : + proposition (const literalt l) : literalt(l) {} + proposition (bool v) : literalt() { + if (v) { + make_true(); + } else { + make_false(); + } + } + proposition (const proposition &old) : literalt(old) {} + + + proposition operator ! (void) const { + return proposition(this->literalt::operator!()); + } + + proposition operator && (const proposition &op) const { + return proposition(solver->prop.land(*this,op)); + } + + proposition operator || (const proposition &op) const { + return proposition(solver->prop.lor(*this,op)); + } + + proposition operator == (const proposition &op) const { + return proposition(solver->prop.lequal(*this,op)); + } + + proposition operator ^ (const proposition &op) const { + return proposition(solver->prop.lxor(*this,op)); + } + + }; + + + + class roundingMode : public bvt { + protected: + friend ite; // For ITE + + public : + roundingMode (const bvt &op) : bvt(op) {} + roundingMode (const unsigned v) : bvt(solver->build_constant(v,32)) {} + roundingMode (const roundingMode &old) : bvt(old) {} + + proposition valid (void) const { + // TODO : Improve... + return true; + } + + proposition operator == (const roundingMode &op) const { + return proposition(solver->equal(*this,op)); + } + + }; + + + + template + class bitVector : public bvt { + protected : + friend bitVector; // To allow conversion between the types + friend ite >; // For ITE + + public : + bitVector (const bitWidthType w, const unsigned v) : bvt(solver->build_constant(v,w)) {} + bitVector (const bvt &old) : bvt(old) {} + bitVector (const proposition &p) { push_back(p); } + bitVector (const bitVector &old) : bvt(old) {} + + bitWidthType getWidth (void) const { + return size(); + } + + + /*** Constant creation and test ***/ + + static bitVector one (const bitWidthType &w) { return bitVector(w,1); } + static bitVector zero (const bitWidthType &w) { return bitVector(w,0); } + static bitVector allOnes (const bitWidthType &w) { return ~zero(w); } + + + inline proposition isAllOnes() const { return proposition(solver->is_all_ones(*this)); } + inline proposition isAllZeros() const { return proposition(solver->is_zero(*this)); } + + static bitVector maxValue (const bitWidthType &w) { + if (isSigned) { + return zero(1).append(allOnes(w-1)); + } else { + return allOnes(w); + } + } + + static bitVector minValue (const bitWidthType &w) { + if (isSigned) { + return allOnes(w); + } else { + return zero(w); + } + } + + + /*** Operators ***/ + inline bitVector operator << (const bitVector &op) const { + return bitVector(solver->shift(*this, bv_utilst::shiftt::LEFT, op)); + } + + inline bitVector operator >> (const bitVector &op) const { + return bitVector(solver->shift(*this, isSigned ? bv_utilst::shiftt::ARIGHT : bv_utilst::shiftt::LRIGHT, op)); + } + + + inline bitVector operator | (const bitVector &op) const { + bitVector bv(*this); + + unsigned width = bv.size(); + for(std::size_t i=0; iprop.lor(bv[i], op[i]); + + return bv; + } + + inline bitVector operator & (const bitVector &op) const { + bitVector bv(*this); + + unsigned width = bv.size(); + for(std::size_t i=0; iprop.land(bv[i], op[i]); + + return bv; + } + + inline bitVector operator + (const bitVector &op) const { + return bitVector(solver->add(*this, op)); + } + + inline bitVector operator - (const bitVector &op) const { + return bitVector(solver->sub(*this, op)); + } + + inline bitVector operator * (const bitVector &op) const { + return bitVector(isSigned ? + solver->signed_multiplier(*this, op) : + solver->unsigned_multiplier(*this, op)); + } + + inline bitVector operator / (const bitVector &op) const { + return bitVector(solver->divider(*this, op, isSigned ? bv_utilst::representationt::SIGNED : bv_utilst::representationt::UNSIGNED)); + } + + inline bitVector operator % (const bitVector &op) const { + return bitVector(solver->remainder(*this, op, isSigned ? bv_utilst::representationt::SIGNED : bv_utilst::representationt::UNSIGNED)); + } + + + inline bitVector operator - (void) const { + return bitVector(solver->negate(*this)); + } + + inline bitVector operator ~ (void) const { + bitVector bv(*this); + + unsigned width = bv.size(); + for(std::size_t i=0; i increment () const { + return bitVector(solver->inc(*this)); + } + + inline bitVector decrement () const { + return *this - bitVector::one(getWidth()); + } + + inline bitVector signExtendRightShift (const bitVector &op) const { + return bitVector(solver->shift(*this, bv_utilst::shiftt::ARIGHT, op)); + } + + + + /*** Modular opertaions ***/ + // No overflow checking so these are the same as other operations + inline bitVector modularLeftShift (const bitVector &op) const { + return *this << op; + } + + inline bitVector modularRightShift (const bitVector &op) const { + return *this >> op; + } + + inline bitVector modularIncrement () const { + return this->increment(); + } + + inline bitVector modularDecrement () const { + return this->decrement(); + } + + inline bitVector modularAdd (const bitVector &op) const { + return *this + op; + } + + inline bitVector modularNegate () const { + return -(*this); + } + + + + + /*** Comparisons ***/ + + inline proposition operator == (const bitVector &op) const { + return proposition(solver->equal(*this, op)); + } + + inline proposition operator <= (const bitVector &op) const { + return proposition(solver->rel(*this, ID_le, op, isSigned ? bv_utilst::representationt::SIGNED : bv_utilst::representationt::UNSIGNED)); + } + + inline proposition operator >= (const bitVector &op) const { + return proposition(solver->rel(*this, ID_ge, op, isSigned ? bv_utilst::representationt::SIGNED : bv_utilst::representationt::UNSIGNED)); + } + + inline proposition operator < (const bitVector &op) const { + return proposition(solver->rel(*this, ID_lt, op, isSigned ? bv_utilst::representationt::SIGNED : bv_utilst::representationt::UNSIGNED)); + } + + inline proposition operator > (const bitVector &op) const { + return proposition(solver->rel(*this, ID_gt, op, isSigned ? bv_utilst::representationt::SIGNED : bv_utilst::representationt::UNSIGNED)); + } + + /*** Type conversion ***/ + // CPROVER bvts make no distinction between signed and unsigned, thus ... + bitVector toSigned (void) const { + return bitVector(*this); + } + bitVector toUnsigned (void) const { + return bitVector(*this); + } + + + + /*** Bit hacks ***/ + + inline bitVector extend (bitWidthType extension) const { + return bitVector(solver->extension(*this, this->size() + extension, isSigned ? bv_utilst::representationt::SIGNED : bv_utilst::representationt::UNSIGNED)); + } + + inline bitVector contract (bitWidthType reduction) const { + bitVector bv(*this); + bv.bvt::resize(bv.size() - reduction); + return bv; + } + + inline bitVector resize (bitWidthType newSize) const { + bitWidthType width = this->getWidth(); + + if (newSize > width) { + return this->extend(newSize - width); + } else if (newSize < width) { + return this->contract(width - newSize); + } else { + return *this; + } + } + + inline bitVector matchWidth (const bitVector &op) const { + PRECONDITION(this->getWidth() <= op.getWidth()); + return this->extend(op.getWidth() - this->getWidth()); + } + + + bitVector append(const bitVector &op) const { + bitVector bv(op); + + bv.insert(bv.end(), this->begin(), this->end()); + + return bv; + } + + // Inclusive of end points, thus if the same, extracts just one bit + bitVector extract(bitWidthType upper, bitWidthType lower) const { + PRECONDITION(upper >= lower); + + bitVector bv(upper-lower + 1, 0); + + for (bitWidthType i = lower; i <= upper; ++i) { + bv[i - lower] = (*this)[i]; + } + + return bv; + } + }; + + }; + + + template <> + struct ite { + static const cprover_bvt::proposition iteOp (const cprover_bvt::proposition &cond, + const cprover_bvt::proposition &l, + const cprover_bvt::proposition &r) { + return cprover_bvt::proposition(symfpu::cprover_bvt::solver->prop.lselect(cond,l,r)); + } + }; + +#define CPROVERBVTITEDFN(T) template <> \ + struct ite { \ + static const T iteOp (const cprover_bvt::proposition &cond, \ + const T &l, \ + const T &r) { \ + assert(l.size() == r.size()); \ + return T(symfpu::cprover_bvt::solver->select(cond,l,r)); \ + } \ + }; + + CPROVERBVTITEDFN(cprover_bvt::traits::rm); + CPROVERBVTITEDFN(cprover_bvt::traits::sbv); + CPROVERBVTITEDFN(cprover_bvt::traits::ubv); + +#undef CPROVERBVTITEDFN + +}; + +#endif diff --git a/third-party/symfpu/baseTypes/cprover_common.h b/third-party/symfpu/baseTypes/cprover_common.h new file mode 100644 index 0000000..9d8af57 --- /dev/null +++ b/third-party/symfpu/baseTypes/cprover_common.h @@ -0,0 +1,63 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** cprover_common.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 24/06/17 +** +** Common CPROVER components. +** +*/ + +// CPROVER headers +#include + +#ifndef SYMFPU_CPROVER_COMMON +#define SYMFPU_CPROVER_COMMON + +namespace symfpu { + namespace cprover_common { + + typedef unsigned bitWidthType; + + + class floatingPointTypeInfo : public ieee_float_spect { + protected : + //friend ite; // For ITE + + public : + // CPROVER's format's significand doesn't include the hidden bit + floatingPointTypeInfo(const ieee_float_spect &old) : ieee_float_spect(old) {} + floatingPointTypeInfo(const floatbv_typet &t) : ieee_float_spect(t) {} + floatingPointTypeInfo(unsigned exp, unsigned sig) : ieee_float_spect(sig - 1, exp) {} + floatingPointTypeInfo(const floatingPointTypeInfo &old) : ieee_float_spect(old) {} + + bitWidthType exponentWidth(void) const { return this->e; } + bitWidthType significandWidth(void) const { return this->f + 1; } + + bitWidthType packedWidth(void) const { return this->e + this->f + 1; } + bitWidthType packedExponentWidth(void) const { return this->e; } + bitWidthType packedSignificandWidth(void) const { return this->f; } + }; + + }; +}; + +#endif diff --git a/third-party/symfpu/baseTypes/cprover_exprt.cpp b/third-party/symfpu/baseTypes/cprover_exprt.cpp new file mode 100644 index 0000000..37b32ac --- /dev/null +++ b/third-party/symfpu/baseTypes/cprover_exprt.cpp @@ -0,0 +1,485 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +#include "symfpu/baseTypes/cprover_exprt.h" + +#include +#include +#include + +#include +#include + +#define THERE_BE_DRAGONS + +#ifdef THERE_BE_DRAGONS +// GCC needs LINKFLAGS="-rdynamic" to give function names in the backtrace +#include +#include +#endif + +namespace symfpu { + namespace cprover_exprt { + + #define BITS 32 + + roundingMode traits::RNE (void) { + return roundingMode(from_integer(0/*ieee_floatt::ROUND_TO_EVEN*/, signedbv_typet(BITS))); + } + + roundingMode traits::RNA (void) { + return roundingMode(from_integer(4, signedbv_typet(BITS))); + } + + roundingMode traits::RTP (void) { + return roundingMode(from_integer(2/*ieee_floatt::ROUND_TO_PLUS_INF*/, signedbv_typet(BITS))); + } + + roundingMode traits::RTN (void) { + return roundingMode(from_integer(1/*ieee_floatt::ROUND_TO_MINUS_INF*/, signedbv_typet(BITS))); + } + + roundingMode traits::RTZ (void) { + return roundingMode(from_integer(3/*ieee_floatt::ROUND_TO_ZERO*/, signedbv_typet(BITS))); + } + +#ifdef THERE_BE_DRAGONS + // The following code is evil and insane + // It exists to add labels in code generated by boolbvt_graph.h + + struct demangledName { + std::string path; + std::string mangledName; + std::string demangledName; + std::string remainder; + }; + +/// Attempts to demangle the function name assuming the glibc +/// format of stack entry: +/// +/// path '(' mangledName '+' offset ') [' address ']\0' +/// +/// \param out: The output stream +/// \param stack_entry: Description of the stack_entry +/// +/// \return True <=> the entry has been successfully demangled and printed. + + static demangledName demangle(const std::string &stack_entry) + { + demangledName return_value = {"Not found", "Not found", "Not found", stack_entry}; + + std::string working(stack_entry); + + std::string::size_type start=working.rfind('('); // Path may contain '(' ! + std::string::size_type end=working.find('+', start); + + return_value.path = working.substr(0, start - 1); + + if(start!=std::string::npos && + end!=std::string::npos && + start+1<=end-1) + { + std::string::size_type length=end-(start+1); + std::string mangled(working.substr(start+1, length)); + return_value.mangledName = mangled; + + int demangle_success=1; + char * demangled = + abi::__cxa_demangle(mangled.c_str(), nullptr, nullptr, &demangle_success); + + if(demangle_success==0) + { + return_value.demangledName = demangled; + } + else + { + return_value.demangledName = "Demangle failed"; + } + } else { + return_value.mangledName = "Mangled name not found"; + return_value.demangledName = "Nothing to demangle"; + } + + return_value.remainder = working.substr(end + 1); + + return return_value; + } + + typedef std::pair creation_context; + + static creation_context find_creation_context (void) { + void * stack[50] = {}; + + std::size_t entries = backtrace(stack, sizeof(stack) / sizeof(void *)); + char **description = backtrace_symbols(stack, entries); + + std::string locationPrefix; + std::string locationPostfix; + + // Start at the right place to avoid the C shim which doesn't decode + #define MAGIC_START 4 + + // Avoid the introspection of this code + #define MAGIC_END 3 + for(std::size_t i=entries - MAGIC_START; i>MAGIC_END; i--) + { + demangledName d = demangle(description[i]); + + if (d.demangledName.find("symfpu::") == 0 && + // !(d.demangledName.find("symfpu::cprover_exprt") == 0) && + d.demangledName.find("symfpu::ite") == std::string::npos && + d.demangledName.find("symfpu::ITE") == std::string::npos && + d.demangledName.find("symfpu::unpackedFloat") != std::string::npos + ) + { + locationPrefix += "subgraph \"cluster_" + d.demangledName + "\" {\n"; + locationPrefix += "label = \"" + d.demangledName + "\"\n"; + locationPostfix += "}\n"; + } + } + free(description); + + return creation_context(locationPrefix, locationPostfix); + } + + static void apply_creation_context_rec (const creation_context &ct, exprt &e) { + e.set("#creation_open", ct.first); + e.set("#creation_close", ct.second); + + // In some cases multiple exprts have been created between tags. + // Naive recursion is bad! + Forall_operands(e_it, e) + { + if (e_it->get_comments().find("#creation_open") == e_it->get_comments().end()) + apply_creation_context_rec(ct, *e_it); + } + return; + } + + static exprt apply_creation_context (const exprt &e) { + creation_context ct = find_creation_context(); + + exprt ei(e); + + if (ct.first.empty()) + return ei; + + apply_creation_context_rec(ct, ei); + + return ei; + } + +#endif + + exprt proposition::tag (const exprt &e) const { + #ifdef THERE_BE_DRAGONS + if (boolbv_grapht::graph_enable) + return apply_creation_context(e); + #endif + return e; + } + + template + exprt bitVector::tag (const exprt &e) const { + #ifdef THERE_BE_DRAGONS + if (boolbv_grapht::graph_enable) + return apply_creation_context(e); + #endif + return e; + } + + // Instantiate + template exprt bitVector::tag (const exprt &e) const; + template exprt bitVector::tag (const exprt &e) const; + + +#define INLINESIMP + + // Inline simplification as simplify_expr does not scale + + + // Just to reduce the visual clutter + exprt simplify_local_constant_fold (const exprt e) { + if (e.id() == ID_constant) { + return e; + + } else { + /* + exprt check_target(e); + + while (check_target.id() == ID_typecast || + check_target.id() == ID_extractbits) + { + check_target = check_target.op0(); + } + + forall_operands(it, check_target) + */ + forall_operands(it, e) + { + if ((*it).id() != ID_constant) + return e; + } + + symbol_tablet s; + namespacet n(s); + return simplify_expr(e, n); + } + } + + + exprt simplify_if (const if_exprt i) { + const exprt cond(i.cond()); + const exprt true_case(i.true_case()); + const exprt false_case(i.false_case()); + + // Start with the simple ones + if (cond.is_true() || (true_case == false_case)) { + return true_case; + + } else if (cond.is_false()) { + return false_case; + + } else { + // Compact if's + if (true_case.id() == ID_if) { + if_exprt l(to_if_expr(true_case)); + + if (l.true_case() == false_case) { + return simplify_if(if_exprt(and_exprt(cond, not_exprt(l.cond())), + l.false_case(), + false_case)); + } else if (l.false_case() == false_case) { + return simplify_if(if_exprt(and_exprt(cond, l.cond()), + l.true_case(), + false_case)); + } + + } else if (false_case.id() == ID_if) { + if_exprt l(to_if_expr(false_case)); + + if (l.true_case() == true_case) { + return simplify_if(if_exprt(and_exprt(not_exprt(cond), not_exprt(l.cond())), + l.false_case(), + true_case)); + } else if (l.false_case() == true_case) { + return simplify_if(if_exprt(and_exprt(not_exprt(cond), l.cond()), + l.true_case(), + true_case)); + } + } + } + + return i; + } + + exprt proposition::simplify (const exprt &e) const { +#ifndef INLINESIMP + return e; +#endif + exprt r(simplify_local_constant_fold(e)); + if (r.id() == ID_constant) + return r; + + if (e.id() == ID_if) { + exprt s(simplify_if(to_if_expr(e))); + + // Additional simplifications for Boolean things + if (s.id() == ID_if) { + if_exprt i(to_if_expr(s)); + + if (i.true_case().is_true()) { + return simplify(or_exprt(i.cond(), i.false_case())); + + } else if (i.true_case().is_false()) { + return simplify(and_exprt(not_exprt(i.cond()), i.false_case())); + + } else if (i.false_case().is_true()) { + return simplify(or_exprt(not_exprt(i.cond()), i.true_case())); + + } else if (i.false_case().is_false()) { + return simplify(and_exprt(i.cond(), i.true_case())); + + } + + assert(!i.cond().is_constant()); + assert(!i.true_case().is_constant()); + assert(!i.false_case().is_constant()); + } + + return s; + + } else if (e.id() == ID_not) { + if (e.op0().id() == ID_not) { + return simplify(e.op0().op0()); + } + + } else if (e.id() == ID_and) { + exprt::operandst operands(e.operands()); + + size_t i = 0; + while (i < operands.size()) { + if (operands[i].is_true()) { + operands.erase(operands.begin() + i); + + } else if (operands[i].is_false()) { + return operands[i]; + + } else if (operands[i].id() == ID_and) { + exprt::operandst appendMe(operands[i].operands()); + for (size_t j = 0; j < appendMe.size(); ++j) { + operands.push_back(appendMe[j]); + } + operands.erase(operands.begin() + i); + + } else if (operands[i].id() == ID_not && + operands[i].op0().id() == ID_or) { + exprt::operandst negateMe(operands[i].op0().operands()); + for (size_t j = 0; j < negateMe.size(); ++j) { + operands.push_back(not_exprt(negateMe[j])); + } + operands.erase(operands.begin() + i); + + } else { + bool duplicate = false; + + for (size_t j = 0; j < i; ++j) { + if (operands[j] == operands[i]) { + duplicate = true; + break; + } + } + + if (duplicate) { + operands.erase(operands.begin() + i); + } else { + ++i; + } + } + } + + if (operands.size() == 0) { + return true_exprt(); + } else if (operands.size() == 1) { + return operands[0]; + } else { + return conjunction(operands); + } + + } else if (e.id() == ID_or) { + exprt::operandst operands(e.operands()); + + size_t i = 0; + while (i < operands.size()) { + if (operands[i].is_false()) { + operands.erase(operands.begin() + i); + + } else if (operands[i].is_true()) { + return operands[i]; + + } else if (operands[i].id() == ID_or) { + exprt::operandst appendMe(operands[i].operands()); + for (size_t j = 0; j < appendMe.size(); ++j) { + operands.push_back(appendMe[j]); + } + operands.erase(operands.begin() + i); + + } else if (operands[i].id() == ID_not && + operands[i].op0().id() == ID_and) { + exprt::operandst negateMe(operands[i].op0().operands()); + for (size_t j = 0; j < negateMe.size(); ++j) { + operands.push_back(not_exprt(negateMe[j])); + } + operands.erase(operands.begin() + i); + + } else { + bool duplicate = false; + + for (size_t j = 0; j < i; ++j) { + if (operands[j] == operands[i]) { + duplicate = true; + break; + } + } + + if (duplicate) { + operands.erase(operands.begin() + i); + } else { + ++i; + } + } + } + + if (operands.size() == 0) { + return false_exprt(); + } else if (operands.size() == 1) { + return operands[0]; + } else { + return disjunction(operands); + } + + } else if (e.id() == ID_equal) { + if (e.op0() == e.op1()) + return true_exprt(); + } + + return e; + } + + template + exprt bitVector::simplify (const exprt &e) const { +#ifndef INLINESIMP + return e; +#endif + + exprt r(simplify_local_constant_fold(e)); + if (r.id() == ID_constant) + return r; + + if (e.id() == ID_if) { + return simplify_if(to_if_expr(e)); + } + + return e; + } + + // Instantiate + template exprt bitVector::simplify (const exprt &e) const; + template exprt bitVector::simplify (const exprt &e) const; + } + + + // Use improved version of some of the operations +#ifndef SYMFPU_WORDLEVEL_ENCODINGS + template <> + cprover_exprt::traits::ubv orderEncode (const cprover_exprt::traits::ubv &b) { + return orderEncodeBitwise(b); + } + + template <> + stickyRightShiftResult stickyRightShift (const cprover_exprt::traits::ubv &input, const cprover_exprt::traits::ubv &shiftAmount) { + return stickyRightShiftBitwise(input, shiftAmount); + } +#endif + + template <> + void probabilityAnnotation (const cprover_exprt::traits::prop &p, const probability &pr) { + boolbv_symfput::probablity_annotations.insert(std::make_pair(p, pr)); + return; + } + +} diff --git a/third-party/symfpu/baseTypes/cprover_exprt.h b/third-party/symfpu/baseTypes/cprover_exprt.h new file mode 100644 index 0000000..899c501 --- /dev/null +++ b/third-party/symfpu/baseTypes/cprover_exprt.h @@ -0,0 +1,433 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** cprover_exprt.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 27/06/17 +** +** Implement bit-vectors by generating CPROVER bit-vectors (bvt) +** +*/ + +// Symfpu headers +#include "../utils/properties.h" +#include "../utils/numberOfRoundingModes.h" +#include "../core/ite.h" +#include "../core/operations.h" + +// CPROVER headers +#include +#include +#include + +// Common components +#include "cprover_common.h" + +#ifndef SYMFPU_CPROVER_EXPRT +#define SYMFPU_CPROVER_EXPRT + +namespace symfpu { + namespace cprover_exprt { + + typedef symfpu::cprover_common::bitWidthType bitWidthType; + typedef symfpu::cprover_common::floatingPointTypeInfo floatingPointTypeInfo; + + // Forward declarations + class roundingMode; + class proposition; + template class bitVector; + + // Wrap up the types into one template parameter + class traits { + public : + typedef bitWidthType bwt; + typedef roundingMode rm; + typedef floatingPointTypeInfo fpt; + typedef proposition prop; + typedef bitVector< true> sbv; + typedef bitVector ubv; + + static roundingMode RNE (void); + static roundingMode RNA (void); + static roundingMode RTP (void); + static roundingMode RTN (void); + static roundingMode RTZ (void); + + // Literal invariants + inline static void precondition (const bool b) { assert(b); return; } + inline static void postcondition (const bool b) { assert(b); return; } + inline static void invariant (const bool b) { assert(b); return; } + + // Symbolic invariants + // TODO : Add to the solver + inline static void precondition(const prop &p) { return; } + inline static void postcondition(const prop &p) { return; } + inline static void invariant(const prop &p) { return; } + + }; + + // To simplify the property macros + typedef traits t; + + + // exprt version using bools + class proposition : public exprt { + protected : + friend ite; // For ITE + + exprt simplify (const exprt &e) const; + exprt tag (const exprt &e) const; + + public : + proposition (const exprt e) : exprt(tag(simplify(e))) {} + proposition (bool v) : exprt(tag(v ? + static_cast(true_exprt()) : + static_cast(false_exprt()) )) {} + proposition (const proposition &old) : exprt(old) {} + + + proposition operator ! (void) const { + return proposition(not_exprt(*this)); + } + + proposition operator && (const proposition &op) const { + return proposition(and_exprt(*this, op)); + } + + proposition operator || (const proposition &op) const { + return proposition(or_exprt(*this, op)); + } + + proposition operator == (const proposition &op) const { + return proposition(equal_exprt(*this, op)); + } + + proposition operator ^ (const proposition &op) const { + return proposition(equal_exprt(*this, not_exprt(op))); + } + }; + + + + class roundingMode : public exprt { + protected: + friend ite; // For ITE + + public : + roundingMode (const exprt &op) : exprt(op) {} + roundingMode (const unsigned v) : exprt(from_integer(v, signedbv_typet(32))) {} + roundingMode (const roundingMode &old) : exprt(old) {} + + proposition valid (void) const { + // TODO : Improve... + return true; + } + + proposition operator == (const roundingMode &op) const { + return proposition(equal_exprt(*this, op)); + } + + }; + + + + template + class bitVector : public exprt { + protected : + friend bitVector; // To allow conversion between the types + friend ite >; // For ITE + + exprt simplify (const exprt &e) const; + exprt tag (const exprt &e) const; + + public : + bitVector (const bitWidthType w, const unsigned v) : + exprt(tag((isSigned) ? from_integer(v, signedbv_typet(w)) : from_integer(v, unsignedbv_typet(w)))) + {} + bitVector (const exprt &e) : exprt(tag(simplify(e))) {} + bitVector (const proposition &p) : exprt(tag((isSigned) ? typecast_exprt(p, signedbv_typet(1)) : typecast_exprt(p, unsignedbv_typet(1)))) {} + bitVector (const bitVector &old) : exprt(old) {} + + bitWidthType getWidth (void) const { + if (isSigned) { + return to_signedbv_type(this->type()).get_width(); + } else { + return to_unsignedbv_type(this->type()).get_width(); + } + } + + + /*** Constant creation and test ***/ + + static bitVector one (const bitWidthType &w) { return bitVector(w,1); } + static bitVector zero (const bitWidthType &w) { return bitVector(w,0); } + static bitVector allOnes (const bitWidthType &w) { return ~zero(w); } + + + inline proposition isAllOnes() const { return (*this) == allOnes(this->getWidth()); } + inline proposition isAllZeros() const { return (*this) == zero(this->getWidth()); } + + static bitVector maxValue (const bitWidthType &w) { + if (isSigned) { + return signedbv_typet(w).largest_expr(); + } else { + return unsignedbv_typet(w).largest_expr(); + } + } + + static bitVector minValue (const bitWidthType &w) { + if (isSigned) { + return signedbv_typet(w).smallest_expr(); + } else { + return unsignedbv_typet(w).smallest_expr(); + } + } + + + /*** Operators ***/ + inline bitVector operator << (const bitVector &op) const { + return bitVector(shl_exprt(*this, op)); + } + + inline bitVector operator >> (const bitVector &op) const { + if (isSigned) { + return bitVector(ashr_exprt(*this, op)); + } else { + return bitVector(lshr_exprt(*this, op)); + } + } + + + inline bitVector operator | (const bitVector &op) const { + return bitVector(bitor_exprt(*this, op)); + } + + inline bitVector operator & (const bitVector &op) const { + return bitVector(bitand_exprt(*this, op)); + } + + inline bitVector operator + (const bitVector &op) const { + return bitVector(plus_exprt(*this, op)); + } + + inline bitVector operator - (const bitVector &op) const { + return bitVector(minus_exprt(*this, op)); + } + + inline bitVector operator * (const bitVector &op) const { + return bitVector(mult_exprt(*this, op)); + } + + inline bitVector operator / (const bitVector &op) const { + return bitVector(div_exprt(*this, op)); + } + + inline bitVector operator % (const bitVector &op) const { + return bitVector(mod_exprt(*this, op)); + } + + + inline bitVector operator - (void) const { + return bitVector(unary_minus_exprt(*this)); + } + + inline bitVector operator ~ (void) const { + return bitVector(bitnot_exprt(*this)); + } + + inline bitVector increment () const { + return bitVector(*this + bitVector::one(getWidth())); + } + + inline bitVector decrement () const { + return bitVector(*this - bitVector::one(getWidth())); + } + + inline bitVector signExtendRightShift (const bitVector &op) const { + return bitVector(ashr_exprt(*this, op)); + } + + + + /*** Modular opertaions ***/ + // No overflow checking so these are the same as other operations + inline bitVector modularLeftShift (const bitVector &op) const { + return *this << op; + } + + inline bitVector modularRightShift (const bitVector &op) const { + return *this >> op; + } + + inline bitVector modularIncrement () const { + return this->increment(); + } + + inline bitVector modularDecrement () const { + return this->decrement(); + } + + inline bitVector modularAdd (const bitVector &op) const { + return *this + op; + } + + inline bitVector modularNegate () const { + return -(*this); + } + + + + + /*** Comparisons ***/ + + inline proposition operator == (const bitVector &op) const { + return proposition(equal_exprt(*this, op)); + } + + inline proposition operator <= (const bitVector &op) const { + return proposition(binary_relation_exprt(*this, ID_le, op)); + } + + inline proposition operator >= (const bitVector &op) const { + return proposition(binary_relation_exprt(*this, ID_ge, op)); + } + + inline proposition operator < (const bitVector &op) const { + return proposition(binary_relation_exprt(*this, ID_lt, op)); + } + + inline proposition operator > (const bitVector &op) const { + return proposition(binary_relation_exprt(*this, ID_gt, op)); + } + + /*** Type conversion ***/ + // CPROVER bvts make no distinction between signed and unsigned, thus ... + bitVector toSigned (void) const { + return bitVector(typecast_exprt(*this, signedbv_typet(getWidth()))); + } + bitVector toUnsigned (void) const { + return bitVector(typecast_exprt(*this, unsignedbv_typet(getWidth()))); + } + + + + /*** Bit hacks ***/ + + inline bitVector extend (bitWidthType extension) const { + if (isSigned) { + return bitVector(typecast_exprt(*this, signedbv_typet(getWidth() + extension))); + } else { + return bitVector(typecast_exprt(*this, unsignedbv_typet(getWidth() + extension))); + } + } + + inline bitVector contract (bitWidthType reduction) const { + if (isSigned) { + return bitVector(typecast_exprt(*this, signedbv_typet(getWidth() - reduction))); + } else { + return bitVector(typecast_exprt(*this, unsignedbv_typet(getWidth() - reduction))); + } + } + + inline bitVector resize (bitWidthType newSize) const { + bitWidthType width = this->getWidth(); + + if (newSize > width) { + return this->extend(newSize - width); + } else if (newSize < width) { + return this->contract(width - newSize); + } else { + return *this; + } + } + + inline bitVector matchWidth (const bitVector &op) const { + PRECONDITION(this->getWidth() <= op.getWidth()); + return this->extend(op.getWidth() - this->getWidth()); + } + + + bitVector append(const bitVector &op) const { + if (isSigned) { + return bitVector(concatenation_exprt(*this, op, signedbv_typet(this->getWidth() + op.getWidth()))); + } else { + return bitVector(concatenation_exprt(*this, op, unsignedbv_typet(this->getWidth() + op.getWidth()))); + } + } + + // Inclusive of end points, thus if the same, extracts just one bit + bitVector extract(bitWidthType upper, bitWidthType lower) const { + PRECONDITION(upper >= lower); + exprt u(bitVector(getWidth(),upper)); + exprt l(bitVector(getWidth(),lower)); + bitWidthType extractedWidth = upper - lower + 1; + + if (isSigned) { + return bitVector(extractbits_exprt(*this, u, l, signedbv_typet(extractedWidth))); + } else { + return bitVector(extractbits_exprt(*this, u, l, unsignedbv_typet(extractedWidth))); + } + } + }; + + }; + + + template <> + struct ite { + static const cprover_exprt::proposition iteOp (const cprover_exprt::proposition &cond, + const cprover_exprt::proposition &l, + const cprover_exprt::proposition &r) { + return cprover_exprt::proposition(if_exprt(cond, l, r)); + } + }; + +#define CPROVERBVTITEDFN(T) template <> \ + struct ite { \ + static const T iteOp (const cprover_exprt::proposition &cond, \ + const T &l, \ + const T &r) { \ + assert(l.type() == r.type()); \ + return T(if_exprt(cond,l,r)); \ + } \ + }; + + CPROVERBVTITEDFN(cprover_exprt::traits::rm); + CPROVERBVTITEDFN(cprover_exprt::traits::sbv); + CPROVERBVTITEDFN(cprover_exprt::traits::ubv); + +#undef CPROVERBVTITEDFN + + // Use improved version of some of the operations + #ifndef SYMFPU_WORDLEVEL_ENCODINGS + template <> + cprover_exprt::traits::ubv orderEncode (const cprover_exprt::traits::ubv &b); + + template <> + stickyRightShiftResult stickyRightShift (const cprover_exprt::traits::ubv &input, const cprover_exprt::traits::ubv &shiftAmount); + #endif + + template <> + void probabilityAnnotation (const cprover_exprt::traits::prop &p, const probability &pr); + + +}; + +#endif diff --git a/third-party/symfpu/baseTypes/cvc4_literal.cpp b/third-party/symfpu/baseTypes/cvc4_literal.cpp new file mode 100644 index 0000000..455fd48 --- /dev/null +++ b/third-party/symfpu/baseTypes/cvc4_literal.cpp @@ -0,0 +1,325 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** cvc4_literal.cpp +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 26/01/15 +** +** Non-templated functions for linking. +** It's best not to ask how this is built... +** +*/ + +#include "base/cvc4_assert.h" + +// cvc4_literal.h needs definition from util/floatingpoint.h and is included in the middle of it +#include "util/floatingpoint.h" +#include "symfpu/baseTypes/cvc4_literal.h" + + +namespace symfpu { + namespace cvc4_literal { + + // To simplify the property macros + typedef traits t; + + + template + bitVector bitVector::one (const bitWidthType &w) { return bitVector(w,1); } + + template + bitVector bitVector::zero (const bitWidthType &w) { return bitVector(w,0); } + + template + bitVector bitVector::allOnes (const bitWidthType &w) { return ~bitVector::zero(w); } + + template + proposition bitVector::isAllOnes() const {return (*this == bitVector::allOnes(this->getWidth()));} + template + proposition bitVector::isAllZeros() const {return (*this == bitVector::zero(this->getWidth()));} + + + template + bitVector bitVector::maxValue (const bitWidthType &w) { + if (isSigned) { + CVC4BV base(w-1, 0U); + return bitVector((~base).zeroExtend(1)); + } else { + return bitVector::allOnes(w); + } + } + + /* + template <> + bitVector bitVector::maxValue (const bitWidthType &w) { + return bitVector::allOnes(w); + } + */ + + template + bitVector bitVector::minValue (const bitWidthType &w) { + if (isSigned) { + CVC4BV base(w, 1U); + CVC4BV shiftAmount(w, w-1); + CVC4BV result(base.leftShift(shiftAmount)); + return bitVector(result); + } else { + return bitVector::zero(w); + } + } + + + + /*** Operators ***/ + template + bitVector bitVector::operator << (const bitVector &op) const { + return this->CVC4BV::leftShift(op); + } + + template <> + bitVector bitVector::operator >> (const bitVector &op) const { + return this->CVC4BV::arithRightShift(op); + } + + template <> + bitVector bitVector::operator >> (const bitVector &op) const { + return this->CVC4BV::logicalRightShift(op); + } + + + + template + bitVector bitVector::operator | (const bitVector &op) const { return this->CVC4BV::operator|(op); } + + template + bitVector bitVector::operator & (const bitVector &op) const { return this->CVC4BV::operator&(op); } + + template + bitVector bitVector::operator + (const bitVector &op) const { return this->CVC4BV::operator+(op); } + + template + bitVector bitVector::operator - (const bitVector &op) const { return this->CVC4BV::operator-(op); } + + template + bitVector bitVector::operator * (const bitVector &op) const { return this->CVC4BV::operator*(op); } + + template <> + bitVector bitVector::operator / (const bitVector &op) const { return this->CVC4BV::unsignedDivTotal(op); } + + template <> + bitVector bitVector::operator % (const bitVector &op) const { return this->CVC4BV::unsignedRemTotal(op); } + + template + bitVector bitVector::operator - (void) const { return this->CVC4BV::operator-(); } + + template + bitVector bitVector::operator ~ (void) const { return this->CVC4BV::operator~(); } + + template + bitVector bitVector::increment () const { + return *this + bitVector::one(this->getWidth()); + } + + template + bitVector bitVector::decrement () const { + return *this - bitVector::one(this->getWidth()); + } + + template + bitVector bitVector::signExtendRightShift (const bitVector &op) const { + return this->CVC4BV::arithRightShift(CVC4BV(this->getWidth(),op)); + } + + + + /*** Modular opertaions ***/ + // No overflow checking so these are the same as other operations + template + bitVector bitVector::modularLeftShift (const bitVector &op) const { + return *this << op; + } + + template + bitVector bitVector::modularRightShift (const bitVector &op) const { + return *this >> op; + } + + template + bitVector bitVector::modularIncrement () const { + return this->increment(); + } + + template + bitVector bitVector::modularDecrement () const { + return this->decrement(); + } + + template + bitVector bitVector::modularAdd (const bitVector &op) const { + return *this + op; + } + + template + bitVector bitVector::modularNegate () const { + return -(*this); + } + + + + + /*** Comparisons ***/ + + template + proposition bitVector::operator == (const bitVector &op) const { return this->CVC4BV::operator==(op); } + + + template <> + proposition bitVector::operator <= (const bitVector &op) const { + return this->signedLessThanEq(op); + } + + template <> + proposition bitVector::operator >= (const bitVector &op) const { + return !(this->signedLessThan(op)); + } + + template <> + proposition bitVector::operator < (const bitVector &op) const { + return this->signedLessThan(op); + } + + template <> + proposition bitVector::operator > (const bitVector &op) const { + return !(this->signedLessThanEq(op)); + } + + + template <> + proposition bitVector::operator <= (const bitVector &op) const { + return this->unsignedLessThanEq(op); + } + + template <> + proposition bitVector::operator >= (const bitVector &op) const { + return !(this->unsignedLessThan(op)); + } + + template <> + proposition bitVector::operator < (const bitVector &op) const { + return this->unsignedLessThan(op); + } + + template <> + proposition bitVector::operator > (const bitVector &op) const { + return !(this->unsignedLessThanEq(op)); + } + + + + /*** Type conversion ***/ + // CVC4 nodes make no distinction between signed and unsigned, thus ... + template + bitVector bitVector::toSigned (void) const { + return bitVector(*this); + } + + template + bitVector bitVector::toUnsigned (void) const { + return bitVector(*this); + } + + + + /*** Bit hacks ***/ + + template + bitVector bitVector::extend (bitWidthType extension) const { + if (isSigned) { + return this->CVC4BV::signExtend(extension); + } else { + return this->CVC4BV::zeroExtend(extension); + } + } + + template + bitVector bitVector::contract (bitWidthType reduction) const { + PRECONDITION(this->getWidth() > reduction); + + return this->extract((this->getWidth() - 1) - reduction, 0); + } + + template + bitVector bitVector::resize (bitWidthType newSize) const { + bitWidthType width = this->getWidth(); + + if (newSize > width) { + return this->extend(newSize - width); + } else if (newSize < width) { + return this->contract(width - newSize); + } else { + return *this; + } + } + + template + bitVector bitVector::matchWidth (const bitVector &op) const { + PRECONDITION(this->getWidth() <= op.getWidth()); + return this->extend(op.getWidth() - this->getWidth()); + } + + + template + bitVector bitVector::append(const bitVector &op) const { + return this->CVC4BV::concat(op); + } + + // Inclusive of end points, thus if the same, extracts just one bit + template + bitVector bitVector::extract(bitWidthType upper, bitWidthType lower) const { + PRECONDITION(upper >= lower); + return this->CVC4BV::extract(upper, lower); + } + + + // Explicit instantiation + template class bitVector; + template class bitVector; + + + + + roundingMode traits::RNE (void) { return ::CVC4::roundNearestTiesToEven; }; + roundingMode traits::RNA (void) { return ::CVC4::roundNearestTiesToAway; }; + roundingMode traits::RTP (void) { return ::CVC4::roundTowardPositive; }; + roundingMode traits::RTN (void) { return ::CVC4::roundTowardNegative; }; + roundingMode traits::RTZ (void) { return ::CVC4::roundTowardZero; }; + + + // This is a literal back-end so props are actually bools + // so these can be handled in the same way as the internal assertions above + + void traits::precondition(const prop &p) { Assert(p); return; } + void traits::postcondition(const prop &p) { Assert(p); return; } + void traits::invariant(const prop &p) { Assert(p); return; } + + }; +}; + + diff --git a/third-party/symfpu/baseTypes/cvc4_literal.h b/third-party/symfpu/baseTypes/cvc4_literal.h new file mode 100644 index 0000000..147f771 --- /dev/null +++ b/third-party/symfpu/baseTypes/cvc4_literal.h @@ -0,0 +1,237 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** cvc4_literal.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 12/06/14 +** +** There are two back-ends for CVC4, one literal and one symbolic. +** This is due to a quirk of the CVC4 infrastructure. Nodes can +** contain literals thus anything that is used to implement a literal +** type cannot contain a node or a massive circular definition +** snarl-up happens. Thus : two back ends. Not all systems will want +** or need this. +** +** This is the literal back-end which uses CVC4 literal datatypes to +** perform arbitrary precision floating-point computations. It is to +** implement the CVC4 literal floating-point type. +** +** It is intended to be included *in the middle* of util/floatingpoint.h +** +*/ + +// Symfpu headers +#include "symfpu/utils/properties.h" +#include "symfpu/utils/numberOfRoundingModes.h" +#include "symfpu/core/ite.h" + +// CVC4 headers + +// Do not include util/floatingpoint.h as we are in the middle of it! +//#include "util/floatingpoint.h" +#include "util/bitvector.h" + + +#ifndef SYMFPU_CVC4_LITERAL +#define SYMFPU_CVC4_LITERAL + +#include + +namespace symfpu { + namespace cvc4_literal { + + typedef unsigned bitWidthType; + typedef bool proposition; + typedef ::CVC4::RoundingMode roundingMode; + typedef ::CVC4::FloatingPointSize floatingPointTypeInfo; + + // Forward declaration + template class bitVector; + + // Wrap up the types into one template parameter + class traits { + public : + typedef bitWidthType bwt; + typedef roundingMode rm; + typedef floatingPointTypeInfo fpt; + typedef proposition prop; + typedef bitVector< true> sbv; + typedef bitVector ubv; + + static roundingMode RNE (void); + static roundingMode RNA (void); + static roundingMode RTP (void); + static roundingMode RTN (void); + static roundingMode RTZ (void); + + static void precondition(const prop &p); + static void postcondition(const prop &p); + static void invariant(const prop &p); + }; + + + + + // Type function + template struct signedToLiteralType; + + template <> struct signedToLiteralType< true> { + typedef int literalType; + }; + template <> struct signedToLiteralType { + typedef unsigned int literalType; + }; + + + + template + class bitVector : public ::CVC4::BitVector { + protected : + typedef typename signedToLiteralType::literalType literalType; + typedef ::CVC4::BitVector CVC4BV; + + friend bitVector; // To allow conversion between the types + friend ite >; // For ITE + + + public : + bitVector (const bitWidthType w, const unsigned v) : CVC4BV(w,v) {} + bitVector (const proposition &p) : CVC4BV(1,p ? 1U : 0U) {} + bitVector (const bitVector &old) : CVC4BV(old) {} + bitVector (const CVC4BV &old) : CVC4BV(old) {} + + + bitWidthType getWidth (void) const { + return getSize(); + } + + + /*** Constant creation and test ***/ + + static bitVector one (const bitWidthType &w); + static bitVector zero (const bitWidthType &w); + static bitVector allOnes (const bitWidthType &w); + + proposition isAllOnes() const; + proposition isAllZeros() const; + + static bitVector maxValue (const bitWidthType &w); + static bitVector minValue (const bitWidthType &w); + + + /*** Operators ***/ + bitVector operator << (const bitVector &op) const; + bitVector operator >> (const bitVector &op) const; + + + /* Inherited but ... + * *sigh* if we use the inherited version then it will return a + * CVC4::BitVector which can be converted back to a + * bitVector but isn't done automatically when working + * out types for templates instantiation. ITE is a particular + * problem as expressions and constants no longer derive the + * same type. There aren't any good solutions in C++, we could + * use CRTP but Liana wouldn't appreciate that, so the following + * pointless wrapping functions are needed. + */ + + bitVector operator | (const bitVector &op) const; + bitVector operator & (const bitVector &op) const; + bitVector operator + (const bitVector &op) const; + bitVector operator - (const bitVector &op) const; + bitVector operator * (const bitVector &op) const; + bitVector operator / (const bitVector &op) const; + bitVector operator % (const bitVector &op) const; + bitVector operator - (void) const; + bitVector operator ~ (void) const; + + + bitVector increment () const; + bitVector decrement () const; + bitVector signExtendRightShift (const bitVector &op) const; + + + /*** Modular opertaions ***/ + // No overflow checking so these are the same as other operations + bitVector modularLeftShift (const bitVector &op) const; + bitVector modularRightShift (const bitVector &op) const; + bitVector modularIncrement () const; + bitVector modularDecrement () const; + bitVector modularAdd (const bitVector &op) const; + bitVector modularNegate () const; + + + + /*** Comparisons ***/ + + /* Inherited ... ish ... */ + proposition operator == (const bitVector &op) const; + proposition operator <= (const bitVector &op) const; + proposition operator >= (const bitVector &op) const; + proposition operator < (const bitVector &op) const; + proposition operator > (const bitVector &op) const; + + + /*** Type conversion ***/ + // CVC4 nodes make no distinction between signed and unsigned, thus ... + bitVector toSigned (void) const; + bitVector toUnsigned (void) const; + + + /*** Bit hacks ***/ + + bitVector extend (bitWidthType extension) const; + bitVector contract (bitWidthType reduction) const; + bitVector resize (bitWidthType newSize) const; + bitVector matchWidth (const bitVector &op) const; + bitVector append(const bitVector &op) const; + + // Inclusive of end points, thus if the same, extracts just one bit + bitVector extract(bitWidthType upper, bitWidthType lower) const; + + }; + }; + +#define CVC4LITITEDFN(T) template <> \ + struct ite { \ + static const T & iteOp (const cvc4_literal::proposition &cond, \ + const T &l, \ + const T &r) { \ + if (cond) { \ + return l; \ + } else { \ + return r; \ + } \ + } \ + } + + CVC4LITITEDFN(cvc4_literal::traits::rm); + CVC4LITITEDFN(cvc4_literal::traits::prop); + CVC4LITITEDFN(cvc4_literal::traits::sbv); + CVC4LITITEDFN(cvc4_literal::traits::ubv); + +#undef CVC4LITITEDFN + +}; + +#endif + + + diff --git a/third-party/symfpu/baseTypes/cvc4_symbolic.cpp b/third-party/symfpu/baseTypes/cvc4_symbolic.cpp new file mode 100644 index 0000000..b0e033b --- /dev/null +++ b/third-party/symfpu/baseTypes/cvc4_symbolic.cpp @@ -0,0 +1,89 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** cvc4_symbolic.cpp +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 05/01/15 +** +** Non-templated functions for linking. +** It's best not to ask how this is built... +** +*/ + +#include "symfpu/baseTypes/cvc4_symbolic.h" + +// CVC4 headers +#include "theory/fp/fp_converter.h" + +namespace symfpu { + namespace cvc4_symbolic { + + roundingMode traits::RNE (void) { return roundingMode(0x01); }; + roundingMode traits::RNA (void) { return roundingMode(0x02); }; + roundingMode traits::RTP (void) { return roundingMode(0x04); }; + roundingMode traits::RTN (void) { return roundingMode(0x08); }; + roundingMode traits::RTZ (void) { return roundingMode(0x10); }; + + + template <> + bitVector bitVector::maxValue (const bitWidthType &w) { + bitVector leadingZero(bitVector::zero(1)); + bitVector base(bitVector::allOnes(w-1)); + + return bitVector(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_CONCAT, leadingZero.node, base.node)); + } + + template <> + bitVector bitVector::maxValue (const bitWidthType &w) { + return bitVector::allOnes(w); + } + + template <> + bitVector bitVector::minValue (const bitWidthType &w) { + bitVector leadingOne(bitVector::one(1)); + bitVector base(bitVector::zero(w-1)); + + return bitVector(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_CONCAT, leadingOne.node, base.node)); + } + + template <> + bitVector bitVector::minValue (const bitWidthType &w) { + return bitVector::zero(w); + } + + }; + + template <> + cvc4_symbolic::traits::ubv orderEncode (const cvc4_symbolic::traits::ubv &b) { + return orderEncodeBitwise(b); + } + + template <> + stickyRightShiftResult stickyRightShift (const cvc4_symbolic::traits::ubv &input, const cvc4_symbolic::traits::ubv &shiftAmount) { + return stickyRightShiftBitwise(input, shiftAmount); + } + + template <> + void probabilityAnnotation (const cvc4_symbolic::traits::prop &p, const probability &pr) { + ::CVC4::theory::fp::FpConverter::currentConverter->registerProbabilityAnnotation(p.getNode(), pr); + return; + } + +}; diff --git a/third-party/symfpu/baseTypes/cvc4_symbolic.h b/third-party/symfpu/baseTypes/cvc4_symbolic.h new file mode 100644 index 0000000..61507b1 --- /dev/null +++ b/third-party/symfpu/baseTypes/cvc4_symbolic.h @@ -0,0 +1,701 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** cvc4_symbolic.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 03/06/14 +** +** A back-end for symfpu that builds CVC4 nodes rather than executing the +** code directly. This allows the symfpu code to be used to generate +** encodings of floating-point operations. +** +*/ + +#include + +// Symfpu headers +#include "symfpu/utils/properties.h" +#include "symfpu/utils/numberOfRoundingModes.h" +#include "symfpu/core/ite.h" + +//#include "util/floatingpoint.h" +//#include "symfpu/baseTypes/cvc4_literal.h" + + +// CVC4 headers +#include "base/cvc4_assert.h" +#include "expr/node.h" +#include "expr/type.h" +#include "expr/node_builder.h" +#include "util/bitvector.h" + +#ifdef SYMBOLIC_EVAL +// This allows debugging of the CVC4 symbolic back-end. +// By enabling this and disabling constant folding in the rewriter, +// SMT files that have operations on constants will be evaluated +// during the encoding step, which means that the expressions +// generated by the symbolic back-end can be debugged with gdb. +#include "theory/rewriter.h" +#endif + +#ifndef SYMFPU_CVC4_SYMBOLIC +#define SYMFPU_CVC4_SYMBOLIC + + +namespace symfpu { + namespace cvc4_symbolic { + + + typedef unsigned bitWidthType; + + // Forward declarations + class roundingMode; + class floatingPointTypeInfo; + class proposition; + template class bitVector; + + // Wrap up the types into one template parameter + class traits { + public : + typedef bitWidthType bwt; + typedef roundingMode rm; + typedef floatingPointTypeInfo fpt; + typedef proposition prop; + typedef bitVector< true> sbv; + typedef bitVector ubv; + + static roundingMode RNE (void); + static roundingMode RNA (void); + static roundingMode RTP (void); + static roundingMode RTN (void); + static roundingMode RTZ (void); + + inline static void precondition (const bool b) { Assert(b); return; } + inline static void postcondition (const bool b) { Assert(b); return; } + inline static void invariant (const bool b) { Assert(b); return; } + + // TODO : These need to check a flag for the use of redundant constraints + // and then make their way into additionalAssertions. + + inline static void precondition(const prop &p) { return; } + inline static void postcondition(const prop &p) { return; } + inline static void invariant(const prop &p) { return; } + + }; + + // To simplify the property macros + typedef traits t; + + + + + typedef ::CVC4::Node Node; + typedef ::CVC4::TNode TNode; + + class nodeWrapper { + protected : + // TODO : move to inheriting from Node rather than including it + Node node; + +/* SYMBOLIC_EVAL is for debugging CVC4 symbolic back-end issues. + * Enable this and disabling constant folding will mean that operations + * that are input with constant args are 'folded' using the symbolic encoding + * allowing them to be traced via GDB. + */ +#ifdef SYMBOLIC_EVAL + nodeWrapper (const Node n) : node(::CVC4::theory::Rewriter::rewrite(n)) {} + nodeWrapper (const nodeWrapper &old) : node(::CVC4::theory::Rewriter::rewrite(old.node)) {} +#else + nodeWrapper (const Node n) : node(n) {} + nodeWrapper (const nodeWrapper &old) : node(old.node) {} +#endif + + public : + const Node getNode (void) const { + return this->node; + } + + Node getNode (void) { + return this->node; + } + + }; + + +#if SYMFPUPROPISBOOL + // Bool version + class proposition : public nodeWrapper { + protected : + bool checkNodeType (const TNode node) { + ::CVC4::TypeNode tn = node.getType(false); + return tn.isBoolean(); + } + + friend ite; // For ITE + + public : + proposition (const Node n) : nodeWrapper(n) { PRECONDITION(checkNodeType(node)); } // Only used within this header so could be friend'd + proposition (bool v) : nodeWrapper(::CVC4::NodeManager::currentNM()->mkConst(v)) { PRECONDITION(checkNodeType(node)); } + proposition (const proposition &old) : nodeWrapper(old) { PRECONDITION(checkNodeType(node)); } + + proposition operator ! (void) const { + return proposition(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::NOT, this->node)); + } + + proposition operator && (const proposition &op) const { + return proposition(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::AND, this->node, op.node)); + } + + proposition operator || (const proposition &op) const { + return proposition(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::OR, this->node, op.node)); + } + + proposition operator == (const proposition &op) const { + return proposition(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::IFF, this->node, op.node)); + } + + proposition operator ^ (const proposition &op) const { + return proposition(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::XOR, this->node, op.node)); + } + + }; +#else + + // (_ BitVec 1) version + class proposition : public nodeWrapper { + protected : + bool checkNodeType (const TNode node) { + ::CVC4::TypeNode tn = node.getType(false); + return tn.isBitVector() && tn.getBitVectorSize() == 1; + } + + friend ite; // For ITE + + public : + proposition (const Node n) : nodeWrapper(n) { PRECONDITION(checkNodeType(node)); } // Only used within this header so could be friend'd + proposition (bool v) : nodeWrapper(::CVC4::NodeManager::currentNM()->mkConst(::CVC4::BitVector(1U, (v?1U:0U)))) { PRECONDITION(checkNodeType(node)); } + proposition (const proposition &old) : nodeWrapper(old) { PRECONDITION(checkNodeType(node)); } + + proposition operator ! (void) const { + return proposition(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_NOT, this->node)); + } + + proposition operator && (const proposition &op) const { + return proposition(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_AND, this->node, op.node)); + } + + proposition operator || (const proposition &op) const { + return proposition(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_OR, this->node, op.node)); + } + + proposition operator == (const proposition &op) const { + return proposition(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_COMP, this->node, op.node)); + } + + proposition operator ^ (const proposition &op) const { + return proposition(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_XOR, this->node, op.node)); + } + + }; +#endif + + + + class roundingMode : public nodeWrapper { + protected : + bool checkNodeType (const TNode n) { + ::CVC4::TypeNode tn = n.getType(false); + + return tn.isBitVector(SYMFPU_NUMBER_OF_ROUNDING_MODES); + } + + // TODO : make this private again + public : + roundingMode (const Node n) : nodeWrapper(n) { PRECONDITION(checkNodeType(node)); } + + friend ite; // For ITE + + public : + roundingMode (const unsigned v) : nodeWrapper(::CVC4::NodeManager::currentNM()->mkConst(::CVC4::BitVector(SYMFPU_NUMBER_OF_ROUNDING_MODES, v))) { + PRECONDITION((v & v-1) == 0 && v != 0); // Exactly one bit set + PRECONDITION(checkNodeType(node)); + } + roundingMode (const roundingMode &old) : nodeWrapper(old) { PRECONDITION(checkNodeType(node)); } + + proposition valid (void) const { + ::CVC4::NodeManager* nm = ::CVC4::NodeManager::currentNM(); + Node zero(nm->mkConst(::CVC4::BitVector(SYMFPU_NUMBER_OF_ROUNDING_MODES, (long unsigned int)0))); + + // Is there a better encoding of this? + #ifdef SYMFPUPROPISBOOL + return proposition(nm->mkNode(::CVC4::kind::AND, + nm->mkNode(::CVC4::kind::EQUAL, + nm->mkNode(::CVC4::kind::BITVECTOR_AND, + this->node, + nm->mkNode(::CVC4::kind::BITVECTOR_SUB, + this->node, + nm->mkConst(::CVC4::BitVector(SYMFPU_NUMBER_OF_ROUNDING_MODES, (long unsigned int)1)))), + zero), + nm->mkNode(::CVC4::kind::NOT, + nm->mkNode(::CVC4::kind::EQUAL, + this->node, + zero)))); + #else + return proposition(nm->mkNode(::CVC4::kind::BITVECTOR_AND, + nm->mkNode(::CVC4::kind::BITVECTOR_COMP, + nm->mkNode(::CVC4::kind::BITVECTOR_AND, + this->node, + nm->mkNode(::CVC4::kind::BITVECTOR_SUB, + this->node, + nm->mkConst(::CVC4::BitVector(SYMFPU_NUMBER_OF_ROUNDING_MODES, (long unsigned int)1)))), + zero), + nm->mkNode(::CVC4::kind::BITVECTOR_NOT, + nm->mkNode(::CVC4::kind::BITVECTOR_COMP, + this->node, + zero)))); + #endif + } + + proposition operator == (const roundingMode &op) const { + #ifdef SYMFPUPROPISBOOL + return proposition(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::EQUAL, this->node, op.node)); + #else + return proposition(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_COMP, this->node, op.node)); + #endif + } + + + }; + + + + // Type function + template struct signedToLiteralType; + + template <> struct signedToLiteralType< true> { + typedef int literalType; + }; + template <> struct signedToLiteralType { + typedef unsigned int literalType; + }; + + + + + template + class bitVector : public nodeWrapper { + protected : + typedef typename signedToLiteralType::literalType literalType; + + inline Node boolNodeToBV(Node node) const { + Assert(node.getType().isBoolean()); + ::CVC4::NodeManager *nm = ::CVC4::NodeManager::currentNM(); + return nm->mkNode(::CVC4::kind::ITE, + node, + nm->mkConst(::CVC4::BitVector(1U, 1U)), + nm->mkConst(::CVC4::BitVector(1U, 0U))); + } + + inline Node BVToBoolNode(Node node) const { + Assert(node.getType().isBitVector()); + Assert(node.getType().getBitVectorSize() == 1); + ::CVC4::NodeManager *nm = ::CVC4::NodeManager::currentNM(); + return nm->mkNode(::CVC4::kind::EQUAL, + node, + nm->mkConst(::CVC4::BitVector(1U, 1U))); + } + + inline Node fromProposition (Node node) const { + #ifdef PROPSYMFPUISBOOL + return boolNodeToBV(node); + #else + return node; + #endif + } + + inline Node toProposition (Node node) const { + #ifdef PROPSYMFPUISBOOL + return node; + #else + return boolNodeToBV(node); + #endif + } + + + + // TODO : make this private again + public : + + bitVector (const Node n) : nodeWrapper(n) { PRECONDITION(checkNodeType(node)); } + + bool checkNodeType (const TNode n) { + ::CVC4::TypeNode tn = n.getType(false); + return tn.isBitVector(); + } + + + friend bitVector; // To allow conversion between the types + friend ite >; // For ITE + + + public : + bitVector (const bitWidthType w, const unsigned v) : nodeWrapper(::CVC4::NodeManager::currentNM()->mkConst(::CVC4::BitVector(w, v))) { PRECONDITION(checkNodeType(node)); } + bitVector (const proposition &p) : nodeWrapper(fromProposition(p.getNode())) {} + bitVector (const bitVector &old) : nodeWrapper(old) { PRECONDITION(checkNodeType(node)); } + bitVector (const ::CVC4::BitVector &old) : nodeWrapper(::CVC4::NodeManager::currentNM()->mkConst(old)) { PRECONDITION(checkNodeType(node)); } + + bitWidthType getWidth (void) const { + return this->node.getType(false).getBitVectorSize(); + } + + + /*** Constant creation and test ***/ + + static bitVector one (const bitWidthType &w) { return bitVector(w,1); } + static bitVector zero (const bitWidthType &w) { return bitVector(w,0); } + static bitVector allOnes (const bitWidthType &w) { return bitVector( ~zero(w) ); } + + inline proposition isAllOnes() const {return (*this == bitVector::allOnes(this->getWidth()));} + inline proposition isAllZeros() const {return (*this == bitVector::zero(this->getWidth()));} + + static bitVector maxValue (const bitWidthType &w); + static bitVector minValue (const bitWidthType &w); + + + /*** Operators ***/ + inline bitVector operator << (const bitVector &op) const { + return bitVector(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_SHL, this->node, op.node)); + } + + inline bitVector operator >> (const bitVector &op) const { + return bitVector(::CVC4::NodeManager::currentNM()->mkNode((isSigned) ? ::CVC4::kind::BITVECTOR_ASHR : ::CVC4::kind::BITVECTOR_LSHR, this->node, op.node)); + } + + + inline bitVector operator | (const bitVector &op) const { + return bitVector(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_OR, this->node, op.node)); + } + + inline bitVector operator & (const bitVector &op) const { + return bitVector(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_AND, this->node, op.node)); + } + + inline bitVector operator + (const bitVector &op) const { + return bitVector(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_PLUS, this->node, op.node)); + } + + inline bitVector operator - (const bitVector &op) const { + return bitVector(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_SUB, this->node, op.node)); + } + + inline bitVector operator * (const bitVector &op) const { + return bitVector(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_MULT, this->node, op.node)); + } + + inline bitVector operator / (const bitVector &op) const { + return bitVector(::CVC4::NodeManager::currentNM()->mkNode((isSigned) ? ::CVC4::kind::BITVECTOR_SDIV : ::CVC4::kind::BITVECTOR_UDIV_TOTAL, this->node, op.node)); + } + + inline bitVector operator % (const bitVector &op) const { + return bitVector(::CVC4::NodeManager::currentNM()->mkNode((isSigned) ? ::CVC4::kind::BITVECTOR_SREM : ::CVC4::kind::BITVECTOR_UREM_TOTAL, this->node, op.node)); + } + + inline bitVector operator - (void) const { + return bitVector(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_NEG, this->node)); + } + + inline bitVector operator ~ (void) const { + return bitVector(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_NOT, this->node)); + } + + inline bitVector increment () const { + return bitVector(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_PLUS, this->node, one(this->getWidth()).node)); + } + + inline bitVector decrement () const { + return bitVector(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_SUB, this->node, one(this->getWidth()).node)); + } + + inline bitVector signExtendRightShift (const bitVector &op) const { + return bitVector(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_ASHR, this->node, op.node)); + } + + + + /*** Modular opertaions ***/ + // No overflow checking so these are the same as other operations + inline bitVector modularLeftShift (const bitVector &op) const { + return *this << op; + } + + inline bitVector modularRightShift (const bitVector &op) const { + return *this >> op; + } + + inline bitVector modularIncrement () const { + return this->increment(); + } + + inline bitVector modularDecrement () const { + return this->decrement(); + } + + inline bitVector modularAdd (const bitVector &op) const { + return *this + op; + } + + inline bitVector modularNegate () const { + return -(*this); + } + + + + + /*** Comparisons ***/ + + inline proposition operator == (const bitVector &op) const { +#ifdef PROPSYMFPUISBOOL + return proposition(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::EQUAL, this->node, op.node)); +#else + return proposition(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_COMP, this->node, op.node)); +#endif + } + + public : + + inline proposition operator <= (const bitVector &op) const { + // TODO add kind::BITVECTOR_SLEBV and BITVECTOR_ULEBV + return (*this < op) || (*this == op); + } + + inline proposition operator >= (const bitVector &op) const { + return (*this > op) || (*this == op); + } + + inline proposition operator < (const bitVector &op) const { + return proposition(::CVC4::NodeManager::currentNM()->mkNode((isSigned) ? ::CVC4::kind::BITVECTOR_SLTBV : ::CVC4::kind::BITVECTOR_ULTBV, this->node, op.node)); + } + + inline proposition operator > (const bitVector &op) const { + return proposition(::CVC4::NodeManager::currentNM()->mkNode((isSigned) ? ::CVC4::kind::BITVECTOR_SLTBV : ::CVC4::kind::BITVECTOR_ULTBV, op.node, this->node)); + } + + /*** Type conversion ***/ + // CVC4 nodes make no distinction between signed and unsigned, thus ... + bitVector toSigned (void) const { + return bitVector(this->node); + } + bitVector toUnsigned (void) const { + return bitVector(this->node); + } + + + + /*** Bit hacks ***/ + + inline bitVector extend (bitWidthType extension) const; + + inline bitVector contract (bitWidthType reduction) const { + PRECONDITION(this->getWidth() > reduction); + + ::CVC4::NodeBuilder<> construct(::CVC4::kind::BITVECTOR_EXTRACT); + construct << ::CVC4::NodeManager::currentNM()->mkConst< ::CVC4::BitVectorExtract>(::CVC4::BitVectorExtract((this->getWidth() - 1) - reduction, 0)) + << this->node; + + return bitVector(construct); + } + + inline bitVector resize (bitWidthType newSize) const { + bitWidthType width = this->getWidth(); + + if (newSize > width) { + return this->extend(newSize - width); + } else if (newSize < width) { + return this->contract(width - newSize); + } else { + return *this; + } + } + + inline bitVector matchWidth (const bitVector &op) const { + PRECONDITION(this->getWidth() <= op.getWidth()); + return this->extend(op.getWidth() - this->getWidth()); + } + + + bitVector append(const bitVector &op) const { + return bitVector(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_CONCAT, this->node, op.node)); + } + + // Inclusive of end points, thus if the same, extracts just one bit + bitVector extract(bitWidthType upper, bitWidthType lower) const { + PRECONDITION(upper >= lower); + + ::CVC4::NodeBuilder<> construct(::CVC4::kind::BITVECTOR_EXTRACT); + construct << ::CVC4::NodeManager::currentNM()->mkConst< ::CVC4::BitVectorExtract>(::CVC4::BitVectorExtract(upper, lower)) + << this->node; + + return bitVector(construct); + } + + + }; + + + template <> + inline bitVector bitVector::extend(bitWidthType extension) const { + ::CVC4::NodeBuilder<> construct(::CVC4::kind::BITVECTOR_SIGN_EXTEND); + construct << ::CVC4::NodeManager::currentNM()->mkConst< ::CVC4::BitVectorSignExtend>(::CVC4::BitVectorSignExtend(extension)) + << this->node; + + return bitVector(construct); + } + + template <> + inline bitVector bitVector::extend(bitWidthType extension) const { + ::CVC4::NodeBuilder<> construct(::CVC4::kind::BITVECTOR_ZERO_EXTEND); + construct << ::CVC4::NodeManager::currentNM()->mkConst< ::CVC4::BitVectorZeroExtend>(::CVC4::BitVectorZeroExtend(extension)) + << this->node; + + return bitVector(construct); + } + + + class floatingPointTypeInfo { + protected : + // If is easier to keep it wrapped as then you can make things of this type more easily + const ::CVC4::TypeNode type; + + friend ite; // For ITE + + public : + floatingPointTypeInfo(const ::CVC4::TypeNode t) : type(t) { + PRECONDITION(t.isFloatingPoint()); + } + floatingPointTypeInfo(unsigned exp, unsigned sig) : type(::CVC4::NodeManager::currentNM()->mkFloatingPointType(exp,sig)) {} + floatingPointTypeInfo(const floatingPointTypeInfo &old) : type(old.type) {} + + bitWidthType exponentWidth(void) const { return this->type.getFloatingPointExponentSize(); } + bitWidthType significandWidth(void) const { return this->type.getFloatingPointSignificandSize(); } + + bitWidthType packedWidth(void) const { return this->exponentWidth() + this->significandWidth(); } + bitWidthType packedExponentWidth(void) const { return this->exponentWidth(); } + bitWidthType packedSignificandWidth(void) const { return this->significandWidth() - 1; } + + ::CVC4::TypeNode getTypeNode (void) const { return type; } + }; + + + }; + + +#ifdef SYMFPUPROPISBOOL +#define CVC4SYMITEDFN(T) template <> \ + struct ite { \ + static const T iteOp (const cvc4_symbolic::proposition &cond, \ + const T &l, \ + const T &r) { \ + return T(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::ITE, cond.getNode(), l.getNode(), r.getNode())); \ + } \ + } + +#else +#define CVC4SYMITEDFN(T) template <> \ + struct ite { \ + static const T iteOp (const cvc4_symbolic::proposition &_cond, \ + const T &_l, \ + const T &_r) { \ + ::CVC4::NodeManager* nm = ::CVC4::NodeManager::currentNM(); \ + \ + ::CVC4::Node cond = _cond.getNode(); \ + ::CVC4::Node l = _l.getNode(); \ + ::CVC4::Node r = _r.getNode(); \ + \ + /* Handle some common symfpu idioms */ \ + if (cond.isConst()) { \ + if (cond == nm->mkConst(::CVC4::BitVector(1U, 1U))) { \ + return l; \ + } else { \ + return r; \ + } \ + } else { \ + if (l.getKind() == ::CVC4::kind::BITVECTOR_ITE) { \ + if (l[1] == r) { \ + return nm->mkNode(::CVC4::kind::BITVECTOR_ITE, \ + nm->mkNode(::CVC4::kind::BITVECTOR_AND, \ + cond, \ + nm->mkNode(::CVC4::kind::BITVECTOR_NOT, l[0])), \ + l[2], \ + r); \ + } else if (l[2] == r) { \ + return nm->mkNode(::CVC4::kind::BITVECTOR_ITE, \ + nm->mkNode(::CVC4::kind::BITVECTOR_AND, \ + cond, \ + l[0]), \ + l[1], \ + r); \ + } \ + \ + } else if (r.getKind() == ::CVC4::kind::BITVECTOR_ITE) { \ + if (r[1] == l) { \ + return nm->mkNode(::CVC4::kind::BITVECTOR_ITE, \ + nm->mkNode(::CVC4::kind::BITVECTOR_AND, \ + nm->mkNode(::CVC4::kind::BITVECTOR_NOT, cond), \ + nm->mkNode(::CVC4::kind::BITVECTOR_NOT, r[0])), \ + r[2], \ + l); \ + } else if (r[2] == l) { \ + return nm->mkNode(::CVC4::kind::BITVECTOR_ITE, \ + nm->mkNode(::CVC4::kind::BITVECTOR_AND, \ + nm->mkNode(::CVC4::kind::BITVECTOR_NOT, cond), \ + r[0]), \ + r[1], \ + l); \ + } \ + \ + } \ + } \ + return T(::CVC4::NodeManager::currentNM()->mkNode(::CVC4::kind::BITVECTOR_ITE, cond, l, r)); \ + } \ + } + +#endif + + // Can (unsurprisingly) only ITE things which contain Nodes + CVC4SYMITEDFN(cvc4_symbolic::traits::rm); + CVC4SYMITEDFN(cvc4_symbolic::traits::prop); + CVC4SYMITEDFN(cvc4_symbolic::traits::sbv); + CVC4SYMITEDFN(cvc4_symbolic::traits::ubv); + +#undef CVC4SYMITEDFN + + template <> + cvc4_symbolic::traits::ubv orderEncode (const cvc4_symbolic::traits::ubv &b); + + template <> + stickyRightShiftResult stickyRightShift (const cvc4_symbolic::traits::ubv &input, const cvc4_symbolic::traits::ubv &shiftAmount); + + template <> + void probabilityAnnotation (const cvc4_symbolic::traits::prop &p, const probability &pr); + + +}; + +#endif diff --git a/third-party/symfpu/baseTypes/shared.h b/third-party/symfpu/baseTypes/shared.h new file mode 100644 index 0000000..1f816eb --- /dev/null +++ b/third-party/symfpu/baseTypes/shared.h @@ -0,0 +1,82 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** shared.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 11/04/17 +** +** Things that are used by multiple back-ends. +** +*/ + +#include +#include + +#ifndef SYMFPU_SHARED +#define SYMFPU_SHARED + +namespace symfpu { + namespace shared { + + + // Must be able to contain the number of bit used in the bit-vector type to avoid overflow + typedef uint64_t bitWidthType; + + // We can use bools for propositions + typedef bool executable_proposition; + + // In SMT-LIB style -- significand includes hidden bit + class floatingPointTypeInfo { + private : + bitWidthType exponentBits; + bitWidthType significandBits; + + public : + floatingPointTypeInfo (bitWidthType eb, bitWidthType sb) : exponentBits(eb), significandBits(sb) { + assert(eb > 1); // Not precondition as we don't have a traits class to use + assert(sb > 1); + } + + floatingPointTypeInfo (const floatingPointTypeInfo &old) : + exponentBits(old.exponentBits), significandBits(old.significandBits) {} + + floatingPointTypeInfo & operator= (const floatingPointTypeInfo &old) { + this->exponentBits = old.exponentBits; + this->significandBits = old.significandBits; + + return *this; + } + + bitWidthType exponentWidth(void) const { return this->exponentBits; } + bitWidthType significandWidth(void) const { return this->significandBits; } + + + bitWidthType packedWidth(void) const { return this->exponentBits + this->significandBits; } + bitWidthType packedExponentWidth(void) const { return this->exponentBits; } + bitWidthType packedSignificandWidth(void) const { return this->significandBits - 1; } + + + }; + + + } +} + +#endif diff --git a/third-party/symfpu/baseTypes/simpleExecutable.cpp b/third-party/symfpu/baseTypes/simpleExecutable.cpp new file mode 100644 index 0000000..a024364 --- /dev/null +++ b/third-party/symfpu/baseTypes/simpleExecutable.cpp @@ -0,0 +1,252 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** simpleExecutable.cpp +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 07/08/14 +** +** The most simple executable implementation of bit-vectors. +** Limited in the ranges it supports but fast and suitable for reasoning. +** +*/ + + +#include "symfpu/baseTypes/simpleExecutable.h" + +#include +#include +#include + +namespace symfpu { + namespace simpleExecutable { + + + // This would all be much easier if C++ allowed partial specialisation of member templates... + + template <> + bool bitVector::isRepresentable (const bitWidthType w, const int64_t v) { + uint64_t shiftSafe = *((uint64_t *)(&v)); + uint64_t top = (shiftSafe >> w); + uint64_t signbit = shiftSafe & 0x8000000000000000; + int64_t stop = *((int64_t *)(&top)); + return (signbit) ? (stop == bitVector::nOnes(bitVector::maxWidth() - w)) : (stop == 0LL); + } + + template <> + bool bitVector::isRepresentable (const bitWidthType w, const uint64_t v) { + uint64_t top = (v >> w); + return (top == 0); + } + + + template <> + uint64_t bitVector::makeRepresentable (const bitWidthType w, const uint64_t v) { + return v & bitVector::nOnes(w); + } + + template <> + int64_t bitVector::makeRepresentable (const bitWidthType w, const int64_t v) { + if (v <= ((1LL << (w - 1)) - 1) && (-(1LL << (w - 1)) <= v)) { + return v; + } else { + return 0; + } + } + + + template <> + bitVector bitVector::maxValue (const bitWidthType &w) { + PRECONDITION(w != 1); + return bitVector(w, (1ULL << (w - 1)) - 1); + } + + template <> + bitVector bitVector::maxValue (const bitWidthType &w) { + PRECONDITION(w != 1); + return bitVector(w, (1ULL << w) - 1); + } + + template <> + bitVector bitVector::minValue (const bitWidthType &w) { + PRECONDITION(w != 1); + return bitVector(w, -(1ULL << (w - 1))); + } + + template <> + bitVector bitVector::minValue (const bitWidthType &w) { + return bitVector(w, 0); + } + + + template <> + bitVector bitVector::operator- (void) const { + return bitVector(this->width, -this->value); + } + + // Used in addition + template <> + bitVector bitVector::operator- (void) const { + return bitVector(this->width, + bitVector::makeRepresentable(this->width, (~this->value) + 1)); + } + + template <> + bitVector bitVector::operator~ (void) const { + return bitVector(this->width, + bitVector::makeRepresentable(this->width, ~this->value)); + } + + + // This is wrong in the signed case as the sign bit it tracks and the sign bit in int64_t are in different places! + static uint64_t stickyRightShift(const bool value, const bitWidthType width, const uint64_t left, const uint64_t right) { + //uint64_t bitsInWord = bitVector::maxWidth(); + uint64_t newValue = left; + uint64_t stickyBit = 0; + uint64_t signBit = left & (1ULL << (width - 1)); + + if (right <= width) { + for (uint64_t i = 1; i <= width; i <<= 1) { + if (right & i) { + uint64_t iOnes = ((1ULL << i) - 1); + stickyBit |= ((newValue & iOnes) ? 1 : 0); + + // Sign extending shift + if (signBit) { + newValue = (newValue >> i) | (iOnes << (width - i)); + } else { + newValue = (newValue >> i); + } + + } + } + } else { + newValue = (signBit) ? 0xFFFFFFFFFFFFFFFFULL : 0x0; + stickyBit = (left) ? 0x1 : 0x0; + } + + return (value) ? newValue : stickyBit; + } + + + + template <> + bitVector bitVector::signExtendRightShift (const bitVector &op) const { + PRECONDITION(this->width == op.width); + return bitVector(this->width, + bitVector::makeRepresentable(this->width, + stickyRightShift(true, this->width, this->value, op.value))); + } + + template <> + bitVector bitVector::signExtendRightShift (const bitVector &op) const { + PRECONDITION(this->width == op.width); + PRECONDITION(this->width < CHAR_BIT*sizeof(int64_t)); + + int64_t newValue; + + if (this->value < 0) { + newValue = -(-(this->value) >> op.value) + ((this->value & 0x1) ? -1 : 0); // Rounds away + } else { + newValue = this->value >> op.value; + } + + return bitVector(this->width, + bitVector::makeRepresentable(this->width, newValue)); + } + + template<> + bitVector bitVector::modularLeftShift (const bitVector &op) const { + PRECONDITION(this->width == op.width); + return bitVector(this->width, + bitVector::makeRepresentable(this->width, + (op.value >= this->width) ? 0ULL : this->value << op.value)); + } + + template<> + bitVector bitVector::modularRightShift (const bitVector &op) const { + PRECONDITION(this->width == op.width); + return bitVector(this->width, + bitVector::makeRepresentable(this->width, + (op.value >= this->width) ? 0ULL : this->value >> op.value)); + } + + + template <> + bitVector bitVector::modularNegate (void) const { + return bitVector(this->width, + bitVector::makeRepresentable(this->width, ~this->value + 1)); + } + + template <> + bitVector bitVector::modularNegate (void) const { + return bitVector(this->width, + bitVector::makeRepresentable(this->width, -this->value)); + } + + + // Only instantiated for unsigned + template <> + bitVector bitVector::extract(bitWidthType upper, bitWidthType lower) const { + PRECONDITION(this->width > upper); + PRECONDITION(upper >= lower); + + bitWidthType newLength = (upper - lower) + 1; + + return bitVector(newLength, + bitVector::makeRepresentable(newLength, (this->value >> lower))); + } + + template <> + bitVector bitVector::append(const bitVector &op) const { + PRECONDITION(this->width + op.width <= bitVector::maxWidth()); + + return bitVector(this->width + op.width, this->value << op.width | op.value); + } + + + + template <> + bitVector::signedVersion> bitVector::toSigned (void) const { + return bitVector(this->width, *((int64_t *)&this->value)); + } + + template <> + bitVector::unsignedVersion> bitVector::toUnsigned (void) const { + // Note we need to mask out the (sign extensions) of the negative part. + return bitVector(this->width, (*((uint64_t *)&this->value)) & bitVector::nOnes(this->width)); + } + + + roundingMode traits::RNE (void) { return roundingMode(FE_TONEAREST); } + roundingMode traits::RNA (void) { return roundingMode(23); } // Could be better... + roundingMode traits::RTP (void) { return roundingMode(FE_UPWARD); } + roundingMode traits::RTN (void) { return roundingMode(FE_DOWNWARD); } + roundingMode traits::RTZ (void) { return roundingMode(FE_TOWARDZERO); } + + } + + #if 0 + template <> + simpleExecutable::traits::ubv orderEncode (const simpleExecutable::traits::ubv &b) { + return orderEncodeBitwise(b); + } + #endif + +} diff --git a/third-party/symfpu/baseTypes/simpleExecutable.h b/third-party/symfpu/baseTypes/simpleExecutable.h new file mode 100644 index 0000000..2881af1 --- /dev/null +++ b/third-party/symfpu/baseTypes/simpleExecutable.h @@ -0,0 +1,423 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** simpleExecutable.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 03/06/14 +** +** The most simple executable implementation of bit-vectors. +** Limited in the ranges it supports but fast and suitable for reasoning. +** +** Unless otherwise stated, bit operations require all operands to have the +** same widths and the result will have the same width (SMT-LIB style, +** but see the 'expanding' instructions below). Also underflow and +** overflow are considered errors (unlike SMT-LIB but see the 'modular' instructions +** below) although error checking is not perfect as overflows in the +** underlying data type can mask errors. +** +*/ + +#include "symfpu/utils/properties.h" +#include "symfpu/core/ite.h" +#include "symfpu/baseTypes/shared.h" + +#include +#include +#include + +#ifndef SYMFPU_SIMPLE_EXECUTABLE +#define SYMFPU_SIMPLE_EXECUTABLE + +namespace symfpu { + namespace simpleExecutable { + + typedef symfpu::shared::bitWidthType bitWidthType; + typedef symfpu::shared::executable_proposition proposition; + typedef symfpu::shared::floatingPointTypeInfo floatingPointTypeInfo; + + // Forwards definitions + class roundingMode; + template class bitVector; + + + // This is the class that is used as a template argument + class traits { + public : + typedef bitWidthType bwt; + typedef roundingMode rm; + typedef floatingPointTypeInfo fpt; + typedef proposition prop; + typedef bitVector< int64_t> sbv; + typedef bitVector ubv; + + static roundingMode RNE(void); + static roundingMode RNA(void); + static roundingMode RTP(void); + static roundingMode RTN(void); + static roundingMode RTZ(void); + + // As prop == bool only one set of these is needed + inline static void precondition(const bool b) { assert(b); return; } + inline static void postcondition(const bool b) { assert(b); return; } + inline static void invariant(const bool b) { assert(b); return; } + + }; + + // To simplify the property macros + typedef traits t; + + + + class roundingMode { + private : + int value; + + public : + roundingMode (int v) : value(v) {} + roundingMode (const roundingMode &old) : value(old.value) {} + + roundingMode & operator = (const roundingMode &op) { + this->value = op.value; + return (*this); + } + + proposition operator == (const roundingMode &op) const { + return proposition(this->value == op.value); + } + + // Only for executable back-ends + int getValue (void) const { + return this->value; + } + }; + + + + template struct modifySignedness; + + template <> struct modifySignedness< int64_t> { + typedef uint64_t unsignedVersion; + typedef int64_t signedVersion; + }; + template <> struct modifySignedness { + typedef uint64_t unsignedVersion; + typedef int64_t signedVersion; + }; + + + + template + class bitVector { + protected : + bitWidthType width; + T value; + + static bitWidthType maxWidth (void) { + return sizeof(T)*CHAR_BIT; + } + + static T nOnes (bitWidthType n) { + if (n == 0) { + return 0; + } else { + // Not (1 << n) - 1 to avoid overflow for n = maxWidth() + bitWidthType shift = bitVector::maxWidth() - n; + return ((~0ULL) << shift) >> shift; + } + } + + // Bit vectors should store values in 2's complement using the full width + // (and thus may have significant bits outside the width). + // Thus need to make sure the value stored is representable within + // bit-vectors of the specified width. + static bool isRepresentable (const bitWidthType w, const T v); + + // Modular operations need to reduce operations back to + // something representable. + static T makeRepresentable (const bitWidthType w, const T v); + + + public : + + // Ideally should protect but is used in subnormal rounding + bitVector (const bitWidthType w, const T v) : width(w), value(v) + { + PRECONDITION(width <= bitVector::maxWidth()); + PRECONDITION(0 < width); + PRECONDITION(bitVector::isRepresentable(w,v)); + } + + bitVector (const proposition &p) : width(1), value(p) {} + + bitVector (const bitVector &old) : width(old.width), value(old.value) {} + + // Constructors + // non-det on other instances but not this so that + // instantiation catches this + + + + + bitWidthType getWidth (void) const { + return this->width; + } + + // Would it be better to not have this and only have copy? + bitVector & operator= (const bitVector &op) { + PRECONDITION(op.width == this->width); + + this->value = op.value; + + return (*this); + } + + + /*** Constant creation and test ***/ + + static bitVector one (const bitWidthType &w) { return bitVector(w,1); } + static bitVector zero (const bitWidthType &w) { return bitVector(w,0); } + static bitVector allOnes (const bitWidthType &w) { return bitVector(w,bitVector::nOnes(w)); } + + inline proposition isAllOnes() const {return proposition(((~this->value) & nOnes(this->width)) == 0);} + inline proposition isAllZeros() const {return proposition(this->value == 0);} + + static bitVector maxValue (const bitWidthType &w); + static bitVector minValue (const bitWidthType &w); + + /*** Operators ***/ + // Need to inline the operations where possible + inline bitVector operator << (const bitVector &op) const { + PRECONDITION(this->width == op.width); + PRECONDITION(op.value >= 0U && op.value < (T)this->width); + return bitVector(this->width, this->value << op.value); + } + + inline bitVector operator >> (const bitVector &op) const { + PRECONDITION(this->width == op.width); + PRECONDITION(op.value >= 0U && op.value < (T)this->width); + return bitVector(this->width, this->value >> op.value); + } + + inline bitVector operator | (const bitVector &op) const { + PRECONDITION(this->width == op.width); + return bitVector(this->width, this->value | op.value); + } + + inline bitVector operator & (const bitVector &op) const { + PRECONDITION(this->width == op.width); + return bitVector(this->width, this->value & op.value); + } + + inline bitVector operator + (const bitVector &op) const { + PRECONDITION(this->width == op.width); + return bitVector(this->width, this->value + op.value); + } + + inline bitVector operator - (const bitVector &op) const { + PRECONDITION(this->width == op.width); + return bitVector(this->width, this->value - op.value); + } + + inline bitVector operator * (const bitVector &op) const { + PRECONDITION(this->width == op.width); + return bitVector(this->width, this->value * op.value); + } + + inline bitVector operator / (const bitVector &op) const { + PRECONDITION(op.value != 0); + PRECONDITION(this->width == op.width); + return bitVector(this->width, this->value / op.value); + } + + inline bitVector operator % (const bitVector &op) const { + PRECONDITION(op.value != 0); + PRECONDITION(this->width == op.width); + return bitVector(this->width, this->value % op.value); + } + + bitVector operator - (void) const; + bitVector operator ~ (void) const; + + inline bitVector increment () const { + return bitVector(this->width, this->value + 1); + } + + inline bitVector decrement () const { + return bitVector(this->width, this->value - 1); + } + + bitVector signExtendRightShift (const bitVector &op) const; + + + /*** Modular operations ***/ + bitVector modularLeftShift (const bitVector &op) const; + bitVector modularRightShift (const bitVector &op) const; + + inline bitVector modularIncrement () const { + return bitVector(this->width, + bitVector::makeRepresentable(this->width, this->value + 1)); + } + + inline bitVector modularDecrement () const { + return bitVector(this->width, + bitVector::makeRepresentable(this->width, this->value - 1)); + } + + inline bitVector modularAdd (const bitVector &op) const { + return bitVector(this->width, + bitVector::makeRepresentable(this->width, + this->value + op.value)); + } + + bitVector modularNegate () const; + + + + + /*** Comparisons ***/ + + inline proposition operator == (const bitVector &op) const { + PRECONDITION(this->width == op.width); + return proposition(this->value == op.value); + } + + inline proposition operator <= (const bitVector &op) const { + PRECONDITION(this->width == op.width); + return proposition(this->value <= op.value); + } + + inline proposition operator >= (const bitVector &op) const { + PRECONDITION(this->width == op.width); + return proposition(this->value >= op.value); + } + + inline proposition operator < (const bitVector &op) const { + PRECONDITION(this->width == op.width); + return proposition(this->value < op.value); + } + + inline proposition operator > (const bitVector &op) const { + PRECONDITION(this->width == op.width); + return proposition(this->value > op.value); + } + + + /*** Type conversion ***/ + + bitVector::signedVersion> toSigned (void) const; + bitVector::unsignedVersion> toUnsigned (void) const; + + + + /*** Bit hacks ***/ + + inline bitVector extend (bitWidthType extension) const { + PRECONDITION(this->width + extension <= bitVector::maxWidth()); + + // No extension needed, even in the signed case as already correctly represented + return bitVector(this->width + extension, this->value); + } + + inline bitVector contract (bitWidthType reduction) const { + PRECONDITION(this->width > reduction); + + return bitVector(this->width - reduction, this->value); + } + + inline bitVector resize (bitWidthType newSize) const { + return bitVector(newSize, + bitVector::makeRepresentable(newSize, this->value)); + } + + inline bitVector matchWidth (const bitVector &op) const { + PRECONDITION(this->width <= op.width); + return this->extend(op.width - this->width); + } + + + + bitVector append(const bitVector &op) const; + + // Inclusive of end points, thus if the same, extracts just one bit + bitVector extract(bitWidthType upper, bitWidthType lower) const; + + // Only meaningful for executable implementations + T contents (void) const { return this->value; } + + }; + + } + + +#define SEITEDFN(T) template <> \ + struct ite { \ + static const T & iteOp (const simpleExecutable::traits::prop &cond, \ + const T &l, \ + const T &r) { \ + if (cond) { \ + return l; \ + } else { \ + return r; \ + } \ + } \ + } + + SEITEDFN(simpleExecutable::traits::rm); + SEITEDFN(simpleExecutable::traits::prop); + +#undef SEITEDFN + +#define SEITEDFNW(T) template <> \ + struct ite { \ + static const T & iteOp (const simpleExecutable::traits::prop &cond, \ + const T &l, \ + const T &r) { \ + assert(l.getWidth() == r.getWidth()); \ + \ + if (cond) { \ + return l; \ + } else { \ + return r; \ + } \ + } \ + } + + SEITEDFNW(simpleExecutable::traits::sbv); + SEITEDFNW(simpleExecutable::traits::ubv); + +#undef SEITEDFNW + +} + + +// For testing only; bitwise implementation is way slower for software +#if 0 +#include "../core/operations.h" + +namespace symfpu { + + template <> + simpleExecutable::traits::ubv orderEncode (const simpleExecutable::traits::ubv &b); + +} +#endif + + +#endif diff --git a/third-party/symfpu/core/Makefile b/third-party/symfpu/core/Makefile new file mode 100644 index 0000000..c51384b --- /dev/null +++ b/third-party/symfpu/core/Makefile @@ -0,0 +1,10 @@ +include ../flags +CXXFLAGS+=-I../ +ALL= +.PHONY : all + +all : $(ALL) + +%.o : %.cpp + $(CXX) $(CXXFLAGS) -c $^ -o $@ + diff --git a/third-party/symfpu/core/add.h b/third-party/symfpu/core/add.h new file mode 100644 index 0000000..c880e7c --- /dev/null +++ b/third-party/symfpu/core/add.h @@ -0,0 +1,775 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** add.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 01/09/14 +** +** Addition of arbitrary precision floats +** +** The current design is based on a two-path adder but it may be useful to use +** more paths. There are five cases that are of interest: +** 1. effective add / very far +** -> set the sticky bit only +** 2. effective add / far or near +** -> align and add, realign down if needed +** 3. effective sub / very far +** -> decrement, re-normalise and set sticky bits or (dependent on rounding-mode, skip entirely) +** 4. effective sub / far +** -> align and subtract, realign up if needed +** 5. effective sub / near +** -> align, subtract and normalise up +** +*/ + + +/* +** Ideas +** Optimisation : Collar the exponent difference, convert add to twice the width and thus unify the paths and simplify the shifting. +** Enable the absolute max underapproximation +*/ + + +#include "symfpu/core/unpackedFloat.h" +#include "symfpu/core/ite.h" +#include "symfpu/core/rounder.h" +#include "symfpu/core/sign.h" +#include "symfpu/core/operations.h" + + +#ifndef SYMFPU_ADD +#define SYMFPU_ADD + +namespace symfpu { + + // There are a number of variants on how this should be done. + // This is the implementation that handles all of them. + // Below are restricted versions for particular special cases. +template + unpackedFloat addAdditionSpecialCasesComplete (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &left, + const unpackedFloat &leftID, + const unpackedFloat &right, + const typename t::prop &returnLeft, + const typename t::prop &returnRight, + const unpackedFloat &additionResult, + const typename t::prop &isAdd) { + + typedef typename t::prop prop; + + // NaN + prop eitherArgumentNan(left.getNaN() || right.getNaN()); + prop bothInfinity(left.getInf() && right.getInf()); + prop signsMatch(left.getSign() == right.getSign()); + //prop compatableSigns(ITE(isAdd, signsMatch, !signsMatch)); + prop compatableSigns(isAdd ^ !signsMatch); + + prop generatesNaN(eitherArgumentNan || (bothInfinity && !compatableSigns)); + + + // Inf + prop generatesInf((bothInfinity && compatableSigns) || + ( left.getInf() && !right.getInf()) || + (!left.getInf() && right.getInf())); + + prop signOfInf(ITE(left.getInf(), left.getSign(), prop(isAdd ^ !right.getSign()))); + + + // Zero + prop bothZero(left.getZero() && right.getZero()); + prop flipRightSign(!isAdd ^ right.getSign()); + prop signOfZero(ITE((roundingMode == t::RTN()), + left.getSign() || flipRightSign, + left.getSign() && flipRightSign)); + + prop idLeft(!left.getZero() && right.getZero()); + prop idRight( left.getZero() && !right.getZero()); + + // At most one of idLeft, idRight, generatesNaN, generatesInf and bothZero is true. + // If used in addition additionResult is guaranteed to not be NaN. + + // Subtle trick : as the input to this will have been rounded it will have + // an ITE with the default values "on top", thus doing the special cases + // first (inner) rather than last (outer) allows them to be compacted better + return ITE(idRight || returnRight, + ITE(isAdd, + right, + negate(format, right)), + ITE(idLeft || returnLeft, + leftID, + ITE(generatesNaN, + unpackedFloat::makeNaN(format), + ITE(generatesInf, + unpackedFloat::makeInf(format, signOfInf), + ITE(bothZero, + unpackedFloat::makeZero(format, signOfZero), + additionResult))))); + } + + + // leftID is the value returned in the idLeft case (i.e. when left is not a + // special number and right is zero). This is needed by FMA as the flags + // for left and leftID are computed differently and need to be handled differently. +template + unpackedFloat addAdditionSpecialCasesWithID (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &left, + const unpackedFloat &leftID, + const unpackedFloat &right, + const unpackedFloat &additionResult, + const typename t::prop &isAdd) { + return addAdditionSpecialCasesComplete(format, roundingMode, left, leftID, + right, typename t::prop(false), typename t::prop(false), + additionResult, isAdd); + } + + + // This is the usual case; use this one! + template + unpackedFloat addAdditionSpecialCases (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &left, + const unpackedFloat &right, + const unpackedFloat &additionResult, + const typename t::prop &isAdd) { + return addAdditionSpecialCasesComplete(format, roundingMode, left, left, + right, typename t::prop(false), typename t::prop(false), + additionResult, isAdd); + } + + + // As above but allows the (very) far path to be accelerated + template + unpackedFloat addAdditionSpecialCasesWithBypass (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &left, + const unpackedFloat &right, + const typename t::prop &returnLeft, + const typename t::prop &returnRight, + const unpackedFloat &additionResult, + const typename t::prop &isAdd) { + return addAdditionSpecialCasesComplete(format, roundingMode, left, left, + right, returnLeft, returnRight, + additionResult, isAdd); + } + + + + /* Computes the normal / subnormal case only. + * This allows multiple versions of the first phase to be used and + * the first phase to be used for other things (e.g. FMA). + */ + +template +struct exponentCompareInfo { + typedef typename t::sbv sbv; + typedef typename t::prop prop; + + prop leftIsMax; + sbv maxExponent; + sbv absoluteExponentDifference; + prop diffIsZero; + prop diffIsOne; + prop diffIsGreaterThanPrecision; + prop diffIsTwoToPrecision; + prop diffIsGreaterThanPrecisionPlusOne; + + exponentCompareInfo(const prop &lil, const sbv &me, const sbv &aed, + const prop &diz, const prop &dio, const prop &digtp, const prop &dittp, const prop &disgtppo) : + leftIsMax(lil), maxExponent(me), absoluteExponentDifference(aed), + diffIsZero(diz), diffIsOne(dio), diffIsGreaterThanPrecision(digtp), diffIsTwoToPrecision(dittp), diffIsGreaterThanPrecisionPlusOne(disgtppo) {} + + exponentCompareInfo(const exponentCompareInfo &old) : + leftIsMax(old.leftIsMax), maxExponent(old.maxExponent), absoluteExponentDifference(old.absoluteExponentDifference), + diffIsZero(old.diffIsZero), diffIsOne(old.diffIsOne), + diffIsGreaterThanPrecision(old.diffIsGreaterThanPrecision), + diffIsTwoToPrecision(old.diffIsTwoToPrecision), + diffIsGreaterThanPrecisionPlusOne(old.diffIsGreaterThanPrecisionPlusOne) {} +}; + +template + exponentCompareInfo addExponentCompare(const typename t::bwt exponentWidth, + const typename t::bwt significandWidth, + const typename t::sbv &leftExponent, + const typename t::sbv &rightExponent, + const typename t::prop &knownInCorrectOrder) { + PRECONDITION( leftExponent.getWidth() + 1 == exponentWidth); + PRECONDITION(rightExponent.getWidth() + 1 == exponentWidth); + + typedef typename t::prop prop; + typedef typename t::sbv sbv; + +#if 0 + // The obvious implementation + + // Compute exponent distance + sbv maxExponent(max(leftExponent.extend(1), rightExponent.extend(1))); + sbv minExponent(min(leftExponent.extend(1), rightExponent.extend(1))); + sbv absoluteExponentDifference(maxExponent - minExponent); + + prop leftIsMax(knownInCorrectOrder || leftExponent.extend(1) == maxExponent); +#else + + // A better implementation(?) + sbv exponentDifference(leftExponent.extend(1) - rightExponent.extend(1)); + + prop signBit(exponentDifference.toUnsigned().extract(exponentWidth - 1, exponentWidth - 1).isAllOnes()); + prop leftIsMax(knownInCorrectOrder || !signBit); + + sbv maxExponent(ITE(leftIsMax, leftExponent.extend(1), rightExponent.extend(1))); + sbv absoluteExponentDifference(ITE(leftIsMax, exponentDifference, exponentDifference.modularNegate())); // Largest negative value not obtainable so negate is safe +#endif + + INVARIANT(sbv::zero(exponentWidth) <= absoluteExponentDifference); + + // Optimisation : compact these comparisons at the bit-level + prop diffIsZero(absoluteExponentDifference == sbv::zero(exponentWidth)); + prop diffIsOne(absoluteExponentDifference == sbv::one(exponentWidth)); + prop diffIsGreaterThanPrecision(sbv(exponentWidth, significandWidth) < absoluteExponentDifference); // Assumes this is representable + prop diffIsTwoToPrecision(!diffIsZero && !diffIsOne && !diffIsGreaterThanPrecision); + prop diffIsGreaterThanPrecisionPlusOne(sbv(exponentWidth, significandWidth + 1) < absoluteExponentDifference); + + probabilityAnnotation(diffIsZero, UNLIKELY); + probabilityAnnotation(diffIsOne, UNLIKELY); + probabilityAnnotation(diffIsGreaterThanPrecision, LIKELY); // In proving if not execution + probabilityAnnotation(diffIsGreaterThanPrecisionPlusOne, LIKELY); // In proving if not execution + + + return exponentCompareInfo(leftIsMax, + maxExponent, absoluteExponentDifference, + diffIsZero, diffIsOne, diffIsGreaterThanPrecision, diffIsTwoToPrecision, diffIsGreaterThanPrecisionPlusOne); + } + + + +// Note that the arithmetic part of add needs the rounding mode. +// This is an oddity due to the way that the sign of zero is generated. + + template + struct floatWithCustomRounderInfo { + unpackedFloat uf; + customRounderInfo known; + + floatWithCustomRounderInfo(const unpackedFloat &_uf, const customRounderInfo &_known) : uf(_uf), known(_known) {} + floatWithCustomRounderInfo(const floatWithCustomRounderInfo &old) : uf(old.uf), known(old.known) {} + }; + + template + floatWithCustomRounderInfo arithmeticAdd (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &left, + const unpackedFloat &right, + const typename t::prop &isAdd, + const typename t::prop &knownInCorrectOrder, + const exponentCompareInfo &ec) { + + typedef typename t::bwt bwt; + typedef typename t::fpt fpt; + typedef typename t::prop prop; + typedef typename t::ubv ubv; + typedef typename t::sbv sbv; + + PRECONDITION(left.valid(format)); + PRECONDITION(right.valid(format)); + + // Work out if an effective subtraction + prop effectiveAdd((left.getSign() ^ right.getSign()) ^ isAdd); + + bwt exponentWidth(left.getExponent().getWidth() + 1); + bwt significandWidth(left.getSignificand().getWidth()); + + /* Exponent difference and effective add implies a large amount about the output exponent and flags + ** R denotes that this is possible via rounding up and incrementing the exponent + ** + ** Case A. max(l,r) + 1, B. max(l,r) C. max(l,r) - 1 D. max(l,r) - k E. zero + ** Eff. Add Y Y + ** diff = 0 Y, sticky 0 + ** diff = 1 Y, sticky 0, R Y, sticky 0 + ** diff : [2,p] decreasing prob., R Y + ** diff > p R Y + ** + ** Eff. Sub Y Y Y, exact Y, exact + ** diff = 0 Y, exact prob. drop with k low prob. + ** diff = 1 Y, sticky 0 Y, exact prob. drop with k + ** diff : [2,p] Y, R decreasing prob. + ** diff > p Y, R low prob. + ** + */ + // Optimisation : add 'bypass' invariants that link the final exponent to the input using this. + + + // Rounder flags + prop noOverflow(!effectiveAdd); + prop noUnderflow(true); + //prop exact(); // Need to see if it cancels, see below + prop subnormalExact(true); + prop noSignificandOverflow((effectiveAdd && ec.diffIsZero) || + (!effectiveAdd && (ec.diffIsZero || ec.diffIsOne))); + + prop stickyBitIsZero(ec.diffIsZero || ec.diffIsOne); + + + // Work out ordering + prop leftLarger(knownInCorrectOrder || + (ec.leftIsMax && + ITE(!ec.diffIsZero, + prop(true), + left.getSignificand() >= right.getSignificand()))); + // Optimisation : can we avoid this comparison completely and allow the result to be negative? + // This may be hard as a compare is cheaper than a negate after, particularly as there has to be an ITE here + + // Extend the significands to give room for carry plus guard and sticky bits + ubv lsig((ITE(leftLarger, left.getSignificand(), right.getSignificand())).extend(1).append(ubv::zero(2))); + ubv ssig((ITE(leftLarger, right.getSignificand(), left.getSignificand())).extend(1).append(ubv::zero(2))); + + prop resultSign(ITE(leftLarger, + left.getSign(), + prop(!isAdd ^ right.getSign()))); + + // Extended so no info lost, negate before shift so that sign-extension works + ubv negatedSmaller(conditionalNegate(!effectiveAdd, ssig)); + + ubv shiftAmount(ec.absoluteExponentDifference.toUnsigned() // Safe as >= 0 + .resize(negatedSmaller.getWidth())); // Safe as long as the significand has more bits than the exponent + INVARIANT(exponentWidth <= significandWidth); + + + // Shift the smaller significand + stickyRightShiftResult shifted(stickyRightShift(negatedSmaller, shiftAmount)); + + ubv negatedAlignedSmaller(ITE(ec.diffIsGreaterThanPrecisionPlusOne, // Fast path the common case, +1 to avoid issues with the guard bit + ITE(effectiveAdd, + ubv::zero(negatedSmaller.getWidth()), + ~ubv::zero(negatedSmaller.getWidth())), + shifted.signExtendedResult)); + ubv shiftedStickyBit(ITE(ec.diffIsGreaterThanPrecision, + ubv::one(negatedSmaller.getWidth()), + shifted.stickyBit)); // Have to separate otherwise align up may convert it to the guard bit + + + // Sum and re-align + ubv sum(lsig.modularAdd(negatedAlignedSmaller)); + + bwt sumWidth(sum.getWidth()); + ubv topBit(sum.extract(sumWidth - 1, sumWidth - 1)); + ubv alignedBit(sum.extract(sumWidth - 2, sumWidth - 2)); + ubv lowerBit(sum.extract(sumWidth - 3, sumWidth - 3)); + + + prop overflow(!(topBit.isAllZeros())); + prop cancel(topBit.isAllZeros() && alignedBit.isAllZeros()); + prop minorCancel(cancel && lowerBit.isAllOnes()); + prop majorCancel(cancel && lowerBit.isAllZeros()); + prop fullCancel(majorCancel && sum.isAllZeros()); + + probabilityAnnotation(overflow, UNLIKELY); + probabilityAnnotation(cancel, UNLIKELY); + probabilityAnnotation(minorCancel, UNLIKELY); + probabilityAnnotation(majorCancel, VERYUNLIKELY); + probabilityAnnotation(fullCancel, VERYUNLIKELY); + + INVARIANT(IMPLIES(effectiveAdd && ec.diffIsZero, overflow)); + INVARIANT(IMPLIES(overflow, effectiveAdd && (!ec.diffIsGreaterThanPrecision))); // That case can only overflow by rounding + INVARIANT(IMPLIES(cancel, !effectiveAdd)); + INVARIANT(IMPLIES(majorCancel, ec.diffIsZero || ec.diffIsOne)); + + probabilityAnnotation(overflow && ec.diffIsTwoToPrecision, UNLIKELY); + probabilityAnnotation(cancel && ec.diffIsTwoToPrecision, UNLIKELY); + probabilityAnnotation(cancel && ec.diffIsGreaterThanPrecision, VERYUNLIKELY); + + prop exact(cancel && (ec.diffIsZero || ec.diffIsOne)); // For completeness + + ubv alignedSum(conditionalLeftShiftOne(minorCancel, + conditionalRightShiftOne(overflow, sum))); + + sbv exponentCorrectionTerm(ITE(minorCancel, + -sbv::one(exponentWidth), + ITE(overflow, + sbv::one(exponentWidth), + sbv::zero(exponentWidth)))); + + sbv correctedExponent(ec.maxExponent + exponentCorrectionTerm); // Safe due to extension + + // Watch closely... + ubv stickyBit(ITE(stickyBitIsZero || majorCancel, + ubv::zero(alignedSum.getWidth()), + (shiftedStickyBit | ITE(!overflow, ubv::zero(1), sum.extract(0,0)).extend(alignedSum.getWidth() - 1)))); + + + // Put it back together + unpackedFloat sumResult(resultSign, correctedExponent, (alignedSum | stickyBit).contract(1)); + + // We return something in an extended format + // *. One extra exponent bit to deal with the 'overflow' case + // *. Two extra significand bits for the guard and sticky bits + fpt extendedFormat(format.exponentWidth() + 1, format.significandWidth() + 2); + + // Deal with the major cancellation case + // It would be nice to use normaliseUpDetectZero but the sign + // of the zero depends on the rounding mode. + unpackedFloat additionResult(ITE(fullCancel, + unpackedFloat::makeZero(extendedFormat, roundingMode == t::RTN()), + ITE(majorCancel, + sumResult.normaliseUp(extendedFormat), + sumResult))); + + // Some thought is required here to convince yourself that + // there will be no subnormal values that violate this. + // See 'all subnormals generated by addition are exact' + // and the extended exponent. + POSTCONDITION(additionResult.valid(extendedFormat)); + + return floatWithCustomRounderInfo(additionResult, customRounderInfo(noOverflow, noUnderflow, exact, subnormalExact, noSignificandOverflow)); + } + + template + unpackedFloat dualPathArithmeticAdd (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &left, + const unpackedFloat &right, + const typename t::prop &isAdd) { + + typedef typename t::bwt bwt; + typedef typename t::fpt fpt; + typedef typename t::prop prop; + typedef typename t::ubv ubv; + typedef typename t::sbv sbv; + + PRECONDITION(left.valid(format)); + PRECONDITION(right.valid(format)); + + // We return something in an extended format + // *. One extra exponent bit to deal with the 'overflow' case + // *. Two extra significand bits for the guard and sticky bits + fpt extendedFormat(format.exponentWidth() + 1, format.significandWidth() + 2); + + + // Compute exponent difference and swap the two arguments if needed + sbv initialExponentDifference(expandingSubtract(left.getExponent(), right.getExponent())); + bwt edWidth(initialExponentDifference.getWidth()); + sbv edWidthZero(sbv::zero(edWidth)); + prop orderingCorrect( initialExponentDifference > edWidthZero || + (initialExponentDifference == edWidthZero && + left.getSignificand() >= right.getSignificand())); + + unpackedFloat larger(ITE(orderingCorrect, left, right)); + unpackedFloat smaller(ITE(orderingCorrect, right, left)); + sbv exponentDifference(ITE(orderingCorrect, + initialExponentDifference, + -initialExponentDifference)); + + prop resultSign(ITE(orderingCorrect, + left.getSign(), + prop(!isAdd ^ right.getSign()))); + + + // Work out if an effective subtraction + prop effectiveAdd(larger.getSign() ^ smaller.getSign() ^ isAdd); + + + // Extend the significands to give room for carry plus guard and sticky bits + ubv lsig( larger.getSignificand().extend(1).append(ubv::zero(2))); + ubv ssig(smaller.getSignificand().extend(1).append(ubv::zero(2))); + + + // This is a two-path adder, so determine which of the two paths to use + // The near path is only needed for things that can cancel more than one bit + prop farPath(exponentDifference > sbv::one(edWidth) || effectiveAdd); + + + // Far path : Align + ubv negatedSmaller(ITE(effectiveAdd, ssig, ssig.modularNegate())); // Extended so no info lost + // Negate before shift so that sign-extension works + + sbv significandWidth(edWidth, lsig.getWidth()); + prop noOverlap(exponentDifference > significandWidth); + + ubv shiftAmount(exponentDifference.toUnsigned() // Safe as >= 0 + .resize(ssig.getWidth())); // This looses information but the case in which it does is handles by noOverlap + + + ubv negatedAlignedSmaller(negatedSmaller.signExtendRightShift(shiftAmount)); + ubv shiftedStickyBit(rightShiftStickyBit(negatedSmaller, shiftAmount)); // Have to separate otherwise align up may convert it to the guard bit + + // Far path : Sum and re-align + ubv sum(lsig.modularAdd(negatedAlignedSmaller)); + + bwt sumWidth(sum.getWidth()); + ubv topBit(sum.extract(sumWidth - 1, sumWidth - 1)); + ubv centerBit(sum.extract(sumWidth - 2, sumWidth - 2)); + + prop noOverflow(topBit.isAllZeros()); // Only correct if effectiveAdd is set + prop noCancel(centerBit.isAllOnes()); + + + + // TODO : Add invariants + + ubv alignedSum(ITE(effectiveAdd, + ITE(noOverflow, + sum, + (sum >> ubv::one(sumWidth)) | (sum & ubv::one(sumWidth))), // Cheap sticky right shift + ITE(noCancel, + sum, + sum.modularLeftShift(ubv::one(sumWidth))))); // In the case when this looses data, the result is not used + + sbv extendedLargerExponent(larger.getExponent().extend(1)); // So that increment and decrement don't overflow + sbv correctedExponent(ITE(effectiveAdd, + ITE(noOverflow, + extendedLargerExponent, + extendedLargerExponent.increment()), + ITE(noCancel, + extendedLargerExponent, + extendedLargerExponent.decrement()))); + + // Far path : Construct result + unpackedFloat farPathResult(resultSign, correctedExponent, (alignedSum | shiftedStickyBit).contract(1)); + + + + + // Near path : Align + prop exponentDifferenceAllZeros(exponentDifference.isAllZeros()); + ubv nearAlignedSmaller(ITE(exponentDifferenceAllZeros, ssig, ssig >> ubv::one(ssig.getWidth()))); + + + // Near path : Sum and realign + ubv nearSum(lsig - nearAlignedSmaller); + // Optimisation : the two paths can be merged up to here to give a pseudo-two path encoding + + prop fullCancel(nearSum.isAllZeros()); + prop nearNoCancel(nearSum.extract(sumWidth - 2, sumWidth - 2).isAllOnes()); + + ubv choppedNearSum(nearSum.extract(sumWidth - 3,1)); // In the case this is used, cut bits are all 0 + unpackedFloat cancellation(resultSign, + larger.getExponent().decrement(), + choppedNearSum); + + + // Near path : Construct result + unpackedFloat nearPathResult(resultSign, extendedLargerExponent, nearSum.contract(1)); + + + + // Bring the paths together + // Optimisation : fix the noOverlap / very far path for directed rounding modes + unpackedFloat additionResult(ITE(farPath, + /* ITE(noOverlap, + ITE((isAdd || orderingCorrect), + larger, + negate(format, larger)), + farPathResult), */ + farPathResult, + ITE(fullCancel, + unpackedFloat::makeZero(extendedFormat, roundingMode == t::RTN()), + ITE(nearNoCancel, + nearPathResult, + cancellation.normaliseUp(format).extend(1,2))))); + + // Some thought is required here to convince yourself that + // there will be no subnormal values that violate this. + // See 'all subnormals generated by addition are exact' + // and the extended exponent. + POSTCONDITION(additionResult.valid(extendedFormat)); + + return additionResult; + } + + + + + template + unpackedFloat dualPathAdd (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &left, + const unpackedFloat &right, + const typename t::prop &isAdd) { + + PRECONDITION(left.valid(format)); + PRECONDITION(right.valid(format)); + + unpackedFloat additionResult(dualPathArithmeticAdd(format, roundingMode, left, right, isAdd)); + + unpackedFloat roundedAdditionResult(rounder(format, roundingMode, additionResult)); + + unpackedFloat result(addAdditionSpecialCases(format, roundingMode, left, right, roundedAdditionResult, isAdd)); + + POSTCONDITION(result.valid(format)); + + return result; + } + +template + unpackedFloat add (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &left, + const unpackedFloat &right, + const typename t::prop &isAdd) { + + //typedef typename t::bwt bwt; + typedef typename t::prop prop; + //typedef typename t::ubv ubv; + //typedef typename t::sbv sbv; + + PRECONDITION(left.valid(format)); + PRECONDITION(right.valid(format)); + + // Optimisation : add a flag which assumes that left and right are in the correct order + prop knownInCorrectOrder(false); + + exponentCompareInfo ec(addExponentCompare(left.getExponent().getWidth() + 1, left.getSignificand().getWidth(), + left.getExponent(), right.getExponent(), knownInCorrectOrder)); + + floatWithCustomRounderInfo additionResult(arithmeticAdd(format, roundingMode, left, right, isAdd, knownInCorrectOrder, ec)); + + unpackedFloat roundedAdditionResult(customRounder(format, roundingMode, additionResult.uf, additionResult.known)); + + unpackedFloat result(addAdditionSpecialCases(format, roundingMode, left, right, roundedAdditionResult, isAdd)); + + POSTCONDITION(result.valid(format)); + + return result; + } + + template + unpackedFloat addWithBypass (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &left, + const unpackedFloat &right, + const typename t::prop &isAdd) { + + //typedef typename t::bwt bwt; + typedef typename t::prop prop; + //typedef typename t::ubv ubv; + //typedef typename t::sbv sbv; + + PRECONDITION(left.valid(format)); + PRECONDITION(right.valid(format)); + + // Optimisation : add a flag which assumes that left and right are in the correct order + prop knownInCorrectOrder(false); + + + exponentCompareInfo ec(addExponentCompare(left.getExponent().getWidth() + 1, left.getSignificand().getWidth(), + left.getExponent(), right.getExponent(), knownInCorrectOrder)); + + floatWithCustomRounderInfo additionResult(arithmeticAdd(format, roundingMode, left, right, isAdd, knownInCorrectOrder, ec)); + + unpackedFloat roundedAdditionResult(customRounder(format, roundingMode, additionResult.uf, additionResult.known)); + + // In the "very far path", i.e. exponent difference is greater than significand length + 1 + // addition becomes max(left,right) or max(left,right)+/-1 ULP. This is rare in execution + // (to the point of being a software quality issue) but common in theorem proving. + // Given we have to have cases for "return left" and "return right" to handle zeros, + // we might as well make use of these cases to handle when addition behaves like max... + // Note that this is possible but more complex with just diffIsGreaterThanPrecision. + + prop enableBypass(ec.diffIsGreaterThanPrecisionPlusOne && + !left.getNaN() && !left.getInf() && !left.getZero() && // Handle this as special cases + !right.getNaN() && !right.getInf() && !right.getZero()); + + + // Duplication but easier to recompute than to pass + prop effectiveAdd((left.getSign() ^ right.getSign()) ^ isAdd); + prop resultSign(ITE((knownInCorrectOrder || ec.leftIsMax), // CAUTION : only true in the enableBypass case! + left.getSign(), + prop(!isAdd ^ right.getSign()))); + + prop significandEven(true); // This is an optimisation that assumes only RNE uses this bit + // This needs to be changed to implement things like roundToOdd + // or for the diffIsGreaterThanPrecision case. + prop farRoundUp(roundingDecision(roundingMode, resultSign, significandEven, !effectiveAdd, prop(true), prop(false))); + + // Returns left or right unchanged if adding and rounded down or subtracting and rounded up + prop roundInCorrectDirection(effectiveAdd ^ farRoundUp); + + prop returnLeft(enableBypass && ec.leftIsMax && roundInCorrectDirection); + prop returnRight(enableBypass && !ec.leftIsMax && roundInCorrectDirection); + + unpackedFloat result(addAdditionSpecialCasesWithBypass(format, roundingMode, left, right, returnLeft, returnRight, roundedAdditionResult, isAdd)); + + POSTCONDITION(result.valid(format)); + + return result; + } + + + // True if and only if adding these would result in a catastrophic cancellation + // I.E. if the addition cancells out cancelAmount or more MSBs leaving only LSBs + template + typename t::prop isCatastrophicCancellation (const typename t::fpt &format, + const unpackedFloat &left, + const unpackedFloat &right, + const typename t::bwt &cancelAmount, + const typename t::prop &isAdd) { + + typedef typename t::bwt bwt; + typedef typename t::prop prop; + typedef typename t::ubv ubv; + //typedef typename t::sbv sbv; + + PRECONDITION(left.valid(format)); + PRECONDITION(right.valid(format)); + PRECONDITION(cancelAmount >= 2); // cancel 0 is not meaningful + // cancel 1 is common on subtract and arguably not an error + PRECONDITION(cancelAmount <= format.significandWidth()); // can't cancel more than you have + + // 1. It has to be an effective subtraction + // Duplication but easier to recompute than to pass + prop effectiveAdd((left.getSign() ^ right.getSign()) ^ isAdd); + + // 2. It must be either normal or subnormal numbers + prop leftSpecial(left.getNaN() || left.getInf() || left.getZero()); + prop rightSpecial(right.getNaN() || right.getInf() || right.getZero()); + + // 3.A. exponents are equal and so are the leading cancelAmount bits + // 3.B. exponent diff is one and the smaller one is 11111, larger one is 10000 + + // Optimisation : add a flag which assumes that left and right are in the correct order + prop knownInCorrectOrder(false); + exponentCompareInfo ec(addExponentCompare(left.getExponent().getWidth() + 1, left.getSignificand().getWidth(), + left.getExponent(), right.getExponent(), knownInCorrectOrder)); + + // Can ignore the MSB of the significand as by invariants this is always 1 + bwt significandWidth(format.significandWidth()); + bwt topBit(significandWidth - 2); + bwt bottomBit(significandWidth - cancelAmount); + + ubv leftExtract(left.getSignificand.extract(topBit, bottomBit)); + ubv rightExtract(right.getSignificand.extract(topBit, bottomBit)); + + prop result(ITE(!effectiveAdd && !leftSpecial && !rightSpecial, + ITE(ec.diffIsZero, + leftExtract == rightExtract, + ITE(ec.diffIsOne, + ITE(ec.leftIsMax, + leftExtract.isAllZeros() && rightExtract.isAllOnes(), + rightExtract.isAllZeros() && leftExtract.isAllOnes()), + false)), + false)); + + return result; + } + +} + +#endif + diff --git a/third-party/symfpu/core/classify.h b/third-party/symfpu/core/classify.h new file mode 100644 index 0000000..006bb10 --- /dev/null +++ b/third-party/symfpu/core/classify.h @@ -0,0 +1,106 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** classify.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 21/08/14 +** +** The classification functions for different classes of float. +** +*/ + +#include "symfpu/core/unpackedFloat.h" + +#ifndef SYMFPU_CLASSIFY +#define SYMFPU_CLASSIFY + +namespace symfpu { + +template + typename t::prop isNormal (const typename t::fpt &format, const unpackedFloat &uf) { + PRECONDITION(uf.valid(format)); + + return !uf.getNaN() && !uf.getInf() && !uf.getZero() && uf.inNormalRange(format, typename t::prop(true)); + } + + +template + typename t::prop isSubnormal (const typename t::fpt &format, const unpackedFloat &uf) { + PRECONDITION(uf.valid(format)); + + return !uf.getNaN() && !uf.getInf() && !uf.getZero() && uf.inSubnormalRange(format, typename t::prop(true)); + } + + +template + typename t::prop isZero (const typename t::fpt &format, const unpackedFloat &uf) { + PRECONDITION(uf.valid(format)); + + return uf.getZero(); + } + + +template + typename t::prop isInfinite (const typename t::fpt &format, const unpackedFloat &uf) { + PRECONDITION(uf.valid(format)); + + return uf.getInf(); + } + + +template + typename t::prop isNaN (const typename t::fpt &format, const unpackedFloat &uf) { + PRECONDITION(uf.valid(format)); + + return uf.getNaN(); + } + + +// Note these are the SMT-LIB semantics, NaN is neither positive or negative + +template + typename t::prop isPositive (const typename t::fpt &format, const unpackedFloat &uf) { + PRECONDITION(uf.valid(format)); + + return !uf.getNaN() && !uf.getSign(); + } + +template + typename t::prop isNegative (const typename t::fpt &format, const unpackedFloat &uf) { + PRECONDITION(uf.valid(format)); + + return !uf.getNaN() && uf.getSign(); + } + + +// C semantics + + template + typename t::prop isFinite (const typename t::fpt &format, const unpackedFloat &uf) { + PRECONDITION(uf.valid(format)); + + return !uf.getNaN() && !uf.getInf(); + } + + +} + +#endif + diff --git a/third-party/symfpu/core/compare.h b/third-party/symfpu/core/compare.h new file mode 100644 index 0000000..c03a59b --- /dev/null +++ b/third-party/symfpu/core/compare.h @@ -0,0 +1,326 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** compare.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 25/08/14 +** +** Comparison between floating-point numbers +** +*/ + +#include "symfpu/core/unpackedFloat.h" +#include "symfpu/core/ite.h" + +#ifndef SYMFPU_COMPARE +#define SYMFPU_COMPARE + +namespace symfpu { + + // SMT-LIB equality + template + typename t::prop smtlibEqual (const typename t::fpt &format, + const unpackedFloat &left, + const unpackedFloat &right) { + typedef typename t::prop prop; + + PRECONDITION(left.valid(format)); + PRECONDITION(right.valid(format)); + + // Relies on a number of properties of the unpacked format + // particularly the use of default exponents, significands and signs + + prop flagsEqual((left.getNaN() == right.getNaN()) && + (left.getInf() == right.getInf()) && + (left.getZero() == right.getZero()) && + (left.getSign() == right.getSign())); + + prop flagsAndExponent(flagsEqual && left.getExponent() == right.getExponent()); + + // Avoid comparing (and thus instantiating) the significand unless necessary + probabilityAnnotation(flagsAndExponent, UNLIKELY); + + prop res(ITE(flagsAndExponent, + left.getSignificand() == right.getSignificand(), + prop(false))); + + return res; + } + + // IEEE-754 Equality (not actually an equivalence relation but ...) + template + typename t::prop ieee754Equal (const typename t::fpt &format, + const unpackedFloat &left, + const unpackedFloat &right) { + + typedef typename t::prop prop; + + PRECONDITION(left.valid(format)); + PRECONDITION(right.valid(format)); + + prop neitherNan(!left.getNaN() && !right.getNaN()); // All comparison with NaN are false + prop bothZero(left.getZero() && right.getZero()); // Both zeros are equal + prop neitherZero(!left.getZero() && !right.getZero()); + + prop flagsAndExponent(neitherNan && + (bothZero || (neitherZero && + (left.getInf() == right.getInf() && + left.getSign() == right.getSign() && + left.getExponent() == right.getExponent())))); + + // Avoid comparing (and thus instantiating) the significand unless necessary + probabilityAnnotation(flagsAndExponent, UNLIKELY); + + prop res(ITE(flagsAndExponent, left.getSignificand() == right.getSignificand(), prop(false))); + + return res; + } + + + // Share the common comparison code between functions + // equality == true if the equal case returns true + // IEEE-754 semantics for ordering with NaN + // (i.e. unordered with everything, not even equal to itself) + template + typename t::prop ordering (const typename t::fpt &format, + const unpackedFloat &left, + const unpackedFloat &right, + const typename t::prop equality) { + + typedef typename t::prop prop; + + PRECONDITION(left.valid(format)); + PRECONDITION(right.valid(format)); + + // All comparison with NaN are false + prop neitherNaN(!left.getNaN() && !right.getNaN()); + + // Either is an infinity (wrong in the case of NaN but will be corrected) + prop infCase( (left.isNegativeInf() && ITE(equality, prop(true), !right.isNegativeInf()) ) || + (right.isPositiveInf() && ITE(equality, prop(true), !left.isPositiveInf()) ) || + (ITE(equality, left.getInf() && right.getInf() && left.getSign() == right.getSign(), prop(false))) ); + + + // Either is a zero (wrong in the case of NaN but will be corrected) + prop zeroCase( ( left.getZero() && !right.getZero() && !right.getSign()) || + (right.getZero() && !left.getZero() && left.getSign()) || + (ITE(equality, left.getZero() && right.getZero(), prop(false))) ); + + + // Normal and subnormal case + prop normalOrSubnormal(!left.getNaN() && !right.getNaN() && + !left.getInf() && !right.getInf() && + !left.getZero() && !right.getZero()); + + prop negativeLessThanPositive(normalOrSubnormal && left.getSign() && !right.getSign()); + + prop exponentNeeded(normalOrSubnormal && left.getSign() == right.getSign()); + probabilityAnnotation(exponentNeeded, UNLIKELY); + + prop positiveCase(!left.getSign() && !right.getSign() && + left.getExponent() < right.getExponent()); + prop negativeCase( left.getSign() && right.getSign() && + left.getExponent() > right.getExponent()); + + + prop exponentEqual(left.getExponent() == right.getExponent()); + + prop significandNeeded(exponentNeeded && exponentEqual); + probabilityAnnotation(significandNeeded, VERYUNLIKELY); + + prop positiveExEqCase(!left.getSign() && !right.getSign() && + left.getSignificand() < right.getSignificand()); + prop negativeExEqCase( left.getSign() && right.getSign() && + left.getSignificand() > right.getSignificand()); + + prop positiveExEqCaseEq(!left.getSign() && !right.getSign() && + left.getSignificand() <= right.getSignificand()); + prop negativeExEqCaseEq( left.getSign() && right.getSign() && + left.getSignificand() >= right.getSignificand()); + + return ITE(!normalOrSubnormal, + neitherNaN && (infCase || zeroCase), + ITE(!exponentNeeded, + negativeLessThanPositive, + ITE(!significandNeeded, + positiveCase || negativeCase, + ITE(equality, + positiveExEqCaseEq || negativeExEqCaseEq, + positiveExEqCase || negativeExEqCase)))); + } + + + template + typename t::prop lessThan (const typename t::fpt &format, + const unpackedFloat &left, + const unpackedFloat &right) { + PRECONDITION(left.valid(format)); + PRECONDITION(right.valid(format)); + + typedef typename t::prop prop; + + return ordering(format, left, right, prop(false)); + } + + + template + typename t::prop lessThanOrEqual (const typename t::fpt &format, + const unpackedFloat &left, + const unpackedFloat &right) { + PRECONDITION(left.valid(format)); + PRECONDITION(right.valid(format)); + + typedef typename t::prop prop; + + return ordering(format, left, right, prop(true)); + } + + + // Note that IEEE-754 says that max(+0,-0) = +/-0 and max(-0,+0) = +/- 0 + template + unpackedFloat max (const typename t::fpt &format, + const unpackedFloat &left, + const unpackedFloat &right, + const typename t::prop &zeroCase) { + return ITE(left.getNaN() || ordering(format, left, right, zeroCase), + right, + left); + } + + // Note that IEEE-754 says that min(+0,-0) = +/-0 and min(-0,+0) = +/- 0 + // this will always return the left one. + template + unpackedFloat min (const typename t::fpt &format, + const unpackedFloat &left, + const unpackedFloat &right, + const typename t::prop &zeroCase) { + return ITE(right.getNaN() || ordering(format, left, right, zeroCase), + left, + right); + } + + + + template + typename t::prop originalLessThan (const typename t::fpt &format, + const unpackedFloat &left, + const unpackedFloat &right) { + + typedef typename t::prop prop; + + PRECONDITION(left.valid(format)); + PRECONDITION(right.valid(format)); + + // Optimisation : merge < and == + + + // All comparison with NaN are false + prop neitherNan(!left.getNaN() && !right.getNaN()); + + // Infinities are bigger than everything but themself + prop eitherInf(left.getInf() || right.getInf()); + prop infCase(( left.isNegativeInf() && !right.isNegativeInf()) || + (!left.isPositiveInf() && right.isPositiveInf())); + + + // Both zero are equal + prop eitherZero(left.getZero() || right.getZero()); + prop zeroCase(( left.getZero() && !right.getZero() && !right.getSign()) || + (!left.getZero() && left.getSign() && right.getZero())); + + + // Normal and subnormal + + prop negativeLessThanPositive(left.getSign() && !right.getSign()); // - < + + prop positiveCase(!left.getSign() && !right.getSign() && + ((left.getExponent() < right.getExponent()) || + (left.getExponent() == right.getExponent() && + left.getSignificand() < right.getSignificand()))); + + prop negativeCase(left.getSign() && right.getSign() && + ((left.getExponent() > right.getExponent()) || + (left.getExponent() == right.getExponent() && + left.getSignificand() > right.getSignificand()))); + + + return neitherNan && + ITE(eitherInf, + infCase, + ITE(eitherZero, + zeroCase, + negativeLessThanPositive || positiveCase || negativeCase)); + } + + // Optimised combination of the two + template + typename t::prop originalLessThanOrEqual (const typename t::fpt &format, + const unpackedFloat &left, + const unpackedFloat &right) { + + typedef typename t::prop prop; + + PRECONDITION(left.valid(format)); + PRECONDITION(right.valid(format)); + + // Optimisation : merge < and == + + + // All comparison with NaN are false + prop neitherNan(!left.getNaN() && !right.getNaN()); + + // Infinities are bigger than everything but themself + prop eitherInf(left.getInf() || right.getInf()); + prop infCase( (left.getInf() && right.getInf() && left.getSign() == right.getSign()) || + left.isNegativeInf() || + right.isPositiveInf()); + + + // Both zero are equal + prop eitherZero(left.getZero() || right.getZero()); + prop zeroCase((left.getZero() && right.getZero()) || + ( left.getZero() && !right.getSign()) || + ( left.getSign() && right.getZero())); + + + // Normal and subnormal + + prop negativeLessThanPositive(left.getSign() && !right.getSign()); // - < + + prop positiveCase(!left.getSign() && !right.getSign() && + ((left.getExponent() < right.getExponent()) || + (left.getExponent() == right.getExponent() && + left.getSignificand() <= right.getSignificand()))); + + prop negativeCase(left.getSign() && right.getSign() && + ((left.getExponent() > right.getExponent()) || + (left.getExponent() == right.getExponent() && + left.getSignificand() >= right.getSignificand()))); + + + return neitherNan && + ITE(eitherInf, + infCase, + ITE(eitherZero, + zeroCase, + negativeLessThanPositive || positiveCase || negativeCase)); + } + +} + +#endif diff --git a/third-party/symfpu/core/convert.h b/third-party/symfpu/core/convert.h new file mode 100644 index 0000000..348ab59 --- /dev/null +++ b/third-party/symfpu/core/convert.h @@ -0,0 +1,502 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** convert.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 03/02/14 +** +** Conversion from unpacked floats in one format to another. +** +*/ + +#include "symfpu/core/unpackedFloat.h" +#include "symfpu/core/rounder.h" + +#ifndef SYMFPU_CONVERT +#define SYMFPU_CONVERT + +namespace symfpu { + +template +unpackedFloat convertFloatToFloat (const typename t::fpt &sourceFormat, + const typename t::fpt &targetFormat, + const typename t::rm &roundingMode, + const unpackedFloat &input) { + + PRECONDITION(input.valid(sourceFormat)); + + typedef typename t::bwt bwt; + //typedef typename t::prop prop; + //typedef typename t::ubv ubv; + //typedef typename t::sbv sbv; + + // increased includes equality + bool exponentIncreased = unpackedFloat::exponentWidth(sourceFormat) <= unpackedFloat::exponentWidth(targetFormat); + bool significandIncreased = unpackedFloat::significandWidth(sourceFormat) <= unpackedFloat::significandWidth(targetFormat); + + bwt expExtension = (exponentIncreased) ? unpackedFloat::exponentWidth(targetFormat) - unpackedFloat::exponentWidth(sourceFormat) : 0; + bwt sigExtension = (significandIncreased) ? unpackedFloat::significandWidth(targetFormat) - unpackedFloat::significandWidth(sourceFormat) : 0; + + unpackedFloat extended(input.extend(expExtension, sigExtension)); + + // Format sizes are literal so it is safe to branch on them + if (exponentIncreased && significandIncreased) { + // Fast path strict promotions + + POSTCONDITION(extended.valid(targetFormat)); + + return extended; + + } else { + + unpackedFloat rounded(rounder(targetFormat, roundingMode, extended)); + + unpackedFloat result(ITE(input.getNaN(), + unpackedFloat::makeNaN(targetFormat), + ITE(input.getInf(), + unpackedFloat::makeInf(targetFormat, input.getSign()), + ITE(input.getZero(), + unpackedFloat::makeZero(targetFormat, input.getSign()), + rounded)))); + + POSTCONDITION(result.valid(targetFormat)); + + return result; + } +} + + +template +unpackedFloat roundToIntegral (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &input) { + + PRECONDITION(input.valid(format)); + + typedef typename t::bwt bwt; + typedef typename t::prop prop; + typedef typename t::ubv ubv; + typedef typename t::sbv sbv; + + sbv exponent(input.getExponent()); + bwt exponentWidth(exponent.getWidth()); + + sbv packedSigWidth(exponentWidth, format.packedSignificandWidth()); + sbv unpackedSigWidth(exponentWidth, format.significandWidth()); + + // Fast path for things that must be integral + prop isIntegral(exponent >= packedSigWidth); + prop isSpecial(input.getNaN() || input.getInf() || input.getZero()); + prop isID(isIntegral || isSpecial); + probabilityAnnotation(isID, LIKELY); + // TODO : fast path the cases that don't round up + + + // Otherwise, compute rounding location + sbv initialRoundingPoint(expandingSubtract(packedSigWidth,exponent)); // Expansion only needed in obscure formats + sbv roundingPoint(collar(initialRoundingPoint, + sbv::zero(exponentWidth + 1), + unpackedSigWidth.extend(1).increment())); + + // Round + ubv significand(input.getSignificand()); + significandRounderResult roundedResult(variablePositionRound(roundingMode, input.getSign(), significand, + roundingPoint.toUnsigned().matchWidth(significand), + prop(false), // TODO : Could actually be exponent >= 0 + isID)); // The fast-path case so just deactives some code + + // Reconstruct + // Note this is not in a valid form if significand is all zeros + // The max is necessary to catch cases when we round up to one from very small numbers + // The rounder ensures these are zero if they don't round up + unpackedFloat reconstructed(input.getSign(), + max(conditionalIncrement(roundedResult.incrementExponent, exponent), + sbv::zero(exponentWidth)), + roundedResult.significand); + + + unpackedFloat result(ITE(isID, + input, + ITE(roundedResult.significand.isAllZeros(), + unpackedFloat::makeZero(format, input.getSign()), + reconstructed))); + + POSTCONDITION(result.valid(format)); + + return result; + + + #if 0 + // increased includes equality + bool exponentIncreased = unpackedFloat::exponentWidth(sourceFormat) <= unpackedFloat::exponentWidth(targetFormat); + bool significandIncreased = unpackedFloat::significandWidth(sourceFormat) <= unpackedFloat::significandWidth(targetFormat); + + bwt expExtension = (exponentIncreased) ? unpackedFloat::exponentWidth(targetFormat) - unpackedFloat::exponentWidth(sourceFormat) : 0; + bwt sigExtension = (significandIncreased) ? unpackedFloat::significandWidth(targetFormat) - unpackedFloat::significandWidth(sourceFormat) : 0; + + unpackedFloat extended(input.extend(expExtension, sigExtension)); + + // Format sizes are literal so it is safe to branch on them + if (exponentIncreased && significandIncreased) { + // Fast path strict promotions + + POSTCONDITION(extended.valid(targetFormat)); + + return extended; + + } else { + + unpackedFloat rounded(rounder(targetFormat, roundingMode, extended)); + + unpackedFloat result(ITE(input.getNaN(), + unpackedFloat::makeNaN(targetFormat), + ITE(input.getInf(), + unpackedFloat::makeInf(targetFormat, input.getSign()), + ITE(input.getZero(), + unpackedFloat::makeZero(targetFormat, input.getSign()), + rounded)))); + + POSTCONDITION(result.valid(targetFormat)); + + return result; + } + #endif + +} + + +template + unpackedFloat convertUBVToFloat (const typename t::fpt &targetFormat, + const typename t::rm &roundingMode, + const typename t::ubv &input, + const typename t::bwt &decimalPointPosition = 0) { + + typedef typename t::bwt bwt; + typedef typename t::prop prop; + typedef typename t::sbv sbv; + typedef typename t::fpt fpt; + + bwt inputWidth(input.getWidth()); + + PRECONDITION(decimalPointPosition <= inputWidth); + + // Devise an appropriate format + bwt initialExponentWidth(bitsToRepresent(inputWidth) + 1); // +1 as unsigned -> signed + fpt initialFormat(initialExponentWidth, inputWidth); + bwt actualExponentWidth(unpackedFloat::exponentWidth(initialFormat)); + + // Build + unpackedFloat initial(prop(false), sbv(actualExponentWidth, (inputWidth - 1) - decimalPointPosition), input); // inputWidth - 1 as we want one bit above the decimal point + + // Normalise + unpackedFloat normalised(initial.normaliseUpDetectZero(initialFormat)); + + // Round (the conversion will catch the cases where no rounding is needed) + return convertFloatToFloat(initialFormat, targetFormat, roundingMode, normalised); + } + + +template + unpackedFloat convertSBVToFloat (const typename t::fpt &targetFormat, + const typename t::rm &roundingMode, + const typename t::sbv &input, + const typename t::bwt &decimalPointPosition = 0) { + typedef typename t::bwt bwt; + typedef typename t::prop prop; + typedef typename t::sbv sbv; + typedef typename t::fpt fpt; + + bwt inputWidth(input.getWidth()); + + PRECONDITION(decimalPointPosition <= inputWidth); + + // Devise an appropriate format + bwt initialExponentWidth(bitsToRepresent(inputWidth) + 1); // +1 as unsigned -> signed + fpt initialFormat(initialExponentWidth, inputWidth + 1); // +1 as signed -> unsigned + bwt actualExponentWidth(unpackedFloat::exponentWidth(initialFormat)); + + // Work out the sign + prop negative(input < sbv::zero(inputWidth)); + + // Build + unpackedFloat initial(negative, sbv(actualExponentWidth, inputWidth - decimalPointPosition), (abs(input.extend(1))).toUnsigned()); + + // Normalise + unpackedFloat normalised(initial.normaliseUpDetectZero(initialFormat)); + + // Round (the conversion will catch the cases where no rounding is needed) + return convertFloatToFloat(initialFormat, targetFormat, roundingMode, normalised); + } + + + // Common conversion code for both convert to sgined and to unsigned. + // Note that the results will be junk if it is not in bounds, etc. + // convertFloatToUBV and convertFloatToSBV handle all of that logic. + template + significandRounderResult convertFloatToBV (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &input, + const typename t::bwt &targetWidth, + const typename t::bwt &decimalPointPosition) { + + typedef typename t::bwt bwt; + typedef typename t::prop prop; + typedef typename t::ubv ubv; + typedef typename t::sbv sbv; + + + PRECONDITION(decimalPointPosition < targetWidth); + + + // TODO : fast path the RTZ / don't need to round case + + bwt maxShift(targetWidth + 1); // + 1 as we have to shift over the guard bit + bwt maxShiftBits(bitsToRepresent(maxShift) + 1); // +1 as we want it to be signed + + bwt exponentWidth(input.getExponent().getWidth()); + bwt workingExponentWidth((exponentWidth >= maxShiftBits) ? + exponentWidth : maxShiftBits); + + sbv maxShiftAmount(workingExponentWidth, maxShift); + sbv exponent(input.getExponent().matchWidth(maxShiftAmount)); + + + // Optimisation : compact the significand in the case targetWidth < significantWidth + ubv inputSignificand(input.getSignificand()); + bwt inputSignificandWidth(inputSignificand.getWidth()); + ubv *working = NULL; + if (targetWidth + 2 < inputSignificandWidth) { + + ubv dataAndGuard(inputSignificand.extract(inputSignificandWidth - 1, (inputSignificandWidth - targetWidth) - 1)); + prop sticky(!inputSignificand.extract((inputSignificandWidth - targetWidth) - 2, 0).isAllZeros()); + + working = new ubv(dataAndGuard.append(ubv(sticky))); + } else { + working = new ubv(inputSignificand); + } + ubv significand(*working); + delete working; + bwt significandWidth(significand.getWidth()); + + // Handle zero + ubv zerodSignificand(significand & + ITE(input.getZero(), ubv::zero(significandWidth), ubv::allOnes(significandWidth))); + ubv expandedSignificand(zerodSignificand.extend(maxShift)); // Start with the significand in the sticky position. + // targetWidth +1 is for the guard bit + + // Align + sbv shiftAmount(collar(expandingAdd(exponent, + sbv(workingExponentWidth, decimalPointPosition + 2)), // +1 to guard, +1 to LSB + sbv::zero(workingExponentWidth + 1), + maxShiftAmount.extend(1))); + ubv convertedShiftAmount(shiftAmount.resize(bitsToRepresent(maxShift) + 1 /* +1 for sign bit, safe due to collar */ + ).toUnsigned().matchWidth(expandedSignificand)); + ubv aligned(expandedSignificand << convertedShiftAmount); // Safe by collar + + + // Fixed position round + significandRounderResult rounded(fixedPositionRound(roundingMode, input.getSign(), + aligned, targetWidth, + prop(false), prop(false))); + + return rounded; + } + + // A more compact version for round to zero + // Only handles normal, subnormal and zero cases, overflow of targetWidth will give junk. + // Inf, NaN, and overflow must be handled by the caller. + template + significandRounderResult convertFloatToBVRTZ (const typename t::fpt &format, + const unpackedFloat &input, + const typename t::bwt &targetWidth, + const typename t::bwt &decimalPointPosition) { + typedef typename t::bwt bwt; + typedef typename t::prop prop; + typedef typename t::ubv ubv; + typedef typename t::sbv sbv; + + PRECONDITION(targetWidth > 0); + PRECONDITION(decimalPointPosition < targetWidth); + + // A working significand of the right length + ubv significand(input.getSignificand()); + bwt significandWidth(significand.getWidth()); + + ubv significantSignificand(significand.extract(significandWidth - 1, + ((targetWidth < significandWidth) ? significandWidth - targetWidth : 0))); + bwt ssWidth(significantSignificand.getWidth()); + + + // Handle zero and fractional cases + sbv exponent(input.getExponent()); + bwt exponentWidth(exponent.getWidth()); + + prop fraction(input.getExponent() < sbv::zero(exponentWidth)); + ubv zerodSignificand(significantSignificand & + ITE(input.getZero() || fraction, ubv::zero(ssWidth), ubv::allOnes(ssWidth))); + + ubv expandedSignificand(zerodSignificand.extend(targetWidth - 1)); // Start with the significand in the LSB of output + + + // Prepare exponent + bwt maxShift(targetWidth - 1); // - 1 as we are already at LSB + bwt maxShiftBits(bitsToRepresent(maxShift)); // Don't care about it being signed + + ubv convertedExponent(exponent.toUnsigned()); + bwt topExtractedBit(((maxShiftBits > (exponentWidth - 1)) ? exponentWidth : maxShiftBits) - 1); + + ubv shiftBits(convertedExponent.extract(topExtractedBit, 0)); + ubv shiftOperand(shiftBits.matchWidth(expandedSignificand)); + + // Align + ubv shifted(expandedSignificand.modularLeftShift(shiftOperand)); + bwt shiftedWidth(shifted.getWidth()); + + // Extract + ubv result(shifted.extract(shiftedWidth - 1, shiftedWidth - targetWidth)); + + return significandRounderResult(result, prop(false)); + } + + + + // Decimal point position in the bit in the output on the left hand side of the decimal point + // I.E. if it is positive then it is converting to a fix-point number + template + typename t::ubv convertFloatToUBV (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &input, + const typename t::bwt &targetWidth, + const typename t::ubv &undefValue, + const typename t::bwt &decimalPointPosition = 0) { + + typedef typename t::bwt bwt; + typedef typename t::prop prop; + typedef typename t::ubv ubv; + typedef typename t::sbv sbv; + + + PRECONDITION(decimalPointPosition < targetWidth); + + + // Invalid cases + prop specialValue(input.getInf() || input.getNaN()); + + bwt maxExponentValue(targetWidth); + bwt maxExponentBits(bitsToRepresent(maxExponentValue) + 1); + + bwt exponentWidth(input.getExponent().getWidth()); + bwt workingExponentWidth((exponentWidth >= maxExponentBits) ? + exponentWidth : maxExponentBits); + + sbv maxExponent(workingExponentWidth, maxExponentValue); + sbv exponent(input.getExponent().matchWidth(maxExponent)); + + prop tooLarge(exponent >= maxExponent); + + prop tooNegative(input.getSign() && + !input.getZero() && // Zero is handled elsewhere + sbv::zero(workingExponentWidth) <= exponent); // Can't round to 0 + + prop earlyUndefinedResult(specialValue || tooLarge || tooNegative); + probabilityAnnotation(earlyUndefinedResult, LIKELY); // Convertable values are rare + + + // Fixed position round + significandRounderResult rounded(convertFloatToBV(format, roundingMode, input, + targetWidth, decimalPointPosition)); + + // TODO : fast path negative by converting exp==0 into guard and exp < 0 into sticky + + // Put the result together + prop undefinedResult(earlyUndefinedResult || + rounded.incrementExponent || // Overflow + (input.getSign() && !rounded.significand.isAllZeros())); // Negative case + + ubv result(ITE(undefinedResult, + undefValue, + rounded.significand)); + + return result; + } + + // Decimal point position in the bit in the output on the left hand side of the decimal point + // I.E. if it is positive then it is converting to a fix-point number + template + typename t::sbv convertFloatToSBV (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &input, + const typename t::bwt &targetWidth, + const typename t::sbv &undefValue, + const typename t::bwt &decimalPointPosition = 0) { + + typedef typename t::bwt bwt; + typedef typename t::prop prop; + //typedef typename t::ubv ubv; + typedef typename t::sbv sbv; + + + PRECONDITION(decimalPointPosition < targetWidth); + + + // Invalid cases + prop specialValue(input.getInf() || input.getNaN()); + + bwt maxExponentValue(targetWidth); + bwt maxExponentBits(bitsToRepresent(maxExponentValue) + 1); + + bwt exponentWidth(input.getExponent().getWidth()); + bwt workingExponentWidth((exponentWidth >= maxExponentBits) ? + exponentWidth : maxExponentBits); + + sbv maxExponent(workingExponentWidth, maxExponentValue); + sbv exponent(input.getExponent().matchWidth(maxExponent)); + + prop tooLarge(exponent >= maxExponent); + + prop earlyUndefinedResult(specialValue || tooLarge); + probabilityAnnotation(earlyUndefinedResult, LIKELY); // Convertable values are rare + + + // Fixed position round + // (It is tempting to think that this could be done with targetWidth - 1 bits but that + // missed the case of things like -128.05 -> int8_t) + significandRounderResult rounded(convertFloatToBV(format, roundingMode, input, + targetWidth, decimalPointPosition)); + + // Put the result together + bwt roundSigWidth(rounded.significand.getWidth()); + prop undefinedResult(earlyUndefinedResult || + rounded.incrementExponent || // Definite Overflow + (rounded.significand.extract(roundSigWidth - 1, + roundSigWidth - 1).isAllOnes() && + !(input.getSign() && rounded.significand.extract(roundSigWidth - 2, 0).isAllZeros()))); // -2^{n-1} is the only safe "overflow" case + + + sbv result(ITE(undefinedResult, + undefValue, + conditionalNegate(input.getSign(), rounded.significand.toSigned()))); + + return result; + } + +} + +#endif diff --git a/third-party/symfpu/core/divide.h b/third-party/symfpu/core/divide.h new file mode 100644 index 0000000..be7360c --- /dev/null +++ b/third-party/symfpu/core/divide.h @@ -0,0 +1,170 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** divide.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 04/02/16 +** +** Division of arbitrary precision floats +** +*/ + +#include "symfpu/core/unpackedFloat.h" +#include "symfpu/core/ite.h" +#include "symfpu/core/rounder.h" +#include "symfpu/core/operations.h" + +#ifndef SYMFPU_DIVIDE +#define SYMFPU_DIVIDE + +namespace symfpu { + +template + unpackedFloat addDivideSpecialCases (const typename t::fpt &format, + const unpackedFloat &left, + const unpackedFloat &right, + const typename t::prop &sign, + const unpackedFloat ÷Result) { + typedef typename t::prop prop; + + prop eitherArgumentNaN(left.getNaN() || right.getNaN()); + prop generateNaN((left.getInf() && right.getInf()) || + (left.getZero() && right.getZero())); + + prop isNaN(eitherArgumentNaN || generateNaN); + + prop isInf((!left.getZero() && right.getZero()) || + (left.getInf() && !right.getInf())); + + prop isZero((!left.getInf() && right.getInf()) || + (left.getZero() && !right.getZero())); + + return ITE(isNaN, + unpackedFloat::makeNaN(format), + ITE(isInf, + unpackedFloat::makeInf(format, sign), + ITE(isZero, + unpackedFloat::makeZero(format, sign), + divideResult))); + } + + + template + unpackedFloat arithmeticDivide (const typename t::fpt &format, + const unpackedFloat &left, + const unpackedFloat &right) { + typedef typename t::bwt bwt; + typedef typename t::prop prop; + typedef typename t::ubv ubv; + typedef typename t::sbv sbv; + typedef typename t::fpt fpt; + + PRECONDITION(left.valid(format)); + PRECONDITION(right.valid(format)); + + // Compute sign + prop divideSign(left.getSign() ^ right.getSign()); + + // Subtract up exponents + sbv exponentDiff(expandingSubtract(left.getExponent(),right.getExponent())); + // Optimisation : do this late and use the increment as a carry in + + sbv min(unpackedFloat::minSubnormalExponent(format)); + sbv max(unpackedFloat::maxNormalExponent(format)); + INVARIANT(expandingSubtract(min,max) <= exponentDiff); + INVARIANT(exponentDiff <= expandingSubtract(max, min)); + // Optimisation : use the if-then-lazy-else to avoid dividing for underflow and overflow + // subnormal / greater-than-2^sigwidth does not need to be evaluated + + + // Divide the significands + // We need significandWidth() + 1 bits in the result but the top one may cancel, so add two bits + ubv extendedNumerator(left.getSignificand().append(ubv::zero(2))); + ubv extendedDenominator(right.getSignificand().append(ubv::zero(2))); + + resultWithRemainderBit divided(fixedPointDivide(extendedNumerator, extendedDenominator)); + + + bwt resWidth(divided.result.getWidth()); + ubv topBit(divided.result.extract(resWidth - 1, resWidth - 1)); + ubv nextBit(divided.result.extract(resWidth - 2, resWidth - 2)); + + // Alignment of inputs means at least one of the two MSB is 1 + // i.e. [1,2) / [1,2) = [0.5,2) + // Top bit is set by the first round of the divide and thus is 50/50 1 or 0 + prop topBitSet(topBit.isAllOnes()); + INVARIANT(topBitSet || nextBit.isAllOnes()); + INVARIANT(topBitSet == (left.getSignificand() >= right.getSignificand())); + + + // Re-align + sbv alignedExponent(conditionalDecrement(!topBitSet, exponentDiff)); // Will not overflow as previously expanded + ubv alignedSignificand(conditionalLeftShiftOne(!topBitSet, divided.result)); // Will not loose information + + // Create the sticky bit, it is important that this is after alignment + ubv finishedSignificand(alignedSignificand | ubv(divided.remainderBit).extend(resWidth - 1)); + + // Put back together + unpackedFloat divideResult(divideSign, alignedExponent.extend(1), finishedSignificand); + + // A brief word about formats. + // You might think that the extend above is unnecessary : it is from a overflow point of view. + // It's needed so that it is a valid number with exponentWidth() + 2. + // +1 is sufficient in almost all cases. However: + // very large normal / very small subnormal + // can have an exponent greater than very large normal * 2 ( + 1) + // because the exponent range is asymmetric with more subnormal than normal. + + fpt extendedFormat(format.exponentWidth() + 2, format.significandWidth() + 2); + POSTCONDITION(divideResult.valid(extendedFormat)); + + return divideResult; + } + + +// Put it all together... +template + unpackedFloat divide (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &left, + const unpackedFloat &right) { + //typedef typename t::bwt bwt; + //typedef typename t::prop prop; + //typedef typename t::ubv ubv; + //typedef typename t::sbv sbv; + + PRECONDITION(left.valid(format)); + PRECONDITION(right.valid(format)); + + unpackedFloat divideResult(arithmeticDivide(format, left, right)); + + unpackedFloat roundedDivideResult(rounder(format, roundingMode, divideResult)); + + unpackedFloat result(addDivideSpecialCases(format, left, right, roundedDivideResult.getSign(), roundedDivideResult)); + + POSTCONDITION(result.valid(format)); + + return result; + } + + +} + +#endif diff --git a/third-party/symfpu/core/fma.h b/third-party/symfpu/core/fma.h new file mode 100644 index 0000000..252e8cb --- /dev/null +++ b/third-party/symfpu/core/fma.h @@ -0,0 +1,218 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** fma.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 20/05/15 +** +** Fused multiply and add : +** fma(R,A,B,C) = round(R, A * B + C) +** +*/ + + +#include "symfpu/core/unpackedFloat.h" +#include "symfpu/core/ite.h" +#include "symfpu/core/rounder.h" +#include "symfpu/core/multiply.h" +#include "symfpu/core/convert.h" +#include "symfpu/core/add.h" + + +#ifndef SYMFPU_FMA +#define SYMFPU_FMA + +namespace symfpu { + + template + unpackedFloat fma (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &leftMultiply, + const unpackedFloat &rightMultiply, + const unpackedFloat &addArgument) { + + // typedef typename t::bwt bwt; + typedef typename t::prop prop; + //typedef typename t::ubv ubv; + //typedef typename t::sbv sbv; + typedef typename t::fpt fpt; + + PRECONDITION(leftMultiply.valid(format)); + PRECONDITION(rightMultiply.valid(format)); + PRECONDITION(addArgument.valid(format)); + + /* First multiply */ + unpackedFloat arithmeticMultiplyResult(arithmeticMultiply(format, leftMultiply, rightMultiply)); + + fpt extendedFormat(format.exponentWidth() + 1, format.significandWidth() * 2); + INVARIANT(arithmeticMultiplyResult.valid(extendedFormat)); + + + + /* Then add */ + + // Rounding mode doesn't matter as this is a strict extension + unpackedFloat extendedAddArgument(convertFloatToFloat(format, extendedFormat, t::RTZ(), addArgument)); + + prop knownInCorrectOrder(false); + exponentCompareInfo ec(addExponentCompare(arithmeticMultiplyResult.getExponent().getWidth() + 1, + arithmeticMultiplyResult.getSignificand().getWidth(), + arithmeticMultiplyResult.getExponent(), + extendedAddArgument.getExponent(), + knownInCorrectOrder)); + + unpackedFloat additionResult(arithmeticAdd(extendedFormat, roundingMode, arithmeticMultiplyResult, extendedAddArgument, prop(true), knownInCorrectOrder, ec).uf); + // Custom rounder flags are ignored as they are not applicable in this case + + fpt evenMoreExtendedFormat(extendedFormat.exponentWidth() + 1, extendedFormat.significandWidth() + 2); + INVARIANT(additionResult.valid(evenMoreExtendedFormat)); + + + /* Then round */ + + unpackedFloat roundedResult(rounder(format, roundingMode, additionResult)); + INVARIANT(roundedResult.valid(format)); + + // This result is correct as long as neither of multiplyResult or extendedAddArgument is + // 0, Inf or NaN. Note that roundedResult may be zero from cancelation or underflow + // or infinity due to rounding. If it is, it has the correct sign. + + + + /* Finally, the special cases */ + + // One disadvantage to having a flag for zero and default exponents and significands for zero + // that are not (min, 0) is that the x + (+/-)0 case has to be handled by the addition special cases. + // This means that you need the value of x, rounded to the correct format. + // arithmeticMultiplyResult is in extended format, thus we have to use a second rounder just for this case. + // It is not zero, inf or NaN so it only matters when addArgument is zero when it would be returned. + unpackedFloat roundedMultiplyResult(rounder(format, roundingMode, arithmeticMultiplyResult)); + + unpackedFloat fullMultiplyResult(addMultiplySpecialCases(format, leftMultiply, rightMultiply, roundedMultiplyResult.getSign(), roundedMultiplyResult)); + + + // We need the flags from the multiply special cases, determined on the arithemtic result, + // i.e. handling special values and not the underflow / overflow of the result. + // But we will use roundedMultiplyResult instead of the value so ... + unpackedFloat dummyZero(unpackedFloat::makeZero(format, prop(false))); + unpackedFloat dummyValue(dummyZero.getSign(), dummyZero.getExponent(), dummyZero.getSignificand()); + + unpackedFloat multiplyResultWithSpecialCases(addMultiplySpecialCases(format, leftMultiply, rightMultiply, arithmeticMultiplyResult.getSign(), dummyValue)); + + + unpackedFloat result(addAdditionSpecialCasesWithID(format, + roundingMode, + multiplyResultWithSpecialCases, + fullMultiplyResult, // for the identity case + addArgument, + roundedResult, + prop(true))); + + POSTCONDITION(result.valid(format)); + + return result; + } + +/* + * BUGS : + * 1. sign of zero different for exact 0 and underflow + * 2. large * -large + inf = inf not NaN + * 3. rounder decision bugs : one looks like an issue with too-eager overflow, + * one looks like a misplaced decision on highest subnormal exponent + */ + + template + unpackedFloat fmaBroken (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &leftMultiply, + const unpackedFloat &rightMultiply, + const unpackedFloat &addArgument) { + + // typedef typename t::bwt bwt; + typedef typename t::prop prop; + //typedef typename t::ubv ubv; + //typedef typename t::sbv sbv; + typedef typename t::fpt fpt; + + PRECONDITION(leftMultiply.valid(format)); + PRECONDITION(rightMultiply.valid(format)); + PRECONDITION(addArgument.valid(format)); + + unpackedFloat multiplyResult(arithmeticMultiply(format, leftMultiply, rightMultiply)); + + fpt extendedFormat(format.exponentWidth() + 1, format.significandWidth() * 2); + INVARIANT(multiplyResult.valid(extendedFormat)); + + // Rounding mode doesn't matter as this is a strict extension + unpackedFloat extendedAddArgument(convertFloatToFloat(format, extendedFormat, t::RTZ(), addArgument)); + + unpackedFloat additionResult(arithmeticAdd(extendedFormat, roundingMode, multiplyResult, extendedAddArgument, prop(true), prop(false)).uf); + // Custom rounder flags are ignored as they are not applicable in this case + + unpackedFloat roundedResult(rounder(format, roundingMode, additionResult)); + + // Note that multiplyResult.getSign() != roundedResult.getSign() in rare cases + // the multiply special cases use the sign for zeros and infinities, thus the sign of the + // result of the multiplication is needed (i.e. the xor of the sign of left and right multiply) + // (-small, +inf, large) should trigger this as the desired result is -inf + // but roundedResult.getSign() is positive. + unpackedFloat roundedResultWithMultiplyCases(addMultiplySpecialCases(format, + leftMultiply, + rightMultiply, + multiplyResult.getSign(), + roundedResult)); + + + // One disadvantage to having a flag for zero and default exponents and significands for zero + // that are not (min, 0) is that the x + 0 case has to be handled by the addition special cases. + // This means that you need the value of x, rounded to the correct format. + // multiplyResult is in extended format, thus we have to use a second rounder just for this case. + // It is not zero, inf or NaN so it only matters when addArgument is zero when it would be returned. + + unpackedFloat roundedMultiplyResult(rounder(format, roundingMode, multiplyResult)); + // Optimisation : Try ITE before rounding so that only one rounder is needed + + + // To make matters more awkward, we also need to apply the multiplicative special cases so that + // (x*0) + y is correctly handled by the addition special cases. Without applying the + // multiplicative ones, (x*0) would not be correctly flagged as 0. + unpackedFloat roundedMultiplyResultWithMultiplyCases(addMultiplySpecialCases(format, + leftMultiply, + rightMultiply, + multiplyResult.getSign(), + roundedMultiplyResult)); + // Optimisation : consolidate the special cases and verify against this + + unpackedFloat result(addAdditionSpecialCases(format, + roundingMode, + roundedMultiplyResultWithMultiplyCases, + addArgument, + roundedResultWithMultiplyCases, + prop(true))); + + POSTCONDITION(result.valid(format)); + + return result; + } + + +} + +#endif diff --git a/third-party/symfpu/core/ite.h b/third-party/symfpu/core/ite.h new file mode 100644 index 0000000..21a98af --- /dev/null +++ b/third-party/symfpu/core/ite.h @@ -0,0 +1,59 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** ite.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 03/12/14 +** +** The handling of if-then-else depends on the type of both the condition +** (i.e. is it concrete or is it symbolic) and the type of the data +** (i.e. is it a symbolic class that wraps a tree node, is it a structure +** containing them, etc.). Some of the handling will work for any condition, +** any of the data, etc. So far not difficult in a language with multiple +** dispatch including type variables. +** +** However, we are using C++, so there are a few extra hoops to jump +** through. We declare ITEs as a struct containing a static function +** as then we can partially specialise templates of them. +** Specialisations of these are then given when appropriate types are +** introduced. Care must be taken with these to ensure that we don't +** get ambigious template instantiations. +** +*/ + +#ifndef SYMFPU_ITE +#define SYMFPU_ITE + +namespace symfpu { + + template + struct ite; + + // To avoid the need for putting the types *everywhere* we use a + // helper function as C++ can perform type inference for functions + // but not classes. + template + const data ITE (const prop &c, const data &l, const data &r) { + return ite::iteOp(c, l, r); + } + +} + +#endif diff --git a/third-party/symfpu/core/multiply.h b/third-party/symfpu/core/multiply.h new file mode 100644 index 0000000..283e563 --- /dev/null +++ b/third-party/symfpu/core/multiply.h @@ -0,0 +1,156 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** multiply.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 25/08/14 +** +** Multiplication of arbitrary precision floats +** +*/ + +#include "symfpu/core/unpackedFloat.h" +#include "symfpu/core/ite.h" +#include "symfpu/core/rounder.h" +#include "symfpu/core/operations.h" + +#ifndef SYMFPU_MULTIPLY +#define SYMFPU_MULTIPLY + +namespace symfpu { + + // sign == multiplyResult.getSign() normally but not for FMA, thus an argument is needed +template + unpackedFloat addMultiplySpecialCases (const typename t::fpt &format, + const unpackedFloat &left, + const unpackedFloat &right, + const typename t::prop &sign, + const unpackedFloat &multiplyResult) { + typedef typename t::prop prop; + + prop eitherArgumentNan(left.getNaN() || right.getNaN()); + prop generateNan((left.getInf() && right.getZero()) || + (left.getZero() && right.getInf())); + prop isNan(eitherArgumentNan || generateNan); + + prop isInf(left.getInf() || right.getInf()); + + prop isZero(left.getZero() || right.getZero()); + + return ITE(isNan, + unpackedFloat::makeNaN(format), + ITE(isInf, + unpackedFloat::makeInf(format, sign), + ITE(isZero, + unpackedFloat::makeZero(format, sign), + multiplyResult))); + } + +template + unpackedFloat arithmeticMultiply (const typename t::fpt &format, + const unpackedFloat &left, + const unpackedFloat &right) { + typedef typename t::bwt bwt; + typedef typename t::prop prop; + typedef typename t::ubv ubv; + typedef typename t::sbv sbv; + typedef typename t::fpt fpt; + + PRECONDITION(left.valid(format)); + PRECONDITION(right.valid(format)); + + // Compute sign + prop multiplySign(left.getSign() ^ right.getSign()); + + // Multiply the significands + ubv significandProduct(expandingMultiply(left.getSignificand(), right.getSignificand())); + // Optimisation : low bits are not needed apart from the guard and sticky bits + // Optimisation : top bits accurately predict whether re-alignment is needed + + bwt spWidth(significandProduct.getWidth()); + ubv topBit(significandProduct.extract(spWidth - 1, spWidth - 1)); + ubv nextBit(significandProduct.extract(spWidth - 2, spWidth - 2)); + + // Alignment of inputs means at least one of the two MSB is 1 + // i.e. [1,2) * [1,2) = [1,4) + // topBitSet is the likely case + prop topBitSet(topBit.isAllOnes()); + INVARIANT(topBitSet || nextBit.isAllOnes()); + probabilityAnnotation(topBitSet, LIKELY); + + // Re-align + ubv alignedSignificand(conditionalLeftShiftOne(!topBitSet, significandProduct)); // Will not loose information + + // Add up exponents + #if 0 + sbv exponentSum(expandingAdd(left.getExponent(),right.getExponent())); + sbv min(unpackedFloat::minSubnormalExponent(format)); + sbv max(unpackedFloat::maxNormalExponent(format)); + INVARIANT(expandingAdd(min,min) <= exponentSum); + INVARIANT(exponentSum <= expandingAdd(max, max)); + // Optimisation : use the if-then-lazy-else to avoid multiplying for underflow and overflow + // subnormal * subnormal does not need to be evaluated + // may be best done in the rounder along with underflow + #endif + + sbv alignedExponent(expandingAddWithCarryIn(left.getExponent(),right.getExponent(), topBitSet)); + + + // Put back together + unpackedFloat multiplyResult(multiplySign, alignedExponent, alignedSignificand); + + + fpt extendedFormat(format.exponentWidth() + 1, format.significandWidth() * 2); + POSTCONDITION(multiplyResult.valid(extendedFormat)); + + return multiplyResult; + } + + +// Put it all together... +template + unpackedFloat multiply (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &left, + const unpackedFloat &right) { + //typedef typename t::bwt bwt; + //typedef typename t::prop prop; + //typedef typename t::ubv ubv; + //typedef typename t::sbv sbv; + + PRECONDITION(left.valid(format)); + PRECONDITION(right.valid(format)); + + unpackedFloat multiplyResult(arithmeticMultiply(format, left, right)); + + unpackedFloat roundedMultiplyResult(rounder(format, roundingMode, multiplyResult)); + + unpackedFloat result(addMultiplySpecialCases(format, left, right, roundedMultiplyResult.getSign(), roundedMultiplyResult)); + + POSTCONDITION(result.valid(format)); + + return result; + } + + +} + +#endif + diff --git a/third-party/symfpu/core/operations.h b/third-party/symfpu/core/operations.h new file mode 100644 index 0000000..b0b76cd --- /dev/null +++ b/third-party/symfpu/core/operations.h @@ -0,0 +1,585 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** operations.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 15/11/14 +** +** A number of compound operations on bit-vectors. These are default +** implementations to reduce the amount of code that is needed for a +** back-end (and the risk of making a mistake). Back-ends can provide +** their own implementations of these if they can handle them in a +** smarter way than the default. +** +*/ + +#include +#include + +#include "../utils/common.h" + + +#ifndef SYMFPU_OPERATIONS +#define SYMFPU_OPERATIONS + +namespace symfpu { + + /*** Expanding operations ***/ + template + bv expandingAdd (const bv &op1, const bv &op2) { + PRECONDITION(op1.getWidth() == op2.getWidth()); + + bv x(op1.extend(1)); + bv y(op2.extend(1)); + + return x + y; + } + + template + bv expandingAddWithCarryIn (const bv &op1, const bv &op2, const prop &cin) { + PRECONDITION(op1.getWidth() == op2.getWidth()); + + bv x(op1.extend(1)); + bv y(op2.extend(1)); + + bv sum(x + y); + + typename t::bwt w(sum.getWidth()); + bv carry(ITE(cin, bv::one(w), bv::zero(w))); + bv res(sum.modularAdd(carry)); // Modular is safe due to the extension + // (2^n - 1) + (2^n - 1) + 1 == 2^(n+1) - 1 + // -(2^n) + -(2^n) + 1 > 2^(n+1) + return res; + } + + template + bv expandingSubtract (const bv &op1, const bv &op2) { + PRECONDITION(op1.getWidth() == op2.getWidth()); + + bv x(op1.extend(1)); + bv y(op2.extend(1)); + + return x - y; + } + + template + bv expandingMultiply (const bv &op1, const bv &op2) { + typename t::bwt width = op1.getWidth(); + PRECONDITION(width == op2.getWidth()); + + bv x(op1.extend(width)); + bv y(op2.extend(width)); + + return x * y; + } + + + /*** Conditional Operations ***/ + template + bv conditionalIncrement (const prop &p, const bv &b) { + PRECONDITION(IMPLIES(p, b < bv::maxValue(b.getWidth()))); + + typename t::bwt w(b.getWidth()); + bv inc(ITE(p, bv::one(w), bv::zero(w))); + + return b + inc; + } + + template + bv conditionalDecrement (const prop &p, const bv &b) { + PRECONDITION(IMPLIES(p, bv::minValue(b.getWidth()) < b)); + + typename t::bwt w(b.getWidth()); + bv inc(ITE(p, bv::one(w), bv::zero(w))); + + return b - inc; + } + + template + bv conditionalLeftShiftOne (const prop &p, const bv &b) { + typename t::bwt w(b.getWidth()); + PRECONDITION(IMPLIES(p, (b.extract(w - 1, w - 1).isAllZeros()))); + + bv shifted(b.modularLeftShift(bv::one(w))); + return bv(ITE(p, shifted, b)); + } + + template + bv conditionalRightShiftOne (const prop &p, const bv &b) { + typename t::bwt w(b.getWidth()); + // PRECONDITION(IMPLIES(p, (b.extract(0, 0).isAllZeros()))); // Adder uses and compensates for this case. + + bv shifted(b.modularRightShift(bv::one(w))); + return bv(ITE(p, shifted, b)); + } + + template + bv conditionalNegate (const prop &p, const bv &b) { + typename t::bwt w(b.getWidth()); + PRECONDITION(w >= 2); + PRECONDITION(IMPLIES(p, !(b.extract(w - 1, w - 1).isAllOnes() && + b.extract(w - 2, 0).isAllZeros()))); + + return bv(ITE(p, -b, b)); + } + + template + bv abs(const bv &b) { + return conditionalNegate(b < bv::zero(b.getWidth()), b); + } + + + + /*** Probability Annotations ***/ + enum probability { + VERYLIKELY = 100, + LIKELY = 50, + NEUTRAL = 0, + UNLIKELY = -50, + VERYUNLIKELY = -100 + }; + + template + void probabilityAnnotation (const prop &, const probability &) { + // Back-ends can make use of this information if they want + return; + } + + + /*** Max and min ***/ + template + bv max (const bv &op1, const bv &op2) { + return ITE(op1 <= op2, op2, op1); + } + + template + bv min (const bv &op1, const bv &op2) { + return ITE(op1 <= op2, op1, op2); + } + + template + bv collar(const bv &op, const bv &lower, const bv &upper) { + return ITE(op < lower, + lower, + ITE(upper < op, + upper, + op)); + } + + + /*** Unary/Binary operations ***/ + template + bv countLeadingZerosRec (const bv &op, const bwt position, const prop &allPreceedingZeros) { + typename t::bwt w(op.getWidth()); + + PRECONDITION(0 <= position && position < w); + + bv bit(op.extract(position, position)); + + prop isLeadingOne(allPreceedingZeros && (bit.isAllOnes())); + prop continuingZero(allPreceedingZeros && (bit.isAllZeros())); + + if (position == 0) { + return ITE(isLeadingOne, bv(w, w - 1), bv(w, w)); + } else { + return ITE(isLeadingOne, + bv(w, w - (position + 1)), + countLeadingZerosRec(op, position - 1, continuingZero)); + } + } + + template + bv countLeadingZeros (const bv &op) { + typedef typename t::bwt bwt; + typedef typename t::prop prop; + bwt w(op.getWidth()); + + return countLeadingZerosRec(op, w - 1, prop(true)); + } + + // This is sort of the opposite of count trailing 1's (a.k.a. clz(reverse(not(x))) ) + template + bv orderEncode (const bv &op) { + typename t::bwt w(op.getWidth()); + + //PRECONDITION(bv::zero(w) <= op && op <= bv(w, w)); // Not needed as using modular shift + + bv tmp((bv::one(w + 1).modularLeftShift(op.resize(w + 1))).modularDecrement().extract(w-1,0)); + return tmp; + } + + + // The comparison we need to do is + // op.extract(relevantBits - 1, 0) == bv(relevantBits, position + 1) + // bits can be shared between instances of this. + // The following is a dynamic programming style solution. + // HOWEVER : it may not actually give a net saving depending on your application + template + struct fragmentMap { + typedef typename t::bwt bwt; + typedef typename t::prop prop; + + typedef std::pair fragment; + typedef std::map map; + + protected : + const bv &op; + map m; + + prop getComparitorRec(bwt length, bwt value) + { + PRECONDITION(length > 0); + PRECONDITION(bitsToRepresent(value) <= length); + typename map::const_iterator it = m.find(std::make_pair(length, value)); + + if (it != m.end()) { + return it->second; + } else { + bwt leadingBit = bwt(1) << (length - 1); + prop leadingBitIsOne(op.extract(length - 1, length - 1).isAllOnes()); + prop correctComparison((value & leadingBit) ? + leadingBitIsOne : !leadingBitIsOne); + prop *step = NULL; + + if (length == 1) { + step = new prop(correctComparison); + } else { + prop rec(getComparitorRec(length - 1, value & (~leadingBit))); + step = new prop(correctComparison && rec); + } + + prop res(*step); + delete step; + + m.insert(std::make_pair(std::make_pair(length, value), res)); + return res; + } + } + + public : + fragmentMap(const bv &_op) : op(_op) {} + + prop getComparitor(bwt length, bwt value) + { + PRECONDITION(length > 0); + PRECONDITION(bitsToRepresent(value) <= length); + + prop res(getComparitorRec(length, value)); + + POSTCONDITION(bv(res) == (op.extract(length - 1, 0) == bv(length, value))); + return res; + } + }; + + + // A more compact, bitwise implementation of orderEncode for SAT encoding + // Intended to be used in specialisation of orderEncode + template + bv orderEncodeBitwise (const bv &op) { + typedef typename t::bwt bwt; + bwt w(op.getWidth()); + + fragmentMap m(op); + + // If op is too large, then set everything to 1 + bv outOfRange(op >= bv(w, w)); + + // SAND to fill in the remaining bits + bv * working = new bv(outOfRange); + for (bwt i = w; i > 0; --i) { + bwt position = i - 1; // Position in the output bitvectors + bwt relevantBits = bitsToRepresent(position + 1); + INVARIANT(relevantBits > 0); + + //bv activateBit(m.getComparitor(relevantBits, position + 1)); // No more compact and slower + bv activateBit(op.extract(relevantBits - 1, 0) == bv(relevantBits, position + 1)); + bv nextBit(working->extract(0,0) | activateBit); + + bv * tmp = working; + working = new bv(working->append(nextBit)); + delete tmp; + } + + bv output(working->extract(w - 1,0)); + delete working; + + POSTCONDITION(output == (bv::one(w + 1).modularLeftShift(op.resize(w + 1))).modularDecrement().extract(w-1,0)); + + return output; + } + + + /*** Custom shifts ***/ + // 1 if and only if the right shift moves at least one 1 out of the word + template + bv rightShiftStickyBit (const bv &op, const bv &shift) { + bv stickyBit(ITE((orderEncode(shift) & op).isAllZeros(), + bv::zero(op.getWidth()), + bv::one(op.getWidth()))); + + return stickyBit; + } + + + // It is easier to compute along with the shift + template + struct stickyRightShiftResult { + typedef typename t::ubv ubv; + + ubv signExtendedResult; + ubv stickyBit; + + stickyRightShiftResult(const ubv &ser, const ubv &sb) : signExtendedResult(ser), stickyBit(sb) {} + stickyRightShiftResult(const stickyRightShiftResult &old) : signExtendedResult(old.signExtendedResult), stickyBit(old.stickyBit) {} + }; + + + template + stickyRightShiftResult stickyRightShift (const typename t::ubv &input, const typename t::ubv &shiftAmount) { + stickyRightShiftResult res(input.signExtendRightShift(shiftAmount), rightShiftStickyBit(input, shiftAmount)); + + return res; + } + + + template + stickyRightShiftResult stickyRightShiftBitwise (const typename t::ubv &input, const typename t::ubv &shiftAmount) { + typedef typename t::bwt bwt; + typedef typename t::prop prop; + typedef typename t::ubv ubv; + + bwt width(input.getWidth()); + bwt startingPosition(positionOfLeadingOne(width)); + INVARIANT(0 < startingPosition && startingPosition < width); + + // Catch the out of bounds case + PRECONDITION(shiftAmount.getWidth() == width); + prop fullShift(shiftAmount >= ubv(width, width)); + // Note the shiftAmount is treated as unsigned... + + ubv *working = new ubv(input); + prop *stickyBit = new prop(ITE(fullShift, !input.isAllZeros(), prop(false))); + + for (bwt i = startingPosition + 1; i > 0; --i) + { + bwt shiftAmountPosition = i - 1; + + prop shiftEnabled = fullShift || shiftAmount.extract(shiftAmountPosition, shiftAmountPosition).isAllOnes(); + + prop stickyAccumulate(shiftEnabled && !(working->extract((1ULL << shiftAmountPosition) - 1, 0).isAllZeros())); // Would this loose data? + + prop * tmp = stickyBit; + stickyBit = new prop(*stickyBit || stickyAccumulate); + delete tmp; + + + // Note the slightly unexpected sign extension + ubv shifted(working->signExtendRightShift(ubv::one(width) << ubv(width, shiftAmountPosition))); + + ubv * workingTmp = working; + working = new ubv(ITE(shiftEnabled, shifted, *working)); + delete workingTmp; + } + + stickyRightShiftResult res(*working, ubv(*stickyBit).extend(width - 1)); + + delete working; + delete stickyBit; + + POSTCONDITION(res.signExtendedResult == input.signExtendRightShift(shiftAmount)); + POSTCONDITION(res.stickyBit == rightShiftStickyBit(input, shiftAmount)); + + return res; + } + + + + template + struct normaliseShiftResult { + typedef typename t::ubv ubv; + typedef typename t::prop prop; + + ubv normalised; + ubv shiftAmount; + prop isZero; + + normaliseShiftResult(const ubv &n, const ubv &s, const prop &z) : normalised(n), shiftAmount(s), isZero(z) {} + normaliseShiftResult(const normaliseShiftResult &old) : normalised(old.normalised), shiftAmount(old.shiftAmount), isZero(old.isZero) {} + }; + + template + normaliseShiftResult normaliseShift (const typename t::ubv input) { + typedef typename t::bwt bwt; + typedef typename t::prop prop; + typedef typename t::ubv ubv; + + bwt width(input.getWidth()); + bwt startingMask(previousPowerOfTwo(width)); + INVARIANT(startingMask < width); + + // Catch the zero case + prop zeroCase(input.isAllZeros()); + + ubv *working = new ubv(input); + ubv *shiftAmount = NULL; + prop *deactivateShifts = new prop(zeroCase); + + for (bwt i = startingMask; i > 0; i >>= 1) { + prop newDeactivateShifts = *deactivateShifts || working->extract(width-1,width-1).isAllOnes(); + delete deactivateShifts; + deactivateShifts = new prop(newDeactivateShifts); + + ubv mask(ubv::allOnes(i).append(ubv::zero(width - i))); + prop shiftNeeded(!(*deactivateShifts) && (mask & *working).isAllZeros()); + + // Modular is safe because of the mask comparison + ubv shifted(ITE(shiftNeeded, working->modularLeftShift(ubv(width, i)), *working)); + delete working; + working = new ubv(shifted); + + if (shiftAmount == NULL) { + shiftAmount = new ubv(shiftNeeded); + } else { + ubv newShiftAmount = shiftAmount->append(ubv(shiftNeeded)); + delete shiftAmount; + shiftAmount = new ubv(newShiftAmount); + } + } + + normaliseShiftResult res(*working, *shiftAmount, zeroCase); + + delete deactivateShifts; + delete working; + delete shiftAmount; + + POSTCONDITION(res.normalised.extract(width-1,width-1).isAllZeros() == res.isZero); + POSTCONDITION(IMPLIES(res.isZero, res.shiftAmount.isAllZeros())); + + bwt shiftAmountWidth(res.shiftAmount.getWidth()); + bwt widthBits(bitsToRepresent(width)); + POSTCONDITION(shiftAmountWidth == widthBits || + shiftAmountWidth == widthBits - 1); // If width is an exact power of 2 + ubv widthBV(widthBits, width); + POSTCONDITION(res.shiftAmount.matchWidth(widthBV) < widthBV); + + return res; + } + + + /*** Dividers ***/ + template + struct resultWithRemainderBit { + typedef typename t::ubv ubv; + typedef typename t::prop prop; + + ubv result; + prop remainderBit; + + resultWithRemainderBit(const ubv &o, const prop &r) : result(o), remainderBit(r) {} + resultWithRemainderBit(const resultWithRemainderBit &old) : result(old.result), remainderBit(old.remainderBit) {} + }; + + // x and y are fixed-point numbers in the range [1,2) + // Compute o \in [0.5,2), r \in [0,\delta) such that: x = o*y + r + // Return (o, r != 0) + template + resultWithRemainderBit fixedPointDivide (const typename t::ubv &x, const typename t::ubv &y) { + typename t::bwt w(x.getWidth()); + + // Same width and both have MSB ones + PRECONDITION(y.getWidth() == w); + PRECONDITION(x.extract(w - 1, w - 1).isAllOnes()); + PRECONDITION(y.extract(w - 1, w - 1).isAllOnes()); + + typedef typename t::ubv ubv; + + // Not the best way of doing this but pretty universal + ubv ex(x.append(ubv::zero(w - 1))); // x . 2 ^ (w - 1) + ubv ey(y.extend(w - 1)); // y + + ubv div(ex / ey); + ubv rem(ex % ey); + + return resultWithRemainderBit(div.extract(w - 1, 0), !(rem.isAllZeros())); + } + + + // x is a fixed-point number in the range [1,4) with 2/p bits + // Compute o \in [1,sqrt(2)), r \in [0,o*2 + 1) such that x = o*o + r with 1/p bits + // Return (o, r != 0) + template + resultWithRemainderBit fixedPointSqrt (const typename t::ubv &x) { + typedef typename t::bwt bwt; + typedef typename t::ubv ubv; + typedef typename t::prop prop; + + // The default algorithm given here isn't a great one + // However it is simple and has a very simple termination criteria. + // Plus most symbolic back ends will prefer + // o = nondet(), r = nondet(), assert(r < o*2 + 1), assert(x = o*o + r) + + bwt inputWidth(x.getWidth()); + bwt outputWidth(inputWidth - 1); + + // To compare against, we need to pad x to 2/2p + ubv xcomp(x.append(ubv::zero(inputWidth - 2))); + + // Start at 1 + ubv working(ubv::one(outputWidth) << ubv(outputWidth, outputWidth - 1)); + + bwt location; + for (location = outputWidth - 1; location > 0; --location) { // Offset by 1 for easy termination + ubv shift(ubv(outputWidth, location - 1)); + + ubv candidate(working | (ubv::one(outputWidth) << shift)); + + prop addBit(expandingMultiply(candidate, candidate) <= xcomp); + + working = working | (ubv(addBit).extend(outputWidth - 1) << shift); + } + + return resultWithRemainderBit(working, !(expandingMultiply(working, working) == xcomp)); + } + + // One step of a divider + // Here the "remainder bit" is actual the result bit and + // The result is the remainder + template + resultWithRemainderBit divideStep (const typename t::ubv &x, const typename t::ubv &y) { + typedef typename t::bwt bwt; + typedef typename t::ubv ubv; + typedef typename t::prop prop; + + bwt xWidth(x.getWidth()); + bwt yWidth(y.getWidth()); + + PRECONDITION(xWidth == yWidth); + PRECONDITION(yWidth >= 2); + PRECONDITION(y.extract(yWidth - 2, yWidth - 2).isAllOnes()); // Assume y is aligned + + prop canSubtract(x >= y); + ubv sub(x.modularAdd(y.modularNegate())); // TODO : modular subtract or better + ubv step(ITE(canSubtract, sub, x)); + + return resultWithRemainderBit(step << ubv::one(xWidth), canSubtract); + } +} + +#endif diff --git a/third-party/symfpu/core/packing.h b/third-party/symfpu/core/packing.h new file mode 100644 index 0000000..417e038 --- /dev/null +++ b/third-party/symfpu/core/packing.h @@ -0,0 +1,177 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** packing.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 03/06/14 +** +** Algorithms for converting from a packed float (a bit vector) into +** the working, unpacked float format. Should be instantiated with a +** traits structure from one of the baseTypes/ implementations. +** +*/ + +#include "symfpu/core/unpackedFloat.h" + +#ifndef SYMFPU_PACKING +#define SYMFPU_PACKING + +namespace symfpu { + + template + unpackedFloat unpack (const typename t::fpt format, const typename t::ubv &packedFloat) { + typedef typename t::bwt bwt; + typedef typename t::prop prop; + typedef typename t::ubv ubv; + typedef typename t::sbv sbv; + + bwt pWidth = format.packedWidth(); + bwt exWidth = format.packedExponentWidth(); + bwt sigWidth = format.packedSignificandWidth(); + + PRECONDITION(packedFloat.getWidth() == pWidth); + + // Extract + ubv packedSignificand(packedFloat.extract(sigWidth - 1, 0)); + ubv packedExponent(packedFloat.extract(sigWidth + exWidth - 1, sigWidth)); + prop sign(packedFloat.extract(pWidth - 1, sigWidth + exWidth).isAllOnes()); + + // Prepare the normal and subnormal cases + bwt unpackedExWidth = unpackedFloat::exponentWidth(format); + bwt unpackedSigWidth = unpackedFloat::significandWidth(format); + + INVARIANT(unpackedExWidth > exWidth); // To avoid overflow + sbv biasedExponent(packedExponent.extend(unpackedExWidth - exWidth).toSigned() - unpackedFloat::bias(format)); + // Optimisation : both the normal and subnormal paths subtract a constant + // from the exponent as the last step (bias and minNormalExponent respectively) + + ubv significandWithLeadingZero(packedSignificand.extend(unpackedSigWidth - sigWidth)); + ubv significandWithLeadingOne(unpackedFloat::leadingOne(unpackedFloat::significandWidth(format)) | significandWithLeadingZero); + + unpackedFloat ufNormal(sign, biasedExponent, significandWithLeadingOne); + unpackedFloat ufSubnormalBase(sign, unpackedFloat::minNormalExponent(format), significandWithLeadingZero); + + // Optimisation : right shift the significand by one if subnormal + // and then set the carry in when you add to the exponent. + // May be sufficient to just assert that it has a leading zero + + + // Analyse + prop zeroExponent(packedExponent.isAllZeros()); + prop onesExponent(packedExponent.isAllOnes()); + prop zeroSignificand(significandWithLeadingZero.isAllZeros()); // Shared with normaliseUp + + // Identify the cases + prop isZero(zeroExponent && zeroSignificand); + prop isSubnormal(zeroExponent && !zeroSignificand); + prop isNormal(!zeroExponent && !onesExponent); + prop isInf(onesExponent && zeroSignificand); + prop isNaN(onesExponent && !zeroSignificand); + + INVARIANT(isZero || isSubnormal || isNormal || isInf || isNaN); + + probabilityAnnotation(isSubnormal, UNLIKELY); + + // Splice together + unpackedFloat uf(ITE(isNaN, + unpackedFloat::makeNaN(format), + ITE(isInf, + unpackedFloat::makeInf(format, sign), + ITE(isZero, + unpackedFloat::makeZero(format, sign), + ITE(!isSubnormal, + ufNormal, + ufSubnormalBase.normaliseUp(format) ))))); + + POSTCONDITION(uf.valid(format)); + + return uf; + } + + + template + typename t::ubv pack (const typename t::fpt &format, const unpackedFloat &uf) { + typedef typename t::bwt bwt; + typedef typename t::prop prop; + typedef typename t::ubv ubv; + typedef typename t::sbv sbv; + + PRECONDITION(uf.valid(format)); + + // Sign + ubv packedSign(uf.getSign()); + + // Exponent + bwt packedExWidth = format.packedExponentWidth(); + + prop inNormalRange(uf.inNormalRange(format, prop(true))); + INVARIANT(inNormalRange || uf.inSubnormalRange(format, prop(true))); // Default values ensure this. + //prop inSubnormalRange(uf.inSubnormalRange(format)); // Allowing this optimisation + prop inSubnormalRange(!inNormalRange); + + probabilityAnnotation(inNormalRange, LIKELY); + probabilityAnnotation(inSubnormalRange, UNLIKELY); + + sbv biasedExp(uf.getExponent() + unpackedFloat::bias(format)); + // Will be correct for normal values only, subnormals may still be negative. + ubv packedBiasedExp(biasedExp.toUnsigned().extract(packedExWidth - 1,0)); + + ubv maxExp(ubv::allOnes(packedExWidth)); + ubv minExp(ubv::zero(packedExWidth)); + + prop hasMaxExp(uf.getNaN() || uf.getInf()); + prop hasMinExp(uf.getZero() || inSubnormalRange); + prop hasFixedExp(hasMaxExp || hasMinExp); + + ubv packedExp(ITE(hasFixedExp, + ITE(hasMaxExp, maxExp, minExp), + packedBiasedExp)); + + + // Significand + bwt packedSigWidth = format.packedSignificandWidth(); + ubv unpackedSignificand(uf.getSignificand()); + + INVARIANT(packedSigWidth == unpackedSignificand.getWidth() - 1); + ubv dropLeadingOne(unpackedSignificand.extract(packedSigWidth - 1,0)); + ubv correctedSubnormal((unpackedSignificand >> (uf.getSubnormalAmount(format).toUnsigned().matchWidth(unpackedSignificand))).extract(packedSigWidth - 1,0)); + + prop hasFixedSignificand(uf.getNaN() || uf.getInf() || uf.getZero()); + + ubv packedSig(ITE(hasFixedSignificand, + ITE(uf.getNaN(), + unpackedFloat::nanPattern(packedSigWidth), + ubv::zero(packedSigWidth)), + ITE(inNormalRange, + dropLeadingOne, + correctedSubnormal))); + + + // Finish up + ubv packed(packedSign.append(packedExp).append(packedSig)); + + POSTCONDITION(packed.getWidth() == format.packedWidth()); + + return packed; + } + +} + +#endif diff --git a/third-party/symfpu/core/remainder.h b/third-party/symfpu/core/remainder.h new file mode 100644 index 0000000..ae91691 --- /dev/null +++ b/third-party/symfpu/core/remainder.h @@ -0,0 +1,262 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** remainder.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 14/12/16 +** +** Computing the IEEE-754 remainder of arbitrary precision floats +** +*/ + +#include "symfpu/core/unpackedFloat.h" +#include "symfpu/core/ite.h" +#include "symfpu/core/rounder.h" +#include "symfpu/core/operations.h" +#include "symfpu/core/add.h" +#include "symfpu/core/sign.h" + + +#ifndef SYMFPU_REMAINDER +#define SYMFPU_REMAINDER + +namespace symfpu { + +template + unpackedFloat addRemainderSpecialCases (const typename t::fpt &format, + const unpackedFloat &left, + const unpackedFloat &right, + const unpackedFloat &remainderResult) { + typedef typename t::prop prop; + + prop eitherArgumentNan(left.getNaN() || right.getNaN()); + prop generateNan(left.getInf() || right.getZero()); + prop isNan(eitherArgumentNan || generateNan); + + prop passThrough((!(left.getInf() || left.getNaN()) && right.getInf()) || + left.getZero()); + + return ITE(isNan, + unpackedFloat::makeNaN(format), + ITE(passThrough, + left, + remainderResult)); + } + +/* Let left = x*2^e, right = y*2^f, x \in [1,2), y \in [1,2) + * x/y \in (0.5,2) x > y x/y \in (1,2) x < y (0.5,1) + * + * rem = x*2^e - (y*2^f * int((x*2^e) / (y*2^f))) + * = x*2^e - (y*2^f * int((x/y) * 2^{e-f})) + * = (x*2^{e-f} - (y * int((x/y) * 2^{e-f}))) * 2^f + * + * + * If e - f > 0 + * = (x*2^{e-f} - (y * int((x*2^{e-f})/y)) * 2^f + * + * + * If e - f == 0 + * = (x - (y * int((x/y) ))) * 2^f + * = ITTE(x ?= y, + * (x - (y * int[guard=1,sticky=1])) * 2^f + * (x - y) * 2^f, + * ...) + * = ITTE(x ?= y, + * (x - (y * int[guard=1,sticky=1])) * 2^f + * left - right, + * ...) + * + * + * If e - f == -1 + * = (x*2^{-1} - (y * int((x/y) * 2^{-1 }))) * 2^f + * = ITTE(x ?= y, + * (x*2^{-1} - (y * int[guard=0,sticky=1])) * 2^f + * (x*2^{-1} - (y * int[guard=1,sticky=0])) * 2^f + * (x*2^{-1} - (y * int[guard=1,sticky=1])) * 2^f + * + * If e - f <= -2 + * = (x*2^{e-f} - (y * int[guard=0,sticky=1])) * 2^f + * = ITE(int[guard=0,sticky=1], + * x*2^e - y*2^f, + * left) + * = ITE(int[guard=0,sticky=1], + * left - right, + * left) + * + */ + +// Divide for max(e - f, 0) cycles +// The equal case, if you divide you use to extract the even bit of n, also save the rem. +// Then one more cycle for the guard bit +// Use that remainder to work out the sticky bit +// Round and either subtract or not from saved rem +// Output at 2^f + +template + unpackedFloat arithmeticRemainder (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &left, + const unpackedFloat &right) { + typedef typename t::bwt bwt; + typedef typename t::prop prop; + typedef typename t::ubv ubv; + typedef typename t::sbv sbv; + //typedef typename t::fpt fpt; + + PRECONDITION(left.valid(format)); + PRECONDITION(right.valid(format)); + + // Compute sign + prop remainderSign(left.getSign()); + + + // Compute exponent difference + sbv exponentDifference(expandingSubtract(left.getExponent(), right.getExponent())); + bwt edWidth(exponentDifference.getWidth()); + + // Extend for divide steps + ubv lsig(left.getSignificand().extend(1)); + ubv rsig(right.getSignificand().extend(1)); + + + ubv first(divideStep(lsig,rsig).result); + ubv *running = new ubv(first); // To avoid running out of stack space loop with a pointer + + bwt maxDifference = unpackedFloat::maximumExponentDifference(format); + for (bwt i = maxDifference - 1; i > 0; i--) { + prop needPrevious(exponentDifference > sbv(edWidth, i)); + probabilityAnnotation(needPrevious, (i > (maxDifference / 2)) ? VERYUNLIKELY : UNLIKELY); + + ubv r(ITE(needPrevious, *running, lsig)); + delete running; // We assume the value / reference has been transfered to ITE + running = new ubv(divideStep(r, rsig).result); + } + + // The zero exponent difference case is a little different + // as we need the result bit for the even flag + // and the actual result for the final + prop lsbRoundActive(exponentDifference > -sbv::one(edWidth)); // i.e. >= 0 + + prop needPrevious(exponentDifference > sbv::zero(edWidth)); + probabilityAnnotation(needPrevious, UNLIKELY); + + ubv r0(ITE(needPrevious, *running, lsig)); + delete running; + resultWithRemainderBit dsr(divideStep(r0, rsig)); + + prop integerEven(!lsbRoundActive || !dsr.remainderBit); // Note negation of guardBit + + + // The same to get the guard flag + prop guardRoundActive(exponentDifference > -sbv(edWidth,2)); // i.e. >= -1 + + ubv rm1(ITE(lsbRoundActive, dsr.result, lsig)); + resultWithRemainderBit dsrg(divideStep(rm1, rsig)); + + prop guardBit(guardRoundActive && dsrg.remainderBit); + + prop stickyBit(!ITE(guardRoundActive, + dsrg.result, + lsig).isAllZeros()); + + + // The base result if lsbRoundActive + unpackedFloat reconstruct(remainderSign, + right.getExponent(), + dsr.result.extract(lsig.getWidth() - 1,1)); // dsr shifts right as last action so is safe + + + probabilityAnnotation(needPrevious, UNLIKELY); // Perhaps stretching it a bit but good for approximation + unpackedFloat candidateResult(ITE(lsbRoundActive, + reconstruct.normaliseUpDetectZero(format), + left)); + + // The final subtract is a little different as previous ones were + // guaranteed to be positive + // TODO : This could be improved as these don't need special cases, etc. + + // From the rounding of the big integer multiple + prop bonusSubtract(roundingDecision(roundingMode, + remainderSign, + integerEven, + guardBit, + stickyBit, + prop(false))); + probabilityAnnotation(bonusSubtract, UNLIKELY); // Again, more like 50/50 + + // The big integer has sign left.getSign() ^ right.getSign() so we subtract something of left.getSign(). + // For the integer part we handle this by working with absolutes (ignoring the sign) and + // adding it back in at the end. + // However for the correction for the rounded part we need to take it into account + unpackedFloat signCorrectedRight(right, left.getSign()); + unpackedFloat remainderResult(ITE(bonusSubtract, + add(format, + roundingMode, + candidateResult, + signCorrectedRight, + false), + candidateResult)); + + // TODO : fast path if first.isAllZeros() + + POSTCONDITION(remainderResult.valid(format)); + + return remainderResult; + } + + +// Put it all together... +template + unpackedFloat remainderWithRounding (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &left, + const unpackedFloat &right) { + //typedef typename t::bwt bwt; + //typedef typename t::prop prop; + //typedef typename t::ubv ubv; + //typedef typename t::sbv sbv; + + PRECONDITION(left.valid(format)); + PRECONDITION(right.valid(format)); + + unpackedFloat remainderResult(arithmeticRemainder(format, roundingMode, left, right)); + + //unpackedFloat result(addRemainderSpecialCases(format, left, right, roundedRemainderResult)); + unpackedFloat result(addRemainderSpecialCases(format, left, right, remainderResult)); + + POSTCONDITION(result.valid(format)); + + return result; + } + +// IEEE-754 remainder always uses round to nearest, ties to even +template + unpackedFloat remainder (const typename t::fpt &format, + const unpackedFloat &left, + const unpackedFloat &right) { + + return remainderWithRounding(format, t::RNE(), left, right); + } + + +} + +#endif + diff --git a/third-party/symfpu/core/rounder.h b/third-party/symfpu/core/rounder.h new file mode 100644 index 0000000..de33d52 --- /dev/null +++ b/third-party/symfpu/core/rounder.h @@ -0,0 +1,698 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** rounder.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 26/08/14 +** +** Rounding arbitrary length unpacked floats back to their correct length. +** +*/ + +/* + * Rounder Ideas + * + * - get the rounder to handle things with 1 or 2 possible leading + * 0's rather than normalise before and after rounding. + * Subnormal rounding should ideally be temporarily denormalised to + * avoid the expensive variable position rounding. + * + * 1. Take exponent and add a 0 at the start to deal with overflow. + * (may not be needed if the exponent has already been extended due + * to subnormals, addition, etc.) + * 2. For each of the possible positions of the binary point, produce + * an incremented version and round and sticky bits. + * (given the alignment is known, may be able to just pick how much + * to increment by and then increment once.) + * 3. The leading zeros of the original exponent pick which set of + * round and sticky to use. Thus pick which of the incremented / + * normal to use and align apart from 1. + * 4. Finally align, most of the information needed for this will be + * already known. + * (Catch -- this can introduce diamonds) + * + * - can fold the increment from the rounder into the circuitry / + * last round of accumulation. + * In fact, can take this further. a + b + 1 takes the same + * circuitry as a + b. a * b + 1 shares most of the circuit with + * a * b and neither of them require a sign extension. Extending + * this to a + b + k and a * b + k for positional rounding is an + * open question. + * + * - add a 'non-deterministic rounding' mode for underapproximation. + * + * - add 'round-to-odd' and 'round-away-from-zero' mode + * + * - add 'flush subnormals to zero' option + * + * - Rather than increment and re-align, take all but the top bit of the + * significand, concatinate on to the exponent and then increment. + * This is effectively using the ordering trick for packed rounding. + * + * - The sticky bit should be a flag rather than concatinated on to the + * number to make arithmetic reasoning easier. + * (Conversely ... having it as bits is better for semi-normalised things) + * + * - Specialised rounders + * Additive + * Only one overflow increment is possible, even for a + b + 1 + * When a subnormal number if generated, it is exact and thus you + * don't need to think about positional rounding for the + * subnormals. + * No need to check for underflow to zero for similar reasons. + * The rounder for the near path can be even more specialised as + * the sticky bit is always 0 and it can't overflow. + * Can only overflow if it is an effective add. + * + * Multiplicative + * May be able to increment without overflow. + * It only seems to be possible for subnormals. + * Don't need to extend the exponent to increment when normalising. + * Can use injection bits during the multiplication reduction tree, + * the problem with the carry up can be fixed afterwards with an + * increment (add for subnormal) or by spotting the carry up during + * the reduction. + * + * FMA + * More like multiply. + */ + + +#include "symfpu/core/operations.h" +#include "symfpu/core/unpackedFloat.h" + +#ifndef SYMFPU_ROUNDER +#define SYMFPU_ROUNDER + +namespace symfpu { + + // The final reconstruction of the rounded result + // Handles the overflow and underflow conditions + template + unpackedFloat rounderSpecialCases (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &roundedResult, + const typename t::prop &overflow, + const typename t::prop &underflow, + const typename t::prop &isZero) + { + typedef typename t::prop prop; + typedef typename t::ubv ubv; + + /*** Underflow and overflow ***/ + + // On overflow either return inf or max + prop returnInf(roundingMode == t::RNE() || + roundingMode == t::RNA() || + (roundingMode == t::RTP() && !roundedResult.getSign()) || + (roundingMode == t::RTN() && roundedResult.getSign())); + probabilityAnnotation(returnInf, LIKELY); // Inf is more likely than max in most application scenarios + + // On underflow either return 0 or minimum subnormal + prop returnZero(roundingMode == t::RNE() || + roundingMode == t::RNA() || + roundingMode == t::RTZ() || + (roundingMode == t::RTP() && roundedResult.getSign()) || + (roundingMode == t::RTN() && !roundedResult.getSign())); + probabilityAnnotation(returnZero, LIKELY); // 0 is more likely than min in most application scenarios + + + + /*** Reconstruct ***/ + unpackedFloat inf(unpackedFloat::makeInf(format, roundedResult.getSign())); + unpackedFloat max(roundedResult.getSign(), unpackedFloat::maxNormalExponent(format), ubv::allOnes(unpackedFloat::significandWidth(format))); + unpackedFloat min(roundedResult.getSign(), unpackedFloat::minSubnormalExponent(format), unpackedFloat::leadingOne(unpackedFloat::significandWidth(format))); + unpackedFloat zero(unpackedFloat::makeZero(format, roundedResult.getSign())); + + unpackedFloat result(ITE(isZero, + zero, + ITE(underflow, + ITE(returnZero, zero, min), + ITE(overflow, + ITE(returnInf, inf, max), + roundedResult)))); + return result; + } + + + // Decide whether to round up or not + template + typename t::prop roundingDecision (const typename t::rm &roundingMode, + const typename t::prop &sign, + const typename t::prop &significandEven, + const typename t::prop &guardBit, + const typename t::prop &stickyBit, + const typename t::prop &knownRoundDown) { + typedef typename t::prop prop; + + prop roundUpRNE(roundingMode == t::RNE() && guardBit && (stickyBit || !significandEven)); + prop roundUpRNA(roundingMode == t::RNA() && guardBit); + prop roundUpRTP(roundingMode == t::RTP() && !sign && (guardBit || stickyBit)); + prop roundUpRTN(roundingMode == t::RTN() && sign && (guardBit || stickyBit)); + prop roundUpRTZ(roundingMode == t::RTZ() && prop(false)); + prop roundUp(!knownRoundDown && + (roundUpRNE || roundUpRNA || roundUpRTP || roundUpRTN || roundUpRTZ)); + + return roundUp; + } + + + + template + struct significandRounderResult{ + typename t::ubv significand; + typename t::prop incrementExponent; + + significandRounderResult(const typename t::ubv &sig, const typename t::prop &inc) : + significand(sig), incrementExponent(inc) {} + + significandRounderResult(const significandRounderResult &old) : + significand(old.significand), incrementExponent(old.incrementExponent) {} + }; + + // Handles rounding the significand to a fixed width + // If knownRoundDown is true should simplify to just extract + // Not quite the same as either rounder so can't quite be refactored + template + significandRounderResult fixedPositionRound(const typename t::rm &roundingMode, + const typename t::prop &sign, + const typename t::ubv &significand, + const typename t::bwt &targetWidth, + const typename t::prop &knownLeadingOne, + const typename t::prop &knownRoundDown) { + typedef typename t::bwt bwt; + typedef typename t::prop prop; + typedef typename t::ubv ubv; + + bwt sigWidth(significand.getWidth()); + PRECONDITION(sigWidth >= targetWidth + 2); + // Extract + ubv extractedSignificand(significand.extract(sigWidth - 1, sigWidth - targetWidth).extend(1)); // extended to catch the overflow + + prop significandEven(extractedSignificand.extract(0,0).isAllZeros()); + + + // Normal guard and sticky bits + bwt guardBitPosition(sigWidth - (targetWidth + 1)); + prop guardBit(significand.extract(guardBitPosition, guardBitPosition).isAllOnes()); + + prop stickyBit(!significand.extract(guardBitPosition - 1,0).isAllZeros()); + + // Rounding decision + prop roundUp(roundingDecision(roundingMode, sign, significandEven, + guardBit, stickyBit, knownRoundDown)); + + // Conditional increment + ubv roundedSignificand(conditionalIncrement(roundUp, extractedSignificand)); + + ubv overflowBit(roundedSignificand.extract(targetWidth, targetWidth) & ubv(roundUp)); + ubv carryUpMask((overflowBit | ubv(knownLeadingOne)).append(ubv::zero(targetWidth - 1))); // Cheaper than conditional shift + + // Build result + significandRounderResult result(roundedSignificand.extract(targetWidth-1,0) | carryUpMask, + overflowBit.isAllOnes()); + + return result; + } + + + // Handles rounding the significand to a fixed width + // If knownRoundDown is true should simplify to just mask + // Not quite the same as either rounder so can't quite be refactored + template + significandRounderResult variablePositionRound(const typename t::rm &roundingMode, + const typename t::prop &sign, + const typename t::ubv &significand, + const typename t::ubv &roundPosition, + const typename t::prop &knownLeadingOne, + const typename t::prop &knownRoundDown) { + typedef typename t::bwt bwt; + typedef typename t::prop prop; + typedef typename t::ubv ubv; + + bwt sigWidth(significand.getWidth()); + + // Set up significand + // Round-up-from-sticky bit and overflow bit at MSB, (fall-back) guard and sticky bits at LSB + ubv expandedSignificand(significand.extend(2).append(ubv::zero(2))); + bwt exsigWidth(expandedSignificand.getWidth()); + + + // Identify the increment, guard and sticky bits + ubv incrementLocation(ubv(exsigWidth, (0x1U << 2U)) << roundPosition.matchWidth(expandedSignificand)); + ubv guardLocation(incrementLocation >> ubv::one(exsigWidth)); + ubv stickyLocations(guardLocation.decrement()); + + prop significandEven((incrementLocation & expandedSignificand).isAllZeros()); + prop guardBit(!(guardLocation & expandedSignificand).isAllZeros()); + prop stickyBit(!(stickyLocations & expandedSignificand).isAllZeros()); + + // Rounding decision + prop roundUp(roundingDecision(roundingMode, sign, significandEven, + guardBit, stickyBit, knownRoundDown)); + + // Conditional increment + ubv roundedSignificand(expandedSignificand + ITE(roundUp, + incrementLocation, + ubv::zero(exsigWidth))); + + // Mask out rounded bits and extract + ubv maskedRoundedSignificand(roundedSignificand & (~(stickyLocations << ubv::one(exsigWidth)))); // LSB is wrong but gets cut + + ubv roundUpFromSticky(roundedSignificand.extract(exsigWidth - 1, exsigWidth - 1)); // Only true when rounding up and whole significand is sticky + ubv overflowBit(roundedSignificand.extract(exsigWidth - 2, exsigWidth - 2)); + ubv maskTrigger((roundUpFromSticky | overflowBit) & ubv(roundUp)); + ubv carryUpMask((maskTrigger | ubv(knownLeadingOne)).append(ubv::zero(sigWidth - 1))); // Cheaper than conditional shift + + // Build result + significandRounderResult result(maskedRoundedSignificand.extract(sigWidth + 1, 2) | carryUpMask, + maskTrigger.isAllOnes()); + + return result; + } + + + + // Allows various of the key branches in the rounder to be fixed / removed + // using information that is known from the operation in which the rounder + // is used. Setting these to false gives the usual rounder. + template + struct customRounderInfo { + typedef typename t::prop prop; + + prop noOverflow; + prop noUnderflow; + prop exact; // Significand does not need to be changed + prop subnormalExact; // If the value is subnormal then it is exact + prop noSignificandOverflow; // Incrementing the significand will not cause overflow + //prop stickyIsZero; // Can be fixed in the number directly + + customRounderInfo (const prop &noO, const prop &noU, + const prop &e, const prop &sE, + const prop &nSO) : + noOverflow(noO), noUnderflow(noU), exact(e), + subnormalExact(sE), noSignificandOverflow(nSO) {} + }; + +template + unpackedFloat customRounder (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &uf, + const customRounderInfo &known) { + + typedef typename t::bwt bwt; + typedef typename t::prop prop; + typedef typename t::ubv ubv; + typedef typename t::sbv sbv; + + //PRECONDITION(uf.valid(format)); + // Not a precondition because + // 1. Exponent and significand may be extended. + // 2. Their values may also be outside of the correct range. + // + // However some thing do hold: + // 1. Leading bit of the significant is 1 (if you want to get a meaningful answer) + // (if not, a cancellation on the near path of add can cause + // this, but the result will not be used, so it can be incorrect) + ubv psig(uf.getSignificand()); + bwt sigWidth(psig.getWidth()); + //PRECONDITION(psig.extract(sigWidth-1, sigWidth-1).isAllOnes()); + ubv sig(psig | unpackedFloat::leadingOne(sigWidth)); + + // 2. Must have round and sticky bits + bwt targetSignificandWidth(unpackedFloat::significandWidth(format)); + PRECONDITION(sigWidth >= targetSignificandWidth + 2); + + // 3. Must have at least enough exponent bits + sbv exp(uf.getExponent()); + bwt expWidth(exp.getWidth()); + bwt targetExponentWidth(unpackedFloat::exponentWidth(format)); + PRECONDITION(expWidth >= targetExponentWidth); + + // Also, do not round special values. + // Note that this relies on these having default values and + // the code that calls the rounder constructing uf from parts. + //PRECONDITION(!uf.getNaN()); + //PRECONDITION(!uf.getInf()); + //PRECONDITION(!uf.getZero()); + // The safe choice of default values means this should work OK + + + + /*** Early underflow and overflow detection ***/ + bwt exponentExtension(expWidth - targetExponentWidth); + prop earlyOverflow(exp > unpackedFloat::maxNormalExponent(format).extend(exponentExtension)); + prop earlyUnderflow(exp < unpackedFloat::minSubnormalExponent(format).extend(exponentExtension).decrement()); + // Optimisation : if the precondition on sigWidth and targetSignificandWidth is removed + // then can change to: + // exponent >= minSubnormalExponent - 1 + // && sigWidth > targetSignificandBits + probabilityAnnotation(earlyOverflow, UNLIKELY); // (over,under)flows are generally rare events + probabilityAnnotation(earlyUnderflow, UNLIKELY); + + prop potentialLateOverflow(exp == unpackedFloat::maxNormalExponent(format).extend(exponentExtension)); + prop potentialLateUnderflow(exp == unpackedFloat::minSubnormalExponent(format).extend(exponentExtension).decrement()); + probabilityAnnotation(potentialLateOverflow, VERYUNLIKELY); + probabilityAnnotation(potentialLateUnderflow, VERYUNLIKELY); + + + + /*** Normal or subnormal rounding? ***/ + prop normalRoundingRange(exp >= unpackedFloat::minNormalExponent(format).extend(exponentExtension)); + probabilityAnnotation(normalRoundingRange, LIKELY); + prop normalRounding(normalRoundingRange || known.subnormalExact); + + + + /*** Round to correct significand. ***/ + // TODO: Unhack below line + ubv extractedSignificand(sig.extract(sigWidth - 1, sigWidth - targetSignificandWidth).extend(2)); // extended to catch the overflow + + // Normal guard and sticky bits + bwt guardBitPosition(sigWidth - (targetSignificandWidth + 1)); + prop guardBit(sig.extract(guardBitPosition, guardBitPosition).isAllOnes()); + + prop stickyBit(!sig.extract(guardBitPosition - 1,0).isAllZeros()); + + + // For subnormals, locating the guard and stick bits is a bit more involved + //sbv subnormalAmount(uf.getSubnormalAmount(format)); // Catch is, uf isn't in the given format, so this doesn't work + sbv subnormalAmount(expandingSubtract(unpackedFloat::minNormalExponent(format).matchWidth(exp),exp)); + INVARIANT((subnormalAmount < sbv(expWidth + 1, sigWidth - 1)) || earlyUnderflow); + // Note that this is negative if normal, giving a full subnormal mask + // but the result will be ignored (see the next invariant) + + ubv subnormalShiftPrepared(subnormalAmount.toUnsigned().matchWidth(extractedSignificand)); + + // Compute masks + ubv subnormalMask(orderEncode(subnormalShiftPrepared)); // Invariant implies this if all ones, it will not be used + ubv subnormalStickyMask(subnormalMask >> ubv::one(targetSignificandWidth + 2)); // +1 as the exponent is extended + // TODO: unhack above line as well + + // Apply + ubv subnormalMaskedSignificand(extractedSignificand & (~subnormalMask)); + ubv subnormalMaskRemoved(extractedSignificand & subnormalMask); + // Optimisation : remove the masking with a single orderEncodeBitwise style construct + + prop subnormalGuardBit(!(subnormalMaskRemoved & (~subnormalStickyMask)).isAllZeros()); + prop subnormalStickyBit(guardBit || stickyBit || + !((subnormalMaskRemoved & subnormalStickyMask).isAllZeros())); + + + // TODO: unhack below line + ubv subnormalIncrementAmount((subnormalMask.modularLeftShift(ubv::one(targetSignificandWidth + 2))) & ~subnormalMask); // The only case when this looses info is earlyUnderflow + INVARIANT(IMPLIES(subnormalIncrementAmount.isAllZeros(), earlyUnderflow || normalRounding)); + + + // Have to choose the right one dependent on rounding mode + prop choosenGuardBit(ITE(normalRounding, guardBit, subnormalGuardBit)); + prop choosenStickyBit(ITE(normalRounding, stickyBit, subnormalStickyBit)); + + prop significandEven(ITE(normalRounding, + extractedSignificand.extract(0,0).isAllZeros(), + ((extractedSignificand & subnormalIncrementAmount).isAllZeros()))); + prop roundUp(roundingDecision(roundingMode, uf.getSign(), significandEven, + choosenGuardBit, choosenStickyBit, + known.exact || (known.subnormalExact && !normalRoundingRange))); + + + // Perform the increment as needed + ubv leadingOne(unpackedFloat::leadingOne(targetSignificandWidth)); + // Not actually true, consider minSubnormalExponent - 1 : not an early underfow and empty significand + //INVARIANT(!(subnormalMaskedSignificand & leadingOne).isAllZeros() || + // earlyUnderflow); // This one really matters, it means only the early underflow path is wrong + + + // Convert the round up flag to a mask + ubv normalRoundUpAmount(ubv(roundUp).matchWidth(extractedSignificand)); + // TODO: unhack below line + ubv subnormalRoundUpMask(ubv(roundUp).append(ubv::zero(targetSignificandWidth + 1)).signExtendRightShift(ubv(targetSignificandWidth + 2, targetSignificandWidth))); + ubv subnormalRoundUpAmount(subnormalRoundUpMask & subnormalIncrementAmount); + + ubv rawRoundedSignificand((ITE(normalRounding, + extractedSignificand, + subnormalMaskedSignificand) + + + ITE(normalRounding, + normalRoundUpAmount, + subnormalRoundUpAmount))); + + // We might have lost the leading one, if so, re-add and note that we need to increment the significand + prop significandOverflow(rawRoundedSignificand.extract(targetSignificandWidth, targetSignificandWidth).isAllOnes()); + INVARIANT(IMPLIES(significandOverflow, roundUp)); + + ubv extractedRoundedSignificand(rawRoundedSignificand.extract(targetSignificandWidth - 1, 0)); + ubv roundedSignificand(extractedRoundedSignificand | leadingOne); + INVARIANT(IMPLIES(significandOverflow, extractedRoundedSignificand.isAllZeros())); + + + + + /*** Round to correct exponent. ***/ + + // The extend is almost certainly unnecessary (see specialised rounders) + sbv extendedExponent(exp.extend(1)); + + prop incrementExponentNeeded(roundUp && significandOverflow); // The roundUp is implied but kept for signal forwarding + probabilityAnnotation(incrementExponentNeeded, VERYUNLIKELY); + prop incrementExponent(!known.noSignificandOverflow && incrementExponentNeeded); + INVARIANT(IMPLIES(known.noSignificandOverflow, !incrementExponentNeeded)); + + sbv correctedExponent(conditionalIncrement(incrementExponent, extendedExponent)); + + // Track overflows and underflows + sbv maxNormal(unpackedFloat::maxNormalExponent(format).matchWidth(correctedExponent)); + sbv minSubnormal(unpackedFloat::minSubnormalExponent(format).matchWidth(correctedExponent)); + + sbv correctedExponentInRange(collar(correctedExponent, minSubnormal, maxNormal)); + + + // This can over and underflow but these values will not be used + bwt currentExponentWidth(correctedExponentInRange.getWidth()); + sbv roundedExponent(correctedExponentInRange.contract(currentExponentWidth - targetExponentWidth)); + + + + /*** Finish ***/ + + prop computedOverflow(potentialLateOverflow && incrementExponentNeeded); + prop computedUnderflow(potentialLateUnderflow && !incrementExponentNeeded); + probabilityAnnotation(computedOverflow, UNLIKELY); + probabilityAnnotation(computedUnderflow, UNLIKELY); + + prop lateOverflow(!earlyOverflow && computedOverflow); + prop lateUnderflow(!earlyUnderflow && computedUnderflow); + probabilityAnnotation(lateOverflow, VERYUNLIKELY); + probabilityAnnotation(lateUnderflow, VERYUNLIKELY); + + + // So that ITE abstraction works... + prop overflow(!known.noOverflow && ITE(lateOverflow, prop(true), earlyOverflow)); + prop underflow(!known.noUnderflow && ITE(lateUnderflow, prop(true), earlyUnderflow)); + + unpackedFloat roundedResult(uf.getSign(), roundedExponent, roundedSignificand); + unpackedFloat result(rounderSpecialCases(format, roundingMode, roundedResult, + overflow, underflow, uf.getZero())); + + POSTCONDITION(result.valid(format)); + + return result; + } + +template +unpackedFloat originalRounder (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &uf) { + + typedef typename t::bwt bwt; + typedef typename t::prop prop; + typedef typename t::ubv ubv; + typedef typename t::sbv sbv; + + //PRECONDITION(uf.valid(format)); + // Not a precondition because + // 1. Exponent and significand may be extended. + // 2. Their values may also be outside of the correct range. + // + // However some thing do hold: + // 1. Leading bit of the significant is 1 (if you want to get a meaningful answer) + // (if not, a cancellation on the near path of add can cause + // this, but the result will not be used, so it can be incorrect) + ubv psig(uf.getSignificand()); + bwt sigWidth(psig.getWidth()); + //PRECONDITION(psig.extract(sigWidth-1, sigWidth-1).isAllOnes()); + ubv sig(psig | unpackedFloat::leadingOne(sigWidth)); + + // 2. Must have round and sticky bits + bwt targetSignificandWidth(unpackedFloat::significandWidth(format)); + PRECONDITION(sigWidth >= targetSignificandWidth + 2); + + // 3. Must have at least enough exponent bits + sbv exp(uf.getExponent()); + bwt expWidth(exp.getWidth()); + bwt targetExponentWidth(unpackedFloat::exponentWidth(format)); + PRECONDITION(expWidth >= targetExponentWidth); + + // Also, do not round special values. + // Note that this relies on these having default values and + // the code that calls the rounder constructing uf from parts. + PRECONDITION(!uf.getNaN()); + PRECONDITION(!uf.getInf()); + //PRECONDITION(!uf.getZero()); // The safe choice of default values means this should work OK + + + + /*** Early underflow and overflow detection ***/ + bwt exponentExtension(expWidth - targetExponentWidth); + prop earlyOverflow(exp > unpackedFloat::maxNormalExponent(format).extend(exponentExtension)); + prop earlyUnderflow(exp < unpackedFloat::minSubnormalExponent(format).extend(exponentExtension).decrement()); + // Optimisation : if the precondition on sigWidth and targetSignificandWidth is removed + // then can change to: + // exponent >= minSubnormalExponent - 1 + // && sigWidth > targetSignificandBits + + + + /*** Normal or subnormal rounding? ***/ + prop normalRounding(exp >= unpackedFloat::minNormalExponent(format).extend(exponentExtension)); + probabilityAnnotation(normalRounding, LIKELY); + + + /*** Round to correct significand. ***/ + ubv extractedSignificand(sig.extract(sigWidth - 1, sigWidth - targetSignificandWidth)); + + bwt guardBitPosition(sigWidth - (targetSignificandWidth + 1)); + prop guardBit(sig.extract(guardBitPosition, guardBitPosition).isAllOnes()); + + prop stickyBit(!sig.extract(guardBitPosition - 1,0).isAllZeros()); + + + // For subnormals, locating the guard and stick bits is a bit more involved + sbv subnormalAmount(unpackedFloat::maxSubnormalExponent(format).extend(exponentExtension) - exp); + prop belowLimit(subnormalAmount <= sbv::zero(expWidth)); // Not subnormal + prop aboveLimit(subnormalAmount >= sbv(expWidth, targetSignificandWidth)); // Will underflow + sbv subnormalShift(ITE((belowLimit || aboveLimit), sbv::zero(expWidth), subnormalAmount)); + // Optimisation : collar + + ubv subnormalShiftPrepared(subnormalShift.toUnsigned().extend(targetSignificandWidth - expWidth)); + ubv guardLocation(ubv::one(targetSignificandWidth) << subnormalShiftPrepared); + ubv stickyMask(guardLocation.decrement()); + + + prop subnormalGuardBit(!(extractedSignificand & guardLocation).isAllZeros()); + prop subnormalStickyBit(guardBit || stickyBit || + !((extractedSignificand & stickyMask).isAllZeros())); + + + + + // Can overflow but is handled + ubv incrementedSignificand(extractedSignificand.modularIncrement()); + prop incrementedSignificandOverflow(incrementedSignificand.isAllZeros()); + // Optimisation : conditional increment + // Optimisation : use top bit of significand to increment the exponent + + ubv correctedIncrementedSignificand(ITE(!incrementedSignificandOverflow, + incrementedSignificand, + unpackedFloat::leadingOne(unpackedFloat::significandWidth(format)))); + + + ubv incrementAmount(guardLocation.modularLeftShift(ubv::one(guardLocation.getWidth()))); // Overflows (safely) in the case of rounding up to the least subnormal. + ubv mask(guardLocation | stickyMask); + ubv maskedSignificand(extractedSignificand & ~mask); + + ubv subnormalIncrementedSignificand(maskedSignificand.modularAdd(incrementAmount)); + prop subnormalIncrementedSignificandOverflow(subnormalIncrementedSignificand.isAllZeros()); + ubv subnomalCorrectedIncrementedSignificand(ITE(!subnormalIncrementedSignificandOverflow, + subnormalIncrementedSignificand, + unpackedFloat::leadingOne(unpackedFloat::significandWidth(format)))); + + + + // Have to choose the right one dependent on rounding mode + prop choosenGuardBit(ITE(normalRounding, guardBit, subnormalGuardBit)); + prop choosenStickyBit(ITE(normalRounding, stickyBit, subnormalStickyBit)); + + prop significandEven(ITE(normalRounding, + extractedSignificand.extract(0,0).isAllZeros(), + ((extractedSignificand & incrementAmount).isAllZeros()))); + prop roundUp(roundingDecision(roundingMode, uf.getSign(), significandEven, + choosenGuardBit, choosenStickyBit, prop(false))); + + ubv roundedSignificand(ITE(normalRounding, + ITE((!roundUp), extractedSignificand, correctedIncrementedSignificand), + ITE((!roundUp), maskedSignificand, subnomalCorrectedIncrementedSignificand))); + + + + /*** Round to correct exponent. ***/ + + // The extend is almost certainly unnecessary (see specialised rounders) + sbv extendedExponent(exp.extend(1)); + + prop incrementExponent(ITE(normalRounding, + incrementedSignificandOverflow, + subnormalIncrementedSignificandOverflow) + && roundUp); + probabilityAnnotation(incrementExponent, VERYUNLIKELY); + + sbv correctedExponent(conditionalIncrement(incrementExponent, extendedExponent)); + + // This can over and underflow but these values will not be used + bwt currentExponentWidth(correctedExponent.getWidth()); + sbv roundedExponent(correctedExponent.contract(currentExponentWidth - targetExponentWidth)); + + + /*** Finish ***/ + prop computedOverflow(correctedExponent > unpackedFloat::maxNormalExponent(format).extend(currentExponentWidth - targetExponentWidth)); + prop computedUnderflow(correctedExponent < unpackedFloat::minSubnormalExponent(format).extend(currentExponentWidth - targetExponentWidth)); + + // So that ITE abstraction works... + prop overflow(ITE(earlyOverflow, prop(true), computedOverflow)); + prop underflow(ITE(earlyUnderflow, prop(true), computedUnderflow)); + + unpackedFloat roundedResult(uf.getSign(), roundedExponent, roundedSignificand); + unpackedFloat result(rounderSpecialCases(format, roundingMode, roundedResult, + overflow, underflow, uf.getZero())); + + POSTCONDITION(result.valid(format)); + + return result; + } + + +template + unpackedFloat rounder (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &uf) { + typedef typename t::prop prop; + customRounderInfo cri(prop(false), prop(false), prop(false), prop(false), prop(false)); // Default is to know nothing + + #ifdef USE_ORIGINAL_ROUNDER + return originalRounder(format, roundingMode, uf); // Allow old versions to be compared + #else + return customRounder(format, roundingMode, uf, cri); + #endif + } + + +} + +#endif diff --git a/third-party/symfpu/core/sign.h b/third-party/symfpu/core/sign.h new file mode 100644 index 0000000..a11944e --- /dev/null +++ b/third-party/symfpu/core/sign.h @@ -0,0 +1,63 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** sign.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 21/08/14 +** +** The sign manipulating operations. +** +*/ + +#include "symfpu/core/unpackedFloat.h" + +#ifndef SYMFPU_SIGN +#define SYMFPU_SIGN + +namespace symfpu { + +template + unpackedFloat negate (const typename t::fpt &format, const unpackedFloat &uf) { + + PRECONDITION(uf.valid(format)); + + unpackedFloat result(uf, !uf.getSign()); + + POSTCONDITION(result.valid(format)); + + return result; + } + +template + unpackedFloat absolute (const typename t::fpt &format, const unpackedFloat &uf) { + + PRECONDITION(uf.valid(format)); + + unpackedFloat result(uf, typename t::prop(false)); + + POSTCONDITION(result.valid(format)); + + return result; + } + + +} + +#endif diff --git a/third-party/symfpu/core/sqrt.h b/third-party/symfpu/core/sqrt.h new file mode 100644 index 0000000..f14adfc --- /dev/null +++ b/third-party/symfpu/core/sqrt.h @@ -0,0 +1,157 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** sqrt.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 05/02/16 +** +** Square root of arbitrary precision floats +** +*/ + +#include "symfpu/core/unpackedFloat.h" +#include "symfpu/core/ite.h" +#include "symfpu/core/rounder.h" +#include "symfpu/core/operations.h" + +#ifndef SYMFPU_SQRT +#define SYMFPU_SQRT + +namespace symfpu { + +template + unpackedFloat addSqrtSpecialCases (const typename t::fpt &format, + const unpackedFloat &uf, + const typename t::prop &sign, + const unpackedFloat &sqrtResult) { + typedef typename t::prop prop; + + prop generateNaN(uf.getSign() && !uf.getZero()); + prop isNaN(uf.getNaN() || generateNaN); + + prop isInf(uf.getInf() && !uf.getSign()); + + prop isZero(uf.getZero()); + + return ITE(isNaN, + unpackedFloat::makeNaN(format), + ITE(isInf, + unpackedFloat::makeInf(format, prop(false)), + ITE(isZero, + unpackedFloat::makeZero(format, sign), + sqrtResult))); + } + + + template + unpackedFloat arithmeticSqrt (const typename t::fpt &format, + const unpackedFloat &uf) { + typedef typename t::bwt bwt; + typedef typename t::prop prop; + typedef typename t::ubv ubv; + typedef typename t::sbv sbv; + typedef typename t::fpt fpt; + + PRECONDITION(uf.valid(format)); + + // Compute sign + prop sqrtSign(uf.getSign()); + + // Divide the exponent by 2 + sbv exponent(uf.getExponent()); + bwt exponentWidth(exponent.getWidth()); + prop exponentEven((exponent & sbv::one(exponentWidth)).isAllZeros()); + #if 0 + sbv exponentHalved(conditionalDecrement((exponent < sbv::zero(exponentWidth)) && !exponentEven, + exponent.signExtendRightShift(sbv::one(exponentWidth)))); + #endif + sbv exponentHalved(exponent.signExtendRightShift(sbv::one(exponentWidth))); + // Right shift rounds down for positive, and away for negative (-5 >>> 1 == -3) + // sqrt(1.s * 2^{-(2n + 1)}) = sqrt(1.s * 2^{-2n - 2 + 1)}) + // = sqrt(1.s * 2^{-2(n + 1)} * 2) + // = sqrt(1.s * 2) * 2^{-(n + 1)} + // Optimisation : improve the encoding of this operation + + // Sqrt the significands + // extend to allow alignment, pad so result has a guard bit + ubv alignedSignificand(conditionalLeftShiftOne(!exponentEven, uf.getSignificand().extend(1).append(ubv::zero(1)))); + + resultWithRemainderBit sqrtd(fixedPointSqrt(alignedSignificand)); + + + bwt resWidth(sqrtd.result.getWidth()); + ubv topBit(sqrtd.result.extract(resWidth - 1, resWidth - 1)); + ubv guardBit(sqrtd.result.extract(0,0)); + + // Alignment of inputs means it is the range [1,4) so the result is in [1,2) + // Also, the square root cannot be exactly between two numbers + INVARIANT(topBit.isAllOnes()); + INVARIANT(IMPLIES(guardBit.isAllOnes(), sqrtd.remainderBit)); + // This also implies that no alignment of the exponent is needed + + ubv finishedSignificand(sqrtd.result.append(ubv(sqrtd.remainderBit))); + + unpackedFloat sqrtResult(sqrtSign, exponentHalved, finishedSignificand); + + + fpt extendedFormat(format.exponentWidth(), format.significandWidth() + 2); + // format.exponentWidth() - 1 should also be true but requires shrinking the exponent and + // then increasing it in the rounder + POSTCONDITION(sqrtResult.valid(extendedFormat)); + + return sqrtResult; + } + + +// Put it all together... +template + unpackedFloat sqrt (const typename t::fpt &format, + const typename t::rm &roundingMode, + const unpackedFloat &uf) { + //typedef typename t::bwt bwt; + typedef typename t::prop prop; + //typedef typename t::ubv ubv; + //typedef typename t::sbv sbv; + + PRECONDITION(uf.valid(format)); + + unpackedFloat sqrtResult(arithmeticSqrt(format, uf)); + + // Exponent is divided by two, thus it can't overflow, underflow or generate a subnormal number. + // The last one is quite subtle but you can show that the largest number generatable + // by arithmeticSqrt is 111...111:0:1 with the last two as the guard and sticky bits. + // Round up (when the sign is positive) and round down (when the sign is negative -- + // the result will be computed but then discarded) are the only cases when this can increment the significand. + customRounderInfo cri(prop(true), prop(true), prop(false), prop(true), + !((roundingMode == t::RTP() && !sqrtResult.getSign()) || + (roundingMode == t::RTN() && sqrtResult.getSign()))); + unpackedFloat roundedSqrtResult(customRounder(format, roundingMode, sqrtResult, cri)); + + unpackedFloat result(addSqrtSpecialCases(format, uf, roundedSqrtResult.getSign(), roundedSqrtResult)); + + POSTCONDITION(result.valid(format)); + + return result; + } + + +} + +#endif diff --git a/third-party/symfpu/core/unpackedFloat.h b/third-party/symfpu/core/unpackedFloat.h new file mode 100644 index 0000000..c5f5dc0 --- /dev/null +++ b/third-party/symfpu/core/unpackedFloat.h @@ -0,0 +1,525 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** unpackedFloat.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 03/06/14 +** +** The working representation of a floating-point number. This is +** from the packed representation in a few ways: +** +** 1. Explicit flags for NaN, Inf and Zero. +** 2. Significand is biased. +** 3. Hidden bit is explicit. +** 4. Subnormals are normalised. +** +** This makes numbers more uniform and makes it easier to implement +** compact and efficient algorithms. +*/ + +#include "symfpu/utils/common.h" +#include "symfpu/utils/properties.h" +#include "symfpu/utils/numberOfRoundingModes.h" + +#include "symfpu/core/ite.h" +#include "symfpu/core/operations.h" + +// For debugging only +#include + +#ifndef SYMFPU_UNPACKED_FLOAT +#define SYMFPU_UNPACKED_FLOAT + +namespace symfpu { + + template + class unpackedFloat { + public : + // Typedef the names from the traits for convenience + typedef typename t::bwt bwt; + typedef typename t::fpt fpt; + typedef typename t::prop prop; + typedef typename t::sbv sbv; + typedef typename t::ubv ubv; + + + protected : + // TODO : protect these again + public : + prop nan; + prop inf; + prop zero; + + prop sign; + sbv exponent; + ubv significand; + protected : + + // It is possible, but hopefully as difficult as possible to create, + // via the constructor an invalid unpacked float + + // A piecewise / literal constructor using fpclass + enum fpclass { FPCLASS_NAN, FPCLASS_INF, FPCLASS_ZERO, FPCLASS_NUMBER }; + + unpackedFloat (const fpclass c, const prop &s, const sbv &exp, const ubv &signif) : + nan(c == FPCLASS_NAN), inf(c == FPCLASS_INF), zero(c == FPCLASS_ZERO), + sign(s), exponent(exp), significand(signif) + {} + + + // Should only be used by ite + friend ite >; + + // TODO : See above -- this should only be used by ite + public : + unpackedFloat (const prop &iteNaN, const prop &iteInf, const prop &iteZero, + const prop &iteSign, const sbv &iteExponent, const ubv &iteSignificand) : + nan(iteNaN), inf(iteInf), zero(iteZero), + sign(iteSign), exponent(iteExponent), significand(iteSignificand) + {} + private : + + // Used for special values + // However this will also be passed through the operations, thus + // if it is also a valid normal number then it will make proving + // invariants easier. In this case it is the value 1.0. + + static sbv defaultExponent(const fpt &fmt) { + return sbv::zero(unpackedFloat::exponentWidth(fmt)); + } + + static ubv defaultSignificand(const fpt &fmt) { + bwt significandWidth = unpackedFloat::significandWidth(fmt); + + return ubv::one(significandWidth) << ubv(significandWidth, (significandWidth - 1)); + } + + + + public : + unpackedFloat (const prop &s, const sbv &exp, const ubv &signif) : + nan(false), inf(false), zero(false), + sign(s), exponent(exp), significand(signif) + {} + + unpackedFloat (const unpackedFloat &old) : + nan(old.nan), inf(old.inf), zero(old.zero), + sign(old.sign), exponent(old.exponent), significand(old.significand) + {} + + // Copy and over-write sign + unpackedFloat (const unpackedFloat &old, const prop &s) : + nan(old.nan), inf(old.inf), zero(old.zero), + sign(ITE(old.nan, old.sign, s)), exponent(old.exponent), significand(old.significand) + {} + + // Swap back-ends + template friend class unpackedFloat; + + template + unpackedFloat (const unpackedFloat &old) : + nan(old.nan), inf(old.inf), zero(old.zero), + sign(old.sign), exponent(old.exponent), significand(old.significand) + {} + + + static unpackedFloat makeZero(const fpt &fmt, const prop &s) { + return unpackedFloat(FPCLASS_ZERO, s, defaultExponent(fmt), defaultSignificand(fmt)); + } + + static unpackedFloat makeInf(const fpt &fmt, const prop &s) { + return unpackedFloat(FPCLASS_INF, s, defaultExponent(fmt), defaultSignificand(fmt)); + } + + static unpackedFloat makeNaN(const fpt &fmt) { + return unpackedFloat(FPCLASS_NAN, false, defaultExponent(fmt), defaultSignificand(fmt)); + } + + inline const prop & getNaN(void) const { return this->nan; } + inline const prop & getInf(void) const { return this->inf; } + inline const prop & getZero(void) const { return this->zero; } + inline const prop & getSign(void) const { return this->sign; } + inline const sbv & getExponent(void) const { return this->exponent; } + inline const ubv & getSignificand(void) const { return this->significand; } + + // inline unpackedFloat changeSign(const prop &newSign) { + // return unpackedFloat(*this, newSign); + // } + + + + + // Get the number of bits in the unpacked format corresponding to a + // given packed format. These are the unpacked counter-parts of + // format.exponentWidth() and format.significandWidth() + + static bwt exponentWidth(const fpt &format) { + + // Note that there is one more exponent above 0 than there is + // below. This is the opposite of 2's compliment but this is not + // a problem because the highest packed exponent corresponds to + // inf and NaN and is thus does not need to be represented in the + // unpacked format. + // However we do need to increase it to allow subnormals (packed) + // to be normalised. + + bwt width = format.exponentWidth(); + + // Could be improved to remove overflow concerns + uint64_t minimumExponent = ((1 << (width - 1)) - 2) + (format.significandWidth() - 1); + + // Increase width until even the smallest subnormal can be normalised + while ((1UL << (width - 1)) < minimumExponent) { + ++width; + } + + return width; + } + + static bwt significandWidth(const fpt &format) { + // Hidden bit is already included in the floating-point format + return format.significandWidth(); + } + + + + + // These should all evaluate to a literal value but are given as + // sbv's to make their use easier and to avoid concerns of overflow. + + static sbv bias(const fpt &format) { + bwt w(exponentWidth(format)); + sbv one(sbv::one(w)); + + return (one << sbv(w,(format.exponentWidth() - 1))) - one; + } + + + static sbv maxNormalExponent(const fpt &format) { + return bias(format); + } + + static sbv minNormalExponent(const fpt &format) { + return -(bias(format) - sbv::one(exponentWidth(format))); + } + + static sbv maxSubnormalExponent(const fpt &format) { + return -bias(format); + } + + static sbv minSubnormalExponent(const fpt &format) { + return maxSubnormalExponent(format) - sbv(exponentWidth(format),(significandWidth(format) - 2)); + } + + // Note the different return type as this is used for iteration in remainder + static bwt maximumExponentDifference(const fpt &format) { + bwt maxNormalExp = (1ULL << (format.exponentWidth() - 1)) - 1; + bwt minSubnormalExp = -maxNormalExp - (significandWidth(format) - 2); + return maxNormalExp - minSubnormalExp; + } + + // knownInFormat uses the format invariant to simplify the test + inline prop inNormalRange(const fpt &format, const prop &knownInFormat) const { + return ((minNormalExponent(format) <= exponent) && + ((exponent <= maxNormalExponent(format) || knownInFormat))); + } + + // knownInFormat uses the format invariant to simplify the test + inline prop inSubnormalRange(const fpt &format, const prop &knownInFormat) const { + // To share tests with the inNormalRange test... + prop upperBound(!(minNormalExponent(format) <= exponent)); + INVARIANT(upperBound == (exponent <= maxSubnormalExponent(format))); + + return (((minSubnormalExponent(format) <= exponent) || knownInFormat) && + upperBound); + } + + inline prop inNormalOrSubnormalRange(const fpt &format, const prop &knownInFormat) const { + return ((minSubnormalExponent(format) <= exponent) && + (exponent <= maxNormalExponent(format))) || knownInFormat; + } + + + + // The amount needed to normalise the number + inline sbv getSubnormalAmount(const fpt &format) const { + return max(minNormalExponent(format) - exponent, + sbv::zero(exponent.getWidth())); + } + + inline prop isPositiveInf (void) const { + return this->inf && !this->sign; + } + + inline prop isNegativeInf (void) const { + return this->inf && this->sign; + } + + + + // Likewise, this is a convenience function + static ubv leadingOne(const bwt sigWidth) { + return ubv::one(sigWidth) << ubv(sigWidth, (sigWidth - 1)); + } + + static ubv nanPattern(const bwt sigWidth) { + return ubv::one(sigWidth) << ubv(sigWidth, (sigWidth - 1)); // For a qNaN, change for sNaN + } + + + + unpackedFloat extend (const bwt expExtension, const bwt sigExtension) const { + return unpackedFloat(this->nan, + this->inf, + this->zero, + this->sign, + this->exponent.extend(expExtension), + this->significand.extend(sigExtension) << ubv((this->significand.getWidth() + sigExtension), sigExtension)); + } + + + // Moves the leading 1 up to the correct position, adjusting the + // exponent as required. + unpackedFloat normaliseUp (const fpt &/*format*/) const { + PRECONDITION(!(nan || inf || zero)); // Should not be attempting to normalise these. + + normaliseShiftResult normal(normaliseShift(this->significand)); + + bwt exponentWidth(this->exponent.getWidth()); + INVARIANT(normal.shiftAmount.getWidth() < exponentWidth); // May loose data / be incorrect for very small exponents and very large significands + + sbv signedAlignAmount(normal.shiftAmount.resize(exponentWidth).toSigned()); + sbv correctedExponent(this->exponent - signedAlignAmount); + + // Optimisation : could move the zero detect version in if used in all cases + // catch - it zero detection in unpacking is different. + return unpackedFloat(this->sign, correctedExponent, normal.normalised); + } + + + unpackedFloat normaliseUpDetectZero (const fpt &format) const { + PRECONDITION(!(nan || inf || zero)); // Should not be attempting to normalise these. + + normaliseShiftResult normal(normaliseShift(this->significand)); + + bwt exponentWidth(this->exponent.getWidth()); + INVARIANT(normal.shiftAmount.getWidth() < exponentWidth); // May loose data / be incorrect for very small exponents and very large significands + + sbv signedAlignAmount(normal.shiftAmount.resize(exponentWidth).toSigned()); + sbv correctedExponent(this->exponent - signedAlignAmount); + + return ITE(normal.isZero, + unpackedFloat::makeZero(format, this->sign), + unpackedFloat(this->sign, correctedExponent, normal.normalised)); + } + +#if 0 + // Moves the leading 1 up to the correct position, adjusting the + // exponent as required. + unpackedFloat normaliseUp (const fpt &/*format*/) const { + PRECONDITION(!(nan || inf || zero)); // Should not be attempting to normalise these. + + ubv alignAmount(countLeadingZeros(this->significand)); + + ubv alignedSignificand(this->significand.modularLeftShift(alignAmount)); // CLZ means data is not lost + + sbv signedAlignAmount(alignAmount.extract(this->exponent.getWidth() - 1,0).toSigned()); + // May loose data / be incorrect for very small exponents and very large significands + sbv correctedExponent(this->exponent - signedAlignAmount); + + // Optimisation : could move the zero detect version in if used in all cases + return unpackedFloat(this->sign, correctedExponent, alignedSignificand); + } + + unpackedFloat normaliseUpDetectZero (const fpt &format) const { + unpackedFloat normal(this->normaliseUp(format)); + + return ITE(this->significand.isAllZeros(), + unpackedFloat::makeZero(format, this->sign), + normal); + } +#endif + + +#if 0 + unpackedFloat normaliseUp (const fpt &format) const { + PRECONDITION(!(nan || inf || zero)); // Should not be attempting to normalise these. + + unpackedFloat working(*this); + bwt sigWidth = unpackedFloat::significandWidth(format); + bwt exWidth = unpackedFloat::exponentWidth(format); + + // TODO : is range checking needed here? Only in obscure use cases. + + for (bwt power = previousPowerOfTwo(sigWidth); power != 0; power >>= 1) { + bwt rem = sigWidth - power; + + INVARIANT(rem > 0); + + ubv mask(ubv::allOnes(power).extend(rem) << rem); + prop shiftNeeded((mask & working.significand).isAllZeros()); + + // Has to be modular as in the case it is not needed, + // performing the shift will loose information. + working.significand = ITE(shiftNeeded, working.significand.modularLeftShift(power), working.significand); + working.exponent = ITE(shiftNeeded, working.exponent - sbv(exWidth,power), working.exponent); + // Optimisation : rather than add each cycle, build shiftNeeded into a number and add once. + } + + return working; + } +#endif + + + + // Is a well formed unpacked struct of the given format? + // The format is needed to ensure that subnormals are correct. + // This invariant does not hold at all points in the code! + prop valid(const fpt &format) const { + + bwt exWidth = exponentWidth(format); + bwt sigWidth = significandWidth(format); + + PRECONDITION((exWidth == exponent.getWidth()) && + (sigWidth == significand.getWidth())); + + // At most one flag is true + prop atMostOneFlag(!(nan && inf) && !(nan && zero) && !(inf && zero)); + + // If one flag is true then exponent and significand are defaults + prop oneFlag(nan || inf || zero); + prop exponentIsDefault(defaultExponent(format) == exponent); + prop significandIsDefault(defaultSignificand(format) == significand); + prop flagImpliesDefaultExponent(IMPLIES(oneFlag, exponentIsDefault)); + prop flagImpliesDefaultSignificand(IMPLIES(oneFlag, significandIsDefault)); + + // NaN has sign = 0 + prop NaNImpliesSignFalse(IMPLIES(nan, !sign)); + + // Exponent is in range + prop exponentInRange(inNormalOrSubnormalRange(format, prop(false))); + + // Has a leading one + prop hasLeadingOne(!(leadingOne(unpackedFloat::significandWidth(format)) & significand).isAllZeros()); + + // Subnormal numbers require an additional check to make sure they + // do not have an unrepresentable amount of significand bits. + sbv subnormalAmount(this->getSubnormalAmount(format)); + INVARIANT((sbv::zero(exWidth) <= subnormalAmount) && + (subnormalAmount <= sbv(exWidth,sigWidth))); + + // Invariant implies this following steps do not loose data + ubv mask(orderEncode(subnormalAmount.toUnsigned().matchWidth(significand))); + + prop correctlyAbbreviated((mask & significand).isAllZeros()); + + prop subnormalImpliesTrailingZeros(IMPLIES(inSubnormalRange(format, prop(false)), correctlyAbbreviated)); + + + return (atMostOneFlag && + (flagImpliesDefaultExponent && flagImpliesDefaultSignificand) && + NaNImpliesSignFalse && + exponentInRange && + hasLeadingOne && + subnormalImpliesTrailingZeros); + } + + + + /* Older version + * Correct but replaced with a version which gives more propagation friendly assertions. + */ +#if 0 + prop valid(const fpt &format) const { + + bwt exWidth = exponentWidth(format); + bwt sigWidth = significandWidth(format); + + PRECONDITION((exWidth == exponent.getWidth()) && + (sigWidth == significand.getWidth())); + + prop hasLeadingOne(!(leadingOne(unpackedFloat::significandWidth(format)) & significand).isAllZeros()); + + + + // Subnormal numbers require an additional check to make sure they + // do not have an unrepresentable amount of significand bits. + sbv subnormalAmount(this->getSubnormalAmount(format)); + INVARIANT((sbv::zero(exWidth) <= subnormalAmount) && + (subnormalAmount <= sbv(exWidth,sigWidth))); + + // Invariant implies this following steps do not loose data + ubv trimmedSubnormalAmount(subnormalAmount.toUnsigned().extract(positionOfLeadingOne(sigWidth),0)); + ubv mask(trimmedSubnormalAmount.orderEncode(sigWidth)); + + prop correctlyAbbreviated((mask & significand).isAllZeros()); + + + + prop normalCase (!nan && !inf && !zero && inNormalRange(format, prop(false)) && hasLeadingOne); + prop subnormalCase(!nan && !inf && !zero && inSubnormalRange(format, prop(false)) && hasLeadingOne && correctlyAbbreviated); + + + + prop exponentIsDefault(defaultExponent(format) == exponent); + prop significandIsDefault(defaultSignificand(format) == significand); + + prop NaNCase ( nan && !inf && !zero && exponentIsDefault && significandIsDefault && !sign); + prop InfCase (!nan && inf && !zero && exponentIsDefault && significandIsDefault); + prop ZeroCase(!nan && !inf && zero && exponentIsDefault && significandIsDefault); + + return (NaNCase || InfCase || ZeroCase || normalCase || subnormalCase); + + } +#endif + + + // Just for debugging + void print (void) const { + std::cerr << "nan : " << this->nan << '\t' + << "inf : " << this->inf << '\t' + << "zero : " << this->zero << '\t' + << "sign : " << this->sign << '\t' + << "exponent : " << this->exponent << '\t' + << "significand : " << this->significand << std::endl; + } + + }; + +template + struct ite > { + static const unpackedFloat iteOp (const typename t::prop &cond, + const unpackedFloat &l, + const unpackedFloat &r) { + return unpackedFloat(ITE(cond, l.nan, r.nan), + ITE(cond, l.inf, r.inf), + ITE(cond, l.zero, r.zero), + ITE(cond, l.sign, r.sign), + ITE(cond, l.exponent, r.exponent), + ITE(cond, l.significand, r.significand)); + } + }; + + + + +} + +#endif diff --git a/third-party/symfpu/flags b/third-party/symfpu/flags new file mode 100644 index 0000000..3284b4b --- /dev/null +++ b/third-party/symfpu/flags @@ -0,0 +1 @@ +CXXFLAGS+=-std=gnu++11 -Wall -W -frounding-math -fsignaling-nans -ffp-contract=off -msse2 -mfpmath=sse -pedantic -mfma -mno-fma4 diff --git a/third-party/symfpu/test b/third-party/symfpu/test deleted file mode 100755 index 3260af9..0000000 Binary files a/third-party/symfpu/test and /dev/null differ diff --git a/third-party/symfpu/utils/Makefile b/third-party/symfpu/utils/Makefile new file mode 100644 index 0000000..dc6bd01 --- /dev/null +++ b/third-party/symfpu/utils/Makefile @@ -0,0 +1,10 @@ +include ../flags +CXXFLAGS+=-I../../ +ALL= +.PHONY : all + +all : $(ALL) + +%.o : %.cpp + $(CXX) $(CXXFLAGS) -c $^ -o $@ + diff --git a/third-party/symfpu/utils/common.h b/third-party/symfpu/utils/common.h new file mode 100644 index 0000000..1e0d27a --- /dev/null +++ b/third-party/symfpu/utils/common.h @@ -0,0 +1,106 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** common.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 05/08/14 +** +** Commonly used utility functions. +** +*/ + +#include +#include + +#include "symfpu/utils/properties.h" + +#ifndef SYMFPU_COMMON +#define SYMFPU_COMMON + +namespace symfpu { + template + T previousPowerOfTwo (T x) { + assert(x > 1); + //PRECONDITION(x > 1); + + T current = 1; + T next = current << 1; + + while (next < x) { + current = next; + next <<= 1; + } + + return current; + } + + template + T leftmostBit (T x) { + assert(x > 1); + //PRECONDITION(x > 1); + + T current = 1; + T next = current << 1; + + while (next <= x) { + current = next; + next <<= 1; + } + + return current; + } + + + // The number of bits required to represent a number + // == the position of the leading 0 + 1 + // == ceil(log_2(value + 1)) + template + T bitsToRepresent (const T value) { + T i = 0; + //unsigned T working = *((unsigned T)&value); // Implementation defined for signed types + T working = value; + + while (working != 0) { + ++i; + working >>= 1; + } + + return i; + } + + template + T positionOfLeadingOne (const T value) { + //PRECONDITION(value != 0); + assert(value != 0); + + T i = 0; + //unsigned T working = *((unsigned T)&value); // Implementation defined for signed types + T working = value; + + while (working != 0) { + ++i; + working >>= 1; + } + + return i - 1; + } +} + +#endif diff --git a/third-party/symfpu/utils/numberOfRoundingModes.h b/third-party/symfpu/utils/numberOfRoundingModes.h new file mode 100644 index 0000000..fa9e724 --- /dev/null +++ b/third-party/symfpu/utils/numberOfRoundingModes.h @@ -0,0 +1,43 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** numberOfRoundingModes.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 20/05/15 +** +** We need a better solution... +** +*/ + +#ifndef SYMFPU_NUMBEROFROUNDINGMODES +#define SYMFPU_NUMBEROFROUNDINGMODES + +namespace symfpu { + + +// Currently support 5 rounding modes +// TODO : This shouldn't be a preprocessor constant + +#define SYMFPU_NUMBER_OF_ROUNDING_MODES 5 + +} + +#endif + diff --git a/third-party/symfpu/utils/properties.h b/third-party/symfpu/utils/properties.h new file mode 100644 index 0000000..0010bd0 --- /dev/null +++ b/third-party/symfpu/utils/properties.h @@ -0,0 +1,58 @@ +/* +** Copyright (C) 2018 Martin Brain +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +/* +** properties.h +** +** Martin Brain +** martin.brain@cs.ox.ac.uk +** 07/08/14 +** +** Macros for specifying invariants in a back-end specific way. +** +** Note that there are two kinds of assertions. +** - Implementation assertions : should be statically or dynamically +** resolvable to bools. Intended to catch cases where the code is +** buggy or being used incorrectly. +** - Algorithm assertions : should be trait::prop and are used +** to document and record properties and assumptions about the +** floating-point computation. Depending on the back-end these may +** be concrete or symbolic and thus handled in different ways. +** +*/ + +#ifndef SYMFPU_PROPERTIES +#define SYMFPU_PROPERTIES + +#define IMPLIES(X,Y) (!(X) || (Y)) + +#ifndef PRECONDITION +#define PRECONDITION(X) t::precondition(X) +#endif + +#ifndef POSTCONDITION +#define POSTCONDITION(X) t::postcondition(X) +#endif + +#ifndef INVARIANT +#define INVARIANT(X) t::invariant(X) +#endif + +#endif + + +