2bf8478639
- 新增日月食中心带、偏食带、阴影足迹、等时线、食分线及升落边界计算,支持极区与混合食拓扑 - 新增日食单时刻阴影求解器、站心状态查询、批量采样和 ΔT 覆盖接口 - 重构恒星与行星月掩路径,补充有限盘面接触、站心修正、掩带宽度、极区投影及升落边界 - 扩展 SVG 与 GeoJSON 输出,支持详细面板、全球/极区/地球投影、边界闭合、时间标记和拓扑签名 - 扩展日月食候选搜索、局地搜索、沙罗序列预计算与范围外推,补充系列锚点和成员一致性校验 - 补齐古历纪年、儒略历独有闰日、多公历候选、历法改革跨日及精确日期运算接口 - 优化 ΔT、章动、恒星时、月球地平线、事件根搜索和本地星历缓存,降低重复计算开销并提升边界稳定
76 lines
2.4 KiB
Go
76 lines
2.4 KiB
Go
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)
|
||
}
|