5#include "Stroika/Foundation/Math/Common.h"
10namespace Stroika::Foundation::Math::ReBin {
17 template <
typename X_TYPE,
typename VALUE_TYPE>
18 inline bool DataDescriptorBase<X_TYPE, VALUE_TYPE>::RangeElementsNearlyEqual (XType lhs, XType rhs)
20 return NearlyEquals (lhs, rhs);
28 template <
typename X_TYPE,
typename VALUE_TYPE>
29 inline BasicDataDescriptor<X_TYPE, VALUE_TYPE>::BasicDataDescriptor (
const ValueType* bucketStart,
const ValueType* bucketEnd, XType xStart, XType xEnd)
30 : _fBucketDataStart{bucketStart}
31 , _fBucketDataEnd{bucketEnd}
37 Require (bucketStart < bucketEnd);
38 Require (xStart < xEnd);
40 template <
typename X_TYPE,
typename VALUE_TYPE>
41 inline typename BasicDataDescriptor<X_TYPE, VALUE_TYPE>::BucketIndexType BasicDataDescriptor<X_TYPE, VALUE_TYPE>::GetBucketCount ()
const
43 BucketIndexType result = _fBucketDataEnd - _fBucketDataStart;
47 template <
typename X_TYPE,
typename VALUE_TYPE>
48 inline auto BasicDataDescriptor<X_TYPE, VALUE_TYPE>::GetBucketRange (BucketIndexType bucket)
const -> Traversal::Range<XType>
50 using Traversal::Range;
51 Require (bucket < GetBucketCount ());
52 X_TYPE kDelta_ = (fXEnd_ - fXStart_) * (
static_cast<X_TYPE
> (1) /
static_cast<X_TYPE
> (GetBucketCount ()));
53 X_TYPE s = fXStart_ + (
static_cast<X_TYPE
> (bucket) * kDelta_);
54 return Range<X_TYPE>{s, s + kDelta_, Traversal::Openness::eClosed, Traversal::Openness::eOpen};
56 template <
typename X_TYPE,
typename VALUE_TYPE>
61 if (xrange.GetUpperBound () < fXStart_) {
64 if (xrange.GetLowerBound () > fXEnd_) {
68 X_TYPE kDelta_ = (fXEnd_ - fXStart_) * (
static_cast<X_TYPE
> (1) /
static_cast<X_TYPE
> (GetBucketCount ()));
71 X_TYPE bucketLowerBound = (xrange.GetLowerBound () - fXStart_) / kDelta_;
72 X_TYPE bucketUpperBound = (xrange.GetUpperBound () - fXStart_) / kDelta_;
74 bucketLowerBound = (bucketLowerBound < 0) ? 0 : bucketLowerBound;
75 bucketUpperBound = (bucketUpperBound < 0) ? 0 : bucketUpperBound;
77 BucketIndexType bucketLB = clamp<BucketIndexType> (
static_cast<BucketIndexType
> (floor (bucketLowerBound)), 0, GetBucketCount () - 1);
78 BucketIndexType bucketUB = clamp<BucketIndexType> (
static_cast<BucketIndexType
> (ceil (bucketUpperBound)), bucketLB, GetBucketCount () - 1);
82 template <
typename X_TYPE,
typename VALUE_TYPE>
85 Require (bucket < GetBucketCount ());
86 return _fBucketDataStart[bucket];
88 template <
typename X_TYPE,
typename VALUE_TYPE>
89 inline auto BasicDataDescriptor<X_TYPE, VALUE_TYPE>::GetValues () const -> Containers::Sequence<ValueType>
99 template <
typename X_TYPE,
typename VALUE_TYPE>
100 inline UpdatableDataDescriptor<X_TYPE, VALUE_TYPE>::UpdatableDataDescriptor (VALUE_TYPE* bucketStart, VALUE_TYPE* bucketEnd, X_TYPE xStart, X_TYPE xEnd)
101 : inherited{bucketStart, bucketEnd, xStart, xEnd}
104 template <
typename X_TYPE,
typename VALUE_TYPE>
105 inline void UpdatableDataDescriptor<X_TYPE, VALUE_TYPE>::AccumulateValue (
typename inherited::BucketIndexType bucket, VALUE_TYPE delta)
107 Require (bucket < inherited::GetBucketCount ());
108 VALUE_TYPE* updatableStart =
const_cast<VALUE_TYPE*
> (inherited::_fBucketDataStart);
109 updatableStart[bucket] += delta;
111 template <
typename X_TYPE,
typename VALUE_TYPE>
112 inline void UpdatableDataDescriptor<X_TYPE, VALUE_TYPE>::clear ()
114 VALUE_TYPE* updatableStart =
const_cast<VALUE_TYPE*
> (inherited::_fBucketDataStart);
115 for (VALUE_TYPE* i = updatableStart; i != inherited::_fBucketDataEnd; ++i) {
116 *i = inherited::kNullValue;
126 template <
typename DATA_DESCRIPTOR_TYPE>
127 void CheckRebinDataDescriptorInvariant_ (
const DATA_DESCRIPTOR_TYPE& d)
130 using namespace Traversal;
131 using BucketIndexType =
typename DATA_DESCRIPTOR_TYPE::BucketIndexType;
132 using XType =
typename DATA_DESCRIPTOR_TYPE::XType;
133 auto myContext = Memory::MakeSharedPtr<BucketIndexType> (0);
134 auto bucketCount = d.GetBucketCount ();
135 auto getNext = [myContext, bucketCount, d] () -> optional<Range<XType>> {
140 optional<Range<XType>> result;
141 while (not result.has_value () and *myContext < bucketCount) {
142 Range<XType> tmp{d.GetBucketRange (*myContext)};
143 if (not tmp.empty ()) {
150 Assert (IsPartition (CreateGenerator<Range<XType>> (getNext), DATA_DESCRIPTOR_TYPE::RangeElementsNearlyEqual));
160 template <
typename SRC_DATA_DESCRIPTOR,
typename TRG_DATA_DESCRIPTOR>
161 void ReBin (
const SRC_DATA_DESCRIPTOR& srcData, TRG_DATA_DESCRIPTOR* trgData)
165 using namespace Traversal;
166 using BucketIndexType =
typename SRC_DATA_DESCRIPTOR::BucketIndexType;
179#if qStroika_Foundation_Debug_AssertionsChecked
180 PRIVATE_::CheckRebinDataDescriptorInvariant_ (srcData);
181 PRIVATE_::CheckRebinDataDescriptorInvariant_ (*trgData);
199 BucketIndexType srcBucketCount = srcData.GetBucketCount ();
200 for (BucketIndexType srcBucketIdx = 0; srcBucketIdx < srcBucketCount; ++srcBucketIdx) {
201 Range<typename SRC_DATA_DESCRIPTOR::XType> curSrcBucketX = srcData.GetBucketRange (srcBucketIdx);
202 auto curSrcBucketXWidth = curSrcBucketX.GetDistanceSpanned ();
203 typename SRC_DATA_DESCRIPTOR::ValueType thisSrcBucketValue = srcData.GetValue (srcBucketIdx);
205 Assert (curSrcBucketXWidth >= 0);
208 if (thisSrcBucketValue != SRC_DATA_DESCRIPTOR::kNullValue and curSrcBucketXWidth != 0) {
215 for (
const auto& targetBucket : trgData->GetIntersectingBuckets (curSrcBucketX)) {
216 Range<typename SRC_DATA_DESCRIPTOR::XType> trgBucketIntersectRange =
217 trgData->GetBucketRange (targetBucket).Intersection (curSrcBucketX);
218 auto trgBucketXWidth = trgBucketIntersectRange.GetDistanceSpanned ();
219 trgData->AccumulateValue (targetBucket, thisSrcBucketValue * (trgBucketXWidth / curSrcBucketXWidth));
224 template <
typename SRC_BUCKET_TYPE,
typename TRG_BUCKET_TYPE,
typename X_OFFSET_TYPE>
225 void ReBin (
const SRC_BUCKET_TYPE* srcStart,
const SRC_BUCKET_TYPE* srcEnd, TRG_BUCKET_TYPE* trgStart, TRG_BUCKET_TYPE* trgEnd)
227 using SRC_DATA_DESCRIPTOR = BasicDataDescriptor<X_OFFSET_TYPE, SRC_BUCKET_TYPE>;
228 using TRG_DATA_DESCRIPTOR = UpdatableDataDescriptor<X_OFFSET_TYPE, TRG_BUCKET_TYPE>;
230 SRC_DATA_DESCRIPTOR srcData{srcStart, srcEnd, 1, 2};
231 TRG_DATA_DESCRIPTOR trgData{trgStart, trgEnd, 1, 2};
233 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...