Memory Leak in SymMatrixBlock - c++

I am trying to use a symMatrixBlock representation for the cloth simulation.
The following class stores a symmetric matrix nxn who's each element is a 3x3 matrix (represented as Mat33 class)
class SymMatrixBlocks
{
public:
int size;
int *rowstart;
std::vector<int> col_lookup;
std::vector<Mat33 *> matBlock;
bool bAllZero;
public:
SymMatrixBlocks(int size);
SymMatrixBlocks(const SymMatrixBlocks &src);
~SymMatrixBlocks();
void Zero(void);
SymMatrixBlocks& operator=(const SymMatrixBlocks &src);
SymMatrixBlocks& operator+=(const SymMatrixBlocks &src);
SymMatrixBlocks& operator-=(const SymMatrixBlocks &src);
SymMatrixBlocks& operator*=(double con);
Mat33* getMatBlock(int row, int col);
void SetDiag(DiagonalMatrix &src, DiagonalMatrix &ret);
void print();
Mat33* operator() (int row, int col);
};
inline const SymMatrixBlocks operator +(const SymMatrixBlocks &lhs, const SymMatrixBlocks &rhs)
{
return SymMatrixBlocks(lhs) += rhs;
}
inline const SymMatrixBlocks operator -(const SymMatrixBlocks &lhs, const SymMatrixBlocks &rhs)
{
return SymMatrixBlocks(lhs) -= rhs;
}
inline const SymMatrixBlocks operator *(const SymMatrixBlocks &lhs, double rhs)
{
return SymMatrixBlocks(lhs) *= rhs;
}
inline const SymMatrixBlocks operator *(double lhs, const SymMatrixBlocks &rhs)
{
return SymMatrixBlocks(rhs) *= lhs;
}
}
SymMatrixBlocks& SymMatrixBlocks::operator+=(const SymMatrixBlocks &src)
{
if (size != src.size)
return *this;
if (src.bAllZero)
return *this;
int i, j, start, length;
for (i = 0; i<src.size; i++)
{
start = src.rowstart[i];
length = src.rowstart[i + 1] - start;
for (j = 0; j<length; j++)
(*((*this)(i, src.col_lookup[start + j]))) += (*(src.matBlock[start + j]));
}
return *this;
}
Mat33* SymMatrixBlocks::operator() (int row, int col)
{
int i, start, l, length;
bAllZero = false;
if (row > col)
{
start = row;
row = col;
col = start;
}
start = rowstart[row];
length = rowstart[row + 1] - start;
for (l = 0; l<length; l++)
if (col_lookup[start + l] == col)
break;
if ((length != 0) && (l != length))
{
return matBlock[start + l];
}
else
{
for (l = 0; l<length; l++)
if (col_lookup[start + l] >= col)
break;
col_lookup.insert(col_lookup.begin() + start + l, col);
Mat33 *tempmat = new Mat33();
matBlock.insert(matBlock.begin() + start + l, tempmat);
for (i = row + 1; i <= size; i++)
rowstart[i]++;
return matBlock[start + l];
}
}
when I run the following line it gives memory leakage. Can anyone spot it out?
*tm1 = *df_dx * h; // all these are object of the SymMtrixBlocks class.

Related

Purpose of custom BitSet implementation in this Leetcode answer

