📄 vnl_matrix.txx
字号:
void vnl_matrix<T>::assert_size_internal(unsigned rs,unsigned cs) const
{
if (this->rows()!=rs || this->cols()!=cs) {
vcl_cerr << __FILE__ ": size is " << this->rows() << 'x' << this->cols()
<< ". should be " << rs << 'x' << cs << vcl_endl;
vcl_abort();
}
}
//: Read a vnl_matrix from an ascii vcl_istream.
// Automatically determines file size if the input matrix has zero size.
template <class T>
bool vnl_matrix<T>::read_ascii(vcl_istream& s)
{
if (!s.good()) {
vcl_cerr << __FILE__ ": vnl_matrix<T>::read_ascii: Called with bad stream\n";
return false;
}
bool size_known = (this->rows() != 0);
if (size_known) {
for (unsigned int i = 0; i < this->rows(); ++i)
for (unsigned int j = 0; j < this->columns(); ++j)
s >> this->data[i][j];
return s.good() || s.eof();
}
bool debug = false;
vcl_vector<T> first_row_vals;
if (debug)
vcl_cerr << __FILE__ ": vnl_matrix<T>::read_ascii: Determining file dimensions: ";
int c;
for (;;) {
// Clear whitespace, looking for a newline
while (1) {
c = s.get();
if (c == EOF)
goto loademup;
if (!vcl_isspace(c)) {
if (!s.putback(c).good())
vcl_cerr << "vnl_matrix<T>::read_ascii: Could not push back '" << c << "'\n";
goto readfloat;
}
// First newline after first number tells us the column dimension
if (c == '\n' && first_row_vals.size() > 0) {
goto loademup;
}
}
readfloat:
T val;
s >> val;
if (!s.fail())
first_row_vals.push_back(val);
if (s.eof())
goto loademup;
}
loademup:
unsigned int colz = first_row_vals.size();
if (debug) vcl_cerr << colz << " cols, ";
if (colz == 0)
return false;
// need to be careful with resizing here as will often be reading humungous files
// So let's just build an array of row pointers
vcl_vector<T*> row_vals;
row_vals.reserve(1000);
{
// Copy first row. Can't use first_row_vals, as may be a vector of bool...
T* row = vnl_c_vector<T>::allocate_T(colz);
for (unsigned int k = 0; k < colz; ++k)
row[k] = first_row_vals[k];
row_vals.push_back(row);
}
while (1) {
T* row = vnl_c_vector<T>::allocate_T(colz);
if (row == 0) {
vcl_cerr << "vnl_matrix<T>::read_ascii: Error, Out of memory on row " << row_vals.size() << vcl_endl;
return false;
}
s >> row[0];
if (!s.good())
break;
for (unsigned int k = 1; k < colz; ++k) {
if (s.eof()) {
vcl_cerr << "vnl_matrix<T>::read_ascii: Error, EOF on row " << row_vals.size() << ", column " << k << vcl_endl;
return false;
}
s >> row[k];
if (s.fail()) {
vcl_cerr << "vnl_matrix<T>::read_ascii: Error, row " << row_vals.size() << " failed on column " << k << vcl_endl;
return false;
}
}
row_vals.push_back(row);
}
unsigned int rowz = row_vals.size();
if (debug)
vcl_cerr << rowz << " rows.\n";
resize(rowz, colz);
T* p = this->data[0];
for (unsigned int i = 0; i < rowz; ++i) {
for (unsigned int j = 0; j < colz; ++j)
*p++ = row_vals[i][j];
if (i > 0) vnl_c_vector<T>::deallocate(row_vals[i], colz);
}
return true;
}
//: Read a vnl_matrix from an ascii vcl_istream.
// Automatically determines file size if the input matrix has zero size.
// This is a static method so you can type
// <verb>
// vnl_matrix<float> M = vnl_matrix<float>::read(cin);
// </verb>
// which many people prefer to the ">>" alternative.
template <class T>
vnl_matrix<T> vnl_matrix<T>::read(vcl_istream& s)
{
vnl_matrix<T> M;
s >> M;
return M;
}
template <class T>
void vnl_matrix<T>::swap(vnl_matrix<T> &that)
{
vcl_swap(this->num_rows, that.num_rows);
vcl_swap(this->num_cols, that.num_cols);
vcl_swap(this->data, that.data);
}
//: Reverse order of rows. Name is from Matlab, meaning "flip upside down".
template <class T>
void vnl_matrix<T>::flipud()
{
unsigned int n = this->rows();
unsigned int colz = this->columns();
unsigned int m = n / 2;
for (unsigned int r = 0; r < m; ++r) {
unsigned int r1 = r;
unsigned int r2 = n - 1 - r;
for (unsigned int c = 0; c < colz; ++c) {
T tmp = (*this)(r1, c);
(*this)(r1, c) = (*this)(r2, c);
(*this)(r2, c) = tmp;
}
}
}
//: Reverse order of columns.
template <class T>
void vnl_matrix<T>::fliplr()
{
unsigned int n = this->cols();
unsigned int rowz = this->rows();
unsigned int m = n / 2;
for (unsigned int c = 0; c < m; ++c) {
unsigned int c1 = c;
unsigned int c2 = n - 1 - c;
for (unsigned int r = 0; r < rowz; ++r) {
T tmp = (*this)(r, c1);
(*this)(r, c1) = (*this)(r, c2);
(*this)(r, c2) = tmp;
}
}
}
// || M || = \max \sum | M |
// 1 j i ij
template <class T>
typename vnl_matrix<T>::abs_t vnl_matrix<T>::operator_one_norm() const
{
//typedef vnl_numeric_traits<T>::abs_t abs_t;
abs_t max(0);
for (unsigned int j=0; j<this->num_cols; ++j) {
abs_t tmp(0);
for (unsigned int i=0; i<this->num_rows; ++i)
tmp += vnl_math_abs(this->data[i][j]);
if (tmp > max)
max = tmp;
}
return max;
}
// || M || = \max \sum | M |
// oo i j ij
template <class T>
typename vnl_matrix<T>::abs_t vnl_matrix<T>::operator_inf_norm() const
{
//typedef vnl_numeric_traits<T>::abs_t abs_t;
abs_t max(0);
for (unsigned int i=0; i<this->num_rows; ++i) {
abs_t tmp(0);
for (unsigned int j=0; j<this->num_cols; ++j)
tmp += vnl_math_abs(this->data[i][j]);
if (tmp > max)
max = tmp;
}
return max;
}
template <class doublereal> // ideally, char* should be bool* - PVr
int vnl_inplace_transpose(doublereal *a, unsigned m, unsigned n, char* move, unsigned iwrk)
{
static doublereal b, c;
int k = m * n - 1;
static int iter, i1, i2, im, i1c, i2c, ncount, max_;
// *****
// ALGORITHM 380 - REVISED
// *****
// A IS A ONE-DIMENSIONAL ARRAY OF LENGTH MN=M*N, WHICH
// CONTAINS THE MXN MATRIX TO BE TRANSPOSED (STORED
// COLUMWISE). MOVE IS A ONE-DIMENSIONAL ARRAY OF LENGTH IWRK
// USED TO STORE INFORMATION TO SPEED UP THE PROCESS. THE
// VALUE IWRK=(M+N)/2 IS RECOMMENDED. IOK INDICATES THE
// SUCCESS OR FAILURE OF THE ROUTINE.
// NORMAL RETURN IOK=0
// ERRORS IOK=-2 ,IWRK NEGATIVE OR ZERO
// IOK.GT.0, (SHOULD NEVER OCCUR),IN THIS CASE
// WE SET IOK EQUAL TO THE FINAL VALUE OF ITER WHEN THE SEARCH
// IS COMPLETED BUT SOME LOOPS HAVE NOT BEEN MOVED
// NOTE * MOVE(I) WILL STAY ZERO FOR FIXED POINTS
if (m < 2 || n < 2)
return 0; // JUST RETURN IF MATRIX IS SINGLE ROW OR COLUMN
if (iwrk < 1)
return -2; // ERROR RETURN
if (m == n) {
// IF MATRIX IS SQUARE, EXCHANGE ELEMENTS A(I,J) AND A(J,I).
for (unsigned i = 0; i < n; ++i)
for (unsigned j = i+1; j < n; ++j) {
i1 = i + j * n;
i2 = j + i * m;
b = a[i1];
a[i1] = a[i2];
a[i2] = b;
}
return 0; // NORMAL RETURN
}
ncount = 2;
for (unsigned i = 0; i < iwrk; ++i)
move[i] = char(0); // false;
if (m > 2 && n > 2) {
// CALCULATE THE NUMBER OF FIXED POINTS, EUCLIDS ALGORITHM FOR GCD(M-1,N-1).
int ir2 = m - 1;
int ir1 = n - 1;
int ir0 = ir2 % ir1;
while (ir0 != 0) {
ir2 = ir1;
ir1 = ir0;
ir0 = ir2 % ir1;
}
ncount += ir1 - 1;
}
// SET INITIAL VALUES FOR SEARCH
iter = 1;
im = m;
// AT LEAST ONE LOOP MUST BE RE-ARRANGED
goto L80;
// SEARCH FOR LOOPS TO REARRANGE
L40:
max_ = k - iter;
++iter;
if (iter > max_)
return iter; // error return
im += m;
if (im > k)
im -= k;
i2 = im;
if (iter == i2)
goto L40;
if (iter <= (int)iwrk) {
if (move[iter-1])
goto L40;
else
goto L80;
}
while (i2 > iter && i2 < max_) {
i1 = i2;
i2 = m * i1 - k * (i1 / n);
}
if (i2 != iter)
goto L40;
// REARRANGE THE ELEMENTS OF A LOOP AND ITS COMPANION LOOP
L80:
i1 = iter;
b = a[i1];
i1c = k - iter;
c = a[i1c];
while (true) {
i2 = m * i1 - k * (i1 / n);
i2c = k - i2;
if (i1 <= (int)iwrk)
move[i1-1] = '1'; // true;
if (i1c <= (int)iwrk)
move[i1c-1] = '1'; // true;
ncount += 2;
if (i2 == iter)
break;
if (i2+iter == k) {
doublereal d = b; b = c; c = d; // interchange b and c
break;
}
a[i1] = a[i2];
a[i1c] = a[i2c];
i1 = i2;
i1c = i2c;
}
// FINAL STORE AND TEST FOR FINISHED
a[i1] = b;
a[i1c] = c;
if (ncount > k)
return 0; // NORMAL RETURN
goto L40;
} /* dtrans_ */
//: Transpose matrix M in place.
// Works for rectangular matrices using an enormously clever algorithm from ACM TOMS.
template <class T>
void vnl_matrix<T>::inplace_transpose()
{
unsigned m = rows();
unsigned n = columns();
unsigned iwrk = (m+n)/2;
vcl_vector<char> move(iwrk);
int iok = ::vnl_inplace_transpose(data_block(), n, m, &move[0], iwrk);
if (iok != 0)
vcl_cerr << __FILE__ " : inplace_transpose() -- iok = " << iok << vcl_endl;
this->num_rows = n;
this->num_cols = m;
// row pointers. we have to reallocate even when n<=m because
// vnl_c_vector<T>::deallocate needs to know n_when_allocatod.
{
T *tmp = data[0];
vnl_c_vector<T>::deallocate(data, m);
data = vnl_c_vector<T>::allocate_Tptr(n);
for (unsigned i=0; i<n; ++i)
data[i] = tmp + i * m;
}
}
//--------------------------------------------------------------------------------
#define VNL_MATRIX_INSTANTIATE(T) \
template class vnl_matrix<T >; \
template vnl_matrix<T > operator-(T const &, vnl_matrix<T > const &); \
VCL_INSTANTIATE_INLINE(vnl_matrix<T > operator+(T const &, vnl_matrix<T > const &)); \
VCL_INSTANTIATE_INLINE(vnl_matrix<T > operator*(T const &, vnl_matrix<T > const &)); \
template T dot_product(vnl_matrix<T > const &, vnl_matrix<T > const &); \
template T inner_product(vnl_matrix<T > const &, vnl_matrix<T > const &); \
template T cos_angle(vnl_matrix<T > const &, vnl_matrix<T > const &); \
template vnl_matrix<T > element_product(vnl_matrix<T > const &, vnl_matrix<T > const &); \
template vnl_matrix<T > element_quotient(vnl_matrix<T > const &, vnl_matrix<T > const &); \
template int vnl_inplace_transpose(T*, unsigned, unsigned, char*, unsigned); \
template vcl_ostream & operator<<(vcl_ostream &, vnl_matrix<T > const &); \
template vcl_istream & operator>>(vcl_istream &, vnl_matrix<T > &); \
VCL_INSTANTIATE_INLINE(bool operator!=(vnl_matrix<T > const &, vnl_matrix<T > const &))
#endif // vnl_matrix_txx_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -