Menu

#23 ln_lunar_next_phase() pathological behaviour

v1.0_(example)
open
nobody
None
5
2022-03-25
2022-03-25
Rob Norris
No

I've been using the latest source code - since ln_lunar_next_phase() was added after the v0.16 release.

I found that for various dates, my program in looking for the next full moon would either be very slow, give strange dates, or even nonsensical dates. I traced this into the behaviour of the function ln_find_zero() as used by ln_lunar_next_phase(). Since the ln_find_zero() function doesn't protect itself as it uses a variable division term - so in particular when '(f - func(x, arg))' becomes small then x2 becomes very large, causing ln_lunar_next_phase() to sometimes return NAN.

I tried improving the ln_find_zero() function but did not find a robust solution. Ultimately I gave up and found it was simply better if ln_lunar_next_phase() did not bother using ln_find_zero() at all.

Possibly if one was concerned about the initial calculation giving a time in the past, then simply adding 29.530588861 should be sufficient.

I note the lntest/test.c doesn't exercise ln_lunar_next_phase(); so I brute forced it to run various dates over the next 20 years (for full moons). For the original function, found that for various dates it returned either obviously wrong answers (e.g way beyond +/- 29.5 days) or NANs.

//struct ln_date ld2022 = { 2022, 1, 22, 0, 0, 0.0 };
//2022-12-10 --> 2022-12-24 is giving 2022-12-25 when it should be around 2023-01-07

struct ln_date ld = { 2041, 1, 17, 7, 11, 0.0 };
/* Initial result = "2041-02-01 10:58:00" */
 /* Actual answer should be around "2041-01-20" */

// IIRC these failed badly
 //JD = 2459977.0; // 2023-02-01
 //JD = 2462533.0; // 2030-02-01
 //JD = 2462563.0; // 2030-03-02

Similarly the ln_lunar_previous_phase() can go badly wrong to.

Discussion


Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.