1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <string.h>
19 #include "cbigint.h"
20
21 #define HIGH_IN_U64(u64) ((u64) >> 32)
22 #define LOW_IN_U64(u64) ((u64) & 0x00000000FFFFFFFFLL)
23
24 #define TEN_E1 (0xALL)
25 #define TEN_E2 (0x64LL)
26 #define TEN_E3 (0x3E8LL)
27 #define TEN_E4 (0x2710LL)
28 #define TEN_E5 (0x186A0LL)
29 #define TEN_E6 (0xF4240LL)
30 #define TEN_E7 (0x989680LL)
31 #define TEN_E8 (0x5F5E100LL)
32 #define TEN_E9 (0x3B9ACA00LL)
33 #define TEN_E19 (0x8AC7230489E80000LL)
34
35 #define TIMES_TEN(x) (((x) << 3) + ((x) << 1))
36 #define bitSection(x, mask, shift) (((x) & (mask)) >> (shift))
37 #define CREATE_DOUBLE_BITS(normalizedM, e) (((normalizedM) & MANTISSA_MASK) | ((static_cast<uint64_t>((e) + E_OFFSET)) << 52))
38
39 #define MANTISSA_MASK (0x000FFFFFFFFFFFFFLL)
40 #define EXPONENT_MASK (0x7FF0000000000000LL)
41 #define NORMAL_MASK (0x0010000000000000LL)
42 #define SIGN_MASK (0x8000000000000000LL)
43
44 #define E_OFFSET (1075)
45
46 #define FLOAT_MANTISSA_MASK (0x007FFFFF)
47 #define FLOAT_EXPONENT_MASK (0x7F800000)
48 #define FLOAT_NORMAL_MASK (0x00800000)
49 #define FLOAT_E_OFFSET (150)
50
51 int32_t
simpleAddHighPrecision(uint64_t * arg1,int32_t length,uint64_t arg2)52 simpleAddHighPrecision (uint64_t * arg1, int32_t length, uint64_t arg2)
53 {
54 /* assumes length > 0 */
55 int32_t index = 1;
56
57 *arg1 += arg2;
58 if (arg2 <= *arg1)
59 return 0;
60 else if (length == 1)
61 return 1;
62
63 while (++arg1[index] == 0 && ++index < length) {
64 }
65
66 return index == length;
67 }
68
69 int32_t
addHighPrecision(uint64_t * arg1,int32_t length1,uint64_t * arg2,int32_t length2)70 addHighPrecision (uint64_t * arg1, int32_t length1, uint64_t * arg2, int32_t length2)
71 {
72 /* addition is limited by length of arg1 as it this function is
73 * storing the result in arg1 */
74 /* fix for cc (GCC) 3.2 20020903 (Red Hat Linux 8.0 3.2-7): code generated does not
75 * do the temp1 + temp2 + carry addition correct. carry is 64 bit because gcc has
76 * subtle issues when you mix 64 / 32 bit maths. */
77 uint64_t temp1, temp2, temp3; /* temporary variables to help the SH-4, and gcc */
78 uint64_t carry;
79 int32_t index;
80
81 if (length1 == 0 || length2 == 0)
82 {
83 return 0;
84 }
85 else if (length1 < length2)
86 {
87 length2 = length1;
88 }
89
90 carry = 0;
91 index = 0;
92 do
93 {
94 temp1 = arg1[index];
95 temp2 = arg2[index];
96 temp3 = temp1 + temp2;
97 arg1[index] = temp3 + carry;
98 if (arg2[index] < arg1[index])
99 carry = 0;
100 else if (arg2[index] != arg1[index])
101 carry = 1;
102 }
103 while (++index < length2);
104 if (!carry)
105 return 0;
106 else if (index == length1)
107 return 1;
108
109 while (++arg1[index] == 0 && ++index < length1) {
110 }
111
112 return index == length1;
113 }
114
115 void
subtractHighPrecision(uint64_t * arg1,int32_t length1,uint64_t * arg2,int32_t length2)116 subtractHighPrecision (uint64_t * arg1, int32_t length1, uint64_t * arg2, int32_t length2)
117 {
118 /* assumes arg1 > arg2 */
119 int32_t index;
120 for (index = 0; index < length1; ++index)
121 arg1[index] = ~arg1[index];
122 simpleAddHighPrecision (arg1, length1, 1);
123
124 while (length2 > 0 && arg2[length2 - 1] == 0)
125 --length2;
126
127 addHighPrecision (arg1, length1, arg2, length2);
128
129 for (index = 0; index < length1; ++index)
130 arg1[index] = ~arg1[index];
131 simpleAddHighPrecision (arg1, length1, 1);
132 }
133
simpleMultiplyHighPrecision(uint64_t * arg1,int32_t length,uint64_t arg2)134 static uint32_t simpleMultiplyHighPrecision(uint64_t* arg1, int32_t length, uint64_t arg2) {
135 /* assumes arg2 only holds 32 bits of information */
136 uint64_t product;
137 int32_t index;
138
139 index = 0;
140 product = 0;
141
142 do
143 {
144 product =
145 HIGH_IN_U64 (product) + arg2 * LOW_U32_FROM_PTR (arg1 + index);
146 LOW_U32_FROM_PTR (arg1 + index) = LOW_U32_FROM_VAR (product);
147 product =
148 HIGH_IN_U64 (product) + arg2 * HIGH_U32_FROM_PTR (arg1 + index);
149 HIGH_U32_FROM_PTR (arg1 + index) = LOW_U32_FROM_VAR (product);
150 }
151 while (++index < length);
152
153 return HIGH_U32_FROM_VAR (product);
154 }
155
156 static void
simpleMultiplyAddHighPrecision(uint64_t * arg1,int32_t length,uint64_t arg2,uint32_t * result)157 simpleMultiplyAddHighPrecision (uint64_t * arg1, int32_t length, uint64_t arg2,
158 uint32_t * result)
159 {
160 /* Assumes result can hold the product and arg2 only holds 32 bits
161 of information */
162 uint64_t product;
163 int32_t index, resultIndex;
164
165 index = resultIndex = 0;
166 product = 0;
167
168 do
169 {
170 product =
171 HIGH_IN_U64 (product) + result[resultIndex] +
172 arg2 * LOW_U32_FROM_PTR (arg1 + index);
173 result[resultIndex] = LOW_U32_FROM_VAR (product);
174 ++resultIndex;
175 product =
176 HIGH_IN_U64 (product) + result[resultIndex] +
177 arg2 * HIGH_U32_FROM_PTR (arg1 + index);
178 result[resultIndex] = LOW_U32_FROM_VAR (product);
179 ++resultIndex;
180 }
181 while (++index < length);
182
183 result[resultIndex] += HIGH_U32_FROM_VAR (product);
184 if (result[resultIndex] < HIGH_U32_FROM_VAR (product))
185 {
186 /* must be careful with ++ operator and macro expansion */
187 ++resultIndex;
188 while (++result[resultIndex] == 0)
189 ++resultIndex;
190 }
191 }
192
193 void
multiplyHighPrecision(uint64_t * arg1,int32_t length1,uint64_t * arg2,int32_t length2,uint64_t * result,int32_t length)194 multiplyHighPrecision (uint64_t * arg1, int32_t length1, uint64_t * arg2, int32_t length2,
195 uint64_t * result, int32_t length)
196 {
197 /* assumes result is large enough to hold product */
198 uint64_t* temp;
199 uint32_t* resultIn32;
200 int32_t count, index;
201
202 if (length1 < length2)
203 {
204 temp = arg1;
205 arg1 = arg2;
206 arg2 = temp;
207 count = length1;
208 length1 = length2;
209 length2 = count;
210 }
211
212 memset (result, 0, sizeof (uint64_t) * length);
213
214 /* length1 > length2 */
215 resultIn32 = reinterpret_cast<uint32_t*>(result);
216 index = -1;
217 for (count = 0; count < length2; ++count)
218 {
219 simpleMultiplyAddHighPrecision (arg1, length1, LOW_IN_U64 (arg2[count]),
220 resultIn32 + (++index));
221 simpleMultiplyAddHighPrecision(arg1, length1, HIGH_IN_U64(arg2[count]), resultIn32 + (++index));
222 }
223 }
224
225 uint32_t
simpleAppendDecimalDigitHighPrecision(uint64_t * arg1,int32_t length,uint64_t digit)226 simpleAppendDecimalDigitHighPrecision (uint64_t * arg1, int32_t length, uint64_t digit)
227 {
228 /* assumes digit is less than 32 bits */
229 uint64_t arg;
230 int32_t index = 0;
231
232 digit <<= 32;
233 do
234 {
235 arg = LOW_IN_U64 (arg1[index]);
236 digit = HIGH_IN_U64 (digit) + TIMES_TEN (arg);
237 LOW_U32_FROM_PTR (arg1 + index) = LOW_U32_FROM_VAR (digit);
238
239 arg = HIGH_IN_U64 (arg1[index]);
240 digit = HIGH_IN_U64 (digit) + TIMES_TEN (arg);
241 HIGH_U32_FROM_PTR (arg1 + index) = LOW_U32_FROM_VAR (digit);
242 }
243 while (++index < length);
244
245 return HIGH_U32_FROM_VAR (digit);
246 }
247
248 void
simpleShiftLeftHighPrecision(uint64_t * arg1,int32_t length,int32_t arg2)249 simpleShiftLeftHighPrecision (uint64_t * arg1, int32_t length, int32_t arg2)
250 {
251 /* assumes length > 0 */
252 int32_t index, offset;
253 if (arg2 >= 64)
254 {
255 offset = arg2 >> 6;
256 index = length;
257
258 while (--index - offset >= 0)
259 arg1[index] = arg1[index - offset];
260 do
261 {
262 arg1[index] = 0;
263 }
264 while (--index >= 0);
265
266 arg2 &= 0x3F;
267 }
268
269 if (arg2 == 0)
270 return;
271 while (--length > 0)
272 {
273 arg1[length] = arg1[length] << arg2 | arg1[length - 1] >> (64 - arg2);
274 }
275 *arg1 <<= arg2;
276 }
277
278 int32_t
highestSetBit(uint64_t * y)279 highestSetBit (uint64_t * y)
280 {
281 uint32_t x;
282 int32_t result;
283
284 if (*y == 0)
285 return 0;
286
287 if (*y & 0xFFFFFFFF00000000LL)
288 {
289 x = HIGH_U32_FROM_PTR (y);
290 result = 32;
291 }
292 else
293 {
294 x = LOW_U32_FROM_PTR (y);
295 result = 0;
296 }
297
298 if (x & 0xFFFF0000)
299 {
300 x = bitSection (x, 0xFFFF0000, 16);
301 result += 16;
302 }
303 if (x & 0xFF00)
304 {
305 x = bitSection (x, 0xFF00, 8);
306 result += 8;
307 }
308 if (x & 0xF0)
309 {
310 x = bitSection (x, 0xF0, 4);
311 result += 4;
312 }
313 if (x > 0x7)
314 return result + 4;
315 else if (x > 0x3)
316 return result + 3;
317 else if (x > 0x1)
318 return result + 2;
319 else
320 return result + 1;
321 }
322
323 int32_t
lowestSetBit(uint64_t * y)324 lowestSetBit (uint64_t * y)
325 {
326 uint32_t x;
327 int32_t result;
328
329 if (*y == 0)
330 return 0;
331
332 if (*y & 0x00000000FFFFFFFFLL)
333 {
334 x = LOW_U32_FROM_PTR (y);
335 result = 0;
336 }
337 else
338 {
339 x = HIGH_U32_FROM_PTR (y);
340 result = 32;
341 }
342
343 if (!(x & 0xFFFF))
344 {
345 x = bitSection (x, 0xFFFF0000, 16);
346 result += 16;
347 }
348 if (!(x & 0xFF))
349 {
350 x = bitSection (x, 0xFF00, 8);
351 result += 8;
352 }
353 if (!(x & 0xF))
354 {
355 x = bitSection (x, 0xF0, 4);
356 result += 4;
357 }
358
359 if (x & 0x1)
360 return result + 1;
361 else if (x & 0x2)
362 return result + 2;
363 else if (x & 0x4)
364 return result + 3;
365 else
366 return result + 4;
367 }
368
369 int32_t
highestSetBitHighPrecision(uint64_t * arg,int32_t length)370 highestSetBitHighPrecision (uint64_t * arg, int32_t length)
371 {
372 int32_t highBit;
373
374 while (--length >= 0)
375 {
376 highBit = highestSetBit (arg + length);
377 if (highBit)
378 return highBit + 64 * length;
379 }
380
381 return 0;
382 }
383
384 int32_t
lowestSetBitHighPrecision(uint64_t * arg,int32_t length)385 lowestSetBitHighPrecision (uint64_t * arg, int32_t length)
386 {
387 int32_t lowBit, index = -1;
388
389 while (++index < length)
390 {
391 lowBit = lowestSetBit (arg + index);
392 if (lowBit)
393 return lowBit + 64 * index;
394 }
395
396 return 0;
397 }
398
399 int32_t
compareHighPrecision(uint64_t * arg1,int32_t length1,uint64_t * arg2,int32_t length2)400 compareHighPrecision (uint64_t * arg1, int32_t length1, uint64_t * arg2, int32_t length2)
401 {
402 while (--length1 >= 0 && arg1[length1] == 0) {
403 }
404 while (--length2 >= 0 && arg2[length2] == 0) {
405 }
406
407 if (length1 > length2)
408 return 1;
409 else if (length1 < length2)
410 return -1;
411 else if (length1 > -1)
412 {
413 do
414 {
415 if (arg1[length1] > arg2[length1])
416 return 1;
417 else if (arg1[length1] < arg2[length1])
418 return -1;
419 }
420 while (--length1 >= 0);
421 }
422
423 return 0;
424 }
425
426 jdouble
toDoubleHighPrecision(uint64_t * arg,int32_t length)427 toDoubleHighPrecision (uint64_t * arg, int32_t length)
428 {
429 int32_t highBit;
430 uint64_t mantissa, test64;
431 uint32_t test;
432 jdouble result;
433
434 while (length > 0 && arg[length - 1] == 0)
435 --length;
436
437 if (length == 0)
438 result = 0.0;
439 else if (length > 16)
440 {
441 DOUBLE_TO_LONGBITS (result) = EXPONENT_MASK;
442 }
443 else if (length == 1)
444 {
445 highBit = highestSetBit (arg);
446 if (highBit <= 53)
447 {
448 highBit = 53 - highBit;
449 mantissa = *arg << highBit;
450 DOUBLE_TO_LONGBITS (result) =
451 CREATE_DOUBLE_BITS (mantissa, -highBit);
452 }
453 else
454 {
455 highBit -= 53;
456 mantissa = *arg >> highBit;
457 DOUBLE_TO_LONGBITS (result) =
458 CREATE_DOUBLE_BITS (mantissa, highBit);
459
460 /* perform rounding, round to even in case of tie */
461 test = (LOW_U32_FROM_PTR (arg) << (11 - highBit)) & 0x7FF;
462 if (test > 0x400 || ((test == 0x400) && (mantissa & 1)))
463 DOUBLE_TO_LONGBITS (result) = DOUBLE_TO_LONGBITS (result) + 1;
464 }
465 }
466 else
467 {
468 highBit = highestSetBit (arg + (--length));
469 if (highBit <= 53)
470 {
471 highBit = 53 - highBit;
472 if (highBit > 0)
473 {
474 mantissa =
475 (arg[length] << highBit) | (arg[length - 1] >>
476 (64 - highBit));
477 }
478 else
479 {
480 mantissa = arg[length];
481 }
482 DOUBLE_TO_LONGBITS (result) =
483 CREATE_DOUBLE_BITS (mantissa, length * 64 - highBit);
484
485 /* perform rounding, round to even in case of tie */
486 test64 = arg[--length] << highBit;
487 if (test64 > SIGN_MASK || ((test64 == SIGN_MASK) && (mantissa & 1)))
488 DOUBLE_TO_LONGBITS (result) = DOUBLE_TO_LONGBITS (result) + 1;
489 else if (test64 == SIGN_MASK)
490 {
491 while (--length >= 0)
492 {
493 if (arg[length] != 0)
494 {
495 DOUBLE_TO_LONGBITS (result) =
496 DOUBLE_TO_LONGBITS (result) + 1;
497 break;
498 }
499 }
500 }
501 }
502 else
503 {
504 highBit -= 53;
505 mantissa = arg[length] >> highBit;
506 DOUBLE_TO_LONGBITS (result) =
507 CREATE_DOUBLE_BITS (mantissa, length * 64 + highBit);
508
509 /* perform rounding, round to even in case of tie */
510 test = (LOW_U32_FROM_PTR (arg + length) << (11 - highBit)) & 0x7FF;
511 if (test > 0x400 || ((test == 0x400) && (mantissa & 1)))
512 DOUBLE_TO_LONGBITS (result) = DOUBLE_TO_LONGBITS (result) + 1;
513 else if (test == 0x400)
514 {
515 do
516 {
517 if (arg[--length] != 0)
518 {
519 DOUBLE_TO_LONGBITS (result) =
520 DOUBLE_TO_LONGBITS (result) + 1;
521 break;
522 }
523 }
524 while (length > 0);
525 }
526 }
527 }
528
529 return result;
530 }
531
532 static uint64_t simpleMultiplyHighPrecision64(uint64_t* arg1, int32_t length, uint64_t arg2);
533
534 int32_t
timesTenToTheEHighPrecision(uint64_t * result,int32_t length,jint e)535 timesTenToTheEHighPrecision (uint64_t * result, int32_t length, jint e)
536 {
537 /* assumes result can hold value */
538 uint64_t overflow;
539 int exp10 = e;
540
541 if (e == 0)
542 return length;
543
544 /* bad O(n) way of doing it, but simple */
545 /*
546 do {
547 overflow = simpleAppendDecimalDigitHighPrecision(result, length, 0);
548 if (overflow)
549 result[length++] = overflow;
550 } while (--e);
551 */
552 /* Replace the current implementaion which performs a
553 * "multiplication" by 10 e number of times with an actual
554 * multiplication. 10e19 is the largest exponent to the power of ten
555 * that will fit in a 64-bit integer, and 10e9 is the largest exponent to
556 * the power of ten that will fit in a 64-bit integer. Not sure where the
557 * break-even point is between an actual multiplication and a
558 * simpleAappendDecimalDigit() so just pick 10e3 as that point for
559 * now.
560 */
561 while (exp10 >= 19)
562 {
563 overflow = simpleMultiplyHighPrecision64 (result, length, TEN_E19);
564 if (overflow)
565 result[length++] = overflow;
566 exp10 -= 19;
567 }
568 while (exp10 >= 9)
569 {
570 overflow = simpleMultiplyHighPrecision (result, length, TEN_E9);
571 if (overflow)
572 result[length++] = overflow;
573 exp10 -= 9;
574 }
575 if (exp10 == 0)
576 return length;
577 else if (exp10 == 1)
578 {
579 overflow = simpleAppendDecimalDigitHighPrecision (result, length, 0);
580 if (overflow)
581 result[length++] = overflow;
582 }
583 else if (exp10 == 2)
584 {
585 overflow = simpleAppendDecimalDigitHighPrecision (result, length, 0);
586 if (overflow)
587 result[length++] = overflow;
588 overflow = simpleAppendDecimalDigitHighPrecision (result, length, 0);
589 if (overflow)
590 result[length++] = overflow;
591 }
592 else if (exp10 == 3)
593 {
594 overflow = simpleMultiplyHighPrecision (result, length, TEN_E3);
595 if (overflow)
596 result[length++] = overflow;
597 }
598 else if (exp10 == 4)
599 {
600 overflow = simpleMultiplyHighPrecision (result, length, TEN_E4);
601 if (overflow)
602 result[length++] = overflow;
603 }
604 else if (exp10 == 5)
605 {
606 overflow = simpleMultiplyHighPrecision (result, length, TEN_E5);
607 if (overflow)
608 result[length++] = overflow;
609 }
610 else if (exp10 == 6)
611 {
612 overflow = simpleMultiplyHighPrecision (result, length, TEN_E6);
613 if (overflow)
614 result[length++] = overflow;
615 }
616 else if (exp10 == 7)
617 {
618 overflow = simpleMultiplyHighPrecision (result, length, TEN_E7);
619 if (overflow)
620 result[length++] = overflow;
621 }
622 else if (exp10 == 8)
623 {
624 overflow = simpleMultiplyHighPrecision (result, length, TEN_E8);
625 if (overflow)
626 result[length++] = overflow;
627 }
628 return length;
629 }
630
631 uint64_t
doubleMantissa(jdouble z)632 doubleMantissa (jdouble z)
633 {
634 uint64_t m = DOUBLE_TO_LONGBITS (z);
635
636 if ((m & EXPONENT_MASK) != 0)
637 m = (m & MANTISSA_MASK) | NORMAL_MASK;
638 else
639 m = (m & MANTISSA_MASK);
640
641 return m;
642 }
643
644 int32_t
doubleExponent(jdouble z)645 doubleExponent (jdouble z)
646 {
647 /* assumes positive double */
648 int32_t k = HIGH_U32_FROM_VAR (z) >> 20;
649
650 if (k)
651 k -= E_OFFSET;
652 else
653 k = 1 - E_OFFSET;
654
655 return k;
656 }
657
floatMantissa(jfloat z)658 uint32_t floatMantissa(jfloat z) {
659 uint32_t m = FLOAT_TO_INTBITS (z);
660
661 if ((m & FLOAT_EXPONENT_MASK) != 0)
662 m = (m & FLOAT_MANTISSA_MASK) | FLOAT_NORMAL_MASK;
663 else
664 m = (m & FLOAT_MANTISSA_MASK);
665
666 return m;
667 }
668
669 int32_t
floatExponent(jfloat z)670 floatExponent (jfloat z)
671 {
672 /* assumes positive float */
673 int32_t k = FLOAT_TO_INTBITS (z) >> 23;
674 if (k)
675 k -= FLOAT_E_OFFSET;
676 else
677 k = 1 - FLOAT_E_OFFSET;
678
679 return k;
680 }
681
682 /* Allow a 64-bit value in arg2 */
683 uint64_t
simpleMultiplyHighPrecision64(uint64_t * arg1,int32_t length,uint64_t arg2)684 simpleMultiplyHighPrecision64 (uint64_t * arg1, int32_t length, uint64_t arg2)
685 {
686 uint64_t intermediate, carry1, carry2, prod1, prod2, sum;
687 uint64_t* pArg1;
688 int32_t index;
689 uint32_t buf32;
690
691 index = 0;
692 intermediate = 0;
693 pArg1 = arg1 + index;
694 carry1 = carry2 = 0;
695
696 do
697 {
698 if ((*pArg1 != 0) || (intermediate != 0))
699 {
700 prod1 =
701 static_cast<uint64_t>(LOW_U32_FROM_VAR (arg2)) * static_cast<uint64_t>(LOW_U32_FROM_PTR (pArg1));
702 sum = intermediate + prod1;
703 if ((sum < prod1) || (sum < intermediate))
704 {
705 carry1 = 1;
706 }
707 else
708 {
709 carry1 = 0;
710 }
711 prod1 =
712 static_cast<uint64_t>(LOW_U32_FROM_VAR (arg2)) * static_cast<uint64_t>(HIGH_U32_FROM_PTR (pArg1));
713 prod2 =
714 static_cast<uint64_t>(HIGH_U32_FROM_VAR (arg2)) * static_cast<uint64_t>(LOW_U32_FROM_PTR (pArg1));
715 intermediate = carry2 + HIGH_IN_U64 (sum) + prod1 + prod2;
716 if ((intermediate < prod1) || (intermediate < prod2))
717 {
718 carry2 = 1;
719 }
720 else
721 {
722 carry2 = 0;
723 }
724 LOW_U32_FROM_PTR (pArg1) = LOW_U32_FROM_VAR (sum);
725 buf32 = HIGH_U32_FROM_PTR (pArg1);
726 HIGH_U32_FROM_PTR (pArg1) = LOW_U32_FROM_VAR (intermediate);
727 intermediate = carry1 + HIGH_IN_U64 (intermediate)
728 + static_cast<uint64_t>(HIGH_U32_FROM_VAR (arg2)) * static_cast<uint64_t>(buf32);
729 }
730 pArg1++;
731 }
732 while (++index < length);
733 return intermediate;
734 }
735