LLZK 2.1.1
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
206class Interval {
207public:
208 enum class Type : std::uint8_t { TypeA = 0, TypeB, TypeC, TypeF, Empty, Degenerate, Entire };
209 static constexpr std::array<std::string_view, 7> TypeNames = {"TypeA", "TypeB", "TypeC",
210 "TypeF", "Empty", "Degenerate",
211 "Entire"};
212
213 static std::string_view TypeName(Type t) { return TypeNames.at(static_cast<size_t>(t)); }
214
215 /* Static constructors for convenience */
216
217 static Interval Empty(const Field &f) { return Interval(Type::Empty, f); }
218
219 static Interval Degenerate(const Field &f, const llvm::DynamicAPInt &val) {
220 return Interval(Type::Degenerate, f, val, val);
221 }
222
223 static Interval False(const Field &f) { return Interval::Degenerate(f, f.zero()); }
224
225 static Interval True(const Field &f) { return Interval::Degenerate(f, f.one()); }
226
227 static Interval Boolean(const Field &f) { return Interval::TypeA(f, f.zero(), f.one()); }
228
229 static Interval Entire(const Field &f) { return Interval(Type::Entire, f); }
230
231 static Interval TypeA(const Field &f, const llvm::DynamicAPInt &a, const llvm::DynamicAPInt &b) {
232 return Interval(Type::TypeA, f, a, b);
233 }
234
235 static Interval TypeB(const Field &f, const llvm::DynamicAPInt &a, const llvm::DynamicAPInt &b) {
236 return Interval(Type::TypeB, f, a, b);
237 }
238
239 static Interval TypeC(const Field &f, const llvm::DynamicAPInt &a, const llvm::DynamicAPInt &b) {
240 return Interval(Type::TypeC, f, a, b);
241 }
242
243 static Interval TypeF(const Field &f, const llvm::DynamicAPInt &a, const llvm::DynamicAPInt &b) {
244 return Interval(Type::TypeF, f, a, b);
245 }
246
250
253
257
261
262 template <std::pair<Type, Type>... Pairs>
263 static bool areOneOf(const Interval &a, const Interval &b) {
264 return ((a.ty == std::get<0>(Pairs) && b.ty == std::get<1>(Pairs)) || ...);
265 }
266
268 Interval join(const Interval &rhs) const;
269
271 Interval intersect(const Interval &rhs) const;
272
286 Interval difference(const Interval &other) const;
287
288 /* arithmetic ops */
289
290 Interval operator-() const;
291 Interval operator~() const;
292 friend Interval operator+(const Interval &lhs, const Interval &rhs);
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);
299 friend Interval operator|(const Interval &lhs, const Interval &rhs);
302 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
306 /* boolean ops */
307 friend Interval boolAnd(const Interval &lhs, const Interval &rhs);
308 friend Interval boolOr(const Interval &lhs, const Interval &rhs);
309 friend Interval boolXor(const Interval &lhs, const Interval &rhs);
310 friend Interval boolNot(const Interval &iv);
311
312 /* Checks and Comparisons */
313
314 inline bool isEmpty() const { return ty == Type::Empty; }
315 inline bool isNotEmpty() const { return !isEmpty(); }
316 inline bool isDegenerate() const { return ty == Type::Degenerate; }
317 inline bool isEntire() const { return ty == Type::Entire; }
318 inline bool isTypeA() const { return ty == Type::TypeA; }
319 inline bool isTypeB() const { return ty == Type::TypeB; }
320 inline bool isTypeC() const { return ty == Type::TypeC; }
321 inline bool isTypeF() const { return ty == Type::TypeF; }
322
323 inline bool isBoolFalse() const { return *this == Interval::False(field.get()); }
324 inline bool isBoolTrue() const { return *this == Interval::True(field.get()); }
325 inline bool isBoolEither() const { return *this == Interval::Boolean(field.get()); }
326 inline bool isBoolean() const { return isBoolFalse() || isBoolTrue() || isBoolEither(); }
327
328 template <Type... Types> bool is() const { return ((ty == Types) || ...); }
329
330 bool operator==(const Interval &rhs) const { return ty == rhs.ty && a == rhs.a && b == rhs.b; }
331
332 /* Getters */
333
334 const Field &getField() const { return field.get(); }
335
336 llvm::DynamicAPInt width() const;
337
338 llvm::DynamicAPInt lhs() const { return a; }
339 llvm::DynamicAPInt rhs() const { return b; }
340
341 /* Utility */
342 struct Hash {
343 unsigned operator()(const Interval &i) const {
344 return std::hash<const Field *> {}(&i.field.get()) ^ std::hash<Type> {}(i.ty) ^
345 llvm::hash_value(i.a) ^ llvm::hash_value(i.b);
346 }
347 };
348
349 void print(llvm::raw_ostream &os) const;
350
351 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Interval &i) {
352 i.print(os);
353 return os;
354 }
355
356private:
357 Interval(Type t, const Field &f) : field(f), ty(t), a(f.zero()), b(f.zero()) {}
358 Interval(Type t, const Field &f, const llvm::DynamicAPInt &lhs, const llvm::DynamicAPInt &rhs)
359 : field(f), ty(t), a(f.reduce(lhs)), b(f.reduce(rhs)) {}
360
361 std::reference_wrapper<const Field> field;
362 Type ty;
363 llvm::DynamicAPInt a, b;
364};
365
373mlir::FailureOr<Interval> feltDiv(const Interval &lhs, const Interval &rhs);
374
377mlir::FailureOr<Interval> unsignedIntDiv(const Interval &lhs, const Interval &rhs);
378
381mlir::FailureOr<Interval> signedIntDiv(const Interval &lhs, const Interval &rhs);
382
385Interval signedMod(const Interval &lhs, const Interval &rhs);
386
387} // 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:81
llvm::DynamicAPInt one() const
Returns 1 at the bitwidth of the field.
Definition Field.h:84
Intervals over a finite field.
Definition Intervals.h:206
bool isEmpty() const
Definition Intervals.h:314
static Interval True(const Field &f)
Definition Intervals.h:225
llvm::DynamicAPInt rhs() const
Definition Intervals.h:339
static constexpr std::array< std::string_view, 7 > TypeNames
Definition Intervals.h:209
bool isTypeA() const
Definition Intervals.h:318
Interval intersect(const Interval &rhs) const
Intersect.
bool isBoolean() const
Definition Intervals.h:326
friend Interval boolOr(const Interval &lhs, const Interval &rhs)
static std::string_view TypeName(Type t)
Definition Intervals.h:213
bool isTypeC() const
Definition Intervals.h:320
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:227
friend Interval operator^(const Interval &lhs, const Interval &rhs)
Perform a bitwise XOR between the two intervals.
bool isBoolFalse() const
Definition Intervals.h:323
bool isTypeB() const
Definition Intervals.h:319
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:229
bool isDegenerate() const
Definition Intervals.h:316
const Field & getField() const
Definition Intervals.h:334
bool isBoolTrue() const
Definition Intervals.h:324
bool is() const
Definition Intervals.h:328
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:243
bool isNotEmpty() const
Definition Intervals.h:315
friend Interval boolAnd(const Interval &lhs, const Interval &rhs)
bool isBoolEither() const
Definition Intervals.h:325
friend llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const Interval &i)
Definition Intervals.h:351
bool operator==(const Interval &rhs) const
Definition Intervals.h:330
friend Interval operator|(const Interval &lhs, const Interval &rhs)
Perform a bitwise OR between the two intervals.
bool isTypeF() const
Definition Intervals.h:321
static Interval False(const Field &f)
Definition Intervals.h:223
friend Interval operator*(const Interval &lhs, const Interval &rhs)
static Interval Empty(const Field &f)
Definition Intervals.h:217
Interval operator~() const
static Interval TypeA(const Field &f, const llvm::DynamicAPInt &a, const llvm::DynamicAPInt &b)
Definition Intervals.h:231
llvm::DynamicAPInt lhs() const
Definition Intervals.h:338
static bool areOneOf(const Interval &a, const Interval &b)
Definition Intervals.h:263
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:249
static Interval Degenerate(const Field &f, const llvm::DynamicAPInt &val)
Definition Intervals.h:219
llvm::DynamicAPInt width() const
friend Interval operator+(const Interval &lhs, const Interval &rhs)
bool isEntire() const
Definition Intervals.h:317
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:239
Interval operator-() const
static Interval TypeB(const Field &f, const llvm::DynamicAPInt &a, const llvm::DynamicAPInt &b)
Definition Intervals.h:235
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:343
unsigned operator()(const UnreducedInterval &ui) const
Definition Intervals.h:107