! words like <scale-matrix3> which have an array of inputs
:$finite-input-note( children-- )
[ "Only the first " ] dip
first2
" values in "swap
[ { $snippet } ] dip suffix
" are used."
5 narray print-element ;
! a note for when a word assumes a 2d matrix
:$2d-only-note( children-- )
drop { "This word is intended for use with \"flat\" (2-dimensional) matrices. "
! "Using it with matrices of 3 or more dimensions may lead to unexpected results."
}
print-element ;
! a note for numeric-specific operations
:$matrix-scalar-note( children-- )
\ $subs-noblprefix
"This word assumes that elements of the input matrix are compatible with the following words:"
swap 2array
print-element ;
:$keep-shape-note( children-- )
drop { "The shape of the input matrix is preserved in the output." } print-element ;
:$link2( children-- )
first2 swap [ write-link ] topic-span ;
! so that we don't end up with multiple $notes calls leading to multiple Notes sections
:$notelist( children-- )
\ $listprefix $notes ;
PRIVATE>
ABOUT: "math.matrices"
ARTICLE: "math.matrices""Matrix operations"
"The " { $vocab-link "math.matrices" } " vocabulary implements many ways of working with " { $emphasis "matrices" } " — sequences which have a minimum of 2 dimensions. Operations on 1-dimensional numeric vectors are implemented in " { $vocab-link "math.vectors" } ", upon which this vocabulary relies."
$nl
"In this vocabulary's documentation, " { $snippet "m" } " and " { $snippet "matrix" } " are the conventional names used for a given matrix object. " { $snippet "m" } " may also refer to a number."
$nl
"The " { $vocab-link "math.matrices.extras" } "vocabulary implements extensions to this one."
$nl
"Matrices are classified their mathematical properties, and by predicate words:"
$nl
! split up intentionally
{ $subsections
matrix
irregular-matrix
square-matrix
zero-matrix
zero-square-matrix
null-matrix
} { $subsections
matrix?
irregular-matrix?
square-matrix?
zero-matrix?
zero-square-matrix?
null-matrix?
}
"There are many ways to create 2-dimensional matrices:"
"The following matrix norms are provided in the 𝑙ₚ vector space; these words are equivalent to ∥・∥ₚ for " { $snippet "p = 1, 2, ∞, n" } ", respectively:"
{ $class-description "The class of regular, rectangular matrices. In mathematics and linear algebra, a matrix is a rectangular collection of scalar elements for the purpose of the uniform application of algorithms." }
{ $notes "In Factor, any sequence with two or more dimensions (one or more layers of subsequences) can be a " { $link matrix } ", and the elements may be any " { $link object } "."
$nl "A regular matrix is a sequence with two or more dimensions, whose subsequences are all of equal length. See " { $link regular-matrix? } "." }
$nl "Irregular matrices are classified by " { $link irregular-matrix } ".";
HELP:irregular-matrix
{ $class-description "The most common matrix, and most easily manipulated by this vocabulary, is rectangular. This predicate classifies irregular (non-rectangular) matrices." } ;
HELP:square-matrix
{ $class-description "The class of square matrices. A square matrix is a " { $link matrix } " which has the same number of rows and columns. In other words, its outermost two dimensions are of equal size." } ;
{ $class-description "The class of square zero matrices. This predicate is a composition of " { $link zero-matrix } " and " { $link square-matrix } "." } ;
{ $description "Tests if the object is a regular (well-formed, rectangular, etc) " { $link matrix } ". A regular matrix is a sequence with an equal number of elements in every row, and an equal number of elements in every column, such that there are no empty slots." }
{ $notes "The " { $link null-matrix } " is considered regular, because of semantic requirements of the matrix implementation." }
{ $description "Creates a matrix of size " { $snippet "m x n" } " using elements given by " { $snippet "quot" } ", a quotation called to create each element." }
{ $description "Creates an " { $snippet "m x n" } " " { $link matrix } " using elements given by " { $snippet "quot" } " . This word differs from " { $link <matrix-by> } " in that the indices are placed on the stack (in the same order) before " { $snippet "quot" } " runs. The output of the quotation will be the element at the given position in the matrix." }
{ $description "Creates a matrix with the specified anti-diagonal. This word has the opposite effect of " { $link main-diagonal } "." }
{ $notes "To use a diagonal starting in the lower left, reverse the input sequence before calling this word." }
{ $examples
{ $example
"USING: math.matrices prettyprint ;"
"{ 1 2 3 } <anti-diagonal-matrix> ."
"{ { 0 0 1 } { 0 2 0 } { 3 0 0 } }"
}
} ;
HELP:<identity-matrix>
{ $values { "n"integer } { "matrix" matrix } }
{ $description "Creates an " { $url URL" http://enwp.org/Identity_matrix""identity matrix" } " of size " { $snippet "n x n" } ", where the diagonal values are all ones." }
{ $description "Creates an " { $snippet "m x n" } " matrix with a diagonal of " { $snippet "z" } " offset by " { $snippet "k" } " from the main diagonal. A positive value of " { $snippet "k" } " gives a diagonal above the main diagonal, whereas a negative value of " { $snippet "k" } " gives a diagonal below the main diagonal." }
{ $description "An alias for " { $link <coordinate-matrix> } " which serves as the logical non-square companion to " { $link <cartesian-square-indices> } "." }
{ $contract "Generate a " { $link square-matrix } " from a descriptor." }
{ $description "If the descriptor is an " { $link integer } ", it is used to generate square rows within that range." $nl "If it is a 1-dimensional sequence, it is " { $link replicate } "d to create each row." $nl "If it is a " { $link matrix } ", it is cropped into a " { $link square-matrix } "." $nl "If it is a " { $link square-matrix } ", it is returned unchanged." }
{ $contract "Generate a " { $link square-matrix } " from a descriptor." }
{ $description "If the descriptor is an " { $link integer } ", it is used to generate square columns within that range." $nl "If it is a 1-dimensional sequence, it is " { $link replicate } "d to create each column." $nl "If it is a " { $link matrix } ", it is cropped into a " { $link square-matrix } "." $nl "If it is a " { $link square-matrix } ", it is returned unchanged." }
{ $description "Make a lower triangular matrix, where all the values above the main diagonal are " { $snippet "0" } ". " { $snippet "object" } " will be used as the value for the nonzero part of the matrix, while " { $snippet "m" } " and " { $snippet "n" } " are used as the dimensions. The inverse of this word is " { $link <upper-matrix> } ". See " { $url URL" https://en.wikipedia.org/wiki/Triangular_matrix""triangular matrix" } "." }
{ $description "Make an upper triangular matrix, where all the values below the main diagonal are " { $snippet "0" } ". " { $snippet "object" } " will be used as the value for the nonzero part of the matrix, while " { $snippet "m" } " and " { $snippet "n" } " are used as the dimensions. The inverse of this word is " { $link <lower-matrix> } ". See " { $url URL" https://en.wikipedia.org/wiki/Triangular_matrix""triangular matrix" } "." }
{ $description "Retrieve all the elements in the matrix at each of the zero-indexed " { $snippet "row, column" } " pairs in " { $snippet "pairs" } "." }
{ { $link bounds-error } " if the first element of a pair in " { $snippet "pairs" } " is greater than the maximum row index in " { $snippet "matrix" } }
{ { $link bounds-error } " if the second element of a pair in " { $snippet "pairs" } " is greater than the maximum column index in " { $snippet "matrix" } }
{ $description "Set the element in the matrix at the 2D index given by " { $snippet "pair" } " to " { $snippet "obj" } ". This operation is destructive." }
{ { $link bounds-error } " if the first element of a pair in " { $snippet "pairs" } " is greater than the maximum row index in " { $snippet "matrix" } }
{ { $link bounds-error } " if the second element of a pair in " { $snippet "pairs" } " is greater than the maximum column index in " { $snippet "matrix" } }
"Throws an error if the sequence cannot hold elements of the given type."
{ { $link bounds-error } " if the first element of a pair in " { $snippet "pairs" } " is greater than the maximum row index in " { $snippet "matrix" } }
{ { $link bounds-error } " if the second element of a pair in " { $snippet "pairs" } " is greater than the maximum column index in " { $snippet "matrix" } }
"Throws an error if the sequence cannot hold elements of the given type."
{ $description "Negate (invert the sign) of every element in the matrix. The resulting matrix is called the " { $emphasis "additive inverse" } " of the input matrix." }
{ $notelist
{ $equiv-word-note "companion" mabs }
$2d-only-note
{ $matrix-scalar-note neg }
}
{ $examples
{ $example
"USING: math.matrices prettyprint ;"
"{ { 5 9 } { 15 -17 } } mneg ."
"{ { -5 -9 } { -15 17 } }"
}
} ;
HELP:mabs
{ $values { "m" matrix } { "m'" matrix } }
{ $description "Compute the absolute value (" { $link abs } ") of each element in the matrix." }
{ $notelist
{ $equiv-word-note "companion" mneg }
$2d-only-note
{ $matrix-scalar-note abs }
}
{ $examples
{ $example
"USING: math.matrices prettyprint ;"
"{ { -5 -9 } { -15 17 } } mabs ."
"{ { 5 9 } { 15 17 } }"
}
} ;
HELP:n+m
{ $values { "n"object } { "m" matrix } }
{ $description { $snippet "n" } " is treated as a scalar and added to each element of the matrix " { $snippet "m" } "." }
{ $notelist
{ $equiv-word-note "swapped" m+n }
$2d-only-note
{ $matrix-scalar-note + }
}
{ $examples
{ $example
"USING: kernel math.matrices prettyprint ;"
"1 3 <identity-matrix> n+m ."
"{ { 2 1 1 } { 1 2 1 } { 1 1 2 } }"
}
} ;
HELP:m+n
{ $values { "m" matrix } { "n"object } }
{ $description { $snippet "n" } " is treated as a scalar and added to each element of the matrix " { $snippet "m" } "." }
{ $notelist
{ $equiv-word-note "swapped" n+m }
$2d-only-note
{ $matrix-scalar-note + }
}
{ $examples
{ $example
"USING: kernel math.matrices prettyprint ;"
"3 <identity-matrix> 1 m+n ."
"{ { 2 1 1 } { 1 2 1 } { 1 1 2 } }"
}
} ;
HELP:n-m
{ $values { "n"object } { "m" matrix } }
{ $description { $snippet "n" } " is treated as a scalar and subtracted from each element of the matrix " { $snippet "m" } "." }
{ $notelist
{ $equiv-word-note "swapped" m-n }
$2d-only-note
{ $matrix-scalar-note - }
}
{ $examples
{ $example
"USING: kernel math.matrices prettyprint ;"
"1 3 <identity-matrix> n-m ."
"{ { 0 1 1 } { 1 0 1 } { 1 1 0 } }"
}
} ;
HELP:m-n
{ $values { "m" matrix } { "n"object } }
{ $description { $snippet "n" } " is treated as a scalar and subtracted from each element of the matrix " { $snippet "m" } "." }
{ $notelist
{ $equiv-word-note "swapped" n-m }
$2d-only-note
{ $matrix-scalar-note - }
}
{ $examples
{ $example
"USING: kernel math.matrices prettyprint ;"
"3 <identity-matrix> 1 m-n ."
"{ { 0 -1 -1 } { -1 0 -1 } { -1 -1 0 } }"
}
} ;
HELP:n*m
{ $values { "n"object } { "m" matrix } }
{ $description "Every element in the input matrix " { $snippet "m" } " is multiplied by the scalar "{ $snippet "n" } "." }
{ $notelist
$keep-shape-note
{ $equiv-word-note "swapped" m*n }
$2d-only-note
{ $matrix-scalar-note * }
}
{ $examples
{ $example
"USING: kernel math.matrices prettyprint ;"
"3 3 <identity-matrix> n*m ."
"{ { 3 0 0 } { 0 3 0 } { 0 0 3 } }"
}
} ;
HELP:m*n
{ $values { "m" matrix } { "n"object } }
{ $description "Every element in the input matrix " { $snippet "m" } " is multiplied by the scalar "{ $snippet "n" } "." }
{ $notelist
$keep-shape-note
{ $equiv-word-note "swapped" n*m }
$2d-only-note
{ $matrix-scalar-note * }
}
{ $examples
{ $example
"USING: kernel math.matrices prettyprint ;"
"3 <identity-matrix> 3 m*n ."
"{ { 3 0 0 } { 0 3 0 } { 0 0 3 } }"
}
} ;
HELP:n/m
{ $values { "n"object } { "m" matrix } }
{ $description "Every element in the input matrix " { $snippet "m" } " is divided by the scalar "{ $snippet "n" } "." }
{ $notelist
$keep-shape-note
{ $equiv-word-note "swapped" m/n }
$2d-only-note
{ $matrix-scalar-note / }
}
{ $examples
{ $example
"USING: kernel math.matrices prettyprint ;"
"2 { { 4 5 } { 2 1 } } n/m ."
"{ { 1/2 2/5 } { 1 2 } }"
}
} ;
HELP:m/n
{ $values { "m" matrix } { "n"object } }
{ $description "Every element in the input matrix " { $snippet "m" } " is divided by the scalar "{ $snippet "n" } "." }
{ "In the example, only " { $snippet ".01" } " was added to each element, so the new matrix is within the epsilon " { $snippet ".1" } "of the original." }
{ $values { "m" matrix } { "p""positive real number" } { "n""non-negative real number" } }
{ $description "Find the entry-wise norm of a matrix, in 𝑙ₚ (" { $snippet "L^p" } ") vector space." }
{ $notes "This word is distinct from a Schatten p-norm, as well as any of " { $links m-1norm frobenius-norm m-infinity-norm } "." }
{ $examples
{ $example
"USING: math.matrices prettyprint ;"
"4 4 1 <matrix> 2 matrix-p-norm-entrywise ."
"4.0"
}
} ;
HELP:matrix-p-norm
{ $values { "m" matrix } { "p""positive real number" } { "n""non-negative real number" } }
{ $description "Find the size of a matrix in 𝑙ₚ (" { $snippet "L^p" } ") vector space, usually written ∥・∥ₚ. For " { $snippet "p ≠ 1, 2, ∞" } ", this is an \"entry-wise\" norm." }
{ $examples
"Calls " { $link m-1norm } ":"
{ $example
"USING: math.matrices prettyprint ;"
"4 4 1 <matrix> 1 matrix-p-norm ."
"4"
}
"Falls back to " { $link matrix-p-norm-entrywise } ":"
{ $description "Normalize a matrix. Each element from the input matrix is computed as a fraction of the maximum element. The maximum element becomes " { $snippet "1/1" } "." }
{ $description "Find the main diagonal of a matrix." $nl "This diagonal begins in the upper left of the matrix at index " { $snippet "{ 0 0 }" } ", continuing downward and rightward for all indices " { $snippet "{ n n }" } " in the " { $link square-matrix } " subset of the input (see " { $link <square-rows> } ")." }
{ $notelist
{ "If the number of rows in the square subset of the input is even, then this diagonal will not contain elements found in the " { $link anti-diagonal } ". However, if the size of the square subset is odd, then this diagonal will share at most one element with " { $link anti-diagonal } "." }
{ "This diagonal is sometimes called the " { $emphasis "first diagonal" } "." }
{ $equiv-word-note "opposite" anti-diagonal }
}
{ $examples
{ "The operation is simple on a " { $link square-matrix } ":" }
{ $example
"USING: math.matrices prettyprint ;"
"{
{ 7 2 11 }
{ 9 7 7 }
{ 1 8 0 }
} main-diagonal ."
"{ 7 7 0 }"
}
"The square subset of the following input matrix consists of all rows but the last. The main diagonal does not include the last row because it has no fourth element."
{ $example
"USING: math.matrices prettyprint ;"
"{
{ 6 5 0 }
{ 7 2 6 }
{ 4 3 9 }
{ 3 3 3 }
} main-diagonal ."
"{ 6 2 9 }"
}
} ;
HELP:anti-diagonal
{ $values { "matrix" matrix } { "seq"sequence } }
{ $description "Find the anti-diagonal of a matrix." $nl "This diagonal begins in the upper right of the matrix, continuing downward and leftward for all indices in the " { $link square-matrix } " subset of the input (see " { $link <square-rows> } ")." }
{ $notelist
{ "If the number of rows in the square subset of the input is even, then this diagonal will not contain elements found in the " { $link main-diagonal } ". However, if the size of the square subset is odd, then this diagonal will share at most one element with " { $link main-diagonal } "." }
{ "This diagonal is sometimes called the " { $emphasis "second diagonal" } "." }
{ $equiv-word-note "opposite" main-diagonal }
}
{ $examples
{ "The operation is simple on a " { $link square-matrix } ":" }
{ $example
"USING: math.matrices prettyprint ;"
"{
{ 7 2 11 }
{ 9 7 7 }
{ 1 8 0 }
} anti-diagonal ."
"{ 11 7 1 }"
}
"The square subset of the following input matrix consists of all rows but the last. The anti-diagonal does not include the last row because it has no fourth element."
{ $description "Transpose the input matrix over its " { $link main-diagonal } ". The main diagonal itself is preserved, whereas the anti-diagonal is reversed." }
{ $notelist
{ "This word is an alias for " { $link flip } ", so that it may be recognised as the common mathematical operation." }
{ $description "Like " { $link transpose } " except that the matrix is transposed over the " { $link anti-diagonal } ", so that the anti-diagonal itself is preserved and the " { $link main-diagonal } " is reversed." }
{ $description "Get all the rows and columns from " { $snippet "matrix" } " except the row and column given in " { $snippet "exclude-pair" } ". The result is the " { $snippet "submatrix" } " containing no values from the given row and column." }