Skip to content
Snippets Groups Projects
Commit 77a2c1b5 authored by Mark OLESEN's avatar Mark OLESEN
Browse files

ENH: support token conversion of scalar to label (#1696)

- this specifically arises in the case we have used the `#eval` syntax
  to generate a value.
  However, since the expressions produce scalar/vector/tensor etc, the
  tokenized value will *not* be introduced into the dictionary as a
  label, even if it appears to be an integer value.

  Eg, eval "2*5", eval "sqrt(100)" both yield `scalar(100)`, which
  will not be suitable for any consumer expecting a label value.

  With the `#calc` version, this problem is glossed over since it uses a
  string buffer for the output (which can suppress the decimal)
  and re-parses the string into tokens, which causes a label to be
  recognized.

- Since we obviously already support implicit handling of ints as
  floats (when reading), now also allow conversion of float
  representations of integral values.

  Uses the ad hoc value of 1e-4 for deciding if the value deviates too
  far from being integral.

- As a side-effect, can now also support scientific notation when
  specifying integers.  Eg, (10 100 1e+3) for cell counts.
parent 8cfb4830
Branches
Tags
No related merge requests found
......@@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2014-2016 OpenFOAM Foundation
Copyright (C) 2016-2019 OpenCFD Ltd.
Copyright (C) 2016-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -31,6 +31,7 @@ License
#include "parsing.H"
#include "IOstreams.H"
#include <cinttypes>
#include <cmath>
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
......@@ -94,6 +95,34 @@ Foam::Istream& Foam::operator>>(Istream& is, int32_t& val)
{
val = int32_t(t.labelToken());
}
else if (t.isScalar())
{
const scalar sval(t.scalarToken());
const intmax_t parsed = intmax_t(std::round(sval));
val = 0 + int32_t(parsed);
// Accept integral floating-point values.
// Eg, from string expression evaluation (#1696)
if (parsed < INT32_MIN || parsed > INT32_MAX)
{
FatalIOErrorInFunction(is)
<< "Expected integral (int32), value out-of-range "
<< t.info()
<< exit(FatalIOError);
is.setBad();
return is;
}
else if (1e-4 < std::abs(sval - scalar(parsed)))
{
FatalIOErrorInFunction(is)
<< "Expected integral (int32), found non-integral value "
<< t.info()
<< exit(FatalIOError);
is.setBad();
return is;
}
}
else
{
FatalIOErrorInFunction(is)
......
......@@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2014-2016 OpenFOAM Foundation
Copyright (C) 2017-2019 OpenCFD Ltd.
Copyright (C) 2017-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -31,6 +31,7 @@ License
#include "parsing.H"
#include "IOstreams.H"
#include <cinttypes>
#include <cmath>
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
......@@ -94,6 +95,34 @@ Foam::Istream& Foam::operator>>(Istream& is, int64_t& val)
{
val = int64_t(t.labelToken());
}
else if (t.isScalar())
{
const scalar sval(t.scalarToken());
const intmax_t parsed = intmax_t(std::round(sval));
val = 0 + int64_t(parsed);
// Accept integral floating-point values.
// Eg, from string expression evaluation (#1696)
if (parsed < INT64_MIN || parsed > INT64_MAX)
{
FatalIOErrorInFunction(is)
<< "Expected integral (int64), value out-of-range "
<< t.info()
<< exit(FatalIOError);
is.setBad();
return is;
}
else if (1e-4 < std::abs(sval - scalar(parsed)))
{
FatalIOErrorInFunction(is)
<< "Expected integral (int64), found non-integral value "
<< t.info()
<< exit(FatalIOError);
is.setBad();
return is;
}
}
else
{
FatalIOErrorInFunction(is)
......
......@@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2014-2016 OpenFOAM Foundation
Copyright (C) 2017-2018 OpenCFD Ltd.
Copyright (C) 2017-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -30,6 +30,7 @@ License
#include "parsing.H"
#include "IOstreams.H"
#include <cinttypes>
#include <cmath>
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
......@@ -93,6 +94,34 @@ Foam::Istream& Foam::operator>>(Istream& is, uint32_t& val)
{
val = uint32_t(t.labelToken());
}
else if (t.isScalar())
{
const scalar sval(t.scalarToken());
const uintmax_t parsed = uintmax_t(std::round(sval));
val = 0 + uint32_t(parsed);
// Accept integral floating-point values.
// Eg, from string expression evaluation (#1696)
if ((sval < -1e-4) || parsed > UINT32_MAX)
{
FatalIOErrorInFunction(is)
<< "Expected label (uint32), value out-of-range "
<< t.info()
<< exit(FatalIOError);
is.setBad();
return is;
}
else if (1e-4 < std::abs(sval - scalar(parsed)))
{
FatalIOErrorInFunction(is)
<< "Expected label (uint32), found non-integral value "
<< t.info()
<< exit(FatalIOError);
is.setBad();
return is;
}
}
else
{
FatalIOErrorInFunction(is)
......
......@@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2014-2016 OpenFOAM Foundation
Copyright (C) 2017-2019 OpenCFD Ltd.
Copyright (C) 2017-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -30,6 +30,7 @@ License
#include "parsing.H"
#include "IOstreams.H"
#include <cinttypes>
#include <cmath>
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
......@@ -93,6 +94,34 @@ Foam::Istream& Foam::operator>>(Istream& is, uint64_t& val)
{
val = uint64_t(t.labelToken());
}
else if (t.isScalar())
{
const scalar sval(t.scalarToken());
const uintmax_t parsed = uintmax_t(std::round(sval));
val = 0 + uint64_t(parsed);
// Accept integral floating-point values.
// Eg, from string expression evaluation (#1696)
if ((sval < -1e-4) || parsed > UINT64_MAX)
{
FatalIOErrorInFunction(is)
<< "Expected label (uint64), value out-of-range "
<< t.info()
<< exit(FatalIOError);
is.setBad();
return is;
}
else if (1e-4 < std::abs(sval - scalar(parsed)))
{
FatalIOErrorInFunction(is)
<< "Expected label (uint64), found non-integral value "
<< t.info()
<< exit(FatalIOError);
is.setBad();
return is;
}
}
else
{
FatalIOErrorInFunction(is)
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment