Skip to content
This repository was archived by the owner on Aug 18, 2020. It is now read-only.

Commit c1165c9

Browse files
author
Todd Stavish
committed
add integer encoding, strict-prototypes fix
1 parent 8df1314 commit c1165c9

File tree

3 files changed

+85
-2
lines changed

3 files changed

+85
-2
lines changed

SEALPython/setup.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import os, sys
2-
32
from distutils.core import setup, Extension
43
from distutils import sysconfig
54

5+
# Remove strict-prototypes compiler flag
6+
cfg_vars = sysconfig.get_config_vars()
7+
for key, value in cfg_vars.items():
8+
if type(value) == str:
9+
cfg_vars[key] = value.replace('-Wstrict-prototypes', '')
10+
611
cpp_args = ['-std=c++11']
712

813
ext_modules = [

SEALPython/wrapper.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include "biguint.h"
44
#include "chooser.h"
55
#include "encryptionparams.h"
6+
#include "encoder.h"
7+
#include "memorypoolhandle.h"
68

79
namespace py = pybind11;
810

@@ -26,6 +28,8 @@ PYBIND11_MODULE(seal, m) {
2628
py::class_<EncryptionParameters>(m, "EncryptionParameters")
2729
.def(py::init<>())
2830
.def(py::init<const MemoryPoolHandle &>())
31+
.def("plain_modulus", &EncryptionParameters::plain_modulus,
32+
"Returns the plaintext modulus")
2933
.def("set_coeff_modulus",
3034
(void (EncryptionParameters::*)(const BigUInt &)) &EncryptionParameters::set_coeff_modulus,
3135
"Set coefficient modulus parameter")
@@ -51,4 +55,12 @@ PYBIND11_MODULE(seal, m) {
5155
"Validates parameters");
5256

5357
py::class_<EncryptionParameterQualifiers>(m, "EncryptionParameterQuailifers");
58+
59+
py::class_<IntegerEncoder>(m, "IntegerEncoder")
60+
.def(py::init<const BigUInt &, std::uint64_t, const MemoryPoolHandle &>());
61+
62+
py::class_<MemoryPoolHandle>(m, "MemoryPoolHandle")
63+
.def(py::init<>())
64+
.def_static("acquire_global", &MemoryPoolHandle::acquire_global,
65+
"Returns a MemoryPoolHandle pointing to the global memory pool");
5466
}

SEALPythonExamples/examples.py

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
from seal import EncryptionParameters, ChooserEvaluator
1+
from seal import ChooserEvaluator, \
2+
EncryptionParameters, \
3+
IntegerEncoder, \
4+
MemoryPoolHandle
25

36
def example_basics():
47
"""
@@ -81,6 +84,69 @@ def example_basics():
8184
# important pre-computation.
8285
parms.validate()
8386

87+
# Plaintext elements in the FV scheme are polynomials (represented by the
88+
# Plaintext class) with coefficients integers modulo plain_modulus. To
89+
# encrypt for example integers instead, one must use an "encoding scheme",
90+
# i.e. a specific way of representing integers as such polynomials. SEAL
91+
# comes with a few basic encoders:
92+
#
93+
# IntegerEncoder:
94+
# Given an integer base b, encodes integers as plaintext polynomials in the
95+
# following way. First, a base-b expansion of the integer is computed. This
96+
# expansion uses a "balanced" set of representatives of integers modulo b as
97+
# the coefficients. Namely, when b is off the coefficients are integers
98+
# between -(b-1)/2 and (b-1)/2. When b is even, the integers are between
99+
# -b/2 and (b-1)/2, except when b is two and the usual binary expansion is
100+
# used (coefficients 0 and 1). Decoding amounts to evaluating the polynomial
101+
# at x=b. For example, if b=2, the integer 26 = 2^4 + 2^3 + 2^1 is encoded
102+
# as the polynomial 1x^4 + 1x^3 + 1x^1. When b=3, 26 = 3^3 - 3^0 is encoded
103+
# as the polynomial 1x^3 - 1. In reality, coefficients of polynomials are
104+
# always unsigned integers, and in this case are stored as their smallest
105+
# non-negative representatives modulo plain_modulus. To create an integer
106+
# encoder with a base b, use IntegerEncoder(plain_modulus, b). If no b is
107+
# given to the constructor, the default value of b=2 is used.
108+
#
109+
# FractionalEncoder:
110+
# Encodes fixed-precision rational numbers as follows. First expand the
111+
# number in a given base b, possibly truncating an infinite fractional part
112+
# to finite precision, e.g. 26.75 = 2^4 + 2^3 + 2^1 + 2^(-1) + 2^(-2) when
113+
# =2. For the sake of the example, suppose poly_modulus is 1x^1024 + 1. Next
114+
# represent the integer part of the number in the same way as in
115+
# IntegerEncoder (with b=2 here). Finally, represent the fractional part in
116+
# the leading coefficients of the polynomial, but when doing so invert the
117+
# signs of the coefficients. So in this example we would represent 26.75 as
118+
# the polynomial -1x^1023 - 1x^1022 + 1x^4 + 1x^3 + 1x^1. The negative
119+
# coefficients of the polynomial will again be represented as their
120+
# negatives modulo plain_modulus.
121+
#
122+
# PolyCRTBuilder:
123+
# If poly_modulus is 1x^N + 1, PolyCRTBuilder allows "batching" of N
124+
# plaintext integers modulo plain_modulus into one plaintext polynomial,
125+
# where homomorphic operations can be carried out very efficiently in a SIMD
126+
# manner by operating on such a "composed" plaintext or ciphertext
127+
# polynomials. For full details on this very powerful technique we
128+
# recommend https://eprint.iacr.org/2012/565.pdf and
129+
# https://eprint.iacr.org/2011/133.
130+
#
131+
# A crucial fact to understand is that when homomorphic operations are
132+
# performed on ciphertexts, they will carry over to the underlying
133+
# plaintexts, and as a result of additions and multiplications the
134+
# coefficients in the plaintext polynomials will increase from what they
135+
# originally were in freshly encoded polynomials. This becomes a problem
136+
# when the coefficients reach the size of plain_modulus, in which case they
137+
# will get automatically reduced modulo plain_modulus, and might render the
138+
# underlying plaintext polynomial impossible to be correctly decoded back
139+
# into an integer or rational number. Therefore, it is typically crucial to
140+
# have a good sense of how large the coefficients will grow in the
141+
# underlying plaintext polynomials when homomorphic computations are carried
142+
# out on the ciphertexts, and make sure that plain_modulus is chosen to be
143+
# at least as large as this number.
144+
145+
# Here we choose to create an IntegerEncoder with base b=2.
146+
encoder = IntegerEncoder(parms.plain_modulus(),
147+
2,
148+
MemoryPoolHandle.acquire_global())
149+
84150
def main():
85151
# Example: Basics
86152
example_basics()

0 commit comments

Comments
 (0)