Skip to content

Commit e24c9c0

Browse files
author
Benedikt Führer
committed
improved const-correctness of internal Block structure as well as API interface
1 parent e148dbc commit e24c9c0

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
@@ -48,7 +48,7 @@ void Vocabulary::setParams(int aligment, int k, int desc_type, int desc_size, in
4848

4949
}
5050

51-
void Vocabulary::transform(const cv::Mat &features, int level,fBow &result,fBow2&result2){
51+
void Vocabulary::transform(const cv::Mat &features, int level,fBow &result,fBow2&result2) const {
5252
if (features.rows==0) throw std::runtime_error("Vocabulary::transform No input data");
5353
if (features.type()!=_params._desc_type) throw std::runtime_error("Vocabulary::transform features are of different type than vocabulary");
5454
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");
@@ -89,7 +89,7 @@ void Vocabulary::transform(const cv::Mat &features, int level,fBow &result,fBow2
8989

9090
}
9191

92-
fBow Vocabulary::transform(const cv::Mat &features)
92+
fBow Vocabulary::transform(const cv::Mat &features) const
9393
{
9494
if (features.rows==0) throw std::runtime_error("Vocabulary::transform No input data");
9595
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
@@ -89,8 +89,8 @@ class FBOW_API Vocabulary
8989
Vocabulary(Vocabulary&&) = default;
9090

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

9595

9696
//loads/saves from a file
@@ -170,24 +170,43 @@ class FBOW_API Vocabulary
170170
//CiWi are the so called block_node_info (see structure up)
171171
//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
172172
//Wi: float value empkoyed to know the weight of a leaf node (employed in cases of bagofwords)
173-
struct Block{
174-
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){}
173+
template<typename T>
174+
struct Block {
175+
176+
// conditionally qualifies its argument as const
177+
// depending on whether T is a const type as well
178+
template<typename TT>
179+
using conditional_const =
180+
std::conditional_t<
181+
std::is_const_v<T>,
182+
std::add_const_t<TT>,
183+
TT>;
184+
185+
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){}
175186
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){}
176187

177-
inline uint16_t getN()const{return (*((uint16_t*)(_blockstart)));}
178-
inline void setN(uint16_t n){ *((uint16_t*)(_blockstart))=n;}
188+
inline uint16_t getN() const { return (*((conditional_const<uint16_t>*)(_blockstart))); }
189+
inline void setN(uint16_t n) { *((conditional_const<uint16_t>*)(_blockstart)) = n; }
179190

180-
inline bool isLeaf()const{return *((uint16_t*)(_blockstart)+1);}
181-
inline void setLeaf(bool v)const{*((uint16_t*)(_blockstart)+1)=1;}
191+
inline bool isLeaf() const { return *((conditional_const<uint16_t>*)(_blockstart) + 1); }
192+
inline void setLeaf(bool v) { *((conditional_const<uint16_t>*)(_blockstart) + 1) = 1; }
182193

183-
inline void setParentId(uint32_t pid){*(((uint32_t*)(_blockstart))+1)=pid;}
184-
inline uint32_t getParentId(){ return *(((uint32_t*)(_blockstart))+1);}
194+
inline void setParentId(uint32_t pid) { *(((conditional_const<uint32_t>*)(_blockstart)) + 1) = pid; }
195+
inline uint32_t getParentId() const { return *(((conditional_const<uint32_t>*)(_blockstart)) + 1); }
185196

186-
inline block_node_info * getBlockNodeInfo(int i){ return (block_node_info *)(_blockstart+_child_off_start+i*sizeof(block_node_info)); }
187-
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); }
188-
inline void getFeature(int i,cv::Mat feature){ memcpy( feature.ptr<char>(0), _blockstart+_feature_off_start+i*_desc_size_bytes,_desc_size_bytes ); }
189-
template<typename T> inline T*getFeature(int i){return (T*) (_blockstart+_feature_off_start+i*_desc_size_bytes_wp);}
190-
char *_blockstart;
197+
inline conditional_const<block_node_info>* getBlockNodeInfo(int i) const
198+
{ return (conditional_const<block_node_info>*)(_blockstart + _child_off_start + i * sizeof(block_node_info)); }
199+
200+
inline void setFeature(int i,const cv::Mat &feature)
201+
{ memcpy(_blockstart + _feature_off_start + i * _desc_size_bytes_wp, feature.ptr<char>(0), feature.elemSize1()*feature.cols); }
202+
203+
inline void getFeature(int i,cv::Mat feature) const
204+
{ memcpy(feature.ptr<char>(0), _blockstart + _feature_off_start + i * _desc_size_bytes, _desc_size_bytes); }
205+
206+
template<typename T> inline conditional_const<T>*getFeature(int i)
207+
{ return (conditional_const<T>*)(_blockstart + _feature_off_start + i * _desc_size_bytes_wp); }
208+
209+
T* _blockstart;
191210
uint64_t _desc_size_bytes=0;//size of the descriptor(without padding)
192211
uint64_t _desc_size_bytes_wp=0;//size of the descriptor(includding padding)
193212
uint64_t _feature_off_start=0;
@@ -196,12 +215,26 @@ class FBOW_API Vocabulary
196215

