]> rtime.felk.cvut.cz Git - opencv.git/commitdiff
converted ml (dtree, rtrees, ertrees, boost) from OpenMP to TBB.
authormdim <mdim@73c94f0f-984f-4a5f-82bc-2d8db8d8ee08>
Mon, 29 Mar 2010 14:47:43 +0000 (14:47 +0000)
committermdim <mdim@73c94f0f-984f-4a5f-82bc-2d8db8d8ee08>
Mon, 29 Mar 2010 14:47:43 +0000 (14:47 +0000)
git-svn-id: https://code.ros.org/svn/opencv/trunk@2938 73c94f0f-984f-4a5f-82bc-2d8db8d8ee08

opencv/apps/traincascade/boost.cpp
opencv/apps/traincascade/boost.h
opencv/include/opencv/ml.h
opencv/src/ml/mlboost.cpp
opencv/src/ml/mlertrees.cpp
opencv/src/ml/mlrtrees.cpp
opencv/src/ml/mltree.cpp

index c04f17d10e7519d036556a4e9b4f02b61c9c1cee..f74b489b0d3c81f4593fc5c83e3584277c528945 100755 (executable)
@@ -285,21 +285,6 @@ void CvCascadeBoostTrainData::setData( const CvFeatureEvaluator* _featureEvaluat
         buf = cvCreateMat( buf_count, buf_size, CV_32SC1 );
 
     cat_count = cvCreateMat( 1, cat_var_count + 1, CV_32SC1 );
-    pred_float_buf.resize(maxNumThreads);
-    pred_int_buf.resize(maxNumThreads);
-    resp_float_buf.resize(maxNumThreads);
-    resp_int_buf.resize(maxNumThreads);
-    cv_lables_buf.resize(maxNumThreads);
-    sample_idx_buf.resize(maxNumThreads);
-    for( int ti = 0; ti < maxNumThreads; ti++ )
-    {
-        pred_float_buf[ti].resize(sample_count);
-        pred_int_buf[ti].resize(sample_count);
-        resp_float_buf[ti].resize(sample_count);
-        resp_int_buf[ti].resize(sample_count);
-        cv_lables_buf[ti].resize(sample_count);
-        sample_idx_buf[ti].resize(sample_count);
-    }
 
     // precalculate valCache and set indices in buf
        precalculate();
@@ -361,59 +346,55 @@ void CvCascadeBoostTrainData::free_train_data()
     valCache.release();
 }
 
-void CvCascadeBoostTrainData::get_class_labels( CvDTreeNode* n, int* labelsBuf, const int** labels )
+const int* CvCascadeBoostTrainData::get_class_labels( CvDTreeNode* n, int* labelsBuf)
 {
     int nodeSampleCount = n->sample_count; 
-    int* sampleIndicesBuf = get_sample_idx_buf();
-    const int* sampleIndices = 0;
     int rStep = CV_IS_MAT_CONT( responses->type ) ? 1 : responses->step / CV_ELEM_SIZE( responses->type );
 
-    get_sample_indices(n, sampleIndicesBuf, &sampleIndices);
-
+    int* sampleIndicesBuf = labelsBuf; //
+    const int* sampleIndices = get_sample_indices(n, sampleIndicesBuf);
     for( int si = 0; si < nodeSampleCount; si++ )
     {
         int sidx = sampleIndices[si];
         labelsBuf[si] = (int)responses->data.fl[sidx*rStep];
     }    
-    *labels = labelsBuf;
+    return labelsBuf;
 }
 
-void CvCascadeBoostTrainData::get_sample_indices( CvDTreeNode* n, int* indicesBuf, const int** indices )
+const int* CvCascadeBoostTrainData::get_sample_indices( CvDTreeNode* n, int* indicesBuf )
 {
-    CvDTreeTrainData::get_cat_var_data( n, get_work_var_count(), indicesBuf, indices );
+    return CvDTreeTrainData::get_cat_var_data( n, get_work_var_count(), indicesBuf );
 }
 
-void CvCascadeBoostTrainData::get_cv_labels( CvDTreeNode* n, int* labels_buf, const int** labels )
+const int* CvCascadeBoostTrainData::get_cv_labels( CvDTreeNode* n, int* labels_buf )
 {
-    CvDTreeTrainData::get_cat_var_data( n, get_work_var_count()- 1, labels_buf, labels );
+    return CvDTreeTrainData::get_cat_var_data( n, get_work_var_count() - 1, labels_buf );
 }
 
-int CvCascadeBoostTrainData::get_ord_var_data( CvDTreeNode* n, int vi, float* ordValuesBuf, int* indicesBuf,
-        const float** ordValues, const int** indices )
+void CvCascadeBoostTrainData::get_ord_var_data( CvDTreeNode* n, int vi, float* ordValuesBuf, int* sortedIndicesBuf,
+        const float** ordValues, const int** sortedIndices, int* sampleIndicesBuf )
 {
     int nodeSampleCount = n->sample_count; 
-    int* sampleIndicesBuf = get_sample_idx_buf();
-    const int* sampleIndices = 0;
-    get_sample_indices(n, sampleIndicesBuf, &sampleIndices);
+    const int* sampleIndices = get_sample_indices(n, sampleIndicesBuf);
     
        if ( vi < numPrecalcIdx )
        {
                if( !is_buf_16u )
-               *indices = buf->data.i + n->buf_idx*buf->cols + vi*sample_count + n->offset;
+            *sortedIndices = buf->data.i + n->buf_idx*buf->cols + vi*sample_count + n->offset;
            else 
         {
                const unsigned short* shortIndices = (const unsigned short*)(buf->data.s + n->buf_idx*buf->cols + 
                                                      vi*sample_count + n->offset );
                for( int i = 0; i < nodeSampleCount; i++ )
-                   indicesBuf[i] = shortIndices[i];
-               *indices = indicesBuf;
+                sortedIndicesBuf[i] = shortIndices[i];
+            *sortedIndices = sortedIndicesBuf;
            }
                
                if ( vi < numPrecalcVal )
                {
                        for( int i = 0; i < nodeSampleCount; i++ )
                {
-                   int idx = (*indices)[i];
+                int idx = (*sortedIndices)[i];
                    idx = sampleIndices[idx];
                    ordValuesBuf[i] =  valCache.at<float>( vi, idx);
                }
@@ -422,7 +403,7 @@ int CvCascadeBoostTrainData::get_ord_var_data( CvDTreeNode* n, int vi, float* or
                {
                        for( int i = 0; i < nodeSampleCount; i++ )
                {
-                   int idx = (*indices)[i];
+                int idx = (*sortedIndices)[i];
                    idx = sampleIndices[idx];
                                ordValuesBuf[i] = (*featureEvaluator)( vi, idx);
                        }
@@ -435,7 +416,7 @@ int CvCascadeBoostTrainData::get_ord_var_data( CvDTreeNode* n, int vi, float* or
                {
                        for( int i = 0; i < nodeSampleCount; i++ )
                {
-                               indicesBuf[i] = i;
+                sortedIndicesBuf[i] = i;
                    ((float*)sampleIndices)[i] = valCache.at<float>( vi, sampleIndices[i] );
                }
                }
@@ -443,26 +424,24 @@ int CvCascadeBoostTrainData::get_ord_var_data( CvDTreeNode* n, int vi, float* or
                {
             for( int i = 0; i < nodeSampleCount; i++ )
                {
-                               indicesBuf[i] = i;
+                sortedIndicesBuf[i] = i;
                                ((float*)sampleIndices)[i] = (*featureEvaluator)( vi, sampleIndices[i]);
                        }
                }
-               icvSortIntAux( indicesBuf, sample_count, (float *)sampleIndices );
+        icvSortIntAux( sortedIndicesBuf, sample_count, (float *)sampleIndices );
                for( int i = 0; i < nodeSampleCount; i++ )
-               ordValuesBuf[i] = ((float*)sampleIndices)[indicesBuf[i]];
-               *indices = indicesBuf;
+            ordValuesBuf[i] = ((float*)sampleIndices)[sortedIndicesBuf[i]];
+        *sortedIndices = sortedIndicesBuf;
        }
        
     *ordValues = ordValuesBuf;
-    return 0;
 }
  
-int CvCascadeBoostTrainData::get_cat_var_data( CvDTreeNode* n, int vi, int* catValuesBuf, const int** catValues )
+const int* CvCascadeBoostTrainData::get_cat_var_data( CvDTreeNode* n, int vi, int* catValuesBuf)
 {
     int nodeSampleCount = n->sample_count; 
-    int* sampleIndicesBuf = get_sample_idx_buf();
-    const int* sampleIndices = 0;
-    get_sample_indices(n, sampleIndicesBuf, &sampleIndices);
+    int* sampleIndicesBuf = catValuesBuf; //
+    const int* sampleIndices = get_sample_indices(n, sampleIndicesBuf);
 
     if ( vi < numPrecalcVal )
        {
@@ -474,9 +453,7 @@ int CvCascadeBoostTrainData::get_cat_var_data( CvDTreeNode* n, int vi, int* catV
                for( int i = 0; i < nodeSampleCount; i++ )
                        catValuesBuf[i] = (int)(*featureEvaluator)( vi, sampleIndices[i] );
        }
-    *catValues = catValuesBuf;
-    
-    return 0;
+    return catValuesBuf;
 }
 
 float CvCascadeBoostTrainData::getVarValue( int vi, int si )
@@ -719,7 +696,8 @@ void CvCascadeBoostTree::split_node_data( CvDTreeNode* node )
     int newBufIdx = data->get_child_buf_idx( node );
     int workVarCount = data->get_work_var_count();
     CvMat* buf = data->buf;
-    int* tempBuf = (int*)cvStackAlloc(n*sizeof(tempBuf[0]));
+    cv::AutoBuffer<uchar> inn_buf(n*(3*sizeof(int)+sizeof(float)));
+    int* tempBuf = (int*)(uchar*)inn_buf;
     bool splitInputData;
 
     complete_node_dir(node);
@@ -740,23 +718,23 @@ void CvCascadeBoostTree::split_node_data( CvDTreeNode* node )
         (node->left->sample_count > data->params.min_sample_count ||
         node->right->sample_count > data->params.min_sample_count);
 
-       // split ordered variables, keep both halves sorted.
+    // split ordered variables, keep both halves sorted.
     for( int vi = 0; vi < ((CvCascadeBoostTrainData*)data)->numPrecalcIdx; vi++ )
     {
         int ci = data->get_var_type(vi);
-        int n1 = node->get_num_valid(vi);
-        int *src_idx_buf = data->get_pred_int_buf();
-        const int* src_idx = 0;
-        float *src_val_buf = data->get_pred_float_buf();
-        const float* src_val = 0;
-        
         if( ci >= 0 || !splitInputData )
             continue;
 
-        data->get_ord_var_data(node, vi, src_val_buf, src_idx_buf, &src_val, &src_idx);
+        int n1 = node->get_num_valid(vi);
+        float *src_val_buf = (float*)(tempBuf + n);
+        int *src_sorted_idx_buf = (int*)(src_val_buf + n);
+        int *src_sample_idx_buf = src_sorted_idx_buf + n;
+        const int* src_sorted_idx = 0;
+        const float* src_val = 0;
+        data->get_ord_var_data(node, vi, src_val_buf, src_sorted_idx_buf, &src_val, &src_sorted_idx, src_sample_idx_buf);
 
         for(int i = 0; i < n; i++)
-            tempBuf[i] = src_idx[i];
+            tempBuf[i] = src_sorted_idx[i];
 
         if (data->is_buf_16u)
         {
@@ -820,9 +798,8 @@ void CvCascadeBoostTree::split_node_data( CvDTreeNode* node )
     }
 
     // split cv_labels using newIdx relocation table
-    int *src_lbls_buf = data->get_pred_int_buf();
-    const int* src_lbls = 0;
-    data->get_cv_labels(node, src_lbls_buf, &src_lbls);
+    int *src_lbls_buf = tempBuf + n;
+    const int* src_lbls = data->get_cv_labels(node, src_lbls_buf);
 
     for(int i = 0; i < n; i++)
         tempBuf[i] = src_lbls[i];
@@ -879,9 +856,8 @@ void CvCascadeBoostTree::split_node_data( CvDTreeNode* node )
     }
 
     // split sample indices
-    int *sampleIdx_src_buf = data->get_sample_idx_buf();
-    const int* sampleIdx_src = 0;
-    data->get_sample_indices(node, sampleIdx_src_buf, &sampleIdx_src);
+    int *sampleIdx_src_buf = tempBuf + n;
+    const int* sampleIdx_src = data->get_sample_indices(node, sampleIdx_src_buf);
 
     for(int i = 0; i < n; i++)
         tempBuf[i] = sampleIdx_src[i];
@@ -1029,26 +1005,25 @@ void CvCascadeBoost::update_weights( CvBoostTree* tree )
     float* fdata = 0;
     int *sampleIdxBuf;
     const int* sampleIdx = 0;
+    int inn_buf_size = ((params.boost_type == LOGIT) || (params.boost_type == GENTLE) ? n*sizeof(int) : 0) +
+                       ( !tree ? n*sizeof(int) : 0 );
+    cv::AutoBuffer<uchar> inn_buf(inn_buf_size);
+    uchar* cur_inn_buf_pos = (uchar*)inn_buf;
     if ( (params.boost_type == LOGIT) || (params.boost_type == GENTLE) )
     {
         step = CV_IS_MAT_CONT(data->responses_copy->type) ?
             1 : data->responses_copy->step / CV_ELEM_SIZE(data->responses_copy->type);
         fdata = data->responses_copy->data.fl;
-        sampleIdxBuf = (int*)cvStackAlloc(data->sample_count*sizeof(sampleIdxBuf[0]));
-        data->get_sample_indices( data->data_root, sampleIdxBuf, &sampleIdx );    
+        sampleIdxBuf = (int*)cur_inn_buf_pos; cur_inn_buf_pos = (uchar*)(sampleIdxBuf + n);
+        sampleIdx = data->get_sample_indices( data->data_root, sampleIdxBuf );
     }
     CvMat* buf = data->buf;
     if( !tree ) // before training the first tree, initialize weights and other parameters
     {
-        int* classLabelsBuf = data->get_resp_int_buf();
-        const int* classLabels = 0;
-        data->get_class_labels(data->data_root, classLabelsBuf, &classLabels);
+        int* classLabelsBuf = (int*)cur_inn_buf_pos; cur_inn_buf_pos = (uchar*)(classLabelsBuf + n);
+        const int* classLabels = data->get_class_labels(data->data_root, classLabelsBuf);
         // in case of logitboost and gentle adaboost each weak tree is a regression tree,
         // so we need to convert class labels to floating-point values
-        float* responses_buf = data->get_resp_float_buf();
-        const float* responses = 0;
-        data->get_ord_responses(data->data_root, responses_buf, &responses);
-        
         double w0 = 1./n;
         double p[2] = { 1, 1 };
 
@@ -1203,9 +1178,6 @@ void CvCascadeBoost::update_weights( CvBoostTree* tree )
 
             const double lbWeightThresh = FLT_EPSILON;
             const double lbZMax = 10.;
-            float* responsesBuf = data->get_resp_float_buf();
-            const float* responses = 0;
-            data->get_ord_responses(data->data_root, responsesBuf, &responses);
 
             for( int i = 0; i < n; i++ )
             {
index 35af0600db589c516cc74ea002a63a208abf8c50..28f22a061cc429f8f856292678e97073d31fb8b0 100755 (executable)
@@ -32,13 +32,13 @@ struct CvCascadeBoostTrainData : CvDTreeTrainData
                           const CvDTreeParams& _params=CvDTreeParams() );
     void precalculate();
 
-    virtual void get_class_labels( CvDTreeNode* n, int* labelsBuf, const int** labels );
-    virtual void get_cv_labels( CvDTreeNode* n, int* labelsBuf, const int** labels );
-    virtual void get_sample_indices( CvDTreeNode* n, int* indicesBuf, const int** labels );
+    virtual const int* get_class_labels( CvDTreeNode* n, int* labelsBuf );
+    virtual const int* get_cv_labels( CvDTreeNode* n, int* labelsBuf);
+    virtual const int* get_sample_indices( CvDTreeNode* n, int* indicesBuf );
     
-    virtual int get_ord_var_data( CvDTreeNode* n, int vi, float* ordValuesBuf, int* indicesBuf,
-                                  const float** ordValues, const int** indices );
-    virtual int get_cat_var_data( CvDTreeNode* n, int vi, int* catValuesBuf, const int** catValues );
+    virtual void get_ord_var_data( CvDTreeNode* n, int vi, float* ordValuesBuf, int* sortedIndicesBuf,
+                                  const float** ordValues, const int** sortedIndices, int* sampleIndicesBuf );
+    virtual const int* get_cat_var_data( CvDTreeNode* n, int vi, int* catValuesBuf );
     virtual float getVarValue( int vi, int si );
     virtual void free_train_data();
 
index 3dc88afa6883a9ec6eee9a04a5efa7f84d129bc9..b6b56300ce9919dcb418ba60680c23c0ca5dd02e 100644 (file)
 // that interferes with a method definiton in this header
 #undef check
 
+#include "cvinternal.h"
+
 /****************************************************************************************\
 *                               Main struct definitions                                  *
 \****************************************************************************************/
@@ -837,13 +839,13 @@ struct CV_EXPORTS CvDTreeTrainData
     int get_var_type(int vi) const;
     int get_work_var_count() const {return work_var_count;}
 
-    virtual void get_ord_responses( CvDTreeNode* n, float* values_buf, const float** values );    
-    virtual void get_class_labels( CvDTreeNode* n, int* labels_buf, const int** labels );
-    virtual void get_cv_labels( CvDTreeNode* n, int* labels_buf, const int** labels );
-    virtual void get_sample_indices( CvDTreeNode* n, int* indices_buf, const int** labels );
-    virtual int get_cat_var_data( CvDTreeNode* n, int vi, int* cat_values_buf, const int** cat_values );
-    virtual int get_ord_var_data( CvDTreeNode* n, int vi, float* ord_values_buf, int* indices_buf,
-        const float** ord_values, const int** indices );
+    virtual const float* get_ord_responses( CvDTreeNode* n, float* values_buf, int* sample_indices_buf );
+    virtual const int* get_class_labels( CvDTreeNode* n, int* labels_buf );
+    virtual const int* get_cv_labels( CvDTreeNode* n, int* labels_buf );
+    virtual const int* get_sample_indices( CvDTreeNode* n, int* indices_buf );
+    virtual const int* get_cat_var_data( CvDTreeNode* n, int vi, int* cat_values_buf );
+    virtual void get_ord_var_data( CvDTreeNode* n, int vi, float* ord_values_buf, int* sorted_indices_buf,
+                                   const float** ord_values, const int** sorted_indices, int* sample_indices_buf );
     virtual int get_child_buf_idx( CvDTreeNode* n );
 
     ////////////////////////////////////
@@ -859,21 +861,6 @@ struct CV_EXPORTS CvDTreeTrainData
     virtual void free_train_data();
     virtual void free_node( CvDTreeNode* node );
 
-    // inner arrays for getting predictors and responses
-    float* get_pred_float_buf();
-    int* get_pred_int_buf();
-    float* get_resp_float_buf();
-    int* get_resp_int_buf();
-    int* get_cv_lables_buf();
-    int* get_sample_idx_buf();
-
-    std::vector<std::vector<float> > pred_float_buf;
-    std::vector<std::vector<int> > pred_int_buf;
-    std::vector<std::vector<float> > resp_float_buf;
-    std::vector<std::vector<int> > resp_int_buf;
-    std::vector<std::vector<int> > cv_lables_buf;
-    std::vector<std::vector<int> > sample_idx_buf;
-
     int sample_count, var_all, var_count, max_c_count;
     int ord_var_count, cat_var_count, work_var_count;
     bool have_labels, have_priors;
@@ -919,6 +906,34 @@ struct CV_EXPORTS CvDTreeTrainData
     CvRNG rng;
 };
 
+class CvDTree;
+class CvForestTree;
+
+namespace cv
+{
+    struct DTreeBestSplitFinder
+    {
+        DTreeBestSplitFinder(){ tree = 0; node = 0; }
+        DTreeBestSplitFinder( CvDTree* _tree, CvDTreeNode* _node);
+        DTreeBestSplitFinder( const DTreeBestSplitFinder& finder, Split );
+        virtual void operator()(const BlockedRange& range);
+        void join( DTreeBestSplitFinder& rhs );
+        Ptr<CvDTreeSplit> bestSplit;
+        Ptr<CvDTreeSplit> split;
+        int splitSize;
+        CvDTree* tree;
+        CvDTreeNode* node;
+    };
+
+    struct ForestTreeBestSplitFinder : DTreeBestSplitFinder
+    {
+        ForestTreeBestSplitFinder() : DTreeBestSplitFinder() {}
+        ForestTreeBestSplitFinder( CvForestTree* _tree, CvDTreeNode* _node );
+        ForestTreeBestSplitFinder( const ForestTreeBestSplitFinder& finder, Split );
+        virtual void operator()(const BlockedRange& range);
+    };
+}
+
 
 class CV_EXPORTS CvDTree : public CvStatModel
 {
@@ -968,6 +983,7 @@ public:
     CvDTreeTrainData* get_data();
 
 protected:
+    friend struct cv::DTreeBestSplitFinder;
 
     virtual bool do_train( const CvMat* _subsample_idx );
 
@@ -975,15 +991,15 @@ protected:
     virtual void split_node_data( CvDTreeNode* n );
     virtual CvDTreeSplit* find_best_split( CvDTreeNode* n );
     virtual CvDTreeSplit* find_split_ord_class( CvDTreeNode* n, int vi, 
-                            float init_quality = 0, CvDTreeSplit* _split = 0 );
+                            float init_quality = 0, CvDTreeSplit* _split = 0, uchar* ext_buf = 0 );
     virtual CvDTreeSplit* find_split_cat_class( CvDTreeNode* n, int vi,
-                            float init_quality = 0, CvDTreeSplit* _split = 0 );
+                            float init_quality = 0, CvDTreeSplit* _split = 0, uchar* ext_buf = 0 );
     virtual CvDTreeSplit* find_split_ord_reg( CvDTreeNode* n, int vi, 
-                            float init_quality = 0, CvDTreeSplit* _split = 0 );
+                            float init_quality = 0, CvDTreeSplit* _split = 0, uchar* ext_buf = 0 );
     virtual CvDTreeSplit* find_split_cat_reg( CvDTreeNode* n, int vi, 
-                            float init_quality = 0, CvDTreeSplit* _split = 0 );
-    virtual CvDTreeSplit* find_surrogate_split_ord( CvDTreeNode* n, int vi );
-    virtual CvDTreeSplit* find_surrogate_split_cat( CvDTreeNode* n, int vi );
+                            float init_quality = 0, CvDTreeSplit* _split = 0, uchar* ext_buf = 0 );
+    virtual CvDTreeSplit* find_surrogate_split_ord( CvDTreeNode* n, int vi, uchar* ext_buf = 0 );
+    virtual CvDTreeSplit* find_surrogate_split_cat( CvDTreeNode* n, int vi, uchar* ext_buf = 0 );
     virtual double calc_node_dir( CvDTreeNode* node );
     virtual void complete_node_dir( CvDTreeNode* node );
     virtual void cluster_categories( const int* vectors, int vector_count,
@@ -1044,6 +1060,8 @@ public:
     /* dummy methods to avoid warnings: END */
 
 protected:
+    friend struct cv::ForestTreeBestSplitFinder;
+
     virtual CvDTreeSplit* find_best_split( CvDTreeNode* n );
     CvRTrees* forest;
 };
@@ -1152,13 +1170,13 @@ struct CV_EXPORTS CvERTreeTrainData : public CvDTreeTrainData
                           const CvDTreeParams& _params=CvDTreeParams(),
                           bool _shared=false, bool _add_labels=false,
                           bool _update_data=false );
-    virtual int get_ord_var_data( CvDTreeNode* n, int vi, float* ord_values_buf, int* missing_buf,
-        const float** ord_values, const int** missing );
-    virtual void get_sample_indices( CvDTreeNode* n, int* indices_buf, const int** indices );
-    virtual void get_cv_labels( CvDTreeNode* n, int* labels_buf, const int** labels );
-    virtual int get_cat_var_data( CvDTreeNode* n, int vi, int* cat_values_buf, const int** cat_values );
-    virtual void get_vectors( const CvMat* _subsample_idx,
-         float* values, uchar* missing, float* responses, bool get_class_idx=false );
+    virtual void get_ord_var_data( CvDTreeNode* n, int vi, float* ord_values_buf, int* missing_buf,
+                                   const float** ord_values, const int** missing, int* sample_buf = 0 );
+    virtual const int* get_sample_indices( CvDTreeNode* n, int* indices_buf );
+    virtual const int* get_cv_labels( CvDTreeNode* n, int* labels_buf );
+    virtual const int* get_cat_var_data( CvDTreeNode* n, int vi, int* cat_values_buf );
+    virtual void get_vectors( const CvMat* _subsample_idx, float* values, uchar* missing,
+                              float* responses, bool get_class_idx=false );
     virtual CvDTreeNode* subsample_data( const CvMat* _subsample_idx );
     const CvMat* missing_mask;
 };
@@ -1168,14 +1186,13 @@ class CV_EXPORTS CvForestERTree : public CvForestTree
 protected:
     virtual double calc_node_dir( CvDTreeNode* node );
     virtual CvDTreeSplit* find_split_ord_class( CvDTreeNode* n, int vi, 
-        float init_quality = 0, CvDTreeSplit* _split = 0 );
+        float init_quality = 0, CvDTreeSplit* _split = 0, uchar* ext_buf = 0 );
     virtual CvDTreeSplit* find_split_cat_class( CvDTreeNode* n, int vi,
-        float init_quality = 0, CvDTreeSplit* _split = 0 );
+        float init_quality = 0, CvDTreeSplit* _split = 0, uchar* ext_buf = 0 );
     virtual CvDTreeSplit* find_split_ord_reg( CvDTreeNode* n, int vi, 
-        float init_quality = 0, CvDTreeSplit* _split = 0 );
+        float init_quality = 0, CvDTreeSplit* _split = 0, uchar* ext_buf = 0 );
     virtual CvDTreeSplit* find_split_cat_reg( CvDTreeNode* n, int vi, 
-        float init_quality = 0, CvDTreeSplit* _split = 0 );
-    //virtual void complete_node_dir( CvDTreeNode* node );
+        float init_quality = 0, CvDTreeSplit* _split = 0, uchar* ext_buf = 0 );
     virtual void split_node_data( CvDTreeNode* n );
 };
 
