Parameters: integrate the cyclic-wrap function
a much more complete and robust implementation, but requires a precision limit to be pre-computed in the floating-point case
This commit is contained in:
parent
620ca918c3
commit
eef5ddef0e
3 changed files with 31 additions and 10 deletions
|
|
@ -28,14 +28,18 @@
|
|||
#define LIB_PAR_SCALE_H
|
||||
|
||||
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/par/domain.hpp"
|
||||
#include "lib/util.hpp"
|
||||
#include "lib/util-quant.hpp"
|
||||
#include "lib/format-string.hpp"
|
||||
//#include "lib/util.hpp"
|
||||
|
||||
#include <optional>
|
||||
|
||||
|
||||
namespace lib {
|
||||
namespace par {
|
||||
namespace err = lumiera::error;
|
||||
|
||||
using std::optional;
|
||||
|
||||
|
|
@ -66,12 +70,13 @@ namespace par {
|
|||
optional<VAL> neutral{};
|
||||
optional<VAL> defVal{};
|
||||
/////////////////////////////OOO »Sentinels« and nominal scales?
|
||||
bool cyclic{false};
|
||||
VAL cyclicLim =0;
|
||||
|
||||
/* ===== information functions ===== */
|
||||
|
||||
bool isValid() const;
|
||||
bool isFactor() const;
|
||||
bool isCyclic() const;
|
||||
|
||||
/* ===== conforming operations ===== */
|
||||
|
||||
|
|
@ -113,7 +118,7 @@ namespace par {
|
|||
and (not minVal or *minVal <= *defVal)
|
||||
)
|
||||
)
|
||||
and (not cyclic
|
||||
and (not isCyclic()
|
||||
or (minVal and maxVal and *minVal < *maxVal)
|
||||
)
|
||||
;
|
||||
|
|
@ -128,6 +133,13 @@ namespace par {
|
|||
and *neutral == VAL(1);
|
||||
}
|
||||
|
||||
template<typename VAL>
|
||||
inline bool
|
||||
Scale<VAL>::isCyclic() const
|
||||
{
|
||||
return VAL(0) != cyclicLim;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ===== conforming operations ===== */
|
||||
|
|
@ -150,13 +162,17 @@ namespace par {
|
|||
inline VAL
|
||||
Scale<VAL>::conform (VAL const& rawVal) const
|
||||
{
|
||||
if (cyclic)
|
||||
if (isCyclic())
|
||||
{
|
||||
REQUIRE (minVal and maxVal);
|
||||
REQUIRE (*minVal < *maxVal);
|
||||
const VAL PERIOD = *maxVal - *minVal;
|
||||
ENSURE (0 < PERIOD);
|
||||
return (rawVal - *minVal) % PERIOD;
|
||||
if (std::is_floating_point_v<VAL>)
|
||||
if (not (std::abs (rawVal) < cyclicLim))
|
||||
throw err::Invalid {util::_Fmt{"Parameter value %4.2g beyond supported numeric precision "
|
||||
"for cyclic wrapping into (%4.2g ... %4.2g("}
|
||||
% rawVal % minVal % maxVal
|
||||
};
|
||||
return util::cyclicWrap (rawVal, *minVal, *maxVal);
|
||||
}
|
||||
if (minVal and rawVal < *minVal)
|
||||
return *minVal;
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@ namespace util {
|
|||
inline constexpr F
|
||||
limit_cyclicWrap (F period)
|
||||
{
|
||||
REQUIRE (std::isfinite (period));
|
||||
REQUIRE (std::isnormal (period));
|
||||
REQUIRE (F(0) < period);
|
||||
F limit = period / std::numeric_limits<F>::epsilon();
|
||||
if (not std::isfinite (limit))
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ namespace test{
|
|||
run (Arg)
|
||||
{
|
||||
simpleUsage();
|
||||
verify_Bounds();
|
||||
verify_Conforming();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -80,8 +80,13 @@ namespace test{
|
|||
* @todo WIP 9/26 🔁 define ⟶ implement
|
||||
*/
|
||||
void
|
||||
verify_Bounds()
|
||||
verify_Conforming()
|
||||
{
|
||||
Scale<float> scale;
|
||||
CHECK (1e5f == scale.conform (1e5f));
|
||||
|
||||
scale.maxVal = -5.0f;
|
||||
CHECK (-5.0f == scale.conform (1e5f));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue