00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef _SIMPLEFEATURES__H__
00013 #define _SIMPLEFEATURES__H__
00014
00015 #include "lib/common.h"
00016 #include "lib/Mathematics.h"
00017 #include "lib/io.h"
00018 #include "lib/Cache.h"
00019 #include "lib/File.h"
00020 #include "preproc/SimplePreProc.h"
00021 #include "features/DotFeatures.h"
00022 #include "features/StringFeatures.h"
00023
00024 #include <string.h>
00025
00026 template <class ST> class CStringFeatures;
00027 template <class ST> class CSimpleFeatures;
00028 template <class ST> class CSimplePreProc;
00029
00059 template <class ST> class CSimpleFeatures: public CDotFeatures
00060 {
00061 public:
00066 CSimpleFeatures(int32_t size=0)
00067 : CDotFeatures(size), num_vectors(0), num_features(0),
00068 feature_matrix(NULL), feature_cache(NULL) {}
00069
00071 CSimpleFeatures(const CSimpleFeatures & orig)
00072 : CDotFeatures(orig), num_vectors(orig.num_vectors),
00073 num_features(orig.num_features),
00074 feature_matrix(orig.feature_matrix),
00075 feature_cache(orig.feature_cache)
00076 {
00077 if (orig.feature_matrix)
00078 {
00079 free_feature_matrix();
00080 feature_matrix=new ST(num_vectors*num_features);
00081 memcpy(feature_matrix, orig.feature_matrix, sizeof(float64_t)*num_vectors*num_features);
00082 }
00083 }
00084
00091 CSimpleFeatures(ST* src, int32_t num_feat, int32_t num_vec)
00092 : CDotFeatures(0), num_vectors(0), num_features(0),
00093 feature_matrix(NULL), feature_cache(NULL)
00094 {
00095 copy_feature_matrix(src, num_feat, num_vec);
00096 }
00097
00104 CSimpleFeatures(char* fname)
00105 : CDotFeatures(fname), num_vectors(0), num_features(0),
00106 feature_matrix(NULL), feature_cache(NULL) {}
00107
00112 virtual CFeatures* duplicate() const
00113 {
00114 return new CSimpleFeatures<ST>(*this);
00115 }
00116
00117 virtual ~CSimpleFeatures()
00118 {
00119 SG_DEBUG("deleting simplefeatures (0x%p)\n", this);
00120 free_features();
00121 }
00122
00126 void free_feature_matrix()
00127 {
00128 delete[] feature_matrix;
00129 feature_matrix = NULL;
00130 num_vectors=0;
00131 num_features=0;
00132 }
00133
00137 void free_features()
00138 {
00139 free_feature_matrix();
00140 delete feature_cache;
00141 feature_cache = NULL;
00142 }
00143
00154 ST* get_feature_vector(int32_t num, int32_t& len, bool& dofree)
00155 {
00156 len=num_features;
00157
00158 if (feature_matrix)
00159 {
00160 dofree=false;
00161 return &feature_matrix[num*num_features];
00162 }
00163 else
00164 {
00165 SG_DEBUG( "compute feature!!!\n") ;
00166
00167 ST* feat=NULL;
00168 dofree=false;
00169
00170 if (feature_cache)
00171 {
00172 feat=feature_cache->lock_entry(num);
00173
00174 if (feat)
00175 return feat;
00176 else
00177 {
00178 feat=feature_cache->set_entry(num);
00179 }
00180 }
00181
00182 if (!feat)
00183 dofree=true;
00184 feat=compute_feature_vector(num, len, feat);
00185
00186
00187 if (get_num_preproc())
00188 {
00189 int32_t tmp_len=len;
00190 ST* tmp_feat_before = feat;
00191 ST* tmp_feat_after = NULL;
00192
00193 for (int32_t i=0; i<get_num_preproc(); i++)
00194 {
00195 CSimplePreProc<ST>* p = (CSimplePreProc<ST>*) get_preproc(i);
00196 tmp_feat_after=p->apply_to_feature_vector(tmp_feat_before, tmp_len);
00197 SG_UNREF(p);
00198
00199 if (i!=0)
00200 delete[] tmp_feat_before;
00201 tmp_feat_before=tmp_feat_after;
00202 }
00203
00204 memcpy(feat, tmp_feat_after, sizeof(ST)*tmp_len);
00205 delete[] tmp_feat_after;
00206
00207 len=tmp_len ;
00208 SG_DEBUG( "len: %d len2: %d\n", len, num_features);
00209 }
00210 return feat ;
00211 }
00212 }
00213
00222 void set_feature_vector(ST* src, int32_t len, int32_t num)
00223 {
00224 if (num>=num_vectors)
00225 {
00226 SG_ERROR("Index out of bounds (number of vectors %d, you "
00227 "requested %d)\n", num_vectors, num);
00228 }
00229
00230 if (!feature_matrix)
00231 SG_ERROR("Requires a in-memory feature matrix\n");
00232
00233 if (len != num_features)
00234 SG_ERROR("Vector not of length %d (has %d)\n", num_features, len);
00235
00236 memcpy(&feature_matrix[num*num_features], src, num_features*sizeof(ST));
00237 }
00238
00245 void get_feature_vector(ST** dst, int32_t* len, int32_t num)
00246 {
00247 if (num>=num_vectors)
00248 {
00249 SG_ERROR("Index out of bounds (number of vectors %d, you "
00250 "requested %d)\n", num_vectors, num);
00251 }
00252
00253 int32_t vlen=0;
00254 bool free_vec;
00255
00256 ST* vec= get_feature_vector(num, vlen, free_vec);
00257
00258 *len=vlen;
00259 *dst=(ST*) malloc(vlen*sizeof(ST));
00260 memcpy(*dst, vec, vlen*sizeof(ST));
00261
00262 free_feature_vector(vec, num, free_vec);
00263 }
00264
00271 void free_feature_vector(ST* feat_vec, int32_t num, bool dofree)
00272 {
00273 if (feature_cache)
00274 feature_cache->unlock_entry(num);
00275
00276 if (dofree)
00277 delete[] feat_vec ;
00278 }
00279
00287 void get_feature_matrix(ST** dst, int32_t* num_feat, int32_t* num_vec)
00288 {
00289 ASSERT(feature_matrix);
00290
00291 int64_t num=num_features*num_vectors;
00292 *num_feat=num_features;
00293 *num_vec=num_vectors;
00294 *dst=(ST*) malloc(sizeof(ST)*num);
00295 memcpy(*dst, feature_matrix, num * sizeof(ST));
00296 }
00297
00305 ST* get_feature_matrix(int32_t &num_feat, int32_t &num_vec)
00306 {
00307 num_feat=num_features;
00308 num_vec=num_vectors;
00309 return feature_matrix;
00310 }
00311
00322 virtual void set_feature_matrix(ST* fm, int32_t num_feat, int32_t num_vec)
00323 {
00324 free_feature_matrix();
00325 feature_matrix=fm;
00326 num_features=num_feat;
00327 num_vectors=num_vec;
00328 }
00329
00339 virtual void copy_feature_matrix(ST* src, int32_t num_feat, int32_t num_vec)
00340 {
00341 free_feature_matrix();
00342 feature_matrix=new ST[((int64_t) num_feat)*num_vec];
00343 memcpy(feature_matrix, src, (sizeof(ST)*((int64_t) num_feat)*num_vec));
00344
00345 num_features=num_feat;
00346 num_vectors=num_vec;
00347 }
00348
00354 virtual bool apply_preproc(bool force_preprocessing=false)
00355 {
00356 SG_DEBUG( "force: %d\n", force_preprocessing);
00357
00358 if ( feature_matrix && get_num_preproc())
00359 {
00360
00361 for (int32_t i=0; i<get_num_preproc(); i++)
00362 {
00363 if ( (!is_preprocessed(i) || force_preprocessing) )
00364 {
00365 set_preprocessed(i);
00366 CSimplePreProc<ST>* p = (CSimplePreProc<ST>*) get_preproc(i);
00367 SG_INFO( "preprocessing using preproc %s\n", p->get_name());
00368 if (p->apply_to_feature_matrix(this) == NULL)
00369 {
00370 SG_UNREF(p);
00371 return false;
00372 }
00373 SG_UNREF(p);
00374 }
00375 }
00376 return true;
00377 }
00378 else
00379 {
00380 if (!feature_matrix)
00381 SG_ERROR( "no feature matrix\n");
00382
00383 if (!get_num_preproc())
00384 SG_ERROR( "no preprocessors available\n");
00385
00386 return false;
00387 }
00388 }
00389
00394 virtual int32_t get_size() { return sizeof(ST); }
00395
00396
00401 virtual inline int32_t get_num_vectors() { return num_vectors; }
00402
00407 inline int32_t get_num_features() { return num_features; }
00408
00413 inline void set_num_features(int32_t num)
00414 {
00415 num_features= num;
00416
00417 if (num_features && num_vectors)
00418 {
00419 delete feature_cache;
00420 feature_cache= new CCache<ST>(get_cache_size(), num_features, num_vectors);
00421 }
00422 }
00423
00428 inline void set_num_vectors(int32_t num)
00429 {
00430 num_vectors= num;
00431 if (num_features && num_vectors)
00432 {
00433 delete feature_cache;
00434 feature_cache= new CCache<ST>(get_cache_size(), num_features, num_vectors);
00435 }
00436 }
00437
00442 inline virtual EFeatureClass get_feature_class() { return C_SIMPLE; }
00443
00448 inline virtual EFeatureType get_feature_type();
00449
00456 virtual bool reshape(int32_t p_num_features, int32_t p_num_vectors)
00457 {
00458 if (p_num_features*p_num_vectors == this->num_features * this->num_vectors)
00459 {
00460 this->num_features=p_num_features;
00461 this->num_vectors=p_num_vectors;
00462 return true;
00463 }
00464 else
00465 return false;
00466 }
00467
00475 virtual int32_t get_dim_feature_space()
00476 {
00477 return num_features;
00478 }
00479
00486 virtual float64_t dot(int32_t vec_idx1, int32_t vec_idx2)
00487 {
00488 int32_t len1, len2;
00489 bool free1, free2;
00490
00491 ST* vec1= get_feature_vector(vec_idx1, len1, free1);
00492 ST* vec2= get_feature_vector(vec_idx2, len2, free2);
00493
00494 float64_t result=CMath::dot(vec1, vec2, len1);
00495
00496 free_feature_vector(vec1, vec_idx1, free1);
00497 free_feature_vector(vec2, vec_idx2, free2);
00498
00499 return result;
00500 }
00501
00508 virtual float64_t dense_dot(int32_t vec_idx1, const float64_t* vec2, int32_t vec2_len);
00509
00518 virtual void add_to_dense_vec(float64_t alpha, int32_t vec_idx1, float64_t* vec2, int32_t vec2_len, bool abs_val=false)
00519 {
00520 ASSERT(vec2_len == num_features);
00521
00522 int32_t vlen;
00523 bool vfree;
00524 ST* vec1=get_feature_vector(vec_idx1, vlen, vfree);
00525
00526 ASSERT(vlen == num_features);
00527
00528 if (abs_val)
00529 {
00530 for (int32_t i=0; i<num_features; i++)
00531 vec2[i]+=alpha*CMath::abs(vec1[i]);
00532 }
00533 else
00534 {
00535 for (int32_t i=0; i<num_features; i++)
00536 vec2[i]+=alpha*vec1[i];
00537 }
00538
00539 free_feature_vector(vec1, vec_idx1, vfree);
00540 }
00541
00547 virtual inline int32_t get_nnz_features_for_vector(int32_t num)
00548 {
00549 return num_features;
00550 }
00551
00559 virtual inline bool Align_char_features(
00560 CStringFeatures<char>* cf, CStringFeatures<char>* Ref, float64_t gapCost)
00561 {
00562 return false;
00563 }
00564
00570 virtual bool load(char* fname)
00571 {
00572 bool status=false;
00573 num_vectors=1;
00574 num_features=0;
00575 CFile f(fname, 'r', get_feature_type());
00576 int64_t numf=0;
00577 free_feature_matrix();
00578 feature_matrix=f.load_data<ST>(NULL, numf);
00579 num_features=numf;
00580
00581 if (!f.is_ok())
00582 SG_ERROR( "loading file \"%s\" failed", fname);
00583 else
00584 status=true;
00585
00586 return status;
00587 }
00588
00594 virtual bool save(char* fname)
00595 {
00596 int32_t len;
00597 bool free;
00598 ST* fv;
00599
00600 CFile f(fname, 'w', get_feature_type());
00601
00602 for (int32_t i=0; i< (int32_t) num_vectors && f.is_ok(); i++)
00603 {
00604 if (!(i % (num_vectors/10+1)))
00605 SG_PRINT( "%02d%%.", (int) (100.0*i/num_vectors));
00606 else if (!(i % (num_vectors/200+1)))
00607 SG_PRINT( ".");
00608
00609 fv=get_feature_vector(i, len, free);
00610 f.save_data<ST>(fv, len);
00611 free_feature_vector(fv, i, free) ;
00612 }
00613
00614 if (f.is_ok())
00615 SG_INFO( "%d vectors with %d features each successfully written (filesize: %ld)\n", num_vectors, num_features, num_vectors*num_features*sizeof(float64_t));
00616
00617 return true;
00618 }
00619
00621 inline virtual const char* get_name() const { return "SimpleFeatures"; }
00622
00623 protected:
00635 virtual ST* compute_feature_vector(int32_t num, int32_t& len, ST* target=NULL)
00636 {
00637 len=0;
00638 return NULL;
00639 }
00640
00642 int32_t num_vectors;
00643
00645 int32_t num_features;
00646
00648 ST* feature_matrix;
00649
00651 CCache<ST>* feature_cache;
00652 };
00653
00654 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00655
00659 template<> inline EFeatureType CSimpleFeatures<bool>::get_feature_type()
00660 {
00661 return F_BOOL;
00662 }
00663
00668 template<> inline EFeatureType CSimpleFeatures<char>::get_feature_type()
00669 {
00670 return F_CHAR;
00671 }
00672
00677 template<> inline EFeatureType CSimpleFeatures<uint8_t>::get_feature_type()
00678 {
00679 return F_BYTE;
00680 }
00681
00686 template<> inline EFeatureType CSimpleFeatures<int16_t>::get_feature_type()
00687 {
00688 return F_SHORT;
00689 }
00690
00695 template<> inline EFeatureType CSimpleFeatures<uint16_t>::get_feature_type()
00696 {
00697 return F_WORD;
00698 }
00699
00700
00705 template<> inline EFeatureType CSimpleFeatures<int32_t>::get_feature_type()
00706 {
00707 return F_INT;
00708 }
00709
00714 template<> inline EFeatureType CSimpleFeatures<uint32_t>::get_feature_type()
00715 {
00716 return F_UINT;
00717 }
00718
00723 template<> inline EFeatureType CSimpleFeatures<int64_t>::get_feature_type()
00724 {
00725 return F_LONG;
00726 }
00727
00732 template<> inline EFeatureType CSimpleFeatures<uint64_t>::get_feature_type()
00733 {
00734 return F_ULONG;
00735 }
00736
00741 template<> inline EFeatureType CSimpleFeatures<float32_t>::get_feature_type()
00742 {
00743 return F_SHORTREAL;
00744 }
00745
00750 template<> inline EFeatureType CSimpleFeatures<float64_t>::get_feature_type()
00751 {
00752 return F_DREAL;
00753 }
00754
00759 template<> inline EFeatureType CSimpleFeatures<floatmax_t>::get_feature_type()
00760 {
00761 return F_LONGREAL;
00762 }
00763
00765 template<> inline const char* CSimpleFeatures<bool>::get_name() const
00766 {
00767 return "BoolFeatures";
00768 }
00769
00771 template<> inline const char* CSimpleFeatures<char>::get_name() const
00772 {
00773 return "CharFeatures";
00774 }
00775
00777 template<> inline const char* CSimpleFeatures<uint8_t>::get_name() const
00778 {
00779 return "ByteFeatures";
00780 }
00781
00783 template<> inline const char* CSimpleFeatures<int16_t>::get_name() const
00784 {
00785 return "ShortFeatures";
00786 }
00787
00789 template<> inline const char* CSimpleFeatures<uint16_t>::get_name() const
00790 {
00791 return "WordFeatures";
00792 }
00793
00795 template<> inline const char* CSimpleFeatures<int32_t>::get_name() const
00796 {
00797 return "IntFeatures";
00798 }
00799
00801 template<> inline const char* CSimpleFeatures<uint32_t>::get_name() const
00802 {
00803 return "UIntFeatures";
00804 }
00805
00807 template<> inline const char* CSimpleFeatures<int64_t>::get_name() const
00808 {
00809 return "LongIntFeatures";
00810 }
00811
00813 template<> inline const char* CSimpleFeatures<uint64_t>::get_name() const
00814 {
00815 return "ULongIntFeatures";
00816 }
00817
00819 template<> inline const char* CSimpleFeatures<float32_t>::get_name() const
00820 {
00821 return "ShortRealFeatures";
00822 }
00823
00825 template<> inline const char* CSimpleFeatures<float64_t>::get_name() const
00826 {
00827 return "RealFeatures";
00828 }
00829
00831 template<> inline const char* CSimpleFeatures<floatmax_t>::get_name() const
00832 {
00833 return "LongRealFeatures";
00834 }
00835
00836 template<> inline bool CSimpleFeatures<float64_t>::Align_char_features(
00837 CStringFeatures<char>* cf, CStringFeatures<char>* Ref, float64_t gapCost)
00838 {
00839 ASSERT(cf);
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865 return true;
00866 }
00867
00868 template<> inline float64_t CSimpleFeatures<bool>:: dense_dot(int32_t vec_idx1, const float64_t* vec2, int32_t vec2_len)
00869 {
00870 ASSERT(vec2_len == num_features);
00871
00872 int32_t vlen;
00873 bool vfree;
00874 bool* vec1= get_feature_vector(vec_idx1, vlen, vfree);
00875
00876 ASSERT(vlen == num_features);
00877 float64_t result=0;
00878
00879 for (int32_t i=0 ; i<num_features; i++)
00880 result+=vec1[i] ? vec2[i] : 0;
00881
00882 free_feature_vector(vec1, vec_idx1, vfree);
00883
00884 return result;
00885 }
00886
00887
00888 template<> inline float64_t CSimpleFeatures<char>:: dense_dot(int32_t vec_idx1, const float64_t* vec2, int32_t vec2_len)
00889 {
00890 ASSERT(vec2_len == num_features);
00891
00892 int32_t vlen;
00893 bool vfree;
00894 char* vec1= get_feature_vector(vec_idx1, vlen, vfree);
00895
00896 ASSERT(vlen == num_features);
00897 float64_t result=0;
00898
00899 for (int32_t i=0 ; i<num_features; i++)
00900 result+=vec1[i]*vec2[i];
00901
00902 free_feature_vector(vec1, vec_idx1, vfree);
00903
00904 return result;
00905 }
00906
00907 template<> inline float64_t CSimpleFeatures<uint8_t>:: dense_dot(int32_t vec_idx1, const float64_t* vec2, int32_t vec2_len)
00908 {
00909 ASSERT(vec2_len == num_features);
00910
00911 int32_t vlen;
00912 bool vfree;
00913 uint8_t* vec1= get_feature_vector(vec_idx1, vlen, vfree);
00914
00915 ASSERT(vlen == num_features);
00916 float64_t result=0;
00917
00918 for (int32_t i=0 ; i<num_features; i++)
00919 result+=vec1[i]*vec2[i];
00920
00921 free_feature_vector(vec1, vec_idx1, vfree);
00922
00923 return result;
00924 }
00925
00926 template<> inline float64_t CSimpleFeatures<int16_t>:: dense_dot(int32_t vec_idx1, const float64_t* vec2, int32_t vec2_len)
00927 {
00928 ASSERT(vec2_len == num_features);
00929
00930 int32_t vlen;
00931 bool vfree;
00932 int16_t* vec1= get_feature_vector(vec_idx1, vlen, vfree);
00933
00934 ASSERT(vlen == num_features);
00935 float64_t result=0;
00936
00937 for (int32_t i=0 ; i<num_features; i++)
00938 result+=vec1[i]*vec2[i];
00939
00940 free_feature_vector(vec1, vec_idx1, vfree);
00941
00942 return result;
00943 }
00944
00945
00946 template<> inline float64_t CSimpleFeatures<uint16_t>:: dense_dot(int32_t vec_idx1, const float64_t* vec2, int32_t vec2_len)
00947 {
00948 ASSERT(vec2_len == num_features);
00949
00950 int32_t vlen;
00951 bool vfree;
00952 uint16_t* vec1= get_feature_vector(vec_idx1, vlen, vfree);
00953
00954 ASSERT(vlen == num_features);
00955 float64_t result=0;
00956
00957 for (int32_t i=0 ; i<num_features; i++)
00958 result+=vec1[i]*vec2[i];
00959
00960 free_feature_vector(vec1, vec_idx1, vfree);
00961
00962 return result;
00963 }
00964
00965 template<> inline float64_t CSimpleFeatures<int32_t>:: dense_dot(int32_t vec_idx1, const float64_t* vec2, int32_t vec2_len)
00966 {
00967 ASSERT(vec2_len == num_features);
00968
00969 int32_t vlen;
00970 bool vfree;
00971 int32_t* vec1= get_feature_vector(vec_idx1, vlen, vfree);
00972
00973 ASSERT(vlen == num_features);
00974 float64_t result=0;
00975
00976 for (int32_t i=0 ; i<num_features; i++)
00977 result+=vec1[i]*vec2[i];
00978
00979 free_feature_vector(vec1, vec_idx1, vfree);
00980
00981 return result;
00982 }
00983
00984 template<> inline float64_t CSimpleFeatures<uint32_t>:: dense_dot(int32_t vec_idx1, const float64_t* vec2, int32_t vec2_len)
00985 {
00986 ASSERT(vec2_len == num_features);
00987
00988 int32_t vlen;
00989 bool vfree;
00990 uint32_t* vec1= get_feature_vector(vec_idx1, vlen, vfree);
00991
00992 ASSERT(vlen == num_features);
00993 float64_t result=0;
00994
00995 for (int32_t i=0 ; i<num_features; i++)
00996 result+=vec1[i]*vec2[i];
00997
00998 free_feature_vector(vec1, vec_idx1, vfree);
00999
01000 return result;
01001 }
01002
01003 template<> inline float64_t CSimpleFeatures<int64_t>:: dense_dot(int32_t vec_idx1, const float64_t* vec2, int32_t vec2_len)
01004 {
01005 ASSERT(vec2_len == num_features);
01006
01007 int32_t vlen;
01008 bool vfree;
01009 int64_t* vec1= get_feature_vector(vec_idx1, vlen, vfree);
01010
01011 ASSERT(vlen == num_features);
01012 float64_t result=0;
01013
01014 for (int32_t i=0 ; i<num_features; i++)
01015 result+=vec1[i]*vec2[i];
01016
01017 free_feature_vector(vec1, vec_idx1, vfree);
01018
01019 return result;
01020 }
01021
01022 template<> inline float64_t CSimpleFeatures<uint64_t>:: dense_dot(int32_t vec_idx1, const float64_t* vec2, int32_t vec2_len)
01023 {
01024 ASSERT(vec2_len == num_features);
01025
01026 int32_t vlen;
01027 bool vfree;
01028 uint64_t* vec1= get_feature_vector(vec_idx1, vlen, vfree);
01029
01030 ASSERT(vlen == num_features);
01031 float64_t result=0;
01032
01033 for (int32_t i=0 ; i<num_features; i++)
01034 result+=vec1[i]*vec2[i];
01035
01036 free_feature_vector(vec1, vec_idx1, vfree);
01037
01038 return result;
01039 }
01040
01041 template<> inline float64_t CSimpleFeatures<float32_t>:: dense_dot(int32_t vec_idx1, const float64_t* vec2, int32_t vec2_len)
01042 {
01043 ASSERT(vec2_len == num_features);
01044
01045 int32_t vlen;
01046 bool vfree;
01047 float32_t* vec1= get_feature_vector(vec_idx1, vlen, vfree);
01048
01049 ASSERT(vlen == num_features);
01050 float64_t result=0;
01051
01052 for (int32_t i=0 ; i<num_features; i++)
01053 result+=vec1[i]*vec2[i];
01054
01055 free_feature_vector(vec1, vec_idx1, vfree);
01056
01057 return result;
01058 }
01059
01060 template<> inline float64_t CSimpleFeatures<float64_t>:: dense_dot(int32_t vec_idx1, const float64_t* vec2, int32_t vec2_len)
01061 {
01062 ASSERT(vec2_len == num_features);
01063
01064 int32_t vlen;
01065 bool vfree;
01066 float64_t* vec1= get_feature_vector(vec_idx1, vlen, vfree);
01067
01068 ASSERT(vlen == num_features);
01069 float64_t result=CMath::dot(vec1, vec2, num_features);
01070
01071 free_feature_vector(vec1, vec_idx1, vfree);
01072
01073 return result;
01074 }
01075
01076 template<> inline float64_t CSimpleFeatures<floatmax_t>:: dense_dot(int32_t vec_idx1, const float64_t* vec2, int32_t vec2_len)
01077 {
01078 ASSERT(vec2_len == num_features);
01079
01080 int32_t vlen;
01081 bool vfree;
01082 floatmax_t* vec1= get_feature_vector(vec_idx1, vlen, vfree);
01083
01084 ASSERT(vlen == num_features);
01085 float64_t result=0;
01086
01087 for (int32_t i=0 ; i<num_features; i++)
01088 result+=vec1[i]*vec2[i];
01089
01090 free_feature_vector(vec1, vec_idx1, vfree);
01091
01092 return result;
01093 }
01094 #endif // DOXYGEN_SHOULD_SKIP_THIS
01095 #endif // _SIMPLEFEATURES__H__