2 * vint64ops.c - operations on 'vint64' values
4 * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project.
5 * The contents of 'html/copyright.html' apply.
6 * ----------------------------------------------------------------------
7 * This is an attempt to get the vint64 calculations stuff centralised.
16 #include "ntp_types.h"
18 #include "vint64ops.h"
20 /* ---------------------------------------------------------------------
21 * GCC is rather sticky with its 'const' attribute. We have to do it more
22 * explicit than with a cast if we want to get rid of a CONST qualifier.
23 * Greetings from the PASCAL world, where casting was only possible via
39 /* -------------------------------------------------------------------------*/
54 src = (const u_char*)begp;
61 } else if (*src == '+') {
69 if (toupper(*++src) == 'X') {
74 } else if (base == 16) { /* remove optional leading '0x' or '0X' */
75 if (src[0] == '0' && toupper(src[1]) == 'X')
77 } else if (base <= 2 || base > 36) {
78 memset(&res, 0xFF, sizeof(res));
83 memset(&res, 0, sizeof(res));
87 else if (isupper(*src))
88 digit = *src - 'A' + 10;
89 else if (islower(*src))
90 digit = *src - 'a' + 10;
96 #if defined(HAVE_INT64)
97 res.Q_s = res.Q_s * base + digit;
99 /* res *= base, using 16x16->32 bit
100 * multiplication. Slow but portable.
104 accu = (uint32_t)res.W_s.ll * base;
105 res.W_s.ll = (uint16_t)accu;
107 + (uint32_t)res.W_s.lh * base;
108 res.W_s.lh = (uint16_t)accu;
109 /* the upper bits can be done in one step: */
110 res.D_s.hi = res.D_s.hi * base + (accu >> 16);
112 M_ADD(res.D_s.hi, res.D_s.lo, 0, digit);
119 *endp = (char*)noconst(src);
121 M_NEG(res.D_s.hi, res.D_s.lo);
125 /* -------------------------------------------------------------------------*/
135 #if defined(HAVE_INT64)
136 res = (lhs->q_s > rhs->q_s)
137 - (lhs->q_s < rhs->q_s);
139 res = (lhs->d_s.hi > rhs->d_s.hi)
140 - (lhs->d_s.hi < rhs->d_s.hi);
142 res = (lhs->D_s.lo > rhs->D_s.lo)
143 - (lhs->D_s.lo < rhs->D_s.lo);
149 /* -------------------------------------------------------------------------*/
159 #if defined(HAVE_INT64)
160 res = (lhs->Q_s > rhs->Q_s)
161 - (lhs->Q_s < rhs->Q_s);
163 res = (lhs->D_s.hi > rhs->D_s.hi)
164 - (lhs->D_s.hi < rhs->D_s.hi);
166 res = (lhs->D_s.lo > rhs->D_s.lo)
167 - (lhs->D_s.lo < rhs->D_s.lo);
172 /* -------------------------------------------------------------------------*/
182 #if defined(HAVE_INT64)
183 res.Q_s = lhs->Q_s + rhs->Q_s;
186 M_ADD(res.D_s.hi, res.D_s.lo, rhs->D_s.hi, rhs->D_s.lo);
191 /* -------------------------------------------------------------------------*/
201 #if defined(HAVE_INT64)
202 res.Q_s = lhs->Q_s - rhs->Q_s;
205 M_SUB(res.D_s.hi, res.D_s.lo, rhs->D_s.hi, rhs->D_s.lo);
210 /* -------------------------------------------------------------------------*/
221 #if defined(HAVE_INT64)
224 M_ADD(res.D_s.hi, res.D_s.lo, -(rhs < 0), rhs);
229 /* -------------------------------------------------------------------------*/
240 #if defined(HAVE_INT64)
243 M_SUB(res.D_s.hi, res.D_s.lo, -(rhs < 0), rhs);
248 /* -------------------------------------------------------------------------*/
259 #if defined(HAVE_INT64)
262 M_ADD(res.D_s.hi, res.D_s.lo, 0, rhs);
267 /* -------------------------------------------------------------------------*/
278 #if defined(HAVE_INT64)
281 M_SUB(res.D_s.hi, res.D_s.lo, 0, rhs);