virtual void operator()(utils::kernel_generation_stream & stream, std::size_t device_offset, statements_type const & statements) const {
          std::vector<detail::mapping_type> mapping(statements.size());

          ///Get Prototype, initialize mapping
          std::string prototype;
          std::set<std::string> already_generated;
          kernel_arguments(statements, prototype);

          {
            std::map<void *, std::size_t> memory;
            unsigned int current_arg = 0;
            std::size_t i = 0;
            for(statements_type::const_iterator it = statements.begin() ; it != statements.end() ; ++it)
              detail::traverse(it->first, it->second, detail::map_functor(memory,current_arg,mapping[i++]));
          }

          for(statements_type::const_iterator it = statements.begin() ; it != statements.end() ; ++it){
            detail::traverse(it->first, it->second, detail::prototype_generation_traversal(already_generated, prototype, vectorization(), mapping[std::distance(statements.begin(), it)]));
          }

          prototype.erase(prototype.size()-1); //Last comma pruned

          //Generate
          for(std::size_t n = 0 ; n < num_kernels() ; ++n){
            //stream << "__attribute__((vec_type_hint()))" << std::endl;
            stream << " __attribute__((reqd_work_group_size(" << local_size_1_ << "," << local_size_2_ << "," << 1 << ")))" << std::endl;
            stream << "__kernel " << "void " << "kernel_" << device_offset << "_" << n << "(" << std::endl;
            stream << prototype << std::endl;
            stream << ")" << std::endl;

            //core:
            stream << "{" << std::endl;
            stream.inc_tab();
            core(n, stream, statements, mapping);
            stream.dec_tab();
            stream << "}" << std::endl;
          }
        }