Last night I was working on the "Longest Palindromic Subsequence" problem on leetcode. After completing it I took a look at the fastest answer, and to my surprise it was a giant custom bitset implementation. I decided to try and reverse engineer it a bit and see if I could implement it using std::bitset, but I've run into some issues.
Here's the code:
#if __cplusplus>199711L //c++11
#include<unordered_map>
#endif
const int N=1005;
template<int S>
struct BitSet{
#define W 6
#define mask 63
#define get_size(n) ((n)<1?0:((n)+mask)>>W)
typedef unsigned long long uint; //typedef unsigned int uint;
uint a[get_size(S)];int size;
void reset(){memset(a,0,sizeof(uint)*size);}
BitSet():size(get_size(S)){reset();}
BitSet(uint x):size(get_size(S)){reset();a[0]=x;}
BitSet(const BitSet<S> &x):size(get_size(S)){*this=x;}
BitSet& set(int x,int y){
//if (y<0||y>1){printf("error!\n");return *this;}
int X=x>>W,Y=x&mask;
if (y)a[X]|=1ull<<Y;else a[X]&=~(1ull<<Y);
return *this;
}
int find(int x){int X=x>>W,Y=x&mask;return (a[X]>>Y)&1ull;}
int operator [](int x){return find(x);}
BitSet& operator =(const BitSet &y){
memcpy(a,y.a,sizeof(uint)*size);
return *this;
}
BitSet<S> operator |(const BitSet<S> &y)const{return BitSet<S>(*this)|=y;}
BitSet<S> operator &(const BitSet<S> &y)const{return BitSet<S>(*this)&=y;}
BitSet<S> operator ^(const BitSet<S> &y)const{return BitSet<S>(*this)^=y;}
BitSet<S> operator +(const BitSet<S> &y)const{return BitSet<S>(*this)+=y;}
BitSet<S> operator -(const BitSet<S> &y)const{return BitSet<S>(*this)-=y;}
BitSet<S> operator <<(int x)const{return BitSet<S>(*this)<<=x;}
BitSet<S> operator >>(int x)const{return BitSet<S>(*this)>>=x;}
BitSet<S> operator ~()const{return BitSet<S>(*this).flip();}
BitSet<S>& operator =(const char *s){
memset(a,0,sizeof(uint)*size);
for (int i=0;i<S;++i){
if (s[i]!='0'&&s[i]!='1')break;
int X=i>>W,Y=i&mask;
if (s[i]=='1')a[X]|=1ull<<Y;
}
return *this;
}
BitSet<S>& operator =(const int *s){
memset(a,0,sizeof(uint)*size);
for (int i=0;i<S;++i){
if (s[i]!=0&&s[i]!=1)break;
int X=i>>W,Y=i&mask;
if (s[i]==1)a[X]|=1ull<<Y;
}
return *this;
}
BitSet<S>& operator <<=(int x){
int shift=x>>W; int delta=x&mask,delta1=mask+1-delta;
if (!x)return *this;
if (delta==0)for (uint *p=a+size-1,*q=p-shift,*end=a+shift-1;p!=end;--p,--q)*p=*q;
else {
for (uint *p=a+size-1,*q1=p-shift,*q2=p-shift-1,*end=a+shift;p!=end;--p,--q1,--q2)*p=(*q1<<delta)|(*q2>>delta1);
a[shift]=a[0]<<delta;
}
memset(a,0,sizeof(uint)*shift); //for (uint *p=a,*end=a+shift;p!=end;++p)*p=0;
return *this;
}
BitSet<S>& operator >>=(int x){
int shift=x>>W; int delta=x&mask,delta1=mask+1-delta;
if (!x)return *this;
correction();
if (delta==0)for (uint *p=a,*q=p+shift,*end=a+size-shift;p!=end;++p,++q)*p=*q;
else {
for (uint *p=a,*q1=p+shift,*q2=p+shift+1,*end=a+size-shift-1;p!=end;++p,++q1,++q2)*p=(*q1>>delta)|(*q2<<delta1);
a[size-shift-1]=a[size-1]>>delta;
}
memset(a+size-shift,0,sizeof(uint)*shift);
return *this;
}
BitSet<S>& operator |=(const BitSet<S> &y){
uint *startA=a;const uint *startB=y.a,*endA=a+size;
while (startA!=endA){*startA|=*startB;++startA;++startB;}
//for (int i=0;i<size;++i)a[i]|=y.a[i];
return *this;
}
/*BitSet<S>& operator |=(const BitSet<S> &y){
uint *p0=a,*p1=p0+1,*p2=p0+2,*p3=p0+3;const uint *q0=y.a,*q1=q0+1,*q2=q0+2,*q3=q0+3,*pend=a+((size>>2)<<2);
while (p0!=pend){
*p0|=*q0; p0+=4; q0+=4;
*p1|=*q1; p1+=4; q1+=4;
*p2|=*q2; p2+=4; q2+=4;
*p3|=*q3; p3+=4; q3+=4;
}
for (int i=0;i<(size&3);++i)*p0++|=*q0++;
return *this;
}*/
BitSet<S>& operator &=(const BitSet<S> &y){
uint *startA=a;const uint *startB=y.a,*endA=a+size;
while (startA!=endA){*startA&=*startB;++startA;++startB;}
return *this;
}
BitSet<S>& operator ^=(const BitSet<S> &y){
uint *startA=a;const uint *startB=y.a,*endA=a+size;
while (startA!=endA){*startA^=*startB;++startA;++startB;}
return *this;
}
BitSet<S>& operator +=(const BitSet<S> &y){
uint t=0,*p=a,*end=a+size; const uint *q=y.a;
while (p!=end){
uint p1=*p; *p=p1+*q+t;
t=(*p<p1)||(p1+t<t);
++p; ++q;
}
return *this;
}
BitSet<S>& operator -=(const BitSet<S> &y){
uint t=0,*p=a,*end=a+size; const uint *q=y.a;
while (p!=end){
uint p1=*p; *p=p1-*q-t;
t=(*p>p1)||(p1+t<t);
++p; ++q;
}
return *this;
}
operator bool(){return count()>0;}
BitSet<S>& flip(){
//for (uint *start=a,*end=a+size;start!=end;*start=~*start,++start);
uint *p0=a,*p1=p0+1,*p2=p0+2,*p3=p0+3,*pend=a+((size>>2)<<2);
while (p0!=pend){
*p0=~*p0; p0+=4;
*p1=~*p1; p1+=4;
*p2=~*p2; p2+=4;
*p3=~*p3; p3+=4;
}
for (int i=0;i<(size&3);++i,++p0)*p0=~*p0;
return *this;
}
//void flip(){*this=~*this;}
void flip(int x){a[x>>W]^=1ull<<(x&mask);}
int popcount(uint x)const{
x-=(x&0xaaaaaaaaaaaaaaaaull)>>1;
x=((x&0xccccccccccccccccull)>>2)+(x&0x3333333333333333ull);
x=((x>>4)+x)&0x0f0f0f0f0f0f0f0full;
return (x*0x0101010101010101ull)>>56;
}
int count(){
int res=0;
correction();
for (int i=0;i<size;++i)res+=__builtin_popcountll(a[i]); //popcount
return res;
}
int clz(){
correction();
int res=0;
if (a[size-1])res=__builtin_clzll(a[size-1])-(mask+1-(S&mask));
else {
res+=S&mask;
for (int i=size-2;i>=0;--i)
if (a[i]){res+=__builtin_clzll(a[i]); break;}
else res+=mask+1;
}
return res;
}
int ctz(){
correction();
int res=0;
for (int i=0;i<size;++i)
if (a[i]){res+=__builtin_ctzll(a[i]); break;}
else res+=mask+1;
return min(res,S);
}
int ffs(){
int res=ctz()+1;
if (res==S+1)res=0;
return res;
}
uint to_uint(){
correction();
return a[0];
}
void print(){
for (int i=0;i<size;++i)
for (int j=0;j<=mask&&(i<<W)+j+1<=S;++j)printf("%I64d",(a[i]>>j)&1ull);
printf("\n");
}
void correction(){if (S&mask)a[size-1]&=(1ull<<(S&mask))-1;}
#undef mask
#undef W
#undef get_size
};
int a[N],b[N];
BitSet<N> row[2],X,Y;
unordered_map<int,vector<int> > S;
unordered_map<int,BitSet<N> > match;
class Solution {
public:
int longestPalindromeSubseq(string s) {
int n=s.size(),m=n;
S.clear();match.clear();row[1].reset();
for (int i=0;i<n;++i)a[i]=int(s[i]),S[a[i]].push_back(i);
for (int i=0;i<m;++i)b[i]=int(s[n-1-i]);
for (int i=0;i<m;++i)if (match.find(b[i])==match.end()){
unordered_map<int,BitSet<N> >::iterator x=match.insert(make_pair(b[i],BitSet<N>())).first;
for (vector<int>::iterator j=S[b[i]].begin();j!=S[b[i]].end();++j)x->second.set(*j,1);
}
for (int i=0,now=0;i<m;++i,now^=1)
X=(row[now^1]|match[b[i]]).set(n,1),row[now]=(X&((X-(row[now^1]<<1).set(0,1))^X)).set(n,0);
return row[(m-1)&1].count();
}
};
And here's my attempt at cleaning it up/understanding it:
Bitset.h:
#pragma once
//#if __cplusplus>199711L //c++11
#include<unordered_map>
//#endif
#include <intrin.h>
const int N = 1005; //this size doesn't even matter?? It's just enigmatically assigning a type of int, I guess??
template<int S>
struct BitSet {
#define W 6
#define mask 63
#define get_size(n) ((n)<1?0:((n)+mask)>>W)
//members
typedef unsigned long long uint; //typedef unsigned int uint; //not sure why they didn't just use size_t here...
uint a[get_size(S)]; //represents the "BitSet" I think...
int size;
//constructors
BitSet() :size(get_size(S)) { reset(); }
BitSet(uint x) :size(get_size(S)) { reset(); a[0] = x; }
BitSet(const BitSet<S>& x) :size(get_size(S)) { *this = x; }
//utility functions
BitSet& set(int x, int y) {
//if (y<0||y>1){printf("error!\n");return *this;}
int X = x >> W, Y = x & mask; //bit shift with the magic numbers??? //What is the significance of 6, 63, and 1005?
if (y)a[X] |= 1ull << Y; else a[X] &= ~(1ull << Y);
return *this;
}
void reset() { memset(a, 0, sizeof(uint) * size); }
int find(int x) { int X = x >> W, Y = x & mask; return (a[X] >> Y) & 1ull; }
//void flip(){*this=~*this;}
void flip(int x) { a[x >> W] ^= 1ull << (x & mask); }
int popcount(uint x)const {
x -= (x & 0xaaaaaaaaaaaaaaaaull) >> 1;
x = ((x & 0xccccccccccccccccull) >> 2) + (x & 0x3333333333333333ull);
x = ((x >> 4) + x) & 0x0f0f0f0f0f0f0f0full;
return (x * 0x0101010101010101ull) >> 56;
}
int count() {
int res = 0;
correction();
for (int i = 0; i < size; ++i)res += __popcnt(a[i]); //popcount // __builtin_popcountll is only available on GCC apparently. Substituted with library version.
return res;
}
int clz() {
correction();
int res = 0;
if (a[size - 1])res = __builtin_clzll(a[size - 1]) - (mask + 1 - (S & mask));
else {
res += S & mask;
for (int i = size - 2; i >= 0; --i)
if (a[i]) { res += __builtin_clzll(a[i]); break; }
else res += mask + 1;
}
return res;
}
int ctz() {
correction();
int res = 0;
for (int i = 0; i < size; ++i)
if (a[i]) { res += __builtin_ctzll(a[i]); break; }
else res += mask + 1;
return min(res, S);
}
int ffs() {
int res = ctz() + 1;
if (res == S + 1)res = 0;
return res;
}
uint to_uint() {
correction();
return a[0];
}
void print() {
for (int i = 0; i < size; ++i)
for (int j = 0; j <= mask && (i << W) + j + 1 <= S; ++j)printf("%I64d", (a[i] >> j) & 1ull);
printf("\n");
}
void correction() { if (S & mask)a[size - 1] &= (1ull << (S & mask)) - 1; }
BitSet<S>& flip() {
//for (uint *start=a,*end=a+size;start!=end;*start=~*start,++start);
uint* p0 = a, * p1 = p0 + 1, * p2 = p0 + 2, * p3 = p0 + 3, * pend = a + ((size >> 2) << 2);
while (p0 != pend) {
*p0 = ~*p0; p0 += 4;
*p1 = ~*p1; p1 += 4;
*p2 = ~*p2; p2 += 4;
*p3 = ~*p3; p3 += 4;
}
for (int i = 0; i < (size & 3); ++i, ++p0)*p0 = ~*p0;
return *this;
}
//operators
int operator [](int x) { return find(x); }
BitSet& operator =(const BitSet& y) {
memcpy(a, y.a, sizeof(uint) * size);
return *this;
}
BitSet<S>& operator =(const char* s) {
memset(a, 0, sizeof(uint) * size);
for (int i = 0; i < S; ++i) {
if (s[i] != '0' && s[i] != '1')break;
int X = i >> W, Y = i & mask;
if (s[i] == '1')a[X] |= 1ull << Y;
}
return *this;
}
BitSet<S>& operator =(const int* s) {
memset(a, 0, sizeof(uint) * size);
for (int i = 0; i < S; ++i) {
if (s[i] != 0 && s[i] != 1)break;
int X = i >> W, Y = i & mask;
if (s[i] == 1)a[X] |= 1ull << Y;
}
return *this;
}
BitSet<S> operator |(const BitSet<S>& y)const { return BitSet<S>(*this) |= y; }
BitSet<S> operator &(const BitSet<S>& y)const { return BitSet<S>(*this) &= y; }
BitSet<S> operator ^(const BitSet<S>& y)const { return BitSet<S>(*this) ^= y; }
BitSet<S> operator +(const BitSet<S>& y)const { return BitSet<S>(*this) += y; }
BitSet<S> operator -(const BitSet<S>& y)const { return BitSet<S>(*this) -= y; }
BitSet<S> operator <<(int x)const { return BitSet<S>(*this) <<= x; }
BitSet<S> operator >>(int x)const { return BitSet<S>(*this) >>= x; }
BitSet<S> operator ~()const { return BitSet<S>(*this).flip(); }
BitSet<S>& operator <<=(int x) {
int shift = x >> W; int delta = x & mask, delta1 = mask + 1 - delta;
if (!x)return *this;
if (delta == 0)for (uint* p = a + size - 1, *q = p - shift, *end = a + shift - 1; p != end; --p, --q)*p = *q;
else {
for (uint* p = a + size - 1, *q1 = p - shift, *q2 = p - shift - 1, *end = a + shift; p != end; --p, --q1, --q2)*p = (*q1 << delta) | (*q2 >> delta1);
a[shift] = a[0] << delta;
}
memset(a, 0, sizeof(uint) * shift); //for (uint *p=a,*end=a+shift;p!=end;++p)*p=0; //if this is a left shift... why is it setting the beginning of the "a" array to 0???... unless the damn array is "backwards". Sheesh.
//wait... this is a right shift according to https://orthallelous.wordpress.com/2019/10/24/magic-numbers-encoding-truth-tables-into-giant-single-values/ ... fuck.
return *this;
}
BitSet<S>& operator >>=(int x) {
int shift = x >> W; int delta = x & mask, delta1 = mask + 1 - delta;
if (!x)return *this;
correction();
if (delta == 0)for (uint* p = a, *q = p + shift, *end = a + size - shift; p != end; ++p, ++q)*p = *q;
else {
for (uint* p = a, *q1 = p + shift, *q2 = p + shift + 1, *end = a + size - shift - 1; p != end; ++p, ++q1, ++q2)*p = (*q1 >> delta) | (*q2 << delta1);
a[size - shift - 1] = a[size - 1] >> delta;
}
memset(a + size - shift, 0, sizeof(uint) * shift);
return *this;
}
BitSet<S>& operator |=(const BitSet<S>& y) {
uint* startA = a; const uint* startB = y.a, * endA = a + size;
while (startA != endA) { *startA |= *startB; ++startA; ++startB; }
//for (int i=0;i<size;++i)a[i]|=y.a[i];
return *this;
}
/*BitSet<S>& operator |=(const BitSet<S> &y){
uint *p0=a,*p1=p0+1,*p2=p0+2,*p3=p0+3;const uint *q0=y.a,*q1=q0+1,*q2=q0+2,*q3=q0+3,*pend=a+((size>>2)<<2);
while (p0!=pend){
*p0|=*q0; p0+=4; q0+=4;
*p1|=*q1; p1+=4; q1+=4;
*p2|=*q2; p2+=4; q2+=4;
*p3|=*q3; p3+=4; q3+=4;
}
for (int i=0;i<(size&3);++i)*p0++|=*q0++;
return *this;
}*/
BitSet<S>& operator &=(const BitSet<S>& y) {
uint* startA = a; const uint* startB = y.a, * endA = a + size;
while (startA != endA) { *startA &= *startB; ++startA; ++startB; }
return *this;
}
BitSet<S>& operator ^=(const BitSet<S>& y) {
uint* startA = a; const uint* startB = y.a, * endA = a + size;
while (startA != endA) { *startA ^= *startB; ++startA; ++startB; }
return *this;
}
BitSet<S>& operator +=(const BitSet<S>& y) {
uint t = 0, * p = a, * end = a + size; const uint* q = y.a;
while (p != end) {
uint p1 = *p; *p = p1 + *q + t;
t = (*p < p1) || (p1 + t < t);
++p; ++q;
}
return *this;
}
BitSet<S>& operator -=(const BitSet<S>& y) {
uint t = 0, * p = a, * end = a + size; const uint* q = y.a;
while (p != end) {
uint p1 = *p; *p = p1 - *q - t;
t = (*p > p1) || (p1 + t < t);
++p; ++q;
}
return *this;
}
operator bool() { return count() > 0; }
#undef mask
#undef W
#undef get_size
};
LeetCode516.cpp
// LeetCode516.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <iostream>
#include "BitSet.h"
#include <bitset>
// If parameter is not true, test fails
// This check function would be provided by the test framework
#define IS_TRUE(x) { if (!x) std::cout << __FUNCTION__ << " failed on line " << __LINE__ << std::endl; else std::cout << __FUNCTION__ << " passed" << std:: endl;}
int longestPalindromeSubseq(std::string s) {
int a[N] = { 0 }, b[N] = { 0 }; //2 integer arrays - initialzing to 0 isn't necessary, but seems to make the debug output more readable?
BitSet<N> row[2], X, Y; //3 bitsets... one of them is actually 2 (lol)
std::unordered_map<int, std::vector<int>> S; //This map tracks the number of occurrences of each letter?
std::unordered_map<int, BitSet<N>> match;
int n = s.size(), m = n;
S.clear();
match.clear();
//row[1].reset(); //WTF is this? Garbage.
//For each piece of the string, cast it from a char to an int and shove it in the first array, then push back a copy of each array into the UOMap S.
for (int i = 0; i < n; ++i) {
a[i] = static_cast<int>(s[i]); //changed C-style cast to static_cast
S[a[i]].push_back(i);
}
//Set the second array to a backwards copy of A I guess? (while converting the characters to integers ofc)
for (int i = 0; i < m; ++i) {
b[i] = int(s[n - 1 - i]);
}
for (int i = 0; i < m; ++i) {
//so if it's the first loop iteration or the find (working on the "backwards" array) matches the end, do this:
if (match.find(b[i]) == match.end()) { //how does this even run the first time? Match is getting cleared and never set? I guess it's working because "find(b[i])" and "end()" are both 0? - Kind of - turns out that if the find function fails, it returns "end"...
//Insert a new bitset with a "key" of "b[i]" into the match map.
auto x = match.insert(std::make_pair(b[i], BitSet<N>())).first; // replaced std::unordered_map<int, BitSet<N> >::iterator with auto... that's nice.
//Then using the iterator we just created above, loop through all entries in UOMap S under that key and ???
//Since we found it in "match", lets check for it(?) in UOMap S... and then set some bit in match based on how many entries there are in S?
for (auto j = S[b[i]].begin(); j != S[b[i]].end(); ++j) {
x->second.set(*j, 1); //this is setting some bit value in "match" to 1 I guess.
}
}
}
for (int i = 0, now = 0; i < m; ++i, now ^= 1) { //Is "*=" being intentionally obfuscated here to "^=" or is it actually different?? Ugh... nasty.
X = (row[now ^ 1] | match[b[i]]).set(n, 1); // if the caret is supposed to represent XOR, why does this still work whenever I replace it with a *... very funky.
row[now] = (X & ((X - (row[now ^ 1] << 1).set(0, 1)) ^ X)).set(n, 0);
}
return row[(m - 1) & 1].count();
}
template<int S>
std::bitset<S>& operator-(const std::bitset<S>&y) { return std::bitset<S>(*this) -= y; }
#define W 6
#define mask 63
#define get_size(n) ((n)<1?0:((n)+mask)>>W)
template<size_t S>
std::bitset<S>& operator-(std::bitset<S>& y, const std::bitset<S>& z) {
//return std::bitset<S>(*this) -= y;
size_t thing[get_size(S)];
size_t t = 0, * p = thing, * end = thing + get_size(y);
const size_t* q = z[0]; //z.a
while (p != end) {
size_t p1 = *p;
*p = p1 - *q - t;
t = (*p > p1) || (p1 + t < t);
++p;
++q;
}
return y;
}
template<size_t S>
std::bitset<S>& operator+(std::bitset<S>& y, const std::bitset<S>& z) {
size_t thing[get_size(S)];
size_t t = 0, * p = thing, * end = thing + get_size(y);
const size_t* q = z[0];
while (p != end) {
size_t p1 = *p; *p = p1 + *q + t;
t = (*p < p1) || (p1 + t < t);
++p;
++q;
}
return y;
}
template<size_t S>
std::bitset<S>& operator -=(const std::bitset<S>& y) {
uint t = 0, * p = a, * end = a + size;
const uint* q = y.a;
while (p != end) {
uint p1 = *p; *p = p1 - *q - t;
t = (*p > p1) || (p1 + t < t);
++p; ++q;
}
return *this;
}
int LPS_STL(std::string s) {
const int M = 1005;
int c[M], d[M];
std::bitset<M> row[2], X, Y;
std::unordered_map<int, std::vector<int> > S;
std::unordered_map<int, std::bitset<M> > match;
int n = s.size(), m = n;
S.clear();
match.clear();
row[1].reset();
for (int i = 0; i < n; ++i)c[i] = int(s[i]), S[c[i]].push_back(i);
for (int i = 0; i < m; ++i)d[i] = int(s[n - 1 - i]);
for (int i = 0; i < m; ++i)if (match.find(d[i]) == match.end()) {
std::unordered_map<int, std::bitset<M> >::iterator x = match.insert(std::make_pair(d[i], std::bitset<M>())).first;
for (std::vector<int>::iterator j = S[d[i]].begin(); j != S[d[i]].end(); ++j)x->second.set(*j, 1);
}
for (int i = 0, now = 0; i < m; ++i, now ^= 1)
X = (row[now ^ 1] | match[d[i]]).set(n, 1), row[now] = (X & (( X - (row[now ^ 1] << 1).set(0, 1)) ^ X)).set(n, 0);
return row[(m - 1) & 1].count();
}
void test1() {
int test = longestPalindromeSubseq("");
IS_TRUE(test == 0);
}
void test2() {
int test = longestPalindromeSubseq("bbbab");
IS_TRUE(test == 4);
}
void test3() {
int test = longestPalindromeSubseq("cbbd");
IS_TRUE(test == 2);
}
void test4() {
int test = longestPalindromeSubseq("cbbd");
IS_TRUE(test == 0); //purposefully fail
}
void test5() {
int test = longestPalindromeSubseq("cacbcbba");
IS_TRUE(test == 5);
}
void test6() {
int test = longestPalindromeSubseq("eeeecdeabfbeeb");
IS_TRUE(test == 7);
}
//Std::bitset tests
//void test7() {
// int test = LPS_STL("");
// IS_TRUE(test == 0);
//}
//void test8() {
// int test = LPS_STL("bbbab")
// IS_TRUE(test == 4);
//}
int main()
{
std::cout << "Longest Palindrome Subsequence\n";
test1();
test2();
test3();
test4();
test5();
test6();
test7();
test8();
}
Main question: Is there a core reason this person chose to implement a custom bitset instead of the std library?
Extraneous questions:
Is some of this code intentionally obfuscated?
It feels a bit naive to ask this, but do some of you intentionally code this way?
Why are they using the value of N (an int) as the type for their bitsets?
Some of their formulas are incredibly long.
Attempting to implement the necessary operators for the std::bitset implementation didn't go well. Can someone elucidate the reason these don't exist? I feel like there's a good reason for it regarding expected output, but I can't articulate it.
Is this question more appropriate for another SO site, such as Code Review?
Is some of this code intentionally obfuscated?
It is just faster to type
#define W 6
than
constexpr size_t bitcoverage { std::bitwidth(sizeof(int64_t)*CHAR_BIT)-1 }; // bits needed to represent 8*8=64 2^7 so 7-1=6 which 0-63 bits.
(if I got it right ...)
It feels a bit naive to ask this, but do some of you intentionally code this way?
When I started programming I did, now I have realized that code is read more than written and it could confuse people, including me, who read it later.
Why are they using the value of N (an int) as the type for their bitsets?
N is just how many entries there is max, see the link you provided.
It actually uses an int64_t to store the bits. Which for many operaton on most larger CPU's is far more efficient than the same doing the same operation on an byte as you can do or/and/etc on a lot of bits with just one instuction.
Some of their formulas are incredibly long.
I am not sure which your are speculating about.
Attempting to implement the necessary operators for the std::bitset implementation didn't go well. Can someone elucidate the reason these don't exist? I feel like there's a good reason for it regarding expected output, but I can't articulate it.
Again, what exact are you referring to?

