Convolution: the last element in the convolution is never right - c++

I am writing a c++ implementation of convolution with the following function
vector<double> Conv(vector<double> a, vector<double> b)
{
// a and b are the same size
int n = a.size() * 2 - 1;
vector<double> c;
for (int i = 0; i < n; i++) {
c.push_back(0);
for (int j = 0; j <= i; j++) {
c[i] += a[j] * b[i - j];
}
}
return c;
}
The problem is that all the convolution values are correct except for the last one. I checked using a convolution calculator I found online.
Example input:
Vector a = <0.961232, 0.00685581, 0.905588, 0.914544>
Vector b = <0.719889, 0.675933, 0.0571511, 0.148412>
Returned vector = <0.691981, 0.654664, 0.711493, 1.41354, 0.670944, 0.186668, 0.653971>
Expected = <0.691980343248, 0.65466385166109, 0.71149237410793, 1.413537159886891, 0.67094330437252, 0.1866673218544, 0.135729304128>
The accuracy of the floats in the returned vector is fine, but the last result doesn't match up.

According to comments of other community members, I believe that your algorithm is not quite correct. Instead of debugging, I decided to find a correct one by google.
These two links gave me the clue:
Convolution of Vectors (Mlmode)
Convolution of two vectors in R
I used these links to make a small sample in C++:
#include <iostream>
#include <vector>
template <typename VALUE>
void convolve(
std::vector<VALUE> &c, // out
const std::vector<VALUE> &a, const std::vector<VALUE> &b) // in
{
const size_t nA = a.size(), nB = b.size();
const size_t nC = nA + nB - 1;
c.clear(); c.resize(nC, (VALUE)0);
for (size_t i = 0; i < nA; ++i) {
for (size_t j = 0; j < nB; ++j) {
c[i + j] += a[i] * b[j];
}
}
}
template <typename VALUE>
inline std::vector<VALUE> convolve(
const std::vector<VALUE> &a, const std::vector<VALUE> &b)
{
std::vector<VALUE> c; convolve(c, a, b); return c;
}
template <typename VALUE>
void print(
std::ostream &out, const char *label, const std::vector<VALUE> &vec)
{
out << label << '[' << vec.size() << "]: {";
const char *sep = " ";
for (const VALUE &v : vec) {
out << sep << v;
sep = ", ";
}
out << " }" << std::endl;
}
int main()
{
// test 1
// http://www.omatrix.com/manual/mlmode_conv.htm
{ std::cout << "Test 1:" << std::endl;
const std::vector<int> a = {
1, 1, 1, 1, 1
};
std::vector<int> c;
convolve(c, a, a);
print(std::cout, "a", a);
std::cout << "Convolution of a and a:" << std::endl;
print(std::cout, "c", c);
}
// test 2
{ std::cout << "Test 2:" << std::endl;
const std::vector<float> a = {
0.961232f, 0.00685581f, 0.905588f, 0.914544f
};
const std::vector<float> b = {
0.719889f, 0.675933f, 0.0571511f, 0.148412f
};
std::vector<float> c;
convolve(c, a, b);
print(std::cout, "a", a);
print(std::cout, "b", b);
std::cout << "Convolution of a and b:" << std::endl;
print(std::cout, "c", c);
}
// done
return 0;
}
Notes:
To copy a vector (as it is done in return) might be expensive for large vectors. Therefore, I provide the result vector by reference. (For those, who prefer return I wrote an inline wrapper but I didn't use it.)
Instead of vector::push_back(), I used vector::resize(). It is usually less expensive to do allocation at once (especially if size is known from beginning). The vector::resize() is also used for initialization. To discard possible previous values, a vector::clear() is done before. (vector::clear() is a cheap method because it does not free storage but simply resets internal number of elements.)
I made convolve a template. This makes the usage more flexible.
I compiled and tested it with g++ in cygwin on Windows 10 (64 bit):
$ g++ -std=c++11 -o vector-convolution vector-convolution.cc
$ ./vector-convolution.exe
Test 1:
a[5]: { 1, 1, 1, 1, 1 }
Convolution of a and a:
c[9]: { 1, 2, 3, 4, 5, 4, 3, 2, 1 }
Test 2:
a[4]: { 0.961232, 0.00685581, 0.905588, 0.914544 }
b[4]: { 0.719889, 0.675933, 0.0571511, 0.148412 }
Convolution of a and b:
c[7]: { 0.69198, 0.654664, 0.711492, 1.41354, 0.670943, 0.186667, 0.135729 }
$
This looks quite good:
Test 1 matches the expected values according to Convolution of Vectors (Mlmode).
Test 2 matches the expected values of your question.

Related

How can I replace the auto reference keyword in this code? [duplicate]

This question already has answers here:
Passing an array by reference
(5 answers)
Passing a 2D array to a C++ function
(17 answers)
C++ pass an array by reference
(7 answers)
Closed last month.
hello i want to find a way to replace auto keyword in the following code.
#include <iostream>
using namespace std;
void printMatrix(const auto & matrix) {
/* print matrix using range-based for */
}
int main() {
int matrix[][3] = {{}, {}, {}};
int matrix2[][6] = {{}, {}, {}};
printMatrix(matrix);
printMatrix(matrix2);
return 0;
}
what should i use to replace auto in const auto & matrix.
i can use pointers but the problem is i have to pass the rows and columns size.
the upper code is working but i want to know how the auto keyword handle this.
This function declaration
void printMatrix(const auto & matrix) {
/* print matrix using range-based for */
}
declares a template function.
Instead you could write for example
template <typename T, size_t M, size_t N>
void printMatrix(const T ( & matrix)[M][N]) {
/* print matrix using range-based for */
}
and the function is called as the previous function
printMatrix(matrix);
printMatrix(matrix2);
As the element type of the arrays is known then you can also write
template <size_t M, size_t N>
void printMatrix(const int ( & matrix)[M][N]) {
/* print matrix using range-based for */
}
//...
printMatrix(matrix);
printMatrix(matrix2);
Within the function you can use the values M and N in nested for loops to output the arrays as for example
for ( size_t i = 0; i < M; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
std::cout << matrix[i][j] << ' ';
}
std::cout << '\n';
}
Or you can use range-based for loop
for ( const auto &row : matrix )
{
for ( const auto &item : row )
{
std::cout << item << ' ';
}
std::cout << '\n';
}
You could do the same using the initial function like for example
#include <iterator>
//...
void printMatrix(const auto & matrix) {
for ( size_t i = 0, m = std::size( matrix ); i < m; i++ )
{
for ( size_t j = 0, n = std::size( matrix[i] ); j < n; j++ )
{
std::cout << matrix[i][j] << ' ';
}
std::cout << '\n';
}
}
Here is a demonstration program.
#include <iostream>
#include <iterator>
std::ostream & printMatrix( const auto &matrix, std::ostream &os = std::cout )
{
for (size_t i = 0, m = std::size( matrix ); i < m; i++)
{
for (size_t j = 0, n = std::size( matrix[i] ); j < n; j++)
{
os << matrix[i][j] << ' ';
}
os << '\n';
}
return os;
}
int main()
{
int matrix[][3] =
{
{ 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }
};
int matrix2[][6] =
{
{ 0, 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 0, 1 }, { 2, 3, 4, 5, 6, 7 }
};
printMatrix( matrix ) << '\n';
printMatrix( matrix2 ) << '\n';
}
The program output is
0 1 2
3 4 5
6 7 8
0 1 2 3 4 5
6 7 8 9 0 1
2 3 4 5 6 7
Re-declare the print function to allow only a function parameter that is a 2D-array by reference, for a parameterized element type:
#include <cstddef> // std::size_t
template<typename T, std::size_t num_rows, std::size_t num_cols>
void printMatrix(T const (&mat)[num_rows][num_cols]) {
/* print matrix using range-based for */
}
// ....
printMatrix(matrix); // template arguments inferred as <int, 3, 3>
printMatrix(matrix2); // template arguments inferred as <int, 3, 6>
This is essentially a more specialized version as compared to an overload using a single type template parameter (as in OP's example, via auto/abbreviated function template with a single invented type template parameter).
A good replacement can be with a concept.
From here:
template<typename T>
concept nested_range = std::ranges::range<T> && std::ranges::range<std::ranges::range_value_t<T>>;
So
template <nested_range Matrix>
void printMatrix(const Matrix & matrix) {
for (const auto& line: matrix) {
for (const auto& x: line) {
std::cout << x << " ";
}
std::cout << "\n";
}
}
This way, it is shown in the code that only an iterable (concept range) containing an iterable (e.g. 2D-array) is expected and a reasonable error message will be given for wrong parameters.
Live example with more than enough includes.
You can replace auto with a template parameter.
That's how it was done before C++ 14.
#include <iostream>
using namespace std;
template <typename Matrix>
void printMatrix(const Matrix & matrix) {
/* print matrix using range-based for */
}
int main() {
int matrix[][3] = {{}, {}, {}};
int matrix2[][6] = {{}, {}, {}};
printMatrix(matrix);
printMatrix(matrix2);
return 0;
}

How do I order an array of strings on the basis of an array of integers

I have an array of integers with a bunch of numbers from 1-10
Then I have an array of names(strings) which belong with the numbers a.e.
Numbers[0] = 5, Numbers[1] = 2
Names[0] = "Jeremy", Names [1] = "Samantha".
I can easily order the numbers with:
int n = sizeof(Numbers) / sizeof(Numbers[0]);
sort(Numbers, Numbers + n, greater<int>());
But then the names and numbers don't match at all.
How do I fix this?
A very common approach is to create an array of indices and sort that:
std::vector<int> indices(Numbers.size());
std::iota(indices.begin(), indices.end(), 0);
std::sort(indices.begin(), indices.end(),
[&](int A, int B) -> bool {
return Numbers[A] < Numbers[B];
});
The original arrays are not altered, but now indices can be used to access both arrays in the desired order.
If we want to reorder Numbers or Names in place, then we can
create a set of "back indices" that record where to find the element i in the sorted array:
std::vector<int> back_indices(indices.size());
for (size_t i = 0; i < indices.size(); i++)
back_indices[indices[i]] = i;
Now we can reorder, for example, Names in place in the desired order:
int index = 0;
std::string name = Names[index];
for (int i = 0; i < back_indices.size(); i++) {
index = back_indices[index];
std::swap(name,Names[index]);
}
I've tested this code which should give you the required behavior:
struct numberName {
int num;
string name;
};
bool compare(numberName a, numberName b){
return a.num < b.num; // if equal, no need to sort.
}
int main() {
numberName list[2];
list[0].num = 5, list[1].num = 2;
list[0].name = "Jeremy", list[1].name = "Samantha";
sort(list, list+2, compare);
}
Like HAL9000 said, you want to use a struct since this keeps variables that belong to each other together. Alternatively you could use a pair, but I don't know if a pair would be good practice for your situation or not.
This is a great example of the complexities introduced by using parallel arrays.
If you insist on keeping them as parallel arrays, here is a possible approach. Create a vector of integer indexes, initialised to { 0, 1, 2, 3, etc }. Each integer represents one position in your array. Sort your vector of indexes using a custom comparision function that uses the indexes to refer to array1 (Numbers). When finished you can use the sorted indexes to reorder array1 and array2 (Names).
One could also write their own sort algorithm that performs swaps on the extra array at the same time.
Or one could trick std::sort into sorting both arrays simultaneously by using a cleverly designed proxy. I will demonstrate that such a thing is possible, although the code below may be considered a simple hackish proof of concept.
Tricking std::sort with a cleverly-designed proxy
#include <iostream>
#include <algorithm>
constexpr size_t SZ = 2;
int Numbers[SZ] = {5, 2};
std::string Names[SZ] = {"Jeremy", "Samantha"};
int tempNumber;
std::string tempName;
class aproxy {
public:
const size_t index = 0;
const bool isTemp = false;
aproxy(size_t i) : index(i) {}
aproxy() = delete;
aproxy(const aproxy& b) : isTemp(true)
{
tempName = Names[b.index];
tempNumber = Numbers[b.index];
}
void operator=(const aproxy& b) {
if(b.isTemp) {
Names[index] = tempName;
Numbers[index] = tempNumber;
} else {
Names[index] = Names[b.index];
Numbers[index] = Numbers[b.index];
}
}
bool operator<(const aproxy& other) {
return Numbers[index] < Numbers[other.index];
}
};
int main() {
aproxy toSort[SZ] = {0, 1};
std::sort(toSort, toSort+SZ);
for(int i=0; i<SZ; ++i) {
std::cout << "Numbers[" << i << "]=" << Numbers[i] << std::endl;
std::cout << "Names[" << i << "]=" << Names[i] << std::endl;
}
return 0;
}
...and an even more cleverly-designed proxy could avoid entirely the need to allocate SZ "aproxy" elements.
Tricking std::sort with an "even more cleverly-designed" proxy
#include <iostream>
#include <algorithm>
class aproxy;
constexpr size_t SZ = 2;
int Numbers[SZ] = {5, 2};
std::string Names[SZ] = {"Jeremy", "Samantha"};
aproxy *tempProxyPtr = nullptr;
int tempNumber;
std::string tempName;
class aproxy {
public:
size_t index() const
{
return (this - reinterpret_cast<aproxy*>(Numbers));
}
bool isTemp() const
{
return (this == tempProxyPtr);
}
~aproxy()
{
if(isTemp()) tempProxyPtr = nullptr;
}
aproxy() {}
aproxy(const aproxy& b)
{
tempProxyPtr = this;
tempName = Names[b.index()];
tempNumber = Numbers[b.index()];
}
void operator=(const aproxy& b) {
if(b.isTemp()) {
Names[index()] = tempName;
Numbers[index()] = tempNumber;
} else {
Names[index()] = Names[b.index()];
Numbers[index()] = Numbers[b.index()];
}
}
bool operator<(const aproxy& other) {
return Numbers[index()] < Numbers[other.index()];
}
};
int main() {
aproxy* toSort = reinterpret_cast<aproxy*>(Numbers);
std::sort(toSort, toSort+SZ);
for(int i=0; i<SZ; ++i) {
std::cout << "Numbers[" << i << "]=" << Numbers[i] << std::endl;
std::cout << "Names[" << i << "]=" << Names[i] << std::endl;
}
return 0;
}
Disclaimer: although my final example above may technically be in violation of the strict-aliasing rule (due to accessing the same space in memory as two different types), the underlying memory is only used for addressing space-- not modified-- and it does seems to work fine when I tested it. Also it relies entirely on std::sort being written in a certain way: using a single temp variable initialized via copy construction, single-threaded, etc. Putting together all these assumptions it may be a convenient trick but not very portable so use at your own risk.

Efficient matrix implementation

I have the following problem:
I've a precomputed 2d matrix of values which i need to lookup very often and compute only once
The size of the matrix is about 4000x4000 at most
The matrix won't be sparse, i typically need almost all values.
The values in the matrix can be boolean, integer or double. At least they are always small objects
Currently i am storing the precomputed values in a std::vector<<std::vector<T>>, and i've noticed the lookups into this datastructure takes quite some time in heavy computations. I've googled around and so far the suggested implementation seems to be to try a solution in which all the memory is stored contigious using an 1D array where the location in this array is computed based on i and j.
Does anybody have a good example implementation of this or has an even better suggestion? I couldn't find a modern C++ example, while it seems to be a very common problem to me. I'd prefer to use someone elses code instead of reinventing the wheel here. Of course i will measure the differences to see whether it actually improves performance.
Examples i've found:
https://medium.com/#patdhlk/c-2d-array-a-different-better-solution-6d371363ebf8
https://secure.eld.leidenuniv.nl/~moene/Home/tips/matrix2d/
Here is a very simple and efficient 2-d matrix. The 'main' creates a 10000x10000 double array 'mat', then filled it with random number. The array 'mat' is copied into another array 'mat2'. your may input two integers 'n' and 'm' between 0 and 9999 to fetch the double data at mat2(n,m).
Feel free to use or test it. Let me know if you encounter problems or need some more functions to be implemented. Good luck!
#ifndef ytlu_simple_matrix_class_
#define ytlu_simple_matrix_class_
#include <iostream>
#include <iomanip>
#include <complex>
template <typename T> class tMatrix
{
public:
T *ptr;
int col, row, size;
inline T* begin() const {return ptr;}
inline T* end() const {return this->ptr + this->size;}
inline T operator()(const int i, const int j) const { return ptr[i*col+j];
} // r-value
inline T&operator()(const int i, const int j) { return ptr[i*col+j]; } //l-value
inline tMatrix(): col{0}, row{0}, size{0}, ptr{0} {;}
tMatrix(const int i, const int j): col(j), row(i), size(i*j)
{
ptr = new T [this->size] ;
}
tMatrix(const tMatrix<T>&a) : tMatrix<T>(a.row, a.col)
{
std::copy(a.begin(), a.end(), this->ptr);
}
tMatrix<T>& operator=(tMatrix<T>&&a)
{
this->col = a.col;
this->row = a.row;
delete [] this->ptr;
this->ptr = a.ptr;
a.ptr = nullptr;
return *this;
}
tMatrix<T>& operator=(const tMatrix<T>&a)
{
if (col==a.cpl && row==a.row) std::copy(a.begin(), a.end(), this->ptr);
else { tMatrix<T>&&v(a); *this = std::move(v);}
return *this;
}
~tMatrix() {delete [] this->ptr;}
}; //end of class tMatrix
template <typename X> std::ostream& operator<<(std::ostream&p, const tMatrix<X>&a)
{
p << std::fixed;
for (int i=0; i<a.row; i++) {
for (int j=0; j <a.col; j++) p << std::setw(12) << a(i, j);
p << std::endl;
}
return p;
}
using iMatrix = tMatrix<int>;
using rMatrix = tMatrix<double>;
using cMatrix = tMatrix<std::complex<double> >;
#endif
//
//
#include <ctime>
#include <cstdlib>
#define N1 10000
int main()
{
int n, m;
std:srand(time(NULL)); // randomize
rMatrix mat(N1, N1); // declare a 10000 x 10000 double matrix
//
// fill the whole matrix with double random number 0.0 - 1.0
//
for (int i = 0; i<mat.row; i++)
{ for (int j=0; j<mat.col; j++) mat(i, j) = (double)std::rand() / (double)RAND_MAX; }
//
// copy mat to mat 2 just for test
//
rMatrix mat2 = mat;
//
// fetch data test input 0 <= n m < 10000 to print mat2(n, m)
//
while(1)
{
std::cout << "Fetch 2d array at (n m) = ";
std::cin >> n >> m;
if ((n < 0) || (m < 0) || (n > mat2.row) || (m > mat2.col) )break;
std::cout << "mat(" << n << ", " << m << ") = " << mat2(n, m) << std::endl << std::endl;
}
return 0;
}
The compile parameter I used and the test run. It takes a couple seconds to fill the random numbers, and I felt no lapse at all in fetch a data running in my aged PC.
ytlu#ytlu-PC MINGW32 /d/ytlu/working/cpptest
$ g++ -O3 -s mtx_class.cpp -o a.exe
ytlu#ytlu-PC MINGW32 /d/ytlu/working/cpptest
$ ./a.exe
Fetch 2d array at (n m) = 7000 9950
mat(7000, 9950) = 0.638447
Fetch 2d array at (n m) = 2904 5678
mat(2904, 5678) = 0.655934
Fetch 2d array at (n m) = -3 4

Rotate M*N matrix 90 Degrees Clockwise ,C++

I am trying to rotate a vector of Vectors of chars.
I made a 2d vector matrix setup. right now the matrix takes input from a file, I use vector.push_back(c) to add the characters to the vvc;
An example of the vvc array would be something like this
aaaaa
azzza
azaza
azzza
azaaa
azaaa
azaaa
aaaaa
I have the vvc setup, But I am trying to rotate it 90 degrees. I rotated it 90 degrees counter clockwise but I need to rotate it 90 degrees clockwise.
as of right now my code does this
90 counter clock
aaaaaaaa
azzzzzza
azazaaaa
azzzaaaa
aaaaaaaa
and it does it through this loop;
cout <<"\n90 counter clock"<<endl;
for (size_t colNo = 0; colNo < kvsize2; colNo++)
{
for (const auto &row : twovector)
{
char colVal = row.at(colNo);
cout << colVal;
}
cout << endl;
}
I am just learning about vectors, and the range for. Trying to do a decrement loop almost works, but keeps throwing me into a segfault.
"Solved"
I was using
twovector.push_back(temp);
using
twovector.insert(twovector.begin(),temp);
gives me
90 counter clock
aaaaaaaa
azzzzzza
aaaazaza
aaaazzza
aaaaaaaa
Tackling a specific part of the question :
If anyone has any tips or suggestions on how to rotate a M*N 2d vector array
C++ is good at segregating algorithms from data.
Kindly note that the answer is a bit lengthy and has been written with the objective of a tutorial.
Lets begin !!
We want 3 features from our rotate_2d_matrix_clockwise algorithm :
It should work with all datatypes, i.e. int, char, double or any user defined type.
It should work with different types of containers, such as std::array and std::vector
It should be chain-able, i.e. user should be able to call rotate_2d_matrix_clockwise on the result returned by rotate_2d_matrix_clockwise, to achieve 2 times rotation.
Once we are clear with our requirements, we can draft some use-cases for our algorithm.
std::vector<std::vector<char>> data = { {'a', 'b', 'c', 'd'},
{'e', 'f', 'g', 'h'},
{'i', 'j', 'k', 'l'} };
rotate_2d_matrix_clockwise(data); // rotating 2d-matrix of vector<char>
std::array<std::array<int, 4>, 3> data2 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
// rotating 2d-matrix of array<int>, twice
rotate_2d_matrix_clockwise(rotate_2d_matrix_clockwise(data2)));
So lets use some templates to create a generic 2d-clockwise-rotate function.
Our rotate_2d_matrix_clockwise will :
take the original_matrix and return a new rotated_matrix.
automatically deduce the dimensions i.e. M x N of the container passed to it.
create the rotated_matrix and pass it to a helper function rotate_2d_matrix_clockwise_impl where the actual work would be done.
So how will the implementation of rotate_2d_matrix_clockwise for std::array look ?
template<typename T, size_t M, size_t N>
auto rotate_2d_matrix_clockwise(std::array<std::array<T, M>, N> const & original_matrix)
-> std::array<std::array<T, N>, M>
{
std::array<std::array<T, N>, M> rotated_matrix;
rotate_2d_matrix_clockwise_impl(original_matrix, rotated_matrix, M, N); // rotate
return rotated_matrix;
}
Neat and precise.
The implementation of rotate_2d_matrix_clockwise for std::vector is a bit messy, though.
template<typename Matrix2D>
auto rotate_2d_matrix_clockwise(Matrix2D const & original_matrix) -> Matrix2D
{
int const M = original_matrix[0].size(); // deduce M and N
int const N = original_matrix.size();
Matrix2D rotated_matrix; // vector has no form, hence we have to resize it for `N x M`
rotated_matrix.resize(M);
for (auto x = 0; x < M; ++x) {
rotated_matrix[x].resize(N);
}
rotate_2d_matrix_clockwise_impl(original_matrix, rotated_matrix, M, N); // rotate
return rotated_matrix;
}
Now lets look at how the actual rotation algorithm rotate_2d_matrix_clockwise_impl would look.
It should be noted, that the algorithm is independent of the container and/or the data contained. It just focuses on rotating.
template<typename OriginalMatrix2D, typename RotatedMatrix2D>
void rotate_2d_matrix_clockwise_impl(OriginalMatrix2D const & original_matrix,
RotatedMatrix2D & rotated_matrix,
int const M,
int const N)
{
for (auto x = 0; x < N; ++x) {
for (auto y = 0; y < M; ++y) {
// Source : https://stackoverflow.com/questions/4780119/2d-euclidean-vector-rotations
rotated_matrix[y][-x -1 +N] = original_matrix[x][y];
}
}
}
Here is a full working example compiled in C++11.
#include <iostream>
#include <vector>
#include <array>
template<typename Matrix2D>
void print_matrix(Matrix2D const & vec)
{
std::cout << "size of matrix is [" << vec[0].size() << " x " << vec.size() << "]\n";
for (auto const & inner_vec : vec) {
for (auto const & item : inner_vec) {
std::cout << item << ", ";
}
std::cout << std::endl;
}
}
template<typename OriginalMatrix2D, typename RotatedMatrix2D>
void rotate_2d_matrix_clockwise_impl(OriginalMatrix2D const & matrix,
RotatedMatrix2D & rotated_matrix,
int const M,
int const N)
{
for (auto x = 0; x < N; ++x) {
for (auto y = 0; y < M; ++y) {
// Source : https://stackoverflow.com/questions/4780119/2d-euclidean-vector-rotations
rotated_matrix[y][-x -1 +N] = matrix[x][y];
}
}
}
template<typename T, size_t M, size_t N>
auto rotate_2d_matrix_clockwise(std::array<std::array<T, M>, N> const & original_matrix)
-> std::array<std::array<T, N>, M>
{
std::array<std::array<T, N>, M> rotated_matrix;
rotate_2d_matrix_clockwise_impl(original_matrix, rotated_matrix, M, N);
return rotated_matrix;
}
template<typename Matrix2D>
auto rotate_2d_matrix_clockwise(Matrix2D const & original_matrix) -> Matrix2D
{
int const M = original_matrix[0].size();
int const N = original_matrix.size();
Matrix2D rotated_matrix;
rotated_matrix.resize(M);
for (auto x = 0; x < M; ++x) {
rotated_matrix[x].resize(N);
}
rotate_2d_matrix_clockwise_impl(original_matrix, rotated_matrix, M, N);
return rotated_matrix;
}
int main()
{
std::array<std::array<int, 4>, 3> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
std::cout << "\nBefore Rotation :\n";
print_matrix(data);
std::cout << "\nAfter 2nd Clockwise Rotation :\n";
print_matrix(rotate_2d_matrix_clockwise(rotate_2d_matrix_clockwise(data)));
std::vector<std::vector<char>> data2 = { {'a', 'b', 'c', 'd'}, {'e', 'f', 'g', 'h'}, {'i', 'j', 'k', 'l'}};
std::cout << "Before Rotation :\n";
print_matrix(data2);
std::cout << "\nAfter Clockwise Rotation :\n";
print_matrix(rotate_2d_matrix_clockwise(data2));
return 0;
}
If I got you right, and all you want is to print the matrix 90 degrees clockwise, try this code:
for (int colNo = 0; colNo < vec[0].size(); colNo++)
{
for (int i = vec.size() - 1; i >= 0; i--)
{
const auto& row = vec[i];
int colVal = row.at(colNo);
cout << colVal;
}
cout << endl;
}

