Skip to content

Commit 46b3d0f

Browse files
author
Benedikt Führer
committed
improved const-correctness of internal Block structure as well as API interface
1 parent 1029eff commit 46b3d0f

File tree

2 files changed

+75
-40
lines changed

2 files changed

+75
-40
lines changed

src/fbow.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ void Vocabulary::setParams(int aligment, int k, int desc_type, int desc_size, in
4747

4848
}
4949

50-
void Vocabulary::transform(const cv::Mat &features, int level,fBow &result,fBow2&result2){
50+
void Vocabulary::transform(const cv::Mat &features, int level,fBow &result,fBow2&result2) const {
5151
if (features.rows==0) throw std::runtime_error("Vocabulary::transform No input data");
5252
if (features.type()!=_params._desc_type) throw std::runtime_error("Vocabulary::transform features are of different type than vocabulary");
5353
if (features.cols * features.elemSize() !=size_t(_params._desc_size)) throw std::runtime_error("Vocabulary::transform features are of different size than the vocabulary ones");
@@ -88,7 +88,7 @@ void Vocabulary::transform(const cv::Mat &features, int level,fBow &result,fBow2
8888

8989
}
9090

91-
fBow Vocabulary::transform(const cv::Mat &features)
91+
fBow Vocabulary::transform(const cv::Mat &features) const
9292
{
9393
if (features.rows==0) throw std::runtime_error("Vocabulary::transform No input data");
9494
if (features.type()!=_params._desc_type) throw std::runtime_error("Vocabulary::transform features are of different type than vocabulary");

src/fbow.h

Lines changed: 73 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ class FBOW_API Vocabulary
8888
Vocabulary(Vocabulary&&) = default;
8989

9090
//transform the features stored as rows in the returned BagOfWords
91-
fBow transform(const cv::Mat &features);
92-
void transform(const cv::Mat &features, int level,fBow &result,fBow2&result2);
91+
fBow transform(const cv::Mat &features) const;
92+
void transform(const cv::Mat &features, int level,fBow &result,fBow2&result2) const;
9393

9494

9595
//loads/saves from a file
@@ -168,24 +168,43 @@ class FBOW_API Vocabulary
168168
//CiWi are the so called block_node_info (see structure up)
169169
//Ci : either if the node is leaf (msb is set to 1) or not. If not leaf, the remaining 31 bits is the block where its children are. Else, it is the index of the feature that it represent
170170
//Wi: float value empkoyed to know the weight of a leaf node (employed in cases of bagofwords)
171-
struct Block{
172-
Block(char * bsptr,uint64_t ds,uint64_t ds_wp,uint64_t fo,uint64_t co):_blockstart(bsptr),_desc_size_bytes(ds),_desc_size_bytes_wp(ds_wp),_feature_off_start(fo),_child_off_start(co){}
171+
template<typename T>
172+
struct Block {
173+
174+
// conditionally qualifies its argument as const
175+
// depending on whether T is a const type as well
176+
template<typename TT>
177+
using conditional_const =
178+
std::conditional_t<
179+
std::is_const_v<T>,
180+
std::add_const_t<TT>,
181+
TT>;
182+
183+
Block(T* bsptr,uint64_t ds,uint64_t ds_wp,uint64_t fo,uint64_t co):_blockstart(bsptr),_desc_size_bytes(ds),_desc_size_bytes_wp(ds_wp),_feature_off_start(fo),_child_off_start(co){}
173184
Block(uint64_t ds,uint64_t ds_wp,uint64_t fo,uint64_t co):_desc_size_bytes(ds),_desc_size_bytes_wp(ds_wp),_feature_off_start(fo),_child_off_start(co){}
174185

175-
inline uint16_t getN()const{return (*((uint16_t*)(_blockstart)));}
176-
inline void setN(uint16_t n){ *((uint16_t*)(_blockstart))=n;}
186+
inline uint16_t getN() const { return (*((conditional_const<uint16_t>*)(_blockstart))); }
187+
inline void setN(uint16_t n) { *((conditional_const<uint16_t>*)(_blockstart)) = n; }
177188

178-
inline bool isLeaf()const{return *((uint16_t*)(_blockstart)+1);}
179-
inline void setLeaf(bool v)const{*((uint16_t*)(_blockstart)+1)=1;}
189+
inline bool isLeaf() const { return *((conditional_const<uint16_t>*)(_blockstart) + 1); }
190+
inline void setLeaf(bool v) { *((conditional_const<uint16_t>*)(_blockstart) + 1) = 1; }
180191

181-
inline void setParentId(uint32_t pid){*(((uint32_t*)(_blockstart))+1)=pid;}
182-
inline uint32_t getParentId(){ return *(((uint32_t*)(_blockstart))+1);}
192+
inline void setParentId(uint32_t pid) { *(((conditional_const<uint32_t>*)(_blockstart)) + 1) = pid; }
193+
inline uint32_t getParentId() const { return *(((conditional_const<uint32_t>*)(_blockstart)) + 1); }
183194

184-
inline block_node_info * getBlockNodeInfo(int i){ return (block_node_info *)(_blockstart+_child_off_start+i*sizeof(block_node_info)); }
185-
inline void setFeature(int i,const cv::Mat &feature){memcpy( _blockstart+_feature_off_start+i*_desc_size_bytes_wp,feature.ptr<char>(0),feature.elemSize1()*feature.cols); }
186-
inline void getFeature(int i,cv::Mat feature){ memcpy( feature.ptr<char>(0), _blockstart+_feature_off_start+i*_desc_size_bytes,_desc_size_bytes ); }
187-
template<typename T> inline T*getFeature(int i){return (T*) (_blockstart+_feature_off_start+i*_desc_size_bytes_wp);}
188-
char *_blockstart;
195+
inline conditional_const<block_node_info>* getBlockNodeInfo(int i) const
196+
{ return (conditional_const<block_node_info>*)(_blockstart + _child_off_start + i * sizeof(block_node_info)); }
197+
198+
inline void setFeature(int i,const cv::Mat &feature)
199+
{ memcpy(_blockstart + _feature_off_start + i * _desc_size_bytes_wp, feature.ptr<char>(0), feature.elemSize1()*feature.cols); }
200+
201+
inline void getFeature(int i,cv::Mat feature) const
202+
{ memcpy(feature.ptr<char>(0), _blockstart + _feature_off_start + i * _desc_size_bytes, _desc_size_bytes); }
203+
204+
template<typename T> inline conditional_const<T>*getFeature(int i)
205+
{ return (conditional_const<T>*)(_blockstart + _feature_off_start + i * _desc_size_bytes_wp); }
206+
207+
T* _blockstart;
189208
uint64_t _desc_size_bytes=0;//size of the descriptor(without padding)
190209
uint64_t _desc_size_bytes_wp=0;//size of the descriptor(includding padding)
191210
uint64_t _feature_off_start=0;
@@ -194,12 +213,26 @@ class FBOW_API Vocabulary
194213

195214

196215
//returns a block structure pointing at block b
197-
inline Block getBlock(uint32_t b) { assert(_data != 0); assert(b < _params._nblocks); return Block(_data.get() + b * _params._block_size_bytes_wp, _params._desc_size, _params._desc_size_bytes_wp, _params._feature_off_start, _params._child_off_start); }
216+
inline Block<const char> getBlock(uint32_t b) const
217+
{
218+
assert(_data != 0);
219+
assert(b < _params._nblocks);
220+
return Block<const char>(const_cast<const char*>(_data.get()) + b * _params._block_size_bytes_wp, _params._desc_size, _params._desc_size_bytes_wp, _params._feature_off_start, _params._child_off_start);
221+
}
222+
223+
inline Block<char> getBlock(uint32_t b)
224+
{
225+
assert(_data != 0);
226+
assert(b < _params._nblocks);
227+
return Block<char>(_data.get() + b * _params._block_size_bytes_wp, _params._desc_size, _params._desc_size_bytes_wp, _params._feature_off_start, _params._child_off_start);
228+
}
229+
198230
//given a block already create with getBlock, moves it to point to block b
199-
inline void setBlock(uint32_t b, Block &block) { block._blockstart = _data.get() + b * _params._block_size_bytes_wp; }
231+
template<typename T>
232+
inline void setBlock(uint32_t b, Block<T>& block) const { block._blockstart = _data.get() + b * _params._block_size_bytes_wp; }
200233

201234
//information about the cpu so that mmx,sse or avx extensions can be employed
202-
std::shared_ptr<cpu> cpu_info;
235+
mutable std::shared_ptr<cpu> cpu_info;
203236

204237

205238
////////////////////////////////////////////////////////////
@@ -226,33 +259,33 @@ class FBOW_API Vocabulary
226259
memset(feature,0,_nwords*sizeof(register_type ));
227260
}
228261
inline void startwithfeature(const register_type *feat_ptr){memcpy(feature,feat_ptr,_desc_size);}
229-
virtual distType computeDist(register_type *fptr)=0;
262+
virtual distType computeDist(const register_type *fptr)=0;
230263

231264
};
232265

233266

234267
struct L2_generic:public Lx<float,float,4>{
235268
virtual ~L2_generic(){ }
236-
inline float computeDist(float *fptr){
269+
inline float computeDist(const float *fptr){
237270
float d=0;
238271
for(int f=0;f<_nwords;f++) d+= (feature[f]-fptr[f])*(feature[f]-fptr[f]);
239272
return d;
240273
}
241274
};
242275
#ifdef __ANDROID__
243276
//fake elements to allow compilation
244-
struct L2_avx_generic:public Lx<uint64_t,float,32>{inline float computeDist(uint64_t *ptr){return std::numeric_limits<float>::max();}};
245-
struct L2_se3_generic:public Lx<uint64_t,float,32>{inline float computeDist(uint64_t *ptr){return std::numeric_limits<float>::max();}};
246-
struct L2_sse3_16w:public Lx<uint64_t,float,32>{inline float computeDist(uint64_t *ptr){return std::numeric_limits<float>::max();}};
247-
struct L2_avx_8w:public Lx<uint64_t,float,32>{inline float computeDist(uint64_t *ptr){return std::numeric_limits<float>::max();}};
277+
struct L2_avx_generic:public Lx<uint64_t,float,32>{inline float computeDist(const uint64_t *ptr){return std::numeric_limits<float>::max();}};
278+
struct L2_se3_generic:public Lx<uint64_t,float,32>{inline float computeDist(const uint64_t *ptr){return std::numeric_limits<float>::max();}};
279+
struct L2_sse3_16w:public Lx<uint64_t,float,32>{inline float computeDist(const uint64_t *ptr){return std::numeric_limits<float>::max();}};
280+
struct L2_avx_8w:public Lx<uint64_t,float,32>{inline float computeDist(const uint64_t *ptr){return std::numeric_limits<float>::max();}};
248281

249282

250283

251284

252285
#else
253286
struct L2_avx_generic:public Lx<__m256,float,32>{
254287
virtual ~L2_avx_generic(){}
255-
inline float computeDist(__m256 *ptr){
288+
inline float computeDist(const __m256 *ptr){
256289
__m256 sum=_mm256_setzero_ps(), sub_mult;
257290
//substract, multiply and accumulate
258291
for(int i=0;i<_nwords;i++){
@@ -267,7 +300,7 @@ class FBOW_API Vocabulary
267300
}
268301
};
269302
struct L2_se3_generic:public Lx<__m128,float,16>{
270-
inline float computeDist(__m128 *ptr){
303+
inline float computeDist(const __m128 *ptr){
271304
__m128 sum=_mm_setzero_ps(), sub_mult;
272305
//substract, multiply and accumulate
273306
for(int i=0;i<_nwords;i++){
@@ -283,7 +316,7 @@ class FBOW_API Vocabulary
283316
};
284317
struct L2_sse3_16w:public Lx<__m128,float,16> {
285318

286-
inline float computeDist(__m128 *ptr){
319+
inline float computeDist(const __m128 *ptr){
287320
__m128 sum=_mm_setzero_ps(), sub_mult;
288321
//substract, multiply and accumulate
289322
for(int i=0;i<16;i++){
@@ -300,7 +333,7 @@ class FBOW_API Vocabulary
300333
//specific for surf in avx
301334
struct L2_avx_8w:public Lx<__m256,float,32> {
302335

303-
inline float computeDist(__m256 *ptr){
336+
inline float computeDist(const __m256 *ptr){
304337
__m256 sum=_mm256_setzero_ps(), sub_mult;
305338
//substract, multiply and accumulate
306339

@@ -321,15 +354,15 @@ class FBOW_API Vocabulary
321354

322355
//generic hamming distance calculator
323356
struct L1_x64:public Lx<uint64_t,uint64_t,8>{
324-
inline uint64_t computeDist(uint64_t *feat_ptr){
357+
inline uint64_t computeDist(const uint64_t *feat_ptr){
325358
uint64_t result = 0;
326359
for(int i = 0; i < _nwords; ++i ) result += std::bitset<64>(feat_ptr[i] ^ feature[i]).count();
327360
return result;
328361
}
329362
};
330363

331364
struct L1_x32:public Lx<uint32_t,uint32_t,8>{
332-
inline uint32_t computeDist(uint32_t *feat_ptr){
365+
inline uint32_t computeDist(const uint32_t *feat_ptr){
333366
uint32_t result = 0;
334367
for(int i = 0; i < _nwords; ++i ) result += std::bitset<32>(feat_ptr[i] ^ feature[i]).count();
335368
return result;
@@ -339,7 +372,7 @@ class FBOW_API Vocabulary
339372

340373
//for orb
341374
struct L1_32bytes:public Lx<uint64_t,uint64_t,8>{
342-
inline uint64_t computeDist(uint64_t *feat_ptr){
375+
inline uint64_t computeDist(const uint64_t *feat_ptr){
343376
return uint64_popcnt(feat_ptr[0]^feature[0])+ uint64_popcnt(feat_ptr[1]^feature[1])+
344377
uint64_popcnt(feat_ptr[2]^feature[2])+uint64_popcnt(feat_ptr[3]^feature[3]);
345378
}
@@ -350,7 +383,7 @@ class FBOW_API Vocabulary
350383
};
351384
//for akaze
352385
struct L1_61bytes:public Lx<uint64_t,uint64_t,8>{
353-
inline uint64_t computeDist(uint64_t *feat_ptr){
386+
inline uint64_t computeDist(const uint64_t *feat_ptr){
354387

355388
return uint64_popcnt(feat_ptr[0]^feature[0])+ uint64_popcnt(feat_ptr[1]^feature[1])+
356389
uint64_popcnt(feat_ptr[2]^feature[2])+uint64_popcnt(feat_ptr[3]^feature[3])+
@@ -364,19 +397,20 @@ class FBOW_API Vocabulary
364397

365398

366399
template<typename Computer>
367-
fBow _transform(const cv::Mat &features){
400+
fBow _transform(const cv::Mat &features) const {
368401
Computer comp;
369402
comp.setParams(_params._desc_size,_params._desc_size_bytes_wp);
370403
using DType=typename Computer::DType;//distance type
371404
using TData=typename Computer::TData;//data type
372405

373406
fBow result;
374407
std::pair<DType,uint32_t> best_dist_idx(std::numeric_limits<uint32_t>::max(),0);//minimum distance found
375-
block_node_info *bn_info;
408+
const block_node_info *bn_info;
376409
for(int cur_feature=0;cur_feature<features.rows;cur_feature++){
377410
comp.startwithfeature(features.ptr<TData>(cur_feature));
378411
//ensure feature is in a
379-
Block c_block=getBlock(0);
412+
//(jbfuehrer: template type can automatically be deduced since C++17)
413+
Block<const char> c_block=getBlock(0);
380414
//copy to another structure and add padding with zeros
381415
do{
382416
//given the current block, finds the node with minimum distance
@@ -397,7 +431,7 @@ class FBOW_API Vocabulary
397431
return result;
398432
}
399433
template<typename Computer>
400-
void _transform2(const cv::Mat &features,uint32_t storeLevel,fBow &r1,fBow2 &r2){
434+
void _transform2(const cv::Mat &features,uint32_t storeLevel,fBow &r1,fBow2 &r2) const {
401435
Computer comp;
402436
comp.setParams(_params._desc_size,_params._desc_size_bytes_wp);
403437
using DType=typename Computer::DType;//distance type
@@ -406,12 +440,13 @@ class FBOW_API Vocabulary
406440
r1.clear();
407441
r2.clear();
408442
std::pair<DType,uint32_t> best_dist_idx(std::numeric_limits<uint32_t>::max(),0);//minimum distance found
409-
block_node_info *bn_info;
443+
const block_node_info *bn_info;
410444
int nbits=ceil(log2(_params._m_k));
411445
for(int cur_feature=0;cur_feature<features.rows;cur_feature++){
412446
comp.startwithfeature(features.ptr<TData>(cur_feature));
413447
//ensure feature is in a
414-
Block c_block=getBlock(0);
448+
//(jbfuehrer: template type can automatically be deduced since C++17)
449+
Block<const char> c_block=getBlock(0);
415450
uint32_t level=0;//current level of recursion
416451
uint32_t curNode=0;//id of the current node of the tree
417452
//copy to another structure and add padding with zeros

0 commit comments

Comments
 (0)