zaidjan1295
zaidjan1295

Reputation: 39

Function defined in scope but the compiler complains that it is out of scope

I tried to implement strassens algorithm for two 2x2 matrices in order to make a recursive matrix multiplication algorithm however the implementation doesn't compile giving me errors like:

"strassen was not declared in this scope" and "unqualified-id"

Here's the code:

#include <iostream>
#include <cstdlib>

using namespace std;

int[][] strassen(int A[][2], int B[][2])
{
    int s1 = B[0][1] - B[1][1];
    int s2 = A[0][0] + A[0][1];
    int s3 = A[1][0] + A[1][1];
    int s4 = B[1][0] - B[0][0];
    int s5 = A[0][0] + A[1][1];
    int s6 = B[0][0] + B[1][1];
    int s7 = A[0][1] - A[1][1];
    int s8 = B[1][0] + B[1][1];
    int s9 = A[0][0] - A[1][0];
    int s10 = B[0][0] + B[0][1];

    int p1 = A[0][0] * s1;
    int p2 = s2 * B[1][1];
    int p3 = s3 * B[0][0];
    int p4 = A[1][1] * s4;
    int p5 = s5 * s6;
    int p6 = s7 * s8;
    int p7 = s9 * s10;

int C[2][2];

C[0][0] = p5 + p4 - p2 + p6;
C[0][1] = p1 + p2;
C[1][0] = p3 + p4;
C[1][1] = p5 + p1 - p3 - p7;

return C[][];
}

int main()
{
    int A[2][2] = {{1,3},{7,5}};
    int B[2][2] = {{6,8},{4,2}};
    int C[][2] = strassen(A,B);
    cout<<C[0][0]<<endl<<C[0][1]<<endl<<C[1][0]<<endl<<C[1][1]<<endl;
    return 0;
}

Could you tell me why I'm getting the compile time errors. I also need to know how to malloc space for a 2D array, as my current implementation of C will go out of scope as soon as the function exits returning garbage values.

Upvotes: 0

Views: 181

Answers (2)

dtell
dtell

Reputation: 2568

As mentioned in many comments your solution is typical C style which can create many problems (especially when you are a beginner). C++ provides powerful, memory save and easy to use workarounds for a lot of cases where C can get complicated.

Don't get me wrong: C is a great language but when you decided to use C++, use it!

For your case std::array is perfect since you use arrays of clearly defined size. It works like this: You define the size and the type of its content with std::array<type,size>.

The following code implements your attempt using std::array:

#include <iostream>
// #include <cstdlib> // use C libraries only when really needed
#include <array> 

using namespace std;

array<array<int,2>,2> strassen(array<array<int,2>,2> A, array<array<int,2>,2> B){
    int s1 = B[0][1] - B[1][1];
    int s2 = A[0][0] + A[0][1];
    int s3 = A[1][0] + A[1][1];
    int s4 = B[1][0] - B[0][0];
    int s5 = A[0][0] + A[1][1];
    int s6 = B[0][0] + B[1][1];
    int s7 = A[0][1] - A[1][1];
    int s8 = B[1][0] + B[1][1];
    int s9 = A[0][0] - A[1][0];
    int s10 = B[0][0] + B[0][1];

    int p1 = A[0][0] * s1;
    int p2 = s2 * B[1][1];
    int p3 = s3 * B[0][0];
    int p4 = A[1][1] * s4;
    int p5 = s5 * s6;
    int p6 = s7 * s8;
    int p7 = s9 * s10;

    array<array<int,2>,2> C;

    C[0][0] = p5 + p4 - p2 + p6;
    C[0][1] = p1 + p2;
    C[1][0] = p3 + p4;
    C[1][1] = p5 + p1 - p3 - p7;

    return C;
}

int main(){
    array<array<int,2>,2> A  {{{{1,3}},{{7,5}}}};
    array<array<int,2>,2> B  {{{{6,8}},{{4,2}}}};
    array<array<int,2>,2> C = strassen(A,B);
    cout<<C[0][0]<<endl<<C[0][1]<<endl<<C[1][0]<<endl<<C[1][1]<<endl;
}

As you did with C style arrays, two dimensional arrrays are realized as array of array thus std::array<std::array<T,size>,size>>.

For the strange looking number of braces in the initialization of A and B see the top answer to Why can't simple initialize (with braces) 2D std::array? [duplicate].

Please note that the way I initialized the arrays in main() requires the -std=c++11 compiler flag. Compile with something like gcc -std=c++11 -o strassen strassen.c

Upvotes: 1

Sacha
Sacha

Reputation: 245

There are a couple of reasons why your code doesn't compile: You are getting the error of function out of scope because the function strassen is not compiling, and it is not compiling because you are returning an array declared inside the function.

A good rule of thumb is to never return arrays nor pass them as arguments, use references instead, it saves memory and time.

Heres is a solution without using dynamic memory (although I think it would be easier to do it that way)

#include <iostream>

using namespace std;

void strassen(int (&A)[2][2], int (&B)[2][2], int (&C)[2][2])
{
    int s1 = B[0][1] - B[1][1];
    int s2 = A[0][0] + A[0][1];
    int s3 = A[1][0] + A[1][1];
    int s4 = B[1][0] - B[0][0];
    int s5 = A[0][0] + A[1][1];
    int s6 = B[0][0] + B[1][1];
    int s7 = A[0][1] - A[1][1];
    int s8 = B[1][0] + B[1][1];
    int s9 = A[0][0] - A[1][0];
    int s10 = B[0][0] + B[0][1];

    int p1 = A[0][0] * s1;
    int p2 = s2 * B[1][1];
    int p3 = s3 * B[0][0];
    int p4 = A[1][1] * s4;
    int p5 = s5 * s6;
    int p6 = s7 * s8;
    int p7 = s9 * s10;

    C[0][0] = p5 + p4 - p2 + p6;
    C[0][1] = p1 + p2;
    C[1][0] = p3 + p4;
    C[1][1] = p5 + p1 - p3 - p7;

}

int main()
{
    int A[2][2] = {{1,3},{7,5}};
    int B[2][2] = {{6,8},{4,2}};
    int C[2][2];

    strassen(A,B,C);

    cout<<C[0][0]<<endl<<C[0][1]<<endl<<C[1][0]<<endl<<C[1][1]<<endl;

    return 0;
}

Note that you are passing C as a reference to the function so the changes that you make to it inside the function will also affect it outside the function

Upvotes: 0

Related Questions