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
178 lines
5.2 KiB
Go
178 lines
5.2 KiB
Go
// Copyright ©2020 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 2009 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
//go:build !safe
|
|
// +build !safe
|
|
|
|
package iterator
|
|
|
|
import (
|
|
"unsafe"
|
|
|
|
"gonum.org/v1/gonum/graph"
|
|
)
|
|
|
|
// A mapIter is an iterator for ranging over a map.
|
|
type mapIter struct {
|
|
m *emptyInterface
|
|
hiter hiter
|
|
}
|
|
|
|
type emptyInterface struct {
|
|
typ, word unsafe.Pointer
|
|
}
|
|
|
|
// hiter's structure matches runtime.hiter's structure.
|
|
// Having a clone here allows us to embed a map iterator
|
|
// inside type mapIter so that mapIters can be re-used
|
|
// without doing any allocations.
|
|
//
|
|
//lint:ignore U1000 This is a verbatim copy of the runtime type.
|
|
type hiter struct {
|
|
key unsafe.Pointer
|
|
elem unsafe.Pointer
|
|
t unsafe.Pointer
|
|
h unsafe.Pointer
|
|
buckets unsafe.Pointer
|
|
bptr unsafe.Pointer
|
|
overflow *[]unsafe.Pointer
|
|
oldoverflow *[]unsafe.Pointer
|
|
startBucket uintptr
|
|
offset uint8
|
|
wrapped bool
|
|
B uint8
|
|
i uint8
|
|
bucket uintptr
|
|
checkBucket uintptr
|
|
}
|
|
|
|
func (h *hiter) initialized() bool {
|
|
return h.t != nil
|
|
}
|
|
|
|
// newMapIterNodes returns a range iterator for a map of nodes.
|
|
// The returned mapIter must not have its line or weightedLine methods called.
|
|
func newMapIterNodes(m map[int64]graph.Node) *mapIter {
|
|
return &mapIter{m: eface(m)}
|
|
}
|
|
|
|
// newMapIterEdges returns a range iterator for a map of edges.
|
|
// The returned mapIter must not have its node, line or weightedLine methods called.
|
|
func newMapIterEdges(m map[int64]graph.Edge) *mapIter {
|
|
return &mapIter{m: eface(m)}
|
|
}
|
|
|
|
// newMapIterLines returns a range iterator for a map of line.
|
|
// The returned mapIter must not have its node or weightedLine method called.
|
|
func newMapIterLines(m map[int64]graph.Line) *mapIter {
|
|
return &mapIter{m: eface(m)}
|
|
}
|
|
|
|
// newMapIterWeightedLines returns a range iterator for a map of line.
|
|
// The returned mapIter must not have its node, line or weightedLine methods called.
|
|
func newMapIterWeightedLines(m map[int64]graph.WeightedLine) *mapIter {
|
|
return &mapIter{m: eface(m)}
|
|
}
|
|
|
|
// newMapIterByWeightedEdges returns a range iterator for a map of edges.
|
|
// The returned mapIter must not have its node, line or weightedLine methods called.
|
|
func newMapIterByWeightedEdges(m map[int64]graph.WeightedEdge) *mapIter {
|
|
return &mapIter{m: eface(m)}
|
|
}
|
|
|
|
// newMapIterByLines returns a range iterator for a map of edges.
|
|
// The returned mapIter must not have its node, line or weightedLine methods called.
|
|
func newMapIterByLines(m map[int64]map[int64]graph.Line) *mapIter {
|
|
return &mapIter{m: eface(m)}
|
|
}
|
|
|
|
// newMapIterByWeightedLines returns a range iterator for a map of edges.
|
|
// The returned mapIter must not have its node, line or weightedLine methods called.
|
|
func newMapIterByWeightedLines(m map[int64]map[int64]graph.WeightedLine) *mapIter {
|
|
return &mapIter{m: eface(m)}
|
|
}
|
|
|
|
func eface(i interface{}) *emptyInterface {
|
|
return (*emptyInterface)(unsafe.Pointer(&i))
|
|
}
|
|
|
|
// id returns the key of the iterator's current map entry.
|
|
func (it *mapIter) id() int64 {
|
|
if !it.hiter.initialized() {
|
|
panic("mapIter.id called before Next")
|
|
}
|
|
if mapiterkey(&it.hiter) == nil {
|
|
panic("mapIter.id called on exhausted iterator")
|
|
}
|
|
return *(*int64)(mapiterkey(&it.hiter))
|
|
}
|
|
|
|
// node returns the value of the iterator's current map entry.
|
|
func (it *mapIter) node() graph.Node {
|
|
if !it.hiter.initialized() {
|
|
panic("mapIter.node called before next")
|
|
}
|
|
if mapiterkey(&it.hiter) == nil {
|
|
panic("mapIter.node called on exhausted iterator")
|
|
}
|
|
return *(*graph.Node)(mapiterelem(&it.hiter))
|
|
}
|
|
|
|
// line returns the value of the iterator's current map entry.
|
|
func (it *mapIter) line() graph.Line {
|
|
if !it.hiter.initialized() {
|
|
panic("mapIter.line called before next")
|
|
}
|
|
if mapiterkey(&it.hiter) == nil {
|
|
panic("mapIter.line called on exhausted iterator")
|
|
}
|
|
return *(*graph.Line)(mapiterelem(&it.hiter))
|
|
}
|
|
|
|
// weightedLine returns the value of the iterator's current map entry.
|
|
func (it *mapIter) weightedLine() graph.WeightedLine {
|
|
if !it.hiter.initialized() {
|
|
panic("mapIter.weightedLine called before next")
|
|
}
|
|
if mapiterkey(&it.hiter) == nil {
|
|
panic("mapIter.weightedLine called on exhausted iterator")
|
|
}
|
|
return *(*graph.WeightedLine)(mapiterelem(&it.hiter))
|
|
}
|
|
|
|
// next advances the map iterator and reports whether there is another
|
|
// entry. It returns false when the iterator is exhausted; subsequent
|
|
// calls to Key, Value, or next will panic.
|
|
func (it *mapIter) next() bool {
|
|
if !it.hiter.initialized() {
|
|
mapiterinit(it.m.typ, it.m.word, &it.hiter)
|
|
} else {
|
|
if mapiterkey(&it.hiter) == nil {
|
|
panic("mapIter.next called on exhausted iterator")
|
|
}
|
|
mapiternext(&it.hiter)
|
|
}
|
|
return mapiterkey(&it.hiter) != nil
|
|
}
|
|
|
|
//go:linkname mapiterinit runtime.mapiterinit
|
|
//go:noescape
|
|
func mapiterinit(t, m unsafe.Pointer, it *hiter)
|
|
|
|
//go:linkname mapiterkey reflect.mapiterkey
|
|
//go:noescape
|
|
func mapiterkey(it *hiter) (key unsafe.Pointer)
|
|
|
|
//go:linkname mapiterelem reflect.mapiterelem
|
|
//go:noescape
|
|
func mapiterelem(it *hiter) (elem unsafe.Pointer)
|
|
|
|
//go:linkname mapiternext reflect.mapiternext
|
|
//go:noescape
|
|
func mapiternext(it *hiter)
|