-1

I am implementing code for convolution in C++ (I know it exists already but I'm just doing it for practice since I'm a beginner), and while I can get the correct output, there are certain methods I'm trying that are giving unexpected output depending on how I access the values of the convolution that I store in an array and I'm not sure why. The function code that works, whether I access the values by array indexing or with pointer incrementing, is:

void conv(int M, int* h, int L, int* x, int* y) {
    int n, m = 0;
    for (n = 0; n < L + M - 1; n++) {
        for (m = std::max(0, n - L + 1); m <= std::min(n, M - 1); m++) {
            *(y+n) += *(h + m) * *(x + n - m);
        };
        std::cout << "using array index: " << std::endl;
        std::cout << "n = " << n << " " << "y = " << y[n] << " " << std::endl;
        std::cout << std::endl;
        std::cout << "using pointer: " << std::endl;
        std::cout << "n = " << n << " " << "y = " << *(y+n) << " " << std::endl;
        std::cout << std::endl;
        //y++;
    }
}

However, if I make slight changes to this (numbered below):

void conv(int M, int* h, int L, int* x, int* y) {
    int n, m = 0;
    for (n = 0; n < L + M - 1; n++) {
        for (m = std::max(0, n - L + 1); m <= std::min(n, M - 1); m++) {
            *y += *(h + m) * *(x + n - m); //[1]
        };
        std::cout << "using array index: " << std::endl;
        std::cout << "n = " << n << " " << "y = " << y[n] << " " << std::endl;
        std::cout << std::endl;
        std::cout << "using pointer: " << std::endl;
        std::cout << "n = " << n << " " << "y = " << *y << " " << std::endl; //[2]
        std::cout << std::endl;
        y++; //[3]
    }
}

In this case, only accessing the values via pointer provides the correct output, while accessing it via array indexing provides random garbage.

My test code is:

int main()
{
    const int M = 5; const int L = 6;
    int y[M + L - 1] = {};
    int x[L] = { 1, -2, 5, 3, 8, -4 };
    int h[M] = { 1,2,3,4,5 };
    int* yPtr = y; int* hPtr = h; int* xPtr = x;
    conv(M, hPtr, L, xPtr, yPtr);
    std::cout << "value after leaving conv" << std::endl;
    for (int i = 0; i < M+L-1; i++) {
        std::cout << "i = " << i << " " << "y = " <<  y[i] << std::endl;
    }
}

which always provides the correct output even when accessing the array elements in the for loop of the conv provides the incorrect output.

For reference, the correct output is y = {1, 0, 4, 11, 26, 31, 53, 35, 24, -20}.

What am I doing wrong in the second example of conv to be getting the wrong values when using array indexing?

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • *and I'm not sure why* -- There is a tool that comes with your compiler toolset, and that is a [debugger](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems). You have not mentioned whether you have used the debugger. – PaulMcKenzie Feb 17 '21 at 15:07
  • If you consistently use indexing instead, you will see that the first prints `y[n]` twice, while the second prints first `y[n]` and then `y[0]`. – molbdnilo Feb 17 '21 at 15:14

2 Answers2

1

In the second version of the code, you are incrementing y as you go through the loop, so y[n] in the second version is equivalent to y[2*n] in the first. Once n reaches half the size of the array, y[n] is past the end of the array, thus garbage. *y is equivalent to y[0].

Pierre Abbat
  • 485
  • 4
  • 10
  • Sorry, I'm not quite understanding why this is the issue. If ```y++``` just increments the pointer, why does it make ```y[n]``` become ```y[2n]``` when ```n``` is incremented? I thought that doing this would make ```y``` point to the next array index, but all indices would be accessible without having to account for that, which I'm guessing is not the case. Is this then why once I print out the whole array in ```main``` I get the correct response regardless of whether ```conv``` is working, because the incremented pointer that is causing the indexing issue no longer exists? – Jacob Gehrig Feb 17 '21 at 15:33
  • Let's say you passed an array `b` to `y`. When `n` is 3, `y` is `b+3`. If you then access `y[3]`, that's `b[6]`. – Pierre Abbat Feb 17 '21 at 18:33
0

Your example is sufficiently weird to be a little difficult to read, but from your second version, this is fishy:

    std::cout << "n = " << n << " " << "y = " << y[n] << " " << std::endl;

You're incrementing y as you go, so y[n] is going to go to weird places fast.

I saved Y as int * yOrig = y; and then used that, and I think I'm getting the output you expect, but I'm not sure.

Joseph Larson
  • 8,530
  • 1
  • 19
  • 36