LLZK 2.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 */
106 llvm::DynamicAPInt getLHS() const { return a; }
107 llvm::DynamicAPInt getRHS() const { return b; }
108
111 llvm::DynamicAPInt width() const;
112
114 inline bool isEmpty() const { return width() == 0; }
115
116 bool isNotEmpty() const { return !isEmpty(); }
117
118 void print(llvm::raw_ostream &os) const { os << "Unreduced:[ " << a << ", " << b << " ]"; }
119
120 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const UnreducedInterval &ui) {
121 ui.print(os);
122 return os;
123 }
124
125private:
126 llvm::DynamicAPInt a, b;
127};
128
129/* Interval */
130
200class Interval {
201public:
202 enum class Type : std::uint8_t { TypeA = 0, TypeB, TypeC, TypeF, Empty, Degenerate, Entire };
203 static constexpr std::array<std::string_view, 7> TypeNames = {"TypeA", "TypeB", "TypeC",
204 "TypeF", "Empty", "Degenerate",
205 "Entire"};
206
207 static std::string_view TypeName(Type t) { return TypeNames.at(static_cast<size_t>(t)); }
208
209 /* Static constructors for convenience */
210
211 static Interval Empty(const Field &f) { return Interval(Type::Empty, f); }
212
213 static Interval Degenerate(const Field &f, const llvm::DynamicAPInt &val) {
214 return Interval(Type::Degenerate, f, val, val);
215 }
216
217 static Interval False(const Field &f) { return Interval::Degenerate(f, f.zero()); }
218
219 static Interval True(const Field &f) { return Interval::Degenerate(f, f.one()); }
220
221 static Interval Boolean(const Field &f) { return Interval::TypeA(f, f.zero(), f.one()); }
222
223 static Interval Entire(const Field &f) { return Interval(Type::Entire, f); }
224
225 static Interval TypeA(const Field &f, const llvm::DynamicAPInt &a, const llvm::DynamicAPInt &b) {
226 return Interval(Type::TypeA, f, a, b);
227 }
228
229 static Interval TypeB(const Field &f, const llvm::DynamicAPInt &a, const llvm::DynamicAPInt &b) {
230 return Interval(Type::TypeB, f, a, b);
231 }
232
233 static Interval TypeC(const Field &f, const llvm::DynamicAPInt &a, const llvm::DynamicAPInt &b) {
234 return Interval(Type::TypeC, f, a, b);
235 }
236
237 static Interval TypeF(const Field &f, const llvm::DynamicAPInt &a, const llvm::DynamicAPInt &b) {
238 return Interval(Type::TypeF, f, a, b);
239 }
240
244
247
251
255
256 template <std::pair<Type, Type>... Pairs>
257 static bool areOneOf(const Interval &a, const Interval &b) {
258 return ((a.ty == std::get<0>(Pairs) && b.ty == std::get<1>(Pairs)) || ...);
259 }
260
262 Interval join(const Interval &rhs) const;
263
265 Interval intersect(const Interval &rhs) const;
266
280 Interval difference(const Interval &other) const;
281
282 /* arithmetic ops */
283
284 Interval operator-() const;
285 Interval operator~() const;
286 friend Interval operator+(const Interval &lhs, const Interval &rhs);
287 friend Interval operator-(const Interval &lhs, const Interval &rhs);
288 friend Interval operator*(const Interval &lhs, const Interval &rhs);
289 friend Interval operator%(const Interval &lhs, const Interval &rhs);
290 friend Interval operator&(const Interval &lhs, const Interval &rhs);
293 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);
298 friend Interval operator>>(const Interval &lhs, const Interval &rhs);
299
300 /* boolean ops */
301 friend Interval boolAnd(const Interval &lhs, const Interval &rhs);
302 friend Interval boolOr(const Interval &lhs, const Interval &rhs);
303 friend Interval boolXor(const Interval &lhs, const Interval &rhs);
304 friend Interval boolNot(const Interval &iv);
305
306 /* Checks and Comparisons */
307
308 inline bool isEmpty() const { return ty == Type::Empty; }
309 inline bool isNotEmpty() const { return !isEmpty(); }
310 inline bool isDegenerate() const { return ty == Type::Degenerate; }
311 inline bool isEntire() const { return ty == Type::Entire; }
312 inline bool isTypeA() const { return ty == Type::TypeA; }
313 inline bool isTypeB() const { return ty == Type::TypeB; }
314 inline bool isTypeC() const { return ty == Type::TypeC; }
315 inline bool isTypeF() const { return ty == Type::TypeF; }
316
317 inline bool isBoolFalse() const { return *this == Interval::False(field.get()); }
318 inline bool isBoolTrue() const { return *this == Interval::True(field.get()); }
319 inline bool isBoolEither() const { return *this == Interval::Boolean(field.get()); }
320 inline bool isBoolean() const { return isBoolFalse() || isBoolTrue() || isBoolEither(); }
321
322 template <Type... Types> bool is() const { return ((ty == Types) || ...); }
323
324 bool operator==(const Interval &rhs) const { return ty == rhs.ty && a == rhs.a && b == rhs.b; }
325
326 /* Getters */
327
328 const Field &getField() const { return field.get(); }
329
330 llvm::DynamicAPInt width() const;
331
332 llvm::DynamicAPInt lhs() const { return a; }
333 llvm::DynamicAPInt rhs() const { return b; }
334
335 /* Utility */
336 struct Hash {
337 unsigned operator()(const Interval &i) const {
338 return std::hash<const Field *> {}(&i.field.get()) ^ std::hash<Type> {}(i.ty) ^
339 llvm::hash_value(i.a) ^ llvm::hash_value(i.b);
340 }
341 };
342
343 void print(llvm::raw_ostream &os) const;
344
345 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Interval &i) {
346 i.print(os);
347 return os;
348 }
349
350private:
351 Interval(Type t, const Field &f) : field(f), ty(t), a(f.zero()), b(f.zero()) {}
352 Interval(Type t, const Field &f, const llvm::DynamicAPInt &lhs, const llvm::DynamicAPInt &rhs)
353 : field(f), ty(t), a(f.reduce(lhs)), b(f.reduce(rhs)) {}
354
355 std::reference_wrapper<const Field> field;
356 Type ty;
357 llvm::DynamicAPInt a, b;
358};
359
367mlir::FailureOr<Interval> feltDiv(const Interval &lhs, const Interval &rhs);
368
371mlir::FailureOr<Interval> unsignedIntDiv(const Interval &lhs, const Interval &rhs);
372
375mlir::FailureOr<Interval> signedIntDiv(const Interval &lhs, const Interval &rhs);
376
377} // namespace llzk
Information about the prime finite field used for the interval analysis.
Definition Field.h:35
llvm::DynamicAPInt zero() const
Returns 0 at the bitwidth of the field.
Definition Field.h:80
llvm::DynamicAPInt one() const
Returns 1 at the bitwidth of the field.
Definition Field.h:83
Intervals over a finite field.
Definition Intervals.h:200
bool isEmpty() const
Definition Intervals.h:308
static Interval True(const Field &f)
Definition Intervals.h:219
llvm::DynamicAPInt rhs() const
Definition Intervals.h:333
static constexpr std::array< std::string_view, 7 > TypeNames
Definition Intervals.h:203
bool isTypeA() const
Definition Intervals.h:312
Interval intersect(const Interval &rhs) const
Intersect.
bool isBoolean() const
Definition Intervals.h:320
friend Interval boolOr(const Interval &lhs, const Interval &rhs)
static std::string_view TypeName(Type t)
Definition Intervals.h:207
bool isTypeC() const
Definition Intervals.h:314
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:221
friend Interval operator^(const Interval &lhs, const Interval &rhs)
Perform a bitwise XOR between the two intervals.
bool isBoolFalse() const
Definition Intervals.h:317
bool isTypeB() const
Definition Intervals.h:313
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:223
bool isDegenerate() const
Definition Intervals.h:310
const Field & getField() const
Definition Intervals.h:328
bool isBoolTrue() const
Definition Intervals.h:318
bool is() const
Definition Intervals.h:322
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:237
bool isNotEmpty() const
Definition Intervals.h:309
friend Interval boolAnd(const Interval &lhs, const Interval &rhs)
bool isBoolEither() const
Definition Intervals.h:319
friend llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const Interval &i)
Definition Intervals.h:345
bool operator==(const Interval &rhs) const
Definition Intervals.h:324
friend Interval operator|(const Interval &lhs, const Interval &rhs)
Perform a bitwise OR between the two intervals.
bool isTypeF() const
Definition Intervals.h:315
static Interval False(const Field &f)
Definition Intervals.h:217
friend Interval operator*(const Interval &lhs, const Interval &rhs)
static Interval Empty(const Field &f)
Definition Intervals.h:211
Interval operator~() const
static Interval TypeA(const Field &f, const llvm::DynamicAPInt &a, const llvm::DynamicAPInt &b)
Definition Intervals.h:225
llvm::DynamicAPInt lhs() const
Definition Intervals.h:332
static bool areOneOf(const Interval &a, const Interval &b)
Definition Intervals.h:257
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:243
static Interval Degenerate(const Field &f, const llvm::DynamicAPInt &val)
Definition Intervals.h:213
llvm::DynamicAPInt width() const
friend Interval operator+(const Interval &lhs, const Interval &rhs)
bool isEntire() const
Definition Intervals.h:311
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:233
Interval operator-() const
static Interval TypeB(const Field &f, const llvm::DynamicAPInt &a, const llvm::DynamicAPInt &b)
Definition Intervals.h:229
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:114
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:107
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:116
llvm::DynamicAPInt getLHS() const
Definition Intervals.h:106
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:120
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:118
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.
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:337