xref: /aosp_15_r20/external/mesa3d/src/util/bigmath.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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