avr-libc-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-libc-commit] [2369] Augmented the comments on several functions.


From: Mike Rice
Subject: [avr-libc-commit] [2369] Augmented the comments on several functions.
Date: Sun, 28 Apr 2013 14:19:39 +0000

Revision: 2369
          http://svn.sv.gnu.org/viewvc/?view=rev&root=avr-libc&revision=2369
Author:   swfltek
Date:     2013-04-28 14:19:35 +0000 (Sun, 28 Apr 2013)
Log Message:
-----------
Augmented the comments on several functions. Hopefully the algorithms employed 
will be clear.

Modified Paths:
--------------
    trunk/avr-libc/libc/time/daylight_seconds.c
    trunk/avr-libc/libc/time/equation_of_time.c
    trunk/avr-libc/libc/time/gm_sidereal.c
    trunk/avr-libc/libc/time/gmtime_r.c
    trunk/avr-libc/libc/time/iso_weeknum.c
    trunk/avr-libc/libc/time/mk_gmtime.c
    trunk/avr-libc/libc/time/solar_declination.c

Modified: trunk/avr-libc/libc/time/daylight_seconds.c
===================================================================
--- trunk/avr-libc/libc/time/daylight_seconds.c 2013-04-27 15:49:22 UTC (rev 
2368)
+++ trunk/avr-libc/libc/time/daylight_seconds.c 2013-04-28 14:19:35 UTC (rev 
2369)
@@ -29,8 +29,9 @@
 /* $Id$ */
 
 /*
-    Determine the amount of time the sun is above the horizon. At high 
latitudes, this can be zero,
-    or >= ONE_DAY.
+    Determine the amount of time the sun is above the horizon. At high 
latitudes, around the
+    solstices, this can be zero or greater than ONE_DAY.
+
 */
 
 #include <time.h>
@@ -49,17 +50,20 @@
 
     d = -solar_declination(timer);
 
+    /* partial 'Sunrise Equation' */
     d = tan(l) * tan(d);
 
-    /* d may exceed a magnitude of 1.0 at high latitudes */
+    /* magnitude of d may exceed 1.0 at near solstices */
     if (d > 1.0)
         d = 1.0;
 
     if (d < -1.0)
         d = -1.0;
 
+    /* derive hour angle */
     d = acos(d);
 
+    /* but for atmospheric refraction, this would be d /= M_PI */
     d /= 3.112505;
 
     n = ONE_DAY * d;

Modified: trunk/avr-libc/libc/time/equation_of_time.c
===================================================================
--- trunk/avr-libc/libc/time/equation_of_time.c 2013-04-27 15:49:22 UTC (rev 
2368)
+++ trunk/avr-libc/libc/time/equation_of_time.c 2013-04-28 14:19:35 UTC (rev 
2369)
@@ -31,6 +31,19 @@
 /*
     The so called Equation of Time.
 
+    The eccentricity of Earths orbit contributes about 7.7 minutes of 
variation to the result. It
+    has a period of 1 anomalous year, with zeroes at perihelion and aphelion.
+
+    The tilt of Earths rotational axis (obliquity) contributes about 9.9 
minutes of variation. It
+    has a period of 1/2 tropical year, with zeroes at solstices and equinoxes. 
The time of Earths
+    arrival at these events is influenced by the eccentricity, which causes it 
to progress along its
+    orbital path faster as it approaches perihelion, imposing a 'modulation' 
on the tropical phase.
+
+    The algorithm employed computes the orbital position with respect to 
perihelion, deriving
+    from that a 'velocity correction factor'. The orbital position with 
respect to the winter solstice
+    is then computed, as modulated by that factor. The individual 
contributions of the obliquity and the
+    eccentricity components are then summed, and returned as an integer value 
in seconds.
+
 */
 
 #include <time.h>
@@ -58,14 +71,15 @@
     s += SOLSTICE;
     s *= 2;
     sf = s;
+    sf /= TROP_CYCLE;
 