How to improve multiplication efficiency in big integer?

This weekend I followed the wiki to implement the basic big integer multiplication. I use the Toom-3 algorithm to implement. But the time spends unexpectedly at the beginning is slower than long multiplication(grade-school multiplication) and gone forever. I hope the program can over the grade-school multiplication within 500 digits, How should I do, please?
I try to optimize, I reserve the vector capacity and remove the supernumerary code. But is not very effective.
And should I use the vector<long long> to be my base digits?
The whole source code in Github:
typedef long long BigIntBase;
typedef vector<BigIntBase> BigIntDigits;
// ceil(numeric_limits<BigIntBase>::digits10 / 2.0) - 1;
static const int digit_base_len = 9;
// b
static const BigIntBase digit_base = 1000000000;
class BigInt {
public:
BigInt(int digits_capacity = 0, bool nega = false) {
negative = nega;
digits.reserve(digits_capacity);
}
BigInt(BigIntDigits _digits, bool nega = false) {
negative = nega;
digits = _digits;
}
BigInt(const span<const BigIntBase> &range, bool nega = false) {
negative = nega;
digits = BigIntDigits(range.begin(), range.end());
}
BigInt operator+(const BigInt &rhs) {
if ((*this).negative == rhs.negative)
return BigInt(plus((*this).digits, rhs.digits), (*this).negative);
if (greater((*this).digits, rhs.digits))
return BigInt(minus((*this).digits, rhs.digits), (*this).negative);
return BigInt(minus(rhs.digits, (*this).digits), rhs.negative);
}
BigInt operator-(const BigInt &rhs) { return *this + BigInt(rhs.digits, !rhs.negative); }
BigInt operator*(const BigInt &rhs) {
if ((*this).digits.empty() || rhs.digits.empty()) {
return BigInt();
} else if ((*this).digits.size() == 1 && rhs.digits.size() == 1) {
BigIntBase val = (*this).digits[0] * rhs.digits[0];
return BigInt(val < digit_base ? BigIntDigits{val} : BigIntDigits{val % digit_base, val / digit_base}, (*this).negative ^ rhs.negative);
} else if ((*this).digits.size() == 1)
return BigInt(multiply(rhs, (*this).digits[0]).digits, (*this).negative ^ rhs.negative);
else if (rhs.digits.size() == 1)
return BigInt(multiply((*this), rhs.digits[0]).digits, (*this).negative ^ rhs.negative);
return BigInt(toom3(span((*this).digits), span(rhs.digits)), (*this).negative ^ rhs.negative);
}
string to_string() {
if (this->digits.empty())
return "0";
stringstream ss;
if (this->negative)
ss << "-";
ss << std::to_string(this->digits.back());
for (auto it = this->digits.rbegin() + 1; it != this->digits.rend(); ++it)
ss << setw(digit_base_len) << setfill('0') << std::to_string(*it);
return ss.str();
}
BigInt from_string(string s) {
digits.clear();
negative = s[0] == '-';
for (int pos = max(0, (int)s.size() - digit_base_len); pos >= 0; pos -= digit_base_len)
digits.push_back(stoll(s.substr(pos, digit_base_len)));
if (s.size() % digit_base_len)
digits.push_back(stoll(s.substr(0, s.size() % digit_base_len)));
return *this;
}
private:
bool negative;
BigIntDigits digits;
const span<const BigIntBase> toom3_slice_num(const span<const BigIntBase> &num, const int &n, const int &i) {
int begin = n * i;
if (begin < num.size()) {
const span<const BigIntBase> result = num.subspan(begin, min((int)num.size() - begin, i));
return result;
}
return span<const BigIntBase>();
}
BigIntDigits toom3(const span<const BigIntBase> &num1, const span<const BigIntBase> &num2) {
int i = ceil(max(num1.size() / 3.0, num2.size() / 3.0));
const span<const BigIntBase> m0 = toom3_slice_num(num1, 0, i);
const span<const BigIntBase> m1 = toom3_slice_num(num1, 1, i);
const span<const BigIntBase> m2 = toom3_slice_num(num1, 2, i);
const span<const BigIntBase> n0 = toom3_slice_num(num2, 0, i);
const span<const BigIntBase> n1 = toom3_slice_num(num2, 1, i);
const span<const BigIntBase> n2 = toom3_slice_num(num2, 2, i);
BigInt pt0 = plus(m0, m2);
BigInt pp0 = m0;
BigInt pp1 = plus(pt0.digits, m1);
BigInt pn1 = pt0 - m1;
BigInt pn2 = multiply(pn1 + m2, 2) - m0;
BigInt pin = m2;
BigInt qt0 = plus(n0, n2);
BigInt qp0 = n0;
BigInt qp1 = plus(qt0.digits, n1);
BigInt qn1 = qt0 - n1;
BigInt qn2 = multiply(qn1 + n2, 2) - n0;
BigInt qin = n2;
BigInt rp0 = pp0 * qp0;
BigInt rp1 = pp1 * qp1;
BigInt rn1 = pn1 * qn1;
BigInt rn2 = pn2 * qn2;
BigInt rin = pin * qin;
BigInt r0 = rp0;
BigInt r4 = rin;
BigInt r3 = divide(rn2 - rp1, 3);
BigInt r1 = divide(rp1 - rn1, 2);
BigInt r2 = rn1 - rp0;
r3 = divide(r2 - r3, 2) + multiply(rin, 2);
r2 = r2 + r1 - r4;
r1 = r1 - r3;
BigIntDigits result = r0.digits;
if (!r1.digits.empty()) {
shift_left(r1.digits, i);
result = plus(result, r1.digits);
}
if (!r2.digits.empty()) {
shift_left(r2.digits, i << 1);
result = plus(result, r2.digits);
}
if (!r3.digits.empty()) {
shift_left(r3.digits, i * 3);
result = plus(result, r3.digits);
}
if (!r4.digits.empty()) {
shift_left(r4.digits, i << 2);
result = plus(result, r4.digits);
}
return result;
}
BigIntDigits plus(const span<const BigIntBase> &lhs, const span<const BigIntBase> &rhs) {
if (lhs.empty())
return BigIntDigits(rhs.begin(), rhs.end());
if (rhs.empty())
return BigIntDigits(lhs.begin(), lhs.end());
int max_length = max(lhs.size(), rhs.size());
BigIntDigits result;
result.reserve(max_length + 1);
for (int w = 0; w < max_length; ++w)
result.push_back((lhs.size() > w ? lhs[w] : 0) + (rhs.size() > w ? rhs[w] : 0));
for (int w = 0; w < result.size() - 1; ++w) {
result[w + 1] += result[w] / digit_base;
result[w] %= digit_base;
}
if (result.back() >= digit_base) {
result.push_back(result.back() / digit_base);
result[result.size() - 2] %= digit_base;
}
return result;
}
BigIntDigits minus(const span<const BigIntBase> &lhs, const span<const BigIntBase> &rhs) {
if (lhs.empty())
return BigIntDigits(rhs.begin(), rhs.end());
if (rhs.empty())
return BigIntDigits(lhs.begin(), lhs.end());
BigIntDigits result;
result.reserve(lhs.size() + 1);
for (int w = 0; w < lhs.size(); ++w)
result.push_back((lhs.size() > w ? lhs[w] : 0) - (rhs.size() > w ? rhs[w] : 0));
for (int w = 0; w < result.size() - 1; ++w)
if (result[w] < 0) {
result[w + 1] -= 1;
result[w] += digit_base;
}
while (!result.empty() && !result.back())
result.pop_back();
return result;
}
void shift_left(BigIntDigits &lhs, const int n) {
if (!lhs.empty()) {
BigIntDigits zeros(n, 0);
lhs.insert(lhs.begin(), zeros.begin(), zeros.end());
}
}
BigInt divide(const BigInt &lhs, const int divisor) {
BigIntDigits reminder(lhs.digits);
BigInt result(lhs.digits.capacity(), lhs.negative);
for (int w = reminder.size() - 1; w >= 0; --w) {
result.digits.insert(result.digits.begin(), reminder[w] / divisor);
reminder[w - 1] += (reminder[w] % divisor) * digit_base;
}
while (!result.digits.empty() && !result.digits.back())
result.digits.pop_back();
return result;
}
BigInt multiply(const BigInt &lhs, const int multiplier) {
BigInt result(lhs.digits, lhs.negative);
for (int w = 0; w < result.digits.size(); ++w)
result.digits[w] *= multiplier;
for (int w = 0; w < result.digits.size(); ++w)
if (result.digits[w] >= digit_base) {
if (w + 1 == result.digits.size())
result.digits.push_back(result.digits[w] / digit_base);
else
result.digits[w + 1] += result.digits[w] / digit_base;
result.digits[w] %= digit_base;
}
return result;
}
bool greater(const BigIntDigits &lhs, const BigIntDigits &rhs) {
if (lhs.size() == rhs.size()) {
int w = lhs.size() - 1;
while (w >= 0 && lhs[w] == rhs[w])
--w;
return w >= 0 && lhs[w] > rhs[w];
} else
return lhs.size() > rhs.size();
}
};
Digits
Grade-school
Toom-3
10
4588
10003
50
24147
109084
100
52165
286535
150
92405
476275
200
172156
1076570
250
219599
1135946
300
320939
1530747
350
415655
1689745
400
498172
1937327
450
614467
2629886
500
863116
3184277
The problem is that you do a million allocations in among others toom3_slice_num, here you could use a std::span (or a std::pair of iterator to the actual part) as the number you give is a const. toom3 is also allocator hell.
The multiply might allocate 1 more time. Count the bits needed or just add 1 to the size.
And the vectors should be pmr (with appropriate allocator) for nearly lock free allocations.
All this is wasted if not compiled with -O2 or -O3.

