📄 mmat_00.cc
字号:
this->debug(L"this"); return Error::handle(name(), L"setCapacity", Error::ARG, __FILE__, __LINE__); } // capacity < length: error (capacity can't be less than the length) // else if (vecLength(nrows_a , ncols_a, type_a) < vecLength(nrows_d, ncols_d, type_d)) { this->debug(L"this"); return Error::handle(name(), L"setCapacity", Error::ARG, __FILE__, __LINE__); } // condition: type = UNCHANGED // else if (type_a == Integral::UNCHANGED) { return setCapacity(nrows_a, ncols_a, preserve_values_a, type_d); } // condition: preserve_values = false // if we don't need to preserve values, this is really easy. simply // convert the old space into the new space. // else if (!preserve_values_a) { return vecResetCapacity(nrows_a, ncols_a, type_a); } // condition: preserve values = true and the types are the same // else if (type_a == type_d) { // we need to simply resize the underlying data structures // return vecResizeCapacity(nrows_a, ncols_a); } // condition: preserve values = true and the types are different // // this is the hard one. the new matrix is a different type // than the old matrix. we must do this in two steps: (1) change // the type of the existing matrix; (2) change the capacity. // // fortunately, changeType copies the data for us, which makes this // operation much easier. // else { // copy the old data manually // changeType(type_a); // change the capacity // return setCapacity((long)nrows_a, (long)ncols_a, preserve_values_a, type_a); }}// method: setDimensions//// arguments:// const MMatrix& pmat: (input) prototype matrix// boolean preserve_values: (input) should we save the memory// Integral::MTYPE type: (input) type of the new matrix//// return: a boolean value indicating status//// this method sets the dimensions of the matrix to be the same as// that of the input matrix. it preserves the values only when the// boolean flag is true.//template<class TScalar, class TIntegral>boolean MMatrix<TScalar, TIntegral>::setDimensions(const MMatrix& pmat_a, boolean preserve_values_a, Integral::MTYPE type_a) { // call the master function // return setDimensions(pmat_a.getNumRows(), pmat_a.getNumColumns(), preserve_values_a, type_a);}// method: setDimensions//// arguments:// long nrows: (input) new number of rows// long ncols: (input) new number of columns// boolean preserve_values: (input) flag to save existing values// Integral::MTYPE type: (input) type of the new matrix//// return: a boolean value indicating status//// this method sets the dimensions of the matrix. capacity is// adjusted accordingly.//template<class TScalar, class TIntegral>boolean MMatrix<TScalar, TIntegral>::setDimensions(long nrows_a, long ncols_a, boolean preserve_values_a, Integral::MTYPE type_a) { // condition: bad arguments // if ((nrows_a < 0) || (ncols_a < 0) || (!checkSquare(nrows_a, ncols_a, type_a))) { this->debug(L"this"); return Error::handle(name(), L"setDimensions", Error::ARG, __FILE__, __LINE__); } // condition: type = UNCHANGED // else if (type_a == Integral::UNCHANGED) { return setDimensions(nrows_a, ncols_a, preserve_values_a, type_d); } // condition: the types are the same // whether we preserve values or not, we do essentially the same thing. // else if (type_a == type_d) { return vecDimensionLength(nrows_a, ncols_a, preserve_values_a); } // condition: preserve_values = false // if we don't need to preserve values, this is really easy. simply // convert the old space into the new space. because we have to // change the type, we have to do a little more work deleting // old space and creating new space. // else if (!preserve_values_a) { return vecCreateLength(nrows_a, ncols_a, type_a); } // condition: preserve_values = true and the types are different // // this is the hard one. the new matrix is a different type // than the old matrix. we must do this in two steps: (1) change // the type of the existing matrix; (2) change the capacity. // // fortunately, changeType copies the data for us, which makes this // operation much easier. // else { // change the type (which preserves the values) // changeType(type_a); // change the dimensions now that the types are the same // return setDimensions(nrows_a, ncols_a, true, type_d); }}// method: almostEqual//// arguments:// TIntegral value: (input) value to be compared with// double percent: (input) percentage of allowable difference// double bound: (input) a lower bound on the comparison//// return: a boolean value indicating status//// note that this method is now very simple, because it only checks// values actually stored in the matrix (instead of checking all values// including values that are zero by definition). so this simple// function call works for all types of matrices.//template<class TScalar, class TIntegral>boolean MMatrix<TScalar, TIntegral>::almostEqual(TIntegral value_a, double percent_a, double bound_a) const { return m_d.almostEqual(value_a, percent_a, bound_a);}// method: almostEqual//// argument(s):// MMatrix& arg: (input) matrix to be compared// double percent: (input) percentage of allowable difference// double bound: (input) a lower bound on the comparison//// return: a boolean value indicating status//// this methods checks if the current matrix is almost equal to the// input matrix//template<class TScalar, class TIntegral>boolean MMatrix<TScalar, TIntegral>::almostEqual(const MMatrix& arg_a, double percent_a, double bound_a) const { // check the dimensions: the matrices must be the same size // if (!checkDimensions(arg_a)) { return false; } // condition: both are SPARSE // check all components of the matrix // if ((type_d == Integral::SPARSE) && (arg_a.type_d == Integral::SPARSE)) { return (m_d.almostEqual(arg_a.m_d, percent_a, bound_a) && row_index_d.eq(arg_a.row_index_d) && col_index_d.eq(arg_a.col_index_d)); } // condition: both are the same type, and not SPARSE // check data directly // else if ((type_d != Integral::SPARSE) && (type_d == arg_a.type_d)) { return m_d.almostEqual(arg_a.m_d, percent_a, bound_a); } // condition: different types // must compare the matrices element by element // else { long nrows = getNumRows(); long ncols = getNumColumns(); for (long row = 0; row < nrows; row++) { for (long col = 0; col < ncols; col++) { if (!Integral::almostEqual(getValue(row, col), arg_a.getValue(row, col), percent_a, bound_a)) { return false; } } } } // exit gracefully: they must be equal // return true;}// method: checkType//// arguments:// Integral::MTYPE type: (input) the type of the matrix//// return: an MTYPE value that is the same as the input//// unfortunately, C++ lets you define a integer value outside the range// of an enum. therefore, every time an enum is passed as an argument,// we must check its validity. this method errors if the argument// is not an allowable value.// template<class TScalar, class TIntegral>Integral::MTYPEMMatrix<TScalar, TIntegral>::checkType(Integral::MTYPE type_a) const { // UNCHANGED: pass the existing type // if (type_a == Integral::UNCHANGED) { return type_d; } // check against all known valid storage types. // else if ((type_a == Integral::FULL) || (type_a == Integral::DIAGONAL) || (type_a == Integral::SYMMETRIC) || (type_a == Integral::LOWER_TRIANGULAR) || (type_a == Integral::UPPER_TRIANGULAR) || (type_a == Integral::SPARSE)) { return type_a; } // else: error // else { this->debug(L"this"); Error::handle(name(), L"checkType", Error::ARG, __FILE__, __LINE__); return Integral::UNKNOWN; }}// method: checkSquare//// arguments:// long nrows: (input) the number of rows// long ncols: (input) the number of cols// Integral::MTYPE type: (input) the type of the matrix//// return: a boolean value indicating status//// several matrix types require the matrix to be square.// this method performs this check and errors accordingly.//template<class TScalar, class TIntegral>booleanMMatrix<TScalar, TIntegral>::checkSquare(long nrows_a, long ncols_a, Integral::MTYPE type_a) const { // UNCHANGED: pass the existing type // if (type_a == Integral::UNCHANGED) { return checkSquare(nrows_a, ncols_a, type_d); } // check against all known valid storage types that require a // square matrix // else if ((type_a == Integral::SYMMETRIC) || (type_a == Integral::LOWER_TRIANGULAR) || (type_a == Integral::UPPER_TRIANGULAR)) { // check for a square matrix // if (nrows_a == ncols_a) { return true; } else { this->debug(L"this"); return Error::handle(name(), L"checkSquare", Error::ARG, __FILE__, __LINE__); } } // else: other types don't require a square matrix // else { return true; }}// method: changeType//// arguments:// Integral::MTYPE type: (input) new matrix type //// return: a boolean value indicating status//// this method changes the type of a matrix from the// current type (type_d) to the new type (type_a). data is preserved// by copying it to a local vector.// template<class TScalar, class TIntegral>boolean MMatrix<TScalar, TIntegral>::changeType(Integral::MTYPE type_a) { // condition: check the arguments // (1) old and new matrices are the same type; we are done // (2) type_a is UNCHANGED; we are done // if ((type_d == type_a) || (type_a == Integral::UNCHANGED)) { return true; } // condition: check if the conversion is possible // else if (!isTypePossible(type_a)) { String output(L"cannot change this matrix to type "); output.concat(TYPE_MAP(type_a)); Console::put(output); this->debug(L"this"); return Error::handle(name(), L"changeType", MMatrix<TScalar, TIntegral>::ERR_OPTYPE, __FILE__, __LINE__); } // condition: non-SPARSE => non-SPARSE // the technique for copying data from non-SPARSE matrices is to loop over // all elements in the output matrix, and retrieve the corresponding // values from the input. // if ((type_d != Integral::SPARSE) && (type_a != Integral::SPARSE)) { // create a temporary vector for the output values // TVector tmp(vecLength(nrows_d, ncols_d, type_a)); // assign elements - loop over rows // for (long row = 0; row < nrows_d; row++) { // loop over *only* the necessary columns // long first_col = startColumn(row, type_d, type_a); long last_col = stopColumn(row, type_d, type_a); for (long col = first_col; col <= last_col; col++) { tmp(index(row, col, nrows_d, ncols_d, type_a)) = m_d(index(row, col, nrows_d, ncols_d, type_d)); } } // now we can overwrite the input data // m_d.assign(tmp); } // condition: non-SPARSE => SPARSE // the technique for filling SPARSE is to only assign non-zero elements // else if ((type_d != Integral::SPARSE) && (type_a == Integral::SPARSE)) { // find the number of non-zero elements in the matrix // and allocate temporary space // long count = numNotEqual(0); TVector tmp(count); row_index_d.setLength(count); col_index_d.setLength(count); // assign elements // for (long row = 0, index = 0; row < nrows_d; row++) { // loop over *only* the necessary columns: // long first_col = startColumn(row, type_d, Integral::FULL); long last_col = stopColumn(row, type_d, Integral::FULL); for (long col = first_col; col <= last_col; col++) { // get the value at current position and save it if it is non-zero // TIntegral value = getValue(row, col); if (value != (TIntegral)0) { tmp(index) = value; row_index_d(index) = row; col_index_d(index++) = col; } } } // now we can overwrite the input data // m_d.assign(tmp); } // condition: SPARSE => non-SPARSE // the technique for converting SPARSE is fairly easy: only assign // the specified non-zero elements. // else if ((type_d == Integral::SPARSE) && (type_a != Integral::SPARSE)) { // allocate temporary space and make sure it is zero'ed // TVector tmp(vecLength(nrows_d, ncols_d, type_a)); // assign elements // long num_elements = row_index_d.length(); for (long ind = 0; ind < num_elements; ind++) { tmp(index(row_index_d(ind), col_index_d(ind), nrows_d, ncols_d, type_a)) = m_d(ind); } // now we can overwrite the input data // m_d.assign(tmp); row_index_d.clear(Integral::RETAIN); col_index_d.clear(Integral::RETAIN); } // condition: error // we never should hit this point else { this->debug(L"this"); return Error::handle(name(), L"changeType", MMatrix<TScalar, TIntegral>::ERR_UNKTYP, __FILE__, __LINE__); } // finally, set the type equal to the new type // type_d = type_a; // exit ungracefully // return true;}// method: index//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -