This repository has been archived by the owner on Dec 10, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 51
/
gendoc.go
346 lines (319 loc) · 13 KB
/
gendoc.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
// 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.
// This repository is no longer maintained.
// Development has moved to https://github.com/gonum/gonum.
//
// 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}}
`,
},
{
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}}
`,
},
{
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}}
`,
},
}
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()
}
}