Commit 57eb7e0a authored by Kirill Terekhov's avatar Kirill Terekhov

Annotations for the classes in inmost_sparse.h

Classes  AnnotationService, Vector, Row in inmost_sparse.h
parent 9c714400
......@@ -10,544 +10,640 @@
namespace INMOST
{
namespace Sparse
{
namespace Sparse
{
#if defined(USE_SOLVER) || defined(USE_AUTODIFF)
/// Retrive MPI type for row entry type
/// Retrive MPI type for row entry type.
INMOST_MPI_Type GetRowEntryType();
/// Create MPI type for row entry type
/// Create MPI type for row entry type.
void CreateRowEntryType();
/// Release MPI type
/// Release MPI type.
void DestroyRowEntryType();
/// Check whether MPI type was created
/// Check whether MPI type was created.
bool HaveRowEntryType();
/// This class can be used to annotate the matrix
/// This class can be used to annotate the matrix.
/// You can optionally provide a pointer to an object of
/// this class to Sparse::Matrix::Save or Sparse::HessianMatrix::Save.
/// Then comments would be added to mtx file next to the
/// non-empty strings.
class AnnotationService
{
interval<INMOST_DATA_ENUM_TYPE,std::string> text;
interval<INMOST_DATA_ENUM_TYPE,std::string> text; ///< Array of strings corresponding to matrix rows.
public:
/// Create a new annotation for local matrix.
/// @param start First row of the matrix.
/// @param end Last row of the matrix.
AnnotationService(INMOST_DATA_ENUM_TYPE start = 0, INMOST_DATA_ENUM_TYPE end = 0) { if( end != start ) SetInterval(start,end); }
/// Copy annotations for the matrix.
/// @param other Another class for annotation.
AnnotationService(const AnnotationService & other) : text(other.text) { }
/// Assign annotations for the matrix.
/// @param other Another class for annotation.
AnnotationService & operator = (AnnotationService const & other) {text = other.text; return *this;}
/// Destroy annotations for the matrix.
~AnnotationService() {}
/// Get the first row index of the distributed matrix interval.
INMOST_DATA_ENUM_TYPE GetFirstIndex() const {return text.get_interval_beg();}
/// Get the last row index of the distributed matrix interval.
INMOST_DATA_ENUM_TYPE GetLastIndex() const {return text.get_interval_end();}
/// Check whether the interval of the local matrix was specified and non-empty.
bool Empty() const {return text.empty();}
/// Specify interval of the local matrix.
/// @param beg The first row of the local matrix.
/// @param end The last row of the local matrix.
void SetInterval(INMOST_DATA_ENUM_TYPE beg, INMOST_DATA_ENUM_TYPE end) { text.set_interval_beg(beg); text.set_interval_end(end); }
/// Retrive interval of the local matrix.
/// @param start Record the first row of the local matrix into this variable.
/// @param end Record the last row of the local matrix into this variable.
void GetInterval(INMOST_DATA_ENUM_TYPE & start, INMOST_DATA_ENUM_TYPE & end) const {start = text.get_interval_beg(); end = text.get_interval_end();}
/// Retrive the text corresponding to a certain row of the matrix.
/// @param row Row of the matrix.
std::string & GetAnnotation(INMOST_DATA_ENUM_TYPE row) {assert(!text.empty()); return text[row];}
/// Retrive the text corresponding to a certain row of the matrix without right of modification.
/// @param row Row of the matrix.
const std::string & GetAnnotation(INMOST_DATA_ENUM_TYPE row) const {assert(!text.empty()); return text[row];}
/// Specify the text to a certain row of the matrix.
/// @param row Row of the matrix.
/// @param str Annotation for the row of the matrix.
void SetAnnotation(INMOST_DATA_ENUM_TYPE row, std::string str) {assert(!text.empty()); text[row] = str;}
};
#endif
#if defined(USE_SOLVER)
/// Distributed vector class.
/// This class can be used to store both local and distributed dense data of real type.
/// For example, to form the right-hand side or initial guess to the solution.
/// @see Solve
class Vector
{
public:
typedef interval<INMOST_DATA_ENUM_TYPE,INMOST_DATA_REAL_TYPE> Entries;
typedef Entries::iterator iterator;
typedef Entries::const_iterator const_iterator;
private:
INMOST_MPI_Comm comm;
Entries data;
std::string name;
bool is_parallel;
public:
/// Main constructor of the Vector class.
/// @param _name Name of the vector, empty string by default.
/// @param start Start of the local data interval.
/// @param end End of the local data interval.
/// @param _comm Communicator for parallel data exchanges, MPI_COMM_WORLD by default.
Vector(std::string _name = "", INMOST_DATA_ENUM_TYPE start = 0, INMOST_DATA_ENUM_TYPE end = 0, INMOST_MPI_Comm _comm = INMOST_MPI_COMM_WORLD);
Vector(const Vector & other);
Vector & operator =(Vector const & other);
~Vector();
/// Return reference to i-th element of the vector.
INMOST_DATA_REAL_TYPE & operator [](INMOST_DATA_ENUM_TYPE i) {return data[i];}
/// Return i-th element of the vector.
INMOST_DATA_REAL_TYPE operator [](INMOST_DATA_ENUM_TYPE i) const {return data[i];}
/// Return the global size of the vector.
INMOST_DATA_ENUM_TYPE Size() const { return static_cast<INMOST_DATA_ENUM_TYPE>(data.size()); }
iterator Begin() {return data.begin();}
const_iterator Begin() const {return data.begin();}
iterator End() {return data.end();}
const_iterator End() const {return data.end();}
bool Empty() const {return data.empty();}
/// Set the start and the end of the distributed vector interval.
void SetInterval(INMOST_DATA_ENUM_TYPE start, INMOST_DATA_ENUM_TYPE end) {assert(start<=end); data.set_interval_beg(start); data.set_interval_end(end);}
/// Get the start and the end of the distributed vector interval.
void GetInterval(INMOST_DATA_ENUM_TYPE & start, INMOST_DATA_ENUM_TYPE & end) const {start = data.get_interval_beg(); end = data.get_interval_end();}
/// Move starting position of local indexes
void ShiftInterval(INMOST_DATA_ENUM_TYPE shift) {data.shift_interval(shift);}
/// Get the first index of the distributed vector interval.
INMOST_DATA_ENUM_TYPE GetFirstIndex() const {return data.get_interval_beg();}
/// Get the last index of the distributed vector interval.
INMOST_DATA_ENUM_TYPE GetLastIndex() const {return data.get_interval_end();}
/// Get the communicator which the vector is associated with.
INMOST_MPI_Comm GetCommunicator() const {return comm;}
void Swap(Vector & other) {data.swap(other.data); name.swap(other.name); std::swap(is_parallel,other.is_parallel); std::swap(comm,other.comm);}
/// Save the distributed vector to a single data file using parallel MPI I/O.
void Save(std::string file);
/// Load the vector from a single data file using the specified interval.
/// If interval is not specified, then it will be automatically constructed,
/// with the about equal block size (the last block may has larger dimension).
void Load(std::string file, INMOST_DATA_ENUM_TYPE mbeg = ENUMUNDEF, INMOST_DATA_ENUM_TYPE mend = ENUMUNDEF, std::string file_ord = "");
bool & isParallel() {return is_parallel;}
/// Get the vector name specified in the main constructor.
std::string GetName() {return name;}
/// Clear all data of the current vector.
void Clear() {data.clear();}
};
#endif //defined(USE_SOLVER)
/// Distributed vector class.
/// This class can be used to store both local and distributed dense data of real type.
/// For example, to form the right-hand side or initial guess to the solution.
/// @see Solve
class Vector
{
public:
typedef interval<INMOST_DATA_ENUM_TYPE,INMOST_DATA_REAL_TYPE> Entries; ///< Type for representation of the local array of values.
typedef Entries::iterator iterator; ///< Type for the iterator over vector of the values.
typedef Entries::const_iterator const_iterator; ///< Type for the iterator over vector of the constant values.
private:
INMOST_MPI_Comm comm; ///< Communicator corresponding to the Vector. Do we need this?
Entries data; ///< Vector of the vector values on the current processor.
std::string name; ///< Name of the vector, may be used to specify some parameters.
bool is_parallel; ///< A flag indicating that the vector has extended range of values via OrderInfo class.
public:
/// Main constructor of the Vector class.
/// @param _name Name of the vector, empty string by default.
/// @param start Start of the local data interval.
/// @param end End of the local data interval.
/// @param _comm Communicator for parallel data exchanges, MPI_COMM_WORLD by default.
Vector(std::string _name = "", INMOST_DATA_ENUM_TYPE start = 0, INMOST_DATA_ENUM_TYPE end = 0, INMOST_MPI_Comm _comm = INMOST_MPI_COMM_WORLD);
/// Copy constructor.
/// @param other Another vector.
Vector(const Vector & other);
/// Assignment operator.
/// @param other Another vector.
Vector & operator =(Vector const & other);
/// Delete data of the vector.
~Vector();
/// Return reference to i-th element of the vector.
INMOST_DATA_REAL_TYPE & operator [](INMOST_DATA_ENUM_TYPE i) {return data[i];}
/// Return i-th element of the vector.
INMOST_DATA_REAL_TYPE operator [](INMOST_DATA_ENUM_TYPE i) const {return data[i];}
/// Return the global size of the vector.
INMOST_DATA_ENUM_TYPE Size() const { return static_cast<INMOST_DATA_ENUM_TYPE>(data.size()); }
/// Iterator pointing to the first value of the vector.
iterator Begin() {return data.begin();}
/// Iterator pointing to the first constant value of the vector.
const_iterator Begin() const {return data.begin();}
/// Iterator pointing behind the last value of the vector.
iterator End() {return data.end();}
/// Iterator pointing behind the last constant value of the vector.
const_iterator End() const {return data.end();}
/// Test is there any data in the vector.
bool Empty() const {return data.empty();}
/// Set the start and the end of the distributed vector interval.
/// @param start The first index of the local part of the vector.
/// @param end The last index of the local part of the vector.
void SetInterval(INMOST_DATA_ENUM_TYPE start, INMOST_DATA_ENUM_TYPE end) {assert(start<=end); data.set_interval_beg(start); data.set_interval_end(end);}
/// Get the start and the end of the distributed vector interval.
/// @param start Record the first index of the local part of the vector into this variable.
/// @param end Record the last index of the local part of the vector into this variable.
void GetInterval(INMOST_DATA_ENUM_TYPE & start, INMOST_DATA_ENUM_TYPE & end) const {start = data.get_interval_beg(); end = data.get_interval_end();}
/// Move starting position of local indexes
/// @param shift Number of positions to shift indices.
void ShiftInterval(INMOST_DATA_ENUM_TYPE shift) {data.shift_interval(shift);}
/// Get the first index of the distributed vector interval.
INMOST_DATA_ENUM_TYPE GetFirstIndex() const {return data.get_interval_beg();}
/// Get the last index of the distributed vector interval.
INMOST_DATA_ENUM_TYPE GetLastIndex() const {return data.get_interval_end();}
/// Get the communicator which the vector is associated with.
INMOST_MPI_Comm GetCommunicator() const {return comm;}
/// Exchange all the data with another vector.
/// @param other Another vector.
void Swap(Vector & other) {data.swap(other.data); name.swap(other.name); std::swap(is_parallel,other.is_parallel); std::swap(comm,other.comm);}
/// Save the distributed vector to a single data file using parallel MPI I/O.
void Save(std::string file);
/// Load the vector from a single data file using the specified interval.
/// If interval is not specified, then it will be automatically constructed,
/// with the about equal block size (the last block may has larger dimension).
void Load(std::string file, INMOST_DATA_ENUM_TYPE mbeg = ENUMUNDEF, INMOST_DATA_ENUM_TYPE mend = ENUMUNDEF, std::string file_ord = "");
/// Test whether the vector was assigned an extended range of values via OrderInfo class.
bool & isParallel() {return is_parallel;}
/// Get the vector name specified in the main constructor.
std::string GetName() {return name;}
/// Clear all data of the current vector.
void Clear() {data.clear();}
};
#endif //defined(USE_SOLVER)
#if defined(USE_SOLVER) || defined(USE_AUTODIFF)
/// Class to store the sparse matrix row.
class Row
{
public:
/// Entry of the sparse matrix row.
typedef struct entry_s
{
INMOST_DATA_ENUM_TYPE first; ///< the column number of the row element.
INMOST_DATA_REAL_TYPE second; ///< the real value of the row element.
bool operator < (const entry_s & other) const { return first < other.first || (first == other.first && second < other.second); }
} entry;
__INLINE static entry make_entry(INMOST_DATA_ENUM_TYPE ind, INMOST_DATA_REAL_TYPE val)
{
entry ret;
ret.first = ind;
ret.second = val;
return ret;
}
private:
//typedef dynarray<entry,16> Entries; //replace later with more memory-efficient chunk_array, with first chunk in stack
typedef array<entry> Entries;
public:
typedef Entries::iterator iterator;
typedef Entries::const_iterator const_iterator;
typedef Entries::reverse_iterator reverse_iterator;
typedef Entries::const_reverse_iterator const_reverse_iterator;
private:
Entries data;
public:
Row() : data() {}
Row(const Row & other) : data(other.data) {}
Row(entry * pbegin, entry * pend) :data(pbegin, pend) {}
~Row() {}
Row & operator = (Row const & other) { data = other.data; return *this; }
/// The operator [] used to fill the sparse matrix row, but not to access individual elements of the row.
INMOST_DATA_REAL_TYPE & operator [](INMOST_DATA_ENUM_TYPE i) // use to fill matrix, not to access individual elements
{
for(Entries::size_type it = 0; it < data.size(); ++it)
if( data[it].first == i ) return data[it].second;
data.push_back(make_entry(i,0));
return data.back().second;
}
/// The operator [] used to access individual elements of the row.
INMOST_DATA_REAL_TYPE operator[](INMOST_DATA_ENUM_TYPE i) const
{
for (Entries::size_type it = 0; it < data.size(); ++it) if (data[it].first == i) return data[it].second;
//you should not come here
assert(false);
return 1.0e20;
}
/// Returns zero if no entry was found.
INMOST_DATA_REAL_TYPE get_safe(INMOST_DATA_ENUM_TYPE i) const
{
for (Entries::size_type it = 0; it < data.size(); ++it) if (data[it].first == i) return data[it].second;
return 0.0;
}
//void Reserve(INMOST_DATA_ENUM_TYPE num) { data.reserve(num);}
/// Clear all data of the current row.
void Clear() { data.clear(); }
void Swap(Row & other) { data.swap(other.data); }
/// The size of the sparse row, i.e. the total number of nonzero elements.
INMOST_DATA_ENUM_TYPE Size() const { return static_cast<INMOST_DATA_ENUM_TYPE>(data.size()); }
bool Empty() const { return data.empty(); }
INMOST_DATA_ENUM_TYPE & GetIndex(INMOST_DATA_ENUM_TYPE k) {assert(k < data.size()); return (data.begin()+k)->first;}
INMOST_DATA_REAL_TYPE & GetValue(INMOST_DATA_ENUM_TYPE k) {assert(k < data.size()); return (data.begin()+k)->second;}
INMOST_DATA_ENUM_TYPE GetIndex(INMOST_DATA_ENUM_TYPE k) const {assert(k < data.size()); return (data.begin()+k)->first;}
INMOST_DATA_REAL_TYPE GetValue(INMOST_DATA_ENUM_TYPE k) const {assert(k < data.size()); return (data.begin()+k)->second;}
iterator Begin() {return data.begin();}
iterator End() {return data.end();}
const_iterator Begin() const {return data.begin();}
const_iterator End() const {return data.end();}
reverse_iterator rBegin() { return data.rbegin(); }
reverse_iterator rEnd() { return data.rend(); }
const_reverse_iterator rBegin() const { return data.rbegin(); }
const_reverse_iterator rEnd() const { return data.rend(); }
/// Class to store the sparse matrix row.
/// Represents a sparse vector and facilitates access to individual entries.
/// This class is used in expressions of automatic differentiation.
class Row
{
public:
/// Entry of the sparse matrix row.
typedef struct entry_s
{
INMOST_DATA_ENUM_TYPE first; ///< the column number of the row element.
INMOST_DATA_REAL_TYPE second; ///< the real value of the row element.
/// Comparison operator that helps sorting entries.
bool operator < (const entry_s & other) const { return first < other.first || (first == other.first && second < other.second); }
} entry;
/// Assemble an entry of entry_s type.
/// @param ind Index.
/// @param val Value.
__INLINE static entry make_entry(INMOST_DATA_ENUM_TYPE ind, INMOST_DATA_REAL_TYPE val)
{
entry ret;
ret.first = ind;
ret.second = val;
return ret;
}
private:
//typedef dynarray<entry,16> Entries; //replace later with more memory-efficient chunk_array, with first chunk in stack
typedef array<entry> Entries; ///< Container type for
public:
typedef Entries::iterator iterator; ///< Iterator over pairs of index and value.
typedef Entries::const_iterator const_iterator; ///< Iterator over constant pairs of index and value.
typedef Entries::reverse_iterator reverse_iterator; ///< Iterator over pairs of index and value running in backward direction.
typedef Entries::const_reverse_iterator const_reverse_iterator; ///< Iterator over constant pairs of index and value running in backward direction.
private:
Entries data; ///< Array of paris of index and value.
public:
/// Construct an empty row.
Row() : data() {}
/// Copy all data from another row.
/// @param other Another row.
Row(const Row & other) : data(other.data) {}
/// Construct a row from array of pairs of indices and values.
/// @param pbegin Pointer to the first position in array.
/// @param pend Pointer behind the last position of array.
Row(entry * pbegin, entry * pend) :data(pbegin, pend) {}
/// Release all data.
~Row() {}
/// Copy all data from another row.
/// @param other Another row.
Row & operator = (Row const & other) { data = other.data; return *this; }
/// Finds and returns value with specified index. Adds a new entry if index was not found.
/// \warning
/// The operator [] should be used to fill the sparse matrix row, but not to routinely access individual elements of the row.
/// You can use Sparse::Row::GetIndex and Sparse::Row::GetValue for rapid access to individual elements.
/// @param i Index.
/// @return Value corresponding to specified index.
INMOST_DATA_REAL_TYPE & operator [](INMOST_DATA_ENUM_TYPE i)
{
for(Entries::size_type it = 0; it < data.size(); ++it)
if( data[it].first == i ) return data[it].second;
data.push_back(make_entry(i,0));
return data.back().second;
}
/// Finds and returns value with specified index. Rises exception on debug and returns extra large value on release if
/// index was not found.
/// \warning
/// The operator [] should be used to fill the sparse matrix row, but not to routinely access individual elements of the row.
/// You can use Sparse::Row::GetIndex and Sparse::Row::GetValue for rapid access to individual elements.
/// @param i Index.
/// @return Value corresponding to specified index.
INMOST_DATA_REAL_TYPE operator[](INMOST_DATA_ENUM_TYPE i) const
{
for (Entries::size_type it = 0; it < data.size(); ++it) if (data[it].first == i) return data[it].second;
//you should not come here
assert(false);
return 1.0e20;
}
/// Finds and returns value with specified index.
/// Returns zero if no entry was found.
/// @param i Index.
/// @return Value corresponding to specified index.
INMOST_DATA_REAL_TYPE get_safe(INMOST_DATA_ENUM_TYPE i) const
{
for (Entries::size_type it = 0; it < data.size(); ++it) if (data[it].first == i) return data[it].second;
return 0.0;
}
/// Clear all data of the current row.
void Clear() { data.clear(); }
/// Exchange all the data with another row.
/// @param other Another row.
void Swap(Row & other) { data.swap(other.data); }
/// The size of the sparse row, i.e. the total number of nonzero elements.
INMOST_DATA_ENUM_TYPE Size() const { return static_cast<INMOST_DATA_ENUM_TYPE>(data.size()); }
/// Checks are there any nonzero entries in the row.
bool Empty() const { return data.empty(); }
/// Retrive an index corresponding to certain position in the array of pairs of index and value.
/// @param k Position in the array of pairs of index and value.
/// @return Index corresponding to the position in the array.
INMOST_DATA_ENUM_TYPE & GetIndex(INMOST_DATA_ENUM_TYPE k) {assert(k < data.size()); return (data.begin()+k)->first;}
/// Retrive a value corresponding to certain position in the array of pairs of index and value.
/// @param k Position in the array of pairs of index and value.
/// @return Value corresponding to the position in the array.
INMOST_DATA_REAL_TYPE & GetValue(INMOST_DATA_ENUM_TYPE k) {assert(k < data.size()); return (data.begin()+k)->second;}
/// Retrive an index corresponding to certain position in the array of pairs of index and value.
/// @param k Position in the array of pairs of index and value.
/// @return Index corresponding to the position in the array.
INMOST_DATA_ENUM_TYPE GetIndex(INMOST_DATA_ENUM_TYPE k) const {assert(k < data.size()); return (data.begin()+k)->first;}
/// Retrive a value corresponding to certain position in the array of pairs of index and value.
/// @param k Position in the array of pairs of index and value.
/// @return Value corresponding to the position in the array.
INMOST_DATA_REAL_TYPE GetValue(INMOST_DATA_ENUM_TYPE k) const {assert(k < data.size()); return (data.begin()+k)->second;}
/// An iterator pointing to the first position in the array of pairs of index and value.
iterator Begin() {return data.begin();}
/// An iterator pointing behind the last position in the array of pairs of index and value.
iterator End() {return data.end();}
/// An iterator pointing to the first position in the array of constant pairs of index and value.
const_iterator Begin() const {return data.begin();}
/// An iterator pointing behind the last position in the array of constant pairs of index and value.
const_iterator End() const {return data.end();}
/// An iterator pointing to the last position in the array of pairs of index and value.
reverse_iterator rBegin() { return data.rbegin(); }
/// An iterator pointing before the first position in the array of pairs of index and value.
reverse_iterator rEnd() { return data.rend(); }
/// An iterator pointing to the last position in the array of constant pairs of index and value.
const_reverse_iterator rBegin() const { return data.rbegin(); }
/// An iterator pointing before the first position in the array of constant pairs of index and value.
const_reverse_iterator rEnd() const { return data.rend(); }
#if defined(USE_SOLVER)
/// Return the scalar product of the current sparse row by a dense Vector.
INMOST_DATA_REAL_TYPE RowVec(Vector & x) const; // returns A(row) * x
/// Return the scalar product of the current sparse row by a dense Vector.
INMOST_DATA_REAL_TYPE RowVec(Vector & x) const; // returns A(row) * x
#endif
void MoveRow(Row & new_pos) {data = new_pos.data;} //here move constructor and std::move may be used in future
/// Set the vector entries by zeroes.
void Zero() {for(iterator it = Begin(); it != End(); ++it) it->second = 0;}
/// Push specified element into sparse row.
/// This function should be used only if the index is not repeated in the row.
void Push(INMOST_DATA_ENUM_TYPE ind, INMOST_DATA_REAL_TYPE val) {data.push_back(make_entry(ind,val));}
/// Resize row to specified size.
/// It is intended to be used together with non-const Row::GetIndex and Row::GetValue
/// that allow for the modification of individual entries.
/// @param size New size of the row.
void Resize(INMOST_DATA_ENUM_TYPE size) {data.resize(size);}
void Print() const
{
for(const_iterator it = Begin(); it != End(); ++it) std::cout << "(" << it->first << "," << it->second << ") ";
std::cout << std::endl;
}
bool isSorted() const;
/// output = alpha * left + beta *right
static void MergeSortedRows(INMOST_DATA_REAL_TYPE alpha, const Row & left, INMOST_DATA_REAL_TYPE beta, const Row & right, Row & output);
};
/// An optimized assignment of the row, when the content of the source row may not be preserved.
/// @param source Source raw where to get the contents.
void MoveRow(Row & source) {data = source.data;} //here move constructor and std::move may be used in future
/// Set the vector entries by zeroes.
void Zero() {for(iterator it = Begin(); it != End(); ++it) it->second = 0;}
/// Push specified element into sparse row.
/// This function should be used only if the index is not repeated in the row.
void Push(INMOST_DATA_ENUM_TYPE ind, INMOST_DATA_REAL_TYPE val) {data.push_back(make_entry(ind,val));}
/// Resize row to specified size.
/// It is intended to be used together with non-const Row::GetIndex and Row::GetValue
/// that allow for the modification of individual entries.
/// @param size New size of the row.
void Resize(INMOST_DATA_ENUM_TYPE size) {data.resize(size);}
/// Output all entries of the row.
void Print() const
{
for(const_iterator it = Begin(); it != End(); ++it) std::cout << "(" << it->first << "," << it->second << ") ";
std::cout << std::endl;
}
/// Check whether the row is sorted.
bool isSorted() const;
/// Add up two rows. Performs operation output=alpha*left+beta*right.
/// @param alpha Coefficient to multiply the left row.
/// @param left The left row.
/// @param beta Coefficient to multiply the right row.
/// @param right The right row.
/// @param output Record result in this vector.
static void MergeSortedRows(INMOST_DATA_REAL_TYPE alpha, const Row & left, INMOST_DATA_REAL_TYPE beta, const Row & right, Row & output);
};
#endif //defined(USE_SOLVER) || defined(USE_AUTODIFF)
#if defined(USE_SOLVER) || defined(USE_AUTODIFF)
/// Class to store the compressed symmetric matrix of a hessian row.
class HessianRow
{
public:
/// Entry of the sparse matrix row.
typedef struct hessian_index_s
{
INMOST_DATA_ENUM_TYPE first;
INMOST_DATA_ENUM_TYPE second;
bool operator < (const hessian_index_s & other) const {return first < other.first || (first == other.first && second < other.second); }
bool operator ==(const hessian_index_s & other) const {return first == other.first && second == other.second;}
} index;
__INLINE static index make_index(INMOST_DATA_ENUM_TYPE _first, INMOST_DATA_ENUM_TYPE _second)
{
index ret;
ret.first = std::min(_first,_second);
ret.second = std::max(_first,_second);
return ret;
}
typedef struct hessian_entry_s
{
index first; ///< the column number of the row element.
INMOST_DATA_REAL_TYPE second; ///< the real value of the row element.
bool operator < (const hessian_entry_s & other) const { return first < other.first || (first == other.first && second < other.second); }
} entry;
__INLINE static entry make_entry(index ind, INMOST_DATA_REAL_TYPE val)
{
entry ret;
ret.first = ind;
ret.second = val;
return ret;
}
private:
typedef array<entry> Entries; //replace later with more memory-efficient chunk_array, with first chunk in stack
//typedef dynarray<entry,8> Entries;
public:
typedef Entries::iterator iterator;
typedef Entries::const_iterator const_iterator;
typedef Entries::reverse_iterator reverse_iterator;
typedef Entries::const_reverse_iterator const_reverse_iterator;
private:
Entries data;
public:
HessianRow() : data() {}
HessianRow(const HessianRow & other) : data(other.data) {}
HessianRow(entry * pbegin, entry * pend) : data(pbegin,pend) {}
~HessianRow() {}
HessianRow & operator = (HessianRow const & other) {data = other.data; return *this;}
/// The operator [] used to fill the sparse matrix row, but not to access individual elements of the row.
INMOST_DATA_REAL_TYPE & operator [](index i) // use to fill matrix, not to access individual elements
{
for(Entries::size_type it = 0; it < data.size(); ++it)
if( data[it].first == i ) return data[it].second;
data.push_back(make_entry(i,0));
return data.back().second;
}
/// The operator [] used to access individual elements of the row.
INMOST_DATA_REAL_TYPE operator[](index i) const
{
for (Entries::size_type it = 0; it < data.size(); ++it) if (data[it].first == i) return data[it].second;
//you should not come here
assert(false);
return 1.0e20;
}
INMOST_DATA_REAL_TYPE get_safe(index i) const
{
for (Entries::size_type it = 0; it < data.size(); ++it) if (data[it].first == i) return data[it].second;
return 0.0;
}
//void Reserve(INMOST_DATA_ENUM_TYPE num) { data.reserve(num);}
/// Clear all data of the current row.
void Clear() { data.clear(); }
void Swap(HessianRow & other) { data.swap(other.data); }
/// The size of the sparse row, i.e. the total number of nonzero elements.
INMOST_DATA_ENUM_TYPE Size() const { return static_cast<INMOST_DATA_ENUM_TYPE>(data.size()); }
bool Empty() const { return data.empty(); }
index & GetIndex(INMOST_DATA_ENUM_TYPE k) {assert(k < data.size()); return (data.begin()+k)->first;}
INMOST_DATA_REAL_TYPE & GetValue(INMOST_DATA_ENUM_TYPE k) {assert(k < data.size()); return (data.begin()+k)->second;}
index GetIndex(INMOST_DATA_ENUM_TYPE k) const {assert(k < data.size()); return (data.begin()+k)->first;}
INMOST_DATA_REAL_TYPE GetValue(INMOST_DATA_ENUM_TYPE k) const {assert(k < data.size()); return (data.begin()+k)->second;}
iterator Begin() {return data.begin();}
iterator End() {return data.end();}
const_iterator Begin() const {return data.begin();}
const_iterator End() const {return data.end();}
reverse_iterator rBegin() { return data.rbegin(); }
reverse_iterator rEnd() { return data.rend(); }
const_reverse_iterator rBegin() const { return data.rbegin(); }
const_reverse_iterator rEnd() const { return data.rend(); }
/// Return the scalar product of the current sparse row by a dense Vector.
void RowVec(INMOST_DATA_REAL_TYPE alpha, const Row & rU, INMOST_DATA_REAL_TYPE beta, Row & rJ) const; // returns A(row) * x
void MoveRow(HessianRow & new_pos) {data = new_pos.data;} //here move constructor and std::move may be used in future
/// Set the vector entries by zeroes.
void Zero() {for(iterator it = Begin(); it != End(); ++it) it->second = 0;}
/// Push specified element into sparse row.
/// This function should be used only if the index is not repeated in the row.
void Push(index ind, INMOST_DATA_REAL_TYPE val) {data.push_back(make_entry(ind,val));}
/// Resize row to specified size.
/// It is intended to be used together with non-const Row::GetIndex and Row::GetValue
/// that allow for the modification of individual entries.
/// @param size New size of the row.
void Resize(INMOST_DATA_ENUM_TYPE size) {data.resize(size);}
void Print() const
{
for(const_iterator it = Begin(); it != End(); ++it) std::cout << "(" << it->first.first << "," << it->first.second << "," << it->second << ") ";
std::cout << std::endl;
}
bool isSorted() const;
/// output = alpha * left + beta *right
static void MergeSortedRows(INMOST_DATA_REAL_TYPE alpha, const HessianRow & left, INMOST_DATA_REAL_TYPE beta, const HessianRow & right, HessianRow & output);
static void MergeJacobianHessian(INMOST_DATA_REAL_TYPE a, const Row & JL, const Row & JR, INMOST_DATA_REAL_TYPE b, const HessianRow & HL, INMOST_DATA_REAL_TYPE c, const HessianRow & HR, HessianRow & output);
static void MergeJacobianHessian(INMOST_DATA_REAL_TYPE a, const Row & JL, const Row & JR, INMOST_DATA_REAL_TYPE b, const HessianRow & H, HessianRow & output);
};
/// Class to store the compressed symmetric matrix of a hessian row.
class HessianRow
{
public:
/// Entry of the sparse matrix row.
typedef struct hessian_index_s
{
INMOST_DATA_ENUM_TYPE first;
INMOST_DATA_ENUM_TYPE second;
bool operator < (const hessian_index_s & other) const {return first < other.first || (first == other.first && second < other.second); }
bool operator ==(const hessian_index_s & other) const {return first == other.first && second == other.second;}
} index;
__INLINE static index make_index(INMOST_DATA_ENUM_TYPE _first, INMOST_DATA_ENUM_TYPE _second)
{
index ret;
ret.first = std::min(_first,_second);
ret.second = std::max(_first,_second);
return ret;
}
typedef struct hessian_entry_s
{
index first; ///< the column number of the row element.
INMOST_DATA_REAL_TYPE second; ///< the real value of the row element.
bool operator < (const hessian_entry_s & other) const { return first < other.first || (first == other.first && second < other.second); }
} entry;
__INLINE static entry make_entry(index ind, INMOST_DATA_REAL_TYPE val)
{
entry ret;
ret.first = ind;
ret.second = val;
return ret;
}
private:
typedef array<entry> Entries; //replace later with more memory-efficient chunk_array, with first chunk in stack
//typedef dynarray<entry,8> Entries;
public:
typedef Entries::iterator iterator;
typedef Entries::const_iterator const_iterator;
typedef Entries::reverse_iterator reverse_iterator;
typedef Entries::const_reverse_iterator const_reverse_iterator;
private:
Entries data;
public:
HessianRow() : data() {}
HessianRow(const HessianRow & other) : data(other.data) {}
HessianRow(entry * pbegin, entry * pend) : data(pbegin,pend) {}
~HessianRow() {}
HessianRow & operator = (HessianRow const & other) {data = other.data; return *this;}
/// The operator [] used to fill the sparse matrix row, but not to access individual elements of the row.
INMOST_DATA_REAL_TYPE & operator [](index i) // use to fill matrix, not to access individual elements
{
for(Entries::size_type it = 0; it < data.size(); ++it)
if( data[it].first == i ) return data[it].second;
data.push_back(make_entry(i,0));
return data.back().second;
}
/// The operator [] used to access individual elements of the row.
INMOST_DATA_REAL_TYPE operator[](index i) const
{
for (Entries::size_type it = 0; it < data.size(); ++it) if (data[it].first == i) return data[it].second;
//you should not come here
assert(false);
return 1.0e20;
}
INMOST_DATA_REAL_TYPE get_safe(index i) const
{
for (Entries::size_type it = 0; it < data.size(); ++it) if (data[it].first == i) return data[it].second;
return 0.0;
}
//void Reserve(INMOST_DATA_ENUM_TYPE num) { data.reserve(num);}
/// Clear all data of the current row.
void Clear() { data.clear(); }
void Swap(HessianRow & other) { data.swap(other.data); }
/// The size of the sparse row, i.e. the total number of nonzero elements.
INMOST_DATA_ENUM_TYPE Size() const { return static_cast<INMOST_DATA_ENUM_TYPE>(