CoinUtils 2.11.4
CoinPackedMatrix.hpp
Go to the documentation of this file.
1/* $Id$ */
2// Copyright (C) 2000, International Business Machines
3// Corporation and others. All Rights Reserved.
4// This code is licensed under the terms of the Eclipse Public License (EPL).
5
6#ifndef CoinPackedMatrix_H
7#define CoinPackedMatrix_H
8
9#include "CoinError.hpp"
10#include "CoinTypes.hpp"
11#ifndef CLP_NO_VECTOR
14#else
15class CoinRelFltEq;
16#endif
17
81
82public:
83 //---------------------------------------------------------------------------
87 inline double getExtraGap() const { return extraGap_; }
89 inline double getExtraMajor() const { return extraMajor_; }
90
93 void reserve(const int newMaxMajorDim, const CoinBigIndex newMaxSize,
94 bool create = false);
96 void clear();
97
99 inline bool isColOrdered() const { return colOrdered_; }
100
102 inline bool hasGaps() const { return (size_ < start_[majorDim_]); }
103
105 inline CoinBigIndex getNumElements() const { return size_; }
106
108 inline int getNumCols() const
109 {
111 }
112
114 inline int getNumRows() const
115 {
117 }
118
126 inline const double *getElements() const { return element_; }
127
136 inline const int *getIndices() const { return index_; }
137
142 inline int getSizeVectorStarts() const
143 {
144 return ((majorDim_ > 0) ? (majorDim_ + 1) : (0));
145 }
146
151 inline int getSizeVectorLengths() const { return majorDim_; }
152
158 inline const CoinBigIndex *getVectorStarts() const { return start_; }
159
164 inline const int *getVectorLengths() const { return length_; }
165
168 CoinBigIndex getVectorFirst(const int i) const
169 {
170#ifndef COIN_FAST_CODE
171 if (i < 0 || i >= majorDim_)
172 throw CoinError("bad index", "vectorFirst", "CoinPackedMatrix");
173#endif
174 return start_[i];
175 }
178 CoinBigIndex getVectorLast(const int i) const
179 {
180#ifndef COIN_FAST_CODE
181 if (i < 0 || i >= majorDim_)
182 throw CoinError("bad index", "vectorLast", "CoinPackedMatrix");
183#endif
184 return start_[i] + length_[i];
185 }
187 inline int getVectorSize(const int i) const
188 {
189#ifndef COIN_FAST_CODE
190 if (i < 0 || i >= majorDim_)
191 throw CoinError("bad index", "vectorSize", "CoinPackedMatrix");
192#endif
193 return length_[i];
194 }
195#ifndef CLP_NO_VECTOR
198 {
199#ifndef COIN_FAST_CODE
200 if (i < 0 || i >= majorDim_)
201 throw CoinError("bad index", "vector", "CoinPackedMatrix");
202#endif
204 index_ + start_[i],
205 element_ + start_[i],
206 false);
207 }
208#endif
219 int *getMajorIndices() const;
221
222 //---------------------------------------------------------------------------
233 void setDimensions(int numrows, int numcols);
234
236 void setExtraGap(const double newGap);
238 void setExtraMajor(const double newMajor);
239#ifndef CLP_NO_VECTOR
247#endif
254 void appendCol(const int vecsize,
255 const int *vecind, const double *vecelem);
256#ifndef CLP_NO_VECTOR
263 void appendCols(const int numcols,
264 const CoinPackedVectorBase *const *cols);
265#endif
271 int appendCols(const int numcols,
272 const CoinBigIndex *columnStarts, const int *row,
273 const double *element, int numberRows = -1);
274#ifndef CLP_NO_VECTOR
282#endif
289 void appendRow(const int vecsize,
290 const int *vecind, const double *vecelem);
291#ifndef CLP_NO_VECTOR
298 void appendRows(const int numrows,
299 const CoinPackedVectorBase *const *rows);
300#endif
306 int appendRows(const int numrows,
307 const CoinBigIndex *rowStarts, const int *column,
308 const double *element, int numberColumns = -1);
309
320
322 void deleteCols(const int numDel, const int *indDel);
324 void deleteRows(const int numDel, const int *indDel);
325
329 void replaceVector(const int index,
330 const int numReplace, const double *newElements);
335 void modifyCoefficient(int row, int column, double newElement,
336 bool keepZero = false);
340 double getCoefficient(int row, int column) const;
341
347 CoinBigIndex compress(double threshold);
362 CoinBigIndex cleanMatrix(double threshold = 1.0e-20);
364
365 //---------------------------------------------------------------------------
370 void removeGaps(double removeValue = -1.0);
371
375 void submatrixOf(const CoinPackedMatrix &matrix,
376 const int numMajor, const int *indMajor);
381 const int numMajor, const int *indMajor);
382#if 0
386 void submatrixOf(const CoinPackedMatrix& matrix,
387 const int numMajor, const int * indMajor,
388 const int numMinor, const int * indMinor);
389#endif
390
393 void copyOf(const CoinPackedMatrix &rhs);
397 void copyOf(const bool colordered,
398 const int minor, const int major, const CoinBigIndex numels,
399 const double *elem, const int *ind,
400 const CoinBigIndex *start, const int *len,
401 const double extraMajor = 0.0, const double extraGap = 0.0);
406
415
424 void assignMatrix(const bool colordered,
425 const int minor, const int major,
426 const CoinBigIndex numels,
427 double *&elem, int *&ind,
428 CoinBigIndex *&start, int *&len,
429 const int maxmajor = -1, const CoinBigIndex maxsize = -1);
430
434
442
452 void transpose();
453
455 void swap(CoinPackedMatrix &matrix);
456
458
459 //---------------------------------------------------------------------------
465 void times(const double *x, double *y) const;
466#ifndef CLP_NO_VECTOR
469 void times(const CoinPackedVectorBase &x, double *y) const;
470#endif
474 void transposeTimes(const double *x, double *y) const;
475#ifndef CLP_NO_VECTOR
478 void transposeTimes(const CoinPackedVectorBase &x, double *y) const;
479#endif
481
482 //---------------------------------------------------------------------------
490
491 //-------------------------------------------------------------------------
498 int *countOrthoLength() const;
501 void countOrthoLength(int *counts) const;
504 inline int getMajorDim() const { return majorDim_; }
507 inline void setMajorDim(int value) { majorDim_ = value; }
510 inline int getMinorDim() const { return minorDim_; }
513 inline void setMinorDim(int value) { minorDim_ = value; }
517 inline int getMaxMajorDim() const { return maxMajorDim_; }
518
521 void dumpMatrix(const char *fname = NULL) const;
522
524 void printMatrixElement(const int row_val, const int col_val) const;
526
527 //-------------------------------------------------------------------------
537#ifndef CLP_NO_VECTOR
540#endif
542 void appendMajorVector(const int vecsize, const int *vecind,
543 const double *vecelem);
544#ifndef CLP_NO_VECTOR
546 void appendMajorVectors(const int numvecs,
547 const CoinPackedVectorBase *const *vecs);
548
551#endif
553 void appendMinorVector(const int vecsize, const int *vecind,
554 const double *vecelem);
555#ifndef CLP_NO_VECTOR
557 void appendMinorVectors(const int numvecs,
558 const CoinPackedVectorBase *const *vecs);
559#endif
572 void appendMinorFast(const int number,
573 const CoinBigIndex *starts, const int *index,
574 const double *element);
576
577 //-------------------------------------------------------------------------
610
611 //-----------------------------------------------------------------------
616 void deleteMajorVectors(const int numDel, const int *indDel);
619 void deleteMinorVectors(const int numDel, const int *indDel);
621
622 //-----------------------------------------------------------------------
629 void timesMajor(const double *x, double *y) const;
630#ifndef CLP_NO_VECTOR
634 void timesMajor(const CoinPackedVectorBase &x, double *y) const;
635#endif
640 void timesMinor(const double *x, double *y) const;
641#ifndef CLP_NO_VECTOR
645 void timesMinor(const CoinPackedVectorBase &x, double *y) const;
646#endif
648
649
650 //--------------------------------------------------------------------------
653#ifndef CLP_NO_VECTOR
661 template < class FloatEqual >
662 bool
663 isEquivalent(const CoinPackedMatrix &rhs, const FloatEqual &eq) const
664 {
665 // Both must be column order or both row ordered and must be of same size
666 if ((isColOrdered() ^ rhs.isColOrdered()) || (getNumCols() != rhs.getNumCols()) || (getNumRows() != rhs.getNumRows()) || (getNumElements() != rhs.getNumElements()))
667 return false;
668
669 for (int i = getMajorDim() - 1; i >= 0; --i) {
671 CoinShallowPackedVector rhsPv = rhs.getVector(i);
672 if (!pv.isEquivalent(rhsPv, eq))
673 return false;
674 }
675 return true;
676 }
677
684 bool isEquivalent2(const CoinPackedMatrix &rhs) const;
685#else
694 bool isEquivalent(const CoinPackedMatrix &rhs, const CoinRelFltEq &eq) const;
695#endif
700 bool isEquivalent(const CoinPackedMatrix &rhs) const;
702
703 //--------------------------------------------------------------------------
713 inline double *getMutableElements() const { return element_; }
719 inline int *getMutableIndices() const { return index_; }
720
723 inline CoinBigIndex *getMutableVectorStarts() const { return start_; }
725 inline int *getMutableVectorLengths() const { return length_; }
727 inline void setNumElements(CoinBigIndex value)
728 {
729 size_ = value;
730 }
735 inline void nullElementArray() { element_ = NULL; }
736
741 inline void nullStartArray() { start_ = NULL; }
742
747 inline void nullLengthArray() { length_ = NULL; }
748
753 inline void nullIndexArray() { index_ = NULL; }
755
756 //--------------------------------------------------------------------------
759
761
763 CoinPackedMatrix(const bool colordered,
764 const double extraMajor, const double extraGap);
765
766 CoinPackedMatrix(const bool colordered,
767 const int minor, const int major, const CoinBigIndex numels,
768 const double *elem, const int *ind,
769 const CoinBigIndex *start, const int *len,
770 const double extraMajor, const double extraGap);
771
772 CoinPackedMatrix(const bool colordered,
773 const int minor, const int major, const CoinBigIndex numels,
774 const double *elem, const int *ind,
775 const CoinBigIndex *start, const int *len);
776
787 CoinPackedMatrix(const bool colordered,
788 const int *rowIndices,
789 const int *colIndices,
790 const double *elements,
791 CoinBigIndex numels);
792
795
811 int extraForMajor, int extraElements,
812 bool reverseOrdering = false);
813
817 int numberRows, const int *whichRows,
818 int numberColumns, const int *whichColumns);
819
823
847 int verifyMtx(int verbosity = 1, bool zeroesAreError = false) const;
849
850 //--------------------------------------------------------------------------
851protected:
853 void gutsOfCopyOf(const bool colordered,
854 const int minor, const int major, const CoinBigIndex numels,
855 const double *elem, const int *ind,
856 const CoinBigIndex *start, const int *len,
857 const double extraMajor = 0.0, const double extraGap = 0.0);
859 void gutsOfCopyOfNoGaps(const bool colordered,
860 const int minor, const int major,
861 const double *elem, const int *ind,
862 const CoinBigIndex *start);
863 void gutsOfOpEqual(const bool colordered,
864 const int minor, const int major, const CoinBigIndex numels,
865 const double *elem, const int *ind,
866 const CoinBigIndex *start, const int *len);
867 void resizeForAddingMajorVectors(const int numVec, const int *lengthVec);
868 void resizeForAddingMinorVectors(const int *addedEntries);
869
879 int appendMajor(const int number,
880 const CoinBigIndex *starts, const int *index,
881 const double *element, int numberOther = -1);
891 int appendMinor(const int number,
892 const CoinBigIndex *starts, const int *index,
893 const double *element, int numberOther = -1);
894
895private:
897 {
898 return majorDim_ == 0 ? 0 : start_[majorDim_];
899 }
900
901 //--------------------------------------------------------------------------
902protected:
912 double extraGap_;
917
920 double *element_;
923 int *index_;
928
935
941};
942
943//#############################################################################
952
953#endif
954
955/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
956*/
void CoinPackedMatrixUnitTest()
Test the methods in the CoinPackedMatrix class.
int CoinBigIndex
Error Class thrown by an exception.
Definition: CoinError.hpp:42
Sparse Matrix Base Class.
void nullElementArray()
NULLify element array.
CoinBigIndex size_
the number of nonzero entries
void appendRows(const int numrows, const CoinPackedVectorBase *const *rows)
Append a set of rows to the end of the matrix.
CoinBigIndex cleanMatrix(double threshold=1.0e-20)
Really clean up matrix.
const CoinShallowPackedVector getVector(int i) const
Return the i'th vector in matrix.
void nullIndexArray()
NULLify index array.
double * getMutableElements() const
A vector containing the elements in the packed matrix.
void replaceVector(const int index, const int numReplace, const double *newElements)
Replace the elements of a vector.
void setDimensions(int numrows, int numcols)
Set the dimensions of the matrix.
void resizeForAddingMinorVectors(const int *addedEntries)
CoinBigIndex * getMutableVectorStarts() const
The positions where the major-dimension vectors start in element_ and index_.
void times(const double *x, double *y) const
Return A * x in y.
void majorAppendSameOrdered(const CoinPackedMatrix &matrix)
Append the columns of the argument to the right end of this matrix.
void reverseOrdering()
Reverse the ordering of the packed matrix.
const int * getVectorLengths() const
The lengths of the major-dimension vectors.
void timesMajor(const double *x, double *y) const
Return A * x (multiplied from the "right" direction) in y.
int maxMajorDim_
max space allocated for major-dimension
void transposeTimes(const double *x, double *y) const
Return x * A in y.
int minorDim_
size of other dimension
void nullLengthArray()
NULLify length array.
int getSizeVectorLengths() const
The size of the vectorLengths array.
bool isColOrdered() const
Whether the packed matrix is column major ordered or not.
int getMaxMajorDim() const
Current maximum for major dimension.
int getVectorSize(const int i) const
The length of i'th vector.
double * element_
List of nonzero element values.
void times(const CoinPackedVectorBase &x, double *y) const
Return A * x in y.
const int * getIndices() const
A vector containing the minor indices of the elements in the packed matrix.
int getMinorDim() const
Minor dimension.
CoinBigIndex getNumElements() const
Number of entries in the packed matrix.
void minorAppendSameOrdered(const CoinPackedMatrix &matrix)
Append the columns of the argument to the bottom end of this matrix.
int * getMutableIndices() const
A vector containing the minor indices of the elements in the packed matrix.
int * length_
Lengths of major-dimension vectors.
int getSizeVectorStarts() const
The size of the vectorStarts array.
void copyReuseArrays(const CoinPackedMatrix &rhs)
Copy method.
void appendMinorVector(const int vecsize, const int *vecind, const double *vecelem)
Append a minor-dimension vector to the end of the matrix.
void gutsOfDestructor()
const double * getElements() const
A vector containing the elements in the packed matrix.
void dumpMatrix(const char *fname=NULL) const
Dump the matrix on stdout.
virtual ~CoinPackedMatrix()
Destructor.
int * countOrthoLength() const
Count the number of entries in every minor-dimension vector and return an array containing these leng...
void majorAppendOrthoOrdered(const CoinPackedMatrix &matrix)
Append the rows of the argument to the right end of this matrix.
int appendMinor(const int number, const CoinBigIndex *starts, const int *index, const double *element, int numberOther=-1)
Append a set of rows (columns) to the end of a column (row) ordered matrix.
CoinBigIndex compress(double threshold)
Eliminate all elements in matrix whose absolute value is less than threshold.
void copyOf(const CoinPackedMatrix &rhs)
Copy method.
CoinPackedMatrix & operator=(const CoinPackedMatrix &rhs)
Assignment operator.
void transposeTimes(const CoinPackedVectorBase &x, double *y) const
Return x * A in y.
void appendCol(const int vecsize, const int *vecind, const double *vecelem)
Append a column to the end of the matrix.
void appendMajorVector(const CoinPackedVectorBase &vec)
Append a major-dimension vector to the end of the matrix.
double getExtraGap() const
Return the current setting of the extra gap.
CoinBigIndex getVectorLast(const int i) const
The position of the last element (well, one entry past the last) in the i'th major-dimension vector.
int appendRows(const int numrows, const CoinBigIndex *rowStarts, const int *column, const double *element, int numberColumns=-1)
Append a set of rows to the end of the matrix.
CoinPackedMatrix(const CoinPackedMatrix &wholeModel, int numberRows, const int *whichRows, int numberColumns, const int *whichColumns)
Subset constructor (without gaps).
int * getMajorIndices() const
Returns an array containing major indices.
void reserve(const int newMaxMajorDim, const CoinBigIndex newMaxSize, bool create=false)
Reserve sufficient space for appending major-ordered vectors.
void appendRow(const CoinPackedVectorBase &vec)
Append a row to the end of the matrix.
void assignMatrix(const bool colordered, const int minor, const int major, const CoinBigIndex numels, double *&elem, int *&ind, CoinBigIndex *&start, int *&len, const int maxmajor=-1, const CoinBigIndex maxsize=-1)
Assign the arguments to the matrix.
void setNumElements(CoinBigIndex value)
Change the size of the bulk store after modifying - be careful.
void setMajorDim(int value)
Set major dimension.
CoinBigIndex getLastStart() const
void deleteMinorVectors(const int numDel, const int *indDel)
Delete the minor-dimension vectors whose indices are listed in indDel.
void timesMinor(const CoinPackedVectorBase &x, double *y) const
Return A * x (multiplied from the "right" direction) in y.
void appendCol(const CoinPackedVectorBase &vec)
Append a column to the end of the matrix.
bool isEquivalent2(const CoinPackedMatrix &rhs) const
Test for equivalence and report differences.
const CoinBigIndex * getVectorStarts() const
The positions where the major-dimension vectors start in elements and indices.
double extraMajor_
his much times more space should be allocated for major-dimension vectors when the matrix is resized.
void setExtraGap(const double newGap)
Set the extra gap to be allocated to the specified value.
CoinBigIndex getVectorFirst(const int i) const
The position of the first element in the i'th major-dimension vector.
void countOrthoLength(int *counts) const
Count the number of entries in every minor-dimension vector and fill in an array containing these len...
void deleteMajorVectors(const int numDel, const int *indDel)
Delete the major-dimension vectors whose indices are listed in indDel.
int * getMutableVectorLengths() const
The lengths of the major-dimension vectors.
void appendRow(const int vecsize, const int *vecind, const double *vecelem)
Append a row to the end of the matrix.
void appendMajorVectors(const int numvecs, const CoinPackedVectorBase *const *vecs)
Append several major-dimensonvectors to the end of the matrix.
void timesMajor(const CoinPackedVectorBase &x, double *y) const
Return A * x (multiplied from the "right" direction) in y.
double getCoefficient(int row, int column) const
Return one element of packed matrix.
int getNumCols() const
Number of columns.
int * index_
List of nonzero element minor-dimension indices.
void setExtraMajor(const double newMajor)
Set the extra major to be allocated to the specified value.
void appendMinorVector(const CoinPackedVectorBase &vec)
Append a minor-dimension vector to the end of the matrix.
void appendCols(const int numcols, const CoinPackedVectorBase *const *cols)
Append a set of columns to the end of the matrix.
CoinPackedMatrix(const CoinPackedMatrix &m, int extraForMajor, int extraElements, bool reverseOrdering=false)
Copy constructor with fine tuning.
void setMinorDim(int value)
Set minor dimension.
void gutsOfOpEqual(const bool colordered, const int minor, const int major, const CoinBigIndex numels, const double *elem, const int *ind, const CoinBigIndex *start, const int *len)
void reverseOrderedCopyOf(const CoinPackedMatrix &rhs)
Make a reverse-ordered copy.
void submatrixOfWithDuplicates(const CoinPackedMatrix &matrix, const int numMajor, const int *indMajor)
Extract a submatrix from matrix.
int getMajorDim() const
Major dimension.
void appendMinorFast(const int number, const CoinBigIndex *starts, const int *index, const double *element)
Append a set of rows (columns) to the end of a column (row) ordered matrix.
void orderMatrix()
Sort all columns so indices are increasing.in each column.
CoinBigIndex eliminateDuplicates(double threshold)
Eliminate all duplicate AND small elements in matrix The column starts are not affected.
bool hasGaps() const
Whether the packed matrix has gaps or not.
double getExtraMajor() const
Return the current setting of the extra major.
bool isEquivalent(const CoinPackedMatrix &rhs, const FloatEqual &eq) const
Test for equivalence.
int appendCols(const int numcols, const CoinBigIndex *columnStarts, const int *row, const double *element, int numberRows=-1)
Append a set of columns to the end of the matrix.
friend void CoinPackedMatrixUnitTest()
Test the methods in the CoinPackedMatrix class.
CoinPackedMatrix(const CoinPackedMatrix &m)
Copy constructor.
void removeGaps(double removeValue=-1.0)
Remove the gaps from the matrix if there were any Can also remove small elements fabs() <= removeValu...
int getNumRows() const
Number of rows.
void timesMinor(const double *x, double *y) const
Return A * x (multiplied from the "right" direction) in y.
int verifyMtx(int verbosity=1, bool zeroesAreError=false) const
Scan the matrix for anomalies.
void swap(CoinPackedMatrix &matrix)
Swap the content of two packed matrices.
CoinPackedMatrix(const bool colordered, const double extraMajor, const double extraGap)
A constructor where the ordering and the gaps are specified.
double extraGap_
This much times more space should be allocated for each major-dimension vector (with respect to the n...
void deleteRows(const int numDel, const int *indDel)
Delete the rows whose indices are listed in indDel.
void minorAppendOrthoOrdered(const CoinPackedMatrix &matrix)
Append the rows of the argument to the bottom end of this matrix.
CoinBigIndex maxSize_
max space allocated for entries
CoinPackedMatrix()
Default Constructor creates an empty column ordered packed matrix.
void appendMajorVector(const int vecsize, const int *vecind, const double *vecelem)
Append a major-dimension vector to the end of the matrix.
bool colOrdered_
A flag indicating whether the matrix is column or row major ordered.
void appendMinorVectors(const int numvecs, const CoinPackedVectorBase *const *vecs)
Append several minor-dimension vectors to the end of the matrix.
void copyOf(const bool colordered, const int minor, const int major, const CoinBigIndex numels, const double *elem, const int *ind, const CoinBigIndex *start, const int *len, const double extraMajor=0.0, const double extraGap=0.0)
Copy the arguments to the matrix.
void printMatrixElement(const int row_val, const int col_val) const
Print a single matrix element.
void resizeForAddingMajorVectors(const int numVec, const int *lengthVec)
void bottomAppendPackedMatrix(const CoinPackedMatrix &matrix)
Append the argument to the "bottom" of the current matrix.
CoinPackedMatrix(const bool colordered, const int minor, const int major, const CoinBigIndex numels, const double *elem, const int *ind, const CoinBigIndex *start, const int *len, const double extraMajor, const double extraGap)
void gutsOfCopyOf(const bool colordered, const int minor, const int major, const CoinBigIndex numels, const double *elem, const int *ind, const CoinBigIndex *start, const int *len, const double extraMajor=0.0, const double extraGap=0.0)
CoinPackedMatrix(const bool colordered, const int *rowIndices, const int *colIndices, const double *elements, CoinBigIndex numels)
Create packed matrix from triples.
void clear()
Clear the data, but do not free any arrays.
void transpose()
Transpose the matrix.
void modifyCoefficient(int row, int column, double newElement, bool keepZero=false)
Modify one element of packed matrix.
void gutsOfCopyOfNoGaps(const bool colordered, const int minor, const int major, const double *elem, const int *ind, const CoinBigIndex *start)
When no gaps we can do faster.
void nullStartArray()
NULLify start array.
CoinPackedMatrix(const bool colordered, const int minor, const int major, const CoinBigIndex numels, const double *elem, const int *ind, const CoinBigIndex *start, const int *len)
bool isEquivalent(const CoinPackedMatrix &rhs) const
Test for equivalence.
CoinBigIndex * start_
Starting positions of major-dimension vectors.
void deleteCols(const int numDel, const int *indDel)
Delete the columns whose indices are listed in indDel.
void rightAppendPackedMatrix(const CoinPackedMatrix &matrix)
Append the argument to the "right" of the current matrix.
int appendMajor(const int number, const CoinBigIndex *starts, const int *index, const double *element, int numberOther=-1)
Append a set of rows (columns) to the end of a row (colum) ordered matrix.
int majorDim_
number of vectors in matrix
void submatrixOf(const CoinPackedMatrix &matrix, const int numMajor, const int *indMajor)
Extract a submatrix from matrix.
Abstract base class for various sparse vectors.
bool isEquivalent(const CoinPackedVectorBase &rhs, const FloatEqual &eq) const
equivalent - If shallow packed vector A & B are equivalent, then they are still equivalent no matter ...
Equality to a scaled tolerance.