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#if !defined(GPUCA_GPUCODE)
24#include <iostream>
25#endif
26
27using namespace o2::gpu;
28
29IrregularSpline1D::IrregularSpline1D() : FlatObject(), mNumberOfKnots(0), mNumberOfAxisBins(0), mBin2KnotMapOffset(0)
30{
32}
33
35{
37 mNumberOfKnots = 0;
38 mNumberOfAxisBins = 0;
39 mBin2KnotMapOffset = 0;
41}
42
43void IrregularSpline1D::cloneFromObject(const IrregularSpline1D& obj, char* newFlatBufferPtr)
44{
46 FlatObject::cloneFromObject(obj, newFlatBufferPtr);
47 mNumberOfKnots = obj.mNumberOfKnots;
48 mNumberOfAxisBins = obj.mNumberOfAxisBins;
49 mBin2KnotMapOffset = obj.mBin2KnotMapOffset;
50}
51
52void IrregularSpline1D::construct(int32_t numberOfKnots, const float inputKnots[], int32_t numberOfAxisBins)
53{
71
72 numberOfAxisBins -= 1;
73
75
76 if (numberOfAxisBins < 4) {
77 numberOfAxisBins = 4;
78 }
79
80 std::vector<int32_t> vKnotBins;
81
82 { // reorganize knots
83
84 int32_t lastBin = numberOfAxisBins; // last bin starts with U value 1.f, therefore it is outside of the [0.,1.] interval
85
86 vKnotBins.push_back(0); // obligatory knot at 0.0
87
88 for (int32_t i = 0; i < numberOfKnots; ++i) {
89 int32_t bin = (int32_t)roundf(inputKnots[i] * numberOfAxisBins);
90 if (bin <= vKnotBins.back() || bin >= lastBin) {
91 continue; // same knot
92 }
93 vKnotBins.push_back(bin);
94 }
95
96 vKnotBins.push_back(lastBin); // obligatory knot at 1.0
97
98 if (vKnotBins.size() < 5) { // too less knots, make a grid with 5 knots
99 vKnotBins.clear();
100 vKnotBins.push_back(0);
101 vKnotBins.push_back((int32_t)roundf(0.25 * numberOfAxisBins));
102 vKnotBins.push_back((int32_t)roundf(0.50 * numberOfAxisBins));
103 vKnotBins.push_back((int32_t)roundf(0.75 * numberOfAxisBins));
104 vKnotBins.push_back(lastBin);
105 }
106 }
107
108 mNumberOfKnots = vKnotBins.size();
109 mNumberOfAxisBins = numberOfAxisBins;
110 mBin2KnotMapOffset = mNumberOfKnots * sizeof(IrregularSpline1D::Knot);
111
112 FlatObject::finishConstruction(mBin2KnotMapOffset + (numberOfAxisBins + 1) * sizeof(int32_t));
113
114 IrregularSpline1D::Knot* s = getKnotsNonConst();
115
116 for (int32_t i = 0; i < mNumberOfKnots; i++) {
117 s[i].u = vKnotBins[i] / ((double)mNumberOfAxisBins); // do division in double
118 }
119
120 { // values will not be used, we define them for consistency
121 int32_t i = 0;
122 double du = (s[i + 1].u - s[i].u);
123 double x3 = (s[i + 2].u - s[i].u) / du;
124 s[i].scale = 1. / du;
125 s[i].scaleL0 = 0.; // undefined
126 s[i].scaleL2 = 0.; // undefined
127 s[i].scaleR2 = (x3 - 2.) / (x3 - 1.);
128 s[i].scaleR3 = 1. / (x3 * (x3 - 1.));
129 }
130
131 for (int32_t i = 1; i < mNumberOfKnots - 2; i++) {
132 double du = (s[i + 1].u - s[i].u);
133 double x0 = (s[i - 1].u - s[i].u) / du;
134 double x3 = (s[i + 2].u - s[i].u) / du;
135 s[i].scale = 1. / du;
136 s[i].scaleL0 = -1. / (x0 * (x0 - 1.));
137 s[i].scaleL2 = x0 / (x0 - 1.);
138 s[i].scaleR2 = (x3 - 2.) / (x3 - 1.);
139 s[i].scaleR3 = 1. / (x3 * (x3 - 1.));
140 }
141
142 { // values will not be used, we define them for consistency
143 int32_t i = mNumberOfKnots - 2;
144 double du = (s[i + 1].u - s[i].u);
145 double x0 = (s[i - 1].u - s[i].u) / du;
146 s[i].scale = 1. / du;
147 s[i].scaleL0 = -1. / (x0 * (x0 - 1.));
148 s[i].scaleL2 = x0 / (x0 - 1.);
149 s[i].scaleR2 = 0; // undefined
150 s[i].scaleR3 = 0; // undefined
151 }
152
153 { // values will not be used, we define them for consistency
154 int32_t i = mNumberOfKnots - 1;
155 s[i].scale = 0; // undefined
156 s[i].scaleL0 = 0; // undefined
157 s[i].scaleL2 = 0; // undefined
158 s[i].scaleR2 = 0; // undefined
159 s[i].scaleR3 = 0; // undefined
160 }
161
162 // Set up map (U bin) -> (knot index)
163
164 int32_t* map = getBin2KnotMapNonConst();
165
166 int32_t iKnotMin = 1;
167 int32_t iKnotMax = mNumberOfKnots - 3;
168
169 //
170 // With iKnotMin=1, iKnotMax=nKnots-3 we release edge intervals:
171 //
172 // Map U coordinates from the first segment [knot0,knot1] to the second segment [knot1,knot2].
173 // Map coordinates from segment [knot{n-2},knot{n-1}] to the previous segment [knot{n-3},knot{n-4}]
174 //
175 // This trick allows one to use splines without special conditions for edge cases.
176 // Any U from [0,1] is mapped to some knote i, where i-1, i, i+1, and i+2 knots always exist
177 //
178
179 for (int32_t iBin = 0, iKnot = iKnotMin; iBin <= mNumberOfAxisBins; iBin++) {
180 if ((iKnot < iKnotMax) && vKnotBins[iKnot + 1] == iBin) {
181 iKnot = iKnot + 1;
182 }
183 map[iBin] = iKnot;
184 }
185}
186
187void IrregularSpline1D::constructRegular(int32_t numberOfKnots)
188{
192
193 if (numberOfKnots < 5) {
194 numberOfKnots = 5;
195 }
196
197 std::vector<float> knots(numberOfKnots);
198 double du = 1. / (numberOfKnots - 1.);
199 for (int32_t i = 1; i < numberOfKnots - 1; i++) {
200 knots[i] = i * du;
201 }
202 knots[0] = 0.f;
203 knots[numberOfKnots - 1] = 1.f;
204 construct(numberOfKnots, knots.data(), numberOfKnots);
205}
206
208{
209#if !defined(GPUCA_GPUCODE)
210 LOG(info) << " Irregular Spline 1D: ";
211 LOG(info) << " mNumberOfKnots = " << mNumberOfKnots;
212 LOG(info) << " mNumberOfAxisBins = " << mNumberOfAxisBins;
213 LOG(info) << " mBin2KnotMapOffset = " << mBin2KnotMapOffset;
214 LOG(info) << " knots: ";
215 for (int32_t i = 0; i < mNumberOfKnots; i++) {
216 LOG(info) << getKnot(i).u << " ";
217 }
218 LOG(info);
219#endif
220}
int32_t i
Definition of IrregularSpline1D class.
GPUCA_GPUCODE.
Definition FlatObject.h:176
void destroy()
_______________ Utilities _______________________________________________
Definition FlatObject.h:349
void startConstruction()
_____________ Construction _________
Definition FlatObject.h:342
void finishConstruction(int32_t flatBufferSize)
Definition FlatObject.h:358
void cloneFromObject(const FlatObject &obj, char *newFlatBufferPtr)
Definition FlatObject.h:373
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"