Paeth Filter/Algorithm not working correctly for PNG

I'm trying to binary read png's.
Reading images that only use the None, sub, up or average filter work fine.
I used the documentation as described here: http://www.libpng.org/pub/png/spec/1.2/PNG-Filters.html
Original picure:
* Pixel struct *
struct Pixel
{
unsigned char r,g,b;
int all() const { return r + g + b; }
Pixel& operator+=(const Pixel& rhs)
{
this->r = (this->r + rhs.r) % 256;
this->g = (this->g + rhs.g) % 256;
this->b = (this->b + rhs.b) % 256;
return *this;
}
Pixel& operator-=(const Pixel& rhs)
{
this->r = (this->r - rhs.r) % 256;
this->g = (this->g - rhs.g) % 256;
this->b = (this->b - rhs.b) % 256;
return *this;
}
bool operator<=(const Pixel& rhs)
{
return ((this->r <= rhs.r) && (this->g <= rhs.g) && (this->b <= rhs.b));
}
friend Pixel& operator+(Pixel lhs, const Pixel& rhs)
{
lhs += rhs;
return lhs;
}
friend Pixel& operator-(Pixel lhs, const Pixel& rhs)
{
lhs -= rhs;
return lhs;
}
};
* First possibility *
void INC_Image::Paeth(std::vector<Pixel>& thesePixels, std::vector<Pixel>& priorPixels) const
{
for (int i{ 1 }; i < thesePixels.size(); i++)
{
Pixel tempPixel = thesePixels[i];
tempPixel.r = (thesePixels[i].r + PaethPredictor(thesePixels[i - 1].r, priorPixels[i].r, priorPixels[i - 1].r)) % 256;
tempPixel.g = (thesePixels[i].g + PaethPredictor(thesePixels[i - 1].g, priorPixels[i].g, priorPixels[i - 1].g)) % 256;
tempPixel.b = (thesePixels[i].b + PaethPredictor(thesePixels[i - 1].b, priorPixels[i].b, priorPixels[i - 1].b)) % 256;
thesePixels[i] = tempPixel;
}
}
unsigned char INC_Image::PaethPredictor(const unsigned char& previous, const unsigned char& prior, const unsigned char& priorPrevious) const
{
auto p = (previous + prior - priorPrevious) ;
auto pa = abs(p - previous) ;
auto pb = abs(p - prior) ;
auto pc = abs(p - priorPrevious) ;
if (pa <= pb && pa <= pc) return previous ;
else if (pb <= pc) return prior;
else return (priorPrevious );
}
With thesePixels == vector of 1 image line.
With priorPixels == vector of previous image line.
Result:
* Second possibility *
void INC_Image::Paeth(std::vector<Pixel>& thesePixels, std::vector<Pixel>& priorPixels) const
{
for (int i{ 1 }; i < thesePixels.size(); i++)
{
thesePixels[i] += PaethPredictor(thesePixels[i - 1], priorPixels[i], priorPixels[i - 1]);
}
}
Pixel INC_Image::PaethPredictor(const Pixel& previous, const Pixel& prior, const Pixel& priorPrevious) const
{
auto p = previous.all() + prior.all() - priorPrevious.all();
auto pa = abs(p - previous.all());
auto pb = abs(p - prior.all());
auto pc = abs(p - priorPrevious.all());
if (pa <= pb && pa <= pc) return previous;
else if (pb <= pc) return prior;
else return priorPrevious;
}
With thesePixels == vector of 1 image line.
With priorPixels == vector of previous image line.
Result:
I don't know what's wrong with the calculation.

