purify
C++ Purify implementation with native circuit and BPP support
Loading...
Searching...
No Matches
uint_impl.h
Go to the documentation of this file.
1// Copyright (c) 2026 Judica, Inc.
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or https://opensource.org/license/mit/.
4
5#ifndef PURIFY_UINT_FN
6#error "PURIFY_UINT_FN must be defined before including uint_impl.h"
7#endif
8
9#ifndef PURIFY_UINT_WORDS
10#error "PURIFY_UINT_WORDS must be defined before including uint_impl.h"
11#endif
12
13int PURIFY_UINT_FN(try_add_small)(uint64_t value[PURIFY_UINT_WORDS], uint32_t addend);
14int PURIFY_UINT_FN(try_mul_small)(uint64_t value[PURIFY_UINT_WORDS], uint32_t factor);
15
17 size_t i;
18 for (i = 0; i < PURIFY_UINT_WORDS; ++i) {
19 out[i] = 0;
20 }
21}
22
23void PURIFY_UINT_FN(set_u64)(uint64_t out[PURIFY_UINT_WORDS], uint64_t value) {
25 out[0] = value;
26}
27
28void PURIFY_UINT_FN(from_bytes_be)(uint64_t out[PURIFY_UINT_WORDS], const unsigned char* data, size_t size) {
29 size_t i;
31 for (i = 0; i < size; ++i) {
32 int ok = PURIFY_UINT_FN(try_mul_small)(out, 256);
33 ok = ok && PURIFY_UINT_FN(try_add_small)(out, data[i]);
34 assert(ok != 0);
35 }
36}
37
38int PURIFY_UINT_FN(is_zero)(const uint64_t value[PURIFY_UINT_WORDS]) {
39 size_t i;
40 for (i = 0; i < PURIFY_UINT_WORDS; ++i) {
41 if (value[i] != 0) {
42 return 0;
43 }
44 }
45 return 1;
46}
47
48int PURIFY_UINT_FN(compare)(const uint64_t lhs[PURIFY_UINT_WORDS], const uint64_t rhs[PURIFY_UINT_WORDS]) {
49 size_t i;
50 for (i = PURIFY_UINT_WORDS; i != 0; --i) {
51 size_t idx = i - 1u;
52 if (lhs[idx] < rhs[idx]) {
53 return -1;
54 }
55 if (lhs[idx] > rhs[idx]) {
56 return 1;
57 }
58 }
59 return 0;
60}
61
62int PURIFY_UINT_FN(try_add_small)(uint64_t value[PURIFY_UINT_WORDS], uint32_t addend) {
63 uint64_t carry = addend;
64 size_t i;
65 for (i = 0; i < PURIFY_UINT_WORDS && carry != 0; ++i) {
66 uint64_t sum = value[i] + carry;
67 carry = sum < value[i] ? 1u : 0u;
68 value[i] = sum;
69 }
70 return carry == 0;
71}
72
73int PURIFY_UINT_FN(try_mul_small)(uint64_t value[PURIFY_UINT_WORDS], uint32_t factor) {
74 uint64_t carry = 0;
75 size_t i;
76 for (i = 0; i < PURIFY_UINT_WORDS; ++i) {
77 uint64_t hi = 0;
78 uint64_t lo = purify_uint_mul_u64(value[i], factor, &hi);
79 lo = purify_uint_add_u64_carry(lo, carry, &hi);
80 value[i] = lo;
81 carry = hi;
82 }
83 return carry == 0;
84}
85
86int PURIFY_UINT_FN(try_add)(uint64_t value[PURIFY_UINT_WORDS], const uint64_t addend[PURIFY_UINT_WORDS]) {
87 uint64_t carry = 0;
88 size_t i;
89 for (i = 0; i < PURIFY_UINT_WORDS; ++i) {
90 uint64_t sum = value[i] + addend[i];
91 uint64_t carry1 = sum < value[i] ? 1u : 0u;
92 uint64_t next = sum + carry;
93 uint64_t carry2 = next < sum ? 1u : 0u;
94 value[i] = next;
95 carry = carry1 | carry2;
96 }
97 return carry == 0;
98}
99
100int PURIFY_UINT_FN(try_sub)(uint64_t value[PURIFY_UINT_WORDS], const uint64_t subtrahend[PURIFY_UINT_WORDS]) {
101 uint64_t borrow = 0;
102 size_t i;
103 for (i = 0; i < PURIFY_UINT_WORDS; ++i) {
104 uint64_t rhs = subtrahend[i] + borrow;
105 uint64_t rhs_overflow = rhs < subtrahend[i] ? 1u : 0u;
106 uint64_t next = value[i] - rhs;
107 uint64_t needs_borrow = value[i] < rhs ? 1u : 0u;
108 value[i] = next;
109 borrow = rhs_overflow | needs_borrow;
110 }
111 return borrow == 0;
112}
113
114size_t PURIFY_UINT_FN(bit_length)(const uint64_t value[PURIFY_UINT_WORDS]) {
115 size_t i;
116 for (i = PURIFY_UINT_WORDS; i != 0; --i) {
117 size_t idx = i - 1u;
118 if (value[idx] != 0) {
119 return idx * 64u + purify_uint_bit_length_u64(value[idx]);
120 }
121 }
122 return 0;
123}
124
125int PURIFY_UINT_FN(bit)(const uint64_t value[PURIFY_UINT_WORDS], size_t index) {
126 size_t word = index / 64u;
127 size_t shift = index % 64u;
128 if (word >= PURIFY_UINT_WORDS) {
129 return 0;
130 }
131 return ((value[word] >> shift) & 1u) != 0;
132}
133
134int PURIFY_UINT_FN(try_set_bit)(uint64_t value[PURIFY_UINT_WORDS], size_t index) {
135 size_t word = index / 64u;
136 size_t shift = index % 64u;
137 if (word >= PURIFY_UINT_WORDS) {
138 return 0;
139 }
140 value[word] |= ((uint64_t)1u << shift);
141 return 1;
142}
143
144void PURIFY_UINT_FN(shifted_left)(uint64_t out[PURIFY_UINT_WORDS], const uint64_t value[PURIFY_UINT_WORDS], size_t bits) {
145 size_t word_shift = bits / 64u;
146 size_t bit_shift = bits % 64u;
147 size_t i;
149 for (i = PURIFY_UINT_WORDS; i != 0; --i) {
150 size_t src;
151 size_t idx = i - 1u;
152 if (idx < word_shift) {
153 continue;
154 }
155 src = idx - word_shift;
156 out[idx] |= value[src] << bit_shift;
157 if (bit_shift != 0 && src > 0) {
158 out[idx] |= value[src - 1] >> (64u - bit_shift);
159 }
160 }
161}
162
163void PURIFY_UINT_FN(shifted_right)(uint64_t out[PURIFY_UINT_WORDS], const uint64_t value[PURIFY_UINT_WORDS], size_t bits) {
164 size_t word_shift = bits / 64u;
165 size_t bit_shift = bits % 64u;
166 size_t i;
168 for (i = 0; i < PURIFY_UINT_WORDS; ++i) {
169 size_t src = i + word_shift;
170 if (src >= PURIFY_UINT_WORDS) {
171 break;
172 }
173 out[i] |= value[src] >> bit_shift;
174 if (bit_shift != 0 && src + 1 < PURIFY_UINT_WORDS) {
175 out[i] |= value[src + 1] << (64u - bit_shift);
176 }
177 }
178}
179
181 size_t i;
182 for (i = 0; i < PURIFY_UINT_WORDS; ++i) {
183 uint64_t next = i + 1 < PURIFY_UINT_WORDS ? value[i + 1] : 0;
184 value[i] = (value[i] >> 1) | (next << 63);
185 }
186}
187
188void PURIFY_UINT_FN(mask_bits)(uint64_t value[PURIFY_UINT_WORDS], size_t bits) {
189 const size_t total_bits = PURIFY_UINT_WORDS * 64u;
190 const size_t full_words = bits / 64u;
191 const size_t extra_bits = bits % 64u;
192 size_t i;
193 if (bits >= total_bits) {
194 return;
195 }
196 for (i = full_words + (extra_bits != 0 ? 1u : 0u); i < PURIFY_UINT_WORDS; ++i) {
197 value[i] = 0;
198 }
199 if (extra_bits != 0 && full_words < PURIFY_UINT_WORDS) {
200 uint64_t mask = ((uint64_t)1u << extra_bits) - 1u;
201 value[full_words] &= mask;
202 }
203}
204
205uint32_t PURIFY_UINT_FN(divmod_small)(uint64_t value[PURIFY_UINT_WORDS], uint32_t divisor) {
206 uint64_t rem = 0;
207 size_t i;
208 assert(divisor != 0);
209 for (i = PURIFY_UINT_WORDS; i != 0; --i) {
210 size_t idx = i - 1u;
211 uint32_t next_rem = 0;
212 uint64_t quotient = purify_uint_divmod_u32(rem, value[idx], divisor, &next_rem);
213 value[idx] = quotient;
214 rem = next_rem;
215 }
216 return (uint32_t)rem;
217}
218
219void PURIFY_UINT_FN(to_bytes_be)(unsigned char out[PURIFY_UINT_WORDS * 8], const uint64_t value[PURIFY_UINT_WORDS]) {
220 size_t i;
221 for (i = 0; i < PURIFY_UINT_WORDS; ++i) {
222 uint64_t limb = value[i];
223 size_t j;
224 for (j = 0; j < 8u; ++j) {
225 out[PURIFY_UINT_WORDS * 8u - 1u - (i * 8u + j)] = (unsigned char)(limb & 0xffu);
226 limb >>= 8;
227 }
228 }
229}
static size_t purify_uint_bit_length_u64(uint64_t value)
Definition uint.c:17
#define PURIFY_UINT_FN(name)
Definition uint.c:147
static uint64_t purify_uint_add_u64_carry(uint64_t value, uint64_t addend, uint64_t *hi)
Definition uint.c:54
static uint64_t purify_uint_divmod_u32(uint64_t hi, uint64_t lo, uint32_t divisor, uint32_t *rem_out)
Definition uint.c:110
static uint64_t purify_uint_mul_u64(uint64_t lhs, uint64_t rhs, uint64_t *hi)
Definition uint.c:33
#define PURIFY_UINT_WORDS
Definition uint.c:148
int PURIFY_UINT_FN() try_sub(uint64_t value[PURIFY_UINT_WORDS], const uint64_t subtrahend[PURIFY_UINT_WORDS])
Definition uint_impl.h:100
void PURIFY_UINT_FN() mask_bits(uint64_t value[PURIFY_UINT_WORDS], size_t bits)
Definition uint_impl.h:188
void PURIFY_UINT_FN() set_u64(uint64_t out[PURIFY_UINT_WORDS], uint64_t value)
Definition uint_impl.h:23
int PURIFY_UINT_FN() compare(const uint64_t lhs[PURIFY_UINT_WORDS], const uint64_t rhs[PURIFY_UINT_WORDS])
Definition uint_impl.h:48
void PURIFY_UINT_FN() shift_right_one(uint64_t value[PURIFY_UINT_WORDS])
Definition uint_impl.h:180
void PURIFY_UINT_FN() to_bytes_be(unsigned char out[PURIFY_UINT_WORDS *8], const uint64_t value[PURIFY_UINT_WORDS])
Definition uint_impl.h:219
int PURIFY_UINT_FN() try_mul_small(uint64_t value[PURIFY_UINT_WORDS], uint32_t factor)
Definition uint_impl.h:73
int PURIFY_UINT_FN() try_add_small(uint64_t value[PURIFY_UINT_WORDS], uint32_t addend)
Definition uint_impl.h:62
int PURIFY_UINT_FN() try_set_bit(uint64_t value[PURIFY_UINT_WORDS], size_t index)
Definition uint_impl.h:134
void PURIFY_UINT_FN() from_bytes_be(uint64_t out[PURIFY_UINT_WORDS], const unsigned char *data, size_t size)
Definition uint_impl.h:28
void PURIFY_UINT_FN() shifted_right(uint64_t out[PURIFY_UINT_WORDS], const uint64_t value[PURIFY_UINT_WORDS], size_t bits)
Definition uint_impl.h:163
int PURIFY_UINT_FN() try_add(uint64_t value[PURIFY_UINT_WORDS], const uint64_t addend[PURIFY_UINT_WORDS])
Definition uint_impl.h:86
uint32_t PURIFY_UINT_FN() divmod_small(uint64_t value[PURIFY_UINT_WORDS], uint32_t divisor)
Definition uint_impl.h:205
void PURIFY_UINT_FN() set_zero(uint64_t out[PURIFY_UINT_WORDS])
Definition uint_impl.h:16
int PURIFY_UINT_FN() is_zero(const uint64_t value[PURIFY_UINT_WORDS])
Definition uint_impl.h:38
int PURIFY_UINT_FN() bit(const uint64_t value[PURIFY_UINT_WORDS], size_t index)
Definition uint_impl.h:125
void PURIFY_UINT_FN() shifted_left(uint64_t out[PURIFY_UINT_WORDS], const uint64_t value[PURIFY_UINT_WORDS], size_t bits)
Definition uint_impl.h:144
size_t PURIFY_UINT_FN() bit_length(const uint64_t value[PURIFY_UINT_WORDS])
Definition uint_impl.h:114