Longfellow ZK 0290cb32
Loading...
Searching...
No Matches
limb.h
1// Copyright 2025 Google LLC.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef PRIVACY_PROOFS_ZK_LIB_ALGEBRA_LIMB_H_
16#define PRIVACY_PROOFS_ZK_LIB_ALGEBRA_LIMB_H_
17
18#include <array>
19#include <cstddef>
20#include <cstdint>
21
22#include "util/serialization.h"
23
24namespace proofs {
25
26// Base class for representing bignum or bigpoly as arrays of
27// machine-dependent "limbs". The serialization is in this
28// class; arithmetic is in subclasses.
29
30template <size_t W64>
31class Limb {
32 public:
33 using T = Limb<W64>;
34
35#if __WORDSIZE == 64
36 using limb_t = uint64_t;
37#else
38 using limb_t = uint32_t;
39#endif
40
41 // sizes in bytes, bits, limbs, uint64_t
42 static constexpr size_t kBytes = 8 * W64;
43 static constexpr size_t kBits = 64 * W64;
44 static constexpr size_t kLimbs = kBytes / sizeof(limb_t);
45 static constexpr size_t kU64 = W64;
46 static constexpr size_t kBitsPerLimb = 8 * sizeof(limb_t);
47
48 // no rounding allowed
49 static_assert(kLimbs * sizeof(limb_t) == kBytes);
50
51 limb_t limb_[kLimbs];
52
53 Limb() = default; // uninitialized
54 explicit Limb(uint64_t x) : limb_{} { assign(limb_, 1, &x); }
55
56 explicit Limb(const std::array<uint64_t, kU64>& a) : limb_{} {
57 assign(limb_, kU64, &a[0]);
58 }
59
60 std::array<uint64_t, kU64> u64() const {
61 std::array<uint64_t, kU64> a;
62 unassign(limb_, kU64, &a[0]);
63 return a;
64 }
65
66 void to_bytes(uint8_t a[/* kBytes */]) const {
67 for (size_t i = 0; i < kLimbs; ++i) {
68 a = to_bytes(&limb_[i], a);
69 }
70 }
71
72 bool operator==(const T& other) const {
73 for (size_t i = 0; i < kLimbs; ++i) {
74 if (limb_[i] != other.limb_[i]) {
75 return false;
76 }
77 }
78 return true;
79 }
80 bool operator!=(const T& other) const { return !(operator==(other)); }
81
82 // Shift right by z. Return the bits that fall off
83 // the edge.
84 limb_t shiftr(size_t z) {
85 limb_t c = 0;
86 for (size_t i = kLimbs; i-- > 0;) {
87 limb_t d = limb_[i];
88 limb_[i] = c | (d >> z);
89 c = d << (kBitsPerLimb - z);
90 }
91 return c;
92 }
93
94 // Returns the pos-th bit in the representation of this nat.
95 limb_t bit(size_t pos) const {
96 size_t ind = pos / kBitsPerLimb;
97 if (ind < kLimbs) {
98 size_t off = pos % kBitsPerLimb;
99 return (limb_[ind] >> off) & 0x1u;
100 }
101 return 0;
102 }
103
104 protected:
105 static void assign(uint64_t d[], size_t ns, const uint64_t s[/*ns*/]) {
106 for (size_t i = 0; i < ns; ++i) {
107 d[i] = s[i];
108 }
109 }
110
111 static void assign(uint32_t d[], size_t ns, const uint64_t s[/*ns*/]) {
112 for (size_t i = 0; i < ns; ++i) {
113 d[2 * i] = static_cast<uint32_t>(s[i]);
114 d[2 * i + 1] = static_cast<uint32_t>(s[i] >> 32);
115 }
116 }
117
118 static void unassign(const uint64_t d[], size_t ns, uint64_t s[/*ns*/]) {
119 for (size_t i = 0; i < ns; ++i) {
120 s[i] = d[i];
121 }
122 }
123
124 static void unassign(const uint32_t d[], size_t ns, uint64_t s[/*ns*/]) {
125 for (size_t i = 0; i < ns; ++i) {
126 s[i] = d[2 * i] | (static_cast<uint64_t>(d[2 * i + 1]) << 32);
127 }
128 }
129
130 static const uint8_t* of_bytes(uint64_t* r, const uint8_t* a) {
131 *r = u64_of_le(a);
132 return a + 8;
133 }
134 static const uint8_t* of_bytes(uint32_t* r, const uint8_t* a) {
135 *r = u32_of_le(a);
136 return a + 4;
137 }
138
139 static uint8_t* to_bytes(const uint64_t* r, uint8_t* a) {
140 u64_to_le(a, *r);
141 return a + 8;
142 }
143 static uint8_t* to_bytes(const uint32_t* r, uint8_t* a) {
144 u32_to_le(a, *r);
145 return a + 4;
146 }
147};
148} // namespace proofs
149
150#endif // PRIVACY_PROOFS_ZK_LIB_ALGEBRA_LIMB_H_