typedef double

I would like to calculate the inverse of a lower triangular matrix.But, I got errors.


#include<iostream>
#include<cmath>
#include<fstream>
using namespace std;


//Main function
//All the operations is done here
int main(int argc, char** argv)
{

float b[10][10];
int n = 4;

double L[4][4] = { { 1, 0, 0, 0 },{ 4, 1, 0, 0 },{ 2, 5, 1, 0 },{ 6, 8, 4, 1 } };

int i, j, k;
double *p_i, *p_j, *p_k;
double sum;

// Invert the diagonal elements of the lower triangular matrix L.

for (k = 0, p_k = L; k < n; p_k += (n + 1), k++) {
if (*p_k == 0.0) return -1;
else *p_k = 1.0 / *p_k;
}

// Invert the remaining lower triangular matrix L row by row.

for (i = 1, p_i = L + n; i < n; i++, p_i += n) {
for (j = 0, p_j = L; j < i; p_j += n, j++) {
sum = 0.0;
for (k = j, p_k = p_j; k < i; k++, p_k += n)
sum += *(p_i + k) * *(p_k + j);
*(p_i + j) = -*(p_i + i) * sum;
}
}
cout << "\n";
system("pause");
return 0;

}


These are the errors:
In function 'int main(int, char**)':
23:18: error: cannot convert 'double [4][4]' to 'double*' in assignment
30:18: error: cannot convert 'double (*)[4]' to 'double*' in assignment
31:19: error: cannot convert 'double [4][4]' to 'double*' in assignment


Many thanks.
If you had formatted your code with code tags so I could see some line numbers, I would feel like going through your code. But what says it to your mood expecting some help if you not even have the time using code tags?
Hello nurulhudaismail,

PLEASE ALWAYS USE CODE TAGS (the <> formatting button), to the right of this box, when posting code.

It makes it easier to read your code and also easier to respond to your post.

http://www.cplusplus.com/articles/jEywvCM9/
http://www.cplusplus.com/articles/z13hAqkS/

Hint: You can edit your post, highlight your code and press the <> formatting button.
You can use the preview button at the bottom to see how it looks.

I found the second link to be the most help.

I am not sure what the answer is yet, but I did figure out that "L", a better name here to describe what the variable is or does would help, is defined as a 2D array and "p_k" is defined as a pointer to hold a single address, but the 2Darray has rows and columns, so it is not really a single address.

Even when I tried double *p_k = &L it did not work.

Someone more use to pointers will likely explain this before I can figure it out, But I am getting better with pointers.

BTW the "arg" variables inside the ()s of main are not used or needed.

You have defined five variables as "double" and one array as "float". Be consistent with your types and "double" is the preferred floating point type.

Also in regard to the {}s again be consistent. You end your first line for "main by pressing enter and starting the opening brace in the first column, but with your for loops you end the line with the opening brace. As much as I have seen this it still makes the code hard to follow. The advantage of putting the opening brace on the next line and along with proper indenting the code is much easier to read and follow. It also makes matching the {}s up when they are in the same column.

With the variable names that you have it makes it hard to figure out what yo are trying to do. I will admit that my understand of math is not what I would like it to be, but given a little time I can usually figure out what is trying to be done.

Hope that helps,

Andy
L is an 2 dimensional array. It cannot implicitly casted to a pointer. This can only be applied to a 1 dimensional array.

Thus

p_i = L + n

will be a compiler error.

But writing this:

p_i = L[n]

will be okay.
So I would generally suggest to use []:

*(p_i + k) -> p_i[k]

which is simpler to read. And by the way: I would suggest to use more descriptive names.
closed account (1vRz3TCk)
A bit of code to help you see what is going on and to make it easier to talk about issues...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<iostream>

