mirror of
https://github.com/gonum/gonum.git
synced 2025-09-27 03:26:04 +08:00

Changes made in dsp/fourier/internal/fftpack break the formatting used there, so these are reverted. There will be complaints in CI. [git-generate] gofmt -w . go generate gonum.org/v1/gonum/blas go generate gonum.org/v1/gonum/blas/gonum go generate gonum.org/v1/gonum/unit go generate gonum.org/v1/gonum/unit/constant go generate gonum.org/v1/gonum/graph/formats/dot go generate gonum.org/v1/gonum/graph/formats/rdf go generate gonum.org/v1/gonum/stat/card git checkout -- dsp/fourier/internal/fftpack
410 lines
8.7 KiB
Go
410 lines
8.7 KiB
Go
// This file is dual licensed under CC0 and The Gonum License.
|
|
//
|
|
// Copyright ©2017 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.
|
|
//
|
|
// Copyright ©2017 Robin Eklind.
|
|
// This file is made available under a Creative Commons CC0 1.0
|
|
// Universal Public Domain Dedication.
|
|
|
|
package ast
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
)
|
|
|
|
// === [ File ] ================================================================
|
|
|
|
// A File represents a DOT file.
|
|
//
|
|
// Examples.
|
|
//
|
|
// digraph G {
|
|
// A -> B
|
|
// }
|
|
// graph H {
|
|
// C - D
|
|
// }
|
|
type File struct {
|
|
// Graphs.
|
|
Graphs []*Graph
|
|
}
|
|
|
|
// String returns the string representation of the file.
|
|
func (f *File) String() string {
|
|
buf := new(bytes.Buffer)
|
|
for i, graph := range f.Graphs {
|
|
if i != 0 {
|
|
buf.WriteString("\n")
|
|
}
|
|
buf.WriteString(graph.String())
|
|
}
|
|
return buf.String()
|
|
}
|
|
|
|
// === [ Graphs ] ==============================================================
|
|
|
|
// A Graph represents a directed or an undirected graph.
|
|
//
|
|
// Examples.
|
|
//
|
|
// digraph G {
|
|
// A -> {B C}
|
|
// B -> C
|
|
// }
|
|
type Graph struct {
|
|
// Strict graph; multi-edges forbidden.
|
|
Strict bool
|
|
// Directed graph.
|
|
Directed bool
|
|
// Graph ID; or empty if anonymous.
|
|
ID string
|
|
// Graph statements.
|
|
Stmts []Stmt
|
|
}
|
|
|
|
// String returns the string representation of the graph.
|
|
func (g *Graph) String() string {
|
|
buf := new(bytes.Buffer)
|
|
if g.Strict {
|
|
buf.WriteString("strict ")
|
|
}
|
|
if g.Directed {
|
|
buf.WriteString("digraph ")
|
|
} else {
|
|
buf.WriteString("graph ")
|
|
}
|
|
if len(g.ID) > 0 {
|
|
fmt.Fprintf(buf, "%s ", g.ID)
|
|
}
|
|
buf.WriteString("{\n")
|
|
for _, stmt := range g.Stmts {
|
|
fmt.Fprintf(buf, "\t%s\n", stmt)
|
|
}
|
|
buf.WriteString("}")
|
|
return buf.String()
|
|
}
|
|
|
|
// === [ Statements ] ==========================================================
|
|
|
|
// A Stmt represents a statement, and has one of the following underlying types.
|
|
//
|
|
// *NodeStmt
|
|
// *EdgeStmt
|
|
// *AttrStmt
|
|
// *Attr
|
|
// *Subgraph
|
|
type Stmt interface {
|
|
fmt.Stringer
|
|
// isStmt ensures that only statements can be assigned to the Stmt interface.
|
|
isStmt()
|
|
}
|
|
|
|
// --- [ Node statement ] ------------------------------------------------------
|
|
|
|
// A NodeStmt represents a node statement.
|
|
//
|
|
// Examples.
|
|
//
|
|
// A [color=blue]
|
|
type NodeStmt struct {
|
|
// Node.
|
|
Node *Node
|
|
// Node attributes.
|
|
Attrs []*Attr
|
|
}
|
|
|
|
// String returns the string representation of the node statement.
|
|
func (e *NodeStmt) String() string {
|
|
buf := new(bytes.Buffer)
|
|
buf.WriteString(e.Node.String())
|
|
if len(e.Attrs) > 0 {
|
|
buf.WriteString(" [")
|
|
for i, attr := range e.Attrs {
|
|
if i != 0 {
|
|
buf.WriteString(" ")
|
|
}
|
|
buf.WriteString(attr.String())
|
|
}
|
|
buf.WriteString("]")
|
|
}
|
|
return buf.String()
|
|
}
|
|
|
|
// --- [ Edge statement ] ------------------------------------------------------
|
|
|
|
// An EdgeStmt represents an edge statement.
|
|
//
|
|
// Examples.
|
|
//
|
|
// A -> B
|
|
// A -> {B C}
|
|
// A -> B -> C
|
|
type EdgeStmt struct {
|
|
// Source vertex.
|
|
From Vertex
|
|
// Outgoing edge.
|
|
To *Edge
|
|
// Edge attributes.
|
|
Attrs []*Attr
|
|
}
|
|
|
|
// String returns the string representation of the edge statement.
|
|
func (e *EdgeStmt) String() string {
|
|
buf := new(bytes.Buffer)
|
|
fmt.Fprintf(buf, "%s %s", e.From, e.To)
|
|
if len(e.Attrs) > 0 {
|
|
buf.WriteString(" [")
|
|
for i, attr := range e.Attrs {
|
|
if i != 0 {
|
|
buf.WriteString(" ")
|
|
}
|
|
buf.WriteString(attr.String())
|
|
}
|
|
buf.WriteString("]")
|
|
}
|
|
return buf.String()
|
|
}
|
|
|
|
// An Edge represents an edge between two vertices.
|
|
type Edge struct {
|
|
// Directed edge.
|
|
Directed bool
|
|
// Destination vertex.
|
|
Vertex Vertex
|
|
// Outgoing edge; or nil if none.
|
|
To *Edge
|
|
}
|
|
|
|
// String returns the string representation of the edge.
|
|
func (e *Edge) String() string {
|
|
op := "--"
|
|
if e.Directed {
|
|
op = "->"
|
|
}
|
|
if e.To != nil {
|
|
return fmt.Sprintf("%s %s %s", op, e.Vertex, e.To)
|
|
}
|
|
return fmt.Sprintf("%s %s", op, e.Vertex)
|
|
}
|
|
|
|
// --- [ Attribute statement ] -------------------------------------------------
|
|
|
|
// An AttrStmt represents an attribute statement.
|
|
//
|
|
// Examples.
|
|
//
|
|
// graph [rankdir=LR]
|
|
// node [color=blue fillcolor=red]
|
|
// edge [minlen=1]
|
|
type AttrStmt struct {
|
|
// Graph component kind to which the attributes are assigned.
|
|
Kind Kind
|
|
// Attributes.
|
|
Attrs []*Attr
|
|
}
|
|
|
|
// String returns the string representation of the attribute statement.
|
|
func (a *AttrStmt) String() string {
|
|
buf := new(bytes.Buffer)
|
|
fmt.Fprintf(buf, "%s [", a.Kind)
|
|
for i, attr := range a.Attrs {
|
|
if i != 0 {
|
|
buf.WriteString(" ")
|
|
}
|
|
buf.WriteString(attr.String())
|
|
}
|
|
buf.WriteString("]")
|
|
return buf.String()
|
|
}
|
|
|
|
// Kind specifies the set of graph components to which attribute statements may
|
|
// be assigned.
|
|
type Kind uint
|
|
|
|
// Graph component kinds.
|
|
const (
|
|
GraphKind Kind = iota // graph
|
|
NodeKind // node
|
|
EdgeKind // edge
|
|
)
|
|
|
|
// String returns the string representation of the graph component kind.
|
|
func (k Kind) String() string {
|
|
switch k {
|
|
case GraphKind:
|
|
return "graph"
|
|
case NodeKind:
|
|
return "node"
|
|
case EdgeKind:
|
|
return "edge"
|
|
}
|
|
panic(fmt.Sprintf("invalid graph component kind (%d)", k))
|
|
}
|
|
|
|
// --- [ Attribute ] -----------------------------------------------------------
|
|
|
|
// An Attr represents an attribute.
|
|
//
|
|
// Examples.
|
|
//
|
|
// rank=same
|
|
type Attr struct {
|
|
// Attribute key.
|
|
Key string
|
|
// Attribute value.
|
|
Val string
|
|
}
|
|
|
|
// String returns the string representation of the attribute.
|
|
func (a *Attr) String() string {
|
|
return fmt.Sprintf("%s=%s", a.Key, a.Val)
|
|
}
|
|
|
|
// --- [ Subgraph ] ------------------------------------------------------------
|
|
|
|
// A Subgraph represents a subgraph vertex.
|
|
//
|
|
// Examples.
|
|
//
|
|
// subgraph S {A B C}
|
|
type Subgraph struct {
|
|
// Subgraph ID; or empty if none.
|
|
ID string
|
|
// Subgraph statements.
|
|
Stmts []Stmt
|
|
}
|
|
|
|
// String returns the string representation of the subgraph.
|
|
func (s *Subgraph) String() string {
|
|
buf := new(bytes.Buffer)
|
|
if len(s.ID) > 0 {
|
|
fmt.Fprintf(buf, "subgraph %s ", s.ID)
|
|
}
|
|
buf.WriteString("{")
|
|
for i, stmt := range s.Stmts {
|
|
if i != 0 {
|
|
buf.WriteString(" ")
|
|
}
|
|
buf.WriteString(stmt.String())
|
|
}
|
|
buf.WriteString("}")
|
|
return buf.String()
|
|
}
|
|
|
|
// isStmt ensures that only statements can be assigned to the Stmt interface.
|
|
func (*NodeStmt) isStmt() {}
|
|
func (*EdgeStmt) isStmt() {}
|
|
func (*AttrStmt) isStmt() {}
|
|
func (*Attr) isStmt() {}
|
|
func (*Subgraph) isStmt() {}
|
|
|
|
// === [ Vertices ] ============================================================
|
|
|
|
// A Vertex represents a vertex, and has one of the following underlying types.
|
|
//
|
|
// *Node
|
|
// *Subgraph
|
|
type Vertex interface {
|
|
fmt.Stringer
|
|
// isVertex ensures that only vertices can be assigned to the Vertex
|
|
// interface.
|
|
isVertex()
|
|
}
|
|
|
|
// --- [ Node identifier ] -----------------------------------------------------
|
|
|
|
// A Node represents a node vertex.
|
|
//
|
|
// Examples.
|
|
//
|
|
// A
|
|
// A:nw
|
|
type Node struct {
|
|
// Node ID.
|
|
ID string
|
|
// Node port; or nil if none.
|
|
Port *Port
|
|
}
|
|
|
|
// String returns the string representation of the node.
|
|
func (n *Node) String() string {
|
|
if n.Port != nil {
|
|
return fmt.Sprintf("%s%s", n.ID, n.Port)
|
|
}
|
|
return n.ID
|
|
}
|
|
|
|
// A Port specifies where on a node an edge should be aimed.
|
|
type Port struct {
|
|
// Port ID; or empty if none.
|
|
ID string
|
|
// Compass point.
|
|
CompassPoint CompassPoint
|
|
}
|
|
|
|
// String returns the string representation of the port.
|
|
func (p *Port) String() string {
|
|
buf := new(bytes.Buffer)
|
|
if len(p.ID) > 0 {
|
|
fmt.Fprintf(buf, ":%s", p.ID)
|
|
}
|
|
if p.CompassPoint != CompassPointNone {
|
|
fmt.Fprintf(buf, ":%s", p.CompassPoint)
|
|
}
|
|
return buf.String()
|
|
}
|
|
|
|
// CompassPoint specifies the set of compass points.
|
|
type CompassPoint uint
|
|
|
|
// Compass points.
|
|
const (
|
|
CompassPointNone CompassPoint = iota //
|
|
CompassPointNorth // n
|
|
CompassPointNorthEast // ne
|
|
CompassPointEast // e
|
|
CompassPointSouthEast // se
|
|
CompassPointSouth // s
|
|
CompassPointSouthWest // sw
|
|
CompassPointWest // w
|
|
CompassPointNorthWest // nw
|
|
CompassPointCenter // c
|
|
CompassPointDefault // _
|
|
)
|
|
|
|
// String returns the string representation of the compass point.
|
|
func (c CompassPoint) String() string {
|
|
switch c {
|
|
case CompassPointNone:
|
|
return ""
|
|
case CompassPointNorth:
|
|
return "n"
|
|
case CompassPointNorthEast:
|
|
return "ne"
|
|
case CompassPointEast:
|
|
return "e"
|
|
case CompassPointSouthEast:
|
|
return "se"
|
|
case CompassPointSouth:
|
|
return "s"
|
|
case CompassPointSouthWest:
|
|
return "sw"
|
|
case CompassPointWest:
|
|
return "w"
|
|
case CompassPointNorthWest:
|
|
return "nw"
|
|
case CompassPointCenter:
|
|
return "c"
|
|
case CompassPointDefault:
|
|
return "_"
|
|
}
|
|
panic(fmt.Sprintf("invalid compass point (%d)", uint(c)))
|
|
}
|
|
|
|
// isVertex ensures that only vertices can be assigned to the Vertex interface.
|
|
func (*Node) isVertex() {}
|
|
func (*Subgraph) isVertex() {}
|