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:
Fischlurch 2026-09-16 19:42:55 +02:00
parent 620ca918c3
commit eef5ddef0e
3 changed files with 31 additions and 10 deletions

View file

@ -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;

View file

@ -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))

View file

@ -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));
}
};