A pascal matrix is a two-dimensional square matrix holding numbers from   Pascal's triangle,   also known as   binomial coefficients   and which can be shown as   nCr.

Shown below are truncated   5-by-5   matrices   M[i, j]   for   i,j   in range   0..4. 


A Pascal upper-triangular matrix that is populated with   jCi:

[[1, 1, 1, 1, 1],
 [0, 1, 2, 3, 4],
 [0, 0, 1, 3, 6],
 [0, 0, 0, 1, 4],
 [0, 0, 0, 0, 1]]

A Pascal lower-triangular matrix that is populated with   iCj   (the transpose of the upper-triangular matrix):

[[1, 0, 0, 0, 0],
 [1, 1, 0, 0, 0],
 [1, 2, 1, 0, 0],
 [1, 3, 3, 1, 0],
 [1, 4, 6, 4, 1]]

A Pascal symmetric matrix that is populated with   i+jCi:

[[1, 1, 1, 1, 1],
 [1, 2, 3, 4, 5],
 [1, 3, 6, 10, 15],
 [1, 4, 10, 20, 35],
 [1, 5, 15, 35, 70]]



Task

Write functions capable of generating each of the three forms of   n-by-n   matrices.

Use those functions to display upper, lower, and symmetric Pascal   5-by-5   matrices on this page.

The output should distinguish between different matrices and the rows of each matrix   (no showing a list of 25 numbers assuming the reader should split it into rows).



Note
 
The   Cholesky decomposition   of a Pascal symmetric matrix is the Pascal lower-triangle matrix of the same size.




matrix = array[array[int]]
 
make_matrix = proc (gen: proctype (int,int,matrix) returns (int),
                    size: int) returns (matrix)
    m: matrix := matrix$fill_copy(0, size, array[int]$fill(0, size, 0))
    for y: int in int$from_to(0, size-1) do
        for x: int in int$from_to(0, size-1) do
            m[y][x] := gen(x,y,m)
        end
    end
    return(m)
end make_matrix
 
lower = proc (x,y: int, m: matrix) returns (int)
    if x>y then return(0)
    elseif x=y | x=0 then return(1)
    else return( m[y-1][x-1] + m[y-1][x] )
    end
end lower
 
upper = proc (x,y: int, m: matrix) returns (int)
    if x<y then return(0)
    elseif x=y | y=0 then return(1)
    else return( m[y-1][x-1] + m[y][x-1] )
    end
end upper     
 
symmetric = proc (x,y: int, m: matrix) returns (int)
    if x=0 | y=0 then return(1)
    else return(m[y][x-1] + m[y-1][x])
    end
end symmetric
 
print_matrix = proc (s: stream, m: matrix, w: int)
    for line: array[int] in matrix$elements(m) do
        for item: int in array[int]$elements(line) do
            stream$putright(s, int$unparse(item), w)
            stream$putc(s, ' ')
        end
        stream$putl(s, "")
    end
end print_matrix
 
start_up = proc ()
    po: stream := stream$primary_output()
 
    stream$putl(po, "Upper-triangular matrix:")
    print_matrix(po, make_matrix(upper,5), 1)
 
    stream$putl(po, "\nLower-triangular matrix:")
    print_matrix(po, make_matrix(lower,5), 1)
 
    stream$putl(po, "\nSymmetric matrix:")
    print_matrix(po, make_matrix(symmetric,5), 2)
end start_up