1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright © 2018 Intel Corporation
3*61046927SAndroid Build Coastguard Worker *
4*61046927SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker *
11*61046927SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker * Software.
14*61046927SAndroid Build Coastguard Worker *
15*61046927SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*61046927SAndroid Build Coastguard Worker * IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker */
23*61046927SAndroid Build Coastguard Worker
24*61046927SAndroid Build Coastguard Worker #ifndef UTIL_BIGMATH_H
25*61046927SAndroid Build Coastguard Worker #define UTIL_BIGMATH_H
26*61046927SAndroid Build Coastguard Worker
27*61046927SAndroid Build Coastguard Worker #include "macros.h"
28*61046927SAndroid Build Coastguard Worker
29*61046927SAndroid Build Coastguard Worker #include <assert.h>
30*61046927SAndroid Build Coastguard Worker #include <stdint.h>
31*61046927SAndroid Build Coastguard Worker #include <string.h>
32*61046927SAndroid Build Coastguard Worker
33*61046927SAndroid Build Coastguard Worker static inline bool
_ubm_add_u32arr(uint32_t * dst,unsigned dst_len,uint32_t * a,unsigned a_len,uint32_t * b,unsigned b_len)34*61046927SAndroid Build Coastguard Worker _ubm_add_u32arr(uint32_t *dst, unsigned dst_len,
35*61046927SAndroid Build Coastguard Worker uint32_t *a, unsigned a_len,
36*61046927SAndroid Build Coastguard Worker uint32_t *b, unsigned b_len)
37*61046927SAndroid Build Coastguard Worker {
38*61046927SAndroid Build Coastguard Worker uint32_t carry = 0;
39*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < dst_len; i++) {
40*61046927SAndroid Build Coastguard Worker uint64_t sum = carry;
41*61046927SAndroid Build Coastguard Worker if (i < a_len)
42*61046927SAndroid Build Coastguard Worker sum += a[i];
43*61046927SAndroid Build Coastguard Worker if (i < b_len)
44*61046927SAndroid Build Coastguard Worker sum += b[i];
45*61046927SAndroid Build Coastguard Worker dst[i] = sum;
46*61046927SAndroid Build Coastguard Worker carry = sum >> 32;
47*61046927SAndroid Build Coastguard Worker }
48*61046927SAndroid Build Coastguard Worker
49*61046927SAndroid Build Coastguard Worker /* Now compute overflow */
50*61046927SAndroid Build Coastguard Worker
51*61046927SAndroid Build Coastguard Worker for (unsigned i = dst_len; i < a_len; i++) {
52*61046927SAndroid Build Coastguard Worker if (a[i])
53*61046927SAndroid Build Coastguard Worker return true;
54*61046927SAndroid Build Coastguard Worker }
55*61046927SAndroid Build Coastguard Worker
56*61046927SAndroid Build Coastguard Worker for (unsigned i = dst_len; i < b_len; i++) {
57*61046927SAndroid Build Coastguard Worker if (b[i])
58*61046927SAndroid Build Coastguard Worker return true;
59*61046927SAndroid Build Coastguard Worker }
60*61046927SAndroid Build Coastguard Worker
61*61046927SAndroid Build Coastguard Worker return carry;
62*61046927SAndroid Build Coastguard Worker }
63*61046927SAndroid Build Coastguard Worker #define ubm_add_u32arr(dst, a, b) \
64*61046927SAndroid Build Coastguard Worker _ubm_add_u32arr(dst, ARRAY_SIZE(dst), a, ARRAY_SIZE(a), b, ARRAY_SIZE(b))
65*61046927SAndroid Build Coastguard Worker
66*61046927SAndroid Build Coastguard Worker static inline bool
_ubm_mul_u32arr(uint32_t * dst,unsigned dst_len,uint32_t * a,unsigned a_len,uint32_t * b,unsigned b_len)67*61046927SAndroid Build Coastguard Worker _ubm_mul_u32arr(uint32_t *dst, unsigned dst_len,
68*61046927SAndroid Build Coastguard Worker uint32_t *a, unsigned a_len,
69*61046927SAndroid Build Coastguard Worker uint32_t *b, unsigned b_len)
70*61046927SAndroid Build Coastguard Worker {
71*61046927SAndroid Build Coastguard Worker memset(dst, 0, dst_len * sizeof(*dst));
72*61046927SAndroid Build Coastguard Worker
73*61046927SAndroid Build Coastguard Worker bool overflow = false;
74*61046927SAndroid Build Coastguard Worker
75*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < a_len; i++) {
76*61046927SAndroid Build Coastguard Worker uint32_t carry = 0;
77*61046927SAndroid Build Coastguard Worker for (unsigned j = 0; j < b_len; j++) {
78*61046927SAndroid Build Coastguard Worker /* The maximum values of a[i] and b[i] are UINT32_MAX so the maximum
79*61046927SAndroid Build Coastguard Worker * value of tmp is UINT32_MAX * UINT32_MAX. The maximum value that
80*61046927SAndroid Build Coastguard Worker * will fit in tmp is
81*61046927SAndroid Build Coastguard Worker *
82*61046927SAndroid Build Coastguard Worker * UINT64_MAX = UINT32_MAX << 32 + UINT32_MAX
83*61046927SAndroid Build Coastguard Worker * = UINT32_MAX * (UINT32_MAX + 1) + UINT32_MAX
84*61046927SAndroid Build Coastguard Worker * = UINT32_MAX * UINT32_MAX + 2 * UINT32_MAX
85*61046927SAndroid Build Coastguard Worker *
86*61046927SAndroid Build Coastguard Worker * so we're guaranteed that we can add in two more 32-bit values
87*61046927SAndroid Build Coastguard Worker * without overflowing tmp.
88*61046927SAndroid Build Coastguard Worker */
89*61046927SAndroid Build Coastguard Worker uint64_t tmp = (uint64_t)a[i] * (uint64_t)b[j];
90*61046927SAndroid Build Coastguard Worker tmp += carry;
91*61046927SAndroid Build Coastguard Worker if (i + j < dst_len) {
92*61046927SAndroid Build Coastguard Worker tmp += dst[i + j];
93*61046927SAndroid Build Coastguard Worker dst[i + j] = tmp;
94*61046927SAndroid Build Coastguard Worker carry = tmp >> 32;
95*61046927SAndroid Build Coastguard Worker } else {
96*61046927SAndroid Build Coastguard Worker /* We're trying to write a value that doesn't fit */
97*61046927SAndroid Build Coastguard Worker overflow = overflow || tmp > 0;
98*61046927SAndroid Build Coastguard Worker break;
99*61046927SAndroid Build Coastguard Worker }
100*61046927SAndroid Build Coastguard Worker }
101*61046927SAndroid Build Coastguard Worker if (i + b_len < dst_len)
102*61046927SAndroid Build Coastguard Worker dst[i + b_len] = carry;
103*61046927SAndroid Build Coastguard Worker else
104*61046927SAndroid Build Coastguard Worker overflow = overflow || carry > 0;
105*61046927SAndroid Build Coastguard Worker }
106*61046927SAndroid Build Coastguard Worker
107*61046927SAndroid Build Coastguard Worker return overflow;
108*61046927SAndroid Build Coastguard Worker }
109*61046927SAndroid Build Coastguard Worker #define ubm_mul_u32arr(dst, a, b) \
110*61046927SAndroid Build Coastguard Worker _ubm_mul_u32arr(dst, ARRAY_SIZE(dst), a, ARRAY_SIZE(a), b, ARRAY_SIZE(b))
111*61046927SAndroid Build Coastguard Worker
112*61046927SAndroid Build Coastguard Worker #endif /* UTIL_BIGMATH_H */
113