Files
astro/basic/nutation_memo.go
T

76 lines
2.4 KiB
Go
Raw Normal View History

package basic
import (
"math"
"sync"
"sync/atomic"
)
// Nutation2000B 是 jd 的纯函数,但升落、星历与掩星路径会对同一批瞬时反复求值:一条计算链里
// 地球自转、状态上下文与几何装配各自求一次同一个瞬时。这里用有界直接映射表记住结果:
// 槽位固定、无分配、RWMutex 保证 c-shared 宿主多线程安全。章动只依赖传入的 jd,与 ΔT 世代无关。
// Nutation2000B is a pure function of jd, yet the rise/set, ephemeris and occultation chains evaluate
// it repeatedly for the same instants from independent code paths. This bounded direct-mapped memo
// removes that redundancy with fixed slots, no allocation and an RWMutex for the c-shared host.
// Nutation depends only on its argument, so no ΔT generation stamp is needed.
const nutationMemoBits = 13
const nutationMemoSize = 1 << nutationMemoBits
type nutationMemoEntry struct {
// key 是 math.Float64bits(jd)+1,0 表示空槽(避免 jd=0 与空槽同码)。
key uint64
dpsi, deps float64
}
var (
nutationMemoMu sync.RWMutex
nutationMemoTable [nutationMemoSize]nutationMemoEntry
nutationMemoHits uint64
nutationMemoMiss uint64
)
func nutationMemoIndex(jd float64) uint64 {
bits := math.Float64bits(jd)
return (bits ^ (bits >> 31)) & (nutationMemoSize - 1)
}
func nutationMemoLoad(jd float64) (float64, float64, bool) {
key := math.Float64bits(jd) + 1
entry := &nutationMemoTable[nutationMemoIndex(jd)]
nutationMemoMu.RLock()
entryKey, dpsi, deps := entry.key, entry.dpsi, entry.deps
nutationMemoMu.RUnlock()
if key != 0 && entryKey == key {
atomic.AddUint64(&nutationMemoHits, 1)
return dpsi, deps, true
}
atomic.AddUint64(&nutationMemoMiss, 1)
return 0, 0, false
}
func nutationMemoStore(jd, dpsi, deps float64) {
key := math.Float64bits(jd) + 1
if key == 0 {
return
}
nutationMemoMu.Lock()
nutationMemoTable[nutationMemoIndex(jd)] = nutationMemoEntry{key: key, dpsi: dpsi, deps: deps}
nutationMemoMu.Unlock()
}
// nutationMemoStats 返回命中/未命中计数,供测试守护命中率。
func nutationMemoStats() (uint64, uint64) {
return atomic.LoadUint64(&nutationMemoHits), atomic.LoadUint64(&nutationMemoMiss)
}
func resetNutationMemo() {
nutationMemoMu.Lock()
for i := range nutationMemoTable {
nutationMemoTable[i] = nutationMemoEntry{}
}
nutationMemoMu.Unlock()
atomic.StoreUint64(&nutationMemoHits, 0)
atomic.StoreUint64(&nutationMemoMiss, 0)
}