197216

198217
//returns a block structure pointing at block b
199-
inline Block getBlock(uint32_t b) { assert(_data.get() != nullptr); 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); }
218+
inline Block<const char> getBlock(uint32_t b) const
219+
{
220+
assert(_data != nullptr);
221+
assert(b < _params._nblocks);
222+
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);
223+
}
224+
225+
inline Block<char> getBlock(uint32_t b)
226+
{
227+
assert(_data != nullptr);
228+
assert(b < _params._nblocks);
229+
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);
230+
}
231+
200232
//given a block already create with getBlock, moves it to point to block b
201-
inline void setBlock(uint32_t b, Block &block) { block._blockstart = _data.get() + b * _params._block_size_bytes_wp; }
233+
template<typename T>
234+
inline void setBlock(uint32_t b, Block<T>& block) const { block._blockstart = _data.get() + b * _params._block_size_bytes_wp; }
202235

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

206239

207240
////////////////////////////////////////////////////////////
@@ -228,33 +261,33 @@ class FBOW_API Vocabulary
228261
memset(feature,0,_nwords*sizeof(register_type ));
229262
}
230263
inline void startwithfeature(const register_type *feat_ptr){memcpy(feature,feat_ptr,_desc_size);}
231-
virtual distType computeDist(register_type *fptr)=0;
264+
virtual distType computeDist(const register_type *fptr)=0;
232265

233266
};
234267

235268

