- 新增日食、月食、本地可见性、中心线、半影区域、SVG 图示与沙罗周期信息 - 新增行星冲合、留、方照、物理星历、视直径、相位、亮肢角、轨道节点等计算 - 新增木星伽利略卫星位置、现象与接触事件计算 - 新增恒星星表、星座判定、自行修正与观测辅助能力 - 新增 coord、formula、orbit、sundial、lite/sun、lite/moon 等扩展包 - 完善农历年号、月相英文别名、视差角、大气质量、折射、日晷与双星计算 - 增加 NASA、JPL Horizons、IMCCE 等回归测试数据与基线测试 - 重构基础算法文件组织,补充大量公开 API 注释和语义回归测试 - 更新中文和英文 README,补充示例、精度说明、SVG 配图
176 lines
8.5 KiB
Go
176 lines
8.5 KiB
Go
package astro_test
|
|
|
|
import (
|
|
"encoding/json"
|
|
"math"
|
|
"os"
|
|
"testing"
|
|
|
|
"b612.me/astro/basic"
|
|
"b612.me/astro/planet"
|
|
)
|
|
|
|
type lowPrecisionSunSnapshot struct {
|
|
LoBits uint64 `json:"lo_bits"`
|
|
MBits uint64 `json:"m_bits"`
|
|
EccBits uint64 `json:"ecc_bits"`
|
|
PeriBits uint64 `json:"peri_bits"`
|
|
MidBits uint64 `json:"mid_bits"`
|
|
TrueLoBits uint64 `json:"true_lo_bits"`
|
|
ApparentLoBits uint64 `json:"apparent_lo_bits"`
|
|
ApparentRaBits uint64 `json:"apparent_ra_bits"`
|
|
ApparentDecBits uint64 `json:"apparent_dec_bits"`
|
|
TrueRaBits uint64 `json:"true_ra_bits"`
|
|
TrueDecBits uint64 `json:"true_dec_bits"`
|
|
DistanceBits uint64 `json:"distance_bits"`
|
|
}
|
|
|
|
type lowPrecisionMoonSnapshot struct {
|
|
LoBits uint64 `json:"lo_bits"`
|
|
SunAngleBits uint64 `json:"sun_angle_bits"`
|
|
MBits uint64 `json:"m_bits"`
|
|
LonXBits uint64 `json:"lonx_bits"`
|
|
IBits uint64 `json:"i_bits"`
|
|
RBits uint64 `json:"r_bits"`
|
|
BBits uint64 `json:"b_bits"`
|
|
TrueLoBits uint64 `json:"true_lo_bits"`
|
|
TrueBoBits uint64 `json:"true_bo_bits"`
|
|
AwayBits uint64 `json:"away_bits"`
|
|
ApparentLoBits uint64 `json:"apparent_lo_bits"`
|
|
TrueRaBits uint64 `json:"true_ra_bits"`
|
|
TrueDecBits uint64 `json:"true_dec_bits"`
|
|
}
|
|
|
|
type lowPrecisionSample struct {
|
|
UTC string `json:"utc"`
|
|
TTJD float64 `json:"tt_jd"`
|
|
Sun lowPrecisionSunSnapshot `json:"sun"`
|
|
Moon lowPrecisionMoonSnapshot `json:"moon"`
|
|
}
|
|
|
|
func loadLowPrecisionSamples(t *testing.T) []lowPrecisionSample {
|
|
t.Helper()
|
|
|
|
data, err := os.ReadFile("testdata/low_precision_sun_moon_baseline.json")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
var samples []lowPrecisionSample
|
|
if err := json.Unmarshal(data, &samples); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(samples) == 0 {
|
|
t.Fatal("empty low precision baseline samples")
|
|
}
|
|
return samples
|
|
}
|
|
|
|
func TestLowPrecisionSunMoonBaselineRegression(t *testing.T) {
|
|
samples := loadLowPrecisionSamples(t)
|
|
|
|
assertBits := func(t *testing.T, name, utc string, got float64, want uint64) {
|
|
t.Helper()
|
|
if math.Float64bits(got) != want {
|
|
t.Fatalf("%s regression at %s", name, utc)
|
|
}
|
|
}
|
|
|
|
for _, sample := range samples {
|
|
jd := sample.TTJD
|
|
|
|
assertBits(t, "planet.SunLo", sample.UTC, planet.SunLo(jd), sample.Sun.LoBits)
|
|
assertBits(t, "basic.SunLo", sample.UTC, basic.SunLo(jd), sample.Sun.LoBits)
|
|
assertBits(t, "planet.SunM", sample.UTC, planet.SunM(jd), sample.Sun.MBits)
|
|
assertBits(t, "basic.SunM", sample.UTC, basic.SunM(jd), sample.Sun.MBits)
|
|
assertBits(t, "planet.Earthe", sample.UTC, planet.Earthe(jd), sample.Sun.EccBits)
|
|
assertBits(t, "basic.Earthe", sample.UTC, basic.Earthe(jd), sample.Sun.EccBits)
|
|
assertBits(t, "planet.EarthPI", sample.UTC, planet.EarthPI(jd), sample.Sun.PeriBits)
|
|
assertBits(t, "basic.EarthPI", sample.UTC, basic.EarthPI(jd), sample.Sun.PeriBits)
|
|
assertBits(t, "planet.SunMidFun", sample.UTC, planet.SunMidFun(jd), sample.Sun.MidBits)
|
|
assertBits(t, "basic.SunMidFun", sample.UTC, basic.SunMidFun(jd), sample.Sun.MidBits)
|
|
assertBits(t, "planet.SunTrueLo", sample.UTC, planet.SunTrueLo(jd), sample.Sun.TrueLoBits)
|
|
assertBits(t, "basic.SunTrueLo", sample.UTC, basic.SunTrueLo(jd), sample.Sun.TrueLoBits)
|
|
assertBits(t, "planet.SunApparentLo", sample.UTC, planet.SunApparentLo(jd), sample.Sun.ApparentLoBits)
|
|
assertBits(t, "basic.SunApparentLo", sample.UTC, basic.SunApparentLo(jd), sample.Sun.ApparentLoBits)
|
|
assertBits(t, "basic.SunApparentRa", sample.UTC, basic.SunApparentRa(jd), sample.Sun.ApparentRaBits)
|
|
assertBits(t, "basic.SunApparentDec", sample.UTC, basic.SunApparentDec(jd), sample.Sun.ApparentDecBits)
|
|
assertBits(t, "basic.SunTrueRa", sample.UTC, basic.SunTrueRa(jd), sample.Sun.TrueRaBits)
|
|
assertBits(t, "basic.SunTrueDec", sample.UTC, basic.SunTrueDec(jd), sample.Sun.TrueDecBits)
|
|
assertBits(t, "planet.Distance", sample.UTC, planet.Distance(jd), sample.Sun.DistanceBits)
|
|
assertBits(t, "basic.Distance", sample.UTC, basic.Distance(jd), sample.Sun.DistanceBits)
|
|
assertBits(t, "planet.MoonLo", sample.UTC, planet.MoonLo(jd), sample.Moon.LoBits)
|
|
assertBits(t, "basic.MoonLo", sample.UTC, basic.MoonLo(jd), sample.Moon.LoBits)
|
|
assertBits(t, "planet.SunMoonAngle", sample.UTC, planet.SunMoonAngle(jd), sample.Moon.SunAngleBits)
|
|
assertBits(t, "basic.SunMoonAngle", sample.UTC, basic.SunMoonAngle(jd), sample.Moon.SunAngleBits)
|
|
assertBits(t, "planet.MoonM", sample.UTC, planet.MoonM(jd), sample.Moon.MBits)
|
|
assertBits(t, "basic.MoonM", sample.UTC, basic.MoonM(jd), sample.Moon.MBits)
|
|
assertBits(t, "planet.MoonLonX", sample.UTC, planet.MoonLonX(jd), sample.Moon.LonXBits)
|
|
assertBits(t, "basic.MoonLonX", sample.UTC, basic.MoonLonX(jd), sample.Moon.LonXBits)
|
|
assertBits(t, "planet.MoonI", sample.UTC, planet.MoonI(jd), sample.Moon.IBits)
|
|
assertBits(t, "basic.MoonI", sample.UTC, basic.MoonI(jd), sample.Moon.IBits)
|
|
assertBits(t, "planet.MoonR", sample.UTC, planet.MoonR(jd), sample.Moon.RBits)
|
|
assertBits(t, "basic.MoonR", sample.UTC, basic.MoonR(jd), sample.Moon.RBits)
|
|
assertBits(t, "planet.MoonB", sample.UTC, planet.MoonB(jd), sample.Moon.BBits)
|
|
assertBits(t, "basic.MoonB", sample.UTC, basic.MoonB(jd), sample.Moon.BBits)
|
|
assertBits(t, "planet.MoonTrueLo", sample.UTC, planet.MoonTrueLo(jd), sample.Moon.TrueLoBits)
|
|
assertBits(t, "basic.MoonTrueLo", sample.UTC, basic.MoonTrueLo(jd), sample.Moon.TrueLoBits)
|
|
assertBits(t, "planet.MoonTrueBo", sample.UTC, planet.MoonTrueBo(jd), sample.Moon.TrueBoBits)
|
|
assertBits(t, "basic.MoonTrueBo", sample.UTC, basic.MoonTrueBo(jd), sample.Moon.TrueBoBits)
|
|
assertBits(t, "planet.MoonAway", sample.UTC, planet.MoonAway(jd), sample.Moon.AwayBits)
|
|
assertBits(t, "basic.MoonAway", sample.UTC, basic.MoonAway(jd), sample.Moon.AwayBits)
|
|
assertBits(t, "basic.MoonApparentLo", sample.UTC, basic.MoonApparentLo(jd), sample.Moon.ApparentLoBits)
|
|
assertBits(t, "basic.MoonTrueRa", sample.UTC, basic.MoonTrueRa(jd), sample.Moon.TrueRaBits)
|
|
assertBits(t, "basic.MoonTrueDec", sample.UTC, basic.MoonTrueDec(jd), sample.Moon.TrueDecBits)
|
|
}
|
|
}
|
|
|
|
func TestDerivedHighPrecisionTruncationFullMatchesDefault(t *testing.T) {
|
|
jd := 2469808.7654321
|
|
lon := 116.391
|
|
lat := 39.907
|
|
tz := 8.0
|
|
|
|
assertSame := func(name string, got, want float64) {
|
|
t.Helper()
|
|
if math.Float64bits(got) != math.Float64bits(want) {
|
|
t.Fatalf("%s full-n mismatch", name)
|
|
}
|
|
}
|
|
assertSamePair := func(name string, got1, got2, want1, want2 float64) {
|
|
t.Helper()
|
|
assertSame(name+".1", got1, want1)
|
|
assertSame(name+".2", got2, want2)
|
|
}
|
|
|
|
assertSame("HSunTrueLo", basic.HSunTrueLo(jd), basic.HSunTrueLoN(jd, -1))
|
|
assertSame("HSunTrueBo", basic.HSunTrueBo(jd), basic.HSunTrueBoN(jd, -1))
|
|
assertSame("HSunApparentLo", basic.HSunApparentLo(jd), basic.HSunApparentLoN(jd, -1))
|
|
assertSame("SunLoGXC", basic.SunLoGXC(jd), basic.SunLoGXCN(jd, -1))
|
|
assertSame("EarthAway", basic.EarthAway(jd), basic.EarthAwayN(jd, -1))
|
|
assertSame("HSunApparentRa", basic.HSunApparentRa(jd), basic.HSunApparentRaN(jd, -1))
|
|
assertSame("HSunTrueRa", basic.HSunTrueRa(jd), basic.HSunTrueRaN(jd, -1))
|
|
assertSame("HSunApparentDec", basic.HSunApparentDec(jd), basic.HSunApparentDecN(jd, -1))
|
|
assertSame("HSunTrueDec", basic.HSunTrueDec(jd), basic.HSunTrueDecN(jd, -1))
|
|
ra1, dec1 := basic.HSunApparentRaDec(jd)
|
|
ra2, dec2 := basic.HSunApparentRaDecN(jd, -1)
|
|
assertSamePair("HSunApparentRaDec", ra1, dec1, ra2, dec2)
|
|
|
|
assertSame("HMoonTrueLo", basic.HMoonTrueLo(jd), basic.HMoonTrueLoN(jd, -1))
|
|
assertSame("HMoonTrueBo", basic.HMoonTrueBo(jd), basic.HMoonTrueBoN(jd, -1))
|
|
assertSame("HMoonAway", basic.HMoonAway(jd), basic.HMoonAwayN(jd, -1))
|
|
assertSame("HMoonApparentLo", basic.HMoonApparentLo(jd), basic.HMoonApparentLoN(jd, -1))
|
|
assertSame("HMoonTrueRa", basic.HMoonTrueRa(jd), basic.HMoonTrueRaN(jd, -1))
|
|
assertSame("HMoonTrueDec", basic.HMoonTrueDec(jd), basic.HMoonTrueDecN(jd, -1))
|
|
ra1, dec1 = basic.HMoonTrueRaDec(jd)
|
|
ra2, dec2 = basic.HMoonTrueRaDecN(jd, -1)
|
|
assertSamePair("HMoonTrueRaDec", ra1, dec1, ra2, dec2)
|
|
ra1, dec1 = basic.HMoonApparentRaDec(jd, lon, lat, tz)
|
|
ra2, dec2 = basic.HMoonApparentRaDecN(jd, lon, lat, tz, -1)
|
|
assertSamePair("HMoonApparentRaDec", ra1, dec1, ra2, dec2)
|
|
assertSame("HMoonApparentRa", basic.HMoonApparentRa(jd, lon, lat, tz), basic.HMoonApparentRaN(jd, lon, lat, tz, -1))
|
|
assertSame("HMoonApparentDec", basic.HMoonApparentDec(jd, lon, lat, tz), basic.HMoonApparentDecN(jd, lon, lat, tz, -1))
|
|
assertSame("HMoonAzimuth", basic.HMoonAzimuth(jd, lon, lat, tz), basic.HMoonAzimuthN(jd, lon, lat, tz, -1))
|
|
assertSame("HMoonHeight", basic.HMoonHeight(jd, lon, lat, tz), basic.HMoonHeightN(jd, lon, lat, tz, -1))
|
|
}
|