-    sf /= TROP_CYCLE;
+    /* modulate to derive actual position */
     sf += dV;
+    sf = sin(sf);
 
-    sf = sin(sf);
+    /* compute contributions */
+    sf *= 592.2;
     pf *= 459.6;
-    sf *= 592.2;
-
     s = pf + sf;
     return -s;
 

Modified: trunk/avr-libc/libc/time/gm_sidereal.c
===================================================================
--- trunk/avr-libc/libc/time/gm_sidereal.c      2013-04-27 15:49:22 UTC (rev 
2368)
+++ trunk/avr-libc/libc/time/gm_sidereal.c      2013-04-28 14:19:35 UTC (rev 
2369)
@@ -29,9 +29,17 @@
 /* $Id$ */
 
 /*
-    Greenwich Mean Sidereal Time. The ratio of sidereal to civil seconds is
-    1.00273790935ss / 1.0cs , which when shifted left to fill 32 bits becomes
-    0x8059B740.
+    Greenwich Mean Sidereal Time. A sidereal second is somewhat shorter than a 
standard second,
+    about 1.002737909350795 sidereal seconds per standard second.
+
+    We resort to fixed point math due to the insufficient resolution of a 
'double', using...
+
+        timestamp * ( 1.002737909350795 << 31 )
+        --------------------------------------- + Te
+                        1 << 31
+
+    Where Te is the sidereal time at the epoch.
+
 */
 
 #include <time.h>
@@ -40,20 +48,13 @@
 unsigned long
 gm_sidereal(const time_t * timer)
 {
-    uint64_t tmp;
+    uint64_t        tmp;
 
     tmp = *timer;
-
-    /* multiply by 1.00273790935 sidereal seconds */
     tmp *= 0x8059B740;
+    tmp /= 0x80000000;
+    tmp += (uint64_t) 23991;
 
-    /* divide by 1.0 civil second */
-    tmp >>= 31;
-
-    /* add sidereal time at epoch */
-    tmp += (uint64_t)23991;
-
     tmp %= ONE_DAY;
     return tmp;
 }
-

Modified: trunk/avr-libc/libc/time/gmtime_r.c
===================================================================
--- trunk/avr-libc/libc/time/gmtime_r.c 2013-04-27 15:49:22 UTC (rev 2368)
+++ trunk/avr-libc/libc/time/gmtime_r.c 2013-04-28 14:19:35 UTC (rev 2369)
@@ -28,9 +28,7 @@
 
 /* $Id$ */
 
-/*
-    Re entrant version of gmtime(), this function 'breaks down' a Y2K time 
stamp .
-*/
+/* Re entrant version of gmtime(). */
 
 #include <time.h>
 #include <stdlib.h>