Build a string using recursion in c++

I have a matrix of values (stored as an array of values) and a vector with the matrix dimensions( dims[d0, d1, d2]).
I need to build a string like that:
"matA(j, k, l) = x;"
where j, k, l are the indices of the matrix and x the value of the element. I need to write this for each value of the matrix and for matrices with 2 to n dimensions.
I have a problem isolating the base case and replicating it in a useful way. I did a version in a switch case with a case for each dimension and a number of for cycles equal to the number of dimensions:
for (unsigned int k=1; k<=(dims[2]); k++)
{
for (unsigned int j=1; j<=(dims[1]); j++)
{
for (unsigned int i=1; i<=(dims[0]); i++)
{
strs << matName << "(" << i << "," << j << ","<< k << ")="<< tmp[t]<< "; ";
....
but is not what I wanted.. Any idea for a more general case with a variable number of dimensions?
You need a separate worker function to recursively generate the series of indices and main function which operates on it.
For example something like
void worker(stringstream& strs, int[] dims, int dims_size, int step) {
if (step < dims_size) {
... // Add dims[step] to stringstream. Another if may be necessary for
... // whether include `,` or not
worker(strs, dims, dims_size, step + 1);
} else {
... // Add cell value to stringstream.
}
}
string create_matrix_string(int[] dims, int dims_size, int* matrix) {
... // Create stringstream, etc.
strs << ... // Add matrix name etc.
worker(strs, dims, dims_size, 0);
strs << ... // Add ending `;` etc.
}
The main problem here is the value, since the dimension is not known during compilation. You can avoid that by encoding matrix in single-dimensional table (well, that's what C++ is doing anyway for static multidimensional tables) and call it using manually computed index, eg. i + i * j (for two-dimensional table). You can do it, again, by passing an accumulated value recursively and using it in final step (which I omitted in example above). And you probably have to pass two of them (running sum of polynomial components, and the i * j * k * ... * x product for indices from steps done so far.
So, the code above is far from completion (and cleanliness), but I hope the idea is clear.
You can solve this, by doing i, j and k in a container of the size of dim[] - sample:
#include <iostream>
#include <vector>
template< typename Itr >
bool increment( std::vector< int >& ijk, Itr idim, int start )
{
for( auto i = begin(ijk); i != end(ijk); ++i, ++idim )
{
if( ++*i <= *idim )
return true;
*i = start;
}
return false;
}
int main()
{
using namespace std;
int dim[] = { 5, 7, 2, 3 };
const int start = 1;
vector< int > ijk( sizeof(dim)/sizeof(*dim), start );
for( bool inc_done = true; inc_done
; inc_done = increment( ijk, begin(dim), start ) )
{
// .. here make what you want to make with ijk
cout << "(";
bool first = true;
for( auto j = begin(ijk); j != end(ijk); ++j )
{
if( !first )
cout << ",";
else
first = false;
cout << *j;
}
cout << ")= tmp[t] " << endl;
}
return 0;
}