1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //
12 // Copyright (C) 2000, Intel Corporation, all rights reserved.
13 // Third party copyrights are property of their respective owners.
14 //
15 // Redistribution and use in source and binary forms, with or without modification,
16 // are permitted provided that the following conditions are met:
17 //
18 //   * Redistribution's of source code must retain the above copyright notice,
19 //     this list of conditions and the following disclaimer.
20 //
21 //   * Redistribution's in binary form must reproduce the above copyright notice,
22 //     this list of conditions and the following disclaimer in the documentation
23 //     and/or other materials provided with the distribution.
24 //
25 //   * The name of Intel Corporation may not be used to endorse or promote products
26 //     derived from this software without specific prior written permission.
27 //
28 // This software is provided by the copyright holders and contributors "as is" and
29 // any express or implied warranties, including, but not limited to, the implied
30 // warranties of merchantability and fitness for a particular purpose are disclaimed.
31 // In no event shall the Intel Corporation or contributors be liable for any direct,
32 // indirect, incidental, special, exemplary, or consequential damages
33 // (including, but not limited to, procurement of substitute goods or services;
34 // loss of use, data, or profits; or business interruption) however caused
35 // and on any theory of liability, whether in contract, strict liability,
36 // or tort (including negligence or otherwise) arising in any way out of
37 // the use of this software, even if advised of the possibility of such damage.
38 //
39 //M*/
40 
41 #include "old_ml_precomp.hpp"
42 #include <ctype.h>
43 
44 #define MISS_VAL    FLT_MAX
45 #define CV_VAR_MISS    0
46 
CvTrainTestSplit()47 CvTrainTestSplit::CvTrainTestSplit()
48 {
49     train_sample_part_mode = CV_COUNT;
50     train_sample_part.count = -1;
51     mix = false;
52 }
53 
CvTrainTestSplit(int _train_sample_count,bool _mix)54 CvTrainTestSplit::CvTrainTestSplit( int _train_sample_count, bool _mix )
55 {
56     train_sample_part_mode = CV_COUNT;
57     train_sample_part.count = _train_sample_count;
58     mix = _mix;
59 }
60 
CvTrainTestSplit(float _train_sample_portion,bool _mix)61 CvTrainTestSplit::CvTrainTestSplit( float _train_sample_portion, bool _mix )
62 {
63     train_sample_part_mode = CV_PORTION;
64     train_sample_part.portion = _train_sample_portion;
65     mix = _mix;
66 }
67 
68 ////////////////
69 
CvMLData()70 CvMLData::CvMLData()
71 {
72     values = missing = var_types = var_idx_mask = response_out = var_idx_out = var_types_out = 0;
73     train_sample_idx = test_sample_idx = 0;
74     header_lines_number = 0;
75     sample_idx = 0;
76     response_idx = -1;
77 
78     train_sample_count = -1;
79 
80     delimiter = ',';
81     miss_ch = '?';
82     //flt_separator = '.';
83 
84     rng = &cv::theRNG();
85 }
86 
~CvMLData()87 CvMLData::~CvMLData()
88 {
89     clear();
90 }
91 
free_train_test_idx()92 void CvMLData::free_train_test_idx()
93 {
94     cvReleaseMat( &train_sample_idx );
95     cvReleaseMat( &test_sample_idx );
96     sample_idx = 0;
97 }
98 
clear()99 void CvMLData::clear()
100 {
101     class_map.clear();
102 
103     cvReleaseMat( &values );
104     cvReleaseMat( &missing );
105     cvReleaseMat( &var_types );
106     cvReleaseMat( &var_idx_mask );
107 
108     cvReleaseMat( &response_out );
109     cvReleaseMat( &var_idx_out );
110     cvReleaseMat( &var_types_out );
111 
112     free_train_test_idx();
113 
114     total_class_count = 0;
115 
116     response_idx = -1;
117 
118     train_sample_count = -1;
119 }
120 
121 
set_header_lines_number(int idx)122 void CvMLData::set_header_lines_number( int idx )
123 {
124     header_lines_number = std::max(0, idx);
125 }
126 
get_header_lines_number() const127 int CvMLData::get_header_lines_number() const
128 {
129     return header_lines_number;
130 }
131 
fgets_chomp(char * str,int n,FILE * stream)132 static char *fgets_chomp(char *str, int n, FILE *stream)
133 {
134     char *head = fgets(str, n, stream);
135     if( head )
136     {
137         for(char *tail = head + strlen(head) - 1; tail >= head; --tail)
138         {
139             if( *tail != '\r'  && *tail != '\n' )
140                 break;
141             *tail = '\0';
142         }
143     }
144     return head;
145 }
146 
147 
read_csv(const char * filename)148 int CvMLData::read_csv(const char* filename)
149 {
150     const int M = 1000000;
151     const char str_delimiter[3] = { ' ', delimiter, '\0' };
152     FILE* file = 0;
153     CvMemStorage* storage;
154     CvSeq* seq;
155     char *ptr;
156     float* el_ptr;
157     CvSeqReader reader;
158     int cols_count = 0;
159     uchar *var_types_ptr = 0;
160 
161     clear();
162 
163     file = fopen( filename, "rt" );
164 
165     if( !file )
166         return -1;
167 
168     std::vector<char> _buf(M);
169     char* buf = &_buf[0];
170 
171     // skip header lines
172     for( int i = 0; i < header_lines_number; i++ )
173     {
174         if( fgets( buf, M, file ) == 0 )
175         {
176             fclose(file);
177             return -1;
178         }
179     }
180 
181     // read the first data line and determine the number of variables
182     if( !fgets_chomp( buf, M, file ))
183     {
184         fclose(file);
185         return -1;
186     }
187 
188     ptr = buf;
189     while( *ptr == ' ' )
190         ptr++;
191     for( ; *ptr != '\0'; )
192     {
193         if(*ptr == delimiter || *ptr == ' ')
194         {
195             cols_count++;
196             ptr++;
197             while( *ptr == ' ' ) ptr++;
198         }
199         else
200             ptr++;
201     }
202 
203     cols_count++;
204 
205     if ( cols_count == 0)
206     {
207         fclose(file);
208         return -1;
209     }
210 
211     // create temporary memory storage to store the whole database
212     el_ptr = new float[cols_count];
213     storage = cvCreateMemStorage();
214     seq = cvCreateSeq( 0, sizeof(*seq), cols_count*sizeof(float), storage );
215 
216     var_types = cvCreateMat( 1, cols_count, CV_8U );
217     cvZero( var_types );
218     var_types_ptr = var_types->data.ptr;
219 
220     for(;;)
221     {
222         char *token = NULL;
223         int type;
224         token = strtok(buf, str_delimiter);
225         if (!token)
226             break;
227         for (int i = 0; i < cols_count-1; i++)
228         {
229             str_to_flt_elem( token, el_ptr[i], type);
230             var_types_ptr[i] |= type;
231             token = strtok(NULL, str_delimiter);
232             if (!token)
233             {
234                 fclose(file);
235                 delete [] el_ptr;
236                 return -1;
237             }
238         }
239         str_to_flt_elem( token, el_ptr[cols_count-1], type);
240         var_types_ptr[cols_count-1] |= type;
241         cvSeqPush( seq, el_ptr );
242         if( !fgets_chomp( buf, M, file ) )
243             break;
244     }
245     fclose(file);
246 
247     values = cvCreateMat( seq->total, cols_count, CV_32FC1 );
248     missing = cvCreateMat( seq->total, cols_count, CV_8U );
249     var_idx_mask = cvCreateMat( 1, values->cols, CV_8UC1 );
250     cvSet( var_idx_mask, cvRealScalar(1) );
251     train_sample_count = seq->total;
252 
253     cvStartReadSeq( seq, &reader );
254     for(int i = 0; i < seq->total; i++ )
255     {
256         const float* sdata = (float*)reader.ptr;
257         float* ddata = values->data.fl + cols_count*i;
258         uchar* dm = missing->data.ptr + cols_count*i;
259 
260         for( int j = 0; j < cols_count; j++ )
261         {
262             ddata[j] = sdata[j];
263             dm[j] = ( fabs( MISS_VAL - sdata[j] ) <= FLT_EPSILON );
264         }
265         CV_NEXT_SEQ_ELEM( seq->elem_size, reader );
266     }
267 
268     if ( cvNorm( missing, 0, CV_L1 ) <= FLT_EPSILON )
269         cvReleaseMat( &missing );
270 
271     cvReleaseMemStorage( &storage );
272     delete []el_ptr;
273     return 0;
274 }
275 
get_values() const276 const CvMat* CvMLData::get_values() const
277 {
278     return values;
279 }
280 
get_missing() const281 const CvMat* CvMLData::get_missing() const
282 {
283     CV_FUNCNAME( "CvMLData::get_missing" );
284     __BEGIN__;
285 
286     if ( !values )
287         CV_ERROR( CV_StsInternal, "data is empty" );
288 
289     __END__;
290 
291     return missing;
292 }
293 
get_class_labels_map() const294 const std::map<cv::String, int>& CvMLData::get_class_labels_map() const
295 {
296     return class_map;
297 }
298 
str_to_flt_elem(const char * token,float & flt_elem,int & type)299 void CvMLData::str_to_flt_elem( const char* token, float& flt_elem, int& type)
300 {
301 
302     char* stopstring = NULL;
303     flt_elem = (float)strtod( token, &stopstring );
304     assert( stopstring );
305     type = CV_VAR_ORDERED;
306     if ( *stopstring == miss_ch && strlen(stopstring) == 1 ) // missed value
307     {
308         flt_elem = MISS_VAL;
309         type = CV_VAR_MISS;
310     }
311     else
312     {
313         if ( (*stopstring != 0) && (*stopstring != '\n') && (strcmp(stopstring, "\r\n") != 0) ) // class label
314         {
315             int idx = class_map[token];
316             if ( idx == 0)
317             {
318                 total_class_count++;
319                 idx = total_class_count;
320                 class_map[token] = idx;
321             }
322             flt_elem = (float)idx;
323             type = CV_VAR_CATEGORICAL;
324         }
325     }
326 }
327 
set_delimiter(char ch)328 void CvMLData::set_delimiter(char ch)
329 {
330     CV_FUNCNAME( "CvMLData::set_delimited" );
331     __BEGIN__;
332 
333     if (ch == miss_ch /*|| ch == flt_separator*/)
334         CV_ERROR(CV_StsBadArg, "delimited, miss_character and flt_separator must be different");
335 
336     delimiter = ch;
337 
338     __END__;
339 }
340 
get_delimiter() const341 char CvMLData::get_delimiter() const
342 {
343     return delimiter;
344 }
345 
set_miss_ch(char ch)346 void CvMLData::set_miss_ch(char ch)
347 {
348     CV_FUNCNAME( "CvMLData::set_miss_ch" );
349     __BEGIN__;
350 
351     if (ch == delimiter/* || ch == flt_separator*/)
352         CV_ERROR(CV_StsBadArg, "delimited, miss_character and flt_separator must be different");
353 
354     miss_ch = ch;
355 
356     __END__;
357 }
358 
get_miss_ch() const359 char CvMLData::get_miss_ch() const
360 {
361     return miss_ch;
362 }
363 
set_response_idx(int idx)364 void CvMLData::set_response_idx( int idx )
365 {
366     CV_FUNCNAME( "CvMLData::set_response_idx" );
367     __BEGIN__;
368 
369     if ( !values )
370         CV_ERROR( CV_StsInternal, "data is empty" );
371 
372     if ( idx >= values->cols)
373         CV_ERROR( CV_StsBadArg, "idx value is not correct" );
374 
375     if ( response_idx >= 0 )
376         chahge_var_idx( response_idx, true );
377     if ( idx >= 0 )
378         chahge_var_idx( idx, false );
379     response_idx = idx;
380 
381     __END__;
382 }
383 
get_response_idx() const384 int CvMLData::get_response_idx() const
385 {
386     CV_FUNCNAME( "CvMLData::get_response_idx" );
387     __BEGIN__;
388 
389     if ( !values )
390         CV_ERROR( CV_StsInternal, "data is empty" );
391      __END__;
392     return response_idx;
393 }
394 
change_var_type(int var_idx,int type)395 void CvMLData::change_var_type( int var_idx, int type )
396 {
397     CV_FUNCNAME( "CvMLData::change_var_type" );
398     __BEGIN__;
399 
400     int var_count = 0;
401 
402     if ( !values )
403         CV_ERROR( CV_StsInternal, "data is empty" );
404 
405      var_count = values->cols;
406 
407     if ( var_idx < 0 || var_idx >= var_count)
408         CV_ERROR( CV_StsBadArg, "var_idx is not correct" );
409 
410     if ( type != CV_VAR_ORDERED && type != CV_VAR_CATEGORICAL)
411          CV_ERROR( CV_StsBadArg, "type is not correct" );
412 
413     assert( var_types );
414     if ( var_types->data.ptr[var_idx] == CV_VAR_CATEGORICAL && type == CV_VAR_ORDERED)
415         CV_ERROR( CV_StsBadArg, "it`s impossible to assign CV_VAR_ORDERED type to categorical variable" );
416     var_types->data.ptr[var_idx] = (uchar)type;
417 
418     __END__;
419 
420     return;
421 }
422 
set_var_types(const char * str)423 void CvMLData::set_var_types( const char* str )
424 {
425     CV_FUNCNAME( "CvMLData::set_var_types" );
426     __BEGIN__;
427 
428     const char* ord = 0, *cat = 0;
429     int var_count = 0, set_var_type_count = 0;
430     if ( !values )
431         CV_ERROR( CV_StsInternal, "data is empty" );
432 
433     var_count = values->cols;
434 
435     assert( var_types );
436 
437     ord = strstr( str, "ord" );
438     cat = strstr( str, "cat" );
439     if ( !ord && !cat )
440         CV_ERROR( CV_StsBadArg, "types string is not correct" );
441 
442     if ( !ord && strlen(cat) == 3 ) // str == "cat"
443     {
444         cvSet( var_types, cvScalarAll(CV_VAR_CATEGORICAL) );
445         return;
446     }
447 
448     if ( !cat && strlen(ord) == 3 ) // str == "ord"
449     {
450         cvSet( var_types, cvScalarAll(CV_VAR_ORDERED) );
451         return;
452     }
453 
454     if ( ord ) // parse ord str
455     {
456         char* stopstring = NULL;
457         if ( ord[3] != '[')
458             CV_ERROR( CV_StsBadArg, "types string is not correct" );
459 
460         ord += 4; // pass "ord["
461         do
462         {
463             int b1 = (int)strtod( ord, &stopstring );
464             if ( *stopstring == 0 || (*stopstring != ',' && *stopstring != ']' && *stopstring != '-') )
465                 CV_ERROR( CV_StsBadArg, "types string is not correct" );
466             ord = stopstring + 1;
467             if ( (stopstring[0] == ',') || (stopstring[0] == ']'))
468             {
469                 if ( var_types->data.ptr[b1] == CV_VAR_CATEGORICAL)
470                     CV_ERROR( CV_StsBadArg, "it`s impossible to assign CV_VAR_ORDERED type to categorical variable" );
471                 var_types->data.ptr[b1] = CV_VAR_ORDERED;
472                 set_var_type_count++;
473             }
474             else
475             {
476                 if ( stopstring[0] == '-')
477                 {
478                     int b2 = (int)strtod( ord, &stopstring);
479                     if ( (*stopstring == 0) || (*stopstring != ',' && *stopstring != ']') )
480                         CV_ERROR( CV_StsBadArg, "types string is not correct" );
481                     ord = stopstring + 1;
482                     for (int i = b1; i <= b2; i++)
483                     {
484                         if ( var_types->data.ptr[i] == CV_VAR_CATEGORICAL)
485                             CV_ERROR( CV_StsBadArg, "it`s impossible to assign CV_VAR_ORDERED type to categorical variable" );
486                         var_types->data.ptr[i] = CV_VAR_ORDERED;
487                     }
488                     set_var_type_count += b2 - b1 + 1;
489                 }
490                 else
491                     CV_ERROR( CV_StsBadArg, "types string is not correct" );
492 
493             }
494         }
495         while (*stopstring != ']');
496 
497         if ( stopstring[1] != '\0' && stopstring[1] != ',')
498             CV_ERROR( CV_StsBadArg, "types string is not correct" );
499     }
500 
501     if ( cat ) // parse cat str
502     {
503         char* stopstring = NULL;
504         if ( cat[3] != '[')
505             CV_ERROR( CV_StsBadArg, "types string is not correct" );
506 
507         cat += 4; // pass "cat["
508         do
509         {
510             int b1 = (int)strtod( cat, &stopstring );
511             if ( *stopstring == 0 || (*stopstring != ',' && *stopstring != ']' && *stopstring != '-') )
512                 CV_ERROR( CV_StsBadArg, "types string is not correct" );
513             cat = stopstring + 1;
514             if ( (stopstring[0] == ',') || (stopstring[0] == ']'))
515             {
516                 var_types->data.ptr[b1] = CV_VAR_CATEGORICAL;
517                 set_var_type_count++;
518             }
519             else
520             {
521                 if ( stopstring[0] == '-')
522                 {
523                     int b2 = (int)strtod( cat, &stopstring);
524                     if ( (*stopstring == 0) || (*stopstring != ',' && *stopstring != ']') )
525                         CV_ERROR( CV_StsBadArg, "types string is not correct" );
526                     cat = stopstring + 1;
527                     for (int i = b1; i <= b2; i++)
528                         var_types->data.ptr[i] = CV_VAR_CATEGORICAL;
529                     set_var_type_count += b2 - b1 + 1;
530                 }
531                 else
532                     CV_ERROR( CV_StsBadArg, "types string is not correct" );
533 
534             }
535         }
536         while (*stopstring != ']');
537 
538         if ( stopstring[1] != '\0' && stopstring[1] != ',')
539             CV_ERROR( CV_StsBadArg, "types string is not correct" );
540     }
541 
542     if (set_var_type_count != var_count)
543         CV_ERROR( CV_StsBadArg, "types string is not correct" );
544 
545      __END__;
546 }
547 
get_var_types()548 const CvMat* CvMLData::get_var_types()
549 {
550     CV_FUNCNAME( "CvMLData::get_var_types" );
551     __BEGIN__;
552 
553     uchar *var_types_out_ptr = 0;
554     int avcount, vt_size;
555     if ( !values )
556         CV_ERROR( CV_StsInternal, "data is empty" );
557 
558     assert( var_idx_mask );
559 
560     avcount = cvFloor( cvNorm( var_idx_mask, 0, CV_L1 ) );
561     vt_size = avcount + (response_idx >= 0);
562 
563     if ( avcount == values->cols || (avcount == values->cols-1 && response_idx == values->cols-1) )
564         return var_types;
565 
566     if ( !var_types_out || ( var_types_out && var_types_out->cols != vt_size ) )
567     {
568         cvReleaseMat( &var_types_out );
569         var_types_out = cvCreateMat( 1, vt_size, CV_8UC1 );
570     }
571 
572     var_types_out_ptr = var_types_out->data.ptr;
573     for( int i = 0; i < var_types->cols; i++)
574     {
575         if (i == response_idx || !var_idx_mask->data.ptr[i]) continue;
576         *var_types_out_ptr = var_types->data.ptr[i];
577         var_types_out_ptr++;
578     }
579     if ( response_idx >= 0 )
580         *var_types_out_ptr = var_types->data.ptr[response_idx];
581 
582     __END__;
583 
584     return var_types_out;
585 }
586 
get_var_type(int var_idx) const587 int CvMLData::get_var_type( int var_idx ) const
588 {
589     return var_types->data.ptr[var_idx];
590 }
591 
get_responses()592 const CvMat* CvMLData::get_responses()
593 {
594     CV_FUNCNAME( "CvMLData::get_responses_ptr" );
595     __BEGIN__;
596 
597     int var_count = 0;
598 
599     if ( !values )
600         CV_ERROR( CV_StsInternal, "data is empty" );
601     var_count = values->cols;
602 
603     if ( response_idx < 0 || response_idx >= var_count )
604        return 0;
605     if ( !response_out )
606         response_out = cvCreateMatHeader( values->rows, 1, CV_32FC1 );
607     else
608         cvInitMatHeader( response_out, values->rows, 1, CV_32FC1);
609     cvGetCol( values, response_out, response_idx );
610 
611     __END__;
612 
613     return response_out;
614 }
615 
set_train_test_split(const CvTrainTestSplit * spl)616 void CvMLData::set_train_test_split( const CvTrainTestSplit * spl)
617 {
618     CV_FUNCNAME( "CvMLData::set_division" );
619     __BEGIN__;
620 
621     int sample_count = 0;
622 
623     if ( !values )
624         CV_ERROR( CV_StsInternal, "data is empty" );
625 
626     sample_count = values->rows;
627 
628     float train_sample_portion;
629 
630     if (spl->train_sample_part_mode == CV_COUNT)
631     {
632         train_sample_count = spl->train_sample_part.count;
633         if (train_sample_count > sample_count)
634             CV_ERROR( CV_StsBadArg, "train samples count is not correct" );
635         train_sample_count = train_sample_count<=0 ? sample_count : train_sample_count;
636     }
637     else // dtype.train_sample_part_mode == CV_PORTION
638     {
639         train_sample_portion = spl->train_sample_part.portion;
640         if ( train_sample_portion > 1)
641             CV_ERROR( CV_StsBadArg, "train samples count is not correct" );
642         train_sample_portion = train_sample_portion <= FLT_EPSILON ||
643             1 - train_sample_portion <= FLT_EPSILON ? 1 : train_sample_portion;
644         train_sample_count = std::max(1, cvFloor( train_sample_portion * sample_count ));
645     }
646 
647     if ( train_sample_count == sample_count )
648     {
649         free_train_test_idx();
650         return;
651     }
652 
653     if ( train_sample_idx && train_sample_idx->cols != train_sample_count )
654         free_train_test_idx();
655 
656     if ( !sample_idx)
657     {
658         int test_sample_count = sample_count- train_sample_count;
659         sample_idx = (int*)cvAlloc( sample_count * sizeof(sample_idx[0]) );
660         for (int i = 0; i < sample_count; i++ )
661             sample_idx[i] = i;
662         train_sample_idx = cvCreateMatHeader( 1, train_sample_count, CV_32SC1 );
663         *train_sample_idx = cvMat( 1, train_sample_count, CV_32SC1, &sample_idx[0] );
664 
665         CV_Assert(test_sample_count > 0);
666         test_sample_idx = cvCreateMatHeader( 1, test_sample_count, CV_32SC1 );
667         *test_sample_idx = cvMat( 1, test_sample_count, CV_32SC1, &sample_idx[train_sample_count] );
668     }
669 
670     mix = spl->mix;
671     if ( mix )
672         mix_train_and_test_idx();
673 
674     __END__;
675 }
676 
get_train_sample_idx() const677 const CvMat* CvMLData::get_train_sample_idx() const
678 {
679     CV_FUNCNAME( "CvMLData::get_train_sample_idx" );
680     __BEGIN__;
681 
682     if ( !values )
683         CV_ERROR( CV_StsInternal, "data is empty" );
684     __END__;
685 
686     return train_sample_idx;
687 }
688 
get_test_sample_idx() const689 const CvMat* CvMLData::get_test_sample_idx() const
690 {
691     CV_FUNCNAME( "CvMLData::get_test_sample_idx" );
692     __BEGIN__;
693 
694     if ( !values )
695         CV_ERROR( CV_StsInternal, "data is empty" );
696     __END__;
697 
698     return test_sample_idx;
699 }
700 
mix_train_and_test_idx()701 void CvMLData::mix_train_and_test_idx()
702 {
703     CV_FUNCNAME( "CvMLData::mix_train_and_test_idx" );
704     __BEGIN__;
705 
706     if ( !values )
707         CV_ERROR( CV_StsInternal, "data is empty" );
708     __END__;
709 
710     if ( !sample_idx)
711         return;
712 
713     if ( train_sample_count > 0 && train_sample_count < values->rows )
714     {
715         int n = values->rows;
716         for (int i = 0; i < n; i++)
717         {
718             int a = (*rng)(n);
719             int b = (*rng)(n);
720             int t;
721             CV_SWAP( sample_idx[a], sample_idx[b], t );
722         }
723     }
724 }
725 
get_var_idx()726 const CvMat* CvMLData::get_var_idx()
727 {
728      CV_FUNCNAME( "CvMLData::get_var_idx" );
729     __BEGIN__;
730 
731     int avcount = 0;
732 
733     if ( !values )
734         CV_ERROR( CV_StsInternal, "data is empty" );
735 
736     assert( var_idx_mask );
737 
738     avcount = cvFloor( cvNorm( var_idx_mask, 0, CV_L1 ) );
739     int* vidx;
740 
741     if ( avcount == values->cols )
742         return 0;
743 
744     if ( !var_idx_out || ( var_idx_out && var_idx_out->cols != avcount ) )
745     {
746         cvReleaseMat( &var_idx_out );
747         var_idx_out = cvCreateMat( 1, avcount, CV_32SC1);
748         if ( response_idx >=0 )
749             var_idx_mask->data.ptr[response_idx] = 0;
750     }
751 
752     vidx = var_idx_out->data.i;
753 
754     for(int i = 0; i < var_idx_mask->cols; i++)
755         if ( var_idx_mask->data.ptr[i] )
756         {
757             *vidx = i;
758             vidx++;
759         }
760 
761     __END__;
762 
763     return var_idx_out;
764 }
765 
chahge_var_idx(int vi,bool state)766 void CvMLData::chahge_var_idx( int vi, bool state )
767 {
768     change_var_idx( vi, state );
769 }
770 
change_var_idx(int vi,bool state)771 void CvMLData::change_var_idx( int vi, bool state )
772 {
773      CV_FUNCNAME( "CvMLData::change_var_idx" );
774     __BEGIN__;
775 
776     int var_count = 0;
777 
778     if ( !values )
779         CV_ERROR( CV_StsInternal, "data is empty" );
780 
781     var_count = values->cols;
782 
783     if ( vi < 0 || vi >= var_count)
784         CV_ERROR( CV_StsBadArg, "variable index is not correct" );
785 
786     assert( var_idx_mask );
787     var_idx_mask->data.ptr[vi] = state;
788 
789     __END__;
790 }
791 
792 /* End of file. */
793