Visual Studio C++ 0xC0000005 error: confused by memory allocation

I am a Java developer, but now I need a C++ library and I am not so experienced in this language. In particular, I always get confused about pointers, references and memory allocation. This I think is the reason why I am getting an error at a matrix class I am developing.
The main code:
#include "stdafx.h"
#include "matrix.cpp"
void matrixtest();
int main()
{
matrixtest();
system("pause");
return 0;
}
void matrixtest()
{
// let's try 3x3 matrices
static const int arr1[] = {1, 2, 1, -1, 1, 2, 2, 3, -4};
static const int arr2[] = {0, 2, 2, 1, -1, 0, 3, 2, -2};
vector<int> values1(arr1, arr1 + sizeof(arr1) / sizeof(arr1[0]));
vector<int> values2(arr2, arr2 + sizeof(arr2) / sizeof(arr2[0]));
matrix A(values1, 3);
matrix B(values2, 3);
matrix sum = A + B;
sum.show();
matrix diff = A - B;
diff.show();
matrix prod = A * B;
prod.show();
}
matrix.cpp interesting code:
matrix::matrix(vector<int> v, int r) : values(v), rows(r) {
values = v;
rows = r;
}
// [...]
matrix& matrix::operator += (const matrix& rhs) {
matrix result = (*this) + rhs;
(*this) = result;
return *this;
}
matrix matrix::operator + (const matrix& rhs) {
if (rows != rhs.rows || values.size() != rhs.values.size()) {
throw std::length_error("Matrices shapes mismatch");
}
matrix result(values, rows);
for (auto& i : values) {
result.values[i] = this->values[i] + rhs.values[i];
}
return result;
}
// [...]
void matrix::show() {
string delimiter = "";
for (auto& i : values) {
delimiter = "";
for (auto j = 0; j < values.size()/rows; j++) {
cout << delimiter << values[i * values.size()/rows + j]; // this is the line giving the error
delimiter = ",";
}
std::cout << std::endl;
}
}
full matrix.hpp file:
#ifndef matrix_hpp
#define matrix_hpp
class matrix {
private:
std::vector<int> values; // size is found by values.size()
int rows; // columns is values.size()/rows
public:
matrix(vector<int>, int); // base ctor.
matrix(const matrix& rhs); // copy ctor.
matrix& operator=(const matrix& rhs); // assign. ctor.
~matrix(); // dtor.
int& operator () (int row, int column);
const int& operator () (int row, int column) const;
matrix operator + (int scalar) const;
matrix operator - (int scalar) const;
matrix operator * (int scalar) const;
matrix& operator += (int scalar);
matrix& operator -= (int scalar);
matrix& operator *= (int scalar);
matrix operator + (const matrix&);
matrix operator - (const matrix&);
matrix operator * (const matrix&);
matrix& operator += (const matrix&);
matrix& operator *= (const matrix&);
// should be private ??
void reshape(int newRows, int newColumns);
void show(); //used for dev. only
void range(int start, int defaultStep = 1);
void fill(int value);
void randint(int lowerBound, int upperBound);
};
#endif /* CMatrix_hpp */
This class is based on an example given at matrix example.
The error says '0xC0000005: Access violation reading location 0x5820A694.'
So I am guessing the memory allocation is wrong and/or there is an out of bounds array and/or I am messing with the '&' operators.
Edit: I get the following trace:
this 0x00dffe24 {values={ size=9 } rows=3 } matrix *
So, the matrix does exist, but for some reason I am getting the error.
The for loop that you are using, before the one causing the error
for (auto& i : values)
is a range-based for loop.
With this you will get the values present in vector(values).
But based on the logic you have written what you want here is an index that represents the row you are working with.
You should go for the normal for loop.
for(int i =0; i<rows; ++i)

