Task: Kronecker product based fractals

C: #include<graphics.h>
#include<stdlib.h>
#include<stdio.h>

typedef struct{
    int row, col;
}cell;

int ROW,COL,SUM=0;

unsigned long raiseTo(int base,int power){
    if(power==0)
        return 1;
    else
        return base*raiseTo(base,power-1);
}

cell* kroneckerProduct(char* inputFile,int power){
    FILE* fp = fopen(inputFile,"r");
    
    int i,j,k,l;
    unsigned long prod;
    int** matrix;
    cell *coreList,*tempList,*resultList;
    
    fscanf(fp,"%d%d",&ROW,&COL);
    
    matrix = (int**)malloc(ROW*sizeof(int*));
    
    for(i=0;i<ROW;i++){
        matrix[i] = (int*)malloc(COL*sizeof(int));
        for(j=0;j<COL;j++){
            fscanf(fp,"%d",&matrix[i][j]);
            if(matrix[i][j]==1)
                SUM++;
        }
    }
    
    coreList = (cell*)malloc(SUM*sizeof(cell));
    resultList = (cell*)malloc(SUM*sizeof(cell));
    
    k = 0;
    
    for(i=0;i<ROW;i++){
        for(j=0;j<COL;j++){
            if(matrix[i][j]==1){
                coreList[k].row = i+1;
                coreList[k].col = j+1;
                resultList[k].row = i+1;
                resultList[k].col = j+1;
                k++;
            }
        }
    }
    
    prod = k;
    
    for(i=2;i<=power;i++){
        tempList = (cell*)malloc(prod*k*sizeof(cell));
        
        l = 0;
        
        for(j=0;j<prod;j++){
            for(k=0;k<SUM;k++){
                tempList[l].row = (resultList[j].row-1)*ROW + coreList[k].row;
                tempList[l].col = (resultList[j].col-1)*COL + coreList[k].col;
                l++;
            }
        }
        
        free(resultList);
        
        prod *= k;
        
        resultList = (cell*)malloc(prod*sizeof(cell));
        
        for(j=0;j<prod;j++){
            resultList[j].row = tempList[j].row;
            resultList[j].col = tempList[j].col;
        }
        free(tempList);
    }
    
    return resultList;
}

int main(){
    char fileName[100];
    int power,i,length;
    
    cell* resultList;
    
    printf("Enter input file name : ");
    scanf("%s",fileName);
    
    printf("Enter power : ");
    scanf("%d",&power);
    
    resultList = kroneckerProduct(fileName,power);
    
    initwindow(raiseTo(ROW,power),raiseTo(COL,power),"Kronecker Product Fractal");
    
    length = raiseTo(SUM,power);

    for(i=0;i<length;i++){
        putpixel(resultList[i].row,resultList[i].col,15);
    }
    
    getch();
    
    closegraph();
    
    return 0;
}


C++: #include <cassert>
#include <vector>

#include <QImage>

template <typename scalar_type> class matrix {
public:
    matrix(size_t rows, size_t columns)
        : rows_(rows), columns_(columns), elements_(rows * columns) {}
    matrix(size_t rows, size_t columns,
        const std::initializer_list<std::initializer_list<scalar_type>>& values)
        : rows_(rows), columns_(columns), elements_(rows * columns) {
        assert(values.size() <= rows_);
        size_t i = 0;
        for (const auto& row : values) {
            assert(row.size() <= columns_);
            std::copy(begin(row), end(row), &elements_[i]);
            i += columns_;
        }
    }
    size_t rows() const { return rows_; }
    size_t columns() const { return columns_; }

    const scalar_type& operator()(size_t row, size_t column) const {
        assert(row < rows_);
        assert(column < columns_);
        return elements_[row * columns_ + column];
    }
    scalar_type& operator()(size_t row, size_t column) {
        assert(row < rows_);
        assert(column < columns_);
        return elements_[row * columns_ + column];
    }
private:
    size_t rows_;
    size_t columns_;
    std::vector<scalar_type> elements_;
};


template <typename scalar_type>
matrix<scalar_type> kronecker_product(const matrix<scalar_type>& a,
                                      const matrix<scalar_type>& b) {
    size_t arows = a.rows();
    size_t acolumns = a.columns();
    size_t brows = b.rows();
    size_t bcolumns = b.columns();
    matrix<scalar_type> c(arows * brows, acolumns * bcolumns);
    for (size_t i = 0; i < arows; ++i)
        for (size_t j = 0; j < acolumns; ++j)
            for (size_t k = 0; k < brows; ++k)
                for (size_t l = 0; l < bcolumns; ++l)
                    c(i*brows + k, j*bcolumns + l) = a(i, j) * b(k, l);
    return c;
}

bool kronecker_fractal(const char* fileName, const matrix<unsigned char>& m, int order) {
    matrix<unsigned char> result = m;
    for (int i = 0; i < order; ++i)
        result = kronecker_product(result, m);

    size_t height = result.rows();
    size_t width = result.columns();
    size_t bytesPerLine = 4 * ((width + 3)/4);
    std::vector<uchar> imageData(bytesPerLine * height);

    for (size_t i = 0; i < height; ++i)
        for (size_t j = 0; j < width; ++j)
            imageData[i * bytesPerLine + j] = result(i, j);

    QImage image(&imageData[0], width, height, bytesPerLine, QImage::Format_Indexed8);
    QVector<QRgb> colours(2);
    colours[0] = qRgb(0, 0, 0);
    colours[1] = qRgb(255, 255, 255);
    image.setColorTable(colours);
    return image.save(fileName);
}

int main() {
    matrix<unsigned char> matrix1(3, 3, {{0,1,0}, {1,1,1}, {0,1,0}});
    matrix<unsigned char> matrix2(3, 3, {{1,1,1}, {1,0,1}, {1,1,1}});
    matrix<unsigned char> matrix3(2, 2, {{1,1}, {0,1}});
    kronecker_fractal("vicsek.png", matrix1, 5);
    kronecker_fractal("sierpinski_carpet.png", matrix2, 5);
    kronecker_fractal("sierpinski_triangle.png", matrix3, 8);
    return 0;
}