@@ -39,88 +37,108 @@
 void
 gmtime_r(const time_t * timer, struct tm * timeptr)
 {
-       int32_t         fract;
-       ldiv_t          lresult;
-       div_t           result;
-       uint16_t        days, n, leapyear, years;
+    int32_t         fract;
+    ldiv_t          lresult;
+    div_t           result;
+    uint16_t        days, n, leapyear, years;
 
-       /* break down timer into whole and fractional parts of 1 day */
-       days = *timer / 86400UL;
-       fract = *timer % 86400UL;
+    /* break down timer into whole and fractional parts of 1 day */
+    days = *timer / 86400UL;
+    fract = *timer % 86400UL;
 
-       /* Determine day of week ( the epoch was a Saturday ) */
-       n = days + SATURDAY;
-       n %= 7;
-       timeptr->tm_wday = n;
+    /*
+            Extract hour, minute, and second from the fractional day
+        */
+    lresult = ldiv(fract, 60L);
+    timeptr->tm_sec = lresult.rem;
+    result = div(lresult.quot, 60);
+    timeptr->tm_min = result.rem;
+    timeptr->tm_hour = result.quot;
 
-       /* map our place into the 100 year and 4 year leap cycles. */
-       lresult = ldiv((long) days, 36525L);
-       years = 100 * lresult.quot;
-       lresult = ldiv(lresult.rem, 1461L);
-       years += 4 * lresult.quot;
-       days = lresult.rem;
-       if (years > 100)
-               days++;
+    /* Determine day of week ( the epoch was a Saturday ) */
+    n = days + SATURDAY;
+    n %= 7;
+    timeptr->tm_wday = n;
 
-       /*
-         * 'years' is now at a 4 year boundary
-         * 'days' is an index into the current 1461 day leap cycle
-         * If 'years' != 100, this cycle begins with a 366 day year.
+    /*
+        * Our epoch year has the property of being at the conjunction of all 
three 'leap cycles',
+        * 4, 100, and 400 years ( though we can ignore the 400 year cycle in 
this library).
+        *
+        * Using this property, we can easily 'map' the time stamp into the 
leap cycles, quickly
+        * deriving the year and day of year, along with the fact of whether it 
is a leap year.
+        */
+
+    /* map into a 100 year cycle */
+    lresult = ldiv((long) days, 36525L);
+    years = 100 * lresult.quot;
+
+    /* map into a 4 year cycle */
+    lresult = ldiv(lresult.rem, 1461L);
+    years += 4 * lresult.quot;
+    days = lresult.rem;
+    if (years > 100)
+        days++;
+
+    /*
+         * 'years' is now at the first year of a 4 year leap cycle, which will 
always be a leap year,
+         * unless it is 100. 'days' is now an index into that cycle.
          */
-       leapyear = 1;
-       if (years == 100)
-               leapyear = 0;
+    leapyear = 1;
+    if (years == 100)
+        leapyear = 0;
 
-       n = 364 + leapyear;
+    /* compute length, in days, of first year of this cycle */
+    n = 364 + leapyear;
 
-       /*
-            Given the length of the first year of this cycle,
-            we can proceed to break down year and day of year.
-        */
-       if (days > n) {
-               days -= leapyear;
-               leapyear = 0;
-               result = div(days, 365);
-               years += result.quot;
-               days = result.rem;
-       }
-       timeptr->tm_year = 100 + years;
-       timeptr->tm_yday = days;
+    /*
+     * if the number of days remaining is greater than the length of the
+     * first year, we make one more division.
+     */
+    if (days > n) {
+        days -= leapyear;
+        leapyear = 0;
+        result = div(days, 365);
+        years += result.quot;
+        days = result.rem;
+    }
+    timeptr->tm_year = 100 + years;
+    timeptr->tm_yday = days;
 
-       /*
+    /*
             Given the year, day of year, and leap year indicator, we can break 
down the
-            month and day of month.
+            month and day of month. If the day of year is less than 59 (or 60 
if a leap year), then
+            we handle the Jan/Feb month pair as an exception.
         */
-       n = 59 + leapyear;
+    n = 59 + leapyear;
+    if (days < n) {
+        /* special case: Jan/Feb month pair */
+        result = div(days, 31);
+        timeptr->tm_mon = result.quot;
+        timeptr->tm_mday = result.rem;
+    } else {
+        /*
+            The remaining 10 months form a regular pattern of 31 day months 
alternating with 30 day
+            months, with a 'phase change' between July and August (153 days 
after March 1).
+            We proceed by mapping our position into either March-July or 
August-December.
+            */
+        days -= n;
+        result = div(days, 153);
+        timeptr->tm_mon = 2 + result.quot * 5;
 
-       if (days < n) {
-               result = div(days, 31);
-               timeptr->tm_mon = result.quot;
-               timeptr->tm_mday = result.rem;
-       } else {
-               days -= n;
-               result = div(days, 153);
-               timeptr->tm_mon = 2 + result.quot * 5;
-               result = div(result.rem, 61);
-               timeptr->tm_mon += result.quot * 2;
-               result = div(result.rem, 31);
-               timeptr->tm_mon += result.quot;
-               timeptr->tm_mday = result.rem;
-       }
+        /* map into a 61 day pair of months */
+        result = div(result.rem, 61);
+        timeptr->tm_mon += result.quot * 2;
 
-       /*
-            Break down hour, minute, and second from the fractional day
-        */
-       lresult = ldiv(fract, 60L);
-       timeptr->tm_sec = lresult.rem;
-       result = div(lresult.quot, 60);
-       timeptr->tm_min = result.rem;
-       timeptr->tm_hour = result.quot;
+        /* map into a month */
+        result = div(result.rem, 31);
+        timeptr->tm_mon += result.quot;
+        timeptr->tm_mday = result.rem;
+    }
 
-       /*
+    /*
             Cleanup and return
         */
-       timeptr->tm_isdst = 0;  /* gmt is never in DST */
-       timeptr->tm_mday++;     /* tm_mday is 1 based */
+    timeptr->tm_isdst = 0;  /* gmt is never in DST */
+    timeptr->tm_mday++; /* tm_mday is 1 based */
 
 }

