Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
7 changes: 4 additions & 3 deletions src/disco/FixedWidthField.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
template< uint16_t w >
struct FixedWidthField {

/* convenience typedefs */
template< typename T >
using ArgumentType =
Expand All @@ -8,11 +9,12 @@ struct FixedWidthField {
T, std::add_const_t < std::add_lvalue_reference_t< T > > >;

constexpr static bool
isSpace( const char c ){ return c == ' ' or c == '\t'; }
isSpace( const char c ) { return c == ' ' or c == '\t'; }

template< typename Iterator >
constexpr static bool
isNewline( const char c, Iterator& it ){
isNewline( const char c, Iterator& it ) {

return
c == '\n'
or c == '\f'
Expand All @@ -28,5 +30,4 @@ struct FixedWidthField {
isEOF( const char c ){ return c == std::char_traits<char>::eof(); }

#include "disco/FixedWidthField/src/whiteSpace.hpp"

};
3 changes: 0 additions & 3 deletions src/disco/FixedWidthField/Real.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ struct Real : public FixedWidthField< w >{
/* constants */
static constexpr uint16_t width = w;

/* convenience typedefs */
using FixedWidthField_ = FixedWidthField< w >;

template< typename Iterator >
static void write( Iterator& it ){ ColumnPosition< w >::write( it ); }

Expand Down
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
3 changes: 2 additions & 1 deletion src/disco/FixedWidthField/Real/src/noDigits.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
template< typename UnsignedInteger >
static uint16_t
noDigits( UnsignedInteger mantissa ){
noDigits( UnsignedInteger mantissa ) {

if ( mantissa < 10ull ){ return 1; };
if ( mantissa < 100ull ){ return 2; };
if ( mantissa < 1000ull ){ return 3; };
Expand Down
11 changes: 7 additions & 4 deletions src/disco/FixedWidthField/Real/src/parseBase.hpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
template< typename Iterator >
static uint64_t
parseBase( Iterator& it, uint16_t& position, bool& success ){
uint64_t base = ( success = isdigit( *it ) ) ? (*it - 48) : 0;
if ( success ){
parseBase( Iterator& it, uint16_t& position, bool& success ) {

uint64_t base = ( success = isdigit( *it ) ) ? ( *it - 48 ) : 0;
if ( success ) {

++position; ++it;
while ( position < width ) {

if ( not isdigit( *it ) ) { break; }
// TODO: overflow check
base = ( 10 * base ) + (*it - 48);
base = ( 10 * base ) + ( *it - 48 );
++position; ++it;
}
}
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
9 changes: 6 additions & 3 deletions src/disco/FixedWidthField/Real/src/parseFraction.hpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
template< typename Iterator >
static uint64_t
parseFraction( Iterator& it, uint16_t& position, bool& success ){
parseFraction( Iterator& it, uint16_t& position, bool& success ) {

uint64_t fraction = 0;
success = false;
if ( *it == '.' ){
if ( *it == '.' ) {

const auto initialPosition = ++position;
++it;
while ( position < width ) {

if ( not isdigit( *it ) ) { break; }
//TODO: overflow check
fraction = 10 * fraction + (*it - 48);
fraction = 10 * fraction + ( *it - 48 );
++position; ++it;
}
success = initialPosition != position;
Expand Down
32 changes: 18 additions & 14 deletions src/disco/FixedWidthField/Real/src/parseInfinity.hpp
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
template< typename Iterator >
static bool
parseInfinity( Iterator& it, uint16_t& position ){
auto canProceed = [&it](){
return not ( FixedWidthField_::isEOF(*it)
or FixedWidthField_::isNewline(*it, it));
parseInfinity( Iterator& it, uint16_t& position ) {

auto canProceed = [&it]() {

return not ( FixedWidthField< w >::isEOF( *it )
or FixedWidthField< w >::isNewline( *it, it ) );
};
const auto remainingWidth = int(w) - position;

const auto remainingWidth = int( w ) - position;
bool success = false;
if ( remainingWidth >= 3 ){
if ( remainingWidth >= 3 ) {

position += 3;
success =
success =
( toupper( *it++ ) == 'I' )
and ( canProceed() and toupper( *it++ ) == 'N' )
and ( canProceed() and toupper( *it++ ) == 'F' );
if ( success and remainingWidth >= 8 and toupper(*it) == 'I' ){
and ( canProceed() and toupper( *it++ ) == 'F' );
if ( success and remainingWidth >= 8 and toupper( *it ) == 'I' ) {

position += 5;
++it;
success =
success =
( canProceed() and toupper( *it++ ) == 'N' )
and ( canProceed() and toupper( *it++ ) == 'I' )
and ( canProceed() and toupper( *it++ ) == 'T' )
and ( canProceed() and toupper( *it++ ) == 'Y' );
and ( canProceed() and toupper( *it++ ) == 'I' )
and ( canProceed() and toupper( *it++ ) == 'T' )
and ( canProceed() and toupper( *it++ ) == 'Y' );
}
}
return success;
Expand Down
12 changes: 7 additions & 5 deletions src/disco/FixedWidthField/Real/src/parseSign.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
template< typename Iterator >
static int16_t parseSign( Iterator& it, uint16_t& position ){
switch ( *it ){
case '+': ++it; ++position; return 1;
case '-': ++it; ++position; return -1;
default: return 1;
static int16_t parseSign( Iterator& it, uint16_t& position ) {

switch ( *it ) {

case '+': ++it; ++position; return 1;
case '-': ++it; ++position; return -1;
default: return 1;
}
}
66 changes: 44 additions & 22 deletions src/disco/FixedWidthField/Real/src/read.hpp
Original file line number Diff line number Diff line change
@@ -1,28 +1,34 @@
template< typename Representation, typename Iterator, bool trust = true >
static Representation
read( Iterator& it, const Iterator& ){
auto position = FixedWidthField_::whiteSpace( it );
read( Iterator& it, const Iterator& ) {

auto position = FixedWidthField< w >::whiteSpace( it );

if( FixedWidthField< w >::isNewline(*it, it) or FixedWidthField< w >::isEOF(*it) ) {

if( FixedWidthField_::isNewline(*it, it) or FixedWidthField_::isEOF(*it) ){
return Representation(0.0);
}

if ( position == w ){
if ( position == w ) {

++it;
return Representation(0.0);
}

const auto value = [&]{
const auto value = [&] {

const auto sign = Real::parseSign(it, position);

if ( unlikely( position == width ) ){
if ( unlikely( position == width ) ) {

throw std::runtime_error("cannot parse invalid real number");
}

bool baseSuccess = false;
auto base = Real::parseBase(it, position, baseSuccess);

if ( position == width ){
if ( position == width ) {

return Representation( sign * int64_t( base ) );
}

Expand All @@ -31,47 +37,62 @@ read( Iterator& it, const Iterator& ){
const auto fraction = Real::parseFraction( it, position, fractionSuccess );
const auto foundDecimal = decimalPosition != position;

const auto noFractionDigits =
const auto numberFractionDigits =
fractionSuccess
* ( position - decimalPosition - (position != width - 1) );

if ( position == width ){
const auto factor =
realExponentiation< Representation >::cache( -noFractionDigits );
return sign * ( base + fraction * Representation(factor) );
}
// ensure that something like ' . ' always fails
if ( unlikely( not baseSuccess && not fractionSuccess ) ) {

if ( unlikely( not baseSuccess && not fractionSuccess ) ){
const bool succeeded =
not foundDecimal and Real::parseInfinity( it, position );
if ( unlikely( not succeeded ) ){
if ( unlikely( not succeeded ) ) {

throw std::runtime_error("cannot parse invalid real number");
}

return sign * std::numeric_limits< Representation >::infinity();
}

// read over possible trailing white space between the fraction and exponent
while( FixedWidthField< w >::isSpace( *it ) and position < w ) {

++position;
++it;
}

// no need to continue if we are at the end
if ( position == width ) {

const auto factor =
realExponentiation< Representation >::cache( -numberFractionDigits );
return sign * ( base + fraction * Representation(factor) );
}

const auto exponent =
Real::parseExponent( it, position ) - noFractionDigits;
Real::parseExponent( it, position ) - numberFractionDigits;

if ( unlikely( exponent
< std::numeric_limits< Representation >::min_exponent10 ) ){
< std::numeric_limits< Representation >::min_exponent10 ) ) {

return sign * 0.0;
}

if ( unlikely( exponent
> std::numeric_limits< Representation >::max_exponent10 ) ){
> std::numeric_limits< Representation >::max_exponent10 ) ) {

return sign * std::numeric_limits< Representation >::infinity();
}

const auto factor =
integerExponentiation< int64_t >::cache( noFractionDigits );
integerExponentiation< int64_t >::cache( numberFractionDigits );

return sign * int64_t( base * factor + fraction )
* realExponentiation< Representation >::cache( exponent );
}();

if ( unlikely( not FixedWidthField_::whiteSpace(it, position) ) ){
if ( unlikely( not FixedWidthField< w >::whiteSpace(it, position) ) ) {

throw std::runtime_error("cannot parse invalid real number");
}

Expand All @@ -80,6 +101,7 @@ read( Iterator& it, const Iterator& ){

template< typename Iterator, bool trust = true >
static double
read( Iterator& it, const Iterator& end ){
return read<double>( it, end );
read( Iterator& it, const Iterator& end ) {

return read< double >( it, end );
}
Loading