- Joined
- 2/15/22
- Messages
- 1,494
- Points
- 223
def post to your github!
Do you mean like this - Forward Euler? It's usually my first step. As a second step, I am thinking of the C++ solutioning.why not build your own Euler fdm 101 from 1st principles w/o all that boiler plate code i.e. virtual.
C++:/* Let's try to solve the first order ODE given by * x' = (1-2t)x */
Do you mean like this - Forward Euler? It's usually my first step. As a second step, I am thinking of the C++ solutioning.
Polya's quote is great food for thought, and relevant any day.“It is better to solve one problem five different ways, than to solve five problems one way.”
I was unable to unbold that quote of mine, sorry.Polya's quote is great food for thought, and relevant any day.
std::thread
object my_thread
, will continue to access some_local_state
, even after oops()
exits.Hi guys,
I am writing a matrix class - and wanted to get some feedback. My idea is that one should be capable of creating both fixed-size(compile-time) and dynamic matrices. So,containerType
template parameter would be eitherstd::array<T,N>
orstd::vector<N>
.
I should provide proper iterators to traverse through my matrix and also need to overload the assignment operator.
[CODE lang="cpp" title="Matrix.h"]#pragma once
#include <array>
#include <vector>
template <typename T, int r, int c, typename cType=std::array<T,r*c>>
class Matrix;
using Matrix1d = Matrix<double, 1, 1>;
using Matrix2d = Matrix<double, 2, 2>;
using Matrix3d = Matrix<double, 3, 3>;
using Matrix4d = Matrix<double, 4, 4>;
using Matrix1i = Matrix<int, 1, 1>;
using Matrix2i = Matrix<int, 2, 2>;
using Matrix3i = Matrix<int, 3, 3>;
using Matrix4i = Matrix<int, 4, 4>;
using Matrix1f = Matrix<float, 1, 1>;
using Matrix2f = Matrix<float, 2, 2>;
using Matrix3f = Matrix<float, 3, 3>;
using Matrix4f = Matrix<float, 4, 4>;
using Vector1d = Matrix<double, 1, 1>;
using Vector2d = Matrix<double, 1, 2>;
using Vector3d = Matrix<double, 1, 3>;
using Vector4d = Matrix<double, 1, 4>;
using Vector1i = Matrix<int, 1, 1>;
using Vector2i = Matrix<int, 2, 2>;
using Vector3i = Matrix<int, 3, 3>;
using Vector4i = Matrix<int, 4, 4>;
using Vector1f = Matrix<float, 1, 1>;
using Vector2f = Matrix<float, 2, 2>;
using Vector3f = Matrix<float, 3, 3>;
using Vector4f = Matrix<float, 4, 4>;
using MatrixXi = Matrix<int, 0, 0, std::vector<int>>;
using MatrixXd = Matrix<double, 0, 0, std::vector<double>>;
using MatrixXf = Matrix<float, 0, 0, std::vector<float>>;
template <typename scalarType, int rowsAtCompileTime = 0, int colsAtCompileTime = 0, typename containerType = std::array<scalarType,(rowsAtCompileTime * colsAtCompileTime)>>
class Matrix
{
private:
containerType A;
int _rows;
int _cols;
public:
Matrix() = default;
Matrix(const Matrix& m);
int rows() const;
int cols() const;
int size() const;
//Overloaded operators
scalarType operator()(const int i, const int j) const;
scalarType& operator()(const int i, const int j);
Matrix operator+(const Matrix& m) const;
Matrix operator-(const Matrix& m) const;
Matrix operator*(const Matrix& m) const;
};[/CODE]
[CODE lang="cpp" title="Matrix.cpp"]
#pragma once
#include "Matrix.h"
#include <stdexcept>
template<typename scalarType, int rowsAtCompileTime, int colsAtCompileTime, typename containerType>
Matrix<scalarType, rowsAtCompileTime, colsAtCompileTime, containerType>::Matrix(const Matrix& m):A{m.A}, _rows{m.rows()}, _cols{m.cols()}, _size{m.size()}
{
}
template<typename scalarType, int rowsAtCompileTime, int colsAtCompileTime, typename containerType>
int Matrix<scalarType, rowsAtCompileTime, colsAtCompileTime, containerType>::rows() const
{
return _rows;
}
template<typename scalarType, int rowsAtCompileTime, int colsAtCompileTime, typename containerType>
int Matrix<scalarType, rowsAtCompileTime, colsAtCompileTime, containerType>::cols() const
{
return _cols;
}
template<typename scalarType, int rowsAtCompileTime, int colsAtCompileTime, typename containerType>
int Matrix<scalarType, rowsAtCompileTime, colsAtCompileTime, containerType>::size() const
{
return A.size();
}
/// <summary>
/// Coefficient accessors.
/// The primary coefficient accessor is the overloaded parenthesis operators. The data of the matrix
/// is stored in an underlying sequential container such as std::array or std::vector. The element
/// A(i,j) is at an offset of (i*_cols)+j in memory.
/// </summary>
/// <typeparam name="scalarType"></typeparam>
/// <typeparam name="containerType"></typeparam>
/// <param name="i">The row index</param>
/// <param name="j">The col index</param>
/// <returns>The element at position (i,j)</returns>
template<typename scalarType, int rowsAtCompileTime, int colsAtCompileTime, typename containerType>
scalarType Matrix<scalarType, rowsAtCompileTime, colsAtCompileTime, containerType>::operator()(const int i, const int j) const
{
containerType::const_iterator it{ A.begin() };
it = it + (i * _cols) + j;
if (it < A.end())
return *it;
else
throw std::out_of_range("\nError accessing an element beyond matrix bounds");
}
/// <summary>
/// Matrix addition.
/// Overload of the binary operator +. The left hand side and the right hand side matrix must have
/// the same number of rows and columns.
/// </summary>
/// <typeparam name="scalarType"></typeparam>
/// <typeparam name="containerType"></typeparam>
/// <param name="i"></param>
/// <param name="j"></param>
/// <returns></returns>
template<typename scalarType, int rowsAtCompileTime, int colsAtCompileTime, typename containerType>
scalarType& Matrix<scalarType, rowsAtCompileTime, colsAtCompileTime, containerType>::operator()(const int i, const int j)
{
containerType::iterator it{ A.begin() };
it = it + (i * _cols) + j;
if (it < A.end())
return *it;
else
throw std::out_of_range("\nError accessing an element beyond matrix bounds");
}
template<typename scalarType, int rowsAtCompileTime, int colsAtCompileTime, typename containerType>
Matrix<scalarType, rowsAtCompileTime, colsAtCompileTime, containerType> Matrix<scalarType, rowsAtCompileTime, colsAtCompileTime, containerType>::operator+(const Matrix& m) const
{
Matrix<scalarType, rowsAtCompileTime, colsAtCompileTime, containerType> result{};
if (this->rows() == m.rows() && this->cols() == m.cols())
{
containerType::const_iterator it1{ A.begin() };
containerType::const_iterator it2{ m.A.begin() };
containerType::iterator resultIter{ result.A.begin() };
while (it1 < A.end() && it2 < m.A.end())
{
*resultIter = *it1 + *it2;
++it1; ++it2; ++resultIter;
}
}
else
{
throw std::logic_error("Matrices have different dimensions; therefore cannot be added!");
}
return result;
}
template<typename scalarType, int rowsAtCompileTime, int colsAtCompileTime, typename containerType>
Matrix<scalarType, rowsAtCompileTime, colsAtCompileTime, containerType> Matrix<scalarType, rowsAtCompileTime, colsAtCompileTime, containerType>::operator-(const Matrix& B) const
{
Matrix<scalarType, rowsAtCompileTime, colsAtCompileTime, containerType> result{};
if (this->rows() == m.rows() && this->cols() == m.cols())
{
containerType::const_iterator it1{ A.begin() };
containerType::const_iterator it2{ m.A.begin() };
containerType::iterator resultIter{ result.A.begin() };
while (it1 < A.end() && it2 < m.A.end())
{
*resultIter = *it1 - *it2;
++it1; ++it2; ++resultIter;
}
}
else
{
throw std::logic_error("Matrices have different dimensions; therefore cannot be added!");
}
return result;
}
template<typename scalarType, int m, int n, int p, typename containerType>
Matrix<scalarType, m, p, containerType> operator*(const Matrix<scalarType, m, n, containerType>& A, const Matrix<scalarType, n, p, containerType>& B)
{
Matrix<scalarType, m, p, containerType> result;
for (int i{}; i < m; ++i)
{
for (int k{}; k < p; ++k)
{
scalarType sum{};
for (int j{}; j < n; ++j)
{
sum += A(i, j) * B(j, k);
}
result(i, k) = sum;
}
}
}
[/CODE]
Wake me up when their Mac version support C++.Latest Update:
Microsoft Visual Studio Community 2022 (64-bit) - Current Version 17.9.1
Awesome!
I agree, MS is not interested on thatIt's not going to happen, methinks.