Modified: trunk/avr-libc/libc/time/iso_weeknum.c
===================================================================
--- trunk/avr-libc/libc/time/iso_weeknum.c      2013-04-27 15:49:22 UTC (rev 
2368)
+++ trunk/avr-libc/libc/time/iso_weeknum.c      2013-04-28 14:19:35 UTC (rev 
2369)
@@ -28,27 +28,40 @@
 
 /* $Id$ */
 
-/* Compute the ISO 8601 week number of the year. */
+/*
+    Compute the ISO 8601 week number of the year.
+    We return 0 if the week is the final one of the previous year.
+    We return 54 if the week is the first week of the following year.
+    Otherwise we return week numbers 1 to 53
+*/
 
 #include <time.h>
 
 uint8_t
 iso_weeknum(const struct tm * timestruct)
 {
-       int             d, w;
+    int             d, w;
 
-       d = timestruct->tm_wday;
-       if (d == 0)
-               d = 7;
-       w = timestruct->tm_yday + 11 - d;
-       w /= 7;
-       if (w == 53) {
-               /* week 53 must include its thursday in the same year */
-               d = timestruct->tm_mday - 1;
-               d -= timestruct->tm_wday;
-               d += THURSDAY;
-               if (d > 30)
-                       w++;    /* signal first week of the following year */
-       }
-       return w;
+    /* convert to a MONDAY based week */
+    d = timestruct->tm_wday;
+    if (d == 0)
+        d = 7;
+
+    /* compute tentative ISO 8601 week number */
+    w = timestruct->tm_yday + 11 - d;
+    w /= 7;
+
+    /*
+     * handle the special case where week 53 may actually be week 1 of
+     * the following year
+     */
+    if (w == 53) {
+        /* week 53 must include its thursday in the same year */
+        d = timestruct->tm_mday - 1;
+        d -= timestruct->tm_wday;
+        d += THURSDAY;
+        if (d > 30)
+            w++;    /* signal first week of the following year */
+    }
+    return w;
 }

Modified: trunk/avr-libc/libc/time/mk_gmtime.c
===================================================================
--- trunk/avr-libc/libc/time/mk_gmtime.c        2013-04-27 15:49:22 UTC (rev 
2368)
+++ trunk/avr-libc/libc/time/mk_gmtime.c        2013-04-28 14:19:35 UTC (rev 
2369)
@@ -31,6 +31,7 @@
 /*
     'Break down' a y2k time stamp into the elements of struct tm.
     Unlike mktime(), this function does not 'normalize' the elements of 
timeptr.
+
 */
 
 #include <time.h>
@@ -44,7 +45,8 @@
     int             n, m, d, leaps;
 
     /*
-            Determine elapsed whole days, since Y2K, to the beginning of the 
year
+        Determine elapsed whole days since the epoch to the beginning of this 
year. Since our epoch is
+        at a conjunction of the leap cycles, we can do this rather quickly.
         */
     n = timeptr->tm_year - 100;
     leaps = 0;
