int submatrix_determinant(const integer_matrix& matrix, const submatrix_indices& submatrix) { typedef boost::numeric::ublas::matrix_indirect <const integer_matrix, submatrix_indices::indirect_array_type> indirect_matrix_t; assert (submatrix.rows.size() == submatrix.columns.size()); const indirect_matrix_t indirect_matrix(matrix, submatrix.rows, submatrix.columns); boost::numeric::ublas::matrix <float> float_matrix(indirect_matrix); boost::numeric::ublas::permutation_matrix <size_t> permutation_matrix(float_matrix.size1()); /// LU-factorize int result = boost::numeric::ublas::lu_factorize(float_matrix, permutation_matrix); if (result != 0) return 0; /// Calculate the determinant as a product of the diagonal entries, taking the permutation matrix into account. float det = 1.0f; for (size_t i = 0; i < float_matrix.size1(); ++i) { det *= float_matrix(i, i); if (i != permutation_matrix(i)) det = -det; } return (int) det; }
/* Initialize MAX1 maps */ void InitializeMAX1map() { int img, orient, x, y, here, i, trace[2]; /* calculate MAX1 maps and record the shifts */ pooledMax1map = float_matrix(numOrient, sizexSubsample*sizeySubsample); MAX1map = float_matrix(numImage*numOrient, sizexSubsample*sizeySubsample); trackMap = int_matrix(numImage*numOrient, sizexSubsample*sizeySubsample); startx = floor((halfFilterSize+1)/subsample)+1+locationShiftLimit; endx = floor((sizex-halfFilterSize)/subsample)-1-locationShiftLimit; starty = floor((halfFilterSize+1)/subsample)+1+locationShiftLimit; endy = floor((sizey-halfFilterSize)/subsample)-1-locationShiftLimit; for (x=startx; x<=endx; x++) for (y=starty; y<=endy; y++) { here = px(x, y, sizexSubsample, sizeySubsample); for (orient=0; orient<numOrient; orient++) { pooledMax1map[orient][here] = 0.; for (img=0; img<numImage; img++) { i = orient*numImage+img; MAX1map[i][here] = LocalMaximumPooling(img, orient, x*subsample, y*subsample, trace); trackMap[i][here] = trace[0]; pooledMax1map[orient][here] += MAX1map[i][here]; } } } }
/* Initialize MAX1 maps */ void Initialize() { int img, orient, x, y, here, i, trace[2]; pooledMax1map = float_matrix(numOrient, sizexSubsample*sizeySubsample); startx = floor(((double)halfFilterSize+1)/subsample)+1+locationShiftLimit; endx = floor((double)(sizex-halfFilterSize)/subsample)-1-locationShiftLimit; starty = floor((double)(halfFilterSize+1)/subsample)+1+locationShiftLimit; endy = floor((double)(sizey-halfFilterSize)/subsample)-1-locationShiftLimit; for (x=startx; x<=endx; x++) for (y=starty; y<=endy; y++) { here = px(x, y, sizexSubsample, sizeySubsample); for (orient=0; orient<numOrient; orient++) { pooledMax1map[orient][here] = 0.; for (img=0; img<numImage; img++) pooledMax1map[orient][here] += MAX1map[orient*numImage+img][here]; } } }
/* compute sigmoid transformation */ void LocalNormalize() { int x, y, here, orient, leftx, rightx, upy, lowy, k, startx[8], endx[8], starty[8], endy[8], copyx[8], copyy[8], fx, fy; float maxAverage, averageDivide; /* compute the sum over all the orientations at each pixel */ SUM1mapAll = float_matrix(sizex, sizey); for (x=0; x<sizex; x++) for (y=0; y<sizey; y++) { SUM1mapAll[x][y] = 0.; here = px(x+1, y+1, sizex, sizey); for (orient=0; orient<numOrient; orient++) { SUM1mapAll[x][y] += SUM1map[orient][here]; } } /* compute the integral map */ integralMap = float_matrix(sizex, sizey); integralMap[0][0] = SUM1mapAll[0][0]; for (x=1; x<sizex; x++) integralMap[x][0] = integralMap[x-1][0]+SUM1mapAll[x][0]; for (y=1; y<sizey; y++) integralMap[0][y] = integralMap[0][y-1]+SUM1mapAll[0][y]; for (x=1; x<sizex; x++) for (y=1; y<sizey; y++) integralMap[x][y] = integralMap[x][y-1]+integralMap[x-1][y]-integralMap[x-1][y-1]+SUM1mapAll[x][y]; /* compute the local average around each pixel */ averageMap = float_matrix(sizex, sizey); leftx = halfFilterSize+localHalfx; rightx = sizex-halfFilterSize-localHalfx; upy = halfFilterSize+localHalfy; lowy = sizey-halfFilterSize-localHalfy; maxAverage = NEGMAX; if ((leftx<rightx)&&(upy<lowy)) { for (x=leftx; x<rightx; x++) for (y=upy; y<lowy; y++) { averageMap[x][y] = (integralMap[x+localHalfx][y+localHalfy] - integralMap[x-localHalfx-1][y+localHalfy] - integralMap[x+localHalfx][y-localHalfy-1] + integralMap[x-localHalfx-1][y-localHalfy-1])/(2.*localHalfx+1.)/(2.*localHalfy+1.)/numOrient; if (maxAverage < averageMap[x][y]) maxAverage = averageMap[x][y]; } /* take care of the boundaries */ k = 0; /* four corners */ startx[k] = 0; endx[k] = leftx; starty[k] = 0; endy[k] = upy; copyx[k] = leftx; copyy[k] = upy; k++; startx[k] = 0; endx[k] = leftx; starty[k] = lowy; endy[k] = sizey; copyx[k] = leftx; copyy[k] = lowy-1; k++; startx[k] = rightx; endx[k] = sizex; starty[k] = 0; endy[k] = upy; copyx[k] = rightx-1; copyy[k] = upy; k++; startx[k] = rightx; endx[k] = sizex; starty[k] = lowy; endy[k] = sizey; copyx[k] = rightx-1; copyy[k] = lowy-1; k++; /* four sides */ startx[k] = 0; endx[k] = leftx; starty[k] = upy; endy[k] = lowy; copyx[k] = leftx; copyy[k] = -1; k++; startx[k] = rightx; endx[k] = sizex; starty[k] = upy; endy[k] = lowy; copyx[k] = rightx-1; copyy[k] = -1; k++; startx[k] = leftx; endx[k] = rightx; starty[k] = 0; endy[k] = upy; copyx[k] = -1; copyy[k] = upy; k++; startx[k] = leftx; endx[k] = rightx; starty[k] = lowy; endy[k] = sizey; copyx[k] = -1; copyy[k] = lowy-1; k++; /* propagate the average to the boundaries */ for (k=0; k<8; k++) for (x=startx[k]; x<endx[k]; x++) for (y=starty[k]; y<endy[k]; y++) { if (copyx[k]<0) fx = x; else fx = copyx[k]; if (copyy[k]<0) fy = y; else fy = copyy[k]; averageMap[x][y] = averageMap[fx][fy]; } /* normalize the responses by local averages */ for (x=0; x<sizex; x++) for (y=0; y<sizey; y++) { here = px(x+1, y+1, sizex, sizey); averageDivide = MAX(averageMap[x][y], maxAverage*thresholdFactor); for (orient=0; orient<numOrient; orient++) SUM1map[orient][here] /= averageDivide; } } /* free intermediate matrices */ free_matrix(SUM1mapAll, sizex, sizey); free_matrix(integralMap, sizex, sizey); free_matrix(averageMap, sizex, sizey); }
int closest_vector(IntMatrix &b, const IntVect &int_target, IntVect &sol_coord, int method, int flags) { // d = lattice dimension (note that it might decrease during preprocessing) int d = b.get_rows(); // n = dimension of the space int n = b.get_cols(); FPLLL_CHECK(d > 0 && n > 0, "closestVector: empty matrix"); FPLLL_CHECK(d <= n, "closestVector: number of vectors > size of the vectors"); // Sets the floating-point precision // Error bounds on GSO are valid if prec >= minprec double rho; int min_prec = gso_min_prec(rho, d, LLL_DEF_DELTA, LLL_DEF_ETA); int prec = max(53, min_prec + 10); int old_prec = Float::set_prec(prec); // Allocates space for vectors and matrices in constructors IntMatrix empty_mat; MatGSO<Integer, Float> gso(b, empty_mat, empty_mat, GSO_INT_GRAM); FloatVect target_coord; Float max_dist; Integer itmp1; // Computes the Gram-Schmidt orthogonalization in floating-point gso.update_gso(); gen_zero_vect(sol_coord, d); /* Applies Babai's algorithm. Because we use fp, it might be necessary to do it several times (if ||target|| >> ||b_i||) */ FloatMatrix float_matrix(d, n); FloatVect target(n), babai_sol; IntVect int_new_target = int_target; for (int i = 0; i < d; i++) for (int j = 0; j < n; j++) float_matrix(i, j).set_z(b(i, j)); for (int loop_idx = 0;; loop_idx++) { if (loop_idx >= 0x100 && ((loop_idx & (loop_idx - 1)) == 0)) FPLLL_INFO("warning: possible infinite loop in Babai's algorithm"); for (int i = 0; i < n; i++) { target[i].set_z(int_new_target[i]); } babai(float_matrix, gso.get_mu_matrix(), gso.get_r_matrix(), target, babai_sol); int idx; for (idx = 0; idx < d && babai_sol[idx] >= -1 && babai_sol[idx] <= 1; idx++) { } if (idx == d) break; for (int i = 0; i < d; i++) { itmp1.set_f(babai_sol[i]); sol_coord[i].add(sol_coord[i], itmp1); for (int j = 0; j < n; j++) int_new_target[j].submul(itmp1, b(i, j)); } } // FPLLL_TRACE("BabaiSol=" << sol_coord); get_gscoords(float_matrix, gso.get_mu_matrix(), gso.get_r_matrix(), target, target_coord); /* Computes a very large bound to make the algorithm work until the first solution is found */ max_dist = 0.0; for (int i = 1; i < d; i++) { // get_r_exp(i, i) = r(i, i) because gso is initialized without GSO_ROW_EXPO max_dist.add(max_dist, gso.get_r_exp(i, i)); } vector<int> max_indices; if (method & CVPM_PROVED) { // For Exact CVP, we need to reset enum below depth with maximal r_i max_indices = vector<int>(d); int cur, max_index, previous_max_index; previous_max_index = max_index = d-1; Float max_val; while (max_index > 0) { max_val = gso.get_r_exp(max_index, max_index); for (cur = previous_max_index - 1 ; cur >= 0 ; --cur) { if (max_val <= gso.get_r_exp(cur, cur)) { max_val = gso.get_r_exp(cur, cur); max_index = cur; } } for (cur = max_index ; cur < previous_max_index ; ++cur) max_indices[cur] = max_index; max_indices[previous_max_index] = previous_max_index; previous_max_index = max_index; --max_index; } } FPLLL_TRACE("max_indices " << max_indices); FastEvaluator<Float> evaluator(n, gso.get_mu_matrix(), gso.get_r_matrix(), EVALMODE_CV); // Main loop of the enumeration Enumeration<Float> enumobj(gso, evaluator, max_indices); enumobj.enumerate(0, d, max_dist, 0, target_coord); int result = RED_ENUM_FAILURE; if (!evaluator.sol_coord.empty()) { FPLLL_TRACE("evaluator.sol_coord=" << evaluator.sol_coord); if (flags & CVP_VERBOSE) FPLLL_INFO("max_dist=" << max_dist); for (int i = 0; i < d; i++) { itmp1.set_f(evaluator.sol_coord[i]); sol_coord[i].add(sol_coord[i], itmp1); } result = RED_SUCCESS; } Float::set_prec(old_prec); return result; }