mirror of
				https://github.com/gonum/gonum.git
				synced 2025-10-31 10:36:30 +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()
 | ||
| 	}
 | ||
| }
 | 