int main(int argc, char** argv)
{
	int data[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
	int *data_ptr;
	
	data_ptr = (int *) data;
	for (int i = 0; i < 9; i++, data_ptr++)
	{
		std::cout << *data_ptr << " ";
	}
	std::cout << "\n";
	//
	//
	int(*dataSub_ptr)[3];
	dataSub_ptr = data;
	for (int i = 0; i < 3; i++, dataSub_ptr++)
	{
		std::cout << *dataSub_ptr[0] << " ";
	}

	return 0;
}
1 2 3 4 5 6 7 8 9
1 4 7
Last edited on
Hello nurulhudaismail,

A suggestion to better write your code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using namespace std;  // <--- Best not to use.

//Main function
//All the operations is done here
int main()
{

	constexpr size_t MAXROW_B{ 10 };
	constexpr size_t MAXCOL_B{ 10 };
	constexpr size_t MAXROW_L{ 4 };
	constexpr size_t MAXCOL_L{ 4 };

	double b[MAXROW_B][MAXCOL_B];
	int n = 4;

	double L[MAXROW_L][MAXCOL_L] =
	{
		{ 1, 0, 0, 0 },
		{ 4, 1, 0, 0 },
		{ 2, 5, 1, 0 },
		{ 6, 8, 4, 1 }
	};

	int i, j, k;
	double *p_i{ nullptr }, *p_j{ nullptr }, *p_k{ nullptr };
	double sum{};

The visual representation of the initializing of the 2D array can be very helpful especially when writing the initializers.

Some variables like the "int"s do not need initialized because they are given a value in the for loops. The pointers should be set to "nullptr"s just to be safe.

The use of system anything should be avoided.

I use this code when I need to stop or pause the program especially when debugging or testing:
1
2
3
4
5
6
// <--- Used mostly for testing in Debug mode. Removed if compiled for release.
// <--- Used to keep the console window open in Visual Studio Debug mode.
// The next line may not be needed. If you have to press enter to see the prompt it is not needed.
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
std::cout << "\n\n Press Enter to continue: ";
std::cin.get();

I comment out or remove when compiling for "release" mode.

Hope that helps,

Andy
I think you would be better with a vector< vector<double> >

You aren't outputting the result.

Your result is going back into the original matrix. This prohibits you from checking your result by matrix multiplication.
Last edited on
Do you have any other ways that avoid me to use a pointer such as *p_i or *p_j?
nurulhudaismail wrote:
Do you have any other ways that avoid me to use a pointer such as *p_i or *p_j?

Why can't you use a vector< vector<double> >?
Then you could simply refer to your matrix elements as L[i][j].

For your matrix it gives inverse(L) as
1	0	0	0	
-4	1	0	0	
18	-5	1	0	
-46	12	-4	1



Last edited on
I really understand the algorithm of a lower triangular matrix inversion as below:


1. for k = 1 to n
2. X[k,k] = l/L[k,k]
3. for i = k+1 to n
4. X[i,k] = -L[i, k:i-1]*X[k:i-1,k]/L[i,i]
5. end for i
6. end for k

However, I face a difficulities to write the simplest way in c++. Actually, I am not familiar using pointer syntax such as (*pointer).

nurulhudaismail wrote:
Actually, I am not familiar using pointer syntax such as (*pointer).
If you don't like them ... then don't use them!

I've given you a perfectly good solution in your other thread at
http://www.cplusplus.com/forum/beginner/245146/#msg1084687

Please DON'T CREATE MULTIPLE THREADS.



Here are two more solutions (overwriting the original matrix). Take your pick.

Direct array calculation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<iostream>
using namespace std;


int main()
{
   const int N = 4;
   double L[N][N] = { { 1, 0, 0, 0 }, { 4, 1, 0, 0 }, { 2, 5, 1, 0 }, { 6, 8, 4, 1 } };

   // Invert the diagonal elements
   for ( int i = 0; i < N; i++ )
   {
      if ( L[i][i] == 0.0 ) return -1;
      L[i][i] = 1.0 / L[i][i];
   }

   // Invert the remaining lower triangular matrix L row by row.
   for ( int i = 1; i < N; i++ )
   {
      for ( int j = 0; j < i; j++)
      {
         double sum = 0.0;
         for ( int k = j; k < i; k++ ) sum += L[i][k] * L[k][j];
         L[i][j] = -sum * L[i][i];
      }
   }

   // Write out
   for ( int i = 0; i < N; i++ )
   {
      for ( int j = 0; j < N; j++ ) cout << L[i][j] << '\t';
      cout << '\n';
   }
}


Pointers:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include<iostream>
using namespace std;


int main()
{
   const int N = 4;

   double L[N][N] = { { 1, 0, 0, 0 }, { 4, 1, 0, 0 }, { 2, 5, 1, 0 }, { 6, 8, 4, 1 } };

   double *p, *p0 = &L[0][0];
   int i, j, k;

   // Invert the diagonal elements
   for ( k = 0, p = p0; k < N; k++, p += ( N + 1 ) )
   {
      if ( *p == 0.0 ) return -1;
      *p = 1.0 / *p;
   }

   // Invert the remaining lower triangular matrix L row by row.
   for ( i = 0, p = p0; i < N; i++, p += ( N + 1 ) )
   {
      for ( j = 0; j < i; j++)
      {
         double sum = 0.0;
         for ( k = j; k < i; k++ ) sum += *( p0 + N * i + k ) * *( p0 + N * k + j );
         *( p0 + N * i + j ) = -sum * *p;
      }
   }

   for ( i = 0, p = p0; i < N; i++ )
   {
      for ( int j = 0; j < N; j++, p++ ) cout << *p << '\t';
      cout << '\n';
   }
}

Last edited on
What does "straight forward codes" mean?

Does it mean "check if any existing library offers the feature"?

If yes, then websearch. Almost on top of hits:
https://www.gnu.org/software/gsl/doc/html/linalg.html#triangular-systems
thank you lastchance (2541) and sorry for double thread. Thanks for your help.
Topic archived. No new replies allowed.