LLZK 3.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
Intervals.h
Go to the documentation of this file.
1//===-- Intervals.h ---------------------------------------------*- C++ -*-===//
2//
3// Part of the LLZK Project, under the Apache License v2.0.
4// See LICENSE.txt for license information.
5// Copyright 2025 Veridise Inc.
6// SPDX-License-Identifier: Apache-2.0
7//
8//===----------------------------------------------------------------------===//
9
10#pragma once
11
12#include "llzk/Util/Field.h"
13
14#include <mlir/Support/LogicalResult.h>
15
16#include <algorithm>
17
18namespace llzk {
19
20/* UnreducedInterval */
21
22class Interval;
23
27public:
28 UnreducedInterval(const llvm::DynamicAPInt &x, const llvm::DynamicAPInt &y) : a(x), b(y) {}
30 UnreducedInterval(int64_t x, int64_t y) : a(x), b(y) {}
31
32 /* Operations */
33
37 Interval reduce(const Field &field) const;
38
43
48
58
68
78
88
93
94 /* Comparisons */
95
96 bool overlaps(const UnreducedInterval &rhs) const;
97
98 friend std::strong_ordering
99 operator<=>(const UnreducedInterval &lhs, const UnreducedInterval &rhs);
100
101 friend bool operator==(const UnreducedInterval &lhs, const UnreducedInterval &rhs) {
102 return std::is_eq(lhs <=> rhs);
103 };
104
105 /* Utility for hashing unreduced intervals */
106 struct Hash {
107 unsigned operator()(const UnreducedInterval &ui) const {
108 return llvm::hash_value(ui.a) ^ llvm::hash_value(ui.b);
109 }
110 };
111
112 llvm::DynamicAPInt getLHS() const { return a; }
113 llvm::DynamicAPInt getRHS() const { return b; }
114
117 llvm::DynamicAPInt width() const;
118
120 inline bool isEmpty() const { return width() == 0; }
121
122 bool isNotEmpty() const { return !isEmpty(); }
123
124 void print(llvm::raw_ostream &os) const { os << "Unreduced:[ " << a << ", " << b << " ]"; }
125
126 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const UnreducedInterval &ui) {
127 ui.print(os);
128 return os;
129 }
130
131private:
132 llvm::DynamicAPInt a, b;
133};
134
135/* Interval */
136
207class Interval {
208public:
209 enum class Type : std::uint8_t { TypeA = 0, TypeB, TypeC, TypeF, Empty, Degenerate, Entire };
210 static constexpr std::array<std::string_view, 7> TypeNames = {"TypeA", "TypeB", "TypeC",
211 "TypeF", "Empty", "Degenerate",
212 "Entire"};
213
214 static std::string_view TypeName(Type t) { return TypeNames.at(static_cast<size_t>(t)); }
215
216 /* Static constructors for convenience */
217
218 static Interval Empty(const Field &f) { return Interval(Type::Empty, f); }
219
220 static Interval Degenerate(const Field &f, const llvm::DynamicAPInt &val) {
221 return Interval(Type::Degenerate, f, val, val);
222 }
223
224 static Interval False(const Field &f) { return Interval::Degenerate(f, f.zero()); }
225
226 static Interval True(const Field &f) { return Interval::Degenerate(f, f.one()); }
227
228 static Interval Boolean(const Field &f) { return Interval::TypeA(f, f.zero(), f.one()); }
229
230 static Interval Entire(const Field &f) { return Interval(Type::Entire, f); }
231
232 static Interval TypeA(const Field &f, const llvm::DynamicAPInt &a, const llvm::DynamicAPInt &b) {
233 return Interval(Type::TypeA, f, a, b);
234 }
235
236 static Interval TypeB(const Field &f, const llvm::DynamicAPInt &a, const llvm::DynamicAPInt &b) {
237 return Interval(Type::TypeB, f, a, b);
238 }
239
240 static Interval TypeC(const Field &f, const llvm::DynamicAPInt &a, const llvm::DynamicAPInt &b) {
241 return Interval(Type::TypeC, f, a, b);
242 }
243
244 static Interval TypeF(const Field &f, const llvm::DynamicAPInt &a, const llvm::DynamicAPInt &b) {
245 return Interval(Type::TypeF, f, a, b);
246 }
247
251
254
258
262
263 template <std::pair<Type, Type>... Pairs>
264 static bool areOneOf(const Interval &a, const Interval &b) {
265 return ((a.ty == std::get<0>(Pairs) && b.ty == std::get<1>(Pairs)) || ...);
266 }
267
269 Interval join(const Interval &rhs) const;
270
272 Interval intersect(const Interval &rhs) const;
273
287 Interval difference(const Interval &other) const;
288
289 /* arithmetic ops */
290
291 Interval operator-() const;
292 Interval operator~() const;
293 friend Interval operator+(const Interval &lhs, const Interval &rhs);
294 friend Interval operator-(const Interval &lhs, const Interval &rhs);
295 friend Interval operator*(const Interval &lhs, const Interval &rhs);
296 friend Interval operator%(const Interval &lhs, const Interval &rhs);
297 friend Interval operator&(const Interval &lhs, const Interval &rhs);
300 friend Interval operator|(const Interval &lhs, const Interval &rhs);
303 friend Interval operator^(const Interval &lhs, const Interval &rhs);
304 friend Interval operator<<(const Interval &lhs, const Interval &rhs);
305 friend Interval operator>>(const Interval &lhs, const Interval &rhs);
306
307 /* boolean ops */
308 friend Interval boolAnd(const Interval &lhs, const Interval &rhs);
309 friend Interval boolOr(const Interval &lhs, const Interval &rhs);
310 friend Interval boolXor(const Interval &lhs, const Interval &rhs);
311 friend Interval boolNot(const Interval &iv);
312
313 /* Checks and Comparisons */
314
315 inline bool isEmpty() const { return ty == Type::Empty; }
316 inline bool isNotEmpty() const { return !isEmpty(); }
317 inline bool isDegenerate() const { return ty == Type::Degenerate; }
318 inline bool isEntire() const { return ty == Type::Entire; }
319 inline bool isTypeA() const { return ty == Type::TypeA; }
320 inline bool isTypeB() const { return ty == Type::TypeB; }
321 inline bool isTypeC() const { return ty == Type::TypeC; }
322 inline bool isTypeF() const { return ty == Type::TypeF; }
323
324 inline bool isBoolFalse() const { return *this == Interval::False(field.get()); }
325 inline bool isBoolTrue() const { return *this == Interval::True(field.get()); }
326 inline bool isBoolEither() const { return *this == Interval::Boolean(field.get()); }
327 inline bool isBoolean() const { return isBoolFalse() || isBoolTrue() || isBoolEither(); }
328
329 template <Type... Types> bool is() const { return ((ty == Types) || ...); }
330
331 bool operator==(const Interval &rhs) const { return ty == rhs.ty && a == rhs.a && b == rhs.b; }
332
333 /* Getters */
334
335 const Field &getField() const { return field.get(); }
336
337 llvm::DynamicAPInt width() const;
338
339 llvm::DynamicAPInt lhs() const { return a; }
340 llvm::DynamicAPInt rhs() const { return b; }
341
342 /* Utility */
343 struct Hash {
344 unsigned operator()(const Interval &i) const {
345 return std::hash<const Field *> {}(&i.field.get()) ^ std::hash<Type> {}(i.ty) ^
346 llvm::hash_value(i.a) ^ llvm::hash_value(i.b);
347 }
348 };
349
350 void print(llvm::raw_ostream &os) const;
351
352 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Interval &i) {
353 i.print(os);
354 return os;
355 }
356
357private:
358 Interval(Type t, const Field &f) : field(f), ty(t), a(f.zero()), b(f.zero()) {}
359 Interval(Type t, const Field &f, const llvm::DynamicAPInt &lhs, const llvm::DynamicAPInt &rhs)
360 : field(f), ty(t), a(f.reduce(lhs)), b(f.reduce(rhs)) {}
361
362 std::reference_wrapper<const Field> field;
363 Type ty;
364 llvm::DynamicAPInt a, b;
365};
366
374mlir::FailureOr<Interval> feltDiv(const Interval &lhs, const Interval &rhs);
375
378mlir::FailureOr<Interval> unsignedIntDiv(const Interval &lhs, const Interval &rhs);
379
382mlir::FailureOr<Interval> signedIntDiv(const Interval &lhs, const Interval &rhs);
383
386Interval signedMod(const Interval &lhs, const Interval &rhs);
387
388} // namespace llzk
Information about the prime finite field used for the interval analysis.
Definition Field.h:36
llvm::DynamicAPInt zero() const
Returns 0 at the bitwidth of the field.
Definition Field.h:82
llvm::DynamicAPInt one() const
Returns 1 at the bitwidth of the field.
Definition Field.h:85
Intervals over a finite field.
Definition Intervals.h:207
bool isEmpty() const
Definition Intervals.h:315
static Interval True(const Field &f)
Definition Intervals.h:226
llvm::DynamicAPInt rhs() const
Definition Intervals.h:340
static constexpr std::array< std::string_view, 7 > TypeNames
Definition Intervals.h:210
bool isTypeA() const
Definition Intervals.h:319
Interval intersect(const Interval &rhs) const
Intersect.
bool isBoolean() const
Definition Intervals.h:327
friend Interval boolOr(const Interval &lhs, const Interval &rhs)
static std::string_view TypeName(Type t)
Definition Intervals.h:214
bool isTypeC() const
Definition Intervals.h:321
friend Interval operator<<(const Interval &lhs, const Interval &rhs)
void print(llvm::raw_ostream &os) const
UnreducedInterval toUnreduced() const
Convert to an UnreducedInterval.
static Interval Boolean(const Field &f)
Definition Intervals.h:228
friend Interval operator^(const Interval &lhs, const Interval &rhs)
Perform a bitwise XOR between the two intervals.
bool isBoolFalse() const
Definition Intervals.h:324
bool isTypeB() const
Definition Intervals.h:320
UnreducedInterval firstUnreduced() const
Get the first side of the interval for TypeF intervals, otherwise just get the full interval as an Un...
static Interval Entire(const Field &f)
Definition Intervals.h:230
bool isDegenerate() const
Definition Intervals.h:317
const Field & getField() const
Definition Intervals.h:335
bool isBoolTrue() const
Definition Intervals.h:325
bool is() const
Definition Intervals.h:329
UnreducedInterval secondUnreduced() const
Get the second side of the interval for TypeA, TypeB, and TypeC intervals.
static Interval TypeF(const Field &f, const llvm::DynamicAPInt &a, const llvm::DynamicAPInt &b)
Definition Intervals.h:244
bool isNotEmpty() const
Definition Intervals.h:316
friend Interval boolAnd(const Interval &lhs, const Interval &rhs)
bool isBoolEither() const
Definition Intervals.h:326
friend llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const Interval &i)
Definition Intervals.h:352
bool operator==(const Interval &rhs) const
Definition Intervals.h:331
friend Interval operator|(const Interval &lhs, const Interval &rhs)
Perform a bitwise OR between the two intervals.
bool isTypeF() const
Definition Intervals.h:322
static Interval False(const Field &f)
Definition Intervals.h:224
friend Interval operator*(const Interval &lhs, const Interval &rhs)
static Interval Empty(const Field &f)
Definition Intervals.h:218
Interval operator~() const
static Interval TypeA(const Field &f, const llvm::DynamicAPInt &a, const llvm::DynamicAPInt &b)
Definition Intervals.h:232
llvm::DynamicAPInt lhs() const
Definition Intervals.h:339
static bool areOneOf(const Interval &a, const Interval &b)
Definition Intervals.h:264
friend Interval operator>>(const Interval &lhs, const Interval &rhs)
Interval()
To satisfy the dataflow::ScalarLatticeValue requirements, this class must be default initializable.
Definition Intervals.h:250
static Interval Degenerate(const Field &f, const llvm::DynamicAPInt &val)
Definition Intervals.h:220
llvm::DynamicAPInt width() const
friend Interval operator+(const Interval &lhs, const Interval &rhs)
bool isEntire() const
Definition Intervals.h:318
friend Interval boolXor(const Interval &lhs, const Interval &rhs)
Interval difference(const Interval &other) const
Computes and returns this - (this & other) if the operation produces a single interval.
friend Interval operator%(const Interval &lhs, const Interval &rhs)
static Interval TypeC(const Field &f, const llvm::DynamicAPInt &a, const llvm::DynamicAPInt &b)
Definition Intervals.h:240
Interval operator-() const
static Interval TypeB(const Field &f, const llvm::DynamicAPInt &a, const llvm::DynamicAPInt &b)
Definition Intervals.h:236
Interval join(const Interval &rhs) const
Union.
friend Interval boolNot(const Interval &iv)
friend Interval operator&(const Interval &lhs, const Interval &rhs)
An inclusive interval [a, b] where a and b are arbitrary integers not necessarily bound to a given fi...
Definition Intervals.h:26
UnreducedInterval operator-() const
Definition Intervals.cpp:93
friend UnreducedInterval operator+(const UnreducedInterval &lhs, const UnreducedInterval &rhs)
UnreducedInterval intersect(const UnreducedInterval &rhs) const
Compute and return the intersection of this interval and the given RHS.
Definition Intervals.cpp:53
UnreducedInterval(const llvm::DynamicAPInt &x, const llvm::DynamicAPInt &y)
Definition Intervals.h:28
UnreducedInterval(int64_t x, int64_t y)
This constructor is primarily for convenience for unit tests.
Definition Intervals.h:30
bool isEmpty() const
Returns true iff width() is zero.
Definition Intervals.h:120
UnreducedInterval computeLTPart(const UnreducedInterval &rhs) const
Return the part of the interval that is guaranteed to be less than the rhs's max value.
Definition Intervals.cpp:63
llvm::DynamicAPInt getRHS() const
Definition Intervals.h:113
UnreducedInterval computeGEPart(const UnreducedInterval &rhs) const
Return the part of the interval that is greater than or equal to the rhs's lower bound.
Definition Intervals.cpp:86
friend std::strong_ordering operator<=>(const UnreducedInterval &lhs, const UnreducedInterval &rhs)
bool isNotEmpty() const
Definition Intervals.h:122
llvm::DynamicAPInt getLHS() const
Definition Intervals.h:112
bool overlaps(const UnreducedInterval &rhs) const
llvm::DynamicAPInt width() const
Compute the width of this interval within a given field f.
friend llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const UnreducedInterval &ui)
Definition Intervals.h:126
friend bool operator==(const UnreducedInterval &lhs, const UnreducedInterval &rhs)
Definition Intervals.h:101
UnreducedInterval doUnion(const UnreducedInterval &rhs) const
Compute and return the union of this interval and the given RHS.
Definition Intervals.cpp:58
void print(llvm::raw_ostream &os) const
Definition Intervals.h:124
UnreducedInterval computeGTPart(const UnreducedInterval &rhs) const
Return the part of the interval that is greater than the rhs's lower bound.
Definition Intervals.cpp:78
Interval reduce(const Field &field) const
Reduce the interval to an interval in the given field.
Definition Intervals.cpp:23
UnreducedInterval computeLEPart(const UnreducedInterval &rhs) const
Return the part of the interval that is less than or equal to the rhs's upper bound.
Definition Intervals.cpp:71
friend UnreducedInterval operator*(const UnreducedInterval &lhs, const UnreducedInterval &rhs)
FailureOr< Interval > signedIntDiv(const Interval &lhs, const Interval &rhs)
Computes signed integer division with possibly non-Degenerate divisors.
Interval signedMod(const Interval &lhs, const Interval &rhs)
Computes signed integer remainder with possibly non-Degenerate divisors.
FailureOr< Interval > unsignedIntDiv(const Interval &lhs, const Interval &rhs)
Computes unsigned integer division with possibly non-Degenerate divisors.
FailureOr< Interval > feltDiv(const Interval &lhs, const Interval &rhs)
Computes finite-field division by multiplying the dividend by the multiplicative inverse of the divis...
unsigned operator()(const Interval &i) const
Definition Intervals.h:344
unsigned operator()(const UnreducedInterval &ui) const
Definition Intervals.h:107