From cd3b7035e90a5774996523eab5e4526c91f71604 Mon Sep 17 00:00:00 2001 From: Bela Schaum Date: Tue, 12 Nov 2024 15:04:17 +0100 Subject: [PATCH 1/9] Make Range default template argument --- src/base/geom/rect.h | 12 +++++----- src/base/math/floating.h | 19 +++++++--------- src/base/math/range.h | 2 +- src/chart/generator/axis.cpp | 30 ++++++++++++------------- src/chart/generator/axis.h | 16 ++++++------- src/chart/generator/marker.cpp | 5 ++--- src/chart/generator/marker.h | 5 ++--- src/chart/generator/plotbuilder.cpp | 22 +++++++++--------- src/chart/main/style.h | 4 ++-- src/chart/main/stylesheet.cpp | 6 ++--- src/chart/options/align.h | 2 +- src/chart/options/channelrange.cpp | 8 +++---- src/chart/options/channelrange.h | 6 ++--- src/chart/rendering/colorbuilder.h | 2 +- src/chart/rendering/drawinterlacing.cpp | 2 +- src/chart/rendering/drawlegend.cpp | 2 +- src/chart/rendering/drawlegend.h | 2 +- 17 files changed, 68 insertions(+), 77 deletions(-) diff --git a/src/base/geom/rect.h b/src/base/geom/rect.h index bd448d4d9..b53f3236c 100644 --- a/src/base/geom/rect.h +++ b/src/base/geom/rect.h @@ -47,20 +47,20 @@ struct Rect [[nodiscard]] double width() const { return size.x; } [[nodiscard]] double height() const { return size.y; } - [[nodiscard]] Math::Range hSize() const + [[nodiscard]] Math::Range<> hSize() const { return {left(), right()}; } - [[nodiscard]] Math::Range vSize() const + [[nodiscard]] Math::Range<> vSize() const { return {bottom(), top()}; } - [[nodiscard]] Math::Range x() const + [[nodiscard]] Math::Range<> x() const { return {pos.x, pos.x + size.x}; } - [[nodiscard]] Math::Range y() const + [[nodiscard]] Math::Range<> y() const { return {pos.y, pos.y + size.y}; } @@ -89,13 +89,13 @@ struct Rect void setWidth(double val) { size.x = val; } void setHeight(double val) { size.y = val; } - void setHSize(const Math::Range &range) + void setHSize(const Math::Range<> &range) { setLeft(range.getMin()); setRight(range.getMax()); } - void setVSize(const Math::Range &range) + void setVSize(const Math::Range<> &range) { setBottom(range.getMin()); setTop(range.getMax()); diff --git a/src/base/math/floating.h b/src/base/math/floating.h index 5da7a9c67..7398f3488 100644 --- a/src/base/math/floating.h +++ b/src/base/math/floating.h @@ -4,28 +4,25 @@ #include #include #include +#include namespace Math::Floating { [[nodiscard]] int orderOfMagnitude(double value, double base = 10); -constexpr auto inline less = [](auto a, auto b) +constexpr auto inline less = + [](T a, std::type_identity_t b) { - static_assert(std::floating_point); return std::is_lt(std::strong_order(a, b)); }; -constexpr auto inline is_zero = [](auto value) +constexpr auto inline is_zero = [](T value) { - using F = decltype(value); - static_assert(std::floating_point); - if constexpr (std::numeric_limits::is_iec559) { - return value == F{}; - } - else { - return std::is_eq(std::weak_order(F{}, value)); - } + if constexpr (std::numeric_limits::is_iec559) + return value == T{}; + else + return std::is_eq(std::weak_order(T{}, value)); }; } diff --git a/src/base/math/range.h b/src/base/math/range.h index 37ee30709..4a3f92194 100644 --- a/src/base/math/range.h +++ b/src/base/math/range.h @@ -10,7 +10,7 @@ namespace Math { -template struct Range +template struct Range { struct Transform { diff --git a/src/chart/generator/axis.cpp b/src/chart/generator/axis.cpp index 46bdbf233..d84b2170c 100644 --- a/src/chart/generator/axis.cpp +++ b/src/chart/generator/axis.cpp @@ -101,13 +101,12 @@ Geom::Point Axises::origo() const at(AxisId::y).measure.origo()}; } -MeasureAxis::MeasureAxis(const Math::Range &interval, +MeasureAxis::MeasureAxis(const Math::Range<> &interval, std::string series, const std::string_view &unit, const std::optional &step) : enabled(true), - range(interval.isReal() ? interval - : Math::Range::Raw(0, 0)), + range(interval.isReal() ? interval : Math::Range<>::Raw(0, 0)), series(std::move(series)), unit(std::string{unit}), step(step ? *step : Math::Renard::R5().ceil(range.size() / 5.0)) @@ -142,7 +141,7 @@ MeasureAxis interpolate(const MeasureAxis &op0, if (auto s0Zero = is_zero(s0), s1Zero = is_zero(s1); s0Zero && s1Zero) { - res.range = Math::Range::Raw( + res.range = Math::Range<>::Raw( Math::interpolate(op0.range.getMin(), op1.range.getMin(), factor), @@ -159,8 +158,8 @@ MeasureAxis interpolate(const MeasureAxis &op0, 0.0, factor); - res.range = Math::Range::Raw( - op1.range.middle() - middleAt * size, + res.range = Math::Range<>::Raw(op1.range.middle() + - middleAt * size, op1.range.middle() + (factor == 1.0 ? 0.0 : (1 - middleAt) * size)); @@ -169,7 +168,7 @@ MeasureAxis interpolate(const MeasureAxis &op0, res.step = interpolate(op0.step, Anim::Interpolated{max}, - Math::Range::Raw(op0.step.get(), max) + Math::Range<>::Raw(op0.step.get(), max) .rescale(step)); } else if (s0Zero) { @@ -179,8 +178,8 @@ MeasureAxis interpolate(const MeasureAxis &op0, op1.range.rescale(op0.range.middle()), factor); - res.range = Math::Range::Raw( - op0.range.middle() - middleAt * size, + res.range = Math::Range<>::Raw(op0.range.middle() + - middleAt * size, op0.range.middle() + (factor == 0.0 ? 0.0 : (1 - middleAt) * size)); @@ -189,7 +188,7 @@ MeasureAxis interpolate(const MeasureAxis &op0, res.step = interpolate(op1.step, Anim::Interpolated{max}, - Math::Range::Raw(op1.step.get(), max) + Math::Range<>::Raw(op1.step.get(), max) .rescale(step)); } else { @@ -201,7 +200,7 @@ MeasureAxis interpolate(const MeasureAxis &op0, const auto size = is_zero(interp) ? MAX : 1 / interp; - res.range = Math::Range::Raw( + res.range = Math::Range<>::Raw( Math::interpolate(op0.range.getMin() * s0Inv, op1.range.getMin() * s1Inv, factor) @@ -220,19 +219,18 @@ MeasureAxis interpolate(const MeasureAxis &op0, op0sign == std::signbit(op1.step.get())) res.step = interpolate(op0.step, op1.step, - Math::Range::Raw(op0.step.get(), - op1.step.get()) + Math::Range<>::Raw(op0.step.get(), op1.step.get()) .rescale(step)); else if (auto max = std::copysign(MAX, step); op0sign == std::signbit(step)) res.step = interpolate(op0.step, Anim::Interpolated{max}, - Math::Range::Raw(op0.step.get(), max) + Math::Range<>::Raw(op0.step.get(), max) .rescale(step)); else res.step = interpolate(op1.step, Anim::Interpolated{max}, - Math::Range::Raw(op1.step.get(), max) + Math::Range<>::Raw(op1.step.get(), max) .rescale(step)); } @@ -253,7 +251,7 @@ MeasureAxis interpolate(const MeasureAxis &op0, return res; } bool DimensionAxis::add(const Data::SliceIndex &index, - const Math::Range &range, + const Math::Range<> &range, const std::optional &position, const std::optional &color, bool label, diff --git a/src/chart/generator/axis.h b/src/chart/generator/axis.h index dfe7ab82d..1671423c6 100644 --- a/src/chart/generator/axis.h +++ b/src/chart/generator/axis.h @@ -20,11 +20,11 @@ namespace Vizzu::Gen struct ChannelStats { - using TrackType = std::variant, + using TrackType = std::variant, std::vector>>; Refl::EnumArray tracked; - Math::Range lightness; + Math::Range<> lightness; template [[nodiscard]] const TrackType &at(const T &id) const @@ -44,7 +44,7 @@ struct ChannelStats } template - void setIfRange(Id at, const Math::Range &range) + void setIfRange(Id at, const Math::Range<> &range) { if (auto *r = std::get_if<0>(&tracked[asChannel(at)])) *r = range; @@ -54,13 +54,13 @@ struct ChannelStats struct MeasureAxis { ::Anim::Interpolated enabled{false}; - Math::Range range = Math::Range::Raw(0, 1); + Math::Range<> range = Math::Range<>::Raw(0, 1); std::string series; ::Anim::String unit; ::Anim::Interpolated step{1.0}; MeasureAxis() = default; - MeasureAxis(const Math::Range &interval, + MeasureAxis(const Math::Range<> &interval, std::string series, const std::string_view &unit, const std::optional &step); @@ -86,12 +86,12 @@ struct DimensionAxis public: bool start{}; bool end{}; - Math::Range range; + Math::Range<> range; ::Anim::Interpolated position; ::Anim::Interpolated colorBase; ::Anim::Interpolated label; - Item(Math::Range range, + Item(Math::Range<> range, const std::optional &position, const std::optional &color, bool setCategoryAsLabel) : @@ -139,7 +139,7 @@ struct DimensionAxis DimensionAxis() = default; bool add(const Data::SliceIndex &index, - const Math::Range &range, + const Math::Range<> &range, const std::optional &position, const std::optional &color, bool label, diff --git a/src/chart/generator/marker.cpp b/src/chart/generator/marker.cpp index d82894f44..2289839ee 100644 --- a/src/chart/generator/marker.cpp +++ b/src/chart/generator/marker.cpp @@ -209,13 +209,12 @@ void Marker::fromRectangle(const Geom::Rect &rect) size = rect.size; } -Math::Range Marker::getSizeBy(bool horizontal) const +Math::Range<> Marker::getSizeBy(bool horizontal) const { return horizontal ? toRectangle().hSize() : toRectangle().vSize(); } -void Marker::setSizeBy(bool horizontal, - const Math::Range range) +void Marker::setSizeBy(bool horizontal, const Math::Range<> range) { auto rect = toRectangle(); if (horizontal) diff --git a/src/chart/generator/marker.h b/src/chart/generator/marker.h index ec28bb852..13fb6f82e 100644 --- a/src/chart/generator/marker.h +++ b/src/chart/generator/marker.h @@ -85,9 +85,8 @@ class Marker [[nodiscard]] Geom::Rect toRectangle() const; void fromRectangle(const Geom::Rect &rect); - [[nodiscard]] Math::Range getSizeBy( - bool horizontal) const; - void setSizeBy(bool horizontal, Math::Range range); + [[nodiscard]] Math::Range<> getSizeBy(bool horizontal) const; + void setSizeBy(bool horizontal, Math::Range<> range); Conv::JSONObj &&appendToJSON(Conv::JSONObj &&jsonObj) const; diff --git a/src/chart/generator/plotbuilder.cpp b/src/chart/generator/plotbuilder.cpp index 2f0aa2c93..71b034352 100644 --- a/src/chart/generator/plotbuilder.cpp +++ b/src/chart/generator/plotbuilder.cpp @@ -336,11 +336,9 @@ void PlotBuilder::calcAxises(const Data::DataTable &dataTable) } stats.setIfRange(AxisId::x, - Math::Range::Raw(boundRect.left(), - boundRect.right())); + Math::Range<>::Raw(boundRect.left(), boundRect.right())); stats.setIfRange(AxisId::y, - Math::Range::Raw(boundRect.bottom(), - boundRect.top())); + Math::Range<>::Raw(boundRect.bottom(), boundRect.top())); } for (const AxisId &ch : {AxisId::x, AxisId::y}) @@ -425,7 +423,7 @@ void PlotBuilder::calcAxis(const Data::DataTable &dataTable, if (type == plot->getOptions()->subAxisType() && plot->getOptions()->align == Base::Align::Type::stretch) - axis.measure = {Math::Range::Raw(0, 100), + axis.measure = {Math::Range<>::Raw(0, 100), meas->getColIndex(), "%", scale.step.getValue()}; @@ -482,16 +480,16 @@ void PlotBuilder::addAlignment(const Buckets &subBuckets) const if (plot->getOptions()->align == Base::Align::Type::center) { auto &&halfSize = subAxisRange.size() / 2.0; if (!Math::Floating::is_zero(halfSize)) - subAxisRange = Math::Range::Raw( - subAxisRange.getMin() - halfSize, - subAxisRange.getMax() - halfSize); + subAxisRange = + Math::Range<>::Raw(subAxisRange.getMin() - halfSize, + subAxisRange.getMax() - halfSize); } auto &&vectical = !plot->getOptions()->isHorizontal(); const Base::Align align{plot->getOptions()->align, Math::Range(0.0, 1.0)}; for (auto &&bucket : subBuckets) { - Math::Range range; + Math::Range<> range; for (auto &&[marker, idx] : bucket) if (marker.enabled) @@ -512,7 +510,7 @@ void PlotBuilder::addSeparation(const Buckets &subBuckets, auto align = plot->getOptions()->align; std::vector ranges{mainBucketSize, - Math::Range::Raw({}, {})}; + Math::Range<>::Raw({}, {})}; std::vector anyEnabled(mainBucketSize); auto &&vertical = !plot->getOptions()->isHorizontal(); @@ -556,7 +554,7 @@ void PlotBuilder::normalizeSizes() if (plot->getOptions()->geometry == ShapeType::circle || plot->getOptions()->geometry == ShapeType::line) { - Math::Range size; + Math::Range<> size; for (auto &marker : plot->markers) if (marker.enabled) size.include(marker.sizeFactor); @@ -580,7 +578,7 @@ void PlotBuilder::normalizeSizes() void PlotBuilder::normalizeColors() { auto &lightness = stats.lightness; - Math::Range color; + Math::Range<> color; bool wasValidMarker{}; for (auto &marker : plot->markers) { diff --git a/src/chart/main/style.h b/src/chart/main/style.h index 879e0caa1..fdeab75ef 100644 --- a/src/chart/main/style.h +++ b/src/chart/main/style.h @@ -297,9 +297,9 @@ struct DataPoint Param<::Anim::Interpolated>> rectangleSpacing; - [[nodiscard]] Math::Range lightnessRange() const + [[nodiscard]] Math::Range<> lightnessRange() const { - return Math::Range::Raw(*minLightness, *maxLightness); + return Math::Range<>::Raw(*minLightness, *maxLightness); } }; diff --git a/src/chart/main/stylesheet.cpp b/src/chart/main/stylesheet.cpp index 885ab1b17..c1cb76b7f 100644 --- a/src/chart/main/stylesheet.cpp +++ b/src/chart/main/stylesheet.cpp @@ -231,7 +231,7 @@ void Sheet::setAfterStyles(Gen::Plot &plot, const Geom::Size &size) auto font = Gfx::Font{xLabel}; - std::vector> ranges; + std::vector> ranges; bool has_collision = false; for (const auto &[label, item] : plot.axises.at(Gen::AxisId::x).dimension.getValues()) { @@ -251,12 +251,12 @@ void Sheet::setAfterStyles(Gen::Plot &plot, const Geom::Size &size) auto rangeCenter = item.range.middle(); auto next_range = - Math::Range::Raw(rangeCenter - xHalfSize, + Math::Range<>::Raw(rangeCenter - xHalfSize, rangeCenter + xHalfSize); if (std::any_of(ranges.begin(), ranges.end(), - [&next_range](const Math::Range &other) + [&next_range](const Math::Range<> &other) { return other.includes(next_range); })) { diff --git a/src/chart/options/align.h b/src/chart/options/align.h index 1cd2c366a..7f9294e3b 100644 --- a/src/chart/options/align.h +++ b/src/chart/options/align.h @@ -8,7 +8,7 @@ namespace Vizzu::Base { -struct Align : private Math::Range +struct Align : private Math::Range<> { enum class Type : std::uint8_t { none, center, stretch }; diff --git a/src/chart/options/channelrange.cpp b/src/chart/options/channelrange.cpp index 962d649ea..6df5c35a7 100644 --- a/src/chart/options/channelrange.cpp +++ b/src/chart/options/channelrange.cpp @@ -22,17 +22,17 @@ ChannelExtrema::operator std::string() const return std::to_string(value) + std::string{Conv::toString(unit)}; } -Math::Range ChannelRange::getRange( - const Math::Range &original) const +Math::Range<> ChannelRange::getRange( + const Math::Range<> &original) const { - return Math::Range::Raw( + return Math::Range<>::Raw( getExtrema(min, original.getMin(), original), getExtrema(max, original.getMax(), original)); } double ChannelRange::getExtrema(const OptionalChannelExtrema &extrema, double original, - const Math::Range &originalRange) + const Math::Range<> &originalRange) { if (!static_cast(extrema)) return original; diff --git a/src/chart/options/channelrange.h b/src/chart/options/channelrange.h index c2c54aeaa..d1e94494f 100644 --- a/src/chart/options/channelrange.h +++ b/src/chart/options/channelrange.h @@ -41,8 +41,8 @@ class ChannelRange OptionalChannelExtrema min; OptionalChannelExtrema max; - [[nodiscard]] Math::Range getRange( - const Math::Range &original) const; + [[nodiscard]] Math::Range<> getRange( + const Math::Range<> &original) const; bool operator==(const ChannelRange &other) const { @@ -52,7 +52,7 @@ class ChannelRange private: static double getExtrema(const OptionalChannelExtrema &extrema, double original, - const Math::Range &originalRange); + const Math::Range<> &originalRange); }; } diff --git a/src/chart/rendering/colorbuilder.h b/src/chart/rendering/colorbuilder.h index e633eca20..db980beb9 100644 --- a/src/chart/rendering/colorbuilder.h +++ b/src/chart/rendering/colorbuilder.h @@ -13,7 +13,7 @@ namespace Vizzu::Draw struct ColorBuilder { - using LightnessRange = Math::Range; + using LightnessRange = Math::Range<>; ColorBuilder(const LightnessRange &lightnessRange, const ::Anim::Interpolated &palette, diff --git a/src/chart/rendering/drawinterlacing.cpp b/src/chart/rendering/drawinterlacing.cpp index a848831be..a518a66fb 100644 --- a/src/chart/rendering/drawinterlacing.cpp +++ b/src/chart/rendering/drawinterlacing.cpp @@ -79,7 +79,7 @@ void DrawInterlacing::draw(bool horizontal, bool text) const } else { auto highWeight = - Math::Range::Raw(stepLow, stepHigh).rescale(step); + Math::Range<>::Raw(stepLow, stepHigh).rescale(step); auto lowWeight = (1.0 - highWeight) * enabled; highWeight *= enabled; diff --git a/src/chart/rendering/drawlegend.cpp b/src/chart/rendering/drawlegend.cpp index a82d405fa..697826af2 100644 --- a/src/chart/rendering/drawlegend.cpp +++ b/src/chart/rendering/drawlegend.cpp @@ -315,7 +315,7 @@ Geom::Rect DrawLegend::getBarRect(const Info &info) return res; } -Math::Range DrawLegend::markersLegendRange(const Info &info) +Math::Range<> DrawLegend::markersLegendRange(const Info &info) { Math::Range res{0.0, 0.0}; diff --git a/src/chart/rendering/drawlegend.h b/src/chart/rendering/drawlegend.h index 30b2794ca..381a9507f 100644 --- a/src/chart/rendering/drawlegend.h +++ b/src/chart/rendering/drawlegend.h @@ -71,7 +71,7 @@ class DrawLegend : public DrawingContext getLabelRect(const Info &info, const Geom::Rect &itemRect); [[nodiscard]] static Geom::Rect getBarRect(const Info &info); - [[nodiscard]] static Math::Range markersLegendRange( + [[nodiscard]] static Math::Range<> markersLegendRange( const Info &info); void extremaLabel(const Info &info, From 6842ef8635bf6b6c57c13716e0704713ecae654c Mon Sep 17 00:00:00 2001 From: Bela Schaum Date: Tue, 12 Nov 2024 15:25:35 +0100 Subject: [PATCH 2/9] Simplify floating --- src/base/math/floating.cpp | 14 -------------- src/base/math/floating.h | 2 -- src/base/math/normalizednumber.cpp | 2 +- src/base/math/normalizednumber.h | 2 -- 4 files changed, 1 insertion(+), 19 deletions(-) delete mode 100644 src/base/math/floating.cpp diff --git a/src/base/math/floating.cpp b/src/base/math/floating.cpp deleted file mode 100644 index dfa5d288b..000000000 --- a/src/base/math/floating.cpp +++ /dev/null @@ -1,14 +0,0 @@ - -#include "floating.h" - -#include - -namespace Math::Floating -{ - -int orderOfMagnitude(double value, double base) -{ - return static_cast(floor(log(std::abs(value)) / log(base))); -} - -} \ No newline at end of file diff --git a/src/base/math/floating.h b/src/base/math/floating.h index 7398f3488..a2b368989 100644 --- a/src/base/math/floating.h +++ b/src/base/math/floating.h @@ -9,8 +9,6 @@ namespace Math::Floating { -[[nodiscard]] int orderOfMagnitude(double value, double base = 10); - constexpr auto inline less = [](T a, std::type_identity_t b) { diff --git a/src/base/math/normalizednumber.cpp b/src/base/math/normalizednumber.cpp index c98e0fc8f..238cc89f2 100644 --- a/src/base/math/normalizednumber.cpp +++ b/src/base/math/normalizednumber.cpp @@ -24,7 +24,7 @@ NormalizedNumber::NormalizedNumber(double value, double base) : if (value != 0) { positive = !std::signbit(value); if (!positive) value = -value; - exponent = Floating::orderOfMagnitude(value, base); + exponent = static_cast(floor(log(value) / log(base))); coefficient = value / pow(base, exponent); coefficient = std::clamp(coefficient, 1.0, base); } diff --git a/src/base/math/normalizednumber.h b/src/base/math/normalizednumber.h index 96752fbc1..13f7b28bb 100644 --- a/src/base/math/normalizednumber.h +++ b/src/base/math/normalizednumber.h @@ -26,8 +26,6 @@ class NormalizedNumber return positive ? coefficient : -coefficient; } void setExponent(int exp); - -private: }; class ScientificNumber : public NormalizedNumber From 750c392a486e3b64f22ff0856bab64d937db3024 Mon Sep 17 00:00:00 2001 From: Bela Schaum Date: Wed, 13 Nov 2024 12:42:25 +0100 Subject: [PATCH 3/9] Interpolated to EnumArray --- src/base/anim/interpolated.h | 98 ++++++++++--------- src/chart/generator/plot.cpp | 6 +- src/chart/generator/plotbuilder.cpp | 2 +- src/chart/main/style.h | 3 +- src/chart/rendering/colorbuilder.cpp | 2 +- src/chart/rendering/drawaxes.cpp | 19 ++-- src/chart/rendering/drawmarkerinfo.cpp | 3 +- src/chart/rendering/markerrenderer.cpp | 18 +++- .../rendering/markers/abstractmarker.cpp | 9 +- 9 files changed, 85 insertions(+), 75 deletions(-) diff --git a/src/base/anim/interpolated.h b/src/base/anim/interpolated.h index b61e736e4..bd0b51a19 100644 --- a/src/base/anim/interpolated.h +++ b/src/base/anim/interpolated.h @@ -59,7 +59,7 @@ inline InterpolateIndex operator||(const InterpolateIndex &lhs, template class Interpolated { public: - std::array, 2> values; + Refl::EnumArray> values; bool has_second{}; constexpr Interpolated() noexcept( @@ -75,30 +75,30 @@ template class Interpolated constexpr explicit Interpolated(Type value) { - values[0] = Weighted(std::move(value)); + values[first] = Weighted(std::move(value)); } explicit Interpolated(const std::string &str) requires(!std::is_same_v) { - values[0] = Weighted(Conv::parse(str)); + values[first] = Weighted(Conv::parse(str)); } Interpolated &operator=(Type value) { - values[0] = Weighted(std::move(value)); + values[first] = Weighted(std::move(value)); return *this; } Interpolated &operator=(Weighted weightedValue) { - values[0] = std::move(weightedValue); + values[first] = std::move(weightedValue); return *this; } [[nodiscard]] bool hasOneValue() const { - return !has_second && values[0].hasValue(); + return !has_second && values[first].hasValue(); } [[nodiscard]] bool interpolates() const { return has_second; } @@ -110,7 +110,7 @@ template class Interpolated [[nodiscard]] const Type &get() const { - if (!has_second) return values[0].value; + if (!has_second) return values[first].value; throw std::logic_error("Invalid Weigthed Pair"); } @@ -118,15 +118,16 @@ template class Interpolated [[nodiscard]] const Weighted &get_or_first( InterpolateIndex index) const { - return values[has_second && static_cast(index)]; + return values[static_cast( + has_second && static_cast(index))]; } template [[nodiscard]] std::optional get_index( const T &type) const { - if (values[0].value == type) return first; - if (has_second && values[1].value == type) return second; + if (values[first].value == type) return first; + if (has_second && values[second].value == type) return second; return {}; } @@ -136,7 +137,7 @@ template class Interpolated [[nodiscard]] auto toString() const { - if (!has_second) return Conv::toString(values[0].value); + if (!has_second) return Conv::toString(values[first].value); throw std::logic_error("Invalid Weigthed Pair"); } @@ -153,14 +154,15 @@ template class Interpolated bool operator==(const Interpolated &other) const { return has_second == other.has_second - && values[0] == other.values[0] - && (!has_second || values[1] == other.values[1]); + && values[first] == other.values[first] + && (!has_second + || values[second] == other.values[second]); } bool operator==(const Type &other) const { - return !has_second && values[0].weight == 1.0 - && values[0].value == other; + return !has_second && values[first].weight == 1.0 + && values[first].value == other; } bool operator<(const Interpolated &other) const @@ -168,14 +170,14 @@ template class Interpolated if (has_second && other.has_second) throw std::logic_error("cannot compare weigthed pairs"); if (!other.has_second) return false; - return values[0] < other.values[0]; + return values[first] < other.values[first]; } template void visit(T &&branch) const { - if (values[0].hasValue()) branch(first, values[0]); - if (has_second && values[1].hasValue()) - std::forward(branch)(second, values[1]); + if (values[first].hasValue()) branch(first, values[first]); + if (has_second && values[second].hasValue()) + std::forward(branch)(second, values[second]); } template class Interpolated U>> T combine(Fun &&branch) const { - auto res = static_cast(branch(values[0].value)) - * values[0].weight; + auto res = static_cast(branch(values[first].value)) + * values[first].weight; if (has_second) res = res + static_cast( - std::forward(branch)(values[1].value)) - * values[1].weight; + std::forward(branch)(values[second].value)) + * values[second].weight; return static_cast(res); } [[nodiscard]] bool contains(const Type &value) const { - if (value == values[0].value) return true; - if (has_second && value == values[1].value) return true; + if (value == values[first].value) return true; + if (has_second && value == values[second].value) return true; return false; } @@ -206,20 +208,20 @@ template class Interpolated [[nodiscard]] T factor(const U &value) const { double res{}; - if (values[0].value == value) res += values[0].weight; - if (has_second && values[1].value == value) - res += values[1].weight; + if (values[first].value == value) res += values[first].weight; + if (has_second && values[second].value == value) + res += values[second].weight; return T{res}; } template [[nodiscard]] T calculate() const { - auto res = static_cast(this->values[0].value) - * this->values[0].weight; + auto res = static_cast(this->values[first].value) + * this->values[first].weight; if (has_second) res = res - + static_cast(this->values[1].value) - * this->values[1].weight; + + static_cast(this->values[second].value) + * this->values[second].weight; return res; } @@ -228,9 +230,9 @@ template class Interpolated using Less = std::conditional_t, decltype(Math::Floating::less), std::less>; - return !has_second ? this->values[0].value - : std::min(this->values[0].value, - this->values[1].value, + return !has_second ? this->values[first].value + : std::min(this->values[first].value, + this->values[second].value, Less{}); } @@ -239,9 +241,9 @@ template class Interpolated using Less = std::conditional_t, decltype(Math::Floating::less), std::less>; - return !has_second ? this->values[0].value - : std::max(this->values[0].value, - this->values[1].value, + return !has_second ? this->values[first].value + : std::max(this->values[first].value, + this->values[second].value, Less{}); } }; @@ -258,17 +260,19 @@ Interpolated interpolate(const Interpolated &op0, throw std::logic_error("Cannot interpolate Weigthed Pairs"); Interpolated res; - if (op0.values[0].value == op1.values[0].value) { - res.values[0].value = op0.values[0].value; - res.values[0].weight = Math::interpolate(op0.values[0].weight, - op1.values[0].weight, - factor); + if (op0.values[first].value == op1.values[first].value) { + res.values[first].value = op0.values[first].value; + res.values[first].weight = + Math::interpolate(op0.values[first].weight, + op1.values[first].weight, + factor); } else { - res.values[0].value = op0.values[0].value; - res.values[0].weight = op0.values[0].weight * (1.0 - factor); - res.values[1].value = op1.values[0].value; - res.values[1].weight = op1.values[0].weight * factor; + res.values[first].value = op0.values[first].value; + res.values[first].weight = + op0.values[first].weight * (1.0 - factor); + res.values[second].value = op1.values[first].value; + res.values[second].weight = op1.values[first].weight * factor; res.has_second = true; } return res; diff --git a/src/chart/generator/plot.cpp b/src/chart/generator/plot.cpp index ab93e728d..98ac17d2c 100644 --- a/src/chart/generator/plot.cpp +++ b/src/chart/generator/plot.cpp @@ -149,13 +149,11 @@ void Plot::mergeMarkersAndCellInfo(Plot &source, Plot &target) for (std::ptrdiff_t ix{}; ix < markers_size; ++ix) { auto &smarker = smarkers[ix]; auto &tmarker = tmarkers[ix]; - if (auto &[idx, prePos] = - smarker.prevMainMarker.values[0].value; + if (auto &[idx, prePos] = smarker.prevMainMarker->value; !idx.empty()) prePos = indices.at(idx) - ix; - if (auto &[idx, prePos] = - tmarker.prevMainMarker.values[0].value; + if (auto &[idx, prePos] = tmarker.prevMainMarker->value; !idx.empty()) prePos = indices.at(idx) - ix; diff --git a/src/chart/generator/plotbuilder.cpp b/src/chart/generator/plotbuilder.cpp index 71b034352..fa6b7d89a 100644 --- a/src/chart/generator/plotbuilder.cpp +++ b/src/chart/generator/plotbuilder.cpp @@ -151,7 +151,7 @@ PlotBuilder::sortedBuckets(const Buckets &buckets, bool main) const void PlotBuilder::addSpecLayout(Buckets &buckets) { - auto geometry = plot->getOptions()->geometry.values[0].value; + auto geometry = plot->getOptions()->geometry->value; if (auto &markers = plot->markers; isConnecting(geometry)) Charts::TableChart::setupVector(markers, true); else if (plot->getOptions() diff --git a/src/chart/main/style.h b/src/chart/main/style.h index fdeab75ef..c3b17338f 100644 --- a/src/chart/main/style.h +++ b/src/chart/main/style.h @@ -106,7 +106,8 @@ struct Font [[nodiscard]] std::string calculatedFamily() const { if (fontFamily.has_value()) - if (auto &&ff = fontFamily->values[0].value; !ff.empty()) + if (auto &&ff = fontFamily->values[::Anim::first].value; + !ff.empty()) return ff; if (fontParent) return fontParent->calculatedFamily(); diff --git a/src/chart/rendering/colorbuilder.cpp b/src/chart/rendering/colorbuilder.cpp index 446fc0f99..3a726de60 100644 --- a/src/chart/rendering/colorbuilder.cpp +++ b/src/chart/rendering/colorbuilder.cpp @@ -24,7 +24,7 @@ ColorBuilder::ColorBuilder(const LightnessRange &lightnessRange, Gfx::Color ColorBuilder::render( const Anim::Interpolated &colorBase) const { - if (!colorBase.values[0].value.isDiscrete() + if (!colorBase.get_or_first(::Anim::first).value.isDiscrete() && !colorBase.get_or_first(::Anim::second) .value.isDiscrete()) { auto pos = colorBase.combine( diff --git a/src/chart/rendering/drawaxes.cpp b/src/chart/rendering/drawaxes.cpp index 7304f02b3..5e9cfdb02 100644 --- a/src/chart/rendering/drawaxes.cpp +++ b/src/chart/rendering/drawaxes.cpp @@ -357,18 +357,17 @@ void DrawAxes::drawDimensionLabel(bool horizontal, horizontal)); }; - if (labelStyle.position->interpolates() - && text.interpolates()) - draw(text.get_or_first(index), position.weight); - if (!labelStyle.position->interpolates() - && !text.interpolates()) - draw(text.values[0]); - else if (labelStyle.position->interpolates()) - draw(text.values[0], position.weight); - else if (text.interpolates()) { - draw(text.values[0]); + if (text.interpolates() + && !labelStyle.position->interpolates()) { + draw(text.get_or_first(::Anim::first)); draw(text.get_or_first(::Anim::second)); } + else { + draw(text.get_or_first(index), + !labelStyle.position->interpolates() + ? 1.0 + : position.weight); + } }); } diff --git a/src/chart/rendering/drawmarkerinfo.cpp b/src/chart/rendering/drawmarkerinfo.cpp index af863e5ac..8b4594f58 100644 --- a/src/chart/rendering/drawmarkerinfo.cpp +++ b/src/chart/rendering/drawmarkerinfo.cpp @@ -200,7 +200,8 @@ void DrawMarkerInfo::draw(Gfx::ICanvas &canvas, const Geom::Rect &boundary) const { for (const auto &info : plot->getMarkersInfo()) { - auto &&[cnt1, weight1] = info.second.values[0]; + auto &&[cnt1, weight1] = + info.second.get_or_first(::Anim::first); if (!info.second.interpolates() && cnt1) { MarkerDC dc(*this, canvas, boundary, cnt1); dc.draw(weight1); diff --git a/src/chart/rendering/markerrenderer.cpp b/src/chart/rendering/markerrenderer.cpp index acfb0709a..67aadb846 100644 --- a/src/chart/rendering/markerrenderer.cpp +++ b/src/chart/rendering/markerrenderer.cpp @@ -198,7 +198,9 @@ void MarkerRenderer::drawMarkers(Gfx::ICanvas &canvas, if (containsSingle) { auto lineIndex = isConnecting( - getOptions().geometry.values[0].value) + getOptions() + .geometry.values[::Anim::first] + .value) ? ::Anim::first : ::Anim::second; @@ -213,8 +215,9 @@ void MarkerRenderer::drawMarkers(Gfx::ICanvas &canvas, } else drawMarker(::Anim::first, - ::Anim::Weighted{ - blended.marker.prevMainMarker.values[0].value, + ::Anim::Weighted{blended.marker.prevMainMarker + .values[::Anim::first] + .value, sum_weight}); } } @@ -226,11 +229,16 @@ void MarkerRenderer::drawLabels(Gfx::ICanvas &canvas) const auto &&keepMeasure = !measure.interpolates(); auto &&firstUnit = - unit.values[unit.interpolates() && !unit.values[0].hasValue()] + unit.get_or_first(unit.get_or_first(::Anim::first).hasValue() + ? ::Anim::first + : ::Anim::second) .value; auto &&secondUnit = - unit.values[unit.interpolates() && unit.values[1].hasValue()] + unit.get_or_first(unit.get_or_first(::Anim::second).hasValue() + ? ::Anim::second + : ::Anim::first) .value; + for (const auto &blended : markers) { if (blended.marker.enabled == false) continue; drawLabel(canvas, diff --git a/src/chart/rendering/markers/abstractmarker.cpp b/src/chart/rendering/markers/abstractmarker.cpp index c9b146dce..a65ace5dd 100644 --- a/src/chart/rendering/markers/abstractmarker.cpp +++ b/src/chart/rendering/markers/abstractmarker.cpp @@ -49,12 +49,13 @@ AbstractMarker AbstractMarker::createInterpolated( { const auto &options = ctx.getOptions(); - auto fromShapeType = options.geometry.values[0].value; + auto &&[fromShapeType, firstWeight] = + options.geometry.get_or_first(::Anim::first); auto fromMarker = create(ctx, marker, fromShapeType, lineIndex); - auto toShapeType = - options.geometry.get_or_first(::Anim::second).value; + auto &&[toShapeType, secondWeight] = + options.geometry.get_or_first(::Anim::second); if (fromShapeType == toShapeType) return fromMarker; @@ -72,8 +73,6 @@ AbstractMarker AbstractMarker::createInterpolated( auto labelEnableSum = static_cast(aMarker.labelEnabled); if (marker.polarConnection.interpolates()) { - auto firstWeight = options.geometry.values[0].weight; - auto secondWeight = options.geometry.values[1].weight; enableSum = firstWeight + secondWeight; enableFactorBase = secondWeight; labelEnableSum = firstWeight + secondWeight; From dfbcdf81601922f50ca095a8000b789875627253 Mon Sep 17 00:00:00 2001 From: Bela Schaum Date: Wed, 13 Nov 2024 12:50:35 +0100 Subject: [PATCH 4/9] Remove calculate, min, max --- src/base/anim/interpolated.h | 39 ++----------------------- src/chart/rendering/drawinterlacing.cpp | 19 +++++++----- src/chart/rendering/drawlabel.cpp | 2 +- src/chart/rendering/drawlegend.cpp | 6 ++-- src/chart/rendering/drawlegend.h | 2 +- 5 files changed, 19 insertions(+), 49 deletions(-) diff --git a/src/base/anim/interpolated.h b/src/base/anim/interpolated.h index bd0b51a19..fd3788977 100644 --- a/src/base/anim/interpolated.h +++ b/src/base/anim/interpolated.h @@ -181,11 +181,11 @@ template class Interpolated } template , - std::invoke_result_t, + std::remove_cvref_t>, U>> - T combine(Fun &&branch) const + T combine(Fun &&branch = {}) const { auto res = static_cast(branch(values[first].value)) * values[first].weight; @@ -213,39 +213,6 @@ template class Interpolated res += values[second].weight; return T{res}; } - - template [[nodiscard]] T calculate() const - { - auto res = static_cast(this->values[first].value) - * this->values[first].weight; - if (has_second) - res = res - + static_cast(this->values[second].value) - * this->values[second].weight; - return res; - } - - template [[nodiscard]] T min() const - { - using Less = std::conditional_t, - decltype(Math::Floating::less), - std::less>; - return !has_second ? this->values[first].value - : std::min(this->values[first].value, - this->values[second].value, - Less{}); - } - - template [[nodiscard]] T max() const - { - using Less = std::conditional_t, - decltype(Math::Floating::less), - std::less>; - return !has_second ? this->values[first].value - : std::max(this->values[first].value, - this->values[second].value, - Less{}); - } }; template diff --git a/src/chart/rendering/drawinterlacing.cpp b/src/chart/rendering/drawinterlacing.cpp index a518a66fb..c64bc6a51 100644 --- a/src/chart/rendering/drawinterlacing.cpp +++ b/src/chart/rendering/drawinterlacing.cpp @@ -50,16 +50,19 @@ void DrawInterlacing::draw(bool horizontal, bool text) const if (!axis.range.isReal()) return; - auto enabled = axis.enabled.calculate(); + auto enabled = axis.enabled.combine(); - auto step = axis.step.calculate(); + auto step = axis.step.combine(); - auto stepHigh = std::clamp(Math::Renard::R5().ceil(step), - axis.step.min(), - axis.step.max()); - auto stepLow = std::clamp(Math::Renard::R5().floor(step), - axis.step.min(), - axis.step.max()); + auto &&[min, max] = + std::minmax(axis.step.get_or_first(::Anim::first).value, + axis.step.get_or_first(::Anim::second).value, + Math::Floating::less); + + auto stepHigh = + std::clamp(Math::Renard::R5().ceil(step), min, max); + auto stepLow = + std::clamp(Math::Renard::R5().floor(step), min, max); if (stepHigh == step) { draw(axis.enabled, diff --git a/src/chart/rendering/drawlabel.cpp b/src/chart/rendering/drawlabel.cpp index 3ce920a10..26e644d43 100644 --- a/src/chart/rendering/drawlabel.cpp +++ b/src/chart/rendering/drawlabel.cpp @@ -79,7 +79,7 @@ std::pair DrawLabel::alignText( { Geom::Rect res{paddedRect.pos, textSize}; - auto align = style.textAlign->calculate(); + auto align = style.textAlign->combine(); if (auto space = paddedRect.size.x - textSize.x; space > 0) res.pos.x += space / 2.0 * (1 + align); diff --git a/src/chart/rendering/drawlegend.cpp b/src/chart/rendering/drawlegend.cpp index 697826af2..8cb5744ef 100644 --- a/src/chart/rendering/drawlegend.cpp +++ b/src/chart/rendering/drawlegend.cpp @@ -154,7 +154,7 @@ void DrawLegend::drawDimension(Info &info) const if (weight <= 0) continue; auto itemRect = - getItemRect(info, item.position.calculate()); + getItemRect(info, item.position.combine()); if (itemRect.y().getMin() > info.markerWindowRect.y().getMax() || itemRect.y().getMax() @@ -322,8 +322,8 @@ Math::Range<> DrawLegend::markersLegendRange(const Info &info) if (info.measureEnabled > 0.0) res.include(6.0 * info.itemHeight); for (const auto &item : info.axis.dimension) - res.include((item.position.calculate() + 1) - * info.itemHeight); + res.include( + (item.position.combine() + 1) * info.itemHeight); return res; } diff --git a/src/chart/rendering/drawlegend.h b/src/chart/rendering/drawlegend.h index 381a9507f..3c0987c88 100644 --- a/src/chart/rendering/drawlegend.h +++ b/src/chart/rendering/drawlegend.h @@ -46,7 +46,7 @@ class DrawLegend : public DrawingContext double markerSize{}; const Gen::Axis &axis; double measureEnabled = - axis.measure.enabled.calculate(); + axis.measure.enabled.combine(); double measureWeight = Math::FuzzyBool::And(weight, measureEnabled); Events::Targets::LegendProperties properties; From 0e511a5360c91e6c8a01d024822d2bf9801204bb Mon Sep 17 00:00:00 2001 From: Bela Schaum Date: Wed, 13 Nov 2024 13:02:24 +0100 Subject: [PATCH 5/9] Interpolated more simplification --- src/base/anim/interpolated.h | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/src/base/anim/interpolated.h b/src/base/anim/interpolated.h index fd3788977..108b110fb 100644 --- a/src/base/anim/interpolated.h +++ b/src/base/anim/interpolated.h @@ -73,20 +73,18 @@ template class Interpolated Interpolated &operator=(Interpolated &&) noexcept( std::is_nothrow_move_assignable_v) = default; - constexpr explicit Interpolated(Type value) - { - values[first] = Weighted(std::move(value)); - } + constexpr explicit Interpolated(Type value) : + values{{Weighted{std::move(value)}}} + {} explicit Interpolated(const std::string &str) requires(!std::is_same_v) - { - values[first] = Weighted(Conv::parse(str)); - } + : values{{Weighted{Conv::parse(str)}}} + {} Interpolated &operator=(Type value) { - values[first] = Weighted(std::move(value)); + values[first] = Weighted{std::move(value)}; return *this; } @@ -131,10 +129,6 @@ template class Interpolated return {}; } - template - // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward) - [[nodiscard]] auto get(T &&) const = delete; - [[nodiscard]] auto toString() const { if (!has_second) return Conv::toString(values[first].value); @@ -161,16 +155,7 @@ template class Interpolated bool operator==(const Type &other) const { - return !has_second && values[first].weight == 1.0 - && values[first].value == other; - } - - bool operator<(const Interpolated &other) const - { - if (has_second && other.has_second) - throw std::logic_error("cannot compare weigthed pairs"); - if (!other.has_second) return false; - return values[first] < other.values[first]; + return hasOneValue() && values[first].value == other; } template void visit(T &&branch) const @@ -197,7 +182,8 @@ template class Interpolated return static_cast(res); } - [[nodiscard]] bool contains(const Type &value) const + template + [[nodiscard]] bool contains(const T &value) const { if (value == values[first].value) return true; if (has_second && value == values[second].value) return true; From 0e6f9e37521df9fae121deab72a746a7bff87772 Mon Sep 17 00:00:00 2001 From: Bela Schaum Date: Wed, 13 Nov 2024 13:11:25 +0100 Subject: [PATCH 6/9] Math::Range constructors --- src/chart/generator/axis.cpp | 2 +- src/chart/generator/plotbuilder.cpp | 4 ++-- src/chart/rendering/drawlegend.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/chart/generator/axis.cpp b/src/chart/generator/axis.cpp index d84b2170c..3ac65871f 100644 --- a/src/chart/generator/axis.cpp +++ b/src/chart/generator/axis.cpp @@ -106,7 +106,7 @@ MeasureAxis::MeasureAxis(const Math::Range<> &interval, const std::string_view &unit, const std::optional &step) : enabled(true), - range(interval.isReal() ? interval : Math::Range<>::Raw(0, 0)), + range(interval.isReal() ? interval : Math::Range<>::Raw({}, {})), series(std::move(series)), unit(std::string{unit}), step(step ? *step : Math::Renard::R5().ceil(range.size() / 5.0)) diff --git a/src/chart/generator/plotbuilder.cpp b/src/chart/generator/plotbuilder.cpp index fa6b7d89a..bcb9beca6 100644 --- a/src/chart/generator/plotbuilder.cpp +++ b/src/chart/generator/plotbuilder.cpp @@ -487,7 +487,7 @@ void PlotBuilder::addAlignment(const Buckets &subBuckets) const auto &&vectical = !plot->getOptions()->isHorizontal(); const Base::Align align{plot->getOptions()->align, - Math::Range(0.0, 1.0)}; + Math::Range<>::Raw(0.0, 1.0)}; for (auto &&bucket : subBuckets) { Math::Range<> range; @@ -526,7 +526,7 @@ void PlotBuilder::addSeparation(const Buckets &subBuckets, } } - auto max = Math::Range(0.0, 0.0); + auto max = Math::Range<>::Raw({}, {}); for (auto i = 0U; i < ranges.size(); ++i) if (anyEnabled[i]) max = max + ranges[i]; diff --git a/src/chart/rendering/drawlegend.cpp b/src/chart/rendering/drawlegend.cpp index 8cb5744ef..fd7c2011e 100644 --- a/src/chart/rendering/drawlegend.cpp +++ b/src/chart/rendering/drawlegend.cpp @@ -317,7 +317,7 @@ Geom::Rect DrawLegend::getBarRect(const Info &info) Math::Range<> DrawLegend::markersLegendRange(const Info &info) { - Math::Range res{0.0, 0.0}; + auto res = Math::Range<>::Raw({}, {}); if (info.measureEnabled > 0.0) res.include(6.0 * info.itemHeight); From d7d4b733169f5c40475abf75bc55259a4afe3e70 Mon Sep 17 00:00:00 2001 From: Bela Schaum Date: Wed, 13 Nov 2024 13:13:35 +0100 Subject: [PATCH 7/9] Fix potential crash --- src/base/math/segmentedfunc.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/base/math/segmentedfunc.h b/src/base/math/segmentedfunc.h index 456bc15ea..177052228 100644 --- a/src/base/math/segmentedfunc.h +++ b/src/base/math/segmentedfunc.h @@ -44,7 +44,8 @@ template struct SegmentedFunction for (auto it0 = stops.begin(), it1 = other.stops.begin(); it0 != stops.end() || it1 != other.stops.end();) { - if (it1 == other.stops.end() || it0->pos < it1->pos) { + if (it1 == other.stops.end() + || (it0 != stops.end() && it0->pos < it1->pos)) { res.stops.emplace_back(it0->pos, it0->value + other(it0->pos)); ++it0; From 61680af9bee941f3b627d3117c150e27a3597769 Mon Sep 17 00:00:00 2001 From: Bela Schaum Date: Wed, 13 Nov 2024 13:24:50 +0100 Subject: [PATCH 8/9] Clang-tidy --- src/base/math/floating.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/base/math/floating.h b/src/base/math/floating.h index a2b368989..7b192a864 100644 --- a/src/base/math/floating.h +++ b/src/base/math/floating.h @@ -4,13 +4,11 @@ #include #include #include -#include namespace Math::Floating { -constexpr auto inline less = - [](T a, std::type_identity_t b) +constexpr auto inline less = [](T a, T b) { return std::is_lt(std::strong_order(a, b)); }; From 9964b6c030b8cb9882ec76884a6be5fc24f4ef6f Mon Sep 17 00:00:00 2001 From: Bela Schaum Date: Wed, 13 Nov 2024 13:57:53 +0100 Subject: [PATCH 9/9] revert floating --- src/base/math/floating.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/base/math/floating.h b/src/base/math/floating.h index 7b192a864..7f1c4dd50 100644 --- a/src/base/math/floating.h +++ b/src/base/math/floating.h @@ -8,17 +8,20 @@ namespace Math::Floating { -constexpr auto inline less = [](T a, T b) +constexpr auto inline less = [](auto a, auto b) { + static_assert(std::floating_point); return std::is_lt(std::strong_order(a, b)); }; -constexpr auto inline is_zero = [](T value) +constexpr auto inline is_zero = [](auto value) { - if constexpr (std::numeric_limits::is_iec559) - return value == T{}; + using F = decltype(value); + static_assert(std::floating_point); + if constexpr (std::numeric_limits::is_iec559) + return value == F{}; else - return std::is_eq(std::weak_order(T{}, value)); + return std::is_eq(std::weak_order(F{}, value)); }; }