Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- namespace Anon.Math.Matrix
- open System
- open Anon.Math
- open Anon.Core
- type 'a IMatrixFormatProvider =
- /// Разделитель между столбцами
- abstract ColumnSeparator : string
- ///Разделитель между строками
- abstract RowSeparator : string
- /// Приведение элемента матрицы к строке
- abstract ElementConverter : ('a -> string)
- type 'a MatrixFormatInfo (columnSeparator : string, rowSeparator : string, elementConverter : 'a -> string) =
- static let _default : 'a IMatrixFormatProvider = upcast MatrixFormatInfo<'a> (" ", Environment.NewLine, fun v -> v.ToString ())
- interface 'a IMatrixFormatProvider with
- member this.ColumnSeparator = columnSeparator
- member this.RowSeparator = rowSeparator
- member this.ElementConverter = elementConverter
- static member Default = _default
- type private MatrixFuncStorate =
- static member ofSeq columnCount rowCount source = Matrix (columnCount, rowCount, Array.ofSeq source)
- static member isSquare<'a> (matrix : Matrix<'a>) = matrix.RowCount = matrix.ColumnCount
- static member rows (mtx : _ Matrix) =
- mtx.Rows
- static member columns (mtx : _ Matrix) =
- mtx.Columns
- static member cells<'a> (mtx : 'a Matrix) : 'a MatrixCell seq =
- (MatrixFuncStorate.rows >> Seq.collect (fun row -> row.Cells)) mtx
- static member cellsValues<'a> (mtx : 'a Matrix) : 'a seq =
- (MatrixFuncStorate.cells >> Seq.map (fun cell -> cell.Value)) mtx
- static member cellMap f mtx = MatrixFuncStorate.cells mtx
- |> Seq.map f
- |> MatrixFuncStorate.ofSeq mtx.ColumnCount mtx.RowCount
- static member map f = MatrixFuncStorate.cellMap (fun cell -> f cell.Value)
- static member cellMap2 f (mtx1 : _ Matrix) (mtx2 : _ Matrix) =
- if mtx1.RowCount <> mtx2.RowCount then invalidArg "different row count" "mtx2"
- elif mtx1.ColumnCount <> mtx2.ColumnCount then invalidArg "different column count" "mtx2"
- else Seq.map2 f (MatrixFuncStorate.cells mtx1) (MatrixFuncStorate.cells mtx2)
- |> MatrixFuncStorate.ofSeq mtx1.ColumnCount mtx1.RowCount
- static member map2 f mtx1 mtx2 = MatrixFuncStorate.cellMap2 (f |> on <| fun cell -> cell.Value) mtx1 mtx2
- // Immutable matrix
- and 'a Matrix internal (columnCount : int, rowCount : int, source : 'a array) as this =
- do if columnCount < 0
- then argumentOutOfRange "columnCount"
- if rowCount < 0
- then argumentOutOfRange "rowCount"
- if columnCount * rowCount > source.Length
- then invalidArg "low data" "source"
- let rows = lazy [for rowIndex in 0 .. rowCount - 1 -> MatrixRow (this, rowIndex, seq { for columnIndex in 0 .. columnCount - 1 -> source.[rowIndex * columnCount + columnIndex] })]
- let columns = lazy [for columnIndex in 0 .. columnCount - 1 -> MatrixColumn (this, columnIndex, this.Rows |> List.map (fun row -> lazy row.Cells.[columnIndex]))]
- member this.Rows : 'a MatrixRow list = rows.Value
- member this.Columns : 'a MatrixColumn list = columns.Value
- member this.ColumnCount : int = columnCount
- member this.RowCount : int = rowCount
- static member (+) (left : 'a Matrix, right : 'a Matrix) = let mathProvider = MathProvider.Current
- MatrixFuncStorate.map2 mathProvider.Add left right
- static member (-) (left : 'a Matrix, right : 'a Matrix) = let mathProvider = MathProvider.Current
- MatrixFuncStorate.map2 mathProvider.Subtract left right
- static member (*) (left : 'a Matrix, right : 'a Matrix) = let mathProvider = MathProvider.Current
- seq { for matrixRow in left.Rows do
- for otherColumn in right.Columns ->
- (matrixRow.Cells, otherColumn.Cells) ||> List.map2 (mathProvider.Add |> on <| fun c -> c.Value)
- |> MathProvider.sum mathProvider }
- |> MatrixFuncStorate.ofSeq right.ColumnCount left.RowCount
- //static member (/) (left : 'a Matrix, right : 'a Matrix) = BinaryMathExpression (left, DivideOperator, right)
- static member (~+) (matrix : 'a Matrix) = let mathProvider = MathProvider.Current
- MatrixFuncStorate.map mathProvider.Plus matrix
- static member (~-) (matrix : 'a Matrix) = let mathProvider = MathProvider.Current
- MatrixFuncStorate.map mathProvider.Negate matrix
- override this.ToString () = this.ToString MatrixFormatInfo<'a>.Default
- member this.ToString (provider : 'a IMatrixFormatProvider) =
- let stringMatrix = MatrixFuncStorate.map provider.ElementConverter this
- let columnLengths = [for column in stringMatrix.Columns ->
- column.Cells |> Seq.map (fun cell -> cell.Value.Length) |> Seq.max ]
- String.join provider.RowSeparator [for row in stringMatrix.Rows -> String.join provider.ColumnSeparator [for cell in row.Cells -> String (' ', columnLengths.[cell.Column.Index] - cell.Value.Length) + cell.Value]]
- and 'a MatrixRow internal (matrix : 'a Matrix, index, items) as this =
- let cells = lazy [for columnIndex, value in Seq.mapi (curry id) items -> MatrixCell (this, List.nth matrix.Columns columnIndex, value)]
- member this.Matrix : 'a Matrix = matrix
- member this.Index : int = index
- member this.Cells : 'a MatrixCell list = cells.Value
- and 'a MatrixColumn internal (matrix : 'a Matrix, index, lazyCells) =
- let cells = lazy (lazyCells |> List.map (fun lazyCell -> lazyCell.Value))
- member this.Matrix : 'a Matrix = matrix
- member this.Index : int = index
- member this.Cells : 'a MatrixCell list = cells.Value
- and 'a MatrixCell internal (row, column, value) =
- member this.Row : 'a MatrixRow = row
- member this.Column : 'a MatrixColumn = column
- member this.Value : 'a = value
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement