From 47c1e9fc72081187663b5c41c8117742322e09a8 Mon Sep 17 00:00:00 2001 From: Wim Haeck Date: Thu, 4 Apr 2024 22:34:38 -0600 Subject: [PATCH] Adding FixedPoint --- cmake/unit_testing.cmake | 1 + src/tools/disco.hpp | 3 + src/tools/disco/FixedPoint.hpp | 74 ++++++++++++ .../disco/FixedPoint/test/CMakeLists.txt | 1 + .../disco/FixedPoint/test/FixedPoint.test.cpp | 108 ++++++++++++++++++ 5 files changed, 187 insertions(+) create mode 100644 src/tools/disco/FixedPoint.hpp create mode 100644 src/tools/disco/FixedPoint/test/CMakeLists.txt create mode 100644 src/tools/disco/FixedPoint/test/FixedPoint.test.cpp diff --git a/cmake/unit_testing.cmake b/cmake/unit_testing.cmake index 4168c76..6296d9a 100644 --- a/cmake/unit_testing.cmake +++ b/cmake/unit_testing.cmake @@ -35,6 +35,7 @@ add_subdirectory( src/tools/disco/Column/test ) add_subdirectory( src/tools/disco/Character/test ) add_subdirectory( src/tools/disco/Integer/test ) add_subdirectory( src/tools/disco/Real/test ) +add_subdirectory( src/tools/disco/FixedPoint/test ) add_subdirectory( src/tools/disco/Scientific/test ) add_subdirectory( src/tools/disco/Record/test ) diff --git a/src/tools/disco.hpp b/src/tools/disco.hpp index 5647e5b..5f09114 100644 --- a/src/tools/disco.hpp +++ b/src/tools/disco.hpp @@ -2,6 +2,9 @@ #include "tools/disco/BaseField.hpp" #include "tools/disco/BaseFixedWidthField.hpp" #include "tools/disco/Column.hpp" +#include "tools/disco/Character.hpp" #include "tools/disco/Integer.hpp" #include "tools/disco/Real.hpp" +#include "tools/disco/FixedPoint.hpp" #include "tools/disco/Scientific.hpp" +#include "tools/disco/Record.hpp" diff --git a/src/tools/disco/FixedPoint.hpp b/src/tools/disco/FixedPoint.hpp new file mode 100644 index 0000000..b6190f1 --- /dev/null +++ b/src/tools/disco/FixedPoint.hpp @@ -0,0 +1,74 @@ +#ifndef NJOY_TOOLS_DISCO_SCIENTIFIC +#define NJOY_TOOLS_DISCO_SCIENTIFIC + +// system includes +#include +#include + +// other includes +#include "fast_float/fast_float.h" +#include "tools/disco/Real.hpp" + +namespace njoy { +namespace tools { +namespace disco { + +/** + * @brief A class for reading and writing fixed width data fields containing floating + * point values + */ +template < unsigned int Width, unsigned int Precision > +class FixedPoint : public Real< Width > { + + /* fields */ + +public: + + using Real< Width >::read; + + template< typename Representation, typename Iterator > + static void write( const Representation& value, Iterator& iter ) { + + const double absValue = std::abs( value ); + + std::ostringstream buffer; + buffer << std::right << std::setw( Width ); + + if ( absValue == std::numeric_limits< Representation >::max() ) { + + if ( value < 0 ) { + + buffer << "-Inf"; + } + else { + + buffer << "Inf"; + } + } + else { + + unsigned int precision = Width - 1; + if ( value < 0 ) { + + precision -= 1; + } + precision = std::min( precision, Precision ); + + buffer << std::fixed + << std::uppercase + << std::setprecision( precision ) + << value; + } + + for ( auto b : buffer.str() ) { + + *iter++ = b; + } + } +}; + +} // disco namespace +} // tools namespace +} // njoy namespace + +#endif diff --git a/src/tools/disco/FixedPoint/test/CMakeLists.txt b/src/tools/disco/FixedPoint/test/CMakeLists.txt new file mode 100644 index 0000000..2948eaa --- /dev/null +++ b/src/tools/disco/FixedPoint/test/CMakeLists.txt @@ -0,0 +1 @@ +add_cpp_test( disco.FixedPoint FixedPoint.test.cpp ) diff --git a/src/tools/disco/FixedPoint/test/FixedPoint.test.cpp b/src/tools/disco/FixedPoint/test/FixedPoint.test.cpp new file mode 100644 index 0000000..e305f20 --- /dev/null +++ b/src/tools/disco/FixedPoint/test/FixedPoint.test.cpp @@ -0,0 +1,108 @@ +// include Catch2 +#include + +// what we are testing +#include "tools/disco/FixedPoint.hpp" + +// other includes + +// convenience typedefs +using namespace njoy::tools::disco; + +SCENARIO( "FixedPoint" ) { + + double value; + std::string buffer; + auto iter = std::back_inserter( buffer ); + + value = 0; + buffer = ""; + iter = std::back_inserter( buffer ); + FixedPoint< 12, 5 >::write( value, iter ); + CHECK( " 0.00000" == buffer ); + CHECK( 12 == buffer.size() ); + + value = 2; + buffer = ""; + iter = std::back_inserter( buffer ); + FixedPoint< 12, 5 >::write( value, iter ); + CHECK( " 2.00000" == buffer ); + CHECK( 12 == buffer.size() ); + + value = 10; + buffer = ""; + iter = std::back_inserter( buffer ); + FixedPoint< 12, 5 >::write( value, iter ); + CHECK( " 10.00000" == buffer ); + CHECK( 12 == buffer.size() ); + + value = 3.14159265359; + buffer = ""; + iter = std::back_inserter( buffer ); + FixedPoint< 12, 5 >::write( value, iter ); + CHECK( " 3.14159" == buffer ); + CHECK( 12 == buffer.size() ); + + value = 0.69314718056; + buffer = ""; + iter = std::back_inserter( buffer ); + FixedPoint< 12, 5 >::write( value, iter ); + CHECK( " 0.69315" == buffer ); + CHECK( 12 == buffer.size() ); + +// value = 1e-100; +// buffer = ""; +// iter = std::back_inserter( buffer ); +// FixedPoint< 12, 5 >::write( value, iter ); +// CHECK( "1.00000E-100" == buffer ); +// CHECK( 12 == buffer.size() ); +// +// value = 1e+100; +// buffer = ""; +// iter = std::back_inserter( buffer ); +// FixedPoint< 12, 5 >::write( value, iter ); +// CHECK( "1.00000E+100" == buffer ); +// CHECK( 12 == buffer.size() ); + + value = -2; + buffer = ""; + iter = std::back_inserter( buffer ); + FixedPoint< 12, 5 >::write( value, iter ); + CHECK( " -2.00000" == buffer ); + CHECK( 12 == buffer.size() ); + + value = -10; + buffer = ""; + iter = std::back_inserter( buffer ); + FixedPoint< 12, 5 >::write( value, iter ); + CHECK( " -10.00000" == buffer ); + CHECK( 12 == buffer.size() ); + + value = -3.14159265359; + buffer = ""; + iter = std::back_inserter( buffer ); + FixedPoint< 12, 5 >::write( value, iter ); + CHECK( " -3.14159" == buffer ); + CHECK( 12 == buffer.size() ); + + value = -0.69314718056; + buffer = ""; + iter = std::back_inserter( buffer ); + FixedPoint< 12, 5 >::write( value, iter ); + CHECK( " -0.69315" == buffer ); + CHECK( 12 == buffer.size() ); + + value = std::numeric_limits< double >::max(); + buffer = ""; + iter = std::back_inserter( buffer ); + FixedPoint< 12, 5 >::write( value, iter ); + CHECK( " Inf" == buffer ); + CHECK( 12 == buffer.size() ); + + value = -std::numeric_limits< double >::max(); + buffer = ""; + iter = std::back_inserter( buffer ); + FixedPoint< 12, 5 >::write( value, iter ); + CHECK( " -Inf" == buffer ); + CHECK( 12 == buffer.size() ); +} // SCENARIO