@@ -1251,16 +1268,16 @@ public:
 protected:
 
     virtual void try_split_node( CvDTreeNode* n );
-    virtual CvDTreeSplit* find_surrogate_split_ord( CvDTreeNode* n, int vi );
-    virtual CvDTreeSplit* find_surrogate_split_cat( CvDTreeNode* n, int vi );
+    virtual CvDTreeSplit* find_surrogate_split_ord( CvDTreeNode* n, int vi, uchar* ext_buf = 0 );
+    virtual CvDTreeSplit* find_surrogate_split_cat( CvDTreeNode* n, int vi, uchar* ext_buf = 0 );
     virtual CvDTreeSplit* find_split_ord_class( CvDTreeNode* n, int vi, 
-        float init_quality = 0, CvDTreeSplit* _split = 0 );
+        float init_quality = 0, CvDTreeSplit* _split = 0, uchar* ext_buf = 0 );
     virtual CvDTreeSplit* find_split_cat_class( CvDTreeNode* n, int vi,
-        float init_quality = 0, CvDTreeSplit* _split = 0 );
+        float init_quality = 0, CvDTreeSplit* _split = 0, uchar* ext_buf = 0 );
     virtual CvDTreeSplit* find_split_ord_reg( CvDTreeNode* n, int vi, 
-        float init_quality = 0, CvDTreeSplit* _split = 0 );
+        float init_quality = 0, CvDTreeSplit* _split = 0, uchar* ext_buf = 0 );
     virtual CvDTreeSplit* find_split_cat_reg( CvDTreeNode* n, int vi, 
-        float init_quality = 0, CvDTreeSplit* _split = 0 );
+        float init_quality = 0, CvDTreeSplit* _split = 0, uchar* ext_buf = 0 );
     virtual void calc_node_value( CvDTreeNode* n );
     virtual double calc_node_dir( CvDTreeNode* n );
 
index b3a45a2379d310ae29d6978ee0257ad80710e92e..3a35a55f92580574a9e1ecdb785775c2c48a364e 100644 (file)
@@ -107,7 +107,6 @@ CvBoostTree::train( CvDTreeTrainData* _train_data,
     ensemble = _ensemble;
     data = _train_data;
     data->shared = true;
-
     return do_train( _subsample_idx );
 }
 
@@ -168,9 +167,8 @@ CvBoostTree::try_split_node( CvDTreeNode* node )
         // if the node has not been split,
         // store the responses for the corresponding training samples
         double* weak_eval = ensemble->get_weak_response()->data.db;
-        int* labels_buf = data->get_cv_lables_buf();
-        const int* labels = 0;
-        data->get_cv_labels( node, labels_buf, &labels );
+        cv::AutoBuffer<int> inn_buf(node->sample_count);
+        const int* labels = data->get_cv_labels( node, (int*)inn_buf );
         int i, count = node->sample_count;
         double value = node->value;
 