QList<int> Skeleton::possibleNumbers(QList<int> digitsOnField){
    QList<int> list;

    /*if (listHoles.size() > 2 || listJunctions.size() > 5 || listLineEnds.size() > 5){
        // certainly a bad 'catch'
    }
    if (listHoles.size() == 0){
        if (listLineEnds.size() >= 2){
            if (listLineEnds[0].x < 0.3 && listLineEnds[0].y < 0.3 && listLineEnds[1].x > 0.7 && listLineEnds[1].y > 0.7){
                list.push_back(2);
            }
            else if (listLineEnds[0].x > 0.7 && listLineEnds[0].y < 0.3 && listLineEnds[1].y > 0.5){
                list.push_back(5);
            }
            else if (listLineEnds[1].x < 0.4){
                list.push_back(7);
            }
            else {
                list.push_back(1);
            }
        }
        else {
            list.push_back(1);
            list.push_back(2);
            list.push_back(5);
            list.push_back(7);
        }
    }
    else if (listHoles.size() == 1){
        if (listHoles[0].x > 0.35 && listHoles[0].x < 0.65 && listHoles[0].y > 0.35 && listHoles[0].y < 0.65){
            if (listJunctions.size() + listLineEnds.size() < 3){
                list.push_back(0);
            }
            else {
                list.push_back(4);
            }
        }
        else if (listHoles.size() == 1 && listJunctions.size() >= 1 && listLineEnds.size() >= 1){
            if (listHoles[0].y > listLineEnds[0].y){
                list.push_back(6);
            }
            else {
                list.push_back(9);
            }
        }
        else {
            list.push_back(0);
            list.push_back(4);
            list.push_back(6);
            list.push_back(9);
        }
    }
    else if (listHoles.size() == 2){
        list.push_back(8);
    }
    else { // if the 'number' is close to a 'normal' number, but not a perfect match, we try all of them
        for (int i = 0; i < TEMPLATES_COUNT; i++){
            list.push_back(i);
        }
    }*/

    if (HOLE_SEPARATION){
        if (listHoles.size() == 0){
            QList<int> zeroHole;
            zeroHole.push_back(1);
            zeroHole.push_back(2);
            zeroHole.push_back(3);
            zeroHole.push_back(5);
            zeroHole.push_back(7);

            int dim = Skeleton::getDim(M0);

            QList<double> vect = vectorization(M0);

            float sampleData[dim];

            for (int i = 0; i < dim; i++){
                sampleData[i] = vect[i];
            }

            cv::Mat sampleMat(1, dim, CV_32FC1, sampleData);

            int maxVote = 0;
            int intMaxVote = -1;

            for (int i = 0; i < 10; i++){
                int vote = 0;
                for (int j = 0; j < 10; j++){
                    if (i != j && zeroHole.contains(i) && zeroHole.contains(j)){
                        float response = Skeleton::machines.m[min(i,j)][max(i,j)]->predict(sampleMat);

                        if ((response == 0.0 && i == min(i,j)) || (response == 1.0 && i == max(i,j))){
                            vote++;
                        }
                    }
                }

                //qDebug() << i << ": " << vote;

                if (vote > maxVote){
                    maxVote = vote;
                    intMaxVote = i;
                }
            }

            if (intMaxVote == -1){
                qDebug() << "Error : No vote is greater than 0";
            }
            else {
                list.push_back(intMaxVote);
            }
        }
        else if (listHoles.size() == 1){
            QList<int> oneHole;
            oneHole.push_back(0);
            oneHole.push_back(4);
            oneHole.push_back(6);
            oneHole.push_back(9);

            int dim = Skeleton::getDim(M1);

            QList<double> vect = vectorization(M1);

            float sampleData[dim];

            for (int i = 0; i < dim; i++){
                sampleData[i] = vect[i];
            }

            cv::Mat sampleMat(1, dim, CV_32FC1, sampleData);

            int maxVote = 0;
            int intMaxVote = -1;

            for (int i = 0; i < 10; i++){
                int vote = 0;
                for (int j = 0; j < 10; j++){
                    if (i != j && oneHole.contains(i) && oneHole.contains(j)){
                        float response = Skeleton::machines.m[min(i,j)][max(i,j)]->predict(sampleMat);

                        if ((response == 0.0 && i == min(i,j)) || (response == 1.0 && i == max(i,j))){
                            vote++;
                        }
                    }
                }

                //qDebug() << i << ": " << vote;

                if (vote > maxVote){
                    maxVote = vote;
                    intMaxVote = i;
                }
            }

            if (intMaxVote == -1){
                qDebug() << "Error : No vote is greater than 0";
            }
            else {
                list.push_back(intMaxVote);
            }
        }
        else if (listHoles.size() == 2){
            list.push_back(8);
        }
        else { // if the 'number' is close to a 'normal' number, but not a perfect match, we try all of them
            for (int i = 0; i < TEMPLATES_COUNT; i++){
                list.push_back(i);
            }
        }
    }
    else {


        int dim = Skeleton::getDim(M0);
        QList<double> vect = vectorization(M0);

        float sampleData[dim];

        for (int i = 0; i < dim; i++){
            sampleData[i] = vect[i];
        }

        cv::Mat sampleMat(1, dim, CV_32FC1, sampleData);

        int maxVote = 0;
        int intMaxVote = -1;

        for (int i = 0; i < 10; i++){
            int vote = 0;
            for (int j = 0; j < 10; j++){
                if (i != j && digitsOnField.contains(i) && digitsOnField.contains(j)) {
                    float response = Skeleton::machines.m[min(i,j)][max(i,j)]->predict(sampleMat);

                    if ((response == 0.0 && i == min(i,j)) || (response == 1.0 && i == max(i,j))){
                        vote++;
                    }
                }
            }

            //qDebug() << i << ": " << vote;

            if (vote > maxVote){
                maxVote = vote;
                intMaxVote = i;
            }
        }

        if (intMaxVote == -1){
            qDebug() << "Error : No vote is greater than 0";
        }
        else {
            list.push_back(intMaxVote);
        }
    }

    return list;
}