1 /* v/time.c
2 **
3 **  This file is in the public domain.
4 */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <fcntl.h>
8 #include <sys/ioctl.h>
9 #include <sys/stat.h>
10 #include <unistd.h>
11 #include <setjmp.h>
12 #include <gmp.h>
13 #include <dirent.h>
14 #include <stdint.h>
15 #include <uv.h>
16 #include <curses.h>
17 #include <termios.h>
18 #include <term.h>
19 
20 #include "all.h"
21 #include "vere/vere.h"
22 
23 /* u3_time_sec_in(): urbit seconds from unix time.
24 **
25 ** Adjust for future leap secs!
26 */
27 c3_d
u3_time_sec_in(c3_w unx_w)28 u3_time_sec_in(c3_w unx_w)
29 {
30   return 0x8000000cce9e0d80ULL + (c3_d)unx_w;
31 }
32 
33 /* u3_time_sec_out(): unix time from urbit seconds.
34 **
35 ** Adjust for future leap secs!
36 */
37 c3_w
u3_time_sec_out(c3_d urs_d)38 u3_time_sec_out(c3_d urs_d)
39 {
40   c3_d adj_d = (urs_d - 0x8000000cce9e0d80ULL);
41 
42   if ( adj_d > 0xffffffffULL ) {
43     fprintf(stderr, "Agh! It's 2106! And no one's fixed this shite!\n");
44     exit(1);
45   }
46   return (c3_w)adj_d;
47 }
48 
49 /* u3_time_fsc_in(): urbit fracto-seconds from unix microseconds.
50 */
51 c3_d
u3_time_fsc_in(c3_w usc_w)52 u3_time_fsc_in(c3_w usc_w)
53 {
54   c3_d usc_d = usc_w;
55 
56   return ((usc_d * 65536ULL) / 1000000ULL) << 48ULL;
57 }
58 
59 /* u3_time_fsc_out: unix microseconds from urbit fracto-seconds.
60 */
61 c3_w
u3_time_fsc_out(c3_d ufc_d)62 u3_time_fsc_out(c3_d ufc_d)
63 {
64   return (c3_w) (((ufc_d >> 48ULL) * 1000000ULL) / 65536ULL);
65 }
66 
67 /* u3_time_msc_out: unix microseconds from urbit fracto-seconds.
68 */
69 c3_w
u3_time_msc_out(c3_d ufc_d)70 u3_time_msc_out(c3_d ufc_d)
71 {
72   return (c3_w) (((ufc_d >> 48ULL) * 1000ULL) / 65536ULL);
73 }
74 
75 /* u3_time_in_tv(): urbit time from struct timeval.
76 */
77 u3_atom
u3_time_in_tv(struct timeval * tim_tv)78 u3_time_in_tv(struct timeval* tim_tv)
79 {
80   c3_w unx_w = tim_tv->tv_sec;
81   c3_w usc_w = tim_tv->tv_usec;
82   c3_d cub_d[2];
83 
84   cub_d[0] = u3_time_fsc_in(usc_w);
85   cub_d[1] = u3_time_sec_in(unx_w);
86 
87   return u3i_chubs(2, cub_d);
88 }
89 
90 /* u3_time_out_tv(): struct timeval from urbit time.
91 */
92 void
u3_time_out_tv(struct timeval * tim_tv,u3_noun now)93 u3_time_out_tv(struct timeval* tim_tv, u3_noun now)
94 {
95   c3_d ufc_d = u3r_chub(0, now);
96   c3_d urs_d = u3r_chub(1, now);
97 
98   tim_tv->tv_sec = u3_time_sec_out(urs_d);
99   tim_tv->tv_usec = u3_time_fsc_out(ufc_d);
100 
101   u3z(now);
102 }
103 
104 /* u3_time_in_ts(): urbit time from struct timespec.
105 */
106 u3_atom
u3_time_in_ts(struct timespec * tim_ts)107 u3_time_in_ts(struct timespec* tim_ts)
108 {
109   struct timeval tim_tv;
110 
111   tim_tv.tv_sec = tim_ts->tv_sec;
112   tim_tv.tv_usec = (tim_ts->tv_nsec / 1000);
113 
114   return u3_time_in_tv(&tim_tv);
115 }
116 
117 #if defined(U3_OS_linux)
118 /* u3_time_t_in_ts(): urbit time from time_t.
119 */
120 u3_atom
u3_time_t_in_ts(time_t tim)121 u3_time_t_in_ts(time_t tim)
122 {
123   struct timeval tim_tv;
124 
125   tim_tv.tv_sec = tim;
126   tim_tv.tv_usec = 0;
127 
128   return u3_time_in_tv(&tim_tv);
129 }
130 #endif // defined(U3_OS_linux)
131 
132 /* u3_time_out_ts(): struct timespec from urbit time.
133 */
134 void
u3_time_out_ts(struct timespec * tim_ts,u3_noun now)135 u3_time_out_ts(struct timespec* tim_ts, u3_noun now)
136 {
137   struct timeval tim_tv;
138 
139   u3_time_out_tv(&tim_tv, now);
140 
141   tim_ts->tv_sec = tim_tv.tv_sec;
142   tim_ts->tv_nsec = (tim_tv.tv_usec * 1000);
143 }
144 
145 /* u3_time_gap_ms(): (wen - now) in ms.
146 */
147 c3_d
u3_time_gap_ms(u3_noun now,u3_noun wen)148 u3_time_gap_ms(u3_noun now, u3_noun wen)
149 {
150   if ( c3n == u3ka_gth(u3k(wen), u3k(now)) ) {
151     u3z(wen); u3z(now);
152     return 0ULL;
153   }
154   else {
155     u3_noun dif   = u3ka_sub(wen, now);
156     c3_d    fsc_d = u3r_chub(0, dif);
157     c3_d    sec_d = u3r_chub(1, dif);
158 
159     u3z(dif);
160     return (sec_d * 1000ULL) + u3_time_msc_out(fsc_d);
161   }
162 }
163 
164 /* u3_time_gap_double(): (wen - now) in libev resolution.
165 */
166 double
u3_time_gap_double(u3_noun now,u3_noun wen)167 u3_time_gap_double(u3_noun now, u3_noun wen)
168 {
169   mpz_t now_mp, wen_mp, dif_mp;
170   double sec_g = (((double)(1ULL << 32ULL)) * ((double)(1ULL << 32ULL)));
171   double gap_g, dif_g;
172 
173   u3r_mp(now_mp, now);
174   u3r_mp(wen_mp, wen);
175   mpz_init(dif_mp);
176   mpz_sub(dif_mp, wen_mp, now_mp);
177 
178   u3z(now);
179   u3z(wen);
180 
181   dif_g = mpz_get_d(dif_mp) / sec_g;
182   gap_g = (dif_g > 0.0) ? dif_g : 0.0;
183   mpz_clear(dif_mp); mpz_clear(wen_mp); mpz_clear(now_mp);
184 
185   return gap_g;
186 }
187