On Monday, 17 February 2020 at 14:04:34 UTC, Adnan wrote:
cdsa ~master: building configuration "cdsa-test-library"...
source/strassens_matmul.d(22,16): Error: cannot implicitly convert expression &mat[row][column] of type const(uint)* to uint* source/strassens_matmul.d(37,36): Error: template instance strassens_matmul.getPointPtr!uint error instantiating
source/strassens_matmul.d(48,29):

I'd just finished writing a long post explaining the stuff you've apparently figured out. Ah well. :p

In this case, getPointPtr return T*, but takes scope const ref T[][]. Since getPointPtr always takes a mutable array, you could just get rid of const on its parameters. Alternatively, if you want to be able to use it on arrays of different constness, you could use inout:

inout(T)* getPointPtr(T)(inout T[][] mat, size_t row, size_t column) {

This will return a pointer to a mutable T if that's what the array holds when you call the function, const(T) if it's a const array, immutable(T) if it's immutable, and so on.

The same can be done with the other functions you have.

You are also somewhat overusing const, scope and ref, I'd say - you should not take an array by ref unless you plan on modifying it, which you are not doing in getPointPtr or any other of your functions. scope may be worth it, as it guarantees you won't be sending the data elsewhere.

None of these are necessary on your ulongs, which are passed by value and never attempted modified. If you really like the extra guarantee that you don't accidentally modify them, feel free to keep 'const', but 'scope' on a ulong does nothing, and it's been argued it should be a compiler error.

Lastly, you're using ulongs a lot, and this is mostly correct when compiling for 64-bit, but makes code fail to compile for 32-bit. Using size_t instead makes for code that works for both.

All in all, I end up with this code:

module strassens_matmul;

debug {
    static import std;
}

package {
    size_t getRowSize(T)(const T[][] mat) {
        return mat[0].length;
    }

    size_t getColumnSize(T)(const T[][] mat) {
        return mat.length;
    }

    T[][] createMatrix(T)(size_t rowSize, size_t columnSize) {
        return new T[][](rowSize, columnSize);
    }

    /// row and column are 0 index-based
inout(T)* getPointPtr(T)(inout T[][] mat, size_t row, size_t column) {
        return &mat[row][column];
    }

T getPointCopy(T)(const T[][] mat, size_t row, size_t column) {
        return mat[row][column];
    }

    T[][] mulIterative(T)(const T[][] mat1, const T[][] mat2) {
auto result = createMatrix!T(getRowSize!T(mat1), getColumnSize!T(mat2));
        foreach (row; 0 .. mat1.getRowSize()) {
            foreach (column; 0 .. mat2.getColumnSize()) {
                T value;
                foreach (i; 0 .. mat1.getRowSize()) {
value += mat1.getPointCopy(row, i) * mat2.getPointCopy(i, column);
                }
                *result.getPointPtr(row, column) = value;
            }
        }
        return result;
    }
}

unittest {
    const uint[][] matA = [[10, 20, 10], [4, 5, 6], [2, 3, 5]];
    const uint[][] matB = [[3, 2, 4], [3, 3, 9], [4, 4, 2]];
const uint[][] matC = [[130, 120, 240], [51, 47, 73], [35, 33, 45]];
    assert(matA.mulIterative(matB) == matC);
}

--
  Simen

Reply via email to