Task: Kronecker product



C#: using System;
using System.Collections;
using System.Collections.Generic;
using static System.Linq.Enumerable;

public static class KroneckerProduct
{
    public static void Main() {
        int[,] left = { {1, 2}, {3, 4} };
        int[,] right = { {0, 5}, {6, 7} };
        Print(Multiply(left, right));

        left = new [,] { {0, 1, 0}, {1, 1, 1}, {0, 1, 0} };
        right = new [,] { {1, 1, 1, 1}, {1, 0, 0, 1}, {1, 1, 1, 1} };
        Print(Multiply(left, right));
    }

    static int[,] Multiply(int[,] left, int[,] right) {
        (int lRows, int lColumns) = (left.GetLength(0), left.GetLength(1));
        (int rRows, int rColumns) = (right.GetLength(0), right.GetLength(1));
        int[,] result = new int[lRows * rRows, lColumns * rColumns];

        foreach (var (r, c) in from r in Range(0, lRows) from c in Range(0, lColumns) select (r, c)) {
            Copy(r * rRows, c * rColumns, left[r, c]);
        }
        return result;
        
        void Copy(int startRow, int startColumn, int multiplier) {
            foreach (var (r, c) in from r in Range(0, rRows) from c in Range(0, rColumns) select (r, c)) {
                result[startRow + r, startColumn + c] = right[r, c] * multiplier;
            }
        }
    }

    static void Print(int[,] matrix) {
        (int rows, int columns) = (matrix.GetLength(0), matrix.GetLength(1));
        int width = matrix.Cast<int>().Select(LengthOf).Max();
        for (int row = 0; row < rows; row++) {
            Console.WriteLine("| " + string.Join(" ", Range(0, columns).Select(column => (matrix[row, column] + "").PadLeft(width, ' '))) + " |");
        }
        Console.WriteLine();
    }

    private static int LengthOf(int i) {
        if (i < 0) return LengthOf(-i) + 1;
        int length = 0;
        while (i > 0) {
            length++;
            i /= 10;
        }
        return length;
    }

}








Fortran:       MODULE ARRAYMUSH	
       CONTAINS		
        SUBROUTINE KPRODUCT(A,B,AB)	
Considers the arrays to be addressed as A(row,column), despite any storage order arrangements.        .
Creating array AB to fit here, adjusting the caller's array AB, may not work on some compilers.
         INTEGER A(:,:),B(:,:)		
         INTEGER, ALLOCATABLE:: AB(:,:)	
         INTEGER R,RA,RB,C,CA,CB,I	
          RA = UBOUND(A,DIM = 1)	
          CA = UBOUND(A,DIM = 2)	
          RB = UBOUND(B,DIM = 1)	
          CB = UBOUND(B,DIM = 2)	
          WRITE (6,1) "A",RA,CA,"B",RB,CB,"A.k.B",RA*RB,CA*CB	
    1     FORMAT (3(A," is ",I0,"x",I0,1X))	
          IF (ALLOCATED(AB)) DEALLOCATE(AB)	
          ALLOCATE (AB(RA*RB,CA*CB))		
          R = 0		
          DO I = 1,RA	
            C = 0		
            DO J = 1,CA		
              AB(R + 1:R + RB,C + 1:C + CB) = A(I,J)*B	
              C = C + CB		
            END DO		
            R = R + RB		
          END DO	
        END SUBROUTINE KPRODUCT	

        SUBROUTINE SHOW(F,A)	
         INTEGER F	
         INTEGER A(:,:)	
         INTEGER R	
          DO R = 1,UBOUND(A,DIM = 1)	
            WRITE (F,1) A(R,:)		
    1       FORMAT (666I3)		
          END DO			
        END SUBROUTINE SHOW	
      END MODULE ARRAYMUSH	

      PROGRAM POKE
      USE ARRAYMUSH
      INTEGER A(2,2),B(2,2)		
      INTEGER, ALLOCATABLE:: AB(:,:)	
      INTEGER C(3,3),D(3,4)		
      DATA A/1,3, 2,4/,B/0,6, 5,7/	
      DATA C/0,1,0, 1,1,1, 0,1,0/	
      DATA D/1,1,1, 1,0,1, 1,0,1, 1,1,1/

      WRITE (6,*) "First test..."
      CALL KPRODUCT(A,B,AB)
      CALL SHOW (6,AB)

      WRITE (6,*)
      WRITE (6,*) "Second test..."
      CALL KPRODUCT(C,D,AB)
      CALL SHOW (6,AB)

      END