dust3d/thirdparty/cgal/CGAL-5.1/include/CGAL/monotone_matrix_search.h

207 lines
5.8 KiB
C++

// Copyright (c) 1998-2003 ETH Zurich (Switzerland).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL: https://github.com/CGAL/cgal/blob/v5.1/Matrix_search/include/CGAL/monotone_matrix_search.h $
// $Id: monotone_matrix_search.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Hoffmann <hoffmann@inf.ethz.ch>
#ifndef CGAL_MONOTONE_MATRIX_SEARCH_H
#define CGAL_MONOTONE_MATRIX_SEARCH_H 1
#include <CGAL/license/Matrix_search.h>
#include <CGAL/Optimisation/assertions.h>
#include <vector>
#include <functional>
namespace CGAL {
template < class Matrix, class RandomAccessIterator >
inline
void
monotone_matrix_search(
const Matrix& M,
RandomAccessIterator t)
{
typedef typename Matrix::Value V;
monotone_matrix_search( M, t, std::less< V >());
} // monotone_matrix_search( M, t)
template < class Matrix,
class RandomAccessIterator,
class Compare_strictly >
void
monotone_matrix_search(
const Matrix& M,
RandomAccessIterator t,
const Compare_strictly& compare_strictly)
// Matrix has to define:
// o operator()( int, int) [access]
// o int number_of_columns(), int number_of_rows()
// o replace_column( int o, int n)
// o shrink_to_quadratic_size()
// o Matrix* extract_all_even_rows()
//
// Precondition: M is totally monotone
// M.number_of_rows() > 1 and
// RandomAccessIterator has value type int
//
// writes to t the positions (columns)
// of the row maxima of M
{
// divide
// ------
// get even rows of M:
Matrix* M_new = M.extract_all_even_rows();
CGAL_optimisation_assertion(
M_new->number_of_columns() == M.number_of_columns());
CGAL_optimisation_assertion(
M_new->number_of_rows() == 0 ||
M_new->number_of_rows() == ( M.number_of_rows() + 1) >> 1);
// reduce M_new to a quadratic matrix:
// table to store the reduction permutation:
// (incl. sentinel)
int* reduction_table = new int[ M_new->number_of_rows() + 1];
if ( M_new->number_of_rows() < M_new->number_of_columns()) {
// set sentinel:
reduction_table[M_new->number_of_rows()] =
M.number_of_columns() - 1;
_reduce_matrix( *M_new, reduction_table, compare_strictly);
CGAL_optimisation_assertion(
M_new->number_of_columns() == M_new->number_of_rows());
} // if ( M_new->number_of_rows() < M_new->number_of_columns())
else {
// no reduction -> reduction_table is identity table:
for ( int i1( 0); i1 < M_new->number_of_columns(); ++i1)
reduction_table[i1] = i1;
// set sentinel:
reduction_table[M_new->number_of_columns()] =
M_new->number_of_columns() - 1;
}
// recursion:
CGAL_optimisation_assertion(
M_new->number_of_rows() >= M_new->number_of_columns());
// table to store the rmax values of M_new:
// (incl. sentinel)
int* t_new = new int[M_new->number_of_rows() + 1];
t_new[M_new->number_of_rows()] = M_new->number_of_columns();
if ( M_new->number_of_rows() == 1)
// recursion anchor:
// we have just one element ==> no choice
t_new[0] = 0;
else
monotone_matrix_search( *M_new, t_new);
// and conquer
// -----------
int j( 0); // actual index in t
int j_new( 0); // actual index in t_new
do {
// even row ==> we know
*(t+j) = reduction_table[t_new[j_new++]];
if ( ++j >= M.number_of_rows())
break;
// odd row
// search *(t+j) between *(t+j-1) and t_new[j_new]:
*(t+j) = reduction_table[t_new[j_new]];
int j_tmp( *(t+j-1));
while ( j_tmp < reduction_table[t_new[j_new]]) {
if ( compare_strictly( M( j, t[j]), M( j, j_tmp)))
*(t+j) = j_tmp++;
else
++j_tmp;
}
} while ( ++j < M.number_of_rows());
delete M_new;
delete[] t_new;
delete[] reduction_table;
} // monotone_matrix_search( M, t)
template < class Matrix,
class RandomAccessIterator,
class Compare_strictly >
void
_reduce_matrix(
Matrix& M,
RandomAccessIterator t,
const Compare_strictly& compare_strictly)
// Matrix has to define:
// o operator()( int, int) [access]
// o int number_of_columns(), int number_of_rows()
// o replace_column( int o, int n)
// o shrink_to_quadratic_size()
// o Matrix* extract_all_even_rows()
//
// Precondition: M is totally monotone
// reduces M, i.e. deletes some columns that
// do not contain the maximum value of any row
// such that M becomes quadratic
// and returns for each column of the resulting
// matrix its column index in the original matrix
{
CGAL_optimisation_precondition(
M.number_of_columns() >= M.number_of_rows());
// active columns are 0, ..., j1, j2, ..., M.x_dim()-1
int j1( 0), j2( 1);
*t = 0;
while ( j2 - j1 < M.number_of_columns() - M.number_of_rows() + 1) {
if ( compare_strictly( M( j1, j1), M( j1, j2))) {
// delete column j1
if ( j1 > 0)
--j1;
else {
M.replace_column( 0, j2);
*t = j2++;
}
}
else {
if ( j1 < M.number_of_rows() - 1) {
// proceed
M.replace_column( ++j1, j2);
*(t+j1) = j2;
}
// else delete column j2
++j2;
}
} // while ( j2 - j1 <
// M.number_of_columns() - M.number_of_rows() + 1)
// M.number_of_columns() - M.number_of_rows() columns
// have been deleted, now move columns
// j2 .. M.number_of_columns()-1 to the first part
while ( j1 < M.number_of_rows() - 1) {
CGAL_optimisation_assertion( j2 < M.number_of_columns());
M.replace_column( ++j1, j2);
*(t+j1) = j2++;
}
M.shrink_to_quadratic_size();
} // _reduce_matrix( M, t)
} //namespace CGAL
#endif // ! (CGAL_MONOTONE_MATRIX_SEARCH_H)
// ----------------------------------------------------------------------------
// ** EOF
// ----------------------------------------------------------------------------