@@ -57,10 +59,13 @@
     tmp = 365UL * n + leaps;
 
     /*
-            Derive the day of year from month and day of month
-        */
+                Derive the day of year from month and day of month. We use the 
pattern of 31 day months
+                followed by 30 day months to our advantage, but we must 
'special case' Jan/Feb, and
+                account for a 'phase change' between July and August (153 days 
after March 1).
+            */
     d = timeptr->tm_mday - 1;   /* tm_mday is one based */
 
+    /* handle Jan/Feb as a special case */
     if (timeptr->tm_mon < 2) {
         if (timeptr->tm_mon)
             d += 31;
@@ -68,19 +73,26 @@
     } else {
         n = 59 + is_leap_year(timeptr->tm_year + 1900);
         d += n;
+        n = timeptr->tm_mon - MARCH;
 
-        /* Other months exhibit a regular pattern */
-        n = timeptr->tm_mon - 2;
-        if (n > 4)
+        /* account for phase change */
+        if (n > (JULY - MARCH))
             d += 153;
+        n %= 5;
 
-        n %= 5;
+        /*
+         * n is now an index into a group of alternating 31 and 30
+         * day months... 61 day pairs.
+         */
         m = n / 2;
         m *= 61;
         d += m;
 
-        n &= 1;
-        if (n)
+        /*
+         * if n is odd, we are in the second half of the
+         * month pair
+         */
+        if (n & 1)
             d += 31;
     }
 
@@ -94,6 +106,7 @@
     tmp *= ONE_HOUR;
     tmp += timeptr->tm_min * 60UL;
     tmp += timeptr->tm_sec;
+
     ret += tmp;
 
     return ret;

Modified: trunk/avr-libc/libc/time/solar_declination.c
===================================================================
--- trunk/avr-libc/libc/time/solar_declination.c        2013-04-27 15:49:22 UTC 
(rev 2368)
+++ trunk/avr-libc/libc/time/solar_declination.c        2013-04-28 14:19:35 UTC 
(rev 2369)
@@ -28,6 +28,18 @@
 
 /* $Id$ */
 
+/*
+    Were it not for the eccentricity of Earths orbit, this would be a trivial 
function.
+
+    We compute the Earths orbital position with respect to perihelion, from 
which we derive a
+    'velocity correction factor'. We then compute the orbital angle with 
respect to the
+    December solstice, as 'modulated' by that correction factor.
+
+    Due to the accumulation of rounding errors, the computed December solstice 
of 2135 will lag
+    the actual solstice by many hours. A fudge factor, 'LAG', distributes the 
error across
+    the 136 year range of this library.
+*/
+
 #include <time.h>
 #include <math.h>
 #include "ephemera_common.h"
@@ -41,28 +53,25 @@
     uint32_t        fT, oV;
     double          dV, dT;
 
-    /*
-     * Determine approximate orbital angle, relative to the winter
-     * solstice
-     */
-    fT = *timer % TROP_YEAR;
-    fT += SOLSTICE;
-    fT += LAG;
-    dT = fT;
-    dT /= TROP_CYCLE;
-
-    /* Determine approximate orbital angle, relative to perihelion */
+    /* Determine orbital angle relative to perihelion of January 1999 */
     oV = *timer % ANOM_YEAR;
     oV += PERIHELION;
     dV = oV;
     dV /= ANOM_CYCLE;
 
-    /* Derive a velocity correction factor from the perihelion angle */
+    /* Derive velocity correction factor from the perihelion angle */
     dV = sin(dV);
     dV *= DELTA_V;
 
-    /* compute declination */
-    dT = cos(dT + dV) * INCLINATION;
+    /* Determine orbital angle relative to solstice of December 1999 */
+    fT = *timer % TROP_YEAR;
+    fT += SOLSTICE + LAG;
+    dT = fT;
+    dT /= TROP_CYCLE;
+    dT += dV;
 
+    /* Finally having the solstice angle, we can compute the declination */
+    dT = cos(dT) * INCLINATION;
+
     return -dT;
 }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]