inline ErrorCode SweptElementData::add_vsequence(SweptVertexData *vseq, 
                                                 const HomCoord &p1, const HomCoord &q1,
                                                 const HomCoord &p2, const HomCoord &q2, 
                                                 const HomCoord &p3, const HomCoord &q3,
                                                 bool bb_input,
                                                 const HomCoord &bb_min,
                                                 const HomCoord &bb_max)
{
    // compute the transform given the vseq-local parameters and the mapping to
    // this element sequence's parameters passed in minmax
  HomXform M;
  M.three_pt_xform(p1, q1, p2, q2, p3, q3);
  
    // min and max in element seq's parameter system may not be same as those in 
    // vseq's system, so need to take min/max

  HomCoord minmax[2];
  if (bb_input) {
    minmax[0] = bb_min;
    minmax[1] = bb_max;
  }
  else {
    minmax[0] = vseq->min_params() * M;
    minmax[1] = vseq->max_params() * M;
  }
  
    // check against other vseq's to make sure they don't overlap
  for (std::vector<VertexDataRef>::const_iterator vsit = vertexSeqRefs.begin();
       vsit != vertexSeqRefs.end(); vsit++) 
    if ((*vsit).contains(minmax[0]) || (*vsit).contains(minmax[1])) 
      return MB_FAILURE;
    
  HomCoord tmp_min(std::min(minmax[0].i(), minmax[1].i()), 
                   std::min(minmax[0].j(), minmax[1].j()), 
                   std::min(minmax[0].k(), minmax[1].k()));
  HomCoord tmp_max(std::max(minmax[0].i(), minmax[1].i()), 
                   std::max(minmax[0].j(), minmax[1].j()), 
                   std::max(minmax[0].k(), minmax[1].k()));

  
    // set up a new vertex sequence reference
  VertexDataRef tmp_seq_ref(tmp_min, tmp_max, M, vseq);

    // add to the list
  vertexSeqRefs.push_back(tmp_seq_ref);
  
  return MB_SUCCESS;
}
/*
 * Compute new boundary values of new Mondrian block, which
 * depends on the split dimension and split location
 */
std::pair<arma::fvec, arma::fvec> 
MondrianNode::compute_left_right_statistics(
        int& split_dim, float& split_loc, const arma::fvec& sample_x,
        arma::fvec min_cur_block, arma::fvec max_cur_block,
        bool left_split) {
    std::vector<arma::fvec> points;

    if (left_split) {
        if (sample_x[split_dim] <= split_loc) {
            points.push_back(sample_x);
        }         
        if (min_cur_block[split_dim] <= split_loc) {
            points.push_back(min_cur_block);
        }         
        if (max_cur_block[split_dim] <= split_loc) {
            points.push_back(max_cur_block);
        }     
    } else {
        if (sample_x[split_dim] > split_loc) {
            points.push_back(sample_x);
        }         
        if (min_cur_block[split_dim] > split_loc) {
            points.push_back(min_cur_block);
        }         
        if (max_cur_block[split_dim] > split_loc) {
            points.push_back(max_cur_block);
        }     
    }
    /* Calculate min and max boundary values */
    std::vector<arma::fvec>::iterator it = points.begin();
    arma::fvec tmp_min(sample_x.size());
    arma::fvec tmp_max(sample_x.size());
    if (it != points.end()) {
        tmp_min = *it;
        tmp_max = *it;
    }
    for ( ; it < points.end(); it++) {
       tmp_min = arma::min(tmp_min,*it); 
       tmp_max = arma::max(tmp_max,*it); 
    }

    std::pair<arma::fvec, arma::fvec> new_block(tmp_min, tmp_max);
    return new_block; 
}