Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions src/disco/FixedWidthField/Real/ENDF/test/write.test.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
#include <iterator>
#include <string>
#include <tuple>
#include <vector>
#include <sstream>

#include "disco.hpp"
#include "catch.hpp"
Expand Down
82 changes: 57 additions & 25 deletions src/disco/FixedWidthField/Real/src/parseExponent.hpp
Original file line number Diff line number Diff line change
@@ -1,49 +1,81 @@
template< typename Iterator >
static int64_t
parseExponent( Iterator& it, uint16_t& position ){
parseExponent( Iterator& it, uint16_t& position ) {

int16_t sign = 1;

auto boundCheck = []( auto p ){
if ( unlikely( p == width ) ){
auto boundCheck = [] ( auto p ) {

if ( unlikely( p == width ) ) {

throw std::runtime_error ("illegal exponent format");
}
};

const auto first = toupper(*it);

switch( first ) {
case 'E':
case 'D':
++position; ++it;
boundCheck( position );
switch( *it ){
case '-':

case 'E' :
case 'D' : {

++position; ++it;
boundCheck( position );
switch( *it ) {
case '-' : {

sign = -1;
// fall through
}
case '+' : {

++position; ++it;
boundCheck( position );
}
default : break;
}
break;
}
case '-' : {

sign = -1;
// fall through
case '+':
}
case '+' : {

++position; ++it;
boundCheck( position );
default: break;
break;
}
break;
case '-':
sign = -1;
// fall through
case '+':
++position; ++it;
boundCheck( position );
break;
default:
return 0;
default : return 0;
}

if ( unlikely( not isdigit( *it ) ) ){
throw std::runtime_error
("illegal character encountered while parsing real number exponent");
if ( unlikely( not isdigit( *it ) ) ) {

if ( *it == ' ' ) {

// older versions of fortran printed ' ' instead of '0'
do {

++position; ++it;
} while ( position < width and ( *it == ' ' ) );

boundCheck( position );
if ( unlikely( not isdigit( *it ) ) ) {

throw std::runtime_error
("illegal character encountered while parsing real number exponent");
}
}
else {

throw std::runtime_error
("illegal character encountered while parsing real number exponent");
}
}

uint64_t exponent = 0;
do {

exponent = 10 * exponent + ( *it - '0' );
++position; ++it;
} while ( position < width and isdigit( *it ) );
Expand Down
113 changes: 96 additions & 17 deletions src/disco/FixedWidthField/Real/test/parseExponent.test.cpp
Original file line number Diff line number Diff line change
@@ -1,24 +1,103 @@
#include <iterator>
#include <string>
#include <vector>

#include "disco.hpp"
#include "catch.hpp"

SCENARIO("Real parse exponent", "[Real], [parseExponent]"){
std::vector< std::string >
test_strings{ {"+123"}, {"-123"},
{"E123"}, {"E+123"}, {"E-123"},
{"e123"}, {"e+123"}, {"e-123"},
{"D123"}, {"D+123"}, {"D-123"},
{"d123"}, {"d+123"}, {"d-123"} };
uint16_t p = 0;
bool success;
for (unsigned i = 0; i < test_strings.size(); ++i){
p = 0; auto si = test_strings[i].begin();
if ( (i + 1) % 3 == 2 ){
REQUIRE( -123 == njoy::disco::Real<5>::parseExponent( si, p ) );
} else {
REQUIRE( 123 == njoy::disco::Real<5>::parseExponent( si, p ) );
}
SCENARIO( "Real - parse exponent" ) {

auto parse = [] ( const std::string string, uint16_t& position ) {

auto iter = string.begin();
position = 0;
return njoy::disco::Real< 6 >::parseExponent( iter, position );
};

THEN( "valid exponent strings can be readup to the correct position" )
{
uint16_t position = 0;

CHECK( +123 == parse( "+123", position ) );
CHECK( 4 == position );
CHECK( +123 == parse( "+ 123", position ) );
CHECK( 5 == position );
CHECK( +123 == parse( "E+123", position ) );
CHECK( 5 == position );
CHECK( +123 == parse( "E+ 123", position ) );
CHECK( 6 == position );
CHECK( +123 == parse( "E123", position ) );
CHECK( 4 == position );
CHECK( +123 == parse( "E 123", position ) );
CHECK( 5 == position );
CHECK( +123 == parse( "e+123", position ) );
CHECK( 5 == position );
CHECK( +123 == parse( "e+ 123", position ) );
CHECK( 6 == position );
CHECK( +123 == parse( "e123", position ) );
CHECK( 4 == position );
CHECK( +123 == parse( "e 123", position ) );
CHECK( 5 == position );
CHECK( +123 == parse( "D+123", position ) );
CHECK( 5 == position );
CHECK( +123 == parse( "D+ 123", position ) );
CHECK( 6 == position );
CHECK( +123 == parse( "D123", position ) );
CHECK( 4 == position );
CHECK( +123 == parse( "D 123", position ) );
CHECK( 5 == position );
CHECK( +123 == parse( "d+123", position ) );
CHECK( 5 == position );
CHECK( +123 == parse( "d+ 123", position ) );
CHECK( 6 == position );
CHECK( +123 == parse( "d123", position ) );
CHECK( 4 == position );
CHECK( +123 == parse( "d 123", position ) );
CHECK( 5 == position );

CHECK( -123 == parse( "-123", position ) );
CHECK( 4 == position );
CHECK( -123 == parse( "- 123", position ) );
CHECK( 5 == position );
CHECK( -123 == parse( "E-123", position ) );
CHECK( 5 == position );
CHECK( -123 == parse( "E- 123", position ) );
CHECK( 6 == position );
CHECK( -123 == parse( "e-123", position ) );
CHECK( 5 == position );
CHECK( -123 == parse( "e- 123", position ) );
CHECK( 6 == position );
CHECK( -123 == parse( "D-123", position ) );
CHECK( 5 == position );
CHECK( -123 == parse( "D- 123", position ) );
CHECK( 6 == position );
CHECK( -123 == parse( "d-123", position ) );
CHECK( 5 == position );
CHECK( -123 == parse( "d- 123", position ) );
CHECK( 6 == position );

// exponent is only read up to the first non-digit
CHECK( +123 == parse( "+123 ", position ) );
CHECK( 4 == position );
CHECK( +123 == parse( "+123a", position ) );
CHECK( 4 == position );
}

THEN( "invalid exponent strings cause an exception" )
{
uint16_t position = 0;

CHECK_THROWS( parse( "-a123", position ) );
CHECK_THROWS( parse( "+a123", position ) );
CHECK_THROWS( parse( "E-a123", position ) );
CHECK_THROWS( parse( "E+a123", position ) );
CHECK_THROWS( parse( "D-a123", position ) );
CHECK_THROWS( parse( "D+a123", position ) );
CHECK_THROWS( parse( "E -123", position ) );
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are valid in Fortran :)

CHECK_THROWS( parse( "E +123", position ) );
CHECK_THROWS( parse( "D -123", position ) );
CHECK_THROWS( parse( "D +123", position ) );

CHECK_THROWS( parse( "- a3", position ) );
CHECK_THROWS( parse( "- ", position ) );
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fortunately, this one is not valid. I did confirm that because I was concerned.

}
}