5#include "Stroika/Foundation/Math/Common.h"
9namespace Stroika::Foundation::Math::ReBin {
16 template <
typename X_TYPE,
typename VALUE_TYPE>
17 inline bool DataDescriptorBase<X_TYPE, VALUE_TYPE>::RangeElementsNearlyEqual (XType lhs, XType rhs)
19 return NearlyEquals (lhs, rhs);
27 template <
typename X_TYPE,
typename VALUE_TYPE>
28 inline BasicDataDescriptor<X_TYPE, VALUE_TYPE>::BasicDataDescriptor (
const ValueType* bucketStart,
const ValueType* bucketEnd, XType xStart, XType xEnd)
29 : _fBucketDataStart{bucketStart}
30 , _fBucketDataEnd{bucketEnd}
36 Require (bucketStart < bucketEnd);
37 Require (xStart < xEnd);
39 template <
typename X_TYPE,
typename VALUE_TYPE>
40 inline typename BasicDataDescriptor<X_TYPE, VALUE_TYPE>::BucketIndexType BasicDataDescriptor<X_TYPE, VALUE_TYPE>::GetBucketCount ()
const
42 BucketIndexType result = _fBucketDataEnd - _fBucketDataStart;
46 template <
typename X_TYPE,
typename VALUE_TYPE>
47 inline auto BasicDataDescriptor<X_TYPE, VALUE_TYPE>::GetBucketRange (BucketIndexType bucket)
const -> Traversal::Range<XType>
49 using Traversal::Range;
50 Require (bucket < GetBucketCount ());
51 X_TYPE kDelta_ = (fXEnd_ - fXStart_) * (
static_cast<X_TYPE
> (1) /
static_cast<X_TYPE
> (GetBucketCount ()));
52 X_TYPE s = fXStart_ + (
static_cast<X_TYPE
> (bucket) * kDelta_);
53 return Range<X_TYPE>{s, s + kDelta_, Traversal::Openness::eClosed, Traversal::Openness::eOpen};
55 template <
typename X_TYPE,
typename VALUE_TYPE>
60 if (xrange.GetUpperBound () < fXStart_) {
63 if (xrange.GetLowerBound () > fXEnd_) {
67 X_TYPE kDelta_ = (fXEnd_ - fXStart_) * (
static_cast<X_TYPE
> (1) /
static_cast<X_TYPE
> (GetBucketCount ()));
70 X_TYPE bucketLowerBound = (xrange.GetLowerBound () - fXStart_) / kDelta_;
71 X_TYPE bucketUpperBound = (xrange.GetUpperBound () - fXStart_) / kDelta_;
73 bucketLowerBound = (bucketLowerBound < 0) ? 0 : bucketLowerBound;
74 bucketUpperBound = (bucketUpperBound < 0) ? 0 : bucketUpperBound;
76 BucketIndexType bucketLB = clamp<BucketIndexType> (
static_cast<BucketIndexType
> (floor (bucketLowerBound)), 0, GetBucketCount () - 1);
77 BucketIndexType bucketUB = clamp<BucketIndexType> (
static_cast<BucketIndexType
> (ceil (bucketUpperBound)), bucketLB, GetBucketCount () - 1);
81 template <
typename X_TYPE,
typename VALUE_TYPE>
84 Require (bucket < GetBucketCount ());
85 return _fBucketDataStart[bucket];
87 template <
typename X_TYPE,
typename VALUE_TYPE>
88 inline auto BasicDataDescriptor<X_TYPE, VALUE_TYPE>::GetValues () const -> Containers::Sequence<ValueType>
98 template <
typename X_TYPE,
typename VALUE_TYPE>
99 inline UpdatableDataDescriptor<X_TYPE, VALUE_TYPE>::UpdatableDataDescriptor (VALUE_TYPE* bucketStart, VALUE_TYPE* bucketEnd, X_TYPE xStart, X_TYPE xEnd)
100 : inherited{bucketStart, bucketEnd, xStart, xEnd}
103 template <
typename X_TYPE,
typename VALUE_TYPE>
104 inline void UpdatableDataDescriptor<X_TYPE, VALUE_TYPE>::AccumulateValue (
typename inherited::BucketIndexType bucket, VALUE_TYPE delta)
106 Require (bucket < inherited::GetBucketCount ());
107 VALUE_TYPE* updatableStart =
const_cast<VALUE_TYPE*
> (inherited::_fBucketDataStart);
108 updatableStart[bucket] += delta;
110 template <
typename X_TYPE,
typename VALUE_TYPE>
111 inline void UpdatableDataDescriptor<X_TYPE, VALUE_TYPE>::clear ()
113 VALUE_TYPE* updatableStart =
const_cast<VALUE_TYPE*
> (inherited::_fBucketDataStart);
114 for (VALUE_TYPE* i = updatableStart; i != inherited::_fBucketDataEnd; ++i) {
115 *i = inherited::kNullValue;
125 template <
typename DATA_DESCRIPTOR_TYPE>
126 void CheckRebinDataDescriptorInvariant_ (
const DATA_DESCRIPTOR_TYPE& d)
129 using namespace Traversal;
130 using BucketIndexType =
typename DATA_DESCRIPTOR_TYPE::BucketIndexType;
131 using XType =
typename DATA_DESCRIPTOR_TYPE::XType;
132 auto myContext = make_shared<BucketIndexType> (0);
133 auto bucketCount = d.GetBucketCount ();
134 auto getNext = [myContext, bucketCount, d] () -> optional<Range<XType>> {
139 optional<Range<XType>> result;
140 while (not result.has_value () and *myContext < bucketCount) {
141 Range<XType> tmp{d.GetBucketRange (*myContext)};
142 if (not tmp.empty ()) {
149 Assert (IsPartition (CreateGenerator<Range<XType>> (getNext), DATA_DESCRIPTOR_TYPE::RangeElementsNearlyEqual));
159 template <
typename SRC_DATA_DESCRIPTOR,
typename TRG_DATA_DESCRIPTOR>
160 void ReBin (
const SRC_DATA_DESCRIPTOR& srcData, TRG_DATA_DESCRIPTOR* trgData)
164 using namespace Traversal;
165 using BucketIndexType =
typename SRC_DATA_DESCRIPTOR::BucketIndexType;
178#if qStroika_Foundation_Debug_AssertionsChecked
179 PRIVATE_::CheckRebinDataDescriptorInvariant_ (srcData);
180 PRIVATE_::CheckRebinDataDescriptorInvariant_ (*trgData);
198 BucketIndexType srcBucketCount = srcData.GetBucketCount ();
199 for (BucketIndexType srcBucketIdx = 0; srcBucketIdx < srcBucketCount; ++srcBucketIdx) {
200 Range<typename SRC_DATA_DESCRIPTOR::XType> curSrcBucketX = srcData.GetBucketRange (srcBucketIdx);
201 auto curSrcBucketXWidth = curSrcBucketX.GetDistanceSpanned ();
202 typename SRC_DATA_DESCRIPTOR::ValueType thisSrcBucketValue = srcData.GetValue (srcBucketIdx);
204 Assert (curSrcBucketXWidth >= 0);
207 if (thisSrcBucketValue != SRC_DATA_DESCRIPTOR::kNullValue and curSrcBucketXWidth != 0) {
214 for (
const auto& targetBucket : trgData->GetIntersectingBuckets (curSrcBucketX)) {
215 Range<typename SRC_DATA_DESCRIPTOR::XType> trgBucketIntersectRange =
216 trgData->GetBucketRange (targetBucket).Intersection (curSrcBucketX);
217 auto trgBucketXWidth = trgBucketIntersectRange.GetDistanceSpanned ();
218 trgData->AccumulateValue (targetBucket, thisSrcBucketValue * (trgBucketXWidth / curSrcBucketXWidth));
223 template <
typename SRC_BUCKET_TYPE,
typename TRG_BUCKET_TYPE,
typename X_OFFSET_TYPE>
224 void ReBin (
const SRC_BUCKET_TYPE* srcStart,
const SRC_BUCKET_TYPE* srcEnd, TRG_BUCKET_TYPE* trgStart, TRG_BUCKET_TYPE* trgEnd)
226 using SRC_DATA_DESCRIPTOR = BasicDataDescriptor<X_OFFSET_TYPE, SRC_BUCKET_TYPE>;
227 using TRG_DATA_DESCRIPTOR = UpdatableDataDescriptor<X_OFFSET_TYPE, TRG_BUCKET_TYPE>;
229 SRC_DATA_DESCRIPTOR srcData{srcStart, srcEnd, 1, 2};
230 TRG_DATA_DESCRIPTOR trgData{trgStart, trgEnd, 1, 2};
232 ReBin (srcData, &trgData);
#define qStroika_Foundation_Debug_AssertionsChecked
The qStroika_Foundation_Debug_AssertionsChecked flag determines if assertions are checked and validat...
#define RequireNotNull(p)
void ReBin(const SRC_DATA_DESCRIPTOR &srcData, TRG_DATA_DESCRIPTOR *trgData)
A generalization of a vector: a container whose elements are keyed by the natural numbers.
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
A DiscreteRange is a Range where the underlying endpoints are integral (discrete, not continuous); th...