Host C Specs


Directory: src/c/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 10 / 0 / 10
Functions: 100.0% 3 / 0 / 3
Branches: 100.0% 4 / 0 / 4

core/clock/tide.c
Line Branch Exec Source
1 /**
2 * @file tide.c
3 * @brief The rise and fall of a semidiurnal tide, from a plain running minute count.
4 *
5 * @ingroup lib_core
6 */
7 #include "clock/tide.h"
8
9 /// The cycle's length cubed, which the smoothstep divides by
10 #define TIDE_PERIOD_CUBE ((int64_t)TIDE_PERIOD_MIN * TIDE_PERIOD_MIN * TIDE_PERIOD_MIN)
11
12 /**
13 * @brief Where in the cycle a minute count lands.
14 *
15 * C truncates a negative division towards zero, which leaves a negative remainder, so this
16 * pulls it back up by hand.
17 *
18 * @param minutes A running minute count, on the same base as tide_level.
19 * @return The phase within the cycle, 0 to TIDE_PERIOD_MIN - 1.
20 */
21 2998 static int32_t phase(int32_t minutes)
22 {
23 2998 int32_t within = minutes % TIDE_PERIOD_MIN;
24
25
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 2997 times.
2998 return within < 0 ? within + TIDE_PERIOD_MIN : within;
26 }
27
28 2996 int tide_level(int32_t minutes)
29 {
30 // twice the phase, folded back at the turn, so it climbs from 0 to the period over the first
31 // half of the cycle and comes back down over the second
32 2996 int32_t twice = phase(minutes) * 2;
33
2/2
✓ Branch 0 taken 1493 times.
✓ Branch 1 taken 1503 times.
2996 int32_t climb = twice < TIDE_PERIOD_MIN ? twice : 2 * TIDE_PERIOD_MIN - twice;
34
35 // the smoothstep curve 3t^2-2t^3 of climb over the period, scaled to 0..100. it flattens both
36 // turns and steepens the middle
37 // it is worked out in one go with one rounding at the end, so the level moves at most one point
38 // a minute and low and high water last about as long as each other
39 // the product on top runs past 40 billion, so it is worked in 64 bits
40 2996 int64_t top = (int64_t)100 * climb * climb * (3 * TIDE_PERIOD_MIN - 2 * climb);
41
42 2996 return (int)((top + TIDE_PERIOD_CUBE / 2) / TIDE_PERIOD_CUBE);
43 }
44
45 2 bool tide_rising(int32_t minutes)
46 {
47 2 return phase(minutes) * 2 < TIDE_PERIOD_MIN;
48 }
49