LLZK 0.1.0
Veridise's ZK Language IR
Loading...
Searching...
No Matches
Field.cpp
Go to the documentation of this file.
1//===-- Field.cpp -----------------------------------------------*- 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#include "llzk/Analysis/Field.h"
12
13#include <llvm/ADT/Twine.h>
14
15#include <mutex>
16
17namespace llzk {
18
19// We make the primeMod signed to allow for signed arithmetic, otherwise APSInt
20// throws an assertion failure if signedness does not match. This requires adding
21// an extra bit for the signed bit.
22Field::Field(std::string_view primeStr) : primeMod(safeToSigned(primeStr)) {
23 halfPrime = (primeMod + felt(1)) / felt(2);
24}
25
26const Field &Field::getField(const char *fieldName) {
27 static llvm::DenseMap<llvm::StringRef, Field> knownFields;
28 static std::once_flag fieldsInit;
29 std::call_once(fieldsInit, initKnownFields, knownFields);
30
31 if (auto it = knownFields.find(fieldName); it != knownFields.end()) {
32 return it->second;
33 }
34 llvm::report_fatal_error("field \"" + llvm::Twine(fieldName) + "\" is unsupported");
35}
36
37void Field::initKnownFields(llvm::DenseMap<llvm::StringRef, Field> &knownFields) {
38 // bn128/254, default for circom
39 knownFields.try_emplace(
40 "bn128",
41 Field("21888242871839275222246405745257275088696311157297823662689037894645226208583")
42 );
43 knownFields.try_emplace("bn254", knownFields.at("bn128"));
44 // 15 * 2^27 + 1, default for zirgen
45 knownFields.try_emplace("babybear", Field("2013265921"));
46 // 2^64 - 2^32 + 1, used for plonky2
47 knownFields.try_emplace("goldilocks", Field("18446744069414584321"));
48 // 2^31 - 1, used for Plonky3
49 knownFields.try_emplace("mersenne31", Field("2147483647"));
50}
51
52llvm::APSInt Field::reduce(llvm::APSInt i) const {
53 // Force i to be signed since prime() is signed
54 i = safeToSigned(i);
55 unsigned maxBits = std::max(i.getBitWidth(), bitWidth());
56 llvm::APSInt m = (i.extend(maxBits) % prime().extend(maxBits)).trunc(bitWidth());
57 if (m.isNegative()) {
58 return prime() + m;
59 }
60 return m;
61}
62
63llvm::APSInt Field::reduce(int i) const {
64 auto ap = llvm::APSInt(llvm::APInt(bitWidth(), i), /*isUnsigned=*/false);
65 return reduce(ap);
66}
67
68} // namespace llzk
This file defines helpers for manipulating APInts/APSInts for large numbers and operations over those...
Information about the prime finite field used for the interval analysis.
Definition Field.h:22
Field()=delete
unsigned bitWidth() const
Definition Field.h:57
static const Field & getField(const char *fieldName)
Get a Field from a given field name string.
Definition Field.cpp:26
llvm::APSInt prime() const
For the prime field p, returns p.
Definition Field.h:34
llvm::APSInt reduce(llvm::APSInt i) const
Returns i mod p and reduces the result into the appropriate bitwidth.
Definition Field.cpp:52
llvm::APSInt safeToSigned(llvm::APSInt i)
Safely converts the given int to a signed int if it is an unsigned int by adding an extra bit for the...