LLZK 0.1.0
Veridise's ZK Language IR
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/Analysis/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);
291 friend mlir::FailureOr<Interval> operator/(const Interval &lhs, const Interval &rhs);
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
296 /* boolean ops */
297 friend Interval boolAnd(const Interval &lhs, const Interval &rhs);
298 friend Interval boolOr(const Interval &lhs, const Interval &rhs);
299 friend Interval boolXor(const Interval &lhs, const Interval &rhs);
300 friend Interval boolNot(const Interval &iv);
301
302 /* Checks and Comparisons */
303
304 inline bool isEmpty() const { return ty == Type::Empty; }
305 inline bool isNotEmpty() const { return !isEmpty(); }
306 inline bool isDegenerate() const { return ty == Type::Degenerate; }
307 inline bool isEntire() const { return ty == Type::Entire; }
308 inline bool isTypeA() const { return ty == Type::TypeA; }
309 inline bool isTypeB() const { return ty == Type::TypeB; }
310 inline bool isTypeC() const { return ty == Type::TypeC; }
311 inline bool isTypeF() const { return ty == Type::TypeF; }
312
313 inline bool isBoolFalse() const { return *this == Interval::False(field.get()); }
314 inline bool isBoolTrue() const { return *this == Interval::True(field.get()); }
315 inline bool isBoolEither() const { return *this == Interval::Boolean(field.get()); }
316 inline bool isBoolean() const { return isBoolFalse() || isBoolTrue() || isBoolEither(); }
317
318 template <Type... Types> bool is() const { return ((ty == Types) || ...); }
319
320 bool operator==(const Interval &rhs) const { return ty == rhs.ty && a == rhs.a && b == rhs.b; }
321
322 /* Getters */
323
324 const Field &getField() const { return field.get(); }
325
326 llvm::DynamicAPInt width() const;
327
328 llvm::DynamicAPInt lhs() const { return a; }
329 llvm::DynamicAPInt rhs() const { return b; }
330
331 /* Utility */
332 struct Hash {
333 unsigned operator()(const Interval &i) const {
334 return std::hash<const Field *> {}(&i.field.get()) ^ std::hash<Type> {}(i.ty) ^
335 llvm::hash_value(i.a) ^ llvm::hash_value(i.b);
336 }
337 };
338
339 void print(llvm::raw_ostream &os) const;
340
341 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Interval &i) {
342 i.print(os);
343 return os;
344 }
345
346private:
347 Interval(Type t, const Field &f) : field(f), ty(t), a(f.zero()), b(f.zero()) {}
348 Interval(Type t, const Field &f, const llvm::DynamicAPInt &lhs, const llvm::DynamicAPInt &rhs)
349 : field(f), ty(t), a(f.reduce(lhs)), b(f.reduce(rhs)) {}
350
351 std::reference_wrapper<const Field> field;
352 Type ty;
353 llvm::DynamicAPInt a, b;
354};
355
356} // namespace llzk
Information about the prime finite field used for the interval analysis.
Definition Field.h:25
llvm::DynamicAPInt zero() const
Returns 0 at the bitwidth of the field.
Definition Field.h:46
llvm::DynamicAPInt one() const
Returns 1 at the bitwidth of the field.
Definition Field.h:49
Intervals over a finite field.
Definition Intervals.h:200
bool isEmpty() const
Definition Intervals.h:304
static Interval True(const Field &f)
Definition Intervals.h:219
llvm::DynamicAPInt rhs() const
Definition Intervals.h:329
static constexpr std::array< std::string_view, 7 > TypeNames
Definition Intervals.h:203
bool isTypeA() const
Definition Intervals.h:308
Interval intersect(const Interval &rhs) const
Intersect.
bool isBoolean() const
Definition Intervals.h:316
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:310
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
bool isBoolFalse() const
Definition Intervals.h:313
bool isTypeB() const
Definition Intervals.h:309
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:306
const Field & getField() const
Definition Intervals.h:324
bool isBoolTrue() const
Definition Intervals.h:314
bool is() const
Definition Intervals.h:318
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:305
friend Interval boolAnd(const Interval &lhs, const Interval &rhs)
bool isBoolEither() const
Definition Intervals.h:315
friend llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const Interval &i)
Definition Intervals.h:341
bool operator==(const Interval &rhs) const
Definition Intervals.h:320
bool isTypeF() const
Definition Intervals.h:311
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:328
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
friend mlir::FailureOr< Interval > operator/(const Interval &lhs, const Interval &rhs)
Returns failure if a division-by-zero is encountered.
llvm::DynamicAPInt width() const
friend Interval operator+(const Interval &lhs, const Interval &rhs)
bool isEntire() const
Definition Intervals.h:307
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:90
friend UnreducedInterval operator+(const UnreducedInterval &lhs, const UnreducedInterval &rhs)
Definition Intervals.cpp:97
UnreducedInterval intersect(const UnreducedInterval &rhs) const
Compute and return the intersection of this interval and the given RHS.
Definition Intervals.cpp:50
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:60
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:83
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:55
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:75
Interval reduce(const Field &field) const
Reduce the interval to an interval in the given field.
Definition Intervals.cpp:20
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:68
friend UnreducedInterval operator*(const UnreducedInterval &lhs, const UnreducedInterval &rhs)
unsigned operator()(const Interval &i) const
Definition Intervals.h:333