mirror of
https://github.com/gonum/gonum.git
synced 2025-10-07 08:01:20 +08:00
344 lines
13 KiB
Go
344 lines
13 KiB
Go
// Copyright ©2015 The gonum Authors. All rights reserved.
|
||
// Use of this source code is governed by a BSD-style
|
||
// license that can be found in the LICENSE file.
|
||
|
||
//+build ignore
|
||
|
||
// gendoc creates the matrix, mat64 and cmat128 package doc comments.
|
||
package main
|
||
|
||
import (
|
||
"fmt"
|
||
"log"
|
||
"os"
|
||
"path/filepath"
|
||
"strings"
|
||
"text/template"
|
||
"unicode/utf8"
|
||
)
|
||
|
||
var docs = template.Must(template.New("docs").Funcs(funcs).Parse(`{{define "common"}}// Generated by running
|
||
// go generate github.com/gonum/matrix
|
||
// DO NOT EDIT.
|
||
|
||
// Copyright ©2015 The gonum Authors. All rights reserved.
|
||
// Use of this source code is governed by a BSD-style
|
||
// license that can be found in the LICENSE file.
|
||
|
||
// Package {{.Name}} provides {{.Provides}}
|
||
//
|
||
// Overview
|
||
//
|
||
// This section provides a quick overview of the {{.Name}} package. The following
|
||
// sections provide more in depth commentary.
|
||
//
|
||
{{.Overview}}
|
||
//{{end}}
|
||
{{define "interfaces"}}// The Matrix Interfaces
|
||
//
|
||
// The Matrix interface is the common link between the concrete types. The Matrix
|
||
// interface is defined by three functions: Dims, which returns the dimensions
|
||
// of the Matrix, At, which returns the element in the specified location, and
|
||
// T for returning a Transpose (discussed later). All of the concrete types can
|
||
// perform these behaviors and so implement the interface. Methods and functions
|
||
// are designed to use this interface, so in particular the method
|
||
// func (m *Dense) Mul(a, b Matrix)
|
||
// constructs a *Dense from the result of a multiplication with any Matrix types,
|
||
// not just *Dense. Where more restrictive requirements must be met, there are also the
|
||
// Symmetric and Triangular interfaces. For example, in
|
||
// func (s *SymDense) AddSym(a, b Symmetric)
|
||
// the Symmetric interface guarantees a symmetric result.
|
||
//
|
||
// Transposes
|
||
//
|
||
// The T method is used for transposition. For example, c.Mul(a.T(), b) computes
|
||
// c = a^T * b. The {{if .ExamplePackage}}{{.ExamplePackage}}{{else}}{{.Name}}{{end}} types implement this method using an implicit transpose —
|
||
// see the Transpose type for more details. Note that some operations have a
|
||
// transpose as part of their definition, as in *SymDense.SymOuterK.
|
||
//{{end}}
|
||
{{define "factorization"}}// Matrix Factorization
|
||
//
|
||
// Matrix factorizations, such as the LU decomposition, typically have their own
|
||
// specific data storage, and so are each implemented as a specific type. The
|
||
// factorization can be computed through a call to Factorize
|
||
// var lu {{if .ExamplePackage}}{{.ExamplePackage}}{{else}}{{.Name}}{{end}}.LU
|
||
// lu.Factorize(a)
|
||
// The elements of the factorization can be extracted through methods on the
|
||
// appropriate type, i.e. *TriDense.LFromLU and *TriDense.UFromLU. Alternatively,
|
||
// they can be used directly, as in *Dense.SolveLU. Some factorizations can be
|
||
// updated directly, without needing to update the original matrix and refactorize,
|
||
// as in *LU.RankOne.
|
||
//{{end}}
|
||
{{define "blas"}}// BLAS and LAPACK
|
||
//
|
||
// BLAS and LAPACK are the standard APIs for linear algebra routines. Many
|
||
// operations in {{if .Description}}{{.Description}}{{else}}{{.Name}}{{end}} are implemented using calls to the wrapper functions
|
||
// in gonum/blas/{{.BLAS|alts}} and gonum/lapack/{{.LAPACK|alts}}. By default, {{.BLAS|join "/"}} and
|
||
// {{.LAPACK|join "/"}} call the native Go implementations of the routines. Alternatively,
|
||
// it is possible to use C-based implementations of the APIs through the respective
|
||
// cgo packages and "Use" functions. The Go implementation of LAPACK makes calls
|
||
// through {{.BLAS|join "/"}}, so if a cgo BLAS implementation is registered, the {{.LAPACK|join "/"}}
|
||
// calls will be partially executed in Go and partially executed in C.
|
||
//{{end}}
|
||
{{define "switching"}}// Type Switching
|
||
//
|
||
// The Matrix abstraction enables efficiency as well as interoperability. Go's
|
||
// type reflection capabilities are used to choose the most efficient routine
|
||
// given the specific concrete types. For example, in
|
||
// c.Mul(a, b)
|
||
// if a and b both implement RawMatrixer, that is, they can be represented as a
|
||
// {{.BLAS|alts}}.General, {{.BLAS|alts}}.Gemm (general matrix multiplication) is called, while
|
||
// instead if b is a RawSymmetricer {{.BLAS|alts}}.Symm is used (general-symmetric
|
||
// multiplication), and if b is a *Vector {{.BLAS|alts}}.Gemv is used.
|
||
//
|
||
// There are many possible type combinations and special cases. No specific guarantees
|
||
// are made about the performance of any method, and in particular, note that an
|
||
// abstract matrix type may be copied into a concrete type of the corresponding
|
||
// value. If there are specific special cases that are needed, please submit a
|
||
// pull-request or file an issue.
|
||
//{{end}}
|
||
{{define "invariants"}}// Invariants
|
||
//
|
||
// Matrix input arguments to functions are never directly modified. If an operation
|
||
// changes Matrix data, the mutated matrix will be the receiver of a function.
|
||
//
|
||
// For convenience, a matrix may be used as both a receiver and as an input, e.g.
|
||
// a.Pow(a, 6)
|
||
// v.SolveVec(a.T(), v)
|
||
// though in many cases this will cause an allocation (see Element Aliasing).
|
||
// An exception to this rule is Copy, which does not allow a.Copy(a.T()).
|
||
//{{end}}
|
||
{{define "aliasing"}}// Element Aliasing
|
||
//
|
||
// Most methods in {{if .Description}}{{.Description}}{{else}}{{.Name}}{{end}} modify receiver data. It is forbidden for the modified
|
||
// data region of the receiver to overlap the used data area of the input
|
||
// arguments. The exception to this rule is when the method receiver is equal to one
|
||
// of the input arguments, as in the a.Pow(a, 6) call above, or its implicit transpose.
|
||
//
|
||
// This prohibition is to help avoid subtle mistakes when the method needs to read
|
||
// from and write to the same data region. There are ways to make mistakes using the
|
||
// {{.Name}} API, and {{.Name}} functions will detect and complain about those.
|
||
// There are many ways to make mistakes by excursion from the {{.Name}} API via
|
||
// interaction with raw matrix values.
|
||
//
|
||
// If you need to read the rest of this section to understand the behavior of
|
||
// your program, you are being clever. Don't be clever. If you must be clever,
|
||
// {{.BLAS|join "/"}} and {{.LAPACK|join "/"}} may be used to call the behavior directly.
|
||
//
|
||
// {{if .Description}}{{.Description|sentence}}{{else}}{{.Name}}{{end}} will use the following rules to detect overlap between the receiver and one
|
||
// of the inputs:
|
||
// - the input implements one of the Raw methods, and
|
||
// - the Raw type matches that of the receiver or
|
||
// one is a RawMatrixer and the other is a RawVectorer, and
|
||
// - the address ranges of the backing data slices overlap, and
|
||
// - the strides differ or there is an overlap in the used data elements.
|
||
// If such an overlap is detected, the method will panic.
|
||
//
|
||
// The following cases will not panic:
|
||
// - the data slices do not overlap,
|
||
// - there is pointer identity between the receiver and input values after
|
||
// the value has been untransposed if necessary.
|
||
//
|
||
// {{if .Description}}{{.Description|sentence}}{{else}}{{.Name}}{{end}} will not attempt to detect element overlap if the input does not implement a
|
||
// Raw method, or if the Raw method differs from that of the receiver except when a
|
||
// conversion has occurred through a {{.Name}} API function. Method behavior is undefined
|
||
// if there is undetected overlap.
|
||
//{{end}}`))
|
||
|
||
type Package struct {
|
||
path string
|
||
|
||
Name string
|
||
Provides string
|
||
Description string
|
||
ExamplePackage string
|
||
Overview string
|
||
|
||
BLAS []string
|
||
LAPACK []string
|
||
|
||
template string
|
||
}
|
||
|
||
var pkgs = []Package{
|
||
{
|
||
path: ".",
|
||
|
||
Name: "matrix",
|
||
Description: "the matrix packages",
|
||
Provides: `common error handling mechanisms for matrix operations
|
||
// in mat64 and cmat128.`,
|
||
ExamplePackage: "mat64",
|
||
|
||
Overview: `// matrix provides:
|
||
// - Error type definitions
|
||
// - Error recovery mechanisms
|
||
// - Common constants used by mat64 and cmat128
|
||
//
|
||
// Errors
|
||
//
|
||
// The mat64 and cmat128 matrix packages share a common set of errors
|
||
// provided by matrix via the matrix.Error type.
|
||
//
|
||
// Errors are either returned directly or used as the parameter of a panic
|
||
// depending on the class of error encountered. Returned errors indicate
|
||
// that a call was not able to complete successfully while panics generally
|
||
// indicate a programmer or unrecoverable error.
|
||
//
|
||
// Examples of each type are found in the mat64 Solve methods, which find
|
||
// x such that A*x = b.
|
||
//
|
||
// An error value is returned from the function or method when the operation
|
||
// can meaningfully fail. The Solve operation cannot complete if A is
|
||
// singular. However, determining the singularity of A is most easily
|
||
// discovered during the Solve procedure itself and is a valid result from
|
||
// the operation, so in this case an error is returned.
|
||
//
|
||
// A function will panic when the input parameters are inappropriate for
|
||
// the function. In Solve, for example, the number of rows of each input
|
||
// matrix must be equal because of the rules of matrix multiplication.
|
||
// Similarly, for solving A*x = b, a non-zero receiver must have the same
|
||
// number of rows as A has columns and must have the same number of columns
|
||
// as b. In all cases where a function will panic, conditions that would
|
||
// lead to a panic can easily be checked prior to a call.
|
||
//
|
||
// Error Recovery
|
||
//
|
||
// When a matrix.Error is the parameter of a panic, the panic can be
|
||
// recovered by a Maybe function, which will then return the error.
|
||
// Panics that are not of type matrix.Error are re-panicked by the
|
||
// Maybe functions.`,
|
||
BLAS: []string{"blas64", "cblas128"},
|
||
LAPACK: []string{"lapack64", "clapack128"},
|
||
|
||
template: `{{template "common" .}}
|
||
{{template "invariants" .}}
|
||
{{template "aliasing" .}}
|
||
package {{.Name}} // import "gonum.org/v1/gonum/{{.Name}}"
|
||
`,
|
||
},
|
||
{
|
||
path: "mat64",
|
||
|
||
Name: "mat64",
|
||
Provides: `implementations of float64 matrix structures and
|
||
// linear algebra operations on them.`,
|
||
|
||
Overview: `// mat64 provides:
|
||
// - Interfaces for Matrix classes (Matrix, Symmetric, Triangular)
|
||
// - Concrete implementations (Dense, SymDense, TriDense)
|
||
// - Methods and functions for using matrix data (Add, Trace, SymRankOne)
|
||
// - Types for constructing and using matrix factorizations (QR, LU)
|
||
//
|
||
// A matrix may be constructed through the corresponding New function. If no
|
||
// backing array is provided the matrix will be initialized to all zeros.
|
||
// // Allocate a zeroed matrix of size 3×5
|
||
// zero := mat64.NewDense(3, 5, nil)
|
||
// If a backing data slice is provided, the matrix will have those elements.
|
||
// Matrices are all stored in row-major format.
|
||
// // Generate a 6×6 matrix of random values.
|
||
// data := make([]float64, 36)
|
||
// for i := range data {
|
||
// data[i] = rand.NormFloat64()
|
||
// }
|
||
// a := mat64.NewDense(6, 6, data)
|
||
//
|
||
// Operations involving matrix data are implemented as functions when the values
|
||
// of the matrix remain unchanged
|
||
// tr := mat64.Trace(a)
|
||
// and are implemented as methods when the operation modifies the receiver.
|
||
// zero.Copy(a)
|
||
//
|
||
// Receivers must be the correct size for the matrix operations, otherwise the
|
||
// operation will panic. As a special case for convenience, a zero-sized matrix
|
||
// will be modified to have the correct size, allocating data if necessary.
|
||
// var c mat64.Dense // construct a new zero-sized matrix
|
||
// c.Mul(a, a) // c is automatically adjusted to be 6×6`,
|
||
|
||
BLAS: []string{"blas64"},
|
||
LAPACK: []string{"lapack64"},
|
||
|
||
template: `{{template "common" .}}
|
||
{{template "interfaces" .}}
|
||
{{template "factorization" .}}
|
||
{{template "blas" .}}
|
||
{{template "switching" .}}
|
||
{{template "invariants" .}}
|
||
{{template "aliasing" .}}
|
||
package {{.Name}} // import "gonum.org/v1/gonum/matrix/{{.Name}}"
|
||
`,
|
||
},
|
||
{
|
||
path: "cmat128",
|
||
|
||
Name: "cmat128",
|
||
Provides: `implementations of complex128 matrix structures and
|
||
// linear algebra operations on them.`,
|
||
|
||
Overview: `// cmat128 provides:
|
||
// - Interfaces for a complex Matrix`,
|
||
|
||
BLAS: []string{"cblas128"},
|
||
LAPACK: []string{"clapack128"},
|
||
|
||
template: `{{template "common" . }}
|
||
{{template "blas" .}}
|
||
{{template "switching" .}}
|
||
{{template "invariants" .}}
|
||
{{template "aliasing" .}}
|
||
package {{.Name}} // import "gonum.org/v1/gonum/matrix/{{.Name}}"
|
||
`,
|
||
},
|
||
}
|
||
|
||
var funcs = template.FuncMap{
|
||
"sentence": sentence,
|
||
"alts": alts,
|
||
"join": join,
|
||
}
|
||
|
||
// sentence converts a string to sentence case where the string is the prefix of the sentence.
|
||
func sentence(s string) string {
|
||
if len(s) == 0 {
|
||
return ""
|
||
}
|
||
_, size := utf8.DecodeRune([]byte(s))
|
||
return strings.ToUpper(s[:size]) + s[size:]
|
||
}
|
||
|
||
// alts renders a []string as a glob alternatives list.
|
||
func alts(s []string) string {
|
||
switch len(s) {
|
||
case 0:
|
||
return ""
|
||
case 1:
|
||
return s[0]
|
||
default:
|
||
return fmt.Sprintf("{%s}", strings.Join(s, ","))
|
||
}
|
||
}
|
||
|
||
// join is strings.Join with the parameter order changed.
|
||
func join(sep string, s []string) string {
|
||
return strings.Join(s, sep)
|
||
}
|
||
|
||
func main() {
|
||
for _, pkg := range pkgs {
|
||
t, err := template.Must(docs.Clone()).Parse(pkg.template)
|
||
if err != nil {
|
||
log.Fatalf("failed to parse template: %v", err)
|
||
}
|
||
file := filepath.Join(pkg.path, "doc.go")
|
||
f, err := os.Create(file)
|
||
if err != nil {
|
||
log.Fatalf("failed to create %q: %v", file, err)
|
||
}
|
||
err = t.Execute(f, pkg)
|
||
if err != nil {
|
||
log.Fatalf("failed to execute template: %v", err)
|
||
}
|
||
f.Close()
|
||
}
|
||
}
|