Search code examples
c#c++code-translation

"Cartiesian Product" Method in C++


I have the following code in come C++ I need to translate to C#

int** _cartesianProduct(int sizeA, int sizeB) {

    int** array = (int**)malloc(sizeof(int*) * sizeA * sizeB + sizeof(int) * 2 * sizeA * sizeB);

    int* ptr = (int*)(array + sizeA * sizeB);
    for (int i = 0; i < sizeA * sizeB; ++i)
        array[i] = (ptr + 2 * i);

    for (int i = 0; i < sizeA; ++i)
        for (int k = 0; k < sizeB; ++k) {
            array[i * sizeB + k][0] = i;
            array[i * sizeB + k][1] = k;
        }

    return array;
}

This creates an array of "Cartesian products" for all possible combinations of the numbers passed to it. My specific confusion here is what this block is doing?

int* ptr = (int*)(array + sizeA * sizeB);
    for (int i = 0; i < sizeA * sizeB; ++i)
        array[i] = (ptr + 2 * i);

Or even more specifically, this line int* ptr = (int*)(array + sizeA * sizeB);?


Solution

  • This allocates a single block of memory to store a 2D array, as an array of arrays. C arrays of arrays are stored as an array of pointers to further arrays; my first thought was 'yuck', but there's some elegance here in that everything is returned as a single block of memory that can be free()ed in one go afterwards.

    This code

    1. allocates space for (sizeA * sizeB) int-pointers, and then 2 * sizeA * sizeB; store this as an int** pointer, i.e. we'll use the first block of this as the top level of our 2D array
    2. (the code you quoted) sets up the pointers for the top level array to point to two-int blocks of the remaining memory
    3. uses the 2D array to store pairs of values in the range 0-sizeA, 0-sizeB

    How to port this to C#? It depends on how you want to consume the values generated. I'd probably make this an array of value tuples,

    var array = Enumerable.Range(0, sizeA).SelectMany(a =>
                    Enumerable.Range(0, sizeB).Select(b => (a,b))).ToList();
    

    or .ToArray(). If you do want the jagged array version you can new[] { a, b } instead in the inner select.