Commit 892132e3 by Kirill Terekhov

Memory pool for dense matrix operations and more

Fix compilation issue with std::isinf

Finish memory_pool implementation in container.h

Use of matrices allocated in memory pool for intermediate results in
dense linear algebra operations in inmost_dense.h

Use of memory pool for matrices in inmost_autodiff.h

Change error reporting and return type in Invert, Solve,
CholeskyInvert, CholeskySolve, PseudoInvert, PseudoSolve

Add unit tests for linear algebra on dense matrices.
parent 8a15e882
Pipeline #157 failed with stages
in 9 minutes 42 seconds
......@@ -199,9 +199,9 @@ int main(int argc,char ** argv)
NK(k,k+1,0,3) = n*K;
Areas(k,k) = area;
} //end of loop over faces
W = NK*(NK.Transpose()*R).Invert(true).first*NK.Transpose(); //stability part
W+=(rMatrix::Unit(NF) - R*(R.Transpose()*R).Invert(true).first*R.Transpose())*
(2.0/(static_cast<real>(NF)*volume)*(NK*K.Invert(true).first*NK.Transpose()).Trace());
W = NK*(NK.Transpose()*R).PseudoInvert(1.0e-12)*NK.Transpose(); //stability part
W+=(rMatrix::Unit(NF) - R*(R.Transpose()*R).CholeskyInvert()*R.Transpose())*
(2.0/(static_cast<real>(NF)*volume)*(NK*K.CholeskyInvert()*NK.Transpose()).Trace());
W = Areas*W*Areas;
//access data structure for gradient matrix in mesh
real_array store_W = cell->RealArrayDV(tag_W);
......
......@@ -249,7 +249,7 @@ bool find_stencils(Cell cK,
rK = nF.DotProduct(xF-xK);
rN = nF.DotProduct(xN-xF);
//correction due to tensor
iQ = -iC * iT.Invert(true).first;
iQ = -iC * iT.Invert();
rQ = nF.DotProduct(iQ);
//harmonic point
yS = (lambdaC*rN*(xK - iQ - rQ*nF) + lambdaN*(rK+rQ)*xN + rN*(rK+rQ)*nF*KD)/(lambdaC*rN + lambdaN*(rK+rQ));
......
......@@ -105,9 +105,6 @@ static bool BoundingEllipse(Element e, double eps, int iters, rMatrix & Q, rMatr
rMatrix M(A.Cols(), A.Cols());
std::pair<rMatrix, bool> inv, iQ;
inv.first.Resize(d + 1, d + 1);
iQ.first.Resize(d, d);
int done_iters = 0;
double n = d+1, ep , en, kp, kn, beta;
int jp,jn;
......@@ -115,9 +112,7 @@ static bool BoundingEllipse(Element e, double eps, int iters, rMatrix & Q, rMatr
{
for (int k = 0; k < p.Rows(); ++k) D(k, k) = p(k, 0);
inv = (A1*D*A1.Transpose()).Invert(true); // d+1 by d+1
if (!inv.second) return false;
M = A1.Transpose()*inv.first*A1; // m by m
M = A1.Transpose()*(A1*D*A1.Transpose()).Invert()*A1; // m by m
//std::cout << "matrix M:" << std::endl;
//M.Print();
kp = -1.0e20;
......@@ -167,9 +162,7 @@ static bool BoundingEllipse(Element e, double eps, int iters, rMatrix & Q, rMatr
}
for (int k = 0; k < p.Rows(); ++k) D(k, k) = p(k, 0);
iQ = (A*(D - p*p.Transpose())*A.Transpose()).Invert(true);
if (!iQ.second) return false;
Q = iQ.first / static_cast<double>(d);
Q = (A*(D - p*p.Transpose())*A.Transpose()).Invert() / static_cast<double>(d);
c = A*p;
//check
if (d == 2)
......@@ -686,4 +679,4 @@ int main(int argc, char ** argv)
}
m.Save(grid_out);
return 0;
}
\ No newline at end of file
}
......@@ -429,8 +429,8 @@ int main(int argc,char ** argv)
if( faces[k].BackCell() == c )
tag_i[faces[k]] = k;
} //end of loop over faces
W = N*(N.Transpose()*R).Invert(true).first*N.Transpose(); //stability part
W += (rMatrix::Unit(faces.size()) - R*(R.Transpose()*R).Invert(true).first*R.Transpose())*(4.0/(faces.size())*W.Trace());
W = N*(N.Transpose()*R).Invert()*N.Transpose(); //stability part
W += (rMatrix::Unit(faces.size()) - R*(R.Transpose()*R).Invert()*R.Transpose())*(4.0/(faces.size())*W.Trace());
} //end of loop over cells
//initialize normal velocity
......
......@@ -18,11 +18,21 @@ namespace INMOST
template<> Demote<variable>::type AbstractEntry::Access<variable> (const Storage& e, INMOST_DATA_ENUM_TYPE pos) const {return Unknown(e,pos);}
template<> Demote<hessian_variable>::type AbstractEntry::Access<hessian_variable> (const Storage& e, INMOST_DATA_ENUM_TYPE pos) const {return Unknown(e,pos);}
template<> Matrix<Demote<INMOST_DATA_REAL_TYPE>::type> AbstractEntry::Access<INMOST_DATA_REAL_TYPE> (const Storage& e) const {return Value(e);}
template<> Matrix<Demote<INMOST_DATA_INTEGER_TYPE>::type> AbstractEntry::Access<INMOST_DATA_INTEGER_TYPE>(const Storage& e) const {return Index(e);}
template<> Matrix<Demote<unknown>::type> AbstractEntry::Access<unknown> (const Storage& e) const {return Unknown(e);}
template<> Matrix<Demote<variable>::type> AbstractEntry::Access<variable> (const Storage& e) const {return Unknown(e);}
template<> Matrix<Demote<hessian_variable>::type> AbstractEntry::Access<hessian_variable> (const Storage& e) const {return Unknown(e);}
template<>
Matrix<Demote<INMOST_DATA_REAL_TYPE>::type, pool_array_t<Demote<INMOST_DATA_REAL_TYPE>::type> >
AbstractEntry::Access<INMOST_DATA_REAL_TYPE> (const Storage& e) const {return Value(e);}
template<>
Matrix<Demote<INMOST_DATA_INTEGER_TYPE>::type, pool_array_t<Demote<INMOST_DATA_INTEGER_TYPE>::type> >
AbstractEntry::Access<INMOST_DATA_INTEGER_TYPE>(const Storage& e) const {return Index(e);}
template<>
Matrix<Demote<unknown>::type, pool_array_t<Demote<unknown>::type> >
AbstractEntry::Access<unknown>(const Storage& e) const {return Unknown(e);}
template<>
Matrix<Demote<variable>::type, pool_array_t<Demote<variable>::type> >
AbstractEntry::Access<variable>(const Storage& e) const {return Unknown(e);}
template<>
Matrix<Demote<hessian_variable>::type,pool_array_t<Demote<hessian_variable>::type> >
AbstractEntry::Access<hessian_variable>(const Storage& e) const {return Unknown(e);}
#if defined(USE_MESH)
......@@ -392,9 +402,9 @@ namespace INMOST
throw Impossible;
}
rMatrix MultiEntry::Value(const Storage & e) const
rpMatrix MultiEntry::Value(const Storage & e) const
{
vMatrix ret(MatrixSize(e),1);
rpMatrix ret(MatrixSize(e),1);
unsigned l = 0, r, t;
for(unsigned k = 0; k < entries.size(); ++k) if( entries[k]->isValid(e) )
{
......@@ -405,9 +415,9 @@ namespace INMOST
return ret;
}
iMatrix MultiEntry::Index(const Storage & e) const
ipMatrix MultiEntry::Index(const Storage & e) const
{
iMatrix ret(MatrixSize(e),1);
ipMatrix ret(MatrixSize(e),1);
unsigned l = 0, r, t;
for(unsigned k = 0; k < entries.size(); ++k) if( entries[k]->isValid(e) )
{
......@@ -418,9 +428,9 @@ namespace INMOST
return ret;
}
uMatrix MultiEntry::operator [](const Storage & e) const
upMatrix MultiEntry::operator [](const Storage & e) const
{
uMatrix ret(MatrixSize(e),1);
upMatrix ret(MatrixSize(e),1);
unsigned l = 0, r, t;
for(unsigned k = 0; k < entries.size(); ++k) if( entries[k]->isValid(e) )
{
......
......@@ -523,7 +523,7 @@ namespace INMOST
replace(begin(),end(),first,last);
}
template<class> friend class shell;
};
};
#if defined(PACK_ARRAY)
#pragma pack(pop,r1)
#endif
......@@ -2837,29 +2837,366 @@ namespace INMOST
const T * operator ->() const {return &item;}
};
#endif //_OPENMP
/*
class memory_pool
{
std::vector<char> pool; ///< Data storage
static const unsigned pool_size_bits = 16;
//typedef char pool_type[pool_size];
typedef std::map<void *,unsigned> page_fault_type;
std::vector< char * > pool; ///< Data storage
std::vector<unsigned> last_alloc; ///< Last allocated block position, used to track allocation
page_fault_type page_fault;
public:
memory_pool() pool_size(0) {}
memory_pool(const memory_pool & b) : pool(b.pool), last_alloc(b.last_alloc) {}
memory_pool & operator = (memory_pool const & b) {pool = b.pool; last_alloc = b.last_alloc; return *this;}
memory_pool(){pool.push_back(new char[1 << pool_size_bits]); last_alloc.push_back(0); }
//memory_pool(const memory_pool & b) : pool(b.pool), last_alloc(b.last_alloc) {}
//memory_pool & operator = (memory_pool const & b) {pool = b.pool; last_alloc = b.last_alloc; return *this;}
template<typename T>
T * allocate(unsigned n, const T & c = T())
void * allocate(unsigned n, const T & c = T())
{
unsigned oldsize = pool.size();
pool.resize(pool_size() + sizeof(T)*n);
for(unsigned i = 0; i < n; ++i)
new (&static_cast<T *>(static_cast<void *>(&pool[oldsize]))[i]) T(c);
last_alloc.push_back(oldsize);
return &pool[oldsize];
if( sizeof(T)*n < (1 << pool_size_bits) )
{
unsigned oldpos = last_alloc.size() > 0 ? last_alloc.back() : 0;
unsigned newpos = oldpos + sizeof(T)*n;
unsigned pageold = oldpos >> pool_size_bits;
unsigned pagepos = newpos >> pool_size_bits;
unsigned datapos;
if( pagepos == pool.size() )
{
//std::cout << "position from " << oldpos << " to " << newpos << " need new page " << pagepos << std::endl;
pool.push_back(new char[1 << pool_size_bits]);
}
if( pagepos != pageold || last_alloc.empty() )
{
//std::cout << "add page " << pagepos << " start marker" << std::endl;
last_alloc.push_back(pagepos << pool_size_bits);
oldpos = last_alloc.back();
newpos = oldpos + sizeof(T)*n;
}
datapos = oldpos%(1<<pool_size_bits);
void * data = (void *)&pool[pagepos][datapos];
for(unsigned i = 0; i < n; ++i) new (&static_cast<T *>(data)[i]) T(c);
last_alloc.push_back(newpos);
//std::cout << "allocated " << sizeof(T)*n << " bytes from " << oldpos << " to " << newpos << " at page " << pagepos << " at " << data << std::endl;
//std::cout << this << " last_alloc[" << last_alloc.size() << "]:";
//for(unsigned i = 0; i < last_alloc.size(); ++i) std::cout << " " << last_alloc[i];
//std::cout << std::endl;
return data;
}
else
{
//T * data = new T[n];
//for(unsigned i = 0; i < n; ++i) data[i] = c;
void * data = malloc(sizeof(T)*n);
for(unsigned i = 0; i < n; ++i) new (&static_cast<T *>(data)[i]) T(c);
page_fault[(void *)data] = n;
//std::cout << "page fault for " << sizeof(T)*n << " bytes allocated at " << data << std::endl;
//std::cout << this << " last_alloc[" << last_alloc.size() << "]:";
//for(unsigned i = 0; i < last_alloc.size(); ++i) std::cout << " " << last_alloc[i];
//std::cout << std::endl;
return (void *)data;
}
}
template<typename T>
void deallocate
void deallocate(T * mem)
{
unsigned oldpos = last_alloc.size() > 1 ? last_alloc[last_alloc.size()-2] : 0;
unsigned newpos = last_alloc.size() > 0 ? last_alloc[last_alloc.size()-1] : 0;
unsigned pagepos = newpos >> pool_size_bits;
unsigned datapos = oldpos % (1 << pool_size_bits);
//std::cout << "deallocate " << mem << " from " << oldpos << " to " << newpos << " page " << pagepos << std::endl;
//std::cout << this << " last_alloc[" << last_alloc.size() << "]:";
//for(unsigned i = 0; i < last_alloc.size(); ++i) std::cout << " " << last_alloc[i];
//std::cout << std::endl;
if( last_alloc.size() > 1 && (((T*)&pool[pagepos][datapos]) == mem) )
{
unsigned n = (newpos - oldpos)/sizeof(T);
for(unsigned i = 0; i < n; ++i) mem[i].~T();
last_alloc.pop_back();
//std::cout << "deallocate from " << oldpos << " to " << newpos << std::endl;
if( last_alloc.back() != 0 && last_alloc.back()%(1<<pool_size_bits) == 0 )
{
//std::cout << "remove page " << (last_alloc.back() >> pool_size_bits) << " start marker " << std::endl;
last_alloc.pop_back();
}
}
else
{
page_fault_type::iterator it = page_fault.find((void *)mem);
assert(it != page_fault.end() && "deallocated block does not match neither last allocated block nor page fault");
//if(it != page_fault.end() )
//{
// std::cout << "deallocated block does not match neither last allocated block nor page fault";
// throw -1;
//}
unsigned n = it->second;
//std::cout << "deallocate page fault of " << sizeof(T)*n << " bytes at " << mem << std::endl;
//delete [] mem;
for(unsigned i = 0; i < n; ++i) mem[i].~T();
free(mem);
page_fault.erase(it);
}
}
~memory_pool()
{
if( last_alloc.back() != 0 ) std::cout << "warning: memory pool not empty on deallocation!!!" << std::endl;
for(unsigned k = 0; k < pool.size(); ++k)
delete [] pool[k];
if( !page_fault.empty() )
{
std::cout << "warning: memory pool's page fault not empty on deallocation!!!" << std::endl;
for(page_fault_type::iterator it = page_fault.begin(); it != page_fault.end(); ++it)
free(it->first);
}
}
};
//static thread_private<memory_pool> _pool;
memory_pool & get_pool();
template<typename element>//, typename enumerator = unsigned int>
class pool_array
{
public:
typedef unsigned size_type;
typedef make_unsigned<size_type>::type uenum;
template<typename etype>
class _iterator
{
private:
etype * e;
public:
typedef etype * pointer;
typedef etype & reference;
typedef etype value_type;
typedef ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
_iterator():e(NULL){}
_iterator(etype * i):e(i){}
_iterator(const _iterator & other){e = other.e;}
~_iterator() {};
_iterator operator -(size_t n) const { return _iterator(e-n); }
_iterator & operator -=(size_t n) { e-=n; return *this; }
_iterator operator +(size_t n) const { return _iterator(e+n); }
_iterator & operator +=(size_t n) { e+=n; return *this; }
_iterator & operator ++(){ ++e; return *this;}
_iterator operator ++(int){ return _iterator(e++); }
_iterator & operator --(){ --e; return *this; }
_iterator operator --(int){ return _iterator(e--); }
ptrdiff_t operator -(const _iterator & other) const {return e-other.e;}
etype & operator *() { return *e; }
const etype & operator *() const { return *e; }
etype * operator ->() { return e; }
_iterator & operator =(_iterator const & other) { e = other.e; return *this; }
bool operator ==(const _iterator & other) const { return e == other.e;}
bool operator !=(const _iterator & other) const { return e != other.e;}
bool operator <(const _iterator & other) const { return e < other.e;}
bool operator >(const _iterator & other) const { return e > other.e;}
bool operator <=(const _iterator & other) const { return e <= other.e;}
bool operator >=(const _iterator & other) const { return e >= other.e;}
operator void *() {return static_cast<void *> (e);}
operator const void *() const {return const_cast<const void *> (e);}
};
typedef _iterator<element> iterator;
typedef _iterator<const element> const_iterator;
template<typename etype>
class _reverse_iterator
{
private:
etype * e;
public:
typedef etype * pointer;
typedef etype & reference;
typedef etype value_type;
typedef ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
_reverse_iterator():e(NULL){}
_reverse_iterator(etype * i):e(i){}
_reverse_iterator(const _reverse_iterator & other){e = other.e;}
~_reverse_iterator() {};
_reverse_iterator operator -(size_t n) const { return _reverse_iterator(e+n); }
_reverse_iterator & operator -=(size_t n) { e+=n; return *this; }
_reverse_iterator operator +(size_t n) const {return _reverse_iterator(e-n); }
_reverse_iterator & operator +=(size_t n) { e-=n; return *this; }
_reverse_iterator & operator ++(){ --e; return *this;}
_reverse_iterator operator ++(int){ return _reverse_iterator(e--); }
_reverse_iterator & operator --(){ ++e; return *this; }
_reverse_iterator operator --(int){ return _reverse_iterator(e++); }
ptrdiff_t operator -(const _reverse_iterator & other) const {return other.e-e;}
etype & operator *() { return *e; }
const etype & operator *() const { return *e; }
etype * operator ->() { return e; }
_reverse_iterator & operator =(_reverse_iterator const & other) { e = other.e; return *this;}
bool operator ==(const _reverse_iterator & other) const { return e == other.e;}
bool operator !=(const _reverse_iterator & other) const { return e != other.e;}
bool operator <(const _reverse_iterator & other) const { return e < other.e;}
bool operator >(const _reverse_iterator & other) const { return e > other.e;}
bool operator <=(const _reverse_iterator & other) const { return e <= other.e;}
bool operator >=(const _reverse_iterator & other) const { return e >= other.e;}
operator void *() {return static_cast<void *> (e);}
operator const void *() const {return static_cast<const void *> (e);}
};
typedef _reverse_iterator<element> reverse_iterator;
typedef _reverse_iterator<const element> const_reverse_iterator;
private:
element * m_arr;
size_type m_size;
public:
__INLINE element * data() {return m_arr;}
__INLINE const element * data() const {return m_arr;}
pool_array()
{
m_size = 0;
m_arr = NULL;
}
pool_array(size_type n,element c = element())
{
m_size = n;
m_arr = (element *)get_pool().allocate(n,c);
assert(m_arr != NULL);
}
template<class InputIterator>
pool_array(InputIterator first, InputIterator last)
{
//isInputForwardIterators<element,InputIterator>();
m_size = static_cast<size_type>(std::distance(first,last));
m_arr = (element *)get_pool().allocate(m_size,element());
assert(m_arr != NULL);
{
size_type i = 0;
InputIterator it = first;
while(it != last) new (m_arr+i++) element(*it++);
}
}
pool_array(const pool_array & other)
{
m_size = other.m_size;
if( m_size )
{
m_arr = (element *)get_pool().allocate(m_size,element());
assert(m_arr != NULL);
}
else m_arr = NULL;
for(size_type i = 0; i < m_size; i++) new (m_arr+i) element(other.m_arr[i]);
}
~pool_array()
{
get_pool().deallocate(m_arr);
m_arr = NULL;
m_size = 0;
}
__INLINE const element & operator [] (size_type n) const
{
assert(n < m_size);
return m_arr[n];
}
__INLINE element & operator [] (size_type n)
{
assert(n < m_size);
return m_arr[n];
}
__INLINE const element & at (size_type n) const
{
assert(n < m_size);
return m_arr[n];
}
__INLINE element & at (size_type n)
{
assert(n < m_size);
return m_arr[n];
}
/*
//think what todo here
pool_array & operator =(pool_array const & other)
{
if( this != &other )
{
for(size_type i = 0; i < m_size; i++) m_arr[i].~element();
if(m_arr != NULL )
{
free(m_arr);
m_arr = NULL;
m_size = 0;
}
if( other.m_arr != NULL )
{
m_size = other.m_size;
m_arr = static_cast<element *>(malloc(sizeof(element)*growth_formula(m_size)));
assert(m_arr != NULL);
memcpy(m_arr,other.m_arr,sizeof(element)*m_size);
}
}
return *this;
}
*/
void resize(size_type n, element c = element())
{
if( m_size == 0 && m_arr == NULL )
{
m_arr = (element *)get_pool().allocate(n,c);
assert(m_arr != NULL);
m_size = n;
}
else if( n != m_size )
{
assert(false && "resize of non-empty pool_array");
}
}
__INLINE element & back()
{
assert(m_arr != NULL);
assert(m_size > 0);
return m_arr[m_size-1];
}
__INLINE const element & back() const
{
assert(m_arr != NULL);
assert(m_size > 0);
return m_arr[m_size-1];
}
__INLINE element & front()
{
assert(m_arr != NULL);
assert(m_size > 0);
return m_arr[0];
}
__INLINE const element & front() const
{
assert(m_arr != NULL);
assert(m_size > 0);
return m_arr[0];
}
__INLINE size_type capacity() { return m_size; }
__INLINE bool empty() const { if( m_size ) return false; return true; }
__INLINE size_type size() const {return m_size;}
__INLINE size_type capacity() const {return m_size;}
void clear()
{
get_pool().deallocate(m_arr);
m_arr = NULL;
m_size = 0;
}
void swap(pool_array<element> & other)
{
element * t_m_arr = m_arr;
size_type t_m_size = m_size;
m_arr = other.m_arr;
m_size = other.m_size;
other.m_arr = t_m_arr;
other.m_size = t_m_size;
}
__INLINE iterator begin() { return m_arr; }
__INLINE iterator end() { return m_arr+m_size; }
__INLINE const_iterator begin() const { return m_arr; }
__INLINE const_iterator end() const { return m_arr+m_size; }
__INLINE reverse_iterator rbegin() { return reverse_iterator(m_arr+m_size-1); }
__INLINE reverse_iterator rend() { return reverse_iterator(m_arr-1); }
__INLINE const_reverse_iterator rbegin() const { return const_reverse_iterator(m_arr+m_size-1); }
__INLINE const_reverse_iterator rend() const { return const_reverse_iterator(m_arr-1); }
};
*/
}
#endif
......@@ -63,20 +63,24 @@ namespace INMOST
/// @param pos Position for which to extract the unknown, should be no larger then MatrixSize.
virtual unknown Unknown(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const = 0;
/// Return vector filled with values of unknowns of the block.
virtual rMatrix Value(const Storage & e) const = 0;
virtual rpMatrix Value(const Storage & e) const = 0;
/// Return vector filled with indices of unknowns of the block.
virtual iMatrix Index(const Storage & e) const = 0;
virtual ipMatrix Index(const Storage & e) const = 0;
/// Return vector filled with unknowns of the block with their derivatives.
virtual uMatrix Unknown(const Storage & e) const = 0;
virtual upMatrix Unknown(const Storage & e) const = 0;
/// Return vector filled with either values or indices or unknowns of the block,
/// depending on the template parameter.
template<typename T> Matrix<typename Demote<T>::type> Access(const Storage &e) const;
template<typename T>
Matrix<typename Demote<T>::type, pool_array_t<typename Demote<T>::type> >
Access(const Storage &e) const;
/// Return either value or index or unknown at specified position of the block,
/// depending on the template parameter.
/// @param pos Position in the block, should be no larger then MatrixSize.
template<typename T> typename Demote<T>::type Access(const Storage &e, INMOST_DATA_ENUM_TYPE pos) const;
template<typename T>
typename Demote<T>::type
Access(const Storage &e, INMOST_DATA_ENUM_TYPE pos) const;
/// Return vector filled with unknowns of the block with their derivatives.
virtual uMatrix operator [](const Storage & e) const = 0;
virtual upMatrix operator [](const Storage & e) const = 0;
/// The intended size of the matrix for this entry.
virtual INMOST_DATA_ENUM_TYPE MatrixSize(const Storage & e) const = 0;
/// Number of tags in block.
......@@ -131,13 +135,13 @@ namespace INMOST
/// Return unknown in vector of variables of the block at certain position.
unknown Unknown(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const {return unknown(Value(e,pos),Index(e,pos));}
/// Return vector filled with values of unknowns of the block.
rMatrix Value(const Storage & e) const {rMatrix ret(MatrixSize(e),1); for(unsigned k = 0; k < Size(); ++k) ret(k,0) = Value(e,k); return ret; }
rpMatrix Value(const Storage & e) const {rpMatrix ret(MatrixSize(e),1); for(unsigned k = 0; k < Size(); ++k) ret(k,0) = Value(e,k); return ret; }
/// Return vector filled with indices of unknowns of the block.
iMatrix Index(const Storage & e) const {iMatrix ret(MatrixSize(e),1); for(unsigned k = 0; k < Size(); ++k) ret(k,0) = Index(e,k); return ret; }
ipMatrix Index(const Storage & e) const {ipMatrix ret(MatrixSize(e),1); for(unsigned k = 0; k < Size(); ++k) ret(k,0) = Index(e,k); return ret; }
/// Return vector filled with unknowns of the block with their derivatives.
uMatrix Unknown(const Storage & e) const {return BlockEntry::operator [](e);}
upMatrix Unknown(const Storage & e) const {return BlockEntry::operator [](e);}
/// Return vector filled with unknowns of the block with their derivatives.
uMatrix operator [](const Storage & e) const {uMatrix ret(MatrixSize(e),1); for(unsigned k = 0; k < Size(); ++k) ret(k,0) = Unknown(e,k); return ret; }
upMatrix operator [](const Storage & e) const {upMatrix ret(MatrixSize(e),1); for(unsigned k = 0; k < Size(); ++k) ret(k,0) = Unknown(e,k); return ret; }
/// The intended size of the matrix for this entry.
INMOST_DATA_ENUM_TYPE MatrixSize(const Storage & e) const {(void)e; return Size();}
/// Number of tags in block.
......@@ -174,13 +178,13 @@ namespace INMOST
/// Return unknown in vector of variables of the block at certain position.
unknown Unknown(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const {assert(pos==0); return unknown(Value(e,pos),Index(e,pos));}
/// Return vector filled with values of unknowns of the block.
rMatrix Value(const Storage & e) const { rMatrix ret(1,1); ret(0,0) = Value(e,0); return ret; }
rpMatrix Value(const Storage & e) const { rpMatrix ret(1,1); ret(0,0) = Value(e,0); return ret; }
/// Return vector filled with indices of unknowns of the block.
iMatrix Index(const Storage & e) const { iMatrix ret(1,1); ret(0,0) = Index(e,0); return ret; }
ipMatrix Index(const Storage & e) const { ipMatrix ret(1,1); ret(0,0) = Index(e,0); return ret; }
/// Return vector filled with unknowns of the block with their derivatives.
uMatrix Unknown(const Storage & e) const {return SingleEntry::operator [](e);}
upMatrix Unknown(const Storage & e) const {return SingleEntry::operator [](e);}
/// Return vector filled with unknowns of the block with their derivatives.
uMatrix operator [](const Storage & e) const { uMatrix ret(1,1); ret(0,0) = Unknown(e,0); return ret; }
upMatrix operator [](const Storage & e) const { upMatrix ret(1,1); ret(0,0) = Unknown(e,0); return ret; }
/// The intended size of the matrix for this entry.
INMOST_DATA_ENUM_TYPE MatrixSize(const Storage & e) const {(void)e; return 1;}
/// Number of tags in block.
......@@ -216,13 +220,13 @@ namespace INMOST
/// Return unknown in vector of variables of the block at certain position.
unknown Unknown(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const {assert(pos<unknown_tag[e].size()); return unknown(Value(e,pos),Index(e,pos));}
/// Return vector filled with values of unknowns of the block.
rMatrix Value(const Storage & e) const { rMatrix ret(MatrixSize(e),1); for(int k = 0; k < (int)unknown_tag[e].size(); ++k) ret(k,0) = Value(e,k); return ret; }
rpMatrix Value(const Storage & e) const { rpMatrix ret(MatrixSize(e),1); for(int k = 0; k < (int)unknown_tag[e].size(); ++k) ret(k,0) = Value(e,k); return ret; }
/// Return vector filled with indices of unknowns of the block.
iMatrix Index(const Storage & e) const { iMatrix ret(MatrixSize(e),1); for(int k = 0; k < (int)unknown_tag[e].size(); ++k) ret(k,0) = Index(e,k); return ret; }
ipMatrix Index(const Storage & e) const { ipMatrix ret(MatrixSize(e),1); for(int k = 0; k < (int)unknown_tag[e].size(); ++k) ret(k,0) = Index(e,k); return ret; }
/// Return vector filled with unknowns of the block with their derivatives.
uMatrix Unknown(const Storage & e) const {return VectorEntry::operator [](e);}
upMatrix Unknown(const Storage & e) const {return VectorEntry::operator [](e);}
/// Return vector filled with unknowns of the block with their derivatives.
uMatrix operator [](const Storage & e) const { uMatrix ret(MatrixSize(e),1); for(int k = 0; k < (int)unknown_tag[e].size(); ++k) ret(0,0) = Unknown(e,k); return ret; }
upMatrix operator [](const Storage & e) const { upMatrix ret(MatrixSize(e),1); for(int k = 0; k < (int)unknown_tag[e].size(); ++k) ret(0,0) = Unknown(e,k); return ret; }
/// The intended size of the matrix for this entry.
INMOST_DATA_ENUM_TYPE MatrixSize(const Storage & e) const {return (INMOST_DATA_ENUM_TYPE)unknown_tag[e].size();}
/// Number of tags in block.
......@@ -272,13 +276,13 @@ namespace INMOST
/// Return unknown in vector of variables of the block at certain position.
unknown Unknown(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const {return unknown(Value(e,pos),Index(e,pos));}
/// Return vector filled with values of unknowns of the block.
rMatrix Value(const Storage & e) const {rMatrix ret(MatrixSize(e),1); for(INMOST_DATA_ENUM_TYPE k = 0; k < Size(); ++k) ret(k,0) = Value(e,k); return ret; }
rpMatrix Value(const Storage & e) const {rpMatrix ret(MatrixSize(e),1); for(INMOST_DATA_ENUM_TYPE k = 0; k < Size(); ++k) ret(k,0) = Value(e,k); return ret; }
/// Return vector filled with indices of unknowns of the block.
iMatrix Index(const Storage & e) const {iMatrix ret(MatrixSize(e),1); for(INMOST_DATA_ENUM_TYPE k = 0; k < Size(); ++k) ret(k,0) = Index(e,k); return ret; }
ipMatrix Index(const Storage & e) const {ipMatrix ret(MatrixSize(e),1); for(INMOST_DATA_ENUM_TYPE k = 0; k < Size(); ++k) ret(k,0) = Index(e,k); return ret; }
/// Return vector filled with unknowns of the block with their derivatives.
uMatrix Unknown(const Storage & e) const {return StatusBlockEntry::operator [](e);}
upMatrix Unknown(const Storage & e) const {return StatusBlockEntry::operator [](e);}
/// Return vector filled with unknowns of the block with their derivatives.
uMatrix operator [](const Storage & e) const {uMatrix ret(MatrixSize(e),1); for(INMOST_DATA_ENUM_TYPE k = 0; k < Size(); ++k) ret(k,0) = Unknown(e,k); return ret; }
upMatrix operator [](const Storage & e) const {upMatrix ret(MatrixSize(e),1); for(INMOST_DATA_ENUM_TYPE k = 0; k < Size(); ++k) ret(k,0) = Unknown(e,k); return ret; }
/// The intended size of the matrix for this entry.
INMOST_DATA_ENUM_TYPE MatrixSize(const Storage & e) const {(void)e; return Size();}
/// Number of tags in block.
......@@ -325,13 +329,13 @@ namespace INMOST
/// Return unknown in vector of variables of the block at certain position.
unknown Unknown(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const;
/// Return vector filled with values of unknowns of the block.
rMatrix Value(const Storage & e) const;
rpMatrix Value(const Storage & e) const;
/// Return vector filled with indices of unknowns of the block.
iMatrix Index(const Storage & e) const;
ipMatrix Index(const Storage & e) const;
/// Return vector filled with unknowns of the block with their derivatives.
uMatrix Unknown(const Storage & e) const {return MultiEntry::operator [](e);}
upMatrix Unknown(const Storage & e) const {return MultiEntry::operator [](e);}
/// Return vector filled with unknowns of the block with their derivatives.
uMatrix operator [](const Storage & e) const;
upMatrix operator [](const Storage & e) const;
/// The intended size of the matrix for this entry.
INMOST_DATA_ENUM_TYPE MatrixSize(const Storage & e) const;
/// Number of tags in block.
......
......@@ -433,11 +433,11 @@ namespace INMOST