F# Slicing

Aug 16, 2011 at 12:43 AM

I started off using the matrix type in the PowerPack but then found this library offers a lot more features so made the switch. It was relatively easy to make the change, however, one of the features missing from the F# wrapper of the library is slicing (i.e. myMatrix.[0..1, 2..3] would be equivalent to MyMatrix.SubMatrix(0, 1, 2, 1))

To get around this I created a couple of extension members and thought I'd share them here in case anybody else finds them useful (note that I've excluded error checking the arguments and left that to the Matrix/Vector types to handle):

[<AutoOpen>]
module ExtensionMembers =
    open MathNet.Numerics.LinearAlgebra.Generic

    /// Allows the Matrix type to support slicing (i.e. myMatrix.[0..2, 2..4])
    type Matrix<'a when 'a : struct and
                        'a : (new : unit -> 'a) and
                        'a :> System.ValueType and
                        'a :> System.IFormattable and
                        'a :> System.IEquatable<'a>> with

        /// Creates a Matrix containing the specified sub-elements.
        member this.GetSlice(rowStart, rowEnd, colStart, colEnd) =
            // Arguments are optional for when the user writes[1 .. , 1 .. ]  
            let r1 = defaultArg rowStart 0
            let r2 = defaultArg rowEnd (this.RowCount-1)
            let c1 = defaultArg colStart 0
            let c2 = defaultArg colEnd (this.ColumnCount-1)

            // Add 1 to the length because slicing is inclusive
            // (i.e. myMatrix.[0..0,0..0] should return a 1x1 matrix
            this.SubMatrix(r1, r2-r1 + 1, c1, c2-c1 + 1)

        /// Sets the specifed region of the Matrix.
        member this.SetSlice(rowStart, rowEnd, colStart, colEnd, value) =
            let r1 = defaultArg rowStart 0
            let r2 = defaultArg rowEnd (this.RowCount-1)
            let c1 = defaultArg colStart 0
            let c2 = defaultArg colEnd (this.ColumnCount-1)

            this.SetSubMatrix(r1, r2-r1 + 1, c1, c2-c1 + 1, value)

    /// Allows the Vector type to support slicing (i.e. myVector.[0..2])
    type Vector<'a when 'a : struct and
                        'a : (new : unit -> 'a) and
                        'a :> System.ValueType and
                        'a :> System.IFormattable and
                        'a :> System.IEquatable<'a>> with

        /// Creates a Vector containing the specified elements.
        member this.GetSlice(rowStart, rowEnd) =
            let r1 = defaultArg rowStart 0
            let r2 = defaultArg rowEnd (this.Count-1)
            this.SubVector(r1, r2-r1 + 1)

        /// Sets the specified elements of the Vector.
        member this.SetSlice(rowStart, rowEnd, (value:Vector<'a>)) =
            let r1 = defaultArg rowStart 0
            let r2 = defaultArg rowEnd (this.Count-1)
            for i=r1 to r2 do
                this.[i] <- value.[i-r1]
Coordinator
Aug 23, 2011 at 6:58 PM

Very cool! Thanks for sharing.

Jurgen