@@ -192,9 +190,8 @@ CvBoostTree::calc_node_dir( CvDTreeNode* node )
 
     if( data->get_var_type(vi) >= 0 ) // split on categorical var
     {
-        int* cat_labels_buf = data->get_pred_int_buf();
-        const int* cat_labels = 0;
-        data->get_cat_var_data( node, vi, cat_labels_buf, &cat_labels );
+        cv::AutoBuffer<int> inn_buf(n);
+        const int* cat_labels = data->get_cat_var_data( node, vi, (int*)inn_buf );
         const int* subset = node->split->subset;
         double sum = 0, sum_abs = 0;
 
@@ -212,11 +209,13 @@ CvBoostTree::calc_node_dir( CvDTreeNode* node )
     }
     else // split on ordered var
     {
-        float* values_buf = data->get_pred_float_buf();
+        cv::AutoBuffer<uchar> inn_buf(2*n*sizeof(int)+n*sizeof(float));
+        float* values_buf = (float*)(uchar*)inn_buf;
+        int* sorted_indices_buf = (int*)(values_buf + n);
+        int* sample_indices_buf = sorted_indices_buf + n;
         const float* values = 0;
-        int* indices_buf = data->get_pred_int_buf();
-        const int* indices = 0;
-        data->get_ord_var_data( node, vi, values_buf, indices_buf, &values, &indices );
+        const int* sorted_indices = 0;
+        data->get_ord_var_data( node, vi, values_buf, sorted_indices_buf, &values, &sorted_indices, sample_indices_buf );
         int split_point = node->split->ord.split_point;
         int n1 = node->get_num_valid(vi);
 
@@ -225,7 +224,7 @@ CvBoostTree::calc_node_dir( CvDTreeNode* node )
 
         for( i = 0; i <= split_point; i++ )
         {
-            int idx = indices[i];
+            int idx = sorted_indices[i];
             double w = weights[idx];
             dir[idx] = (char)-1;
             L += w;
@@ -233,14 +232,14 @@ CvBoostTree::calc_node_dir( CvDTreeNode* node )
 
         for( ; i < n1; i++ )
         {
-            int idx = indices[i];
+            int idx = sorted_indices[i];
             double w = weights[idx];
             dir[idx] = (char)1;
             R += w;
         }
 
         for( ; i < n; i++ )
-            dir[indices[i]] = (char)0;
+            dir[sorted_indices[i]] = (char)0;
     }
 
     node->maxlr = MAX( L, R );
@@ -249,21 +248,27 @@ CvBoostTree::calc_node_dir( CvDTreeNode* node )
 
 
 CvDTreeSplit*
-CvBoostTree::find_split_ord_class( CvDTreeNode* node, int vi, float init_quality, CvDTreeSplit* _split )
+CvBoostTree::find_split_ord_class( CvDTreeNode* node, int vi, float init_quality,
+                                    CvDTreeSplit* _split, uchar* _ext_buf )
 {
     const float epsilon = FLT_EPSILON*2;
 
     const double* weights = ensemble->get_subtree_weights()->data.db;
     int n = node->sample_count;
     int n1 = node->get_num_valid(vi);
-    float* values_buf = data->get_pred_float_buf();
+
+    cv::AutoBuffer<uchar> inn_buf;
+    if( !_ext_buf )
+        inn_buf.allocate(n*(3*sizeof(int)+sizeof(float)));
+    uchar* ext_buf = _ext_buf ? _ext_buf : (uchar*)inn_buf;
+    float* values_buf = (float*)ext_buf;
+    int* sorted_indices_buf = (int*)(values_buf + n);
+    int* sample_indices_buf = sorted_indices_buf + n;
     const float* values = 0;
-    int* indices_buf = data->get_pred_int_buf();
-    const int* indices = 0;
-    data->get_ord_var_data( node, vi, values_buf, indices_buf, &values, &indices );
-    int* responses_buf = data->get_resp_int_buf();
-    const int* responses = 0;
-    data->get_class_labels( node, responses_buf, &responses);
+    const int* sorted_indices = 0;
+    data->get_ord_var_data( node, vi, values_buf, sorted_indices_buf, &values, &sorted_indices, sample_indices_buf );
+    int* responses_buf = sorted_indices_buf + n;
+    const int* responses = data->get_class_labels( node, responses_buf );
     const double* rcw0 = weights + n;
     double lcw[2] = {0,0}, rcw[2];
     int i, best_i = -1;
@@ -274,7 +279,7 @@ CvBoostTree::find_split_ord_class( CvDTreeNode* node, int vi, float init_quality
     rcw[0] = rcw0[0]; rcw[1] = rcw0[1];
     for( i = n1; i < n; i++ )
     {
-        int idx = indices[i];
+        int idx = sorted_indices[i];
         double w = weights[idx];
         rcw[responses[idx]] -= w;
     }
@@ -289,7 +294,7 @@ CvBoostTree::find_split_ord_class( CvDTreeNode* node, int vi, float init_quality
 
         for( i = 0; i < n1 - 1; i++ )
         {
-            int idx = indices[i];
+            int idx = sorted_indices[i];
             double w = weights[idx], w2 = w*w;
             double lv, rv;
             idx = responses[idx];
@@ -314,7 +319,7 @@ CvBoostTree::find_split_ord_class( CvDTreeNode* node, int vi, float init_quality
     {
         for( i = 0; i < n1 - 1; i++ )
         {
-            int idx = indices[i];
+            int idx = sorted_indices[i];
             double w = weights[idx];
             idx = responses[idx];
             lcw[idx] += w;
@@ -351,21 +356,28 @@ CvBoostTree::find_split_ord_class( CvDTreeNode* node, int vi, float init_quality
 static CV_IMPLEMENT_QSORT_EX( icvSortDblPtr, double*, CV_CMP_NUM_PTR, int )
 
 CvDTreeSplit*
-CvBoostTree::find_split_cat_class( CvDTreeNode* node, int vi, float init_quality, CvDTreeSplit* _split )
+CvBoostTree::find_split_cat_class( CvDTreeNode* node, int vi, float init_quality, CvDTreeSplit* _split, uchar* _ext_buf )
 {
     int ci = data->get_var_type(vi);
     int n = node->sample_count;
     int mi = data->cat_count->data.i[ci];
-    int* cat_labels_buf = data->get_pred_int_buf();
-    const int* cat_labels = 0;
-    data->get_cat_var_data(node, vi, cat_labels_buf, &cat_labels);
-    int* responses_buf = data->get_resp_int_buf();
-    const int* responses = 0;
-    data->get_class_labels(node, responses_buf, &responses);
+
+    int base_size = (2*mi+3)*sizeof(double) + mi*sizeof(double*);
+    cv::AutoBuffer<uchar> inn_buf((2*mi+3)*sizeof(double) + mi*sizeof(double*));
+    if( !_ext_buf)
+        inn_buf.allocate( base_size + 2*n*sizeof(int) );
+    uchar* base_buf = (uchar*)inn_buf;
+    uchar* ext_buf = _ext_buf ? _ext_buf : base_buf + base_size;
+
+    int* cat_labels_buf = (int*)ext_buf;
+    const int* cat_labels = data->get_cat_var_data(node, vi, cat_labels_buf);
+    int* responses_buf = cat_labels_buf + n;
+    const int* responses = data->get_class_labels(node, responses_buf);
     double lcw[2]={0,0}, rcw[2]={0,0};
-    double* cjk = (double*)cvStackAlloc(2*(mi+1)*sizeof(cjk[0]))+2;
+
+    double* cjk = (double*)cv::alignPtr(base_buf,sizeof(double))+2;
     const double* weights = ensemble->get_subtree_weights()->data.db;
-    double** dbl_ptr = (double**)cvStackAlloc( mi*sizeof(dbl_ptr[0]) );
+    double** dbl_ptr = (double**)(cjk + 2*mi);
     int i, j, k, idx;
     double L = 0, R;
     double best_val = init_quality;
@@ -465,21 +477,26 @@ CvBoostTree::find_split_cat_class( CvDTreeNode* node, int vi, float init_quality
 
 
 CvDTreeSplit*
-CvBoostTree::find_split_ord_reg( CvDTreeNode* node, int vi, float init_quality, CvDTreeSplit* _split )
+CvBoostTree::find_split_ord_reg( CvDTreeNode* node, int vi, float init_quality, CvDTreeSplit* _split, uchar* _ext_buf )
 {
     const float epsilon = FLT_EPSILON*2;
     const double* weights = ensemble->get_subtree_weights()->data.db;
     int n = node->sample_count;
     int n1 = node->get_num_valid(vi);
 
-    float* values_buf = data->get_pred_float_buf();
+    cv::AutoBuffer<uchar> inn_buf;
+    if( !_ext_buf )
+        inn_buf.allocate(2*n*(sizeof(int)+sizeof(float)));
+    uchar* ext_buf = _ext_buf ? _ext_buf : (uchar*)inn_buf;
+
+    float* values_buf = (float*)ext_buf;
+    int* indices_buf = (int*)(values_buf + n);
+    int* sample_indices_buf = indices_buf + n;
     const float* values = 0;
-    int* indices_buf = data->get_pred_int_buf();
     const int* indices = 0;
-    data->get_ord_var_data( node, vi, values_buf, indices_buf, &values, &indices );
-    float* responses_buf = data->get_resp_float_buf();
-    const float* responses = 0;
-    data->get_ord_responses(node, responses_buf, &responses);
+    data->get_ord_var_data( node, vi, values_buf, indices_buf, &values, &indices, sample_indices_buf );
+    float* responses_buf = (float*)(indices_buf + n);
+    const float* responses = data->get_ord_responses( node, responses_buf, sample_indices_buf );
 
     int i, best_i = -1;
     double L = 0, R = weights[n];
@@ -529,22 +546,28 @@ CvBoostTree::find_split_ord_reg( CvDTreeNode* node, int vi, float init_quality,
 
 
 CvDTreeSplit*
-CvBoostTree::find_split_cat_reg( CvDTreeNode* node, int vi, float init_quality, CvDTreeSplit* _split )
+CvBoostTree::find_split_cat_reg( CvDTreeNode* node, int vi, float init_quality, CvDTreeSplit* _split, uchar* _ext_buf )
 {
     const double* weights = ensemble->get_subtree_weights()->data.db;
     int ci = data->get_var_type(vi);
     int n = node->sample_count;
     int mi = data->cat_count->data.i[ci];
-    int* cat_labels_buf = data->get_pred_int_buf();
-    const int* cat_labels = 0;
-    data->get_cat_var_data(node, vi, cat_labels_buf, &cat_labels);
-    float* responses_buf = data->get_resp_float_buf();
-    const float* responses = 0;
-    data->get_ord_responses(node, responses_buf, &responses);
-
-    double* sum = (double*)cvStackAlloc( (mi+1)*sizeof(sum[0]) ) + 1;
-    double* counts = (double*)cvStackAlloc( (mi+1)*sizeof(counts[0]) ) + 1;
-    double** sum_ptr = (double**)cvStackAlloc( mi*sizeof(sum_ptr[0]) );
+    int base_size = (2*mi+3)*sizeof(double) + mi*sizeof(double*);
+    cv::AutoBuffer<uchar> inn_buf(base_size);
+    if( !_ext_buf )
+        inn_buf.allocate(base_size + n*(2*sizeof(int) + sizeof(float)));
+    uchar* base_buf = (uchar*)inn_buf;
+    uchar* ext_buf = _ext_buf ? _ext_buf : base_buf + base_size;
+
+    int* cat_labels_buf = (int*)ext_buf;
+    const int* cat_labels = data->get_cat_var_data(node, vi, cat_labels_buf);
+    float* responses_buf = (float*)(cat_labels_buf + n);
+    int* sample_indices_buf = (int*)(responses_buf + n);
+    const float* responses = data->get_ord_responses(node, responses_buf, sample_indices_buf);
+
+    double* sum = (double*)cv::alignPtr(base_buf,sizeof(double)) + 1;
+    double* counts = sum + mi + 1;
+    double** sum_ptr = (double**)(counts + mi);
     double L = 0, R = 0, best_val = init_quality, lsum = 0, rsum = 0;
     int i, best_subset = -1, subset_i;
 
@@ -619,14 +642,20 @@ CvBoostTree::find_split_cat_reg( CvDTreeNode* node, int vi, float init_quality,
 
 
 CvDTreeSplit*
-CvBoostTree::find_surrogate_split_ord( CvDTreeNode* node, int vi )
+CvBoostTree::find_surrogate_split_ord( CvDTreeNode* node, int vi, uchar* _ext_buf )
 {
     const float epsilon = FLT_EPSILON*2;
-    float* values_buf = data->get_pred_float_buf();
+    int n = node->sample_count;
+    cv::AutoBuffer<uchar> inn_buf;
+    if( !_ext_buf )
+        inn_buf.allocate(n*(2*sizeof(int)+sizeof(float)));
+    uchar* ext_buf = _ext_buf ? _ext_buf : (uchar*)inn_buf;
+    float* values_buf = (float*)ext_buf;
+    int* indices_buf = (int*)(values_buf + n);
+    int* sample_indices_buf = indices_buf + n;
     const float* values = 0;
-    int* indices_buf = data->get_pred_int_buf();
     const int* indices = 0;
-    data->get_ord_var_data( node, vi, values_buf, indices_buf, &values, &indices );
+    data->get_ord_var_data( node, vi, values_buf, indices_buf, &values, &indices, sample_indices_buf );
 
     const double* weights = ensemble->get_subtree_weights()->data.db;
     const char* dir = (char*)data->direction->data.ptr;
@@ -690,23 +719,28 @@ CvBoostTree::find_surrogate_split_ord( CvDTreeNode* node, int vi )
 
 
 CvDTreeSplit*
-CvBoostTree::find_surrogate_split_cat( CvDTreeNode* node, int vi )
+CvBoostTree::find_surrogate_split_cat( CvDTreeNode* node, int vi, uchar* _ext_buf )
 {
     const char* dir = (char*)data->direction->data.ptr;
     const double* weights = ensemble->get_subtree_weights()->data.db;
     int n = node->sample_count;
-    int* cat_labels_buf = data->get_pred_int_buf();
-    const int* cat_labels = 0;
-    data->get_cat_var_data(node, vi, cat_labels_buf, &cat_labels);
+    int i, mi = data->cat_count->data.i[data->get_var_type(vi)];
+
+    int base_size = (2*mi+3)*sizeof(double);
+    cv::AutoBuffer<uchar> inn_buf(base_size);
+    if( !_ext_buf )
+        inn_buf.allocate(base_size + n*sizeof(int));
+    uchar* ext_buf = _ext_buf ? _ext_buf : (uchar*)inn_buf;
+    int* cat_labels_buf = (int*)ext_buf;
+    const int* cat_labels = data->get_cat_var_data(node, vi, cat_labels_buf);
 
     // LL - number of samples that both the primary and the surrogate splits send to the left
     // LR - ... primary split sends to the left and the surrogate split sends to the right
     // RL - ... primary split sends to the right and the surrogate split sends to the left
     // RR - ... both send to the right
     CvDTreeSplit* split = data->new_split_cat( vi, 0 );
-    int i, mi = data->cat_count->data.i[data->get_var_type(vi)];
     double best_val = 0;
-    double* lc = (double*)cvStackAlloc( (mi+1)*2*sizeof(lc[0]) ) + 1;
+    double* lc = (double*)cv::alignPtr(cat_labels_buf + n, sizeof(double)) + 1;
     double* rc = lc + mi + 1;
 
     for( i = -1; i < mi; i++ )
@@ -759,18 +793,17 @@ CvBoostTree::calc_node_value( CvDTreeNode* node )
 {
     int i, n = node->sample_count;
     const double* weights = ensemble->get_weights()->data.db;
-    int* labels_buf = data->get_cv_lables_buf();
-    const int* labels = 0;
-    data->get_cv_labels(node, labels_buf, &labels);
+    cv::AutoBuffer<uchar> inn_buf(n*(sizeof(int) + ( data->is_classifier ? sizeof(int) : sizeof(int) + sizeof(float))));
+    int* labels_buf = (int*)(uchar*)inn_buf;
+    const int* labels = data->get_cv_labels(node, labels_buf);
     double* subtree_weights = ensemble->get_subtree_weights()->data.db;
     double rcw[2] = {0,0};
     int boost_type = ensemble->get_params().boost_type;
 
     if( data->is_classifier )
     {
-        int* _responses_buf = data->get_resp_int_buf();
-        const int* _responses = 0;
-        data->get_class_labels(node, _responses_buf, &_responses);
+        int* _responses_buf = labels_buf + n;
+        const int* _responses = data->get_class_labels(node, _responses_buf);
         int m = data->get_num_classes();
         int* cls_count = data->counts->data.i;
         for( int k = 0; k < m; k++ )
@@ -810,9 +843,9 @@ CvBoostTree::calc_node_value( CvDTreeNode* node )
         //    n is the number of samples in the node.
         //  * node risk is the sum of squared errors: sum_i((Y_i - <node_value>)^2)
         double sum = 0, sum2 = 0, iw;
-        float* values_buf = data->get_resp_float_buf();
-        const float* values = 0;
-        data->get_ord_responses(node, values_buf, &values);
+        float* values_buf = (float*)(labels_buf + n);
+        int* sample_indices_buf = (int*)(values_buf + n);
+        const float* values = data->get_ord_responses(node, values_buf, sample_indices_buf);
 
         for( i = 0; i < n; i++ )
         {
@@ -1087,27 +1120,36 @@ CvBoost::update_weights( CvBoostTree* tree )
     float* fdata = 0;
     int *sample_idx_buf;
     const int* sample_idx = 0;
+    cv::AutoBuffer<uchar> inn_buf;
+    int _buf_size = (params.boost_type == LOGIT) || (params.boost_type == GENTLE) ? data->sample_count*sizeof(int) : 0;
+    if( !tree )
+        _buf_size += n*sizeof(int);
+    else
+    {
+        if( have_subsample )
+            _buf_size += data->buf->step*(sizeof(float)+sizeof(uchar));
+    }
+    inn_buf.allocate(_buf_size);
+    uchar* cur_buf_pos = (uchar*)inn_buf;
+
     if ( (params.boost_type == LOGIT) || (params.boost_type == GENTLE) )
     {
         step = CV_IS_MAT_CONT(data->responses_copy->type) ?
             1 : data->responses_copy->step / CV_ELEM_SIZE(data->responses_copy->type);
         fdata = data->responses_copy->data.fl;
-        sample_idx_buf = (int*)cvStackAlloc(data->sample_count*sizeof(sample_idx_buf[0]));
-        data->get_sample_indices( data->data_root, sample_idx_buf, &sample_idx );    
+        sample_idx_buf = (int*)cur_buf_pos;
+        cur_buf_pos = (uchar*)(sample_idx_buf + data->sample_count);
+        sample_idx = data->get_sample_indices( data->data_root, sample_idx_buf );
     }
-    CvMat* buf = data->buf;
+    CvMat* dtree_data_buf = data->buf;
     if( !tree ) // before training the first tree, initialize weights and other parameters
     {
-        int n = data->sample_count;
-        int* class_labels_buf = data->get_resp_int_buf();
-        const int* class_labels = 0;
-        data->get_class_labels(data->data_root, class_labels_buf, &class_labels);
+        int* class_labels_buf = (int*)cur_buf_pos;
+        cur_buf_pos = (uchar*)(class_labels_buf + n);
+        const int* class_labels = data->get_class_labels(data->data_root, class_labels_buf);
         // in case of logitboost and gentle adaboost each weak tree is a regression tree,
         // so we need to convert class labels to floating-point values
-        float* responses_buf = data->get_resp_float_buf();
-        const float* responses = 0;
-        data->get_ord_responses(data->data_root, responses_buf, &responses);
-        
+
         double w0 = 1./n;
         double p[2] = { 1, 1 };
 
@@ -1138,7 +1180,7 @@ CvBoost::update_weights( CvBoostTree* tree )
 
         if (data->is_buf_16u)
         {
-            unsigned short* labels = (unsigned short*)(buf->data.s + data->data_root->buf_idx*buf->cols + 
+            unsigned short* labels = (unsigned short*)(dtree_data_buf->data.s + data->data_root->buf_idx*dtree_data_buf->cols +
                 data->data_root->offset + (data->work_var_count-1)*data->sample_count);
             for( i = 0; i < n; i++ )
             {
@@ -1156,7 +1198,7 @@ CvBoost::update_weights( CvBoostTree* tree )
         }
         else
         {
-            int* labels = buf->data.i + data->data_root->buf_idx*buf->cols + 
+            int* labels = dtree_data_buf->data.i + data->data_root->buf_idx*dtree_data_buf->cols +
                 data->data_root->offset + (data->work_var_count-1)*data->sample_count;
 
             for( i = 0; i < n; i++ )
@@ -1202,8 +1244,10 @@ CvBoost::update_weights( CvBoostTree* tree )
         // recent weak classifier we know the responses. For other samples we need to compute them
         if( have_subsample )
         {
-            float* values0, *values = (float*)cvStackAlloc(data->buf->step*sizeof(float));
-            uchar* missing0, *missing = (uchar*)cvStackAlloc(data->buf->step*sizeof(uchar));
+            float* values0, *values = (float*)cur_buf_pos;
+            cur_buf_pos = (uchar*)(values + data->buf->step);
+            uchar* missing0, *missing = cur_buf_pos;
+            cur_buf_pos = missing + data->buf->step;
             CvMat _sample, _mask;
             values0 = values;
             missing0 = missing;
@@ -1294,9 +1338,9 @@ CvBoost::update_weights( CvBoostTree* tree )
 
             const double lb_weight_thresh = FLT_EPSILON;
             const double lb_z_max = 10.;
-            float* responses_buf = data->get_resp_float_buf();
+            /*float* responses_buf = data->get_resp_float_buf();
             const float* responses = 0;
-            data->get_ord_responses(data->data_root, responses_buf, &responses);
+            data->get_ord_responses(data->data_root, responses_buf, &responses);*/
 
             /*if( weak->total == 7 )
                 putchar('*');*/
index 4f70fc76a30f7dc895939a615feea13fb2b21610..2f977dc52d70fce62beb307dd1e49d69893bab60 100644 (file)
@@ -40,10 +40,6 @@ M*/
 
 #include "_ml.h"
 
-#ifdef _OPENMP
-#include "omp.h"
-#endif
-
 static const float ord_nan = FLT_MAX*0.5f;
 static const int min_block_size = 1 << 16;
 static const int block_size_delta = 1 << 10;
@@ -518,28 +514,6 @@ void CvERTreeTrainData::set_data( const CvMat* _train_data, int _tflag,
     CV_CALL( direction = cvCreateMat( 1, sample_count, CV_8UC1 ));
     CV_CALL( split_buf = cvCreateMat( 1, sample_count, CV_32SC1 ));
 
-    {
-        int maxNumThreads = 1;
-#ifdef _OPENMP
-        maxNumThreads = omp_get_num_procs();
-#endif
-        pred_float_buf.resize(maxNumThreads);
-        pred_int_buf.resize(maxNumThreads);
-        resp_float_buf.resize(maxNumThreads);
-        resp_int_buf.resize(maxNumThreads);
-        cv_lables_buf.resize(maxNumThreads);
-        sample_idx_buf.resize(maxNumThreads);
-        for( int ti = 0; ti < maxNumThreads; ti++ )
-        {
-            pred_float_buf[ti].resize(sample_count);
-            pred_int_buf[ti].resize(sample_count);
-            resp_float_buf[ti].resize(sample_count);
-            resp_int_buf[ti].resize(sample_count);
-            cv_lables_buf[ti].resize(sample_count);
-            sample_idx_buf[ti].resize(sample_count);
-        }
-    }
-    
     __END__;
 
     if( data )
@@ -555,14 +529,13 @@ void CvERTreeTrainData::set_data( const CvMat* _train_data, int _tflag,
     cvReleaseMat( &tmp_map );
 }
 
-int CvERTreeTrainData::get_ord_var_data( CvDTreeNode* n, int vi, float* ord_values_buf, int* missing_buf, const float** ord_values, const int** missing )
+void CvERTreeTrainData::get_ord_var_data( CvDTreeNode* n, int vi, float* ord_values_buf, int* missing_buf,
+                                          const float** ord_values, const int** missing, int* sample_indices_buf )
 {
     int vidx = var_idx ? var_idx->data.i[vi] : vi;
     int node_sample_count = n->sample_count; 
-    int* sample_indices_buf = get_sample_idx_buf();
-    const int* sample_indices = 0;
-
-    get_sample_indices(n, sample_indices_buf, &sample_indices);
+    // may use missing_buf as buffer for sample indices!
+    const int* sample_indices = get_sample_indices(n, sample_indices_buf ? sample_indices_buf : missing_buf);
 
     int td_step = train_data->step/CV_ELEM_SIZE(train_data->type);
     int m_step = missing_mask ? missing_mask->step/CV_ELEM_SIZE(missing_mask->type) : 1;
@@ -584,38 +557,37 @@ int CvERTreeTrainData::get_ord_var_data( CvDTreeNode* n, int vi, float* ord_valu
         }
     *ord_values = ord_values_buf;
     *missing = missing_buf;
-    return 0; //TODO: return the number of non-missing values
 }
 
 
-void CvERTreeTrainData::get_sample_indices( CvDTreeNode* n, int* indices_buf, const int** indices )
+const int* CvERTreeTrainData::get_sample_indices( CvDTreeNode* n, int* indices_buf )
 {
-    get_cat_var_data( n, var_count + (is_classifier ? 1 : 0) + (have_labels ? 1 : 0), indices_buf, indices );
+    return get_cat_var_data( n, var_count + (is_classifier ? 1 : 0) + (have_labels ? 1 : 0), indices_buf );
 }
 
 
-void CvERTreeTrainData::get_cv_labels( CvDTreeNode* n, int* labels_buf, const int** labels )
+const int* CvERTreeTrainData::get_cv_labels( CvDTreeNode* n, int* labels_buf )
 {
     if (have_labels)
-        get_cat_var_data( n, var_count + (is_classifier ? 1 : 0), labels_buf, labels );
+        return get_cat_var_data( n, var_count + (is_classifier ? 1 : 0), labels_buf );
+    return 0;
 }
 
 
-int CvERTreeTrainData::get_cat_var_data( CvDTreeNode* n, int vi, int* cat_values_buf, const int** cat_values )
+const int* CvERTreeTrainData::get_cat_var_data( CvDTreeNode* n, int vi, int* cat_values_buf )
 {
     int ci = get_var_type( vi);
+    const int* cat_values = 0;
     if( !is_buf_16u )
-        *cat_values = buf->data.i + n->buf_idx*buf->cols + 
-        ci*sample_count + n->offset;
+        cat_values = buf->data.i + n->buf_idx*buf->cols + ci*sample_count + n->offset;
     else {
         const unsigned short* short_values = (const unsigned short*)(buf->data.s + n->buf_idx*buf->cols + 
             ci*sample_count + n->offset);
         for( int i = 0; i < n->sample_count; i++ )
             cat_values_buf[i] = short_values[i];
-        *cat_values = cat_values_buf;
+        cat_values = cat_values_buf;
     }
-
-    return 0; //TODO: return the number of non-missing values
+    return cat_values;
 }
 
 void CvERTreeTrainData::get_vectors( const CvMat* _subsample_idx,
@@ -625,6 +597,8 @@ void CvERTreeTrainData::get_vectors( const CvMat* _subsample_idx,
     CvMat* subsample_idx = 0;
     CvMat* subsample_co = 0;
 
+    cv::AutoBuffer<uchar> inn_buf(sample_count*(sizeof(float) + sizeof(int)));
+
     CV_FUNCNAME( "CvERTreeTrainData::get_vectors" );
 
     __BEGIN__;
@@ -664,9 +638,8 @@ void CvERTreeTrainData::get_vectors( const CvMat* _subsample_idx,
         {
             float* dst = values + vi;
             uchar* m = missing ? missing + vi : 0;
-            int* src_buf = get_pred_int_buf();
-            const int* src = 0; 
-            get_cat_var_data(data_root, vi, src_buf, &src);
+            int* lbls_buf = (int*)(uchar*)inn_buf;
+            const int* src = get_cat_var_data(data_root, vi, lbls_buf);
 
             for( i = 0; i < count; i++, dst += var_count )
             {
@@ -682,13 +655,12 @@ void CvERTreeTrainData::get_vectors( const CvMat* _subsample_idx,
         }
         else // ordered
         {
-            float* dst_buf = values + vi;
-            int* m_buf = get_pred_int_buf();
+            int* mis_buf = (int*)(uchar*)inn_buf;
             const float *dst = 0;
-            const int* m = 0;
-            get_ord_var_data(data_root, vi, dst_buf, m_buf, &dst, &m);
+            const int* mis = 0;
+            get_ord_var_data(data_root, vi, values + vi, mis_buf, &dst, &mis, 0);
             for (int si = 0; si < total; si++)
-                *(missing + vi + si) = m[si] == 0 ? 0 : 1;
+                *(missing + vi + si) = mis[si] == 0 ? 0 : 1;
         }
     }
 
@@ -697,9 +669,8 @@ void CvERTreeTrainData::get_vectors( const CvMat* _subsample_idx,
     {
         if( is_classifier )
         {
-            int* src_buf = get_resp_int_buf();
-            const int* src = 0;
-            get_class_labels(data_root, src_buf, &src);
+            int* lbls_buf = (int*)(uchar*)inn_buf;
+            const int* src = get_class_labels(data_root, lbls_buf);
             for( i = 0; i < count; i++ )
             {
                 int idx = sidx ? sidx[i] : i;
@@ -710,9 +681,9 @@ void CvERTreeTrainData::get_vectors( const CvMat* _subsample_idx,
         }
         else           
         {
-            float *_values_buf = get_resp_float_buf();
-            const float* _values = 0;
-            get_ord_responses(data_root, _values_buf, &_values);
+            float* _values_buf = (float*)(uchar*)inn_buf;
+            int* sample_idx_buf = (int*)(_values_buf + sample_count);
+            const float* _values = get_ord_responses(data_root, _values_buf, sample_idx_buf);
             for( i = 0; i < count; i++ )
             {
                 int idx = sidx ? sidx[i] : i;
@@ -773,10 +744,10 @@ double CvForestERTree::calc_node_dir( CvDTreeNode* node )
 
     if( data->get_var_type(vi) >= 0 ) // split on categorical var
     {
-        int* labels_buf = data->get_pred_int_buf();
-        const int* labels = 0;
+        cv::AutoBuffer<uchar> inn_buf(n*sizeof(int)*(!data->have_priors ? 1 : 2));
+        int* labels_buf = (int*)(uchar*)inn_buf;
+        const int* labels = data->get_cat_var_data( node, vi, labels_buf );
         const int* subset = node->split->subset;
-        data->get_cat_var_data( node, vi, labels_buf, &labels );
         if( !data->have_priors )
         {
             int sum = 0, sum_abs = 0;
@@ -797,9 +768,8 @@ double CvForestERTree::calc_node_dir( CvDTreeNode* node )
         {
             const double* priors = data->priors_mult->data.db;
             double sum = 0, sum_abs = 0;
-            int *responses_buf = data->get_resp_int_buf();
-            const int* responses;
-            data->get_class_labels(node, responses_buf, &responses);
+            int *responses_buf = labels_buf + n;
+            const int* responses = data->get_class_labels(node, responses_buf);
 
             for( i = 0; i < n; i++ )
             {
@@ -817,11 +787,12 @@ double CvForestERTree::calc_node_dir( CvDTreeNode* node )
     else // split on ordered var
     {
         float split_val = node->split->ord.c;
-        float* val_buf = data->get_pred_float_buf();
+        cv::AutoBuffer<uchar> inn_buf(n*(sizeof(int)*(!data->have_priors ? 1 : 2) + sizeof(float)));
+        float* val_buf = (float*)(uchar*)inn_buf;
+        int* missing_buf = (int*)(val_buf + n);
         const float* val = 0;
-        int* missing_buf = data->get_pred_int_buf();
         const int* missing = 0;
-        data->get_ord_var_data( node, vi, val_buf, missing_buf, &val, &missing );
+        data->get_ord_var_data( node, vi, val_buf, missing_buf, &val, &missing, 0 );
 
         if( !data->have_priors )
         {
@@ -848,9 +819,8 @@ double CvForestERTree::calc_node_dir( CvDTreeNode* node )
         else
         {
             const double* priors = data->priors_mult->data.db;
-            int* responses_buf = data->get_resp_int_buf();
-            const int* responses = 0;
-            data->get_class_labels(node, responses_buf, &responses);
+            int* responses_buf = missing_buf + n;
+            const int* responses = data->get_class_labels(node, responses_buf);
             L = R = 0;
             for( i = 0; i < n; i++ )
             {
@@ -878,31 +848,30 @@ double CvForestERTree::calc_node_dir( CvDTreeNode* node )
     return node->split->quality/(L + R);
 }
 
-CvDTreeSplit* CvForestERTree::find_split_ord_class( CvDTreeNode* node, int vi, float init_quality, CvDTreeSplit* _split )
+CvDTreeSplit* CvForestERTree::find_split_ord_class( CvDTreeNode* node, int vi, float init_quality, CvDTreeSplit* _split,
+                                                    uchar* _ext_buf )
 {
     const float epsilon = FLT_EPSILON*2;
     const float split_delta = (1 + FLT_EPSILON) * FLT_EPSILON;
 
-    int n = node->sample_count;
+    int n = node->sample_count, i;
     int m = data->get_num_classes();
 
-    float* values_buf = data->get_pred_float_buf();
+    cv::AutoBuffer<uchar> inn_buf;
+    if( !_ext_buf )
+        inn_buf.allocate(n*(2*sizeof(int) + sizeof(float)));
+    uchar* ext_buf = _ext_buf ? _ext_buf : (uchar*)inn_buf;
+    float* values_buf = (float*)ext_buf;
+    int* missing_buf = (int*)(values_buf + n);
     const float* values = 0;
-    int* missing_buf = data->get_pred_int_buf();
     const int* missing = 0;
-    data->get_ord_var_data( node, vi, values_buf, missing_buf, &values, &missing );
-    int* responses_buf =  data->get_resp_int_buf();
-    const int* responses = 0;
-    data->get_class_labels( node, responses_buf, &responses );
+    data->get_ord_var_data( node, vi, values_buf, missing_buf, &values, &missing, 0 );
+    int* responses_buf = missing_buf + n;
+    const int* responses = data->get_class_labels( node, responses_buf );
 
     double lbest_val = 0, rbest_val = 0, best_val = init_quality, split_val = 0;
-    
-    int i;
-
     const double* priors = data->have_priors ? data->priors_mult->data.db : 0;
-
     bool is_find_split = false;
-    
     float pmin, pmax;
     int smpi = 0;
     while ( missing[smpi] && (smpi < n) )
@@ -1022,7 +991,8 @@ CvDTreeSplit* CvForestERTree::find_split_ord_class( CvDTreeNode* node, int vi, f
     return split;
 }
 
-CvDTreeSplit* CvForestERTree::find_split_cat_class( CvDTreeNode* node, int vi, float init_quality, CvDTreeSplit* _split )
+CvDTreeSplit* CvForestERTree::find_split_cat_class( CvDTreeNode* node, int vi, float init_quality, CvDTreeSplit* _split,
+                                                    uchar* _ext_buf )
 {
     int ci = data->get_var_type(vi);
     int n = node->sample_count;
@@ -1033,13 +1003,13 @@ CvDTreeSplit* CvForestERTree::find_split_cat_class( CvDTreeNode* node, int vi, f
 
     if ( vm > 1 )
     {
-        int* labels_buf = data->get_pred_int_buf();
-        const int* labels = 0;
-        data->get_cat_var_data( node, vi, labels_buf, &labels );
+        cv::AutoBuffer<int> inn_buf;
+        if( !_ext_buf )
+            inn_buf.allocate(2*n);
+        int* ext_buf = _ext_buf ? (int*)_ext_buf : (int*)inn_buf;
 
-        int* responses_buf =  data->get_resp_int_buf();
-        const int* responses = 0;
-        data->get_class_labels( node, responses_buf, &responses );
+        const int* labels = data->get_cat_var_data( node, vi, ext_buf );
+        const int* responses = data->get_class_labels( node, ext_buf + n );
     
         const double* priors = data->have_priors ? data->priors_mult->data.db : 0;       
 
@@ -1173,19 +1143,24 @@ CvDTreeSplit* CvForestERTree::find_split_cat_class( CvDTreeNode* node, int vi, f
     return split;
 }
 
-CvDTreeSplit* CvForestERTree::find_split_ord_reg( CvDTreeNode* node, int vi, float init_quality, CvDTreeSplit* _split )
+CvDTreeSplit* CvForestERTree::find_split_ord_reg( CvDTreeNode* node, int vi, float init_quality, CvDTreeSplit* _split,
+                                                  uchar* _ext_buf )
 {
     const float epsilon = FLT_EPSILON*2;
     const float split_delta = (1 + FLT_EPSILON) * FLT_EPSILON;
     int n = node->sample_count;
-    float* values_buf = data->get_pred_float_buf();
+    cv::AutoBuffer<uchar> inn_buf;
+    if( !_ext_buf )
+        inn_buf.allocate(n*(2*sizeof(int) + 2*sizeof(float)));
+    uchar* ext_buf = _ext_buf ? _ext_buf : (uchar*)inn_buf;
+    float* values_buf = (float*)ext_buf;
+    int* missing_buf = (int*)(values_buf + n);
     const float* values = 0;
-    int* missing_buf = data->get_pred_int_buf();
     const int* missing = 0;
-    data->get_ord_var_data( node, vi, values_buf, missing_buf, &values, &missing );
-    float* responses_buf =  data->get_resp_float_buf();
-    const float* responses = 0;
-    data->get_ord_responses( node, responses_buf, &responses );
+    data->get_ord_var_data( node, vi, values_buf, missing_buf, &values, &missing, 0 );
+    float* responses_buf =  (float*)(missing_buf + n);
+    int* sample_indices_buf =  (int*)(responses_buf + n);
+    const float* responses = data->get_ord_responses( node, responses_buf, sample_indices_buf );
 
     double best_val = init_quality, split_val = 0, lsum = 0, rsum = 0;
     int L = 0, R = 0;
@@ -1254,7 +1229,8 @@ CvDTreeSplit* CvForestERTree::find_split_ord_reg( CvDTreeNode* node, int vi, flo
     return split;
 }
 
-CvDTreeSplit* CvForestERTree::find_split_cat_reg( CvDTreeNode* node, int vi, float init_quality, CvDTreeSplit* _split )
+CvDTreeSplit* CvForestERTree::find_split_cat_reg( CvDTreeNode* node, int vi, float init_quality, CvDTreeSplit* _split,
+                                                  uchar* _ext_buf )
 {
     int ci = data->get_var_type(vi);
     int n = node->sample_count;
@@ -1265,16 +1241,20 @@ CvDTreeSplit* CvForestERTree::find_split_cat_reg( CvDTreeNode* node, int vi, flo
 
     if ( vm > 1 )
     {
-        int* labels_buf = data->get_pred_int_buf();
-        const int* labels = 0;
-        data->get_cat_var_data( node, vi, labels_buf, &labels );
-
-        float* responses_buf =  data->get_resp_float_buf();
-        const float* responses = 0;
-        data->get_ord_responses( node, responses_buf, &responses );
+        int base_size =  vm*sizeof(int);
+        cv::AutoBuffer<uchar> inn_buf(base_size);
+        if( !_ext_buf )
+            inn_buf.allocate(base_size + n*(2*sizeof(int) + sizeof(float)));
+        uchar* base_buf = (uchar*)inn_buf;
+        uchar* ext_buf = _ext_buf ? _ext_buf : base_buf + base_size;
+        int* labels_buf = (int*)ext_buf;
+        const int* labels = data->get_cat_var_data( node, vi, labels_buf );
+        float* responses_buf =  (float*)(labels_buf + n);
+        int* sample_indices_buf = (int*)(responses_buf + n);
+        const float* responses = data->get_ord_responses( node, responses_buf, sample_indices_buf );
 
         // create random class mask
-        int *valid_cidx = (int*)cvStackAlloc(vm*sizeof(valid_cidx[0]));
+        int *valid_cidx = (int*)base_buf;
         for (int i = 0; i < vm; i++)
         {
             valid_cidx[i] = -1;
@@ -1347,88 +1327,6 @@ CvDTreeSplit* CvForestERTree::find_split_cat_reg( CvDTreeNode* node, int vi, flo
     return split;
 }
 
-//void CvForestERTree::complete_node_dir( CvDTreeNode* node )
-//{
-//    int vi, i, n = node->sample_count, nl, nr, d0 = 0, d1 = -1;
-//    int nz = n - node->get_num_valid(node->split->var_idx);
-//    char* dir = (char*)data->direction->data.ptr;
-//
-//    // try to complete direction using surrogate splits
-//    if( nz && data->params.use_surrogates )
-//    {
-//        CvDTreeSplit* split = node->split->next;
-//        for( ; split != 0 && nz; split = split->next )
-//        {
-//            int inversed_mask = split->inversed ? -1 : 0;
-//            vi = split->var_idx;
-//
-//            if( data->get_var_type(vi) >= 0 ) // split on categorical var
-//            {
-//                int* labels_buf = data->pred_int_buf;
-//                const int* labels = 0;
-//                data->get_cat_var_data(node, vi, labels_buf, &labels);
-//                const int* subset = split->subset;
-//
-//                for( i = 0; i < n; i++ )
-//                {
-//                    int idx = labels[i];
-//                    if( !dir[i] && ( ((idx >= 0)&&(!data->is_buf_16u)) || ((idx != 65535)&&(data->is_buf_16u)) ))
-//                        
-//                    {
-//                        int d = CV_DTREE_CAT_DIR(idx,subset);
-//                        dir[i] = (char)((d ^ inversed_mask) - inversed_mask);
-//                        if( --nz )
-//                            break;
-//                    }
-//                }
-//            }
-//            else // split on ordered var
-//            {
-//                float* values_buf = data->pred_float_buf;
-//                const float* values = 0;
-//                uchar* missing_buf = (uchar*)data->pred_int_buf;
-//                const uchar* missing = 0;
-//                data->get_ord_var_data( node, vi, values_buf, missing_buf, &values, &missing );
-//                float split_val = node->split->ord.c;
-//                
-//                for( i = 0; i < n; i++ )
-//                {
-//                    if( !dir[i] && !missing[i])
-//                    {
-//                        int d = values[i] <= split_val ? -1 : 1;
-//                        dir[i] = (char)((d ^ inversed_mask) - inversed_mask);
-//                        if( --nz )
-//                            break;
-//                    }
-//                }
-//            }
-//        }
-//    }
-//
-//    // find the default direction for the rest
-//    if( nz )
-//    {
-//        for( i = nr = 0; i < n; i++ )
-//            nr += dir[i] > 0;
-//        nl = n - nr - nz;
-//        d0 = nl > nr ? -1 : nr > nl;
-//    }
-//
-//    // make sure that every sample is directed either to the left or to the right
-//    for( i = 0; i < n; i++ )
-//    {
-//        int d = dir[i];
-//        if( !d )
-//        {
-//            d = d0;
-//            if( !d )
-//                d = d1, d1 = -d1;
-//        }
-//        d = d > 0;
-//        dir[i] = (char)d; // remap (-1,1) to (0,1)
-//    }
-//}
-
 void CvForestERTree::split_node_data( CvDTreeNode* node )
 {
     int vi, i, n = node->sample_count, nl, nr, scount = data->sample_count;
@@ -1455,6 +1353,7 @@ void CvForestERTree::split_node_data( CvDTreeNode* node )
         (node->left->sample_count > data->params.min_sample_count ||
         node->right->sample_count > data->params.min_sample_count);
 
+    cv::AutoBuffer<uchar> inn_buf(n*(sizeof(int)+sizeof(float)));
     // split ordered vars
     for( vi = 0; vi < data->var_count; vi++ )
     {
@@ -1462,12 +1361,11 @@ void CvForestERTree::split_node_data( CvDTreeNode* node )
         if (ci >= 0) continue;
         
         int n1 = node->get_num_valid(vi), nr1 = 0;
-
-        float* values_buf = data->get_pred_float_buf();
+        float* values_buf = (float*)(uchar*)inn_buf;
+        int* missing_buf = (int*)(values_buf + n);
         const float* values = 0;
-        int* missing_buf = data->get_pred_int_buf();
         const int* missing = 0;
-        data->get_ord_var_data( node, vi, values_buf, missing_buf, &values, &missing );
+        data->get_ord_var_data( node, vi, values_buf, missing_buf, &values, &missing, 0 );
 
         for( i = 0; i < n; i++ )
             nr1 += (!missing[i] & dir[i]);
@@ -1481,10 +1379,7 @@ void CvForestERTree::split_node_data( CvDTreeNode* node )
         if (ci < 0) continue;
 
         int n1 = node->get_num_valid(vi), nr1 = 0;
-        
-        int *src_lbls_buf = data->get_pred_int_buf();
-        const int* src_lbls = 0;
-        data->get_cat_var_data(node, vi, src_lbls_buf, &src_lbls);
+        const int* src_lbls = data->get_cat_var_data(node, vi, (int*)(uchar*)inn_buf);
 
         for(i = 0; i < n; i++)
             temp_buf[i] = src_lbls[i];
@@ -1552,13 +1447,12 @@ void CvForestERTree::split_node_data( CvDTreeNode* node )
         }        
     }
 
-
     // split sample indices
-    int *sample_idx_src_buf = data->get_sample_idx_buf();
+    int *sample_idx_src_buf = (int*)(uchar*)inn_buf;
     const int* sample_idx_src = 0;
     if (split_input_data)
     {
-        data->get_sample_indices(node, sample_idx_src_buf, &sample_idx_src);
+        sample_idx_src = data->get_sample_indices(node, sample_idx_src_buf);
 
         for(i = 0; i < n; i++)
             temp_buf[i] = sample_idx_src[i];
index d233b0772bb44d5374e9719cba1c21f33c30801b..add0733fb9d889a88adf47e9c4176be2003edec2 100644 (file)
 \r
 #include "_ml.h"\r
 \r
-#ifdef _OPENMP
-#include "omp.h"
-#endif\r
-\r
 CvForestTree::CvForestTree()\r
 {\r
     forest = NULL;\r
@@ -86,58 +82,29 @@ CvForestTree::train( CvDTreeTrainData*, const CvMat* )
 }\r
 \r
 \r
-CvDTreeSplit* CvForestTree::find_best_split( CvDTreeNode* node )\r
-{\r
-    int vi;\r
 \r
-    CvDTreeSplit *best_split = 0;\r
+namespace cv\r
+{\r
 \r
-    CvMat* active_var_mask = 0;\r
-    if( forest )\r
-    {\r
-        int var_count;\r
-        CvRNG* rng = forest->get_rng();\r
+ForestTreeBestSplitFinder::ForestTreeBestSplitFinder( CvForestTree* _tree, CvDTreeNode* _node ) :\r
+    DTreeBestSplitFinder(_tree, _node) {}\r
 \r
-        active_var_mask = forest->get_active_var_mask();\r
-        var_count = active_var_mask->cols;\r
+ForestTreeBestSplitFinder::ForestTreeBestSplitFinder( const ForestTreeBestSplitFinder& finder, Split spl ) :\r
+    DTreeBestSplitFinder( finder, spl ) {}\r
 \r
-        CV_Assert( var_count == data->var_count );\r
+void ForestTreeBestSplitFinder::operator()(const BlockedRange& range)\r
+{\r
+    int vi, vi1 = range.begin(), vi2 = range.end();\r
+    int n = node->sample_count;\r
+    CvDTreeTrainData* data = tree->get_data();\r
+    AutoBuffer<uchar> inn_buf(2*n*(sizeof(int) + sizeof(float)));\r
 \r
-        for( vi = 0; vi < var_count; vi++ )\r
-        {\r
-            uchar temp;\r
-            int i1 = cvRandInt(rng) % var_count;\r
-            int i2 = cvRandInt(rng) % var_count;\r
-            CV_SWAP( active_var_mask->data.ptr[i1],\r
-                active_var_mask->data.ptr[i2], temp );\r
-        }\r
-    }\r
-    int maxNumThreads = 1;\r
-#ifdef _OPENMP\r
-    maxNumThreads = omp_get_num_procs();\r
-#endif\r
-    std::vector<CvDTreeSplit*> splits(maxNumThreads);\r
-    std::vector<CvDTreeSplit*> bestSplits(maxNumThreads);\r
-    std::vector<int> canSplit(maxNumThreads);\r
-    CvDTreeSplit **splitsPtr = &splits[0], ** bestSplitsPtr = &bestSplits[0];\r
-    int* canSplitPtr = &canSplit[0];\r
-    for (int i = 0; i < maxNumThreads; i++)\r
-    {\r
-        splits[i] = data->new_split_cat( 0, -1.0f );\r
-        bestSplits[i] = data->new_split_cat( 0, -1.0f );\r
-        canSplitPtr[i] = 0;\r
-    }\r
+    CvForestTree* ftree = (CvForestTree*)tree;\r
+    const CvMat* active_var_mask = ftree->forest->get_active_var_mask();\r
 \r
-#ifdef _OPENMP\r
-#pragma omp parallel for num_threads(maxNumThreads) schedule(dynamic)\r
-#endif\r
-    for( vi = 0; vi < data->var_count; vi++ )\r
+    for( vi = vi1; vi < vi2; vi++ )\r
     {\r
-        CvDTreeSplit *res, *t;\r
-        int threadIdx = 0;\r
-#ifdef _OPENMP\r
-                       threadIdx = omp_get_thread_num();\r
-#endif\r
+        CvDTreeSplit *res;\r
         int ci = data->var_type->data.i[vi];\r
         if( node->num_valid[vi] <= 1\r
             || (active_var_mask && !active_var_mask->data.ptr[vi]) )\r
@@ -146,48 +113,56 @@ CvDTreeSplit* CvForestTree::find_best_split( CvDTreeNode* node )
         if( data->is_classifier )\r
         {\r
             if( ci >= 0 )\r
-                res = find_split_cat_class( node, vi, bestSplitsPtr[threadIdx]->quality, splitsPtr[threadIdx] );\r
+                res = ftree->find_split_cat_class( node, vi, bestSplit->quality, split, (uchar*)inn_buf );\r
             else\r
-                res = find_split_ord_class( node, vi, bestSplitsPtr[threadIdx]->quality, splitsPtr[threadIdx] );\r
+                res = ftree->find_split_ord_class( node, vi, bestSplit->quality, split, (uchar*)inn_buf );\r
         }\r
         else\r
         {\r
             if( ci >= 0 )\r
-                res = find_split_cat_reg( node, vi, bestSplitsPtr[threadIdx]->quality, splitsPtr[threadIdx] );\r
+                res = ftree->find_split_cat_reg( node, vi, bestSplit->quality, split, (uchar*)inn_buf );\r
             else\r
-                res = find_split_ord_reg( node, vi, bestSplitsPtr[threadIdx]->quality, splitsPtr[threadIdx] );\r
+                res = ftree->find_split_ord_reg( node, vi, bestSplit->quality, split, (uchar*)inn_buf );\r
         }\r
 \r
-        if( res )\r
-        {\r
-            canSplitPtr[threadIdx] = 1;\r
-            if( bestSplits[threadIdx]->quality < splits[threadIdx]->quality )\r
-                CV_SWAP( bestSplits[threadIdx], splits[threadIdx], t );\r
-        }\r
+        if( res && bestSplit->quality < split->quality )\r
+                memcpy( (CvDTreeSplit*)bestSplit, (CvDTreeSplit*)split, splitSize );\r
     }\r
-    int ti = 0;\r
-    for( ; ti < maxNumThreads; ti++ )\r
+}\r
+}\r
+\r
+CvDTreeSplit* CvForestTree::find_best_split( CvDTreeNode* node )\r
+{\r
+    CvMat* active_var_mask = 0;\r
+    if( forest )\r
     {\r
-        if( canSplitPtr[ti] )\r
+        int var_count;\r
+        CvRNG* rng = forest->get_rng();\r
+\r
+        active_var_mask = forest->get_active_var_mask();\r
+        var_count = active_var_mask->cols;\r
+\r
+        CV_Assert( var_count == data->var_count );\r
+\r
+        for( int vi = 0; vi < var_count; vi++ )\r
         {\r
-            best_split = bestSplitsPtr[ti];\r
-            break;\r
+            uchar temp;\r
+            int i1 = cvRandInt(rng) % var_count;\r
+            int i2 = cvRandInt(rng) % var_count;\r
+            CV_SWAP( active_var_mask->data.ptr[i1],\r
+                active_var_mask->data.ptr[i2], temp );\r
         }\r
     }\r
-    for( ; ti < maxNumThreads; ti++ )\r
-    {\r
-        if( best_split->quality < bestSplitsPtr[ti]->quality )\r
-            best_split = bestSplitsPtr[ti];\r
-    }\r
-    for(int i = 0; i < maxNumThreads; i++)\r
-    {\r
-        cvSetRemoveByPtr( data->split_heap, splits[i] );\r
-        if( bestSplits[i] != best_split )\r
-            cvSetRemoveByPtr( data->split_heap, bestSplits[i] );\r
-    }\r
-    return best_split;\r
-}\r
 \r
+    cv::ForestTreeBestSplitFinder finder( this, node );\r
+\r
+    cv::parallel_reduce(cv::BlockedRange(0, data->var_count), finder);\r
+\r
+    CvDTreeSplit *bestSplit = data->new_split_cat( 0, -1.0f );\r
+    memcpy( bestSplit, finder.bestSplit, finder.splitSize );\r
+\r
+    return bestSplit;\r
+}\r
 \r
 void CvForestTree::read( CvFileStorage* fs, CvFileNode* fnode, CvRTrees* _forest, CvDTreeTrainData* _data )\r
 {\r
index c19e33df9eb920995532b7f857ac1ba13c43ebc3..47d61a334ff7947849495060b49190640d9d95af 100644 (file)
 #include "_ml.h"
 #include <ctype.h>
 
-#ifdef _OPENMP
-#include "omp.h"
-#endif
-
 using namespace cv;
 
 static const float ord_nan = FLT_MAX*0.5f;
@@ -640,28 +636,6 @@ void CvDTreeTrainData::set_data( const CvMat* _train_data, int _tflag,
     CV_CALL( direction = cvCreateMat( 1, sample_count, CV_8UC1 ));
     CV_CALL( split_buf = cvCreateMat( 1, sample_count, CV_32SC1 ));
 
-    {
-        int maxNumThreads = 1;
-#ifdef _OPENMP
-        maxNumThreads = omp_get_num_procs();
-#endif
-        pred_float_buf.resize(maxNumThreads);
-        pred_int_buf.resize(maxNumThreads);
-        resp_float_buf.resize(maxNumThreads);
-        resp_int_buf.resize(maxNumThreads);
-        cv_lables_buf.resize(maxNumThreads);
-        sample_idx_buf.resize(maxNumThreads);
-        for( int ti = 0; ti < maxNumThreads; ti++ )
-        {
-            pred_float_buf[ti].resize(sample_count);
-            pred_int_buf[ti].resize(sample_count);
-            resp_float_buf[ti].resize(sample_count);
-            resp_int_buf[ti].resize(sample_count);
-            cv_lables_buf[ti].resize(sample_count);
-            sample_idx_buf[ti].resize(sample_count);
-        }
-    }
-
     __END__;
 
     if( data )
@@ -746,17 +720,15 @@ CvDTreeNode* CvDTreeTrainData::subsample_data( const CvMat* _subsample_idx )
                 co[i*2+1] = -1;
         }
 
+        cv::AutoBuffer<uchar> inn_buf(sample_count*(2*sizeof(int) + sizeof(float)));
         for( vi = 0; vi < work_var_count; vi++ )
         {
             int ci = get_var_type(vi);
 
             if( ci >= 0 || vi >= var_count )
             {
-                int* src_buf = get_pred_int_buf();
-                const int* src = 0;
                 int num_valid = 0;
-                
-                get_cat_var_data( data_root, vi, src_buf, &src );
+                const int* src = get_cat_var_data( data_root, vi, (int*)(uchar*)inn_buf );
 
                 if (is_buf_16u)
                 {
@@ -786,14 +758,15 @@ CvDTreeNode* CvDTreeTrainData::subsample_data( const CvMat* _subsample_idx )
             }
             else
             {
-                int *src_idx_buf = get_pred_int_buf();
+                int *src_idx_buf = (int*)(uchar*)inn_buf;
+                float *src_val_buf = (float*)(src_idx_buf + sample_count);
+                int* sample_indices_buf = (int*)(src_val_buf + sample_count);
                 const int* src_idx = 0;
-                float *src_val_buf = get_pred_float_buf();
                 const float* src_val = 0;
+                get_ord_var_data( data_root, vi, src_val_buf, src_idx_buf, &src_val, &src_idx, sample_indices_buf );
                 int j = 0, idx, count_i;
                 int num_valid = data_root->get_num_valid(vi);
 
-                get_ord_var_data( data_root, vi, src_val_buf, src_idx_buf, &src_val, &src_idx );
                 if (is_buf_16u)
                 {
                     unsigned short* udst_idx = (unsigned short*)(buf->data.s + root->buf_idx*buf->cols + 
@@ -845,9 +818,7 @@ CvDTreeNode* CvDTreeTrainData::subsample_data( const CvMat* _subsample_idx )
             }
         }
         // sample indices subsampling
-        int* sample_idx_src_buf = get_sample_idx_buf();
-        const int* sample_idx_src = 0;
-        get_sample_indices(data_root, sample_idx_src_buf, &sample_idx_src);
+        const int* sample_idx_src = get_sample_indices(data_root, (int*)(uchar*)inn_buf);
         if (is_buf_16u)
         {
             unsigned short* sample_idx_dst = (unsigned short*)(buf->data.s + root->buf_idx*buf->cols + 
@@ -888,6 +859,7 @@ void CvDTreeTrainData::get_vectors( const CvMat* _subsample_idx,
     int* sidx = 0;
     int* co = 0;
 
+    cv::AutoBuffer<uchar> inn_buf(sample_count*(2*sizeof(int) + sizeof(float)));
     if( _subsample_idx )
     {
         CV_CALL( subsample_idx = cvPreprocessIndexArray( _subsample_idx, sample_count ));
@@ -919,9 +891,7 @@ void CvDTreeTrainData::get_vectors( const CvMat* _subsample_idx,
         {
             float* dst = values + vi;
             uchar* m = missing ? missing + vi : 0;
-            int* src_buf = get_pred_int_buf();
-            const int* src = 0; 
-            get_cat_var_data(data_root, vi, src_buf, &src);
+            const int* src = get_cat_var_data(data_root, vi, (int*)(uchar*)inn_buf);
 
             for( i = 0; i < count; i++, dst += var_count )
             {
@@ -940,11 +910,12 @@ void CvDTreeTrainData::get_vectors( const CvMat* _subsample_idx,
             float* dst = values + vi;
             uchar* m = missing ? missing + vi : 0;
             int count1 = data_root->get_num_valid(vi);
-            float *src_val_buf = get_pred_float_buf();
+            float *src_val_buf = (float*)(uchar*)inn_buf;
+            int* src_idx_buf = (int*)(src_val_buf + sample_count);
+            int* sample_indices_buf = src_idx_buf + sample_count;
             const float *src_val = 0;
-            int* src_idx_buf = get_pred_int_buf();
             const int* src_idx = 0;
-            get_ord_var_data(data_root, vi, src_val_buf, src_idx_buf, &src_val, &src_idx);
+            get_ord_var_data(data_root, vi, src_val_buf, src_idx_buf, &src_val, &src_idx, sample_indices_buf);
 
             for( i = 0; i < count1; i++ )
             {
@@ -976,9 +947,7 @@ void CvDTreeTrainData::get_vectors( const CvMat* _subsample_idx,
     {
         if( is_classifier )
         {
-            int* src_buf = get_resp_int_buf();
-            const int* src = 0;
-            get_class_labels(data_root, src_buf, &src);
+            const int* src = get_class_labels(data_root, (int*)(uchar*)inn_buf);
             for( i = 0; i < count; i++ )
             {
                 int idx = sidx ? sidx[i] : i;
@@ -989,9 +958,9 @@ void CvDTreeTrainData::get_vectors( const CvMat* _subsample_idx,
         }
         else
         {
-            float *_values_buf = get_resp_float_buf();
-            const float* _values = 0;
-            get_ord_responses(data_root, _values_buf, &_values);
+            float* val_buf = (float*)(uchar*)inn_buf;
+            int* sample_idx_buf = (int*)(val_buf + sample_count);
+            const float* _values = get_ord_responses(data_root, val_buf, sample_idx_buf);
             for( i = 0; i < count; i++ )
             {
                 int idx = sidx ? sidx[i] : i;
@@ -1117,13 +1086,6 @@ void CvDTreeTrainData::free_train_data()
     cvReleaseMat( &split_buf );
     cvReleaseMemStorage( &temp_storage );
     cvReleaseMat( &responses_copy );
-    pred_float_buf.clear();
-    pred_int_buf.clear();
-    resp_float_buf.clear();
-    resp_int_buf.clear();
-    cv_lables_buf.clear();
-    sample_idx_buf.clear();
-
     cv_heap = nv_heap = 0;
 }
 
@@ -1167,73 +1129,67 @@ int CvDTreeTrainData::get_var_type(int vi) const
     return var_type->data.i[vi];
 }
 
-int CvDTreeTrainData::get_ord_var_data( CvDTreeNode* n, int vi, float* ord_values_buf, int* indices_buf, const float** ord_values, const int** indices )
+void CvDTreeTrainData::get_ord_var_data( CvDTreeNode* n, int vi, float* ord_values_buf, int* sorted_indices_buf,
+                                         const float** ord_values, const int** sorted_indices, int* sample_indices_buf )
 {
     int vidx = var_idx ? var_idx->data.i[vi] : vi;
     int node_sample_count = n->sample_count; 
-    int* sample_indices_buf = get_sample_idx_buf();
-    const int* sample_indices = 0;
     int td_step = train_data->step/CV_ELEM_SIZE(train_data->type);
 
-    get_sample_indices(n, sample_indices_buf, &sample_indices);
+    const int* sample_indices = get_sample_indices(n, sample_indices_buf);
 
     if( !is_buf_16u )
-        *indices = buf->data.i + n->buf_idx*buf->cols + 
+        *sorted_indices = buf->data.i + n->buf_idx*buf->cols +
         vi*sample_count + n->offset;
     else {
         const unsigned short* short_indices = (const unsigned short*)(buf->data.s + n->buf_idx*buf->cols + 
             vi*sample_count + n->offset );
         for( int i = 0; i < node_sample_count; i++ )
-            indices_buf[i] = short_indices[i];
-        *indices = indices_buf;
+            sorted_indices_buf[i] = short_indices[i];
+        *sorted_indices = sorted_indices_buf;
     }
     
     if( tflag == CV_ROW_SAMPLE )
     {
         for( int i = 0; i < node_sample_count && 
-            ((((*indices)[i] >= 0) && !is_buf_16u) || (((*indices)[i] != 65535) && is_buf_16u)); i++ )
+            ((((*sorted_indices)[i] >= 0) && !is_buf_16u) || (((*sorted_indices)[i] != 65535) && is_buf_16u)); i++ )
         {
-            int idx = (*indices)[i];
+            int idx = (*sorted_indices)[i];
             idx = sample_indices[idx];
             ord_values_buf[i] = *(train_data->data.fl + idx * td_step + vidx);
         }
     }
     else
         for( int i = 0; i < node_sample_count && 
-            ((((*indices)[i] >= 0) && !is_buf_16u) || (((*indices)[i] != 65535) && is_buf_16u)); i++ )
+            ((((*sorted_indices)[i] >= 0) && !is_buf_16u) || (((*sorted_indices)[i] != 65535) && is_buf_16u)); i++ )
         {
-            int idx = (*indices)[i];
+            int idx = (*sorted_indices)[i];
             idx = sample_indices[idx];
             ord_values_buf[i] = *(train_data->data.fl + vidx* td_step + idx);
         }
     
     *ord_values = ord_values_buf;
-    return 0; //TODO: return the number of non-missing values
 }
 
 
-void CvDTreeTrainData::get_class_labels( CvDTreeNode* n, int* labels_buf, const int** labels )
+const int* CvDTreeTrainData::get_class_labels( CvDTreeNode* n, int* labels_buf )
 {
     if (is_classifier)
-        get_cat_var_data( n, var_count, labels_buf, labels );
+        return get_cat_var_data( n, var_count, labels_buf);
+    return 0;
 }
 
-void CvDTreeTrainData::get_sample_indices( CvDTreeNode* n, int* indices_buf, const int** indices )
+const int* CvDTreeTrainData::get_sample_indices( CvDTreeNode* n, int* indices_buf )
 {
-    get_cat_var_data( n, get_work_var_count(), indices_buf, indices );
+    return get_cat_var_data( n, get_work_var_count(), indices_buf );
 }
 
-void CvDTreeTrainData::get_ord_responses( CvDTreeNode* n, float* values_buf, const float** values)
+const float* CvDTreeTrainData::get_ord_responses( CvDTreeNode* n, float* values_buf, int*sample_indices_buf )
 {
     int sample_count = n->sample_count;
-    int* indices_buf = get_sample_idx_buf();
-    const int* indices = 0;
-
     int r_step = CV_IS_MAT_CONT(responses->type) ? 1 : responses->step/CV_ELEM_SIZE(responses->type);
+    const int* indices = get_sample_indices(n, sample_indices_buf);
 
-    get_sample_indices(n, indices_buf, &indices);
-
-    
     for( int i = 0; i < sample_count && 
         (((indices[i] >= 0) && !is_buf_16u) || ((indices[i] != 65535) && is_buf_16u)); i++ )
     {
@@ -1241,31 +1197,32 @@ void CvDTreeTrainData::get_ord_responses( CvDTreeNode* n, float* values_buf, con
         values_buf[i] = *(responses->data.fl + idx * r_step);
     }
     
-    *values = values_buf;    
+    return values_buf;
 }
 
 
-void CvDTreeTrainData::get_cv_labels( CvDTreeNode* n, int* labels_buf, const int** labels )
+const int* CvDTreeTrainData::get_cv_labels( CvDTreeNode* n, int* labels_buf )
 {
     if (have_labels)
-        get_cat_var_data( n, get_work_var_count()- 1, labels_buf, labels );
+        return get_cat_var_data( n, get_work_var_count()- 1, labels_buf);
+    return 0;
 }
 
 
-int CvDTreeTrainData::get_cat_var_data( CvDTreeNode* n, int vi, int* cat_values_buf, const int** cat_values )
+const int* CvDTreeTrainData::get_cat_var_data( CvDTreeNode* n, int vi, int* cat_values_buf)
 {
+    const int* cat_values = 0;
     if( !is_buf_16u )
-        *cat_values = buf->data.i + n->buf_idx*buf->cols + 
-        vi*sample_count + n->offset;
+        cat_values = buf->data.i + n->buf_idx*buf->cols +
+            vi*sample_count + n->offset;
     else {
         const unsigned short* short_values = (const unsigned short*)(buf->data.s + n->buf_idx*buf->cols + 
             vi*sample_count + n->offset);
         for( int i = 0; i < n->sample_count; i++ )
             cat_values_buf[i] = short_values[i];
-        *cat_values = cat_values_buf;
+        cat_values = cat_values_buf;
     }
-
-    return 0; //TODO: return the number of non-missing values
+    return cat_values;
 }
 
 
@@ -1489,55 +1446,6 @@ void CvDTreeTrainData::read_params( CvFileStorage* fs, CvFileNode* node )
     __END__;
 }
 
-float* CvDTreeTrainData::get_pred_float_buf()
-{
-       int i = 0;
-#ifdef _OPENMP
-       i = omp_get_thread_num();
-#endif
-    return &pred_float_buf[i][0];
-}
-int* CvDTreeTrainData::get_pred_int_buf()
-{
-       int i = 0;
-#ifdef _OPENMP
-       i = omp_get_thread_num();
-#endif
-       return &pred_int_buf[i][0];
-}
-float* CvDTreeTrainData::get_resp_float_buf()
-{
-       int i = 0;
-#ifdef _OPENMP
-       i = omp_get_thread_num();
-#endif
-       return &resp_float_buf[i][0];
-}
-int* CvDTreeTrainData::get_resp_int_buf()
-{
-       int i = 0;      
-#ifdef _OPENMP
-       i = omp_get_thread_num();
-#endif
-       return &resp_int_buf[i][0];
-}
-int* CvDTreeTrainData::get_cv_lables_buf()
-{
-       int i = 0;
-#ifdef _OPENMP
-       i = omp_get_thread_num();
-#endif
-       return &cv_lables_buf[i][0];
-}
-int* CvDTreeTrainData::get_sample_idx_buf()
-{
-       int i = 0;
-#ifdef _OPENMP
-       i = omp_get_thread_num();
-#endif
-       return &sample_idx_buf[i][0];
-}
-
 /////////////////////// Decision Tree /////////////////////////
 
 CvDTree::CvDTree()
@@ -1793,10 +1701,10 @@ double CvDTree::calc_node_dir( CvDTreeNode* node )
 
     if( data->get_var_type(vi) >= 0 ) // split on categorical var
     {
-        int* labels_buf = data->get_pred_int_buf();
-        const int* labels = 0;
+        cv::AutoBuffer<int> inn_buf(n*(data->have_priors ? 1 : 2));
+        int* labels_buf = (int*)inn_buf;
+        const int* labels = data->get_cat_var_data( node, vi, labels_buf );
         const int* subset = node->split->subset;
-        data->get_cat_var_data( node, vi, labels_buf, &labels );
         if( !data->have_priors )
         {
             int sum = 0, sum_abs = 0;
@@ -1817,9 +1725,8 @@ double CvDTree::calc_node_dir( CvDTreeNode* node )
         {
             const double* priors = data->priors_mult->data.db;
             double sum = 0, sum_abs = 0;
-            int *responses_buf = data->get_resp_int_buf();
-            const int* responses;
-            data->get_class_labels(node, responses_buf, &responses);
+            int* responses_buf = labels_buf + n;
+            const int* responses = data->get_class_labels(node, responses_buf);
 
             for( i = 0; i < n; i++ )
             {
@@ -1838,12 +1745,13 @@ double CvDTree::calc_node_dir( CvDTreeNode* node )
     {
         int split_point = node->split->ord.split_point;
         int n1 = node->get_num_valid(vi);
-        
-        float* val_buf = data->get_pred_float_buf();
+        cv::AutoBuffer<uchar> inn_buf(n*(sizeof(int)*(data->have_priors ? 3 : 2) + sizeof(float)));
+        float* val_buf = (float*)(uchar*)inn_buf;
+        int* sorted_buf = (int*)(val_buf + n);
+        int* sample_idx_buf = sorted_buf + n;
         const float* val = 0;
-        int* sorted_buf = data->get_pred_int_buf();
         const int* sorted = 0;
-        data->get_ord_var_data( node, vi, val_buf, sorted_buf, &val, &sorted);
+        data->get_ord_var_data( node, vi, val_buf, sorted_buf, &val, &sorted, sample_idx_buf);
         
         assert( 0 <= split_point && split_point < n1-1 );
 
@@ -1862,9 +1770,8 @@ double CvDTree::calc_node_dir( CvDTreeNode* node )
         else
         {
             const double* priors = data->priors_mult->data.db;
-            int* responses_buf = data->get_resp_int_buf();
-            const int* responses = 0;
-            data->get_class_labels(node, responses_buf, &responses);
+            int* responses_buf = sample_idx_buf + n;
+            const int* responses = data->get_class_labels(node, responses_buf);
             L = R = 0;
 
             for( i = 0; i <= split_point; i++ )
@@ -1891,36 +1798,47 @@ double CvDTree::calc_node_dir( CvDTreeNode* node )
     return node->split->quality/(L + R);
 }
 
-CvDTreeSplit* CvDTree::find_best_split( CvDTreeNode* node )
+
+namespace cv
 {
-    int vi;
-    CvDTreeSplit *bestSplit = 0;
-    int maxNumThreads = 1;
-#ifdef _OPENMP
-    maxNumThreads = omp_get_num_procs();
-#endif
-    vector<CvDTreeSplit*> splits(maxNumThreads);
-    vector<CvDTreeSplit*> bestSplits(maxNumThreads);
-    vector<int> canSplit(maxNumThreads);
-    CvDTreeSplit **splitsPtr = &splits[0], ** bestSplitsPtr = &bestSplits[0];
-    int* canSplitPtr = &canSplit[0];
-    for (int i = 0; i < maxNumThreads; i++)
-    {
-        splitsPtr[i] = data->new_split_cat( 0, -1.0f );
-        bestSplitsPtr[i] = data->new_split_cat( 0, -1.0f );
-        canSplitPtr[i] = 0;
-    }
 
-#ifdef _OPENMP
-#pragma omp parallel for num_threads(maxNumThreads) schedule(dynamic)
-#endif
-    for( vi = 0; vi < data->var_count; vi++ )
+DTreeBestSplitFinder::DTreeBestSplitFinder( CvDTree* _tree, CvDTreeNode* _node)
+{
+    tree = _tree;
+    node = _node;
+    splitSize = tree->get_data()->split_heap->elem_size;
+
+    bestSplit = (CvDTreeSplit*)(new char[splitSize]);
+    memset((CvDTreeSplit*)bestSplit, 0, splitSize);
+    bestSplit->quality = -1;
+    bestSplit->condensed_idx = INT_MIN;
+    split = (CvDTreeSplit*)(new char[splitSize]);
+    memset((CvDTreeSplit*)split, 0, splitSize);
+    //haveSplit = false;
+}
+
+DTreeBestSplitFinder::DTreeBestSplitFinder( const DTreeBestSplitFinder& finder, Split )
+{
+    tree = finder.tree;
+    node = finder.node;
+    splitSize = tree->get_data()->split_heap->elem_size;
+
+    bestSplit = (CvDTreeSplit*)(new char[splitSize]);
+    memcpy((CvDTreeSplit*)(bestSplit), (const CvDTreeSplit*)finder.bestSplit, splitSize);
+    split = (CvDTreeSplit*)(new char[splitSize]);
+    memset((CvDTreeSplit*)split, 0, splitSize);
+}
+
+void DTreeBestSplitFinder::operator()(const BlockedRange& range)
+{
+    int vi, vi1 = range.begin(), vi2 = range.end();
+    int n = node->sample_count;
+    CvDTreeTrainData* data = tree->get_data();
+    AutoBuffer<uchar> inn_buf(2*n*(sizeof(int) + sizeof(float)));
+
+    for( vi = vi1; vi < vi2; vi++ )
     {
-        CvDTreeSplit *res, *t;
-        int threadIdx = 0;
-#ifdef _OPENMP
-               threadIdx = omp_get_thread_num();
-#endif
+        CvDTreeSplit *res;
         int ci = data->get_var_type(vi);
         if( node->get_num_valid(vi) <= 1 )
             continue;
@@ -1928,68 +1846,70 @@ CvDTreeSplit* CvDTree::find_best_split( CvDTreeNode* node )
         if( data->is_classifier )
         {
             if( ci >= 0 )
-                res = find_split_cat_class( node, vi, bestSplitsPtr[threadIdx]->quality, splitsPtr[threadIdx] );
+                res = tree->find_split_cat_class( node, vi, bestSplit->quality, split, (uchar*)inn_buf );
             else
-                res = find_split_ord_class( node, vi, bestSplitsPtr[threadIdx]->quality, splitsPtr[threadIdx] );
+                res = tree->find_split_ord_class( node, vi, bestSplit->quality, split, (uchar*)inn_buf );
         }
         else
         {
             if( ci >= 0 )
-                res = find_split_cat_reg( node, vi, bestSplitsPtr[threadIdx]->quality, splitsPtr[threadIdx] );
+                res = tree->find_split_cat_reg( node, vi, bestSplit->quality, split, (uchar*)inn_buf );
             else
-                res = find_split_ord_reg( node, vi, bestSplitsPtr[threadIdx]->quality, splitsPtr[threadIdx] );
+                res = tree->find_split_ord_reg( node, vi, bestSplit->quality, split, (uchar*)inn_buf );
         }
 
-        if( res )
-        {
-            canSplitPtr[threadIdx] = 1;
-            if( bestSplitsPtr[threadIdx]->quality < splitsPtr[threadIdx]->quality )
-                CV_SWAP( bestSplitsPtr[threadIdx], splitsPtr[threadIdx], t );
-        }
-    }
-    int ti = 0;
-    for( ; ti < maxNumThreads; ti++ )
-    {
-        if( canSplitPtr[ti] )
-        {
-            bestSplit = bestSplitsPtr[ti];
-            break;
-        }
-    }
-    for( ; ti < maxNumThreads; ti++ )
-    {
-        if( bestSplit->quality < bestSplitsPtr[ti]->quality )
-            bestSplit = bestSplitsPtr[ti];
-    }
-    for(int i = 0; i < maxNumThreads; i++)
-    {
-        cvSetRemoveByPtr( data->split_heap, splitsPtr[i] );
-        if( bestSplitsPtr[i] != bestSplit )
-            cvSetRemoveByPtr( data->split_heap, bestSplitsPtr[i] );
+        if( res && bestSplit->quality < split->quality )
+                memcpy( (CvDTreeSplit*)bestSplit, (CvDTreeSplit*)split, splitSize );
     }
+}
+
+void DTreeBestSplitFinder::join( DTreeBestSplitFinder& rhs )
+{
+    if( bestSplit->quality < rhs.bestSplit->quality )
+        memcpy( (CvDTreeSplit*)bestSplit, (CvDTreeSplit*)rhs.bestSplit, splitSize );
+}
+}
+
+
+CvDTreeSplit* CvDTree::find_best_split( CvDTreeNode* node )
+{
+    DTreeBestSplitFinder finder( this, node );
+
+    cv::parallel_reduce(cv::BlockedRange(0, data->var_count), finder);
+
+    CvDTreeSplit *bestSplit = data->new_split_cat( 0, -1.0f );
+    memcpy( bestSplit, finder.bestSplit, finder.splitSize );
+
     return bestSplit;
 }
 
 CvDTreeSplit* CvDTree::find_split_ord_class( CvDTreeNode* node, int vi,
-                                            float init_quality, CvDTreeSplit* _split )
+                                             float init_quality, CvDTreeSplit* _split, uchar* _ext_buf )
 {
     const float epsilon = FLT_EPSILON*2;
     int n = node->sample_count;
     int n1 = node->get_num_valid(vi);
     int m = data->get_num_classes();
 
-    float* values_buf = data->get_pred_float_buf();
+    int base_size = 2*m*sizeof(int);
+    cv::AutoBuffer<uchar> inn_buf(base_size);
+    if( !_ext_buf )
+      inn_buf.allocate(base_size + n*(3*sizeof(int)+sizeof(float)));
+    uchar* base_buf = (uchar*)inn_buf;
+    uchar* ext_buf = _ext_buf ? _ext_buf : base_buf + base_size;
+    float* values_buf = (float*)ext_buf;
+    int* sorted_indices_buf = (int*)(values_buf + n);
+    int* sample_indices_buf = sorted_indices_buf + n;
     const float* values = 0;
-    int* indices_buf = data->get_pred_int_buf();
-    const int* indices = 0;
-    data->get_ord_var_data( node, vi, values_buf, indices_buf, &values, &indices );
-    int* responses_buf =  data->get_resp_int_buf();
-    const int* responses = 0;
-    data->get_class_labels( node, responses_buf, &responses );
+    const int* sorted_indices = 0;
+    data->get_ord_var_data( node, vi, values_buf, sorted_indices_buf, &values,
+                            &sorted_indices, sample_indices_buf );
+    int* responses_buf =  sample_indices_buf + n;
+    const int* responses = data->get_class_labels( node, responses_buf );
 
     const int* rc0 = data->counts->data.i;
-    int* lc = (int*)cvStackAlloc(m*sizeof(lc[0]));
-    int* rc = (int*)cvStackAlloc(m*sizeof(rc[0]));
+    int* lc = (int*)base_buf;
+    int* rc = lc + m;
     int i, best_i = -1;
     double lsum2 = 0, rsum2 = 0, best_val = init_quality;
     const double* priors = data->have_priors ? data->priors_mult->data.db : 0;
@@ -2004,7 +1924,7 @@ CvDTreeSplit* CvDTree::find_split_ord_class( CvDTreeNode* node, int vi,
     // compensate for missing values
     for( i = n1; i < n; i++ )
     {
-        rc[responses[indices[i]]]--;
+        rc[responses[sorted_indices[i]]]--;
     }
 
     if( !priors )
@@ -2016,7 +1936,7 @@ CvDTreeSplit* CvDTree::find_split_ord_class( CvDTreeNode* node, int vi,
 
         for( i = 0; i < n1 - 1; i++ )
         {
-            int idx = responses[indices[i]];
+            int idx = responses[sorted_indices[i]];
             int lv, rv;
             L++; R--;
             lv = lc[idx]; rv = rc[idx];
@@ -2047,7 +1967,7 @@ CvDTreeSplit* CvDTree::find_split_ord_class( CvDTreeNode* node, int vi,
 
         for( i = 0; i < n1 - 1; i++ )
         {
-            int idx = responses[indices[i]];
+            int idx = responses[sorted_indices[i]];
             int lv, rv;
             double p = priors[idx], p2 = p*p;
             L += p; R -= p;
@@ -2178,24 +2098,35 @@ void CvDTree::cluster_categories( const int* vectors, int n, int m,
 }
 
 
-CvDTreeSplit* CvDTree::find_split_cat_class( CvDTreeNode* node, int vi, float init_quality, CvDTreeSplit* _split )
+CvDTreeSplit* CvDTree::find_split_cat_class( CvDTreeNode* node, int vi, float init_quality,
+                                             CvDTreeSplit* _split, uchar* _ext_buf )
 {
     int ci = data->get_var_type(vi);
     int n = node->sample_count;
     int m = data->get_num_classes();
     int _mi = data->cat_count->data.i[ci], mi = _mi;
 
-    int* labels_buf = data->get_pred_int_buf();
-    const int* labels = 0;
-    data->get_cat_var_data(node, vi, labels_buf, &labels);
-    int *responses_buf = data->get_resp_int_buf();
-    const int* responses = 0;
-    data->get_class_labels(node, responses_buf, &responses);
-
-    int* lc = (int*)cvStackAlloc(m*sizeof(lc[0]));
-    int* rc = (int*)cvStackAlloc(m*sizeof(rc[0]));
-    int* _cjk = (int*)cvStackAlloc(m*(mi+1)*sizeof(_cjk[0]))+m, *cjk = _cjk;
-    double* c_weights = (double*)cvStackAlloc( mi*sizeof(c_weights[0]) );
+    int base_size = m*(3 + mi)*sizeof(int) + (mi+1)*sizeof(double);
+    if( m > 2 && mi > data->params.max_categories )
+        base_size += (m*min(data->params.max_categories, n) + mi)*sizeof(int);
+    else
+        base_size += mi*sizeof(int*);
+    cv::AutoBuffer<uchar> inn_buf(base_size);
+    if( !_ext_buf )
+        inn_buf.allocate(base_size + 2*n*sizeof(int));
+    uchar* base_buf = (uchar*)inn_buf;
+    uchar* ext_buf = _ext_buf ? _ext_buf : base_buf + base_size;
+
+    int* lc = (int*)base_buf;
+    int* rc = lc + m;
+    int* _cjk = rc + m*2, *cjk = _cjk;
+    double* c_weights = (double*)alignPtr(cjk + m*mi, sizeof(double));
+
+    int* labels_buf = (int*)ext_buf;
+    const int* labels = data->get_cat_var_data(node, vi, labels_buf);
+    int* responses_buf = labels_buf + n;
+    const int* responses = data->get_class_labels(node, responses_buf);
+
     int* cluster_labels = 0;
     int** int_ptr = 0;
     int i, j, k, idx;
@@ -2222,8 +2153,8 @@ CvDTreeSplit* CvDTree::find_split_cat_class( CvDTreeNode* node, int vi, float in
         if( mi > data->params.max_categories )
         {
             mi = MIN(data->params.max_categories, n);
-            cjk = (int*)cvStackAlloc( m*mi*sizeof(cjk[0]) );
-            cluster_labels = (int*)cvStackAlloc( _mi*sizeof(cluster_labels[0]) );
+            cjk = (int*)(c_weights + _mi);
+            cluster_labels = cjk + m*mi;
             cluster_categories( _cjk, _mi, m, cjk, mi, cluster_labels );
         }
         subset_i = 1;
@@ -2232,7 +2163,7 @@ CvDTreeSplit* CvDTree::find_split_cat_class( CvDTreeNode* node, int vi, float in
     else
     {
         assert( m == 2 );
-        int_ptr = (int**)cvStackAlloc( mi*sizeof(int_ptr[0]) );
+        int_ptr = (int**)(c_weights + _mi);
         for( j = 0; j < mi; j++ )
             int_ptr[j] = cjk + j*2 + 1;
         icvSortIntPtr( int_ptr, mi, 0 );
@@ -2356,20 +2287,24 @@ CvDTreeSplit* CvDTree::find_split_cat_class( CvDTreeNode* node, int vi, float in
 }
 
 
-CvDTreeSplit* CvDTree::find_split_ord_reg( CvDTreeNode* node, int vi, float init_quality, CvDTreeSplit* _split )
+CvDTreeSplit* CvDTree::find_split_ord_reg( CvDTreeNode* node, int vi, float init_quality, CvDTreeSplit* _split, uchar* _ext_buf )
 {
     const float epsilon = FLT_EPSILON*2;
     int n = node->sample_count;
     int n1 = node->get_num_valid(vi);
 
-    float* values_buf = data->get_pred_float_buf();
+    cv::AutoBuffer<uchar> inn_buf;
+    if( !_ext_buf )
+        inn_buf.allocate(2*n*(sizeof(int) + sizeof(float)));
+    uchar* ext_buf = _ext_buf ? _ext_buf : (uchar*)inn_buf;
+    float* values_buf = (float*)ext_buf;
+    int* sorted_indices_buf = (int*)(values_buf + n);
+    int* sample_indices_buf = sorted_indices_buf + n;
     const float* values = 0;
-    int* indices_buf = data->get_pred_int_buf();
-    const int* indices = 0;
-    data->get_ord_var_data( node, vi, values_buf, indices_buf, &values, &indices );
-    float* responses_buf =  data->get_resp_float_buf();
-    const float* responses = 0;
-    data->get_ord_responses( node, responses_buf, &responses );
+    const int* sorted_indices = 0;
+    data->get_ord_var_data( node, vi, values_buf, sorted_indices_buf, &values, &sorted_indices, sample_indices_buf );
+    float* responses_buf =  (float*)(sample_indices_buf + n);
+    const float* responses = data->get_ord_responses( node, responses_buf, sample_indices_buf );
 
     int i, best_i = -1;
     double best_val = init_quality, lsum = 0, rsum = node->value*n;
@@ -2377,12 +2312,12 @@ CvDTreeSplit* CvDTree::find_split_ord_reg( CvDTreeNode* node, int vi, float init
 
     // compensate for missing values
     for( i = n1; i < n; i++ )
-        rsum -= responses[indices[i]];
+        rsum -= responses[sorted_indices[i]];
 
     // find the optimal split
     for( i = 0; i < n1 - 1; i++ )
     {
-        float t = responses[indices[i]];
+        float t = responses[sorted_indices[i]];
         L++; R--;
         lsum += t;
         rsum -= t;
@@ -2411,21 +2346,27 @@ CvDTreeSplit* CvDTree::find_split_ord_reg( CvDTreeNode* node, int vi, float init
     return split;
 }
 
-CvDTreeSplit* CvDTree::find_split_cat_reg( CvDTreeNode* node, int vi, float init_quality, CvDTreeSplit* _split )
+CvDTreeSplit* CvDTree::find_split_cat_reg( CvDTreeNode* node, int vi, float init_quality, CvDTreeSplit* _split, uchar* _ext_buf )
 {
     int ci = data->get_var_type(vi);
     int n = node->sample_count;
     int mi = data->cat_count->data.i[ci];
-    int* labels_buf = data->get_pred_int_buf();
-    const int* labels = 0;
-    float* responses_buf = data->get_resp_float_buf();
-    const float* responses = 0;
-    data->get_cat_var_data(node, vi, labels_buf, &labels);
-    data->get_ord_responses(node, responses_buf, &responses);
-
-    double* sum = (double*)cvStackAlloc( (mi+1)*sizeof(sum[0]) ) + 1;
-    int* counts = (int*)cvStackAlloc( (mi+1)*sizeof(counts[0]) ) + 1;
-    double** sum_ptr = (double**)cvStackAlloc( (mi+1)*sizeof(sum_ptr[0]) );
+
+    int base_size = (mi+2)*sizeof(double) + (mi+1)*(sizeof(int) + sizeof(double*));
+    cv::AutoBuffer<uchar> inn_buf(base_size);
+    if( !_ext_buf )
+        inn_buf.allocate(base_size + n*(2*sizeof(int) + sizeof(float)));
+    uchar* base_buf = (uchar*)inn_buf;
+    uchar* ext_buf = _ext_buf ? _ext_buf : base_buf + base_size;
+    int* labels_buf = (int*)ext_buf;
+    const int* labels = data->get_cat_var_data(node, vi, labels_buf);
+    float* responses_buf = (float*)(labels_buf + n);
+    int* sample_indices_buf = (int*)(responses_buf + n);
+    const float* responses = data->get_ord_responses(node, responses_buf, sample_indices_buf);
+
+    double* sum = (double*)cv::alignPtr(base_buf,sizeof(double)) + 1;
+    int* counts = (int*)(sum + mi) + 1;
+    double** sum_ptr = (double**)(counts + mi);
     int i, L = 0, R = 0;
     double best_val = init_quality, lsum = 0, rsum = 0;
     int best_subset = -1, subset_i;
@@ -2498,16 +2439,21 @@ CvDTreeSplit* CvDTree::find_split_cat_reg( CvDTreeNode* node, int vi, float init
     return split;
 }
 
-CvDTreeSplit* CvDTree::find_surrogate_split_ord( CvDTreeNode* node, int vi )
+CvDTreeSplit* CvDTree::find_surrogate_split_ord( CvDTreeNode* node, int vi, uchar* _ext_buf )
 {
     const float epsilon = FLT_EPSILON*2;
     const char* dir = (char*)data->direction->data.ptr;
-    int n1 = node->get_num_valid(vi);
-    float* values_buf = data->get_pred_float_buf();
+    int n = node->sample_count, n1 = node->get_num_valid(vi);
+    cv::AutoBuffer<uchar> inn_buf;
+    if( !_ext_buf )
+        inn_buf.allocate( n*(sizeof(int)*(data->have_priors ? 3 : 2) + sizeof(float)) );
+    uchar* ext_buf = _ext_buf ? _ext_buf : (uchar*)inn_buf;
+    float* values_buf = (float*)ext_buf;
+    int* sorted_indices_buf = (int*)(values_buf + n);
+    int* sample_indices_buf = sorted_indices_buf + n;
     const float* values = 0;
-    int* indices_buf = data->get_pred_int_buf();
-    const int* indices = 0;
-    data->get_ord_var_data( node, vi, values_buf, indices_buf, &values, &indices );
+    const int* sorted_indices = 0;
+    data->get_ord_var_data( node, vi, values_buf, sorted_indices_buf, &values, &sorted_indices, sample_indices_buf );
     // LL - number of samples that both the primary and the surrogate splits send to the left
     // LR - ... primary split sends to the left and the surrogate split sends to the right
     // RL - ... primary split sends to the right and the surrogate split sends to the left
@@ -2523,7 +2469,7 @@ CvDTreeSplit* CvDTree::find_surrogate_split_ord( CvDTreeNode* node, int vi )
 
         for( i = 0; i < n1; i++ )
         {
-            int d = dir[indices[i]];
+            int d = dir[sorted_indices[i]];
             sum += d; sum_abs += d & 1;
         }
 
@@ -2536,7 +2482,7 @@ CvDTreeSplit* CvDTree::find_surrogate_split_ord( CvDTreeNode* node, int vi )
         // now iteratively compute LL, LR, RL and RR for every possible surrogate split value.
         for( i = 0; i < n1 - 1; i++ )
         {
-            int d = dir[indices[i]];
+            int d = dir[sorted_indices[i]];
 
             if( d < 0 )
             {
@@ -2565,14 +2511,13 @@ CvDTreeSplit* CvDTree::find_surrogate_split_ord( CvDTreeNode* node, int vi )
         double worst_val = node->maxlr;
         double sum = 0, sum_abs = 0;
         const double* priors = data->priors_mult->data.db;
-        int* responses_buf = data->get_resp_int_buf();
-        const int* responses = 0;
-        data->get_class_labels(node, responses_buf, &responses);
+        int* responses_buf = sample_indices_buf + n;
+        const int* responses = data->get_class_labels(node, responses_buf);
         best_val = worst_val;
 
         for( i = 0; i < n1; i++ )
         {
-            int idx = indices[i];
+            int idx = sorted_indices[i];
             double w = priors[responses[idx]];
             int d = dir[idx];
             sum += d*w; sum_abs += (d & 1)*w;
@@ -2587,7 +2532,7 @@ CvDTreeSplit* CvDTree::find_surrogate_split_ord( CvDTreeNode* node, int vi )
         // now iteratively compute LL, LR, RL and RR for every possible surrogate split value.
         for( i = 0; i < n1 - 1; i++ )
         {
-            int idx = indices[i];
+            int idx = sorted_indices[i];
             double w = priors[responses[idx]];
             int d = dir[idx];
 
@@ -2616,21 +2561,28 @@ CvDTreeSplit* CvDTree::find_surrogate_split_ord( CvDTreeNode* node, int vi )
 }
 
 
-CvDTreeSplit* CvDTree::find_surrogate_split_cat( CvDTreeNode* node, int vi )
+CvDTreeSplit* CvDTree::find_surrogate_split_cat( CvDTreeNode* node, int vi, uchar* _ext_buf )
 {
     const char* dir = (char*)data->direction->data.ptr;
     int n = node->sample_count;
-    int* labels_buf = data->get_pred_int_buf();
-    const int* labels = 0;
-    data->get_cat_var_data(node, vi, labels_buf, &labels);
+    int i, mi = data->cat_count->data.i[data->get_var_type(vi)], l_win = 0;
+
+    int base_size = (2*(mi+1)+1)*sizeof(double) + (!data->have_priors ? 2*(mi+1)*sizeof(int) : 0);
+    cv::AutoBuffer<uchar> inn_buf(base_size);
+    if( !_ext_buf )
+        inn_buf.allocate(base_size + n*(sizeof(int) + (data->have_priors ? sizeof(int) : 0)));
+    uchar* base_buf = (uchar*)inn_buf;
+    uchar* ext_buf = _ext_buf ? _ext_buf : base_buf + base_size;
+
+    int* labels_buf = (int*)ext_buf;
+    const int* labels = data->get_cat_var_data(node, vi, labels_buf);
     // LL - number of samples that both the primary and the surrogate splits send to the left
     // LR - ... primary split sends to the left and the surrogate split sends to the right
     // RL - ... primary split sends to the right and the surrogate split sends to the left
     // RR - ... both send to the right
     CvDTreeSplit* split = data->new_split_cat( vi, 0 );
-    int i, mi = data->cat_count->data.i[data->get_var_type(vi)], l_win = 0;
     double best_val = 0;
-    double* lc = (double*)cvStackAlloc( (mi+1)*2*sizeof(lc[0]) ) + 1;
+    double* lc = (double*)cv::alignPtr(base_buf,sizeof(double)) + 1;
     double* rc = lc + mi + 1;
 
     for( i = -1; i < mi; i++ )
@@ -2640,7 +2592,7 @@ CvDTreeSplit* CvDTree::find_surrogate_split_cat( CvDTreeNode* node, int vi )
     // sent to the left (lc) and to the right (rc) by the primary split
     if( !data->have_priors )
     {
-        int* _lc = (int*)cvStackAlloc((mi+2)*2*sizeof(_lc[0])) + 1;
+        int* _lc = (int*)rc + 1;
         int* _rc = _lc + mi + 1;
 
         for( i = -1; i < mi; i++ )
@@ -2666,9 +2618,8 @@ CvDTreeSplit* CvDTree::find_surrogate_split_cat( CvDTreeNode* node, int vi )
     else
     {
         const double* priors = data->priors_mult->data.db;
-        int* responses_buf = data->get_resp_int_buf();
-        const int* responses = 0;
-        data->get_class_labels(node, responses_buf, &responses);
+        int* responses_buf = labels_buf + n;
+        const int* responses = data->get_class_labels(node, responses_buf);
 
         for( i = 0; i < n; i++ )
         {
@@ -2715,9 +2666,16 @@ CvDTreeSplit* CvDTree::find_surrogate_split_cat( CvDTreeNode* node, int vi )
 void CvDTree::calc_node_value( CvDTreeNode* node )
 {
     int i, j, k, n = node->sample_count, cv_n = data->params.cv_folds;
-    int* cv_labels_buf = data->get_cv_lables_buf();
-    const int* cv_labels = 0;
-    data->get_cv_labels(node, cv_labels_buf, &cv_labels);
+    int m = data->get_num_classes();
+
+    int base_size = data->is_classifier ? m*cv_n*sizeof(int) : 2*cv_n*sizeof(double)+cv_n*sizeof(int);
+    int ext_size = n*(sizeof(int) + (data->is_classifier ? sizeof(int) : sizeof(int)+sizeof(float)));
+    cv::AutoBuffer<uchar> inn_buf(base_size + ext_size);
+    uchar* base_buf = (uchar*)inn_buf;
+    uchar* ext_buf = base_buf + base_size;
+
+    int* cv_labels_buf = (int*)ext_buf;
+    const int* cv_labels = data->get_cv_labels(node, cv_labels_buf);
 
     if( data->is_classifier )
     {
@@ -2731,11 +2689,9 @@ void CvDTree::calc_node_value( CvDTreeNode* node )
 
         // compute the number of instances of each class
         int* cls_count = data->counts->data.i;
-        int* responses_buf = data->get_resp_int_buf();
-        const int* responses = 0;
-        data->get_class_labels(node, responses_buf, &responses);
-        int m = data->get_num_classes();
-        int* cv_cls_count = (int*)cvStackAlloc(m*cv_n*sizeof(cv_cls_count[0]));
+        int* responses_buf = cv_labels_buf + n;
+        const int* responses = data->get_class_labels(node, responses_buf);
+        int* cv_cls_count = (int*)base_buf;
         double max_val = -1, total_weight = 0;
         int max_k = -1;
         double* priors = data->priors_mult->data.db;
@@ -2837,9 +2793,9 @@ void CvDTree::calc_node_value( CvDTreeNode* node )
         //    over the samples with cv_labels(*)==j.
 
         double sum = 0, sum2 = 0;
-        float* values_buf = data->get_resp_float_buf();
-        const float* values = 0;
-        data->get_ord_responses(node, values_buf, &values);
+        float* values_buf = (float*)(cv_labels_buf + n);
+        int* sample_indices_buf = (int*)(values_buf + n);
+        const float* values = data->get_ord_responses(node, values_buf, sample_indices_buf);
         double *cv_sum = 0, *cv_sum2 = 0;
         int* cv_count = 0;
 
@@ -2854,9 +2810,9 @@ void CvDTree::calc_node_value( CvDTreeNode* node )
         }
         else
         {
-            cv_sum = (double*)cvStackAlloc( cv_n*sizeof(cv_sum[0]) );
-            cv_sum2 = (double*)cvStackAlloc( cv_n*sizeof(cv_sum2[0]) );
-            cv_count = (int*)cvStackAlloc( cv_n*sizeof(cv_count[0]) );
+            cv_sum = (double*)base_buf;
+            cv_sum2 = cv_sum + cv_n;
+            cv_count = (int*)(cv_sum2 + cv_n);
 
             for( j = 0; j < cv_n; j++ )
             {
@@ -2909,6 +2865,7 @@ void CvDTree::complete_node_dir( CvDTreeNode* node )
     // try to complete direction using surrogate splits
     if( nz && data->params.use_surrogates )
     {
+        cv::AutoBuffer<uchar> inn_buf(n*(2*sizeof(int)+sizeof(float)));
         CvDTreeSplit* split = node->split->next;
         for( ; split != 0 && nz; split = split->next )
         {
@@ -2917,9 +2874,8 @@ void CvDTree::complete_node_dir( CvDTreeNode* node )
 
             if( data->get_var_type(vi) >= 0 ) // split on categorical var
             {
-                int* labels_buf = data->get_pred_int_buf();
-                const int* labels = 0;
-                data->get_cat_var_data(node, vi, labels_buf, &labels);
+                int* labels_buf = (int*)(uchar*)inn_buf;
+                const int* labels = data->get_cat_var_data(node, vi, labels_buf);
                 const int* subset = split->subset;
 
                 for( i = 0; i < n; i++ )
@@ -2937,11 +2893,12 @@ void CvDTree::complete_node_dir( CvDTreeNode* node )
             }
             else // split on ordered var
             {
-                float* values_buf = data->get_pred_float_buf();
+                float* values_buf = (float*)(uchar*)inn_buf;
+                int* sorted_indices_buf = (int*)(values_buf + n);
+                int* sample_indices_buf = sorted_indices_buf + n;
                 const float* values = 0;
-                int* indices_buf = data->get_pred_int_buf();
-                const int* indices = 0;
-                data->get_ord_var_data( node, vi, values_buf, indices_buf, &values, &indices );
+                const int* sorted_indices = 0;
+                data->get_ord_var_data( node, vi, values_buf, sorted_indices_buf, &values, &sorted_indices, sample_indices_buf );
                 int split_point = split->ord.split_point;
                 int n1 = node->get_num_valid(vi);
 
@@ -2949,7 +2906,7 @@ void CvDTree::complete_node_dir( CvDTreeNode* node )
 
                 for( i = 0; i < n1; i++ )
                 {
-                    int idx = indices[i];
+                    int idx = sorted_indices[i];
                     if( !dir[idx] )
                     {
                         int d = i <= split_point ? -1 : 1;
@@ -2996,8 +2953,8 @@ void CvDTree::split_node_data( CvDTreeNode* node )
     int new_buf_idx = data->get_child_buf_idx( node );
     int work_var_count = data->get_work_var_count();
     CvMat* buf = data->buf;
-    cv::AutoBuffer<int, 1<<14> _temp_buf(n);
-    int* temp_buf = _temp_buf;
+    cv::AutoBuffer<uchar> inn_buf(n*(3*sizeof(int) + sizeof(float)));
+    int* temp_buf = (int*)(uchar*)inn_buf;
 
     complete_node_dir(node);
 
@@ -3010,7 +2967,6 @@ void CvDTree::split_node_data( CvDTreeNode* node )
         nl += d^1;
     }
 
-
     bool split_input_data;
     node->left = left = data->new_node( node, nl, new_buf_idx, node->offset );
     node->right = right = data->new_node( node, nr, new_buf_idx, node->offset + nl );
@@ -3023,19 +2979,20 @@ void CvDTree::split_node_data( CvDTreeNode* node )
     for( vi = 0; vi < data->var_count; vi++ )
     {
         int ci = data->get_var_type(vi);
-        int n1 = node->get_num_valid(vi);
-        int *src_idx_buf = data->get_pred_int_buf();
-        const int* src_idx = 0;
-        float *src_val_buf = data->get_pred_float_buf();
-        const float* src_val = 0;
-        
+
         if( ci >= 0 || !split_input_data )
             continue;
 
-        data->get_ord_var_data(node, vi, src_val_buf, src_idx_buf, &src_val, &src_idx);
+        int n1 = node->get_num_valid(vi);
+        float* src_val_buf = (float*)(uchar*)(temp_buf + n);
+        int* src_sorted_idx_buf = (int*)(src_val_buf + n);
+        int* src_sample_idx_buf = src_sorted_idx_buf + n;
+        const float* src_val = 0;
+        const int* src_sorted_idx = 0;
+        data->get_ord_var_data(node, vi, src_val_buf, src_sorted_idx_buf, &src_val, &src_sorted_idx, src_sample_idx_buf);
 
         for(i = 0; i < n; i++)
-            temp_buf[i] = src_idx[i];
+            temp_buf[i] = src_sorted_idx[i];
 
         if (data->is_buf_16u)
         {
@@ -3142,9 +3099,8 @@ void CvDTree::split_node_data( CvDTreeNode* node )
         if( ci < 0 || (vi < data->var_count && !split_input_data) )
             continue;
 
-        int *src_lbls_buf = data->get_pred_int_buf();
-        const int* src_lbls = 0;
-        data->get_cat_var_data(node, vi, src_lbls_buf, &src_lbls);
+        int *src_lbls_buf = temp_buf + n;
+        const int* src_lbls = data->get_cat_var_data(node, vi, src_lbls_buf);
 
         for(i = 0; i < n; i++)
             temp_buf[i] = src_lbls[i];
@@ -3214,9 +3170,8 @@ void CvDTree::split_node_data( CvDTreeNode* node )
 
 
     // split sample indices
-    int *sample_idx_src_buf = data->get_sample_idx_buf();
-    const int* sample_idx_src = 0;
-    data->get_sample_indices(node, sample_idx_src_buf, &sample_idx_src);
+    int *sample_idx_src_buf = temp_buf + n;
+    const int* sample_idx_src = data->get_sample_indices(node, sample_idx_src_buf);
 
     for(i = 0; i < n; i++)
         temp_buf[i] = sample_idx_src[i];