Sundials ODE_vector to armadillo conversion for ODE approximation

I am trying to use the Sundials ODE solver libraries in order to approximate the dynamics of an extension to the multi species Lotka-Volterra competition equations. E.g. in the case of two species
dx1/dt = r1 * x1 * (1 - (x1 + a12 * x2))
dx2/dt = r2 * x2 * (1 - (x2 + a21 * x1))
or...
dx/dt = r * x * (1 - A * x)
(where K = a11 = a22 = 1)
From what I understand the Sundials ODE solver expects an object of class ODE_vector, the elements of which represent the various state variables of the system, in this case x1 and x2 and I have no problem getting the solver to approximate the trajectories of the two species' populations if I program each parameter (r1, r2, a12, a21) as unique objects as in the following code:
int community::dynamics(ODE_vector const & state, ODE_vector & time_derivative) {
double r1 = 0.5;
double r2 = 0.2;
double a12 = 0.2;
double a21 = 0.2;
time_derivative[0] = r1 * state[0] * (1 - (state[0] + a12 * state[1]));
time_derivative[1] = r2 * state[1] * (1 - (state[1] + a21 * state[0]));
return 0;
};
... where time_derivative and state are members of the Sundials class ODE.
Can anyone show me how to adapt the code to get the system of ODEs into matrix form, i.e. so that r1, r2, a12 and a21 are in the form r and A? I've been told to convert from ODE_vector to armadillo vector/matrix objects using "Advanced constructors" (e.g. 1) but it's one thing to know that and another to successfully implement it!!
Thanks!
Where you thinking of something like this? I implemented that naively in 30 min. There is a lot of optimisation, but it will never be as performant as your stripped down code. Even if you used Armadillo, Blitz++ etc.
#include <algorithm>
#include <iostream>
#include <vector>
template<class T> class Matrix {
public:
Matrix() {}
Matrix(size_t m, size_t n) : m_(m), n_(n) { v_.resize(m*n); }
Matrix& operator*= (const Matrix& other) {
if (other.m_ != n_) {
throw std::length_error("dimesions don't match");
}
Matrix<T> nv(m_,other.n_);
for (size_t j = 0; j < other.n_; ++j) {
for (size_t i = 0; i < m_; ++i) {
for (size_t k = 0; k < n_; ++k)
nv(i,j) += operator()(i,k) * other(k,j);
}
}
*this = nv;
return *this;
}
Matrix operator* (const Matrix& other) const {
Matrix ret = *this;
return ret *= other;
}
Matrix& operator+= (const Matrix& other) {
if (other.m_ != m_ || other.n_ != n_) {
throw std::length_error("dimesions don't match");
}
std::transform(v_.begin(), v_.end(), other.v_.begin(), v_.begin(), std::plus<T>());
return *this;
}
Matrix operator+ (const Matrix& other) const {
Matrix ret = *this;
return ret += other;
}
Matrix operator- () const {
Matrix<T> res (m_,n_);
std::transform (v_.begin(), v_.end(), res.v_.begin(), std::negate<T>());
return res;
}
Matrix& operator-= (const Matrix& other) {
return *this += -other;
}
Matrix operator- (const Matrix& other) const {
Matrix ret = *this;
return ret -= other;
}
Matrix operator->* (const Matrix& other) const {
if (other.m_ != m_ || other.n_ != n_) {
throw std::length_error("dimesions don't match");
}
Matrix res = *this;
std::transform(res.v_.begin(), res.v_.end(), other.v_.begin(),
res.v_.begin(), std::multiplies<T>());
return res;
}
Matrix operator=(std::vector<std::initializer_list<T>> const& other) {
n_ = other.size();
if (n_ == 0) {
throw std::bad_alloc();
}
m_ = other.front().size();
if (m_ == 0) {
throw std::bad_alloc();
}
for (auto const& i : other) {
if (i.size() != m_) {
throw std::bad_alloc();
}
}
v_.resize(m_*n_);
size_t j = 0;
for (const auto& i : other) {
std::copy(i.begin(), i.end(), v_.begin()+j);
j+=m_;
}
return *this;
}
T& operator() (size_t m, size_t n) {
return v_[n*m_+m];
}
const T& operator() (size_t m, size_t n) const {
return v_[n*m_+m];
}
size_t m() const {return m_;}
size_t n() const {return n_;}
private:
size_t m_, n_;
std::vector<T> v_;
};
template<class T> inline std::ostream&
operator<< (std::ostream& os, const Matrix<T>& v) {
size_t i,j;
for (i = 0; i < v.m(); ++i) {
for (j = 0; j < v.n(); ++j) {
os << v(i,j);
os << " ";
}
if (i<v.m()-1)
os << std::endl;
}
return os;
}
int main() {
Matrix<double> A, r, x, one, dxdt;
A = {{1,.2},
{.2,1}};
r = {{0.5,0.2}};
x = {{0.1,-0.1}};
one = {{1,1}};
dxdt = (r ->* x ->* (one - A * r));
std::cout << dxdt << std::endl;
return 0;
}