On this page:
7.1.1 Function Types
7.1.2 Failure Arguments
7.1.3 Broadcasting
7.1.4 Strictness

7.1 Introduction🔗

From the point of view of the functions in math/matrix, a matrix is an Array with two axes and at least one entry, or an array for which matrix? returns #t.

Technically, a matrix’s entries may be any type, and some fully polymorphic matrix functions such as matrix-row and matrix-map operate on any kind of matrix. Other functions, such as matrix+, require their matrix arguments to contain numeric values.

7.1.1 Function Types🔗

The documentation for math/matrix functions use the type Matrix, a synonym of Array, when the function either requires that an argument is a matrix or ensures that a return value is a matrix.

Most functions that implement matrix algorithms are documented as accepting (Matrix Number) values. This includes (Matrix Real), which is a subtype. Most of these functions have a more precise type than is documented. For example, matrix-conjugate has the type
(case-> ((Matrix Flonum)        -> (Matrix Flonum))
        ((Matrix Real)          -> (Matrix Real))
        ((Matrix Float-Complex) -> (Matrix Float-Complex))
        ((Matrix Number)        -> (Matrix Number)))
but is documented as having the type ((Matrix Number) -> (Matrix Number)).

Precise function types allow Typed Racket to prove more facts about math/matrix client programs. In particular, it is usually easy for it to prove that operations on real matrices return real matrices:
> (matrix-conjugate (matrix [[1 2 3] [4 5 6]]))

- : (Array Real)

(array #[#[1 2 3] #[4 5 6]])

and that operations on inexact matrices return inexact matrices:
> (matrix-conjugate (matrix [[1.0+2.0i 2.0+3.0i 3.0+4.0i]
                             [4.0+5.0i 5.0+6.0i 6.0+7.0i]]))

- : (Array Float-Complex)

(array #[#[1.0-2.0i 2.0-3.0i 3.0-4.0i] #[4.0-5.0i 5.0-6.0i 6.0-7.0i]])

7.1.2 Failure Arguments🔗

In many matrix operations, such as inversion, failure is easy to detect during computation, but is just as expensive to detect ahead of time as the operation itself. In these cases, the functions implementing the operations accept an optional failure thunk, or a zero-argument function that returns the result of the operation in case of failure.

For example, the (simplified) type of matrix-inverse is
(All (F) (case-> ((Matrix Number)        -> (Matrix Number))
                 ((Matrix Number) (-> F) -> (U F (Matrix Number)))))
Thus, if a failure thunk is given, the call site is required to check for return values of type F explicitly.

Default failure thunks usually raise an error, and have the type (-> Nothing). For such failure thunks, (U F (Matrix Number)) is equivalent to (Matrix Number), because Nothing is part of every type. (In Racket, any expression may raise an error.) Thus, in this case, no explicit test for values of type F is necessary (though of course they may be caught using with-handlers or similar).

7.1.3 Broadcasting🔗

Unlike array operations, pointwise matrix operations do not broadcast their arguments when given matrices with different axis lengths:
> (matrix+ (identity-matrix 2) (matrix [[10]]))

matrix-map: matrices must have the same shape; given (array

#[#[1 0] #[0 1]]) (array #[#[10]])

If you need broadcasting, use array operations:
> (array+ (identity-matrix 2) (matrix [[10]]))

- : #(struct:Array

      (Indexes Index (Boxof Boolean) (-> Void) (-> Indexes Index))

      #<syntax:build/user/ prop:equal+hash>

      #<syntax:build/user/ prop:custom-write>

      #<syntax:build/user/ prop:custom-print-quotable>)

(array #[#[11 10] #[10 11]])

7.1.4 Strictness🔗

Functions exported by math/matrix return strict or nonstrict arrays based on the value of the array-strictness parameter. See Nonstrict Arrays for details.