I'm writing a templated matrix class using C++14. This class has three template parameters: the type of data stored (dtype), the number of rows (N) and the number of columns (M).
The class signature is
template<class dtype, size_t N, size_t M>
class Matrix
I've written a determinant member function that calls specific cases when a template parameter has a certain value. For example, when the number of rows is 1 it returns a copy of the matrix itself. Alternatively, when the number of rows is 2 or 3 it returns a 1x1 matrix of the same datatype with the determinant. Finally, when the number of rows is more than 3 it uses a recursive method to calculate the determinant based on the cofactor expansion of the determinant.
I am doing this as an exercise to better learn C++14 so I'd be very grateful for some help.
The code snippet causing issues is this part right here:
Matrix<dtype, 1, 1> det() const {
if (N != M || N >= 12) {
return Matrix<dtype, 1, 1>();
} else if (N == 1) {
return this->copy();
} else if (N == 2) {
return Matrix<dtype, 1, 1>(this->get(0, 0) * this->get(1, 1) - this->get(0, 1) * this->get(1, 0));
} else if (N == 3) {
return Matrix<dtype, 1, 1>(
this->get(0, 0) * (this->get(1, 1) * this->get(2, 2) - this->get(1, 2) * this->get(2, 1)) -
this->get(0, 1) * (this->get(1, 0) * this->get(2, 2) - this->get(1, 2) * this->get(2, 0)) +
this->get(0, 2) * (this->get(1, 0) * this->get(2, 1) - this->get(1, 1) * this->get(2, 0)));
} else if (N < 12) {
Matrix<dtype, 1, 1> determinant;
Matrix<dtype, N - 1, N - 1> sub_matrix;
for (size_t i = 0; i < N; ++i) {
sub_matrix = this->drop_cross(i, i);
Matrix<dtype, 1, 1> sub_det(sub_matrix.det());
if (i % 2 == 0) determinant = determinant + (this->get(0, i) * sub_det);
else if (i % 2 == 1) determinant = determinant - (this->get(0, i) * sub_det);
}
return determinant;
}
}
This function is called by this code:
#include "lin_alg_classes.h"
int main() {
Matrix<double, 3, 3> test3(1.0, true);
std::cout << std::endl;
std::cout << test3.det();
return 0;
}
And gives the following output:
In file included from C:\Users\ekin4\CLionProjects\mt_grav\main.cpp:5:0:
C:\Users\ekin4\CLionProjects\mt_grav\lin_alg_classes.h: In instantiation of 'Matrix<dtype, 1ull, 1ull> Matrix<dtype, N, M>::det() const [with dtype = double; long long unsigned int N = 3ull; long long unsigned int M = 3ull]':
C:\Users\ekin4\CLionProjects\mt_grav\main.cpp:29:28: required from here
C:\Users\ekin4\CLionProjects\mt_grav\lin_alg_classes.h:132:31: error: could not convert 'Matrix<dtype, N, M>::copy<double, 3ull, 3ull>()' from 'Matrix<double, 3ull, 3ull>' to 'Matrix<double, 1ull, 1ull>'
return this->copy();
What I don't understand is why it is calling the N = 1 case when it should be calling the N < 12 case. I have checked braces, parentheses and semicolons, and they are all correct, but for the life of me I don't understand what is happening.
Pre c++17 (if constexpr) you can use SFINAE and enable/disable different versions of det() according the values of N and M.
Something like (sorry: not tested)
template <std::size_t A = N, std::size_t B = M>
std::enable_if_t<(A != B) || (A > 11U), Matrix<dtype, 1, 1>> det() const
{ return Matrix<dtype, 1, 1>(); }
template <std::size_t A = N, std::size_t B = M>
std::enable_if_t<(A == B) && (A == 1U), Matrix<dtype, 1, 1>> det() const
{ return this->copy(); }
// other cases
Related
I would like to write this formula in C++ language:
(2<=n<=1e5), (1<=k<=n), (2<=M<=1e9).
I would like to do this without using special structures.
Unfortunately in this formula there are a lot of cases which effectively make modulation difficult. Example: ((n-k)!) mod M can be equal to 0, or ((n-1)(n-2))/4 may not be an integer. I will be very grateful for any help.
(n−1)!/(n−k)! can be handled by computing the product (n−k+1)…(n−1).
(n−1)! (n−1)(n−2)/4 can be handled by handling n ≤ 2 (0) and n ≥ 3
(3…(n−1) (n−1)(n−2)/2) separately.
Untested C++:
#include <cassert>
#include <cstdint>
class Residue {
public:
// Accept int64_t for convenience.
explicit Residue(int64_t rep, int32_t modulus) : modulus_(modulus) {
assert(modulus > 0);
rep_ = rep % modulus;
if (rep_ < 0)
rep_ += modulus;
}
// Return int64_t for convenience.
int64_t rep() const { return rep_; }
int32_t modulus() const { return modulus_; }
private:
int32_t rep_;
int32_t modulus_;
};
Residue operator+(Residue a, Residue b) {
assert(a.modulus() == b.modulus());
return Residue(a.rep() + b.rep(), a.modulus());
}
Residue operator-(Residue a, Residue b) {
assert(a.modulus() == b.modulus());
return Residue(a.rep() - b.rep(), a.modulus());
}
Residue operator*(Residue a, Residue b) {
assert(a.modulus() == b.modulus());
return Residue(a.rep() * b.rep(), a.modulus());
}
Residue QuotientOfFactorialsMod(int32_t a, int32_t b, int32_t modulus) {
assert(modulus > 0);
assert(b >= 0);
assert(a >= b);
Residue result(1, modulus);
// Don't initialize with b + 1 because it could overflow.
for (int32_t i = b; i < a; i++) {
result = result * Residue(i + 1, modulus);
}
return result;
}
Residue FactorialMod(int32_t a, int32_t modulus) {
assert(modulus > 0);
assert(a >= 0);
return QuotientOfFactorialsMod(a, 0, modulus);
}
Residue Triangular(int32_t a, int32_t modulus) {
assert(modulus > 0);
return Residue((static_cast<int64_t>(a) + 1) * a / 2, modulus);
}
Residue F(int32_t n, int32_t k, int32_t m) {
assert(n >= 2);
assert(n <= 100000);
assert(k >= 1);
assert(k <= n);
assert(m >= 2);
assert(m <= 1000000000);
Residue n_res(n, m);
Residue n_minus_1(n - 1, m);
Residue n_minus_2(n - 2, m);
Residue k_res(k, m);
Residue q = QuotientOfFactorialsMod(n - 1, n - k, m);
return q * (k_res - n_res) * n_minus_1 +
(FactorialMod(n - 1, m) - q) * k_res * n_minus_1 +
(n > 2 ? QuotientOfFactorialsMod(n - 1, 2, m) *
(n_res * n_minus_1 + Triangular(n - 2, m))
: Residue(1, m));
}
As mentioned in the other answer dividing factorials can be evaluated directly without division. Also you need 64bit arithmetics in order to store your subresults. And use modulo after each multiplication otherwise you would need very huge numbers which would take forever to compute.
Also you mention ((n-1)(n-2))/4 can be non just integer how to deal with that is questionable as we do not have any context to what you are doing. However you can move /2 before brackets (apply it on (n-1)! so modpi without 2 beware not to divide the already modded factorial!!!) and then you have no remainder as the (n-1)*(n-2)/4 become (n-1)*(n-2)/2 and the (n-1)*(n-2) is always odd (divisible by 2). The only "problem" is when n=2 as the n*(n-1)/2 is 1 but the /2 moved before bracket will round down the (n-1)! so you should handle it as special case by not moving the /2 before brackets (not included in code below).
I see it like this:
typedef unsigned __int64 u64;
u64 modpi(u64 x0,u64 x1,u64 p) // ( x0*(x0+1)*(x0+2)*...*x1 ) mod p
{
u64 x,y;
if (x0>x1){ x=x0; x0=x1; x1=x; }
for (y=1,x=x0;x<=x1;x++){ y*=x; y%=p; }
return y;
}
void main()
{
u64 n=100,k=20,m=123456789,a,b,b2,c,y;
a =modpi(n-k+1,n-1,m); // (n-1)!/(n-k)!
b =modpi(1,n-1,m); // (n-1)! mod m
b2=modpi(3,n-1,m); // (n-1)!/2 mod m
c =((n*(n-1)))%m; // 2*( n*(n-1)/2 + (n-1)*(n-2)/4 ) mod m
c+=(((n-1)*(n-2))/2)%m;
y =(((a*(k-n))%m)*(n-1))%m; // ((n-1)!/(n-k)!)*(k-1)*(n-1) mod m
y+=b; // (n-1)! mod m
y-=(((a*k)%m)*(n-1))%m; // ((n-1)!/(n-k)!)*k*(n-1) mod m
y+=(b2*c)%m; // (n-1)!*( n*(n-1)/2 + (n-1)*(n-2)/4 ) mod m
// here y should hold your answer
}
however be careful older compilers do not have full support of 64 bit integers and can produce wrong results or even does not compile. In such case use big integer lib or compute using 2*32bit variables or look for 32 bit modmul implementation.
The expression implies the use of a floating point type. Therefore, use the function fmod to get the remainder of the division.
I am writing my own library for a university project, containing the template classes: Vector and Matrix. In addition to these template classes, there are also related template functions for vectors and matrices. The professor explicitly told us to define the matrix as a one-dimensional array in which the elements are sorted by column (reasons of efficiency / optimization). The "matrix" template class has 3 template parameters: type of data allowed by the matrix, number of rows, number of columns.
template <class T, unsigned int M, unsigned int N>
class Matrix
Having said that, I immediately get to the problem. I'm writing a function that calculates the determinant of any matrix of dimension > 4, using the LaPlace rule for columns (using the first column).
I also wrote a function for two-dimensional matrices (called D2MatrixDet) and a function for three-dimensional matrices (called D3MatrixDet) tested and working:
template <class T>
double D2MatrixDet(const Matrix<T, 2, 2>& _m)
template <class T>
double D3MatrixDet(const Matrix<T, 3, 3>& _m)
The template function that I have to write has two template parameters: data type of the input matrix, dimension of the matrix (since the determinant is calculated for square matrices, only one dimension is enough). It is a recursive function; the variable "result" is the one that keeps the determinant in memory at each step. Below, the code I wrote.
template <class T, unsigned int D>
void DNMatrixDet(Matrix<T, D, D> _m, double result) //LaPlace Rule respect to the first column
{
const unsigned int new_D = D - 1;
Matrix<T, new_D, new_D> temp;
if (D > 3)
{
for (unsigned int i = 0; i < _m.row; ++i)
//Indicate the element to multiply
{
for (unsigned int j = _m.row, l = 0; j < _m.row * _m.column && l < pow(new_D, 2); ++j)
//Manage the element to be inserted in temp
{
bool invalid_row = false;
for (unsigned int k = 1; k < _m.row && invalid_row == false; ++k) //Slide over row
{
if (j == (i + k * _m.row))
{
invalid_row = true;
}
}
if (invalid_row == false)
{
temp.components[l] = _m.components[j];
++l;
}
}
DNMatrixDet(temp, result);
result += pow((-1), i) * _m.components[i] * result;
}
}
else if (D == 3)
{
result += D3MatrixDet(_m);
}
}
In main, I test the function using a 5 x 5 matrix.
When I try to compile, several errors come out, all very similar and that have to do with the size of the matrix which is decreased by one at each step. This is when the initial matrix size is 5 (LA is the name of the library and Test.cpp is the file that contains the main):
LA.h: In instantiation of 'void LA::DNMatrixDet(LA::Matrix<T, M, M>, double) [with T = double;
unsigned int D = 5]':
Test.cpp:437:33: required from here
LA.h:668:34: error: no matching function for call to 'D3MatrixDet(LA::Matrix<double, 5, 5>&)'
result += D3MatrixDet(_m);
~~~~~~~~~~~^~~~
In file included from Test.cpp:1:
LA.h:619:12: note: candidate: 'template<class T> double LA::D3MatrixDet(const LA::Matrix<T, 3, 3>&)'
double D3MatrixDet(const Matrix<T, 3, 3>& _m)
^~~~~~~~~~~
LA.h:619:12: note: template argument deduction/substitution failed:
In file included from Test.cpp:1:
LA.h:668:34: note: template argument '5' does not match '3'
result += D3MatrixDet(_m);
~~~~~~~~~~~^~~~
This is when the size becomes 4:
LA.h: In instantiation of 'void LA::DNMatrixDet(LA::Matrix<T, M, M>, double) [with T = double;
unsigned int D = 4]':
LA.h:662:28: required from 'void LA::DNMatrixDet(LA::Matrix<T, M, M>, double) [with T = double;
unsigned int D = 5]'
Test.cpp:437:33: required from here
LA.h:668:34: error: no matching function for call to 'D3MatrixDet(LA::Matrix<double, 4, 4>&)'
In file included from Test.cpp:1:
LA.h:619:12: note: candidate: 'template<class T> double LA::D3MatrixDet(const LA::Matrix<T, 3, 3>&)'
double D3MatrixDet(const Matrix<T, 3, 3>& _m)
^~~~~~~~~~~
LA.h:619:12: note: template argument deduction/substitution failed:
In file included from Test.cpp:1:
LA.h:668:34: note: template argument '4' does not match '3'
result += D3MatrixDet(_m);
~~~~~~~~~~~^~~~
And so on. It keeps going down until starting over at 4294967295 (which I found to be the upper limit of a 32 bit "unsigned int") and continuing to go down until I reach the maximum number of template instances (= 900).
At each iteration, the compiler always checks the function for calculating the determinant of a 3 x 3, even if that function is only executed when the input matrix is a 3 x 3. So why does it check something that in theory should never to happen?
I double-checked the mathematical logic of what I wrote several times, even with the help of a matrix written on paper and slowly carrying out the first steps. I believe and hope it is right. I'm pretty sure the problem has to do with using templates and recursive function.
I apologize for the very long question, I tried to explain it in the best possible way. I hope I have well explained the problem.
EDIT:
Fixed problem by defining "if constexpr" at the beginning of DNMatrixDet function. The compilation is successful. I just need to fix the algorithm, but this is beyond the scope of the post. Below is the reprex with the changes made:
template <class T, unsigned int M, unsigned int N>
class Matrix
{
public:
T components[M * N];
unsigned int row = M;
unsigned int column = N;
Matrix()
{
for (unsigned int i = 0; i < M * N; ++i)
{
components[i] = 1;
}
}
Matrix(T* _c)
{
for (unsigned int i = 0; i < M * N; ++i, ++_c)
{
components[i] = *_c;
}
}
friend std::ostream& operator<<(std::ostream& output, const Matrix& _m)
{
output << _m.row << " x " << _m.column << " matrix:" << std::endl;
for (unsigned int i = 0; i < _m.row; ++i)
{
for (unsigned int j = 0; j < _m.column; ++j)
{
if (j == _m.column -1)
{
output << _m.components[i + j*_m.row];
}
else
{
output << _m.components[i + j*_m.row] << "\t";
}
}
output << std::endl;
}
return output;
}
};
template <class T>
double D3MatrixDet(const Matrix<T, 3, 3>& _m)
{
double result = _m.components[0] * _m.components[4] * _m.components[8] +
_m.components[3] * _m.components[7] * _m.components[2] +
_m.components[6] * _m.components[1] * _m.components[5] -
(_m.components[6] * _m.components[4] * _m.components[2] +
_m.components[3] * _m.components[1] * _m.components[8] +
_m.components[0] * _m.components[7] * _m.components[5]);
return result;
}
template <class T, unsigned int D>
void DNMatrixDet(Matrix<T, D, D> _m, double result)
{
Matrix<T, D - 1, D - 1> temp;
if constexpr (D > 3)
{
for (unsigned int i = 0; i < D; ++i)
{
for (unsigned int j = D, l = 0; j < D * D && l < (D - 1) * (D - 1); ++j)
{
bool invalid_row = false;
for (unsigned int k = 1; k < D && invalid_row == false; ++k)
{
if (j == (i + k * D))
{
invalid_row = true;
}
}
if (invalid_row == false)
{
temp.components[l] = _m.components[j];
++l;
}
}
DNMatrixDet(temp, result);
result += i & 1 ? -1 : 1 * _m.components[i] * result;
}
}
else if (D == 3)
{
result += D3MatrixDet(_m);
}
}
int main()
{
double m_start[25] = {4, 9, 3, 20, 7, 10, 9, 50, 81, 7, 20, 1, 36, 98, 4, 20, 1, 8, 5, 93, 47, 21, 49, 36, 92};
Matrix<double, 5, 5> m = Matrix<double, 5, 5> (m_start);
double m_det = 0;
DNMatrixDet(m, m_det);
std::cout << "m is " << m << std::endl;
std::cout << "Det of m is " << m_det << std::endl;
return 0;
}
When you pass as an argument _m with the type Matrix<T, 5, 5>, the trailing else branch contains the code result += D3MatrixDet(_m);. The compiler will still try to compile this and notice that it cannot find a matching constructor.
Since we know at compile-time whether to take this branch or not, we can instruct the compiler by using if constexpr instead. Since we are within a template, the compiler will no longer check this branch if it is discarded.
So let's change if (D > 3) to if constexpr (D > 3).
I have read few other answers and checked a blog on codeforces. All suggest that it must be some potential overflow. I have tested it for all the testcases from n = 1 to n = 45. I don't see that overflow.
class Solution {
public:
int checkSteps(int n, vector<int>&cache){
if(n <= 0)
return cache[0];
else if(n == 1){
return cache[1];
}
else if(n == 2){
return cache[2];
}
if(cache[n] > 0) return cache[n];
cache[n] = checkSteps(n-1, cache) + checkSteps(n-2, cache);
return cache[n];
}
int climbStairs(int n){
vector<int> cache(n+1, 0);
cache[0] = 0;
cache[1] = 1;
cache[2] = 2;
int result = checkSteps(n, cache);
return result;
}
You can also use the Fib Number formula (Golden Ratio) for this problem, will get accepted:
struct Solution {
static const inline int climbStairs(const int n) {
double ways = 1 / pow(5, 0.5) * (pow((1 + pow(5, 0.5)) / 2, -~n) - pow((1 - pow(5, 0.5)) / 2, -~n));
return (int) ways;
}
};
-~n is simply (n + 1), just a bit shorter
or based on your approach, we would just iterate:
struct Solution {
static const inline int climbStairs(const int n) {
int first = 1;
int second = 0;
int ways = 0;
for (int iter = 0; iter < n; iter++) {
ways = first + second;
second = first;
first = ways;
}
return ways;
}
};
References
For additional details, you can see the Discussion Board. There are plenty of accepted solutions with a variety of languages and explanations, efficient algorithms, as well as asymptotic time/space complexity analysis1, 2 in there.
If you are preparing for interviews:
We would want to write bug-free and clean codes based on standards and conventions (e.g., c1, 2, c++1, 2, java1, 2, c#1, 2, python1, javascript1, go1, rust1).
I am trying to push data to my vector, but I'm met with an error:
expression must have class type
This is my code:
float calcX(float u, float v)
{
return (((-90.0*pow(u, 5) + 225.0*pow(u, 4) - 270.0*pow(u, 3) + 180.0*pow(u, 2) - 45.0*u)*cos(pi*v)));
}
float calcY(float u, float v)
{
return (160.0*pow(u, 4) - 320.0*pow(u, 3) + 160.0*pow(u, 2) - 5.0f);
}
float calcZ(float u, float v)
{
return (((-90.0*pow(u, 5) + 225.0*pow(u, 4) - 270.0*pow(u, 3) + 180.0*pow(u, 2) - 45.0*u)*sin(pi*v)));
}
typedef float point3[3];
std::vector <point3*> createEggBuffor(int n=20)
{
std::vector <point3*> egg;
for (int u = 0; u < n; u++) {
for (int v = 0; v < n; v++) {
egg[u][v][0].push_back(calcX(static_cast<float>(u) / (n - 1), static_cast<float>(v) / (n - 1)));
egg[u][v][1].push_back(calcY(static_cast<float>(u) / (n - 1), static_cast<float>(v) / (n - 1)));
egg[u][v][2].push_back(calcZ(static_cast<float>(u) / (n - 1), static_cast<float>(v) / (n - 1)));
}
}
return egg;
}
What this error means?
egg[u] is a point3*. egg[u][v] is a point3 (which is an array of 3 floats). So egg[u][v][N] is a float. float is a built-in type, and does not have a member function named push_back, or any members at all. The error is telling you that, since it is not a class type, you can't use the dot operator to access members of it (since it doesn't have any).
If you're trying to push back elements onto your egg vector, it would look like this:
egg.push_back(something);
Where something is an expression of type point3*.
int memo[101][101];
int findMinPath(vector<vector<int> >& V, int r, int c) {
int R = V.size();
int C = V[0].size();
if (r >= R || c >= C) return 100000000; // Infinity
if (r == R - 1 && c == C - 1) return 0;
if (memo[r][c] != -1) return memo[r][c];
memo[r][c] = V[r][c] + min(findMinPath(V, r + 1, c), findMinPath(V, r, c + 1));
return memo[r][c];
}
Callsite :
memset(memo, -1, sizeof(memo));
findMinPath(V, 0, 0);
In the above code, what will be the worst case time complexity?.I understand that every function will call other functions atmost one time, but I am not clear with the calculation of the time complexity.
The memoisation is the key here. Normally this would have exponential growth, but because you never perform additional recursive steps if the result is previously computed in memo, then it is reduced to the number of elements in memo as a worst case. i.e. O( 101 x 101 )