16c62a97d5
- 新增时标、ΔT 模型、质心时间与 UT1 支持 - 改进日月食、月掩、行星事件及路径边界计算 - 完善恒星三维自行与动态距离传播 - 扩展 SVG、GeoJSON、KML 输出与底层距离换算工具 - 整理中英文手册、示例资源及回归测试
86 lines
2.4 KiB
Go
86 lines
2.4 KiB
Go
package basic
|
|
|
|
import (
|
|
"math"
|
|
"sync"
|
|
"sync/atomic"
|
|
)
|
|
|
|
// 固定容量缓存以 ΔT 世代区分模型,RWMutex 保护宿主多线程访问。
|
|
const siderealMemoBits = 14
|
|
|
|
const siderealMemoSize = 1 << siderealMemoBits
|
|
|
|
type siderealMemoEntry struct {
|
|
key uint64
|
|
value float64
|
|
generation uint64
|
|
}
|
|
|
|
var (
|
|
siderealMemoMu sync.RWMutex
|
|
siderealMemoTable [siderealMemoSize]siderealMemoEntry
|
|
siderealMemoHits uint64
|
|
siderealMemoMisses uint64
|
|
siderealMemoStores uint64
|
|
)
|
|
|
|
// siderealMemoIndex 用高低位混合避免相邻儒略日落在相邻槽位而互相驱逐。
|
|
func siderealMemoIndex(jd float64) uint64 {
|
|
bits := math.Float64bits(jd)
|
|
return (bits ^ (bits >> 29)) & (siderealMemoSize - 1)
|
|
}
|
|
|
|
// siderealMemoLoad 返回缓存命中值;ΔT 世代不匹配时按未命中处理。
|
|
func siderealMemoLoad(jd float64) (float64, bool) {
|
|
generation := deltaTGenerationValue()
|
|
entry := &siderealMemoTable[siderealMemoIndex(jd)]
|
|
siderealMemoMu.RLock()
|
|
key, value, entryGeneration := entry.key, entry.value, entry.generation
|
|
siderealMemoMu.RUnlock()
|
|
if entryGeneration == generation && key == math.Float64bits(jd) {
|
|
atomic.AddUint64(&siderealMemoHits, 1)
|
|
return value, true
|
|
}
|
|
atomic.AddUint64(&siderealMemoMisses, 1)
|
|
return 0, false
|
|
}
|
|
|
|
// 世代须在求值前采样,防止旧模型结果被缓存为新模型结果。
|
|
func siderealMemoStore(jd, value float64, generation uint64) {
|
|
if deltaTGenerationValue() != generation {
|
|
return
|
|
}
|
|
index := siderealMemoIndex(jd)
|
|
siderealMemoMu.Lock()
|
|
siderealMemoTable[index] = siderealMemoEntry{
|
|
key: math.Float64bits(jd),
|
|
value: value,
|
|
generation: generation,
|
|
}
|
|
siderealMemoMu.Unlock()
|
|
atomic.AddUint64(&siderealMemoStores, 1)
|
|
}
|
|
|
|
// siderealMemoGeneration 在求值前采样 ΔT 世代,供 siderealMemoStore 校验。
|
|
func siderealMemoGeneration() uint64 {
|
|
return deltaTGenerationValue()
|
|
}
|
|
|
|
// siderealMemoStats 返回命中/未命中/写入计数,供测试守护记忆表确实生效。
|
|
func siderealMemoStats() (hits, misses, stores uint64) {
|
|
return atomic.LoadUint64(&siderealMemoHits), atomic.LoadUint64(&siderealMemoMisses),
|
|
atomic.LoadUint64(&siderealMemoStores)
|
|
}
|
|
|
|
func resetSiderealMemo() {
|
|
siderealMemoMu.Lock()
|
|
for i := range siderealMemoTable {
|
|
siderealMemoTable[i] = siderealMemoEntry{}
|
|
}
|
|
siderealMemoMu.Unlock()
|
|
atomic.StoreUint64(&siderealMemoHits, 0)
|
|
atomic.StoreUint64(&siderealMemoMisses, 0)
|
|
atomic.StoreUint64(&siderealMemoStores, 0)
|
|
}
|