Project
Loading...
Searching...
No Matches
IrregularSpline1D.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
16
17#include "IrregularSpline1D.h"
18#include "GPUCommonLogger.h"
19
20#include <cmath>
21#include <vector>
22
23#include <iostream>
24
25using namespace o2::gpu;
26
27IrregularSpline1D::IrregularSpline1D() : FlatObject(), mNumberOfKnots(0), mNumberOfAxisBins(0), mBin2KnotMapOffset(0)
28{
30}
31
33{
35 mNumberOfKnots = 0;
36 mNumberOfAxisBins = 0;
37 mBin2KnotMapOffset = 0;
39}
40
41void IrregularSpline1D::cloneFromObject(const IrregularSpline1D& obj, char* newFlatBufferPtr)
42{
44 FlatObject::cloneFromObject(obj, newFlatBufferPtr);
45 mNumberOfKnots = obj.mNumberOfKnots;
46 mNumberOfAxisBins = obj.mNumberOfAxisBins;
47 mBin2KnotMapOffset = obj.mBin2KnotMapOffset;
48}
49
50void IrregularSpline1D::construct(int32_t numberOfKnots, const float inputKnots[], int32_t numberOfAxisBins)
51{
69
70 numberOfAxisBins -= 1;
71
73
74 if (numberOfAxisBins < 4) {
75 numberOfAxisBins = 4;
76 }
77
78 std::vector<int32_t> vKnotBins;
79
80 { // reorganize knots
81
82 int32_t lastBin = numberOfAxisBins; // last bin starts with U value 1.f, therefore it is outside of the [0.,1.] interval
83
84 vKnotBins.push_back(0); // obligatory knot at 0.0
85
86 for (int32_t i = 0; i < numberOfKnots; ++i) {
87 int32_t bin = (int32_t)roundf(inputKnots[i] * numberOfAxisBins);
88 if (bin <= vKnotBins.back() || bin >= lastBin) {
89 continue; // same knot
90 }
91 vKnotBins.push_back(bin);
92 }
93
94 vKnotBins.push_back(lastBin); // obligatory knot at 1.0
95
96 if (vKnotBins.size() < 5) { // too less knots, make a grid with 5 knots
97 vKnotBins.clear();
98 vKnotBins.push_back(0);
99 vKnotBins.push_back((int32_t)roundf(0.25 * numberOfAxisBins));
100 vKnotBins.push_back((int32_t)roundf(0.50 * numberOfAxisBins));
101 vKnotBins.push_back((int32_t)roundf(0.75 * numberOfAxisBins));
102 vKnotBins.push_back(lastBin);
103 }
104 }
105
106 mNumberOfKnots = vKnotBins.size();
107 mNumberOfAxisBins = numberOfAxisBins;
108 mBin2KnotMapOffset = mNumberOfKnots * sizeof(IrregularSpline1D::Knot);
109
110 FlatObject::finishConstruction(mBin2KnotMapOffset + (numberOfAxisBins + 1) * sizeof(int32_t));
111
112 IrregularSpline1D::Knot* s = getKnotsNonConst();
113
114 for (int32_t i = 0; i < mNumberOfKnots; i++) {
115 s[i].u = vKnotBins[i] / ((double)mNumberOfAxisBins); // do division in double
116 }
117
118 { // values will not be used, we define them for consistency
119 int32_t i = 0;
120 double du = (s[i + 1].u - s[i].u);
121 double x3 = (s[i + 2].u - s[i].u) / du;
122 s[i].scale = 1. / du;
123 s[i].scaleL0 = 0.; // undefined
124 s[i].scaleL2 = 0.; // undefined
125 s[i].scaleR2 = (x3 - 2.) / (x3 - 1.);
126 s[i].scaleR3 = 1. / (x3 * (x3 - 1.));
127 }
128
129 for (int32_t i = 1; i < mNumberOfKnots - 2; i++) {
130 double du = (s[i + 1].u - s[i].u);
131 double x0 = (s[i - 1].u - s[i].u) / du;
132 double x3 = (s[i + 2].u - s[i].u) / du;
133 s[i].scale = 1. / du;
134 s[i].scaleL0 = -1. / (x0 * (x0 - 1.));
135 s[i].scaleL2 = x0 / (x0 - 1.);
136 s[i].scaleR2 = (x3 - 2.) / (x3 - 1.);
137 s[i].scaleR3 = 1. / (x3 * (x3 - 1.));
138 }
139
140 { // values will not be used, we define them for consistency
141 int32_t i = mNumberOfKnots - 2;
142 double du = (s[i + 1].u - s[i].u);
143 double x0 = (s[i - 1].u - s[i].u) / du;
144 s[i].scale = 1. / du;
145 s[i].scaleL0 = -1. / (x0 * (x0 - 1.));
146 s[i].scaleL2 = x0 / (x0 - 1.);
147 s[i].scaleR2 = 0; // undefined
148 s[i].scaleR3 = 0; // undefined
149 }
150
151 { // values will not be used, we define them for consistency
152 int32_t i = mNumberOfKnots - 1;
153 s[i].scale = 0; // undefined
154 s[i].scaleL0 = 0; // undefined
155 s[i].scaleL2 = 0; // undefined
156 s[i].scaleR2 = 0; // undefined
157 s[i].scaleR3 = 0; // undefined
158 }
159
160 // Set up map (U bin) -> (knot index)
161
162 int32_t* map = getBin2KnotMapNonConst();
163
164 int32_t iKnotMin = 1;
165 int32_t iKnotMax = mNumberOfKnots - 3;
166
167 //
168 // With iKnotMin=1, iKnotMax=nKnots-3 we release edge intervals:
169 //
170 // Map U coordinates from the first segment [knot0,knot1] to the second segment [knot1,knot2].
171 // Map coordinates from segment [knot{n-2},knot{n-1}] to the previous segment [knot{n-3},knot{n-4}]
172 //
173 // This trick allows one to use splines without special conditions for edge cases.
174 // Any U from [0,1] is mapped to some knote i, where i-1, i, i+1, and i+2 knots always exist
175 //
176
177 for (int32_t iBin = 0, iKnot = iKnotMin; iBin <= mNumberOfAxisBins; iBin++) {
178 if ((iKnot < iKnotMax) && vKnotBins[iKnot + 1] == iBin) {
179 iKnot = iKnot + 1;
180 }
181 map[iBin] = iKnot;
182 }
183}
184
185void IrregularSpline1D::constructRegular(int32_t numberOfKnots)
186{
190
191 if (numberOfKnots < 5) {
192 numberOfKnots = 5;
193 }
194
195 std::vector<float> knots(numberOfKnots);
196 double du = 1. / (numberOfKnots - 1.);
197 for (int32_t i = 1; i < numberOfKnots - 1; i++) {
198 knots[i] = i * du;
199 }
200 knots[0] = 0.f;
201 knots[numberOfKnots - 1] = 1.f;
202 construct(numberOfKnots, knots.data(), numberOfKnots);
203}
204
206{
207 LOG(info) << " Irregular Spline 1D: ";
208 LOG(info) << " mNumberOfKnots = " << mNumberOfKnots;
209 LOG(info) << " mNumberOfAxisBins = " << mNumberOfAxisBins;
210 LOG(info) << " mBin2KnotMapOffset = " << mBin2KnotMapOffset;
211 LOG(info) << " knots: ";
212 for (int32_t i = 0; i < mNumberOfKnots; i++) {
213 LOG(info) << getKnot(i).u << " ";
214 }
215 LOG(info);
216}
int32_t i
Definition of IrregularSpline1D class.
void destroy()
_______________ Utilities _______________________________________________
Definition FlatObject.h:361
void startConstruction()
_____________ Construction _________
Definition FlatObject.h:354
void finishConstruction(int32_t flatBufferSize)
Definition FlatObject.h:370
void cloneFromObject(const FlatObject &obj, char *newFlatBufferPtr)
Definition FlatObject.h:385
void print() const
Print method.
void construct(int32_t numberOfKnots, const float knots[], int32_t numberOfAxisBins)
_______________ Construction interface ________________________
void cloneFromObject(const IrregularSpline1D &obj, char *newFlatBufferPtr)
Construction interface.
IrregularSpline1D()
_____________ Constructors / destructors __________________________
void constructRegular(int32_t numberOfKnotsU)
Constructor for a regular spline.
GLuint GLfloat x0
Definition glcorearb.h:5034
The struct represents a knot(i) and interval [ knot(i), knot(i+1) ].
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"