236269
struct L2_generic:public Lx<float,float,4>{
237270
virtual ~L2_generic(){ }
238-
inline float computeDist(float *fptr){
271+
inline float computeDist(const float *fptr){
239272
float d=0;
240273
for(int f=0;f<_nwords;f++) d+= (feature[f]-fptr[f])*(feature[f]-fptr[f]);
241274
return d;
242275
}
243276
};
244277
#ifdef __ANDROID__
245278
//fake elements to allow compilation
246-
struct L2_avx_generic:public Lx<uint64_t,float,32>{inline float computeDist(uint64_t *ptr){return std::numeric_limits<float>::max();}};
247-
struct L2_se3_generic:public Lx<uint64_t,float,32>{inline float computeDist(uint64_t *ptr){return std::numeric_limits<float>::max();}};
248-
struct L2_sse3_16w:public Lx<uint64_t,float,32>{inline float computeDist(uint64_t *ptr){return std::numeric_limits<float>::max();}};
249-
struct L2_avx_8w:public Lx<uint64_t,float,32>{inline float computeDist(uint64_t *ptr){return std::numeric_limits<float>::max();}};
279+
struct L2_avx_generic:public Lx<uint64_t,float,32>{inline float computeDist(const uint64_t *ptr){return std::numeric_limits<float>::max();}};
280+
struct L2_se3_generic:public Lx<uint64_t,float,32>{inline float computeDist(const uint64_t *ptr){return std::numeric_limits<float>::max();}};
281+
struct L2_sse3_16w:public Lx<uint64_t,float,32>{inline float computeDist(const uint64_t *ptr){return std::numeric_limits<float>::max();}};
282+
struct L2_avx_8w:public Lx<uint64_t,float,32>{inline float computeDist(const uint64_t *ptr){return std::numeric_limits<float>::max();}};
250283

251284

252285

253286

254287
#else
255288
struct L2_avx_generic:public Lx<__m256,float,32>{
256289
virtual ~L2_avx_generic(){}
257-
inline float computeDist(__m256 *ptr){
290+
inline float computeDist(const __m256 *ptr){
258291
__m256 sum=_mm256_setzero_ps(), sub_mult;
259292
//substract, multiply and accumulate
260293
for(int i=0;i<_nwords;i++){
@@ -269,7 +302,7 @@ class FBOW_API Vocabulary
269302
}
270303
};
271304
struct L2_se3_generic:public Lx<__m128,float,16>{
272-
inline float computeDist(__m128 *ptr){
305+
inline float computeDist(const __m128 *ptr){
273306
__m128 sum=_mm_setzero_ps(), sub_mult;
274307
//substract, multiply and accumulate
275308
for(int i=0;i<_nwords;i++){
@@ -285,7 +318,7 @@ class FBOW_API Vocabulary
285318
};
286319
struct L2_sse3_16w:public Lx<__m128,float,16> {
287320

288-
inline float computeDist(__m128 *ptr){
321+
inline float computeDist(const __m128 *ptr){
289322
__m128 sum=_mm_setzero_ps(), sub_mult;
290323
//substract, multiply and accumulate
291324
for(int i=0;i<16;i++){
@@ -302,7 +335,7 @@ class FBOW_API Vocabulary
302335
//specific for surf in avx
303336
struct L2_avx_8w:public Lx<__m256,float,32> {
304337

305-
inline float computeDist(__m256 *ptr){
338+
inline float computeDist(const __m256 *ptr){
306339
__m256 sum=_mm256_setzero_ps(), sub_mult;
307340
//substract, multiply and accumulate
308341

@@ -323,15 +356,15 @@ class FBOW_API Vocabulary
323356

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

333366
struct L1_x32:public Lx<uint32_t,uint32_t,8>{
334-
inline uint32_t computeDist(uint32_t *feat_ptr){
367+
inline uint32_t computeDist(const uint32_t *feat_ptr){
335368
uint32_t result = 0;
336369
for(int i = 0; i < _nwords; ++i ) result += std::bitset<32>(feat_ptr[i] ^ feature[i]).count();
337370
return result;
@@ -341,7 +374,7 @@ class FBOW_API Vocabulary
341374

342375
//for orb
343376
struct L1_32bytes:public Lx<uint64_t,uint64_t,8>{
344-
inline uint64_t computeDist(uint64_t *feat_ptr){
377+
inline uint64_t computeDist(const uint64_t *feat_ptr){
345378
return uint64_popcnt(feat_ptr[0]^feature[0])+ uint64_popcnt(feat_ptr[1]^feature[1])+
346379
uint64_popcnt(feat_ptr[2]^feature[2])+uint64_popcnt(feat_ptr[3]^feature[3]);
347380
}
@@ -352,7 +385,7 @@ class FBOW_API Vocabulary
352385
};
353386
//for akaze
354387
struct L1_61bytes:public Lx<uint64_t,uint64_t,8>{
355-
inline uint64_t computeDist(uint64_t *feat_ptr){
388+
inline uint64_t computeDist(const uint64_t *feat_ptr){
356389

357390
return uint64_popcnt(feat_ptr[0]^feature[0])+ uint64_popcnt(feat_ptr[1]^feature[1])+
358391
uint64_popcnt(feat_ptr[2]^feature[2])+uint64_popcnt(feat_ptr[3]^feature[3])+
@@ -366,19 +399,20 @@ class FBOW_API Vocabulary
366399

367400

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

375408
fBow result;
376409
std::pair<DType,uint32_t> best_dist_idx(std::numeric_limits<uint32_t>::max(),0);//minimum distance found
377-
block_node_info *bn_info;
410+
const block_node_info *bn_info;
378411
for(int cur_feature=0;cur_feature<features.rows;cur_feature++){
379412
comp.startwithfeature(features.ptr<TData>(cur_feature));
380413
//ensure feature is in a
381-
Block c_block=getBlock(0);
414+
//(jbfuehrer: template type can automatically be deduced since C++17)
415+
Block<const char> c_block=getBlock(0);
382416
//copy to another structure and add padding with zeros
383417
do{
384418
//given the current block, finds the node with minimum distance
@@ -399,7 +433,7 @@ class FBOW_API Vocabulary
399433
return result;
400434
}
401435
template<typename Computer>
402-
void _transform2(const cv::Mat &features,uint32_t storeLevel,fBow &r1,fBow2 &r2){
436+
void _transform2(const cv::Mat &features,uint32_t storeLevel,fBow &r1,fBow2 &r2) const {
403437
Computer comp;
404438
comp.setParams(_params._desc_size,_params._desc_size_bytes_wp);
405439
using DType=typename Computer::DType;//distance type
@@ -408,12 +442,13 @@ class FBOW_API Vocabulary
408442
r1.clear();
409443
r2.clear();
410444
std::pair<DType,uint32_t> best_dist_idx(std::numeric_limits<uint32_t>::max(),0);//minimum distance found
411-
block_node_info *bn_info;
445+
const block_node_info *bn_info;
412446
int nbits=ceil(log2(_params._m_k));
413447
for(int cur_feature=0;cur_feature<features.rows;cur_feature++){
414448
comp.startwithfeature(features.ptr<TData>(cur_feature));
415449
//ensure feature is in a
416-
Block c_block=getBlock(0);
450+
//(jbfuehrer: template type can automatically be deduced since C++17)
451+
Block<const char> c_block=getBlock(0);
417452
uint32_t level=0;//current level of recursion
418453
uint32_t curNode=0;//id of the current node of the tree
419454
//copy to another structure and add padding with zeros

0 commit comments

Comments
 (0)