mirror of
https://github.com/tuneinsight/lattigo.git
synced 2025-09-13 03:27:14 +00:00
[doc] formatting cleanup #38
Fix various Go comments that are misformated in the documentation browser. The set of changes includes - unfolding inlined lists - numerous spelling and grammar fixes - include links to packages, types, functions and constants - documentation generation instructions in the README
This commit is contained in:
committed by
Romain Bouyé
parent
01ca051d36
commit
988d3d7618
11
README.md
11
README.md
@@ -108,6 +108,17 @@ RLWE --> MHE([MHE])
|
||||
MHE --> MHEInt
|
||||
```
|
||||
|
||||
### Documentation
|
||||
|
||||
The full documentation of the individual packages can be browsed as a web page using official
|
||||
Golang documentation rendering tool `pkgsite`
|
||||
|
||||
```bash
|
||||
$ go install golang.org/x/pkgsite/cmd/pkgsite@latest
|
||||
$ cd lattigo
|
||||
$ pkgsite -open .
|
||||
```
|
||||
|
||||
## Versions and Roadmap
|
||||
|
||||
The Lattigo library was originally exclusively developed by the EPFL Laboratory for Data Security
|
||||
|
||||
@@ -23,7 +23,7 @@ func (ct Ciphertext) LevelP() int {
|
||||
return ct.Value[0].LevelP()
|
||||
}
|
||||
|
||||
// NewCiphertext allocates a new RGSW ciphertext in the NTT domain.
|
||||
// NewCiphertext allocates a new RGSW [Ciphertext] in the NTT domain.
|
||||
func NewCiphertext(params rlwe.Parameters, levelQ, levelP, BaseTwoDecomposition int) (ct *Ciphertext) {
|
||||
return &Ciphertext{
|
||||
Value: [2]rlwe.GadgetCiphertext{
|
||||
@@ -38,15 +38,15 @@ func (ct Ciphertext) BinarySize() int {
|
||||
return ct.Value[0].BinarySize() + ct.Value[1].BinarySize()
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// WriteTo writes the object on an [io.Writer]. It implements the [io.WriterTo]
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
//
|
||||
// Unless w implements the buffer.Writer interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a bufio.Writer. Since this requires allocations, it
|
||||
// is preferable to pass a buffer.Writer directly:
|
||||
// Unless w implements the [buffer.Writer] interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a [bufio.Writer]. Since this requires allocations, it
|
||||
// is preferable to pass a [buffer.Writer] directly:
|
||||
//
|
||||
// - When writing multiple times to a io.Writer, it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// - When writing multiple times to a [io.Writer], it is preferable to first wrap the
|
||||
// [io.Writer] in a pre-allocated [bufio.Writer].
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (ct Ciphertext) WriteTo(w io.Writer) (n int64, err error) {
|
||||
@@ -66,15 +66,15 @@ func (ct Ciphertext) WriteTo(w io.Writer) (n int64, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// [io.ReaderFrom] interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a [buffer.Reader] directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// - When reading multiple values from a [io.Reader], it is preferable to first
|
||||
// first wrap [io.Reader] in a pre-allocated [bufio.Reader].
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (ct *Ciphertext) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
@@ -102,7 +102,7 @@ func (ct Ciphertext) MarshalBinary() (p []byte, err error) {
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
// [Ciphertext.MarshalBinary] or [Ciphertext.WriteTo] on the object.
|
||||
func (ct *Ciphertext) UnmarshalBinary(p []byte) (err error) {
|
||||
_, err = ct.ReadFrom(buffer.NewBuffer(p))
|
||||
return
|
||||
@@ -111,7 +111,7 @@ func (ct *Ciphertext) UnmarshalBinary(p []byte) (err error) {
|
||||
// Plaintext stores an RGSW plaintext value.
|
||||
type Plaintext rlwe.GadgetPlaintext
|
||||
|
||||
// NewPlaintext creates a new RGSW plaintext from value, which can be either uint64, int64 or *ring.Poly.
|
||||
// NewPlaintext creates a new RGSW plaintext from value, which can be either uint64, int64 or *[ring.Poly].
|
||||
// Plaintext is returned in the NTT and Montgomery domain.
|
||||
func NewPlaintext(params rlwe.Parameters, value interface{}, levelQ, levelP, BaseTwoDecomposition int) (*Plaintext, error) {
|
||||
gct, err := rlwe.NewGadgetPlaintext(params, value, levelQ, levelP, BaseTwoDecomposition)
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"github.com/tuneinsight/lattigo/v5/ring/ringqp"
|
||||
)
|
||||
|
||||
// Encryptor is a type for encrypting RGSW ciphertexts. It implements the rlwe.Encryptor
|
||||
// interface overriding the `Encrypt` and `EncryptZero` methods to accept rgsw.Ciphertext
|
||||
// Encryptor is a type for encrypting RGSW ciphertexts. It implements the [rlwe.Encryptor]
|
||||
// interface overriding the [rlwe.Encryptor.Encrypt] and [rlwe.Encryptor.EncryptZero] methods to accept [rgsw.Ciphertext]
|
||||
// types in addition to ciphertexts types in the rlwe package.
|
||||
type Encryptor struct {
|
||||
*rlwe.Encryptor
|
||||
@@ -19,7 +19,7 @@ func NewEncryptor(params rlwe.ParameterProvider, key rlwe.EncryptionKey) *Encryp
|
||||
return &Encryptor{rlwe.NewEncryptor(params, key), params.GetRLWEParameters().RingQP().NewPoly()}
|
||||
}
|
||||
|
||||
// Encrypt encrypts a plaintext pt into a ciphertext ct, which can be a rgsw.Ciphertext
|
||||
// Encrypt encrypts a plaintext pt into a ciphertext ct, which can be a [rgsw.Ciphertext]
|
||||
// or any of the `rlwe` cipheretxt types.
|
||||
func (enc Encryptor) Encrypt(pt *rlwe.Plaintext, ct interface{}) (err error) {
|
||||
|
||||
@@ -68,7 +68,7 @@ func (enc Encryptor) Encrypt(pt *rlwe.Plaintext, ct interface{}) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncryptZero generates an encryption of zero into a ciphertext ct, which can be a rgsw.Ciphertext
|
||||
// EncryptZero generates an encryption of zero into a ciphertext ct, which can be a [rgsw.Ciphertext]
|
||||
// or any of the `rlwe` cipheretxt types.
|
||||
func (enc Encryptor) EncryptZero(ct interface{}) (err error) {
|
||||
|
||||
@@ -99,7 +99,7 @@ func (enc Encryptor) EncryptZero(ct interface{}) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of this Encryptor in which all the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of this [Encryptor] in which all the read-only data-structures are
|
||||
// shared with the receiver and the temporary buffers are reallocated. The receiver and the returned
|
||||
// Encryptors can be used concurrently.
|
||||
func (enc Encryptor) ShallowCopy() *Encryptor {
|
||||
|
||||
@@ -8,25 +8,25 @@ import (
|
||||
|
||||
// Evaluator is a type for evaluating homomorphic operations involving RGSW ciphertexts.
|
||||
// It currently supports the external product between a RLWE and a RGSW ciphertext (see
|
||||
// Evaluator.ExternalProduct).
|
||||
// [Evaluator.ExternalProduct]).
|
||||
type Evaluator struct {
|
||||
rlwe.Evaluator
|
||||
}
|
||||
|
||||
// NewEvaluator creates a new Evaluator type supporting RGSW operations in addition
|
||||
// to rlwe.Evaluator operations.
|
||||
// NewEvaluator creates a new [Evaluator] type supporting RGSW operations in addition
|
||||
// to [rlwe.Evaluator] operations.
|
||||
func NewEvaluator(params rlwe.ParameterProvider, evk rlwe.EvaluationKeySet) *Evaluator {
|
||||
return &Evaluator{*rlwe.NewEvaluator(params, evk)}
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of this Evaluator in which all the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of this [Evaluator] in which all the read-only data-structures are
|
||||
// shared with the receiver and the temporary buffers are reallocated. The receiver and the returned
|
||||
// Evaluators can be used concurrently.
|
||||
func (eval Evaluator) ShallowCopy() *Evaluator {
|
||||
return &Evaluator{*eval.Evaluator.ShallowCopy()}
|
||||
}
|
||||
|
||||
// WithKey creates a shallow copy of the receiver Evaluator for which the new EvaluationKey is evaluationKey
|
||||
// WithKey creates a shallow copy of the receiver [Evaluator] for which the evaluation key is set to the provided [rlwe.EvaluationKeySet]
|
||||
// and where the temporary buffers are shared. The receiver and the returned Evaluators cannot be used concurrently.
|
||||
func (eval Evaluator) WithKey(evk rlwe.EvaluationKeySet) *Evaluator {
|
||||
return &Evaluator{*eval.Evaluator.WithKey(evk)}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
// Package rgsw implements an RLWE-based GSW encryption and external product RLWE x RGSW -> RLWE.
|
||||
// RSGW ciphertexts are tuples of two rlwe.GadgetCiphertext encrypting (`m(X)`, s*m(X)).
|
||||
// RSGW ciphertexts are tuples of two [rlwe.GadgetCiphertext] encrypting (`m(X)`, s*m(X)).
|
||||
package rgsw
|
||||
|
||||
@@ -12,17 +12,17 @@ type Ciphertext struct {
|
||||
Element[ring.Poly]
|
||||
}
|
||||
|
||||
// NewCiphertext returns a new Ciphertext with zero values and an associated
|
||||
// NewCiphertext returns a new [Ciphertext] with zero values and an associated
|
||||
// MetaData set to the Parameters default value.
|
||||
func NewCiphertext(params ParameterProvider, degree int, level ...int) (ct *Ciphertext) {
|
||||
op := *NewElement(params, degree, level...)
|
||||
return &Ciphertext{op}
|
||||
}
|
||||
|
||||
// NewCiphertextAtLevelFromPoly constructs a new Ciphertext at a specific level
|
||||
// NewCiphertextAtLevelFromPoly constructs a new [Ciphertext] at a specific level
|
||||
// where the message is set to the passed poly. No checks are performed on poly and
|
||||
// the returned Ciphertext will share its backing array of coefficients.
|
||||
// Returned Ciphertext's MetaData is allocated but empty .
|
||||
// the returned [Ciphertext] will share its backing array of coefficients.
|
||||
// Returned [Ciphertext]'s MetaData is allocated but empty.
|
||||
func NewCiphertextAtLevelFromPoly(level int, poly []ring.Poly) (*Ciphertext, error) {
|
||||
|
||||
operand, err := NewElementAtLevelFromPoly(level, poly)
|
||||
@@ -36,7 +36,7 @@ func NewCiphertextAtLevelFromPoly(level int, poly []ring.Poly) (*Ciphertext, err
|
||||
return &Ciphertext{*operand}, nil
|
||||
}
|
||||
|
||||
// NewCiphertextRandom generates a new uniformly distributed Ciphertext of degree, level.
|
||||
// NewCiphertextRandom generates a new uniformly distributed [Ciphertext] of degree, level.
|
||||
func NewCiphertextRandom(prng sampling.PRNG, params ParameterProvider, degree, level int) (ciphertext *Ciphertext) {
|
||||
ciphertext = NewCiphertext(params, degree, level)
|
||||
PopulateElementRandom(prng, params, ciphertext.El())
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/tuneinsight/lattigo/v5/utils"
|
||||
)
|
||||
|
||||
// Decryptor is a structure used to decrypt Ciphertext. It stores the secret-key.
|
||||
// Decryptor is a structure used to decrypt [Ciphertext]. It stores the secret-key.
|
||||
type Decryptor struct {
|
||||
params Parameters
|
||||
ringQ *ring.Ring
|
||||
@@ -15,7 +15,7 @@ type Decryptor struct {
|
||||
sk *SecretKey
|
||||
}
|
||||
|
||||
// NewDecryptor instantiates a new generic RLWE Decryptor.
|
||||
// NewDecryptor instantiates a new generic RLWE [Decryptor].
|
||||
func NewDecryptor(params ParameterProvider, sk *SecretKey) *Decryptor {
|
||||
|
||||
p := params.GetRLWEParameters()
|
||||
@@ -32,22 +32,22 @@ func NewDecryptor(params ParameterProvider, sk *SecretKey) *Decryptor {
|
||||
}
|
||||
}
|
||||
|
||||
// GetRLWEParameters returns the underlying rlwe.Parameters.
|
||||
// GetRLWEParameters returns the underlying [Parameters].
|
||||
func (d Decryptor) GetRLWEParameters() *Parameters {
|
||||
return &d.params
|
||||
}
|
||||
|
||||
// DecryptNew decrypts the Ciphertext and returns the result in a new Plaintext.
|
||||
// Output pt MetaData will match the input ct MetaData.
|
||||
// DecryptNew decrypts the [Ciphertext] and returns the result in a new [Plaintext].
|
||||
// Output pt [MetaData] will match the input ct [MetaData].
|
||||
func (d Decryptor) DecryptNew(ct *Ciphertext) (pt *Plaintext) {
|
||||
pt = NewPlaintext(d.params, ct.Level())
|
||||
d.Decrypt(ct, pt)
|
||||
return
|
||||
}
|
||||
|
||||
// Decrypt decrypts the Ciphertext and writes the result in pt.
|
||||
// The level of the output Plaintext is min(ct.Level(), pt.Level())
|
||||
// Output pt MetaData will match the input ct MetaData.
|
||||
// Decrypt decrypts the [Ciphertext] and writes the result in pt.
|
||||
// The level of the output [Plaintext] is min(ct.Level(), pt.Level())
|
||||
// Output pt [MetaData] will match the input ct [MetaData].
|
||||
func (d Decryptor) Decrypt(ct *Ciphertext, pt *Plaintext) {
|
||||
|
||||
level := utils.Min(ct.Level(), pt.Level())
|
||||
@@ -89,9 +89,9 @@ func (d Decryptor) Decrypt(ct *Ciphertext, pt *Plaintext) {
|
||||
}
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of Decryptor in which all the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of [Decryptor] in which all the read-only data-structures are
|
||||
// shared with the receiver and the temporary buffers are reallocated. The receiver and the returned
|
||||
// Decryptor can be used concurrently.
|
||||
// [Decryptor] can be used concurrently.
|
||||
func (d Decryptor) ShallowCopy() *Decryptor {
|
||||
return &Decryptor{
|
||||
params: d.params,
|
||||
@@ -101,9 +101,9 @@ func (d Decryptor) ShallowCopy() *Decryptor {
|
||||
}
|
||||
}
|
||||
|
||||
// WithKey creates a shallow copy of Decryptor with a new decryption key, in which all the
|
||||
// WithKey creates a shallow copy of [Decryptor] with a new decryption key, in which all the
|
||||
// read-only data-structures are shared with the receiver and the temporary buffers
|
||||
// are reallocated. The receiver and the returned Decryptor can be used concurrently.
|
||||
// are reallocated. The receiver and the returned [Decryptor] can be used concurrently.
|
||||
func (d Decryptor) WithKey(sk *SecretKey) *Decryptor {
|
||||
return &Decryptor{
|
||||
params: d.params,
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"github.com/tuneinsight/lattigo/v5/utils/structs"
|
||||
)
|
||||
|
||||
// ElementInterface is a common interface for Ciphertext and Plaintext types.
|
||||
// ElementInterface is a common interface for [Ciphertext] and [Plaintext] types.
|
||||
type ElementInterface[T ring.Poly | ringqp.Poly] interface {
|
||||
El() *Element[T]
|
||||
Degree() int
|
||||
@@ -71,10 +71,10 @@ func NewElementExtended(params ParameterProvider, degree, levelQ, levelP int) *E
|
||||
}
|
||||
}
|
||||
|
||||
// NewElementAtLevelFromPoly constructs a new Element at a specific level
|
||||
// NewElementAtLevelFromPoly constructs a new [Element] at a specific level
|
||||
// where the message is set to the passed poly. No checks are performed on poly and
|
||||
// the returned Element will share its backing array of coefficients.
|
||||
// Returned Element's MetaData is nil.
|
||||
// the returned [Element] will share its backing array of coefficients.
|
||||
// Returned [Element]'s [MetaData] is nil.
|
||||
func NewElementAtLevelFromPoly(level int, poly []ring.Poly) (*Element[ring.Poly], error) {
|
||||
Value := make([]ring.Poly, len(poly))
|
||||
for i := range Value {
|
||||
@@ -94,12 +94,12 @@ func (op Element[T]) Equal(other *Element[T]) bool {
|
||||
return cmp.Equal(op.MetaData, other.MetaData) && cmp.Equal(op.Value, other.Value)
|
||||
}
|
||||
|
||||
// Degree returns the degree of the target Element.
|
||||
// Degree returns the degree of the target element.
|
||||
func (op Element[T]) Degree() int {
|
||||
return len(op.Value) - 1
|
||||
}
|
||||
|
||||
// Level returns the level of the target Element.
|
||||
// Level returns the level of the target element.
|
||||
func (op Element[T]) Level() int {
|
||||
return op.LevelQ()
|
||||
}
|
||||
@@ -212,7 +212,7 @@ func GetSmallestLargest[T ring.Poly | ringqp.Poly](el0, el1 *Element[T]) (smalle
|
||||
return el0, el1, true
|
||||
}
|
||||
|
||||
// PopulateElementRandom creates a new rlwe.Element with random coefficients.
|
||||
// PopulateElementRandom creates a new [Element] with random coefficients.
|
||||
func PopulateElementRandom(prng sampling.PRNG, params ParameterProvider, ct *Element[ring.Poly]) {
|
||||
sampler := ring.NewUniformSampler(prng, params.GetRLWEParameters().RingQ()).AtLevel(ct.Level())
|
||||
for i := range ct.Value {
|
||||
@@ -299,15 +299,15 @@ func (op Element[T]) BinarySize() (size int) {
|
||||
return size + op.Value.BinarySize()
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// WriteTo writes the object on an [io.Writer]. It implements the [io.WriterTo]
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
//
|
||||
// Unless w implements the buffer.Writer interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a bufio.Writer. Since this requires allocations, it
|
||||
// is preferable to pass a buffer.Writer directly:
|
||||
// Unless w implements the [buffer.Writer] interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a [bufio.Writer]. Since this requires allocations, it
|
||||
// is preferable to pass a [buffer.Writer] directly:
|
||||
//
|
||||
// - When writing multiple times to a io.Writer, it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// - When writing multiple times to a [io.Writer], it is preferable to first wrap the
|
||||
// [io.Writer] in a pre-allocated [bufio.Writer].
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (op Element[T]) WriteTo(w io.Writer) (n int64, err error) {
|
||||
@@ -348,15 +348,15 @@ func (op Element[T]) WriteTo(w io.Writer) (n int64, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// - When reading multiple values from a [io.Reader], it is preferable to first
|
||||
// first wrap [io.Reader] in a pre-allocated [bufio.Reader].
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (op *Element[T]) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
@@ -408,7 +408,7 @@ func (op Element[T]) MarshalBinary() (data []byte, err error) {
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
// [Element.MarshalBinary] or [Element.WriteTo] on the object.
|
||||
func (op *Element[T]) UnmarshalBinary(p []byte) (err error) {
|
||||
_, err = op.ReadFrom(buffer.NewBuffer(p))
|
||||
return
|
||||
|
||||
@@ -11,12 +11,12 @@ import (
|
||||
)
|
||||
|
||||
// EncryptionKey is an interface for encryption keys. Valid encryption
|
||||
// keys are the SecretKey and PublicKey types.
|
||||
// keys are the [SecretKey] and [PublicKey] types.
|
||||
type EncryptionKey interface {
|
||||
isEncryptionKey()
|
||||
}
|
||||
|
||||
// NewEncryptor creates a new Encryptor from either a public key or a private key.
|
||||
// NewEncryptor creates a new [Encryptor] from either a public key or a private key.
|
||||
func NewEncryptor(params ParameterProvider, key EncryptionKey) *Encryptor {
|
||||
|
||||
p := *params.GetRLWEParameters()
|
||||
@@ -56,7 +56,7 @@ type Encryptor struct {
|
||||
uniformSampler ringqp.UniformSampler
|
||||
}
|
||||
|
||||
// GetRLWEParameters returns the underlying rlwe.Parameters.
|
||||
// GetRLWEParameters returns the underlying [Parameters].
|
||||
func (enc Encryptor) GetRLWEParameters() *Parameters {
|
||||
return &enc.params
|
||||
}
|
||||
@@ -123,10 +123,10 @@ func newEncryptorBuffers(params Parameters) *encryptorBuffers {
|
||||
}
|
||||
|
||||
// Encrypt encrypts the input plaintext using the stored encryption key and writes the result on ct.
|
||||
// The method currently accepts only *rlwe.Ciphertext as ct.
|
||||
// If a Plaintext is given, then the output Ciphertext MetaData will match the Plaintext MetaData.
|
||||
// The method currently accepts only *[Ciphertext] as ct.
|
||||
// If a [Plaintext] is given, then the output [Ciphertext] [MetaData] will match the [Plaintext] [MetaData].
|
||||
// The method returns an error if the ct has an unsupported type or if no encryption key is stored
|
||||
// in the Encryptor.
|
||||
// in the [Encryptor].
|
||||
//
|
||||
// The encryption procedure masks the plaintext by adding a fresh encryption of zero.
|
||||
// The encryption procedure depends on the parameters: If the auxiliary modulus P is defined, the
|
||||
@@ -152,10 +152,10 @@ func (enc Encryptor) Encrypt(pt *Plaintext, ct interface{}) (err error) {
|
||||
}
|
||||
|
||||
// EncryptNew encrypts the input plaintext using the stored encryption key and returns a newly
|
||||
// allocated Ciphertext containing the result.
|
||||
// If a Plaintext is provided, then the output ciphertext MetaData will match the Plaintext MetaData.
|
||||
// allocated [Ciphertext] containing the result.
|
||||
// If a [Plaintext] is provided, then the output [Ciphertext] [MetaData] will match the [Plaintext] [MetaData].
|
||||
// The method returns an error if the ct has an unsupported type or if no encryption key is stored
|
||||
// in the Encryptor.
|
||||
// in the [Encryptor].
|
||||
//
|
||||
// The encryption procedure masks the plaintext by adding a fresh encryption of zero.
|
||||
// The encryption procedure depends on the parameters: If the auxiliary modulus P is defined, the
|
||||
@@ -166,13 +166,13 @@ func (enc Encryptor) EncryptNew(pt *Plaintext) (ct *Ciphertext, err error) {
|
||||
}
|
||||
|
||||
// EncryptZero generates an encryption of zero under the stored encryption key and writes the result on ct.
|
||||
// The method accepts only *rlwe.Ciphertext as input.
|
||||
// The method accepts only *[Ciphertext] as input.
|
||||
// The method returns an error if the ct has an unsupported type or if no encryption key is stored
|
||||
// in the Encryptor.
|
||||
// in the [Encryptor].
|
||||
//
|
||||
// The encryption procedure depends on the parameters: If the auxiliary modulus P is defined, the
|
||||
// encryption of zero is sampled in QP before being rescaled by P; otherwise, it is directly sampled in Q.
|
||||
// The zero encryption is generated according to the given Ciphertext MetaData.
|
||||
// The zero encryption is generated according to the given [Ciphertext] [MetaData].
|
||||
func (enc Encryptor) EncryptZero(ct interface{}) (err error) {
|
||||
switch key := enc.encKey.(type) {
|
||||
case *SecretKey:
|
||||
@@ -188,8 +188,8 @@ func (enc Encryptor) EncryptZero(ct interface{}) (err error) {
|
||||
}
|
||||
|
||||
// EncryptZeroNew generates an encryption of zero under the stored encryption key and returns a newly
|
||||
// allocated Ciphertext containing the result.
|
||||
// The method returns an error if no encryption key is stored in the Encryptor.
|
||||
// allocated [Ciphertext] containing the result.
|
||||
// The method returns an error if no encryption key is stored in the [Encryptor].
|
||||
// The encryption procedure depends on the parameters: If the auxiliary modulus P is defined, the
|
||||
// encryption of zero is sampled in QP before being rescaled by P; otherwise, it is directly sampled in Q.
|
||||
func (enc Encryptor) EncryptZeroNew(level int) (ct *Ciphertext) {
|
||||
|
||||
@@ -60,7 +60,7 @@ func NewEvaluatorBuffers(params Parameters) *EvaluatorBuffers {
|
||||
return buff
|
||||
}
|
||||
|
||||
// NewEvaluator creates a new Evaluator.
|
||||
// NewEvaluator creates a new [Evaluator].
|
||||
func NewEvaluator(params ParameterProvider, evk EvaluationKeySet) (eval *Evaluator) {
|
||||
eval = new(Evaluator)
|
||||
p := params.GetRLWEParameters()
|
||||
@@ -103,7 +103,7 @@ func (eval *Evaluator) GetRLWEParameters() *Parameters {
|
||||
return &eval.params
|
||||
}
|
||||
|
||||
// CheckAndGetGaloisKey returns an error if the GaloisKey for the given Galois element is missing or the EvaluationKey interface is nil.
|
||||
// CheckAndGetGaloisKey returns an error if the [GaloisKey] for the given Galois element is missing or the [EvaluationKey] interface is nil.
|
||||
func (eval Evaluator) CheckAndGetGaloisKey(galEl uint64) (evk *GaloisKey, err error) {
|
||||
if eval.EvaluationKeySet != nil {
|
||||
if evk, err = eval.GetGaloisKey(galEl); err != nil {
|
||||
@@ -127,7 +127,7 @@ func (eval Evaluator) CheckAndGetGaloisKey(galEl uint64) (evk *GaloisKey, err er
|
||||
return
|
||||
}
|
||||
|
||||
// CheckAndGetRelinearizationKey returns an error if the RelinearizationKey is missing or the EvaluationKey interface is nil.
|
||||
// CheckAndGetRelinearizationKey returns an error if the [RelinearizationKey] is missing or the [EvaluationKey] interface is nil.
|
||||
func (eval Evaluator) CheckAndGetRelinearizationKey() (evk *RelinearizationKey, err error) {
|
||||
if eval.EvaluationKeySet != nil {
|
||||
if evk, err = eval.GetRelinearizationKey(); err != nil {
|
||||
@@ -140,14 +140,14 @@ func (eval Evaluator) CheckAndGetRelinearizationKey() (evk *RelinearizationKey,
|
||||
return
|
||||
}
|
||||
|
||||
// InitOutputBinaryOp initializes the output Element opOut for receiving the result of a binary operation over
|
||||
// InitOutputBinaryOp initializes the output [Element] opOut for receiving the result of a binary operation over
|
||||
// op0 and op1. The method also performs the following checks:
|
||||
//
|
||||
// 1. Inputs are not nil
|
||||
// 2. MetaData are not nil
|
||||
// 3. op0.Degree() + op1.Degree() != 0 (i.e at least one Element is a ciphertext)
|
||||
// 4. op0.IsNTT == op1.IsNTT == DefaultNTTFlag
|
||||
// 5. op0.IsBatched == op1.IsBatched
|
||||
// 1. Inputs are not nil
|
||||
// 2. MetaData are not nil
|
||||
// 3. op0.Degree() + op1.Degree() != 0 (i.e at least one [Element] is a ciphertext)
|
||||
// 4. op0.IsNTT == op1.IsNTT == DefaultNTTFlag
|
||||
// 5. op0.IsBatched == op1.IsBatched
|
||||
//
|
||||
// The opOut metadata are initilized as:
|
||||
// IsNTT <- DefaultNTTFlag
|
||||
@@ -198,12 +198,12 @@ func (eval Evaluator) InitOutputBinaryOp(op0, op1 *Element[ring.Poly], opInTotal
|
||||
return
|
||||
}
|
||||
|
||||
// InitOutputUnaryOp initializes the output Element opOut for receiving the result of a unary operation over
|
||||
// InitOutputUnaryOp initializes the output [Element] opOut for receiving the result of a unary operation over
|
||||
// op0. The method also performs the following checks:
|
||||
//
|
||||
// 1. Input and output are not nil
|
||||
// 2. Inoutp and output Metadata are not nil
|
||||
// 2. op0.IsNTT == DefaultNTTFlag
|
||||
// 1. Input and output are not nil
|
||||
// 2. Inoutp and output Metadata are not nil
|
||||
// 3. op0.IsNTT == DefaultNTTFlag
|
||||
//
|
||||
// The method will also update the metadata of opOut:
|
||||
//
|
||||
@@ -234,9 +234,9 @@ func (eval Evaluator) InitOutputUnaryOp(op0, opOut *Element[ring.Poly]) (degree,
|
||||
return utils.Max(op0.Degree(), opOut.Degree()), utils.Min(op0.Level(), opOut.Level()), nil
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of this Evaluator in which all the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of this [Evaluator] in which all the read-only data-structures are
|
||||
// shared with the receiver and the temporary buffers are reallocated. The receiver and the returned
|
||||
// Evaluators can be used concurrently.
|
||||
// evaluators can be used concurrently.
|
||||
func (eval Evaluator) ShallowCopy() *Evaluator {
|
||||
return &Evaluator{
|
||||
params: eval.params,
|
||||
@@ -248,8 +248,8 @@ func (eval Evaluator) ShallowCopy() *Evaluator {
|
||||
}
|
||||
}
|
||||
|
||||
// WithKey creates a shallow copy of the receiver Evaluator for which the new EvaluationKey is evaluationKey
|
||||
// and where the temporary buffers are shared. The receiver and the returned Evaluators cannot be used concurrently.
|
||||
// WithKey creates a shallow copy of the receiver [Evaluator] for which the new [EvaluationKey] is evaluationKey
|
||||
// and where the temporary buffers are shared. The receiver and the returned evaluators cannot be used concurrently.
|
||||
func (eval Evaluator) WithKey(evk EvaluationKeySet) *Evaluator {
|
||||
|
||||
var AutomorphismIndex map[uint64][]uint64
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
// Automorphism computes phi(ct), where phi is the map X -> X^galEl. The method requires
|
||||
// that the corresponding RotationKey has been added to the Evaluator. The method will
|
||||
// that the corresponding RotationKey has been added to the [Evaluator]. The method will
|
||||
// return an error if either ctIn or opOut degree is not equal to 1.
|
||||
func (eval Evaluator) Automorphism(ctIn *Ciphertext, galEl uint64, opOut *Ciphertext) (err error) {
|
||||
|
||||
@@ -55,9 +55,9 @@ func (eval Evaluator) Automorphism(ctIn *Ciphertext, galEl uint64, opOut *Cipher
|
||||
return
|
||||
}
|
||||
|
||||
// AutomorphismHoisted is similar to Automorphism, except that it takes as input ctIn and c1DecompQP, where c1DecompQP is the RNS
|
||||
// decomposition of its element of degree 1. This decomposition can be obtained with DecomposeNTT.
|
||||
// The method requires that the corresponding RotationKey has been added to the Evaluator.
|
||||
// AutomorphismHoisted is similar to [Evaluator.Automorphism], except that it takes as input ctIn and c1DecompQP, where c1DecompQP is the RNS
|
||||
// decomposition of its element of degree 1. This decomposition can be obtained with [Evaluator.DecomposeNTT].
|
||||
// The method requires that the corresponding RotationKey has been added to the [Evaluator].
|
||||
// The method will return an error if either ctIn or opOut degree is not equal to 1.
|
||||
func (eval Evaluator) AutomorphismHoisted(level int, ctIn *Ciphertext, c1DecompQP []ringqp.Poly, galEl uint64, opOut *Ciphertext) (err error) {
|
||||
|
||||
@@ -101,8 +101,8 @@ func (eval Evaluator) AutomorphismHoisted(level int, ctIn *Ciphertext, c1DecompQ
|
||||
return
|
||||
}
|
||||
|
||||
// AutomorphismHoistedLazy is similar to AutomorphismHoisted, except that it returns a ciphertext modulo QP and scaled by P.
|
||||
// The method requires that the corresponding RotationKey has been added to the Evaluator.
|
||||
// AutomorphismHoistedLazy is similar to [Evaluator.AutomorphismHoisted], except that it returns a ciphertext modulo QP and scaled by P.
|
||||
// The method requires that the corresponding RotationKey has been added to the [Evaluator].
|
||||
// Result NTT domain is returned according to the NTT flag of ctQP.
|
||||
func (eval Evaluator) AutomorphismHoistedLazy(levelQ int, ctIn *Ciphertext, c1DecompQP []ringqp.Poly, galEl uint64, ctQP *Element[ringqp.Poly]) (err error) {
|
||||
|
||||
|
||||
@@ -7,12 +7,12 @@ import (
|
||||
"github.com/tuneinsight/lattigo/v5/utils"
|
||||
)
|
||||
|
||||
// ApplyEvaluationKey is a generic method to apply an EvaluationKey on a ciphertext.
|
||||
// ApplyEvaluationKey is a generic method to apply an [EvaluationKey] on a ciphertext.
|
||||
// An EvaluationKey is a type of public key that is be used during the evaluation of
|
||||
// a homomorphic circuit to provide additional functionalities, like relinearization
|
||||
// or rotations.
|
||||
//
|
||||
// In a nutshell, an Evaluationkey encrypts a secret skIn under a secret skOut and
|
||||
// In a nutshell, an [EvaluationKey] encrypts a secret skIn under a secret skOut and
|
||||
// enables the public and non interactive re-encryption of any ciphertext encrypted
|
||||
// under skIn to a new ciphertext encrypted under skOut.
|
||||
//
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
// Note that the parameters of the smaller ring degree must be the same or a subset of the
|
||||
// moduli Q and P of the one for the larger ring degree.
|
||||
//
|
||||
// To do so, it must be provided with the appropriate EvaluationKey, and have the operands
|
||||
// To do so, it must be provided with the appropriate [EvaluationKey], and have the operands
|
||||
// matching the target ring degrees.
|
||||
//
|
||||
// To switch a ciphertext to a smaller ring degree:
|
||||
|
||||
@@ -20,9 +20,9 @@ type GadgetCiphertext struct {
|
||||
Value structs.Matrix[VectorQP]
|
||||
}
|
||||
|
||||
// NewGadgetCiphertext returns a new Ciphertext key with pre-allocated zero-value.
|
||||
// Ciphertext is always in the NTT domain.
|
||||
// A GadgetCiphertext is created by default at degree 1 with the the maximum levelQ and levelP and with no base 2 decomposition.
|
||||
// NewGadgetCiphertext returns a new [GadgetCiphertext] key with pre-allocated zero-value.
|
||||
// [GadgetCiphertext] is always in the NTT domain.
|
||||
// A [GadgetCiphertext] is created by default at degree 1 with the the maximum levelQ and levelP and with no base 2 decomposition.
|
||||
// Give the optional GadgetCiphertextParameters struct to create a GadgetCiphertext with at a specific degree, levelQ, levelP and/or base 2 decomposition.
|
||||
func NewGadgetCiphertext(params ParameterProvider, Degree, LevelQ, LevelP, BaseTwoDecomposition int) *GadgetCiphertext {
|
||||
|
||||
@@ -42,12 +42,12 @@ func NewGadgetCiphertext(params ParameterProvider, Degree, LevelQ, LevelP, BaseT
|
||||
return &GadgetCiphertext{BaseTwoDecomposition: BaseTwoDecomposition, Value: m}
|
||||
}
|
||||
|
||||
// LevelQ returns the level of the modulus Q of the target Ciphertext.
|
||||
// LevelQ returns the level of the modulus Q of the target ciphertext.
|
||||
func (ct GadgetCiphertext) LevelQ() int {
|
||||
return ct.Value[0][0][0].LevelQ()
|
||||
}
|
||||
|
||||
// LevelP returns the level of the modulus P of the target Ciphertext.
|
||||
// LevelP returns the level of the modulus P of the target ciphertext.
|
||||
func (ct GadgetCiphertext) LevelP() int {
|
||||
return ct.Value[0][0][0].LevelP()
|
||||
}
|
||||
@@ -57,7 +57,7 @@ func (ct GadgetCiphertext) BaseRNSDecompositionVectorSize() int {
|
||||
return len(ct.Value)
|
||||
}
|
||||
|
||||
// BaseTwoDecompositionVectorSize returns the number of element in the Power of two decomposition basis for each prime of Q.
|
||||
// BaseTwoDecompositionVectorSize returns the number of element in the power of two decomposition basis for each prime of Q.
|
||||
func (ct GadgetCiphertext) BaseTwoDecompositionVectorSize() (base []int) {
|
||||
base = make([]int, len(ct.Value))
|
||||
for i := range ct.Value {
|
||||
@@ -66,12 +66,12 @@ func (ct GadgetCiphertext) BaseTwoDecompositionVectorSize() (base []int) {
|
||||
return
|
||||
}
|
||||
|
||||
// Equal checks two Ciphertexts for equality.
|
||||
// Equal checks two ciphertexts for equality.
|
||||
func (ct GadgetCiphertext) Equal(other *GadgetCiphertext) bool {
|
||||
return (ct.BaseTwoDecomposition == other.BaseTwoDecomposition) && cmp.Equal(ct.Value, other.Value)
|
||||
}
|
||||
|
||||
// CopyNew creates a deep copy of the receiver Ciphertext and returns it.
|
||||
// CopyNew creates a deep copy of the receiver ciphertext and returns it.
|
||||
func (ct GadgetCiphertext) CopyNew() (ctCopy *GadgetCiphertext) {
|
||||
return &GadgetCiphertext{BaseTwoDecomposition: ct.BaseTwoDecomposition, Value: ct.Value.CopyNew()}
|
||||
}
|
||||
@@ -81,15 +81,15 @@ func (ct GadgetCiphertext) BinarySize() (dataLen int) {
|
||||
return 8 + ct.Value.BinarySize()
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// WriteTo writes the object on an [io.Writer]. It implements the [io.WriterTo]
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
//
|
||||
// Unless w implements the buffer.Writer interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a bufio.Writer. Since this requires allocations, it
|
||||
// is preferable to pass a buffer.Writer directly:
|
||||
// Unless w implements the [buffer.Writer] interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a [bufio.Writer]. Since this requires allocations, it
|
||||
// is preferable to pass a [buffer.Writer] directly:
|
||||
//
|
||||
// - When writing multiple times to a io.Writer, it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// - When writing multiple times to a [io.Writer], it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated [bufio.Writer].
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (ct GadgetCiphertext) WriteTo(w io.Writer) (n int64, err error) {
|
||||
@@ -114,15 +114,15 @@ func (ct GadgetCiphertext) WriteTo(w io.Writer) (n int64, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// [io.ReaderFrom] interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a [buffer.Reader] directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// - When reading multiple values from a [io.Reader], it is preferable to first
|
||||
// first wrap [io.Reader] in a pre-allocated [bufio.Reader].
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (ct *GadgetCiphertext) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
@@ -154,14 +154,14 @@ func (ct GadgetCiphertext) MarshalBinary() (data []byte, err error) {
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
// [GadgetCiphertext.MarshalBinary] or [GadgetCiphertext.WriteTo] on the object.
|
||||
func (ct *GadgetCiphertext) UnmarshalBinary(p []byte) (err error) {
|
||||
_, err = ct.ReadFrom(buffer.NewBuffer(p))
|
||||
return
|
||||
}
|
||||
|
||||
// AddPolyTimesGadgetVectorToGadgetCiphertext takes a plaintext polynomial and a list of Ciphertexts and adds the
|
||||
// plaintext times the RNS and BIT decomposition to the i-th element of the i-th Ciphertexts. This method return
|
||||
// AddPolyTimesGadgetVectorToGadgetCiphertext takes a plaintext polynomial and a list of [GadgetCiphertext] and adds the
|
||||
// plaintext times the RNS and BIT decomposition to the i-th element of the i-th ciphertexts. This method return
|
||||
// an error if len(cts) > 2.
|
||||
func AddPolyTimesGadgetVectorToGadgetCiphertext(pt ring.Poly, cts []GadgetCiphertext, ringQP ringqp.Ring, buff ring.Poly) (err error) {
|
||||
|
||||
@@ -239,7 +239,7 @@ type GadgetPlaintext struct {
|
||||
Value structs.Vector[ring.Poly]
|
||||
}
|
||||
|
||||
// NewGadgetPlaintext creates a new gadget plaintext from value, which can be either uint64, int64 or *ring.Poly.
|
||||
// NewGadgetPlaintext creates a new [GadgetPlaintext] from value, which can be either uint64, int64 or *[ring.Poly].
|
||||
// Plaintext is returned in the NTT and Montgomery domain.
|
||||
func NewGadgetPlaintext(params Parameters, value interface{}, levelQ, levelP, baseTwoDecomposition int) (pt *GadgetPlaintext, err error) {
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@ import (
|
||||
"github.com/tuneinsight/lattigo/v5/utils"
|
||||
)
|
||||
|
||||
// InnerSum applies an optimized inner sum on the Ciphertext (log2(n) + HW(n) rotations with double hoisting).
|
||||
// InnerSum applies an optimized inner sum on the [Ciphertext] (log2(n) + HW(n) rotations with double hoisting).
|
||||
// The operation assumes that `ctIn` encrypts Slots/`batchSize` sub-vectors of size `batchSize` and will add them together (in parallel) in groups of `n`.
|
||||
// It outputs in opOut a Ciphertext for which the "leftmost" sub-vector of each group is equal to the sum of the group.
|
||||
// It outputs in opOut a [Ciphertext] for which the "leftmost" sub-vector of each group is equal to the sum of the group.
|
||||
//
|
||||
// The inner sum is computed in a tree fashion. Example for batchSize=2 & n=4 (garbage slots are marked by 'x'):
|
||||
//
|
||||
// 1) [{a, b}, {c, d}, {e, f}, {g, h}, {a, b}, {c, d}, {e, f}, {g, h}]
|
||||
// 1. [{a, b}, {c, d}, {e, f}, {g, h}, {a, b}, {c, d}, {e, f}, {g, h}]
|
||||
//
|
||||
// 2. [{a, b}, {c, d}, {e, f}, {g, h}, {a, b}, {c, d}, {e, f}, {g, h}]
|
||||
// +
|
||||
@@ -163,16 +163,17 @@ func (eval Evaluator) InnerSum(ctIn *Ciphertext, batchSize, n int, opOut *Cipher
|
||||
return
|
||||
}
|
||||
|
||||
// InnerFunction applies an user defined function on the Ciphertext with a tree-like combination requiring log2(n) + HW(n) rotations.
|
||||
// InnerFunction applies an user defined function on the [Ciphertext] with a tree-like combination requiring log2(n) + HW(n) rotations.
|
||||
//
|
||||
// InnerFunction with f = eval.Add(a, b, c) is equivalent to InnerSum (although slightly slower).
|
||||
// InnerFunction with f = eval.Add(a, b, c) is equivalent to [Evaluator.InnerSum] (although slightly slower).
|
||||
//
|
||||
// The operation assumes that `ctIn` encrypts Slots/`batchSize` sub-vectors of size `batchSize` and will add them together (in parallel) in groups of `n`.
|
||||
// It outputs in opOut a Ciphertext for which the "leftmost" sub-vector of each group is equal to the pair-wise recursive evaluation of function over the group.
|
||||
// It outputs in opOut a [Ciphertext] for which the "leftmost" sub-vector of each group is equal to the pair-wise recursive evaluation of
|
||||
// function over the group.
|
||||
//
|
||||
// The inner function is computed in a tree fashion. Example for batchSize=2 & n=4 (garbage slots are marked by 'x'):
|
||||
//
|
||||
// 1) [{a, b}, {c, d}, {e, f}, {g, h}, {a, b}, {c, d}, {e, f}, {g, h}]
|
||||
// 1. [{a, b}, {c, d}, {e, f}, {g, h}, {a, b}, {c, d}, {e, f}, {g, h}]
|
||||
//
|
||||
// 2. [{a, b}, {c, d}, {e, f}, {g, h}, {a, b}, {c, d}, {e, f}, {g, h}]
|
||||
// f
|
||||
@@ -312,7 +313,7 @@ func (eval Evaluator) InnerFunction(ctIn *Ciphertext, batchSize, n int, f func(a
|
||||
}
|
||||
|
||||
// GaloisElementsForInnerSum returns the list of Galois elements necessary to apply the method
|
||||
// `InnerSum` operation with parameters `batch` and `n`.
|
||||
// [Evaluator.InnerSum] operation with parameters batch and n.
|
||||
func GaloisElementsForInnerSum(params ParameterProvider, batch, n int) (galEls []uint64) {
|
||||
|
||||
rotIndex := make(map[int]bool)
|
||||
@@ -339,19 +340,19 @@ func GaloisElementsForInnerSum(params ParameterProvider, batch, n int) (galEls [
|
||||
return params.GetRLWEParameters().GaloisElements(rotations)
|
||||
}
|
||||
|
||||
// Replicate applies an optimized replication on the Ciphertext (log2(n) + HW(n) rotations with double hoisting).
|
||||
// Replicate applies an optimized replication on the [Ciphertext] (log2(n) + HW(n) rotations with double hoisting).
|
||||
// It acts as the inverse of a inner sum (summing elements from left to right).
|
||||
// The replication is parameterized by the size of the sub-vectors to replicate "batchSize" and
|
||||
// the number of times 'n' they need to be replicated.
|
||||
// The replication is parameterized by the size of the sub-vectors to replicate batchSize and
|
||||
// the number of times n they need to be replicated.
|
||||
// To ensure correctness, a gap of zero values of size batchSize * (n-1) must exist between
|
||||
// two consecutive sub-vectors to replicate.
|
||||
// This method is faster than Replicate when the number of rotations is large and it uses log2(n) + HW(n) instead of 'n'.
|
||||
// This method is faster than Replicate when the number of rotations is large and it uses log2(n) + HW(n) instead of n.
|
||||
func (eval Evaluator) Replicate(ctIn *Ciphertext, batchSize, n int, opOut *Ciphertext) (err error) {
|
||||
return eval.InnerSum(ctIn, -batchSize, n, opOut)
|
||||
}
|
||||
|
||||
// GaloisElementsForReplicate returns the list of Galois elements necessary to perform the
|
||||
// `Replicate` operation with parameters `batch` and `n`.
|
||||
// [Evaluator.Replicate] operation with parameters batch and n.
|
||||
func GaloisElementsForReplicate(params ParameterProvider, batch, n int) (galEls []uint64) {
|
||||
return GaloisElementsForInnerSum(params, -batch, n)
|
||||
}
|
||||
|
||||
@@ -14,35 +14,35 @@ type KeyGenerator struct {
|
||||
*Encryptor
|
||||
}
|
||||
|
||||
// NewKeyGenerator creates a new KeyGenerator, from which the secret and public keys, as well as EvaluationKeys.
|
||||
// NewKeyGenerator creates a new KeyGenerator, from which the secret and public keys, as well as [EvaluationKey].
|
||||
func NewKeyGenerator(params ParameterProvider) *KeyGenerator {
|
||||
return &KeyGenerator{
|
||||
Encryptor: NewEncryptor(params, nil),
|
||||
}
|
||||
}
|
||||
|
||||
// GenSecretKeyNew generates a new SecretKey.
|
||||
// Distribution is set according to `rlwe.Parameters.HammingWeight()`.
|
||||
// GenSecretKeyNew generates a new [SecretKey].
|
||||
// Distribution is set according to [rlwe.Parameters.HammingWeight].
|
||||
func (kgen KeyGenerator) GenSecretKeyNew() (sk *SecretKey) {
|
||||
sk = NewSecretKey(kgen.params)
|
||||
kgen.GenSecretKey(sk)
|
||||
return
|
||||
}
|
||||
|
||||
// GenSecretKey generates a SecretKey.
|
||||
// Distribution is set according to `rlwe.Parameters.HammingWeight()`.
|
||||
// GenSecretKey generates a [SecretKey].
|
||||
// Distribution is set according to [rlwe.Parameters.HammingWeight].
|
||||
func (kgen KeyGenerator) GenSecretKey(sk *SecretKey) {
|
||||
kgen.genSecretKeyFromSampler(kgen.xsSampler, sk)
|
||||
}
|
||||
|
||||
// GenSecretKeyWithHammingWeightNew generates a new SecretKey with exactly hw non-zero coefficients.
|
||||
// GenSecretKeyWithHammingWeightNew generates a new [SecretKey] with exactly hw non-zero coefficients.
|
||||
func (kgen *KeyGenerator) GenSecretKeyWithHammingWeightNew(hw int) (sk *SecretKey) {
|
||||
sk = NewSecretKey(kgen.params)
|
||||
kgen.GenSecretKeyWithHammingWeight(hw, sk)
|
||||
return
|
||||
}
|
||||
|
||||
// GenSecretKeyWithHammingWeight generates a SecretKey with exactly hw non-zero coefficients.
|
||||
// GenSecretKeyWithHammingWeight generates a [SecretKey] with exactly hw non-zero coefficients.
|
||||
func (kgen KeyGenerator) GenSecretKeyWithHammingWeight(hw int, sk *SecretKey) {
|
||||
Xs, err := ring.NewSampler(kgen.prng, kgen.params.RingQ(), ring.Ternary{H: hw}, false)
|
||||
// Sanity check, this error should not happen.
|
||||
@@ -66,14 +66,14 @@ func (kgen KeyGenerator) genSecretKeyFromSampler(sampler ring.Sampler, sk *Secre
|
||||
ringQP.MForm(sk.Value, sk.Value)
|
||||
}
|
||||
|
||||
// GenPublicKeyNew generates a new public key from the provided SecretKey.
|
||||
// GenPublicKeyNew generates a new [PublicKey] from the provided [SecretKey].
|
||||
func (kgen KeyGenerator) GenPublicKeyNew(sk *SecretKey) (pk *PublicKey) {
|
||||
pk = NewPublicKey(kgen.params)
|
||||
kgen.GenPublicKey(sk, pk)
|
||||
return
|
||||
}
|
||||
|
||||
// GenPublicKey generates a public key from the provided SecretKey.
|
||||
// GenPublicKey generates a [PublicKey] from the provided [SecretKey].
|
||||
func (kgen KeyGenerator) GenPublicKey(sk *SecretKey, pk *PublicKey) {
|
||||
if err := kgen.WithKey(sk).EncryptZero(Element[ringqp.Poly]{
|
||||
MetaData: &MetaData{CiphertextMetaData: CiphertextMetaData{IsNTT: true, IsMontgomery: true}},
|
||||
@@ -84,15 +84,15 @@ func (kgen KeyGenerator) GenPublicKey(sk *SecretKey, pk *PublicKey) {
|
||||
}
|
||||
}
|
||||
|
||||
// GenKeyPairNew generates a new SecretKey and a corresponding public key.
|
||||
// Distribution is of the SecretKey set according to `rlwe.Parameters.HammingWeight()`.
|
||||
// GenKeyPairNew generates a new [SecretKey] and a corresponding [PublicKey].
|
||||
// Distribution of the [SecretKey] set according to [rlwe.Parameters.HammingWeight].
|
||||
func (kgen KeyGenerator) GenKeyPairNew() (sk *SecretKey, pk *PublicKey) {
|
||||
sk = kgen.GenSecretKeyNew()
|
||||
pk = kgen.GenPublicKeyNew(sk)
|
||||
return
|
||||
}
|
||||
|
||||
// GenRelinearizationKeyNew generates a new EvaluationKey that will be used to relinearize Ciphertexts during multiplication.
|
||||
// GenRelinearizationKeyNew generates a new [EvaluationKey] that will be used to relinearize [Ciphertexts] during multiplication.
|
||||
func (kgen KeyGenerator) GenRelinearizationKeyNew(sk *SecretKey, evkParams ...EvaluationKeyParameters) (rlk *RelinearizationKey) {
|
||||
levelQ, levelP, BaseTwoDecomposition := ResolveEvaluationKeyParameters(kgen.params, evkParams)
|
||||
rlk = &RelinearizationKey{EvaluationKey: EvaluationKey{GadgetCiphertext: *NewGadgetCiphertext(kgen.params, 1, levelQ, levelP, BaseTwoDecomposition)}}
|
||||
@@ -100,14 +100,14 @@ func (kgen KeyGenerator) GenRelinearizationKeyNew(sk *SecretKey, evkParams ...Ev
|
||||
return
|
||||
}
|
||||
|
||||
// GenRelinearizationKey generates an EvaluationKey that will be used to relinearize Ciphertexts during multiplication.
|
||||
// GenRelinearizationKey generates an [EvaluationKey] that will be used to relinearize [Ciphertexts] during multiplication.
|
||||
func (kgen KeyGenerator) GenRelinearizationKey(sk *SecretKey, rlk *RelinearizationKey) {
|
||||
kgen.buffQP.Q.CopyLvl(rlk.LevelQ(), sk.Value.Q)
|
||||
kgen.params.RingQ().AtLevel(rlk.LevelQ()).MulCoeffsMontgomery(kgen.buffQP.Q, sk.Value.Q, kgen.buffQP.Q)
|
||||
kgen.genEvaluationKey(kgen.buffQP.Q, sk.Value, &rlk.EvaluationKey)
|
||||
}
|
||||
|
||||
// GenGaloisKeyNew generates a new GaloisKey, enabling the automorphism X^{i} -> X^{i * galEl}.
|
||||
// GenGaloisKeyNew generates a new [GaloisKey], enabling the automorphism X^{i} -> X^{i * galEl}.
|
||||
func (kgen KeyGenerator) GenGaloisKeyNew(galEl uint64, sk *SecretKey, evkParams ...EvaluationKeyParameters) (gk *GaloisKey) {
|
||||
levelQ, levelP, BaseTwoDecomposition := ResolveEvaluationKeyParameters(kgen.params, evkParams)
|
||||
gk = &GaloisKey{
|
||||
@@ -155,7 +155,7 @@ func (kgen KeyGenerator) GenGaloisKey(galEl uint64, sk *SecretKey, gk *GaloisKey
|
||||
gk.NthRoot = ringQ.NthRoot()
|
||||
}
|
||||
|
||||
// GenGaloisKeys generates the GaloisKey objects for all galois elements in galEls, and stores
|
||||
// GenGaloisKeys generates the [GaloisKey] objects for all galois elements in galEls, and stores
|
||||
// the resulting key for galois element i in gks[i].
|
||||
// The galEls and gks parameters must have the same length.
|
||||
func (kgen KeyGenerator) GenGaloisKeys(galEls []uint64, sk *SecretKey, gks []*GaloisKey) {
|
||||
@@ -174,8 +174,8 @@ func (kgen KeyGenerator) GenGaloisKeys(galEls []uint64, sk *SecretKey, gks []*Ga
|
||||
}
|
||||
}
|
||||
|
||||
// GenGaloisKeysNew generates the GaloisKey objects for all galois elements in galEls, and
|
||||
// returns the resulting keys in a newly allocated []*GaloisKey.
|
||||
// GenGaloisKeysNew generates the [GaloisKey] objects for all galois elements in galEls, and
|
||||
// returns the resulting keys in a newly allocated []*[GaloisKey].
|
||||
func (kgen KeyGenerator) GenGaloisKeysNew(galEls []uint64, sk *SecretKey, evkParams ...EvaluationKeyParameters) (gks []*GaloisKey) {
|
||||
levelQ, levelP, BaseTwoDecomposition := ResolveEvaluationKeyParameters(kgen.params, evkParams)
|
||||
gks = make([]*GaloisKey, len(galEls))
|
||||
@@ -186,7 +186,7 @@ func (kgen KeyGenerator) GenGaloisKeysNew(galEls []uint64, sk *SecretKey, evkPar
|
||||
return
|
||||
}
|
||||
|
||||
// GenEvaluationKeysForRingSwapNew generates the necessary EvaluationKeys to switch from a standard ring to to a conjugate invariant ring and vice-versa.
|
||||
// GenEvaluationKeysForRingSwapNew generates the necessary evaluation keys to switch from a standard ring to to a conjugate invariant ring and vice-versa.
|
||||
func (kgen KeyGenerator) GenEvaluationKeysForRingSwapNew(skStd, skConjugateInvariant *SecretKey, evkParams ...EvaluationKeyParameters) (stdToci, ciToStd *EvaluationKey) {
|
||||
|
||||
levelQ := utils.Min(skStd.Value.Q.Level(), skConjugateInvariant.Value.Q.Level())
|
||||
@@ -209,15 +209,15 @@ func (kgen KeyGenerator) GenEvaluationKeysForRingSwapNew(skStd, skConjugateInvar
|
||||
return
|
||||
}
|
||||
|
||||
// GenEvaluationKeyNew generates a new EvaluationKey, that will re-encrypt a Ciphertext encrypted under the input key into the output key.
|
||||
// GenEvaluationKeyNew generates a new [EvaluationKey], that will re-encrypt a [Ciphertext] encrypted under the input key into the output key.
|
||||
// If the ringDegree(skOutput) > ringDegree(skInput), generates [-a*SkOut + w*P*skIn_{Y^{N/n}} + e, a] in X^{N}.
|
||||
// If the ringDegree(skOutput) < ringDegree(skInput), generates [-a*skOut_{Y^{N/n}} + w*P*skIn + e_{N}, a_{N}] in X^{N}.
|
||||
// Else generates [-a*skOut + w*P*skIn + e, a] in X^{N}.
|
||||
// The output EvaluationKey is always given in max(N, n) and in the moduli of the output EvaluationKey.
|
||||
// When re-encrypting a Ciphertext from Y^{N/n} to X^{N}, the Ciphertext must first be mapped to X^{N}
|
||||
// using SwitchCiphertextRingDegreeNTT(ctSmallDim, nil, ctLargeDim).
|
||||
// When re-encrypting a Ciphertext from X^{N} to Y^{N/n}, the output of the re-encryption is in still X^{N} and
|
||||
// must be mapped Y^{N/n} using SwitchCiphertextRingDegreeNTT(ctLargeDim, ringQLargeDim, ctSmallDim).
|
||||
// The output [EvaluationKey] is always given in max(N, n) and in the moduli of the output [EvaluationKey].
|
||||
// When re-encrypting a [Ciphertext] from Y^{N/n} to X^{N}, the Ciphertext must first be mapped to X^{N}
|
||||
// using [SwitchCiphertextRingDegreeNTT](ctSmallDim, nil, ctLargeDim).
|
||||
// When re-encrypting a [Ciphertext] from X^{N} to Y^{N/n}, the output of the re-encryption is in still X^{N} and
|
||||
// must be mapped Y^{N/n} using [SwitchCiphertextRingDegreeNTT](ctLargeDim, ringQLargeDim, ctSmallDim).
|
||||
func (kgen KeyGenerator) GenEvaluationKeyNew(skInput, skOutput *SecretKey, evkParams ...EvaluationKeyParameters) (evk *EvaluationKey) {
|
||||
levelQ, levelP, BaseTwoDecomposition := ResolveEvaluationKeyParameters(kgen.params, evkParams)
|
||||
evk = newEvaluationKey(kgen.params, levelQ, levelP, BaseTwoDecomposition)
|
||||
@@ -225,15 +225,15 @@ func (kgen KeyGenerator) GenEvaluationKeyNew(skInput, skOutput *SecretKey, evkPa
|
||||
return
|
||||
}
|
||||
|
||||
// GenEvaluationKey generates an EvaluationKey, that will re-encrypt a Ciphertext encrypted under the input key into the output key.
|
||||
// GenEvaluationKey generates an [EvaluationKey], that will re-encrypt a [Ciphertext] encrypted under the input key into the output key.
|
||||
// If the ringDegree(skOutput) > ringDegree(skInput), generates [-a*SkOut + w*P*skIn_{Y^{N/n}} + e, a] in X^{N}.
|
||||
// If the ringDegree(skOutput) < ringDegree(skInput), generates [-a*skOut_{Y^{N/n}} + w*P*skIn + e_{N}, a_{N}] in X^{N}.
|
||||
// Else generates [-a*skOut + w*P*skIn + e, a] in X^{N}.
|
||||
// The output EvaluationKey is always given in max(N, n) and in the moduli of the output EvaluationKey.
|
||||
// When re-encrypting a Ciphertext from Y^{N/n} to X^{N}, the Ciphertext must first be mapped to X^{N}
|
||||
// using SwitchCiphertextRingDegreeNTT(ctSmallDim, nil, ctLargeDim).
|
||||
// When re-encrypting a Ciphertext from X^{N} to Y^{N/n}, the output of the re-encryption is in still X^{N} and
|
||||
// must be mapped Y^{N/n} using SwitchCiphertextRingDegreeNTT(ctLargeDim, ringQLargeDim, ctSmallDim).
|
||||
// The output [EvaluationKey] is always given in max(N, n) and in the moduli of the output [EvaluationKey].
|
||||
// When re-encrypting a [Ciphertext] from Y^{N/n} to X^{N}, the [Ciphertext] must first be mapped to X^{N}
|
||||
// using [SwitchCiphertextRingDegreeNTT](ctSmallDim, nil, ctLargeDim).
|
||||
// When re-encrypting a [Ciphertext] from X^{N} to Y^{N/n}, the output of the re-encryption is in still X^{N} and
|
||||
// must be mapped Y^{N/n} using [SwitchCiphertextRingDegreeNTT](ctLargeDim, ringQLargeDim, ctSmallDim).
|
||||
func (kgen KeyGenerator) GenEvaluationKey(skInput, skOutput *SecretKey, evk *EvaluationKey) {
|
||||
|
||||
ringQ := kgen.params.RingQ()
|
||||
|
||||
@@ -17,7 +17,7 @@ type SecretKey struct {
|
||||
Value ringqp.Poly
|
||||
}
|
||||
|
||||
// NewSecretKey generates a new SecretKey with zero values.
|
||||
// NewSecretKey generates a new [SecretKey] with zero values.
|
||||
func NewSecretKey(params ParameterProvider) *SecretKey {
|
||||
return &SecretKey{Value: params.GetRLWEParameters().RingQP().NewPoly()}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ func (sk SecretKey) LevelP() int {
|
||||
return sk.Value.P.Level()
|
||||
}
|
||||
|
||||
// CopyNew creates a deep copy of the receiver secret key and returns it.
|
||||
// CopyNew creates a deep copy of the receiver [SecretKey] and returns it.
|
||||
func (sk SecretKey) CopyNew() *SecretKey {
|
||||
return &SecretKey{*sk.Value.CopyNew()}
|
||||
}
|
||||
@@ -47,30 +47,30 @@ func (sk SecretKey) BinarySize() (dataLen int) {
|
||||
return sk.Value.BinarySize()
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// WriteTo writes the object on an [io.Writer]. It implements the [io.WriterTo]
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
//
|
||||
// Unless w implements the buffer.Writer interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a bufio.Writer. Since this requires allocations, it
|
||||
// is preferable to pass a buffer.Writer directly:
|
||||
// Unless w implements the [buffer.Writer] interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a [bufio.Writer]. Since this requires allocations, it
|
||||
// is preferable to pass a [buffer.Writer] directly:
|
||||
//
|
||||
// - When writing multiple times to a io.Writer, it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// - When writing multiple times to a [io.Writer], it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated [bufio.Writer].
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (sk SecretKey) WriteTo(w io.Writer) (n int64, err error) {
|
||||
return sk.Value.WriteTo(w)
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// [io.ReaderFrom] interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a [buffer.Reader] directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// - When reading multiple values from a [io.Reader], it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated [bufio.Reader].
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (sk *SecretKey) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
@@ -83,7 +83,7 @@ func (sk SecretKey) MarshalBinary() (p []byte, err error) {
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
// [SecretKey.MarshalBinary] or [SecretKey.WriteTo] on the object.
|
||||
func (sk *SecretKey) UnmarshalBinary(p []byte) (err error) {
|
||||
return sk.Value.UnmarshalBinary(p)
|
||||
}
|
||||
@@ -92,7 +92,7 @@ func (sk *SecretKey) isEncryptionKey() {}
|
||||
|
||||
type VectorQP []ringqp.Poly
|
||||
|
||||
// NewVectorQP returns a new PublicKey with zero values.
|
||||
// NewVectorQP returns a new [PublicKey] with zero values.
|
||||
func NewVectorQP(params ParameterProvider, size, levelQ, levelP int) (v VectorQP) {
|
||||
rqp := params.GetRLWEParameters().RingQP().AtLevel(levelQ, levelP)
|
||||
|
||||
@@ -105,7 +105,7 @@ func NewVectorQP(params ParameterProvider, size, levelQ, levelP int) (v VectorQP
|
||||
return
|
||||
}
|
||||
|
||||
// LevelQ returns the level of the modulus Q of the first element of the VectorQP.
|
||||
// LevelQ returns the level of the modulus Q of the first element of the [VectorQP].
|
||||
// Returns -1 if the size of the vector is zero or has no modulus Q.
|
||||
func (p VectorQP) LevelQ() int {
|
||||
if len(p) == 0 {
|
||||
@@ -114,7 +114,7 @@ func (p VectorQP) LevelQ() int {
|
||||
return p[0].LevelQ()
|
||||
}
|
||||
|
||||
// LevelP returns the level of the modulus P of the first element of the VectorQP.
|
||||
// LevelP returns the level of the modulus P of the first element of the [VectorQP].
|
||||
// Returns -1 if the size of the vector is zero or has no modulus P.
|
||||
func (p VectorQP) LevelP() int {
|
||||
if len(p) == 0 {
|
||||
@@ -123,7 +123,7 @@ func (p VectorQP) LevelP() int {
|
||||
return p[0].LevelP()
|
||||
}
|
||||
|
||||
// CopyNew creates a deep copy of the target PublicKey and returns it.
|
||||
// CopyNew creates a deep copy of the target [PublicKey] and returns it.
|
||||
func (p VectorQP) CopyNew() *VectorQP {
|
||||
m := make([]ringqp.Poly, len(p))
|
||||
for i := range p {
|
||||
@@ -152,15 +152,15 @@ func (p VectorQP) BinarySize() int {
|
||||
return structs.Vector[ringqp.Poly](p[:]).BinarySize()
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// WriteTo writes the object on an [io.Writer]. It implements the [io.WriterTo]
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
//
|
||||
// Unless w implements the buffer.Writer interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a bufio.Writer. Since this requires allocations, it
|
||||
// is preferable to pass a buffer.Writer directly:
|
||||
// Unless w implements the [buffer.Writer] interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a [bufio.Writer]. Since this requires allocations, it
|
||||
// is preferable to pass a [buffer.Writer] directly:
|
||||
//
|
||||
// - When writing multiple times to a io.Writer, it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// - When writing multiple times to a [io.Writer], it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated [bufio.Writer].
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (p VectorQP) WriteTo(w io.Writer) (n int64, err error) {
|
||||
@@ -168,15 +168,15 @@ func (p VectorQP) WriteTo(w io.Writer) (n int64, err error) {
|
||||
return v.WriteTo(w)
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// [io.ReaderFrom] interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a [buffer.Reader] directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// - When reading multiple values from a [io.Reader], it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated [bufio.Reader].
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (p *VectorQP) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
@@ -194,7 +194,7 @@ func (p VectorQP) MarshalBinary() ([]byte, error) {
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
// [VectorQP.MarshalBinary] or [VectorQP.WriteTo] on the object.
|
||||
func (p *VectorQP) UnmarshalBinary(b []byte) error {
|
||||
_, err := p.ReadFrom(buffer.NewBuffer(b))
|
||||
return err
|
||||
@@ -206,7 +206,7 @@ type PublicKey struct {
|
||||
Value VectorQP
|
||||
}
|
||||
|
||||
// NewPublicKey returns a new PublicKey with zero values.
|
||||
// NewPublicKey returns a new [PublicKey] with zero values.
|
||||
func NewPublicKey(params ParameterProvider) (pk *PublicKey) {
|
||||
p := params.GetRLWEParameters()
|
||||
return &PublicKey{Value: NewVectorQP(params, 2, p.MaxLevelQ(), p.MaxLevelP())}
|
||||
@@ -220,7 +220,7 @@ func (p PublicKey) LevelP() int {
|
||||
return p.Value.LevelP()
|
||||
}
|
||||
|
||||
// CopyNew creates a deep copy of the target PublicKey and returns it.
|
||||
// CopyNew creates a deep copy of the target [PublicKey] and returns it.
|
||||
func (p PublicKey) CopyNew() *PublicKey {
|
||||
return &PublicKey{Value: *p.Value.CopyNew()}
|
||||
}
|
||||
@@ -234,30 +234,30 @@ func (p PublicKey) BinarySize() int {
|
||||
return p.Value.BinarySize()
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// WriteTo writes the object on an [io.Writer]. It implements the [io.WriterTo]
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
//
|
||||
// Unless w implements the buffer.Writer interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a bufio.Writer. Since this requires allocations, it
|
||||
// is preferable to pass a buffer.Writer directly:
|
||||
// Unless w implements the [buffer.Writer] interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a [bufio.Writer]. Since this requires allocations, it
|
||||
// is preferable to pass a [buffer.Writer] directly:
|
||||
//
|
||||
// - When writing multiple times to a io.Writer, it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// - When writing multiple times to a [io.Writer], it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated [bufio.Writer].
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (p PublicKey) WriteTo(w io.Writer) (n int64, err error) {
|
||||
return p.Value.WriteTo(w)
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// [io.ReaderFrom] interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a [buffer.Reader] directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// - When reading multiple values from a [io.Reader], it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated [bufio.Reader].
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (p *PublicKey) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
@@ -270,7 +270,7 @@ func (p PublicKey) MarshalBinary() ([]byte, error) {
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
// [PublicKey.MarshalBinary] or [PublicKey.WriteTo] on the object.
|
||||
func (p *PublicKey) UnmarshalBinary(b []byte) error {
|
||||
return p.Value.UnmarshalBinary(b)
|
||||
}
|
||||
@@ -278,8 +278,8 @@ func (p *PublicKey) UnmarshalBinary(b []byte) error {
|
||||
func (p *PublicKey) isEncryptionKey() {}
|
||||
|
||||
// EvaluationKey is a public key indented to be used during the evaluation phase of a homomorphic circuit.
|
||||
// It provides a one way public and non-interactive re-encryption from a ciphertext encrypted under `skIn`
|
||||
// to a ciphertext encrypted under `skOut`.
|
||||
// It provides a one way public and non-interactive re-encryption from a ciphertext encrypted under skIn
|
||||
// to a ciphertext encrypted under skOut.
|
||||
//
|
||||
// Such re-encryption is for example used for:
|
||||
// - Homomorphic relinearization: re-encryption of a quadratic ciphertext (that requires (1, sk sk^2) to be decrypted)
|
||||
@@ -323,7 +323,7 @@ func ResolveEvaluationKeyParameters(params Parameters, evkParams []EvaluationKey
|
||||
return
|
||||
}
|
||||
|
||||
// NewEvaluationKey returns a new EvaluationKey with pre-allocated zero-value.
|
||||
// NewEvaluationKey returns a new [EvaluationKey] with pre-allocated zero-value.
|
||||
func NewEvaluationKey(params ParameterProvider, evkParams ...EvaluationKeyParameters) *EvaluationKey {
|
||||
p := *params.GetRLWEParameters()
|
||||
levelQ, levelP, BaseTwoDecomposition := ResolveEvaluationKeyParameters(p, evkParams)
|
||||
@@ -334,7 +334,7 @@ func newEvaluationKey(params Parameters, levelQ, levelP, BaseTwoDecomposition in
|
||||
return &EvaluationKey{GadgetCiphertext: *NewGadgetCiphertext(params, 1, levelQ, levelP, BaseTwoDecomposition)}
|
||||
}
|
||||
|
||||
// CopyNew creates a deep copy of the target EvaluationKey and returns it.
|
||||
// CopyNew creates a deep copy of the target [EvaluationKey] and returns it.
|
||||
func (evk EvaluationKey) CopyNew() *EvaluationKey {
|
||||
return &EvaluationKey{GadgetCiphertext: *evk.GadgetCiphertext.CopyNew()}
|
||||
}
|
||||
@@ -344,7 +344,7 @@ func (evk EvaluationKey) Equal(other *EvaluationKey) bool {
|
||||
return evk.GadgetCiphertext.Equal(&other.GadgetCiphertext)
|
||||
}
|
||||
|
||||
// RelinearizationKey is type of evaluation key used for ciphertext multiplication compactness.
|
||||
// RelinearizationKey is type of [EvaluationKey] used for ciphertext multiplication compactness.
|
||||
// The Relinearization key encrypts s^{2} under s and is used to homomorphically re-encrypt the
|
||||
// degree 2 term of a ciphertext (the term that decrypt with s^{2}) into a degree 1 term
|
||||
// (a term that decrypts with s).
|
||||
@@ -352,7 +352,7 @@ type RelinearizationKey struct {
|
||||
EvaluationKey
|
||||
}
|
||||
|
||||
// NewRelinearizationKey allocates a new RelinearizationKey with zero coefficients.
|
||||
// NewRelinearizationKey allocates a new [RelinearizationKey] with zero coefficients.
|
||||
func NewRelinearizationKey(params ParameterProvider, evkParams ...EvaluationKeyParameters) *RelinearizationKey {
|
||||
p := *params.GetRLWEParameters()
|
||||
levelQ, levelP, BaseTwoDecomposition := ResolveEvaluationKeyParameters(p, evkParams)
|
||||
@@ -373,7 +373,7 @@ func (rlk RelinearizationKey) Equal(other *RelinearizationKey) bool {
|
||||
return rlk.EvaluationKey.Equal(&other.EvaluationKey)
|
||||
}
|
||||
|
||||
// GaloisKey is a type of evaluation key used to evaluate automorphisms on ciphertext.
|
||||
// GaloisKey is a type of [EvaluationKey] used to evaluate automorphisms on ciphertext.
|
||||
// An automorphism pi: X^{i} -> X^{i*GaloisElement} changes the key under which the
|
||||
// ciphertext is encrypted from s to pi(s). Thus, the ciphertext must be re-encrypted
|
||||
// from pi(s) to s to ensure correctness, which is done with the corresponding GaloisKey.
|
||||
@@ -390,7 +390,7 @@ type GaloisKey struct {
|
||||
EvaluationKey
|
||||
}
|
||||
|
||||
// NewGaloisKey allocates a new GaloisKey with zero coefficients and GaloisElement set to zero.
|
||||
// NewGaloisKey allocates a new [GaloisKey] with zero coefficients and GaloisElement set to zero.
|
||||
func NewGaloisKey(params ParameterProvider, evkParams ...EvaluationKeyParameters) *GaloisKey {
|
||||
p := *params.GetRLWEParameters()
|
||||
levelQ, levelP, BaseTwoDecomposition := ResolveEvaluationKeyParameters(p, evkParams)
|
||||
@@ -423,15 +423,15 @@ func (gk GaloisKey) BinarySize() (size int) {
|
||||
return gk.EvaluationKey.BinarySize() + 16
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// WriteTo writes the object on an [io.Writer]. It implements the [io.WriterTo]
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
//
|
||||
// Unless w implements the buffer.Writer interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a bufio.Writer. Since this requires allocations, it
|
||||
// is preferable to pass a buffer.Writer directly:
|
||||
// Unless w implements the [buffer.Writer] interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a [bufio.Writer]. Since this requires allocations, it
|
||||
// is preferable to pass a [buffer.Writer] directly:
|
||||
//
|
||||
// - When writing multiple times to a io.Writer, it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// - When writing multiple times to a [io.Writer], it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated [bufio.Writer].
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (gk GaloisKey) WriteTo(w io.Writer) (n int64, err error) {
|
||||
@@ -465,15 +465,15 @@ func (gk GaloisKey) WriteTo(w io.Writer) (n int64, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// [io.ReaderFrom] interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a [buffer.Reader] directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// - When reading multiple values from a [io.Reader], it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated [bufio.Reader].
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (gk *GaloisKey) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
@@ -514,14 +514,14 @@ func (gk GaloisKey) MarshalBinary() (p []byte, err error) {
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
// [GaloisKey.MarshalBinary] or [GaloisKey.WriteTo] on the object.
|
||||
func (gk *GaloisKey) UnmarshalBinary(p []byte) (err error) {
|
||||
_, err = gk.ReadFrom(buffer.NewBuffer(p))
|
||||
return
|
||||
}
|
||||
|
||||
// EvaluationKeySet is an interface implementing methods
|
||||
// to load the RelinearizationKey and GaloisKeys in the Evaluator.
|
||||
// to load the [RelinearizationKey] and the [GaloisKey] in the [Evaluator].
|
||||
// Implementations of this interface must be safe for concurrent use.
|
||||
type EvaluationKeySet interface {
|
||||
|
||||
@@ -536,13 +536,13 @@ type EvaluationKeySet interface {
|
||||
GetRelinearizationKey() (evk *RelinearizationKey, err error)
|
||||
}
|
||||
|
||||
// MemEvaluationKeySet is a basic in-memory implementation of the EvaluationKeySet interface.
|
||||
// MemEvaluationKeySet is a basic in-memory implementation of the [EvaluationKeySet] interface.
|
||||
type MemEvaluationKeySet struct {
|
||||
RelinearizationKey *RelinearizationKey
|
||||
GaloisKeys structs.Map[uint64, GaloisKey]
|
||||
}
|
||||
|
||||
// NewMemEvaluationKeySet returns a new EvaluationKeySet with the provided RelinearizationKey and GaloisKeys.
|
||||
// NewMemEvaluationKeySet returns a new [EvaluationKeySet] with the provided [RelinearizationKey] and the [GaloisKey].
|
||||
func NewMemEvaluationKeySet(relinKey *RelinearizationKey, galoisKeys ...*GaloisKey) (eks *MemEvaluationKeySet) {
|
||||
eks = &MemEvaluationKeySet{GaloisKeys: map[uint64]*GaloisKey{}}
|
||||
eks.RelinearizationKey = relinKey
|
||||
@@ -552,7 +552,7 @@ func NewMemEvaluationKeySet(relinKey *RelinearizationKey, galoisKeys ...*GaloisK
|
||||
return eks
|
||||
}
|
||||
|
||||
// GetGaloisKey retrieves the Galois key for the automorphism X^{i} -> X^{i*galEl}.
|
||||
// GetGaloisKey retrieves the [GaloisKey] for the automorphism X^{i} -> X^{i*galEl}.
|
||||
func (evk MemEvaluationKeySet) GetGaloisKey(galEl uint64) (gk *GaloisKey, err error) {
|
||||
var ok bool
|
||||
if gk, ok = evk.GaloisKeys[galEl]; !ok {
|
||||
@@ -581,7 +581,7 @@ func (evk MemEvaluationKeySet) GetGaloisKeysList() (galEls []uint64) {
|
||||
return
|
||||
}
|
||||
|
||||
// GetRelinearizationKey retrieves the RelinearizationKey.
|
||||
// GetRelinearizationKey retrieves the [RelinearizationKey].
|
||||
func (evk MemEvaluationKeySet) GetRelinearizationKey() (rk *RelinearizationKey, err error) {
|
||||
if evk.RelinearizationKey != nil {
|
||||
return evk.RelinearizationKey, nil
|
||||
@@ -605,15 +605,15 @@ func (evk MemEvaluationKeySet) BinarySize() (size int) {
|
||||
return
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// [WriteTo] writes the object on an [io.Writer]. It implements the [io.WriterTo]
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
//
|
||||
// Unless w implements the buffer.Writer interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a bufio.Writer. Since this requires allocations, it
|
||||
// is preferable to pass a buffer.Writer directly:
|
||||
// Unless w implements the [buffer.Writer] interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a [bufio.Writer]. Since this requires allocations, it
|
||||
// is preferable to pass a [buffer.Writer] directly:
|
||||
//
|
||||
// - When writing multiple times to a io.Writer, it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// - When writing multiple times to a [io.Writer], it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated [bufio.Writer].
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (evk MemEvaluationKeySet) WriteTo(w io.Writer) (n int64, err error) {
|
||||
@@ -669,15 +669,15 @@ func (evk MemEvaluationKeySet) WriteTo(w io.Writer) (n int64, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// [io.ReaderFrom] interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a [buffer.Reader] directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// - When reading multiple values from a [io.Reader], it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated [bufio.Reader].
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (evk *MemEvaluationKeySet) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
@@ -741,7 +741,7 @@ func (evk MemEvaluationKeySet) MarshalBinary() (p []byte, err error) {
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
// [MemEvaluationKeySet.MarshalBinary] or [MemEvaluationKeySet.WriteTo] on the object.
|
||||
func (evk *MemEvaluationKeySet) UnmarshalBinary(p []byte) (err error) {
|
||||
_, err = evk.ReadFrom(buffer.NewBuffer(p))
|
||||
return
|
||||
|
||||
@@ -31,7 +31,7 @@ func (m MetaData) BinarySize() int {
|
||||
return 44 + m.PlaintextMetaData.BinarySize() + m.CiphertextMetaData.BinarySize()
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// WriteTo writes the object on an [io.Writer]. It implements the [io.WriterTo]
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
func (m MetaData) WriteTo(w io.Writer) (int64, error) {
|
||||
if p, err := m.MarshalBinary(); err != nil {
|
||||
@@ -45,15 +45,15 @@ func (m MetaData) WriteTo(w io.Writer) (int64, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// [io.ReaderFrom] interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a [buffer.Reader] directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// - When reading multiple values from a [io.Reader], it is preferable to first
|
||||
// first wrap [io.Reader] in a pre-allocated [bufio.Reader].
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (m *MetaData) ReadFrom(r io.Reader) (int64, error) {
|
||||
@@ -150,7 +150,7 @@ func (m *PlaintextMetaData) Equal(other *PlaintextMetaData) (res bool) {
|
||||
return
|
||||
}
|
||||
|
||||
// Equal returns true if two MetaData structs are identical.
|
||||
// Equal returns true if two [CiphertextMetaData] structs are identical.
|
||||
func (m *CiphertextMetaData) Equal(other *CiphertextMetaData) (res bool) {
|
||||
res = m.IsNTT == other.IsNTT
|
||||
res = res && m.IsMontgomery == other.IsMontgomery
|
||||
@@ -162,15 +162,15 @@ func (m PlaintextMetaData) BinarySize() int {
|
||||
return 61 + m.Scale.BinarySize()
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// [WriteTo] writes the object on an [io.Writer]. It implements the [io.WriterTo]
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
//
|
||||
// Unless w implements the buffer.Writer interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a bufio.Writer. Since this requires allocations, it
|
||||
// is preferable to pass a buffer.Writer directly:
|
||||
// Unless w implements the [buffer.Writer] interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a [bufio.Writer]. Since this requires allocations, it
|
||||
// is preferable to pass a [buffer.Writer] directly:
|
||||
//
|
||||
// - When writing multiple times to a io.Writer, it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// - When writing multiple times to a [io.Writer], it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated [bufio.Writer].
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (m PlaintextMetaData) WriteTo(w io.Writer) (int64, error) {
|
||||
@@ -185,15 +185,15 @@ func (m PlaintextMetaData) WriteTo(w io.Writer) (int64, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// [io.ReaderFrom] interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a [buffer.Reader] directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// - When reading multiple values from a [io.Reader], it is preferable to first
|
||||
// first wrap [io.Reader] in a pre-allocated [bufio.Reader].
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (m *PlaintextMetaData) ReadFrom(r io.Reader) (int64, error) {
|
||||
@@ -272,7 +272,7 @@ func (m *PlaintextMetaData) UnmarshalJSON(p []byte) (err error) {
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
// [PlaintextMetaData.MarshalBinary] or [PlaintextMetaData.WriteTo] on the object.
|
||||
func (m *PlaintextMetaData) UnmarshalBinary(p []byte) (err error) {
|
||||
return m.UnmarshalJSON(p)
|
||||
}
|
||||
@@ -282,15 +282,15 @@ func (m *CiphertextMetaData) BinarySize() int {
|
||||
return 38
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// [WriteTo] writes the object on an [io.Writer]. It implements the [io.WriterTo]
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
//
|
||||
// Unless w implements the buffer.Writer interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a bufio.Writer. Since this requires allocations, it
|
||||
// is preferable to pass a buffer.Writer directly:
|
||||
// Unless w implements the [buffer.Writer] interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a [bufio.Writer]. Since this requires allocations, it
|
||||
// is preferable to pass a [buffer.Writer] directly:
|
||||
//
|
||||
// - When writing multiple times to a io.Writer, it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// - When writing multiple times to a [io.Writer], it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated [bufio.Writer].
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (m *CiphertextMetaData) WriteTo(w io.Writer) (int64, error) {
|
||||
@@ -305,15 +305,15 @@ func (m *CiphertextMetaData) WriteTo(w io.Writer) (int64, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// [io.ReaderFrom] interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a [buffer.Reader] directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// - When reading multiple values from a [io.Reader], it is preferable to first
|
||||
// first wrap [io.Reader] in a pre-allocated [bufio.Reader].
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (m *CiphertextMetaData) ReadFrom(r io.Reader) (int64, error) {
|
||||
@@ -378,7 +378,7 @@ func (m *CiphertextMetaData) UnmarshalJSON(p []byte) (err error) {
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
// [CiphertextMetaData.MarshalBinary] or [CiphertextMetaData.WriteTo] on the object.
|
||||
func (m *CiphertextMetaData) UnmarshalBinary(p []byte) (err error) {
|
||||
return m.UnmarshalJSON(p)
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
|
||||
// Trace maps X -> sum((-1)^i * X^{i*n+1}) for n <= i < N
|
||||
// Monomial X^k vanishes if k is not divisible by (N/n), otherwise it is multiplied by (N/n).
|
||||
// Ciphertext is pre-multiplied by (N/n)^-1 to remove the (N/n) factor.
|
||||
// [Ciphertext] is pre-multiplied by (N/n)^-1 to remove the (N/n) factor.
|
||||
// Examples of full Trace for [0 + 1X + 2X^2 + 3X^3 + 4X^4 + 5X^5 + 6X^6 + 7X^7]
|
||||
//
|
||||
// 1.
|
||||
@@ -119,7 +119,7 @@ func (eval Evaluator) Trace(ctIn *Ciphertext, logN int, opOut *Ciphertext) (err
|
||||
return
|
||||
}
|
||||
|
||||
// GaloisElementsForTrace returns the list of Galois elements requored for the for the `Trace` operation.
|
||||
// GaloisElementsForTrace returns the list of Galois elements requored for the for the [Evaluator.Trace] operation.
|
||||
// Trace maps X -> sum((-1)^i * X^{i*n+1}) for 2^{LogN} <= i < N.
|
||||
func GaloisElementsForTrace(params ParameterProvider, logN int) (galEls []uint64) {
|
||||
|
||||
@@ -144,7 +144,7 @@ func GaloisElementsForTrace(params ParameterProvider, logN int) (galEls []uint64
|
||||
return
|
||||
}
|
||||
|
||||
// Expand expands a RLWE Ciphertext encrypting sum ai * X^i to 2^logN ciphertexts,
|
||||
// Expand expands a RLWE [Ciphertext] encrypting sum ai * X^i to 2^logN ciphertexts,
|
||||
// each encrypting ai * X^0 for 0 <= i < 2^LogN. That is, it extracts the first 2^logN
|
||||
// coefficients, whose degree is a multiple of 2^logGap, of ctIn and returns an RLWE
|
||||
// Ciphertext for each coefficient extracted.
|
||||
@@ -256,7 +256,7 @@ func (eval Evaluator) Expand(ctIn *Ciphertext, logN, logGap int) (opOut []*Ciphe
|
||||
}
|
||||
|
||||
// GaloisElementsForExpand returns the list of Galois elements required
|
||||
// to perform the `Expand` operation with parameter `logN`.
|
||||
// to perform the [Evaluator.Expand] operation with parameter logN.
|
||||
func GaloisElementsForExpand(params ParameterProvider, logN int) (galEls []uint64) {
|
||||
galEls = make([]uint64, logN)
|
||||
|
||||
@@ -269,19 +269,15 @@ func GaloisElementsForExpand(params ParameterProvider, logN int) (galEls []uint6
|
||||
return
|
||||
}
|
||||
|
||||
// Pack packs a batch of RLWE ciphertexts, packing the batch of ciphertexts into a single ciphertext.
|
||||
// Pack packs a batch of RLWE [Ciphertext], packing the batch of ciphertexts into a single ciphertext.
|
||||
// The number of key-switching operations is inputLogGap - log2(gap) + len(cts), where log2(gap) is the
|
||||
// minimum distance between two keys of the map cts[int]*Ciphertext.
|
||||
//
|
||||
// Input:
|
||||
// Inputs:
|
||||
//
|
||||
// cts: a map of Ciphertext, where the index in the map is the future position of the first coefficient
|
||||
// of the indexed ciphertext in the final ciphertext (see example). Ciphertexts can be in or out of the NTT domain.
|
||||
// logGap: all coefficients of the input ciphertexts that are not a multiple of X^{2^{logGap}} will be zeroed
|
||||
// during the merging (see example). This is equivalent to skipping the first 2^{logGap} steps of the
|
||||
// algorithm, i.e. having as input ciphertexts that are already partially packed.
|
||||
// zeroGarbageSlots: if set to true, slots which are not multiples of X^{2^{logGap}} will be zeroed during the procedure.
|
||||
// this will greatly increase the noise and increase the number of key-switching operations to inputLogGap + len(cts).
|
||||
// - cts: a map of Ciphertext, where the index in the map is the future position of the first coefficient of the indexed ciphertext in the final ciphertext (see example). Ciphertexts can be in or out of the NTT domain.
|
||||
// - logGap: all coefficients of the input ciphertexts that are not a multiple of X^{2^{logGap}} will be zeroed during the merging (see example). This is equivalent to skipping the first 2^{logGap} steps of the algorithm, i.e., having as input ciphertexts that are already partially packed.
|
||||
// - zeroGarbageSlots: if set to true, slots which are not multiples of X^{2^{logGap}} will be zeroed during the procedure. This will greatly increase the noise and increase the number of key-switching operations to inputLogGap + len(cts).
|
||||
//
|
||||
// Output: a ciphertext packing all input ciphertexts
|
||||
//
|
||||
@@ -295,7 +291,7 @@ func GaloisElementsForExpand(params ParameterProvider, logN int) (galEls []uint6
|
||||
// 1: [x10, X, X, X, x11, X, X, X],
|
||||
// 2: [x20, X, X, X, x21, X, X, X],
|
||||
// 3: [x30, X, X, X, x31, X, X, X],
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Step 1:
|
||||
// map[0]: 2^{-1} * (map[0] + X^2 * map[2] + phi_{5^2}(map[0] - X^2 * map[2]) = [x00, X, x20, X, x01, X, x21, X]
|
||||
@@ -438,7 +434,7 @@ func (eval Evaluator) Pack(cts map[int]*Ciphertext, inputLogGap int, zeroGarbage
|
||||
return cts[0], nil
|
||||
}
|
||||
|
||||
// GaloisElementsForPack returns the list of Galois elements required to perform the `Pack` operation.
|
||||
// GaloisElementsForPack returns the list of Galois elements required to perform the [Evaluator.Pack] operation.
|
||||
func GaloisElementsForPack(params ParameterProvider, logGap int) (galEls []uint64) {
|
||||
|
||||
p := params.GetRLWEParameters()
|
||||
|
||||
@@ -38,7 +38,7 @@ type ParameterProvider interface {
|
||||
|
||||
// ParametersLiteral is a literal representation of RLWE parameters. It has public fields and
|
||||
// is used to express unchecked user-defined parameters literally into Go programs.
|
||||
// The NewParametersFromLiteral function is used to generate the actual checked parameters
|
||||
// The [NewParametersFromLiteral] function is used to generate the actual checked parameters
|
||||
// from the literal representation.
|
||||
//
|
||||
// Users must set the polynomial degree (LogN) and the coefficient modulus, by either setting
|
||||
@@ -50,7 +50,7 @@ type ParameterProvider interface {
|
||||
// - the error variance (Sigma) and secrets' density (H) and the ring type (RingType).
|
||||
//
|
||||
// If left unset, standard default values for these field are substituted at
|
||||
// parameter creation (see NewParametersFromLiteral).
|
||||
// parameter creation (see [NewParametersFromLiteral]).
|
||||
type ParametersLiteral struct {
|
||||
LogN int
|
||||
LogNthRoot int `json:",omitempty"`
|
||||
@@ -66,7 +66,7 @@ type ParametersLiteral struct {
|
||||
}
|
||||
|
||||
// Parameters represents a set of generic RLWE parameters. Its fields are private and
|
||||
// immutable. See ParametersLiteral for user-specified parameters.
|
||||
// immutable. See [ParametersLiteral] for user-specified parameters.
|
||||
type Parameters struct {
|
||||
logN int
|
||||
qi []uint64
|
||||
@@ -81,7 +81,7 @@ type Parameters struct {
|
||||
}
|
||||
|
||||
// NewParameters returns a new set of generic RLWE parameters from the given ring degree logn, moduli q and p, and
|
||||
// error distribution Xs (secret) and Xe (error). It returns the empty parameters Parameters{} and a non-nil error if the
|
||||
// error distribution Xs (secret) and Xe (error). It returns the empty parameters [Parameters]{} and a non-nil error if the
|
||||
// specified parameters are invalid.
|
||||
func NewParameters(logn int, q, p []uint64, xs, xe DistributionLiteral, ringType ring.Type, defaultScale Scale, NTTFlag bool) (params Parameters, err error) {
|
||||
|
||||
@@ -149,16 +149,16 @@ func NewParameters(logn int, q, p []uint64, xs, xe DistributionLiteral, ringType
|
||||
return params, warning
|
||||
}
|
||||
|
||||
// NewParametersFromLiteral instantiate a set of generic RLWE parameters from a ParametersLiteral specification.
|
||||
// NewParametersFromLiteral instantiate a set of generic RLWE parameters from a [ParametersLiteral] specification.
|
||||
// It returns the empty parameters Parameters{} and a non-nil error if the specified parameters are invalid.
|
||||
//
|
||||
// If the moduli chain is specified through the LogQ and LogP fields, the method generates a moduli chain matching
|
||||
// the specified sizes (see `GenModuli`).
|
||||
// the specified sizes (see [GenModuli]).
|
||||
//
|
||||
// If the secrets' density parameter (H) is left unset, its value is set to 2^(paramDef.LogN-1) to match
|
||||
// the standard ternary distribution.
|
||||
//
|
||||
// If the error variance is left unset, its value is set to `DefaultError`.
|
||||
// If the error variance is left unset, its value is set to [DefaultError].
|
||||
//
|
||||
// If the RingType is left unset, the default value is ring.Standard.
|
||||
func NewParametersFromLiteral(paramDef ParametersLiteral) (params Parameters, err error) {
|
||||
@@ -631,7 +631,7 @@ func (p Parameters) Equal(other *Parameters) (res bool) {
|
||||
}
|
||||
|
||||
// MarshalBinary returns a []byte representation of the parameter set.
|
||||
// This representation corresponds to the MarshalJSON representation.
|
||||
// This representation corresponds to the [Parameters.MarshalJSON] representation.
|
||||
func (p Parameters) MarshalBinary() ([]byte, error) {
|
||||
buf := buffer.NewBufferSize(p.BinarySize())
|
||||
_, err := p.WriteTo(buf)
|
||||
@@ -644,12 +644,12 @@ func (p *Parameters) UnmarshalBinary(data []byte) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalJSON returns a JSON representation of this parameter set. See `Marshal` from the `encoding/json` package.
|
||||
// MarshalJSON returns a JSON representation of this parameter set. See Marshal from the [encoding/json] package.
|
||||
func (p Parameters) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(p.ParametersLiteral())
|
||||
}
|
||||
|
||||
// UnmarshalJSON reads a JSON representation of a parameter set into the receiver Parameter. See `Unmarshal` from the `encoding/json` package.
|
||||
// UnmarshalJSON reads a JSON representation of a parameter set into the receiver Parameter. See Unmarshal from the [encoding/json] package.
|
||||
func (p *Parameters) UnmarshalJSON(data []byte) (err error) {
|
||||
var params ParametersLiteral
|
||||
if err = json.Unmarshal(data, ¶ms); err != nil {
|
||||
|
||||
@@ -13,16 +13,16 @@ type Plaintext struct {
|
||||
Value ring.Poly
|
||||
}
|
||||
|
||||
// NewPlaintext creates a new Plaintext at level `level` from the parameters.
|
||||
// NewPlaintext creates a new [Plaintext] at the specified level from the parameters.
|
||||
func NewPlaintext(params ParameterProvider, level ...int) (pt *Plaintext) {
|
||||
op := *NewElement(params, 0, level...)
|
||||
return &Plaintext{Element: op, Value: op.Value[0]}
|
||||
}
|
||||
|
||||
// NewPlaintextAtLevelFromPoly constructs a new Plaintext at a specific level
|
||||
// NewPlaintextAtLevelFromPoly constructs a new [Plaintext] at a specific level
|
||||
// where the message is set to the passed poly. No checks are performed on poly and
|
||||
// the returned Plaintext will share its backing array of coefficients.
|
||||
// Returned plaintext's MetaData is allocated but empty.
|
||||
// the returned [Plaintext] will share its backing array of coefficients.
|
||||
// Returned plaintext's [MetaData] is allocated but empty.
|
||||
func NewPlaintextAtLevelFromPoly(level int, poly ring.Poly) (pt *Plaintext, err error) {
|
||||
Element, err := NewElementAtLevelFromPoly(level, []ring.Poly{poly})
|
||||
if err != nil {
|
||||
@@ -34,7 +34,7 @@ func NewPlaintextAtLevelFromPoly(level int, poly ring.Poly) (pt *Plaintext, err
|
||||
return &Plaintext{Element: *Element, Value: Element.Value[0]}, nil
|
||||
}
|
||||
|
||||
// Copy copies the `other` plaintext value into the receiver plaintext.
|
||||
// Copy copies the supplied plaintext value into the receiver plaintext.
|
||||
func (pt Plaintext) Copy(other *Plaintext) {
|
||||
pt.Element.Copy(&other.Element)
|
||||
pt.Value = other.Element.Value[0]
|
||||
@@ -52,22 +52,22 @@ func (pt Plaintext) Equal(other *Plaintext) bool {
|
||||
return pt.Element.Equal(&other.Element) && pt.Value.Equal(&other.Value)
|
||||
}
|
||||
|
||||
// NewPlaintextRandom generates a new uniformly distributed Plaintext.
|
||||
// NewPlaintextRandom generates a new uniformly distributed [Plaintext].
|
||||
func NewPlaintextRandom(prng sampling.PRNG, params ParameterProvider, level int) (pt *Plaintext) {
|
||||
pt = NewPlaintext(params, level)
|
||||
PopulateElementRandom(prng, params, pt.El())
|
||||
return
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// [io.ReaderFrom] interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// - When reading multiple values from a [io.Reader], it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated [bufio.Reader].
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (pt *Plaintext) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
|
||||
@@ -17,7 +17,7 @@ const (
|
||||
var ScalePrecisionLog10 = int(math.Ceil(float64(ScalePrecision) / math.Log2(10)))
|
||||
|
||||
// Scale is a struct used to track the scaling factor
|
||||
// of Plaintext and Ciphertext structs.
|
||||
// of [Plaintext] and [Ciphertext] structs.
|
||||
// The scale is managed as an 128-bit precision real and can
|
||||
// be either a floating point value or a mod T
|
||||
// prime integer, which is determined at instantiation.
|
||||
@@ -26,16 +26,16 @@ type Scale struct {
|
||||
Mod *big.Int //`json:",omitempty"`
|
||||
}
|
||||
|
||||
// NewScale instantiates a new floating point Scale.
|
||||
// Accepted types for s are int, int64, uint64, float64, *big.Int, *big.Float and *Scale.
|
||||
// NewScale instantiates a new floating point [Scale].
|
||||
// Accepted types for s are int, int64, uint64, float64, *[big.Int], *[big.Float] and *[Scale].
|
||||
// If the input type is not an accepted type, returns an error.
|
||||
func NewScale(s interface{}) Scale {
|
||||
v := scaleToBigFloat(s)
|
||||
return Scale{Value: *v}
|
||||
}
|
||||
|
||||
// NewScaleModT instantiates a new integer mod T Scale.
|
||||
// Accepted types for s are int, int64, uint64, float64, *big.Int, *big.Float and *Scale.
|
||||
// NewScaleModT instantiates a new integer mod T [Scale].
|
||||
// Accepted types for s are int, int64, uint64, float64, *[big.Int], *[big.Float] and *[Scale].
|
||||
// If the input type is not an accepted type, returns an error.
|
||||
func NewScaleModT(s interface{}, mod uint64) Scale {
|
||||
scale := NewScale(s)
|
||||
@@ -66,7 +66,7 @@ func (s Scale) Uint64() uint64 {
|
||||
}
|
||||
|
||||
// Mul multiplies the target s with s1, returning the result in
|
||||
// a new Scale struct. If mod is specified, performs the multiplication
|
||||
// a new [Scale] struct. If mod is specified, performs the multiplication
|
||||
// modulo mod.
|
||||
func (s Scale) Mul(s1 Scale) Scale {
|
||||
|
||||
@@ -87,7 +87,7 @@ func (s Scale) Mul(s1 Scale) Scale {
|
||||
}
|
||||
|
||||
// Div multiplies the target s with s1^-1, returning the result in
|
||||
// a new Scale struct. If mod is specified, performs the multiplication
|
||||
// a new [Scale] struct. If mod is specified, performs the multiplication
|
||||
// modulo t with the multiplicative inverse of s1. Otherwise, performs
|
||||
// the quotient operation.
|
||||
func (s Scale) Div(s1 Scale) Scale {
|
||||
@@ -177,7 +177,7 @@ func (s Scale) MarshalBinary() (p []byte, err error) {
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
// [Scale.MarshalBinary] on the object.
|
||||
func (s Scale) UnmarshalBinary(p []byte) (err error) {
|
||||
return s.UnmarshalJSON(p)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/tuneinsight/lattigo/v5/utils"
|
||||
)
|
||||
|
||||
// NoisePublicKey returns the log2 of the standard deviation of the input public-key with respect to the given secret-key and parameters.
|
||||
// NoisePublicKey returns the log2 of the standard deviation of the input [PublicKey] with respect to the given [Secret] and parameters.
|
||||
func NoisePublicKey(pk *PublicKey, sk *SecretKey, params Parameters) float64 {
|
||||
|
||||
pk = pk.CopyNew()
|
||||
@@ -24,14 +24,14 @@ func NoisePublicKey(pk *PublicKey, sk *SecretKey, params Parameters) float64 {
|
||||
return ringQP.Log2OfStandardDeviation(pk.Value[0])
|
||||
}
|
||||
|
||||
// NoiseRelinearizationKey the log2 of the standard deviation of the noise of the input relinearization key with respect to the given secret-key and paramters.
|
||||
// NoiseRelinearizationKey the log2 of the standard deviation of the noise of the input [RelinearizationKey] with respect to the given [Secret] and paramters.
|
||||
func NoiseRelinearizationKey(rlk *RelinearizationKey, sk *SecretKey, params Parameters) float64 {
|
||||
sk2 := sk.CopyNew()
|
||||
params.RingQP().AtLevel(rlk.LevelQ(), rlk.LevelP()).MulCoeffsMontgomery(sk2.Value, sk2.Value, sk2.Value)
|
||||
return NoiseEvaluationKey(&rlk.EvaluationKey, sk2, sk, params)
|
||||
}
|
||||
|
||||
// NoiseGaloisKey the log2 of the standard deviation of the noise of the input Galois key key with respect to the given secret-key and paramters.
|
||||
// NoiseGaloisKey the log2 of the standard deviation of the noise of the input [GaloisKey] key with respect to the given [SecretKey] and paramters.
|
||||
func NoiseGaloisKey(gk *GaloisKey, sk *SecretKey, params Parameters) float64 {
|
||||
|
||||
skIn := sk.CopyNew()
|
||||
@@ -46,7 +46,7 @@ func NoiseGaloisKey(gk *GaloisKey, sk *SecretKey, params Parameters) float64 {
|
||||
return NoiseEvaluationKey(&gk.EvaluationKey, skIn, skOut, params)
|
||||
}
|
||||
|
||||
// NoiseGadgetCiphertext returns the log2 of the standard deviation of the noise of the input gadget ciphertext with respect to the given plaintext, secret-key and parameters.
|
||||
// NoiseGadgetCiphertext returns the log2 of the standard deviation of the noise of the input [GadgetCiphertext] with respect to the given [Plaintext], [SecretKey] and [Parameters].
|
||||
// The polynomial pt is expected to be in the NTT and Montgomery domain.
|
||||
func NoiseGadgetCiphertext(gct *GadgetCiphertext, pt ring.Poly, sk *SecretKey, params Parameters) float64 {
|
||||
|
||||
@@ -101,13 +101,13 @@ func NoiseGadgetCiphertext(gct *GadgetCiphertext, pt ring.Poly, sk *SecretKey, p
|
||||
return maxLog2Std
|
||||
}
|
||||
|
||||
// NoiseEvaluationKey the log2 of the standard deviation of the noise of the input Galois key key with respect to the given secret-key and paramters.
|
||||
// NoiseEvaluationKey the log2 of the standard deviation of the noise of the input [GaloisKey] with respect to the given [SecretKey] and [Parameters].
|
||||
func NoiseEvaluationKey(evk *EvaluationKey, skIn, skOut *SecretKey, params Parameters) float64 {
|
||||
return NoiseGadgetCiphertext(&evk.GadgetCiphertext, skIn.Value.Q, skOut, params)
|
||||
}
|
||||
|
||||
// Norm returns the log2 of the standard deviation, minimum and maximum absolute norm of
|
||||
// the decrypted Ciphertext, before the decoding (i.e. including the error).
|
||||
// the decrypted [Ciphertext], before the decoding (i.e. including the error).
|
||||
func Norm(ct *Ciphertext, dec *Decryptor) (std, min, max float64) {
|
||||
|
||||
params := dec.params
|
||||
|
||||
@@ -25,7 +25,7 @@ type Evaluator struct {
|
||||
galoisGenDiscreteLog map[uint64]int
|
||||
}
|
||||
|
||||
// NewEvaluator instantiates a new Evaluator.
|
||||
// NewEvaluator instantiates a new [Evaluator].
|
||||
func NewEvaluator(paramsBR, paramsLWE rlwe.ParameterProvider) (eval *Evaluator) {
|
||||
eval = new(Evaluator)
|
||||
eval.Evaluator = rgsw.NewEvaluator(paramsBR, nil)
|
||||
@@ -43,7 +43,7 @@ func NewEvaluator(paramsBR, paramsLWE rlwe.ParameterProvider) (eval *Evaluator)
|
||||
return
|
||||
}
|
||||
|
||||
// EvaluateAndRepack extracts on the fly LWE samples, evaluates the provided blind rotations on the LWE and repacks everything into a single rlwe.Ciphertext.
|
||||
// EvaluateAndRepack extracts on the fly LWE samples, evaluates the provided blind rotations on the LWE and repacks everything into a single [rlwe.Ciphertext].
|
||||
// testPolyWithSlotIndex : a map with [slot_index] -> blind rotation
|
||||
// repackIndex : a map with [slot_index_have] -> slot_index_want
|
||||
func (eval *Evaluator) EvaluateAndRepack(ct *rlwe.Ciphertext, testPolyWithSlotIndex map[int]*ring.Poly, repackIndex map[int]int, key BlindRotationEvaluationKeySet, repackKey rlwe.EvaluationKeySet) (res *rlwe.Ciphertext, err error) {
|
||||
|
||||
@@ -16,7 +16,7 @@ const (
|
||||
|
||||
// BlindRotationEvaluationKeySet is a interface implementing methods
|
||||
// to load the blind rotation keys (RGSW) and automorphism keys
|
||||
// (via the rlwe.EvaluationKeySet interface).
|
||||
// (via the [rlwe.EvaluationKeySet] interface).
|
||||
// Implementation of this interface must be safe for concurrent use.
|
||||
type BlindRotationEvaluationKeySet interface {
|
||||
|
||||
@@ -28,7 +28,7 @@ type BlindRotationEvaluationKeySet interface {
|
||||
GetEvaluationKeySet() (evk rlwe.EvaluationKeySet, err error)
|
||||
}
|
||||
|
||||
// MemBlindRotationEvaluationKeySet is a basic in-memory implementation of the BlindRotationEvaluationKeySet interface.
|
||||
// MemBlindRotationEvaluationKeySet is a basic in-memory implementation of the [BlindRotationEvaluationKeySet] interface.
|
||||
type MemBlindRotationEvaluationKeySet struct {
|
||||
BlindRotationKeys []*rgsw.Ciphertext
|
||||
AutomorphismKeys []*rlwe.GaloisKey
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/tuneinsight/lattigo/v5/ring"
|
||||
)
|
||||
|
||||
// Ensures that the Evaluator complies to the he.Bootstrapper interface
|
||||
// Ensures that the Evaluator complies to the [he.Bootstrapper] interface
|
||||
var _ he.Bootstrapper[rlwe.Ciphertext] = (*Evaluator)(nil)
|
||||
|
||||
// Bootstrap bootstraps a single ciphertext and returns the bootstrapped ciphertext.
|
||||
|
||||
@@ -24,11 +24,11 @@ import (
|
||||
// can be used to do a scale matching.
|
||||
//
|
||||
// The circuit consists in 5 steps.
|
||||
// 1) ScaleDown: scales the ciphertext to q/|m| and bringing it down to q
|
||||
// 2) ModUp: brings the modulus from q to Q
|
||||
// 3) CoeffsToSlots: homomorphic encoding
|
||||
// 4) EvalMod: homomorphic modular reduction
|
||||
// 5) SlotsToCoeffs: homomorphic decoding
|
||||
// 1. ScaleDown: scales the ciphertext to q/|m| and bringing it down to q
|
||||
// 2. ModUp: brings the modulus from q to Q
|
||||
// 3. CoeffsToSlots: homomorphic encoding
|
||||
// 4. EvalMod: homomorphic modular reduction
|
||||
// 5. SlotsToCoeffs: homomorphic decoding
|
||||
func (eval Evaluator) Evaluate(ctIn *rlwe.Ciphertext) (ctOut *rlwe.Ciphertext, err error) {
|
||||
|
||||
if eval.IterationsParameters == nil && eval.ResidualParameters.PrecisionMode() != ckks.PREC128 {
|
||||
@@ -275,8 +275,9 @@ func (eval Evaluator) bootstrap(ctIn *rlwe.Ciphertext) (ctOut *rlwe.Ciphertext,
|
||||
|
||||
// ScaleDown brings the ciphertext level to zero and scaling factor to Q[0]/MessageRatio
|
||||
// It multiplies the ciphertexts by round(currentMessageRatio / targetMessageRatio) where:
|
||||
// - currentMessageRatio = Q/ctIn.Scale
|
||||
// - targetMessageRatio = q/|m|
|
||||
// - currentMessageRatio = Q/ctIn.Scale
|
||||
// - targetMessageRatio = q/|m|
|
||||
//
|
||||
// and updates the scale of ctIn accordingly
|
||||
// It then rescales the ciphertext down to q if necessary and also returns the rescaling error from this process
|
||||
func (eval Evaluator) ScaleDown(ctIn *rlwe.Ciphertext) (*rlwe.Ciphertext, *rlwe.Scale, error) {
|
||||
|
||||
@@ -37,7 +37,7 @@ type Evaluator struct {
|
||||
SkDebug *rlwe.SecretKey
|
||||
}
|
||||
|
||||
// NewEvaluator creates a new Evaluator.
|
||||
// NewEvaluator creates a new [Evaluator].
|
||||
func NewEvaluator(btpParams Parameters, evk *EvaluationKeys) (eval *Evaluator, err error) {
|
||||
|
||||
eval = &Evaluator{}
|
||||
@@ -119,7 +119,7 @@ func NewEvaluator(btpParams Parameters, evk *EvaluationKeys) (eval *Evaluator, e
|
||||
return
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of this Evaluator in which all the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of this [Evaluator] in which all the read-only data-structures are
|
||||
// shared with the receiver and the temporary buffers are reallocated. The receiver and the returned
|
||||
// Evaluator can be used concurrently.
|
||||
func (eval Evaluator) ShallowCopy() *Evaluator {
|
||||
@@ -153,7 +153,7 @@ func (eval Evaluator) ShallowCopy() *Evaluator {
|
||||
}
|
||||
}
|
||||
|
||||
// CheckKeys checks if all the necessary keys are present in the instantiated Evaluator
|
||||
// CheckKeys checks if all the necessary keys are present in the instantiated [Evaluator]
|
||||
func (eval Evaluator) checkKeys(evk *EvaluationKeys) (err error) {
|
||||
|
||||
if _, err = evk.GetRelinearizationKey(); err != nil {
|
||||
|
||||
@@ -75,15 +75,15 @@ func (b EvaluationKeys) BinarySize() (dLen int) {
|
||||
|
||||
// GenEvaluationKeys generates the bootstrapping evaluation keys, which include:
|
||||
//
|
||||
// - If the bootstrapping parameters' ring degree > residual parameters' ring degree:
|
||||
// If the bootstrapping parameters' ring degree > residual parameters' ring degree:
|
||||
// - An evaluation key to switch from the residual parameters' ring to the bootstrapping parameters' ring
|
||||
// - An evaluation key to switch from the bootstrapping parameters' ring to the residual parameters' ring
|
||||
//
|
||||
// - If the residual parameters use the Conjugate Invariant ring:
|
||||
// If the residual parameters use the Conjugate Invariant ring:
|
||||
// - An evaluation key to switch from the conjugate invariant ring to the standard ring
|
||||
// - An evaluation key to switch from the standard ring to the conjugate invariant ring
|
||||
//
|
||||
// - The core bootstrapping circuit evaluation keys:
|
||||
// The core bootstrapping circuit evaluation keys:
|
||||
// - Relinearization key
|
||||
// - Galois keys
|
||||
// - The encapsulation evaluation keys (https://eprint.iacr.org/2022/024)
|
||||
|
||||
@@ -33,20 +33,20 @@ type Parameters struct {
|
||||
CircuitOrder CircuitOrder
|
||||
}
|
||||
|
||||
// NewParametersFromLiteral instantiates a Parameters from the residual hefloat.Parameters and
|
||||
// NewParametersFromLiteral instantiates a Parameters from the residual [hefloat.Parameters] and
|
||||
// a bootstrapping.ParametersLiteral struct.
|
||||
//
|
||||
// The residualParameters corresponds to the hefloat.Parameters that are left after the bootstrapping circuit is evaluated.
|
||||
// The residualParameters corresponds to the [hefloat.Parameters] that are left after the bootstrapping circuit is evaluated.
|
||||
// These are entirely independent of the bootstrapping parameters with one exception: the ciphertext primes Qi must be
|
||||
// congruent to 1 mod 2N of the bootstrapping parameters (note that the auxiliary primes Pi do not need to be).
|
||||
// This is required because the primes Qi of the residual parameters and the bootstrapping parameters are the same between
|
||||
// the two sets of parameters.
|
||||
//
|
||||
// The user can ensure that this condition is met by setting the appropriate LogNThRoot in the hefloat.ParametersLiteral before
|
||||
// The user can ensure that this condition is met by setting the appropriate LogNThRoot in the [hefloat.ParametersLiteral] before
|
||||
// instantiating them.
|
||||
//
|
||||
// The method NewParametersFromLiteral will automatically allocate the hefloat.Parameters of the bootstrapping circuit based on
|
||||
// the provided residualParameters and the information given in the bootstrapping.ParametersLiteral.
|
||||
// The method NewParametersFromLiteral will automatically allocate the [hefloat.Parameters] of the bootstrapping circuit based on
|
||||
// the provided residualParameters and the information given in the [bootstrapping.ParametersLiteral].
|
||||
func NewParametersFromLiteral(residualParameters hefloat.Parameters, btpLit ParametersLiteral) (Parameters, error) {
|
||||
|
||||
var err error
|
||||
@@ -389,13 +389,13 @@ func (p Parameters) Depth() (depth int) {
|
||||
}
|
||||
|
||||
// MarshalBinary returns a JSON representation of the Parameters struct.
|
||||
// See `Marshal` from the `encoding/json` package.
|
||||
// See Marshal from the [encoding/json] package.
|
||||
func (p Parameters) MarshalBinary() (data []byte, err error) {
|
||||
return json.Marshal(p)
|
||||
}
|
||||
|
||||
// UnmarshalBinary reads a JSON representation on the target Parameters struct.
|
||||
// See `Unmarshal` from the `encoding/json` package.
|
||||
// See Unmarshal from the [encoding/json] package.
|
||||
func (p *Parameters) UnmarshalBinary(data []byte) (err error) {
|
||||
return json.Unmarshal(data, p)
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ import (
|
||||
)
|
||||
|
||||
// ParametersLiteral is a struct to parameterize the bootstrapping parameters.
|
||||
// The `ParametersLiteral` struct an unchecked struct that is given to the method `NewParametersFromLiteral` to validate them
|
||||
// and create the bootstrapping `Parameter` struct, which is used to instantiate a `Bootstrapper`.
|
||||
// The ParametersLiteral struct an unchecked struct that is given to the method [NewParametersFromLiteral] to validate them
|
||||
// and create the bootstrapping [Parameters] struct, which is used to instantiate a Bootstrapper.
|
||||
// This struct contains only optional fields.
|
||||
// The default bootstrapping (with no optional field) has
|
||||
// - Depth 4 for CoeffsToSlots
|
||||
@@ -67,8 +67,8 @@ import (
|
||||
// See https://eprint.iacr.org/2022/024 for more information.
|
||||
//
|
||||
// IterationsParameters : by treating the bootstrapping as a black box with precision logprec, we can construct a bootstrapping of precision ~k*logprec by iteration (see https://eprint.iacr.org/2022/1167).
|
||||
// - BootstrappingPrecision: []float64, the list of iterations (after the initial bootstrapping) given by the expected precision of each previous iteration.
|
||||
// - ReservedPrimeBitSize: the size of the reserved prime for the scaling after the initial bootstrapping.
|
||||
// - BootstrappingPrecision: []float64, the list of iterations (after the initial bootstrapping) given by the expected precision of each previous iteration.
|
||||
// - ReservedPrimeBitSize: the size of the reserved prime for the scaling after the initial bootstrapping.
|
||||
//
|
||||
// For example: &bootstrapping.IterationsParameters{BootstrappingPrecision: []float64{16}, ReservedPrimeBitSize: 16} will define a two iteration bootstrapping (the first iteration being the initial bootstrapping)
|
||||
// with a additional prime close to 2^{16} reserved for the scaling of the error during the second iteration.
|
||||
@@ -76,19 +76,21 @@ import (
|
||||
// Here is an example for a two iterations bootstrapping of an input message mod [logq0=55, logq1=45] with scaling factor 2^{90}:
|
||||
//
|
||||
// INPUT:
|
||||
// 1) The input is a ciphertext encrypting [2^{90} * M]_{q0, q1}
|
||||
// 1. The input is a ciphertext encrypting [2^{90} * M]_{q0, q1}
|
||||
//
|
||||
// ITERATION N°0
|
||||
// 2) Rescale [M^{90}]_{q0, q1} to [M^{90}/q1]_{q0} (ensure that M^{90}/q1 ~ q0/messageratio by additional scaling if necessary)
|
||||
// 3) Bootsrap [M^{90}/q1]_{q0} to [M^{90}/q1 + e^{90 - logprec}/q1]_{q0, q1, q2, ...}
|
||||
// 4) Scale up [M^{90}/q1 + e^{90 - logprec}/q1]_{q0, q1, q2, ...} to [M^{d} + e^{d - logprec}]_{q0, q1, q2, ...}
|
||||
// 2. Rescale [M^{90}]_{q0, q1} to [M^{90}/q1]_{q0} (ensure that M^{90}/q1 ~ q0/messageratio by additional scaling if necessary)
|
||||
// 3. Bootsrap [M^{90}/q1]_{q0} to [M^{90}/q1 + e^{90 - logprec}/q1]_{q0, q1, q2, ...}
|
||||
// 4. Scale up [M^{90}/q1 + e^{90 - logprec}/q1]_{q0, q1, q2, ...} to [M^{d} + e^{d - logprec}]_{q0, q1, q2, ...}
|
||||
//
|
||||
// ITERATION N°1
|
||||
// 5) Subtract [M^{d}]_{q0, q1} to [M^{d} + e^{d - logprec}]_{q0, q1, q2, ...} to get [e^{d - logprec}]_{q0, q1}
|
||||
// 6) Scale up [e^{90 - logprec}]_{q0, q1} by 2^{logprec} to get [e^{d}]_{q0, q1}
|
||||
// 7) Rescale [e^{90}]_{q0, q1} to [{90}/q1]_{q0}
|
||||
// 8) Bootsrap [e^{90}/q1]_{q0} to [e^{90}/q1 + e'^{90 - logprec}/q1]_{q0, q1, q2, ...}
|
||||
// 9) Scale up [e^{90}/q1 + e'^{90 - logprec}/q0]_{q0, q1, q2, ...} by round(q1/2^{logprec}) to get [e^{90-logprec} + e'^{90 - 2logprec}]_{q0, q1, q2, ...}
|
||||
// 10) Subtract [e^{d - logprec} + e'^{d - 2logprec}]_{q0, q1, q2, ...} to [M^{d} + e^{d - logprec}]_{q0, q1, q2, ...} to get [M^{d} + e'^{d - 2logprec}]_{q0, q1, q2, ...}
|
||||
// 11) Go back to step 5 for more iterations until 2^{k * logprec} >= 2^{90}
|
||||
// 5. Subtract [M^{d}]_{q0, q1} to [M^{d} + e^{d - logprec}]_{q0, q1, q2, ...} to get [e^{d - logprec}]_{q0, q1}
|
||||
// 6. Scale up [e^{90 - logprec}]_{q0, q1} by 2^{logprec} to get [e^{d}]_{q0, q1}
|
||||
// 7. Rescale [e^{90}]_{q0, q1} to [{90}/q1]_{q0}
|
||||
// 8. Bootsrap [e^{90}/q1]_{q0} to [e^{90}/q1 + e'^{90 - logprec}/q1]_{q0, q1, q2, ...}
|
||||
// 9. Scale up [e^{90}/q1 + e'^{90 - logprec}/q0]_{q0, q1, q2, ...} by round(q1/2^{logprec}) to get [e^{90-logprec} + e'^{90 - 2logprec}]_{q0, q1, q2, ...}
|
||||
// 10. Subtract [e^{d - logprec} + e'^{d - 2logprec}]_{q0, q1, q2, ...} to [M^{d} + e^{d - logprec}]_{q0, q1, q2, ...} to get [M^{d} + e'^{d - 2logprec}]_{q0, q1, q2, ...}
|
||||
// 11. Go back to step 5 for more iterations until 2^{k * logprec} >= 2^{90}
|
||||
//
|
||||
// This example can be generalized to input messages of any scaling factor and desired output precision by increasing the input scaling factor and substituting q1 by a larger product of primes.
|
||||
//
|
||||
@@ -111,7 +113,7 @@ import (
|
||||
// When using a small ratio (i.e. 2^4), for example if ct.PlaintextScale is close to Q[0] is small or if |m| is large, the Mod1InvDegree can be set to
|
||||
// a non zero value (i.e. 5 or 7). This will greatly improve the precision of the bootstrapping, at the expense of slightly increasing its depth.
|
||||
//
|
||||
// Mod1Type: the type of approximation for the modular reduction polynomial. By default set to hefloat.CosDiscrete.
|
||||
// Mod1Type: the type of approximation for the modular reduction polynomial. By default set to [hefloat.CosDiscrete].
|
||||
//
|
||||
// K: the range of the approximation interval, by default set to 16.
|
||||
//
|
||||
@@ -191,18 +193,18 @@ type IterationsParameters struct {
|
||||
}
|
||||
|
||||
// MarshalBinary returns a JSON representation of the the target ParametersLiteral struct on a slice of bytes.
|
||||
// See `Marshal` from the `encoding/json` package.
|
||||
// See Marshal from the [encoding/json] package.
|
||||
func (p ParametersLiteral) MarshalBinary() (data []byte, err error) {
|
||||
return json.Marshal(p)
|
||||
}
|
||||
|
||||
// UnmarshalBinary reads a JSON representation on the target ParametersLiteral struct.
|
||||
// See `Unmarshal` from the `encoding/json` package.
|
||||
// See Unmarshal from the [encoding/json] package.
|
||||
func (p *ParametersLiteral) UnmarshalBinary(data []byte) (err error) {
|
||||
return json.Unmarshal(data, p)
|
||||
}
|
||||
|
||||
// GetLogN returns the LogN field of the target ParametersLiteral.
|
||||
// GetLogN returns the LogN field of the target [ParametersLiteral].
|
||||
// The default value DefaultLogN is returned if the field is nil.
|
||||
func (p ParametersLiteral) GetLogN() (LogN int) {
|
||||
if v := p.LogN; v == nil {
|
||||
@@ -214,7 +216,7 @@ func (p ParametersLiteral) GetLogN() (LogN int) {
|
||||
return
|
||||
}
|
||||
|
||||
// GetDefaultXs returns the Xs field of the target ParametersLiteral.
|
||||
// GetDefaultXs returns the Xs field of the target [ParametersLiteral].
|
||||
// The default value DefaultXs is returned if the field is nil.
|
||||
func (p ParametersLiteral) GetDefaultXs() (Xs ring.DistributionParameters) {
|
||||
if v := p.Xs; v == nil {
|
||||
@@ -226,7 +228,7 @@ func (p ParametersLiteral) GetDefaultXs() (Xs ring.DistributionParameters) {
|
||||
return
|
||||
}
|
||||
|
||||
// GetDefaultXe returns the Xe field of the target ParametersLiteral.
|
||||
// GetDefaultXe returns the Xe field of the target [ParametersLiteral].
|
||||
// The default value DefaultXe is returned if the field is nil.
|
||||
func (p ParametersLiteral) GetDefaultXe() (Xe ring.DistributionParameters) {
|
||||
if v := p.Xe; v == nil {
|
||||
@@ -254,7 +256,7 @@ func (p ParametersLiteral) GetLogP(NumberOfQi int) (LogP []int) {
|
||||
return
|
||||
}
|
||||
|
||||
// GetLogSlots returns the LogSlots field of the target ParametersLiteral.
|
||||
// GetLogSlots returns the LogSlots field of the target [ParametersLiteral].
|
||||
// The default value LogN-1 is returned if the field is nil.
|
||||
func (p ParametersLiteral) GetLogSlots() (LogSlots int, err error) {
|
||||
|
||||
@@ -274,8 +276,8 @@ func (p ParametersLiteral) GetLogSlots() (LogSlots int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// GetCoeffsToSlotsFactorizationDepthAndLogScales returns a copy of the CoeffsToSlotsFactorizationDepthAndLogScales field of the target ParametersLiteral.
|
||||
// The default value constructed from DefaultC2SFactorization and DefaultC2SLogScale is returned if the field is nil.
|
||||
// GetCoeffsToSlotsFactorizationDepthAndLogScales returns a copy of the CoeffsToSlotsFactorizationDepthAndLogScales field of the target [ParametersLiteral].
|
||||
// The default value constructed from [DefaultSlotsToCoeffsFactorizationDepth] and [DefaultSlotsToCoeffsLogScale] is returned if the field is nil.
|
||||
func (p ParametersLiteral) GetCoeffsToSlotsFactorizationDepthAndLogScales(LogSlots int) (CoeffsToSlotsFactorizationDepthAndLogScales [][]int, err error) {
|
||||
if p.CoeffsToSlotsFactorizationDepthAndLogScales == nil {
|
||||
CoeffsToSlotsFactorizationDepthAndLogScales = make([][]int, utils.Min(DefaultCoeffsToSlotsFactorizationDepth, utils.Max(LogSlots, 1)))
|
||||
@@ -297,8 +299,8 @@ func (p ParametersLiteral) GetCoeffsToSlotsFactorizationDepthAndLogScales(LogSlo
|
||||
return
|
||||
}
|
||||
|
||||
// GetSlotsToCoeffsFactorizationDepthAndLogScales returns a copy of the SlotsToCoeffsFactorizationDepthAndLogScales field of the target ParametersLiteral.
|
||||
// The default value constructed from DefaultS2CFactorization and DefaultS2CLogScale is returned if the field is nil.
|
||||
// GetSlotsToCoeffsFactorizationDepthAndLogScales returns a copy of the SlotsToCoeffsFactorizationDepthAndLogScales field of the target [ParametersLiteral].
|
||||
// The default value constructed from [DefaultSlotsToCoeffsFactorizationDepth] and [DefaultSlotsToCoeffsLogScale] is returned if the field is nil.
|
||||
func (p ParametersLiteral) GetSlotsToCoeffsFactorizationDepthAndLogScales(LogSlots int) (SlotsToCoeffsFactorizationDepthAndLogScales [][]int, err error) {
|
||||
if p.SlotsToCoeffsFactorizationDepthAndLogScales == nil {
|
||||
SlotsToCoeffsFactorizationDepthAndLogScales = make([][]int, utils.Min(DefaultSlotsToCoeffsFactorizationDepth, utils.Max(LogSlots, 1)))
|
||||
@@ -320,8 +322,8 @@ func (p ParametersLiteral) GetSlotsToCoeffsFactorizationDepthAndLogScales(LogSlo
|
||||
return
|
||||
}
|
||||
|
||||
// GetEvalMod1LogScale returns the EvalModLogScale field of the target ParametersLiteral.
|
||||
// The default value DefaultEvalModLogScale is returned if the field is nil.
|
||||
// GetEvalMod1LogScale returns the EvalModLogScale field of the target [ParametersLiteral].
|
||||
// The default value [DefaultEvalModLogScale] is returned if the field is nil.
|
||||
func (p ParametersLiteral) GetEvalMod1LogScale() (EvalModLogScale int, err error) {
|
||||
if v := p.EvalModLogScale; v == nil {
|
||||
EvalModLogScale = DefaultEvalModLogScale
|
||||
@@ -337,7 +339,7 @@ func (p ParametersLiteral) GetEvalMod1LogScale() (EvalModLogScale int, err error
|
||||
return
|
||||
}
|
||||
|
||||
// GetIterationsParameters returns the IterationsParameters field of the target ParametersLiteral.
|
||||
// GetIterationsParameters returns the [IterationsParameters] field of the target [ParametersLiteral].
|
||||
// The default value is nil.
|
||||
func (p ParametersLiteral) GetIterationsParameters() (Iterations *IterationsParameters, err error) {
|
||||
|
||||
@@ -363,8 +365,8 @@ func (p ParametersLiteral) GetIterationsParameters() (Iterations *IterationsPara
|
||||
}
|
||||
}
|
||||
|
||||
// GetLogMessageRatio returns the LogMessageRatio field of the target ParametersLiteral.
|
||||
// The default value DefaultLogMessageRatio is returned if the field is nil.
|
||||
// GetLogMessageRatio returns the []LogMessageRatio field of the target [ParametersLiteral].
|
||||
// The default value [DefaultLogMessageRatio] is returned if the field is nil.
|
||||
func (p ParametersLiteral) GetLogMessageRatio() (LogMessageRatio int, err error) {
|
||||
if v := p.LogMessageRatio; v == nil {
|
||||
LogMessageRatio = DefaultLogMessageRatio
|
||||
@@ -379,8 +381,8 @@ func (p ParametersLiteral) GetLogMessageRatio() (LogMessageRatio int, err error)
|
||||
return
|
||||
}
|
||||
|
||||
// GetK returns the K field of the target ParametersLiteral.
|
||||
// The default value DefaultK is returned if the field is nil.
|
||||
// GetK returns the K field of the target [ParametersLiteral].
|
||||
// The default value [DefaultK] is returned if the field is nil.
|
||||
func (p ParametersLiteral) GetK() (K int, err error) {
|
||||
if v := p.K; v == nil {
|
||||
K = DefaultK
|
||||
@@ -395,14 +397,14 @@ func (p ParametersLiteral) GetK() (K int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// GetMod1Type returns the Mod1Type field of the target ParametersLiteral.
|
||||
// The default value DefaultMod1Type is returned if the field is nil.
|
||||
// GetMod1Type returns the Mod1Type field of the target [ParametersLiteral].
|
||||
// The default value [DefaultMod1Type] is returned if the field is nil.
|
||||
func (p ParametersLiteral) GetMod1Type() (Mod1Type hefloat.Mod1Type) {
|
||||
return p.Mod1Type
|
||||
}
|
||||
|
||||
// GetDoubleAngle returns the DoubleAngle field of the target ParametersLiteral.
|
||||
// The default value DefaultDoubleAngle is returned if the field is nil.
|
||||
// GetDoubleAngle returns the DoubleAngle field of the target [ParametersLiteral].
|
||||
// The default value [DefaultDoubleAngle] is returned if the field is nil.
|
||||
func (p ParametersLiteral) GetDoubleAngle() (DoubleAngle int, err error) {
|
||||
|
||||
if v := p.DoubleAngle; v == nil {
|
||||
@@ -424,8 +426,8 @@ func (p ParametersLiteral) GetDoubleAngle() (DoubleAngle int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// GetMod1Degree returns the Mod1Degree field of the target ParametersLiteral.
|
||||
// The default value DefaultMod1Degree is returned if the field is nil.
|
||||
// GetMod1Degree returns the Mod1Degree field of the target [ParametersLiteral].
|
||||
// The default value [DefaultMod1Degree] is returned if the field is nil.
|
||||
func (p ParametersLiteral) GetMod1Degree() (Mod1Degree int, err error) {
|
||||
if v := p.Mod1Degree; v == nil {
|
||||
Mod1Degree = DefaultMod1Degree
|
||||
@@ -439,8 +441,8 @@ func (p ParametersLiteral) GetMod1Degree() (Mod1Degree int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// GetMod1InvDegree returns the Mod1InvDegree field of the target ParametersLiteral.
|
||||
// The default value DefaultMod1InvDegree is returned if the field is nil.
|
||||
// GetMod1InvDegree returns the Mod1InvDegree field of the target [ParametersLiteral].
|
||||
// The default value [DefaultMod1InvDegree] is returned if the field is nil.
|
||||
func (p ParametersLiteral) GetMod1InvDegree() (Mod1InvDegree int, err error) {
|
||||
if v := p.Mod1InvDegree; v == nil {
|
||||
Mod1InvDegree = DefaultMod1InvDegree
|
||||
@@ -455,8 +457,8 @@ func (p ParametersLiteral) GetMod1InvDegree() (Mod1InvDegree int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// GetEphemeralSecretWeight returns the EphemeralSecretWeight field of the target ParametersLiteral.
|
||||
// The default value DefaultEphemeralSecretWeight is returned if the field is nil.
|
||||
// GetEphemeralSecretWeight returns the EphemeralSecretWeight field of the target [ParametersLiteral].
|
||||
// The default value [DefaultEphemeralSecretWeight] is returned if the field is nil.
|
||||
func (p ParametersLiteral) GetEphemeralSecretWeight() (EphemeralSecretWeight int, err error) {
|
||||
if v := p.EphemeralSecretWeight; v == nil {
|
||||
EphemeralSecretWeight = DefaultEphemeralSecretWeight
|
||||
@@ -471,7 +473,7 @@ func (p ParametersLiteral) GetEphemeralSecretWeight() (EphemeralSecretWeight int
|
||||
}
|
||||
|
||||
// BitConsumption returns the expected consumption in bits of
|
||||
// bootstrapping circuit of the target ParametersLiteral.
|
||||
// bootstrapping circuit of the target [ParametersLiteral].
|
||||
// The value is rounded up and thus will overestimate the value by up to 1 bit.
|
||||
func (p ParametersLiteral) BitConsumption(LogSlots int) (logQ int, err error) {
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"github.com/tuneinsight/lattigo/v5/utils/bignum"
|
||||
)
|
||||
|
||||
// SecretKeyBootstrapper is an implementation of the rlwe.Bootstrapping interface that
|
||||
// SecretKeyBootstrapper is an implementation of the [rlwe.Bootstrapping] interface that
|
||||
// uses the secret-key to decrypt and re-encrypt the bootstrapped ciphertext.
|
||||
type SecretKeyBootstrapper struct {
|
||||
hefloat.Parameters
|
||||
|
||||
@@ -15,8 +15,8 @@ import (
|
||||
"github.com/tuneinsight/lattigo/v5/utils/bignum"
|
||||
)
|
||||
|
||||
// EvaluatorForDFT is an interface defining the set of methods required to instantiate a DFTEvaluator.
|
||||
// The default hefloat.Evaluator is compliant to this interface.
|
||||
// EvaluatorForDFT is an interface defining the set of methods required to instantiate a [DFTEvaluator].
|
||||
// The default [hefloat.Evaluator] is compliant to this interface.
|
||||
type EvaluatorForDFT interface {
|
||||
rlwe.ParameterProvider
|
||||
he.EvaluatorForLinearTransformation
|
||||
@@ -135,13 +135,13 @@ func (d DFTMatrixLiteral) GaloisElements(params Parameters) (galEls []uint64) {
|
||||
}
|
||||
|
||||
// MarshalBinary returns a JSON representation of the the target DFTMatrixLiteral on a slice of bytes.
|
||||
// See `Marshal` from the `encoding/json` package.
|
||||
// See Marshal from the [encoding/json] package.
|
||||
func (d DFTMatrixLiteral) MarshalBinary() (data []byte, err error) {
|
||||
return json.Marshal(d)
|
||||
}
|
||||
|
||||
// UnmarshalBinary reads a JSON representation on the target DFTMatrixLiteral struct.
|
||||
// See `Unmarshal` from the `encoding/json` package.
|
||||
// See Unmarshal from the [encoding/json] package.
|
||||
func (d *DFTMatrixLiteral) UnmarshalBinary(data []byte) error {
|
||||
return json.Unmarshal(data, d)
|
||||
}
|
||||
@@ -154,8 +154,8 @@ type DFTEvaluator struct {
|
||||
parameters Parameters
|
||||
}
|
||||
|
||||
// NewDFTEvaluator instantiates a new DFTEvaluator.
|
||||
// The default hefloat.Evaluator is compliant to the EvaluatorForDFT interface.
|
||||
// NewDFTEvaluator instantiates a new [DFTEvaluator].
|
||||
// The default [hefloat.Evaluator] is compliant to the [EvaluatorForDFT] interface.
|
||||
func NewDFTEvaluator(params Parameters, eval EvaluatorForDFT) *DFTEvaluator {
|
||||
dfteval := new(DFTEvaluator)
|
||||
dfteval.EvaluatorForDFT = eval
|
||||
@@ -350,7 +350,7 @@ func (eval *DFTEvaluator) SlotsToCoeffs(ctReal, ctImag *rlwe.Ciphertext, stcMatr
|
||||
return
|
||||
}
|
||||
|
||||
// dft evaluates a series of LinearTransformation sequentially on the ctIn and stores the result in opOut.
|
||||
// dft evaluates a series of [LinearTransformation] sequentially on the ctIn and stores the result in opOut.
|
||||
func (eval *DFTEvaluator) dft(ctIn *rlwe.Ciphertext, matrices []LinearTransformation, opOut *rlwe.Ciphertext) (err error) {
|
||||
|
||||
inputLogSlots := ctIn.LogDimensions
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
)
|
||||
|
||||
// EvaluatorForInverse defines a set of common and scheme agnostic
|
||||
// methods that are necessary to instantiate an InverseEvaluator.
|
||||
// The default hefloat.Evaluator is compliant to this interface.
|
||||
// methods that are necessary to instantiate an [InverseEvaluator].
|
||||
// The default [hefloat.Evaluator] is compliant to this interface.
|
||||
type EvaluatorForInverse interface {
|
||||
EvaluatorForMinimaxCompositePolynomial
|
||||
SetScale(ct *rlwe.Ciphertext, scale rlwe.Scale) (err error)
|
||||
@@ -26,9 +26,9 @@ type InverseEvaluator struct {
|
||||
Parameters Parameters
|
||||
}
|
||||
|
||||
// NewInverseEvaluator instantiates a new InverseEvaluator.
|
||||
// The default hefloat.Evaluator is compliant to the EvaluatorForInverse interface.
|
||||
// The field he.Bootstrapper[rlwe.Ciphertext] can be nil if the parameters have enough levels to support the computation.
|
||||
// NewInverseEvaluator instantiates a new [InverseEvaluator].
|
||||
// The default [hefloat.Evaluator] is compliant to the EvaluatorForInverse interface.
|
||||
// The field [he.Bootstrapper][[rlwe.Ciphertext]] can be nil if the parameters have enough levels to support the computation.
|
||||
// This method is allocation free.
|
||||
func NewInverseEvaluator(params Parameters, eval EvaluatorForInverse, btp he.Bootstrapper[rlwe.Ciphertext]) InverseEvaluator {
|
||||
return InverseEvaluator{
|
||||
@@ -49,7 +49,7 @@ func NewInverseEvaluator(params Parameters, eval EvaluatorForInverse, btp he.Boo
|
||||
//
|
||||
// The user can provide a minimax composite polynomial (signMinimaxPoly) for the sign function in the interval
|
||||
// [-1-e, -2^{log2min}] U [2^{log2min}, 1+e] (where e is an upperbound on the scheme error).
|
||||
// If no such polynomial is provided, then the DefaultMinimaxCompositePolynomialForSign is used by default.
|
||||
// If no such polynomial is provided, then the [DefaultMinimaxCompositePolynomialForSign] is used by default.
|
||||
// Note that the precision of the output of sign(x * c) does not impact the circuit precision since this value ends up being both at
|
||||
// the numerator and denominator, thus cancelling itself.
|
||||
func (eval InverseEvaluator) EvaluateFullDomainNew(ct *rlwe.Ciphertext, log2min, log2max float64, signMinimaxPoly ...MinimaxCompositePolynomial) (cInv *rlwe.Ciphertext, err error) {
|
||||
|
||||
@@ -15,8 +15,8 @@ func (e floatEncoder[T, U]) Encode(values []T, metadata *rlwe.MetaData, output U
|
||||
return e.Encoder.Embed(values, metadata, output)
|
||||
}
|
||||
|
||||
// Diagonals is a wrapper of he.Diagonals.
|
||||
// See he.Diagonals for the documentation.
|
||||
// Diagonals is a wrapper of [he.Diagonals].
|
||||
// See [he.Diagonals] for the documentation.
|
||||
type Diagonals[T Float] he.Diagonals[T]
|
||||
|
||||
// DiagonalsIndexList returns the list of the non-zero diagonals of the square matrix.
|
||||
@@ -25,12 +25,12 @@ func (m Diagonals[T]) DiagonalsIndexList() (indexes []int) {
|
||||
return he.Diagonals[T](m).DiagonalsIndexList()
|
||||
}
|
||||
|
||||
// LinearTransformationParameters is a wrapper of he.LinearTransformationParameters.
|
||||
// See he.LinearTransformationParameters for the documentation.
|
||||
// LinearTransformationParameters is a wrapper of [he.LinearTransformationParameters].
|
||||
// See [he.LinearTransformationParameters] for the documentation.
|
||||
type LinearTransformationParameters he.LinearTransformationParameters
|
||||
|
||||
// LinearTransformation is a wrapper of he.LinearTransformation.
|
||||
// See he.LinearTransformation for the documentation.
|
||||
// LinearTransformation is a wrapper of [he.LinearTransformation].
|
||||
// See [he.LinearTransformation] for the documentation.
|
||||
type LinearTransformation he.LinearTransformation
|
||||
|
||||
// GaloisElements returns the list of Galois elements required to evaluate the linear transformation.
|
||||
@@ -38,14 +38,14 @@ func (lt LinearTransformation) GaloisElements(params rlwe.ParameterProvider) []u
|
||||
return he.LinearTransformation(lt).GaloisElements(params)
|
||||
}
|
||||
|
||||
// NewLinearTransformation instantiates a new LinearTransformation and is a wrapper of he.LinearTransformation.
|
||||
// See he.LinearTransformation for the documentation.
|
||||
// NewLinearTransformation instantiates a new LinearTransformation and is a wrapper of [he.LinearTransformation].
|
||||
// See [he.LinearTransformation] for the documentation.
|
||||
func NewLinearTransformation(params rlwe.ParameterProvider, lt LinearTransformationParameters) LinearTransformation {
|
||||
return LinearTransformation(he.NewLinearTransformation(params, he.LinearTransformationParameters(lt)))
|
||||
}
|
||||
|
||||
// EncodeLinearTransformation is a method used to encode EncodeLinearTransformation and a wrapper of he.EncodeLinearTransformation.
|
||||
// See he.EncodeLinearTransformation for the documentation.
|
||||
// EncodeLinearTransformation is a method used to encode EncodeLinearTransformation and a wrapper of [he.EncodeLinearTransformation].
|
||||
// See [he.EncodeLinearTransformation] for the documentation.
|
||||
func EncodeLinearTransformation[T Float](ecd *Encoder, diagonals Diagonals[T], allocated LinearTransformation) (err error) {
|
||||
return he.EncodeLinearTransformation[T](
|
||||
&floatEncoder[T, ringqp.Poly]{ecd},
|
||||
@@ -58,15 +58,15 @@ func GaloisElementsForLinearTransformation(params rlwe.ParameterProvider, lt Lin
|
||||
return he.GaloisElementsForLinearTransformation(params, lt.DiagonalsIndexList, 1<<lt.LogDimensions.Cols, lt.LogBabyStepGianStepRatio)
|
||||
}
|
||||
|
||||
// LinearTransformationEvaluator is an evaluator providing an API to evaluate linear transformations on rlwe.Ciphertexts.
|
||||
// LinearTransformationEvaluator is an evaluator providing an API to evaluate linear transformations on [rlwe.Ciphertexts].
|
||||
// All fields of this struct are public, enabling custom instantiations.
|
||||
type LinearTransformationEvaluator struct {
|
||||
he.EvaluatorForLinearTransformation
|
||||
he.EvaluatorForDiagonalMatrix
|
||||
}
|
||||
|
||||
// NewLinearTransformationEvaluator instantiates a new LinearTransformationEvaluator from a circuit.EvaluatorForLinearTransformation.
|
||||
// The default hefloat.Evaluator is compliant to the he.EvaluatorForLinearTransformation interface.
|
||||
// NewLinearTransformationEvaluator instantiates a new [LinearTransformationEvaluator] from a circuit.EvaluatorForLinearTransformation.
|
||||
// The default [hefloat.Evaluator] is compliant to the [he.EvaluatorForLinearTransformation] interface.
|
||||
// This method is allocation free.
|
||||
func NewLinearTransformationEvaluator(eval he.EvaluatorForLinearTransformation) (linTransEval *LinearTransformationEvaluator) {
|
||||
return &LinearTransformationEvaluator{
|
||||
@@ -124,7 +124,7 @@ func (eval LinearTransformationEvaluator) EvaluateSequential(ctIn *rlwe.Cipherte
|
||||
return he.EvaluateLinearTranformationSequential(eval.EvaluatorForLinearTransformation, eval.EvaluatorForDiagonalMatrix, ctIn, circuitLTs, opOut)
|
||||
}
|
||||
|
||||
// defaultDiagonalMatrixEvaluator is a struct implementing the interface he.EvaluatorForDiagonalMatrix.
|
||||
// defaultDiagonalMatrixEvaluator is a struct implementing the interface [he.EvaluatorForDiagonalMatrix].
|
||||
type defaultDiagonalMatrixEvaluator struct {
|
||||
he.EvaluatorForLinearTransformation
|
||||
}
|
||||
@@ -140,8 +140,8 @@ func (eval defaultDiagonalMatrixEvaluator) GetPreRotatedCiphertextForDiagonalMat
|
||||
return he.GetPreRotatedCiphertextForDiagonalMatrixMultiplication(levelQ, eval, ctIn, BuffDecompQP, rots, ctPreRot)
|
||||
}
|
||||
|
||||
// MultiplyByDiagMatrix multiplies the Ciphertext "ctIn" by the plaintext matrix "matrix" and returns the result on the Ciphertext
|
||||
// "opOut". Memory buffers for the decomposed ciphertext BuffDecompQP, BuffDecompQP must be provided, those are list of poly of ringQ and ringP
|
||||
// MultiplyByDiagMatrix multiplies the Ciphertext ctIn by the plaintext matrix and returns the result on the Ciphertext
|
||||
// opOut. Memory buffers for the decomposed ciphertext BuffDecompQP, BuffDecompQP must be provided, those are list of poly of ringQ and ringP
|
||||
// respectively, each of size params.Beta().
|
||||
// The naive approach is used (single hoisting and no baby-step giant-step), which is faster than MultiplyByDiagMatrixBSGS
|
||||
// for matrix of only a few non-zero diagonals but uses more keys.
|
||||
@@ -149,7 +149,7 @@ func (eval defaultDiagonalMatrixEvaluator) MultiplyByDiagMatrix(ctIn *rlwe.Ciphe
|
||||
return he.MultiplyByDiagMatrix(eval.EvaluatorForLinearTransformation, ctIn, matrix, BuffDecompQP, opOut)
|
||||
}
|
||||
|
||||
// MultiplyByDiagMatrixBSGS multiplies the Ciphertext "ctIn" by the plaintext matrix "matrix" and returns the result on the Ciphertext "opOut".
|
||||
// MultiplyByDiagMatrixBSGS multiplies the Ciphertext ctIn by the plaintext matrix and returns the result on the Ciphertext opOut.
|
||||
// ctInPreRotated can be obtained with GetPreRotatedCiphertextForDiagonalMatrixMultiplication.
|
||||
// The BSGS approach is used (double hoisting with baby-step giant-step), which is faster than MultiplyByDiagMatrix
|
||||
// for matrix with more than a few non-zero diagonals and uses significantly less keys.
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
// MinimaxCompositePolynomial is a struct storing P(x) = pk(x) o pk-1(x) o ... o p1(x) o p0(x).
|
||||
type MinimaxCompositePolynomial []bignum.Polynomial
|
||||
|
||||
// NewMinimaxCompositePolynomial creates a new MinimaxCompositePolynomial from a list of coefficients.
|
||||
// NewMinimaxCompositePolynomial creates a new [MinimaxCompositePolynomial] from a list of coefficients.
|
||||
// Coefficients are expected to be given in the Chebyshev basis.
|
||||
func NewMinimaxCompositePolynomial(coeffsStr [][]string) MinimaxCompositePolynomial {
|
||||
polys := make([]bignum.Polynomial, len(coeffsStr))
|
||||
@@ -78,7 +78,7 @@ var CoeffsSignX4Cheby = []string{"0", "1.1962890625", "0", "-0.2392578125", "0",
|
||||
//
|
||||
// The sign function is defined as: -1 if -1 <= x < 0, 0 if x = 0, 1 if 0 < x <= 1.
|
||||
//
|
||||
// See GenMinimaxCompositePolynomial for information about how to instantiate and
|
||||
// See [GenMinimaxCompositePolynomial] for information about how to instantiate and
|
||||
// parameterize each input value of the algorithm.
|
||||
func GenMinimaxCompositePolynomialForSign(prec uint, logalpha, logerr int, deg []int) {
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/tuneinsight/lattigo/v5/ring"
|
||||
)
|
||||
|
||||
// EvaluatorForMinimaxCompositePolynomial defines a set of common and scheme agnostic method that are necessary to instantiate a MinimaxCompositePolynomialEvaluator.
|
||||
// EvaluatorForMinimaxCompositePolynomial defines a set of common and scheme agnostic method that are necessary to instantiate a [MinimaxCompositePolynomialEvaluator].
|
||||
type EvaluatorForMinimaxCompositePolynomial interface {
|
||||
he.Evaluator
|
||||
ConjugateNew(ct *rlwe.Ciphertext) (ctConj *rlwe.Ciphertext, err error)
|
||||
@@ -23,14 +23,14 @@ type MinimaxCompositePolynomialEvaluator struct {
|
||||
Parameters Parameters
|
||||
}
|
||||
|
||||
// NewMinimaxCompositePolynomialEvaluator instantiates a new MinimaxCompositePolynomialEvaluator.
|
||||
// The default hefloat.Evaluator is compliant to the EvaluatorForMinimaxCompositePolynomial interface.
|
||||
// NewMinimaxCompositePolynomialEvaluator instantiates a new [MinimaxCompositePolynomialEvaluator].
|
||||
// The default [hefloat.Evaluator] is compliant to the [EvaluatorForMinimaxCompositePolynomial] interface.
|
||||
// This method is allocation free.
|
||||
func NewMinimaxCompositePolynomialEvaluator(params Parameters, eval EvaluatorForMinimaxCompositePolynomial, bootstrapper he.Bootstrapper[rlwe.Ciphertext]) *MinimaxCompositePolynomialEvaluator {
|
||||
return &MinimaxCompositePolynomialEvaluator{eval, *NewPolynomialEvaluator(params, eval), bootstrapper, params}
|
||||
}
|
||||
|
||||
// Evaluate evaluates the provided MinimaxCompositePolynomial on the input ciphertext.
|
||||
// Evaluate evaluates the provided [MinimaxCompositePolynomial] on the input ciphertext.
|
||||
func (eval MinimaxCompositePolynomialEvaluator) Evaluate(ct *rlwe.Ciphertext, mcp MinimaxCompositePolynomial) (res *rlwe.Ciphertext, err error) {
|
||||
|
||||
params := eval.Parameters
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
)
|
||||
|
||||
// EvaluatorForMod1 defines a set of common and scheme agnostic
|
||||
// methods that are necessary to instantiate a Mod1Evaluator.
|
||||
// The default hefloat.Evaluator is compliant to this interface.
|
||||
// methods that are necessary to instantiate a [Mod1Evaluator].
|
||||
// The default [hefloat.Evaluator] is compliant to this interface.
|
||||
type EvaluatorForMod1 interface {
|
||||
he.Evaluator
|
||||
DropLevel(*rlwe.Ciphertext, int)
|
||||
@@ -25,8 +25,8 @@ type Mod1Evaluator struct {
|
||||
Mod1Parameters Mod1Parameters
|
||||
}
|
||||
|
||||
// NewMod1Evaluator instantiates a new Mod1Evaluator evaluator.
|
||||
// The default hefloat.Evaluator is compliant to the EvaluatorForMod1 interface.
|
||||
// NewMod1Evaluator instantiates a new [Mod1Evaluator] evaluator.
|
||||
// The default [hefloat.Evaluator] is compliant to the [EvaluatorForMod1] interface.
|
||||
// This method is allocation free.
|
||||
func NewMod1Evaluator(eval EvaluatorForMod1, evalPoly *PolynomialEvaluator, Mod1Parameters Mod1Parameters) *Mod1Evaluator {
|
||||
return &Mod1Evaluator{EvaluatorForMod1: eval, PolynomialEvaluator: evalPoly, Mod1Parameters: Mod1Parameters}
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
// Mod1Type is the type of function/approximation used to evaluate x mod 1.
|
||||
type Mod1Type uint64
|
||||
|
||||
// Sin and Cos are the two proposed functions for Mod1Type.
|
||||
// Sin and Cos are the two proposed functions for [Mod1Type].
|
||||
// These trigonometric functions offer a good approximation of the function x mod 1 when the values are close to the origin.
|
||||
const (
|
||||
CosDiscrete = Mod1Type(0) // Special approximation (Han and Ki) of pow((1/2pi), 1/2^r) * cos(2pi(x-0.25)/2^r); this method requires a minimum degree of 2*(K-1).
|
||||
@@ -26,7 +26,7 @@ const (
|
||||
|
||||
// Mod1ParametersLiteral a struct for the parameters of the mod 1 procedure.
|
||||
// The x mod 1 procedure goal is to homomorphically evaluate a modular reduction by Q[0] (the first prime of the moduli chain) on the encrypted plaintext.
|
||||
// This struct is consumed by `NewMod1ParametersLiteralFromLiteral` to generate the `Mod1ParametersLiteral` struct, which notably stores
|
||||
// This struct is consumed by [NewMod1ParametersFromLiteral] to generate the [Mod1ParametersLiteral] struct, which notably stores
|
||||
// the coefficient of the polynomial approximating the function x mod Q[0].
|
||||
type Mod1ParametersLiteral struct {
|
||||
LevelStart int // Starting level of x mod 1
|
||||
@@ -41,13 +41,13 @@ type Mod1ParametersLiteral struct {
|
||||
}
|
||||
|
||||
// MarshalBinary returns a JSON representation of the the target Mod1ParametersLiteral struct on a slice of bytes.
|
||||
// See `Marshal` from the `encoding/json` package.
|
||||
// See Marshal from the [encoding/json] package.
|
||||
func (evm Mod1ParametersLiteral) MarshalBinary() (data []byte, err error) {
|
||||
return json.Marshal(evm)
|
||||
}
|
||||
|
||||
// UnmarshalBinary reads a JSON representation on the target Mod1ParametersLiteral struct.
|
||||
// See `Unmarshal` from the `encoding/json` package.
|
||||
// See Unmarshal from the [encoding/json] package.
|
||||
func (evm *Mod1ParametersLiteral) UnmarshalBinary(data []byte) (err error) {
|
||||
return json.Unmarshal(data, evm)
|
||||
}
|
||||
@@ -115,8 +115,8 @@ func (evp Mod1Parameters) QDiff() float64 {
|
||||
return evp.qDiff
|
||||
}
|
||||
|
||||
// NewMod1ParametersFromLiteral generates an Mod1Parameters struct from the Mod1ParametersLiteral struct.
|
||||
// The Mod1Parameters struct is to instantiates a Mod1Evaluator, which homomorphically evaluates x mod 1.
|
||||
// NewMod1ParametersFromLiteral generates an [Mod1Parameters] struct from the [Mod1ParametersLiteral] struct.
|
||||
// The [Mod1Parameters] struct is to instantiates a [Mod1Evaluator], which homomorphically evaluates x mod 1.
|
||||
func NewMod1ParametersFromLiteral(params Parameters, evm Mod1ParametersLiteral) (Mod1Parameters, error) {
|
||||
|
||||
var mod1InvPoly *bignum.Polynomial
|
||||
|
||||
@@ -7,23 +7,23 @@ import (
|
||||
"github.com/tuneinsight/lattigo/v5/utils/bignum"
|
||||
)
|
||||
|
||||
// Polynomial is a type wrapping the type he.Polynomial.
|
||||
// Polynomial is a type wrapping the type [he.Polynomial].
|
||||
type Polynomial he.Polynomial
|
||||
|
||||
// NewPolynomial creates a new Polynomial from a bignum.Polynomial.
|
||||
// NewPolynomial creates a new Polynomial from a [bignum.Polynomial].
|
||||
func NewPolynomial(poly bignum.Polynomial) Polynomial {
|
||||
return Polynomial(he.NewPolynomial(poly))
|
||||
}
|
||||
|
||||
// PolynomialVector is a type wrapping the type he.PolynomialVector.
|
||||
// PolynomialVector is a type wrapping the type [he.PolynomialVector].
|
||||
type PolynomialVector he.PolynomialVector
|
||||
|
||||
// Depth returns the depth of the target PolynomialVector.
|
||||
// Depth returns the depth of the target [PolynomialVector].
|
||||
func (p PolynomialVector) Depth() int {
|
||||
return p.Value[0].Depth()
|
||||
}
|
||||
|
||||
// NewPolynomialVector creates a new PolynomialVector from a list of bignum.Polynomial and a mapping
|
||||
// NewPolynomialVector creates a new [PolynomialVector] from a list of [bignum.Polynomial] and a mapping
|
||||
// map[poly_index][slots_index] which stores which polynomial has to be evaluated on which slot.
|
||||
// Slots that are not referenced in this mapping will be evaluated to zero.
|
||||
// User must ensure that a same slot is not referenced twice.
|
||||
|
||||
@@ -8,14 +8,14 @@ import (
|
||||
"github.com/tuneinsight/lattigo/v5/utils/bignum"
|
||||
)
|
||||
|
||||
// PolynomialEvaluator is a wrapper of the he.PolynomialEvaluator.
|
||||
// PolynomialEvaluator is a wrapper of the [he.PolynomialEvaluator].
|
||||
// All fields of this struct are public, enabling custom instantiations.
|
||||
type PolynomialEvaluator struct {
|
||||
Parameters Parameters
|
||||
he.EvaluatorForPolynomial
|
||||
}
|
||||
|
||||
// NewPowerBasis is a wrapper of NewPolynomialBasis.
|
||||
// NewPowerBasis is a wrapper of [he.NewPolynomialBasis].
|
||||
// This function creates a new powerBasis from the input ciphertext.
|
||||
// The input ciphertext is treated as the base monomial X used to
|
||||
// generate the other powers X^{n}.
|
||||
@@ -23,8 +23,8 @@ func NewPowerBasis(ct *rlwe.Ciphertext, basis bignum.Basis) he.PowerBasis {
|
||||
return he.NewPowerBasis(ct, basis)
|
||||
}
|
||||
|
||||
// NewPolynomialEvaluator instantiates a new PolynomialEvaluator from a circuit.Evaluator.
|
||||
// The default hefloat.Evaluator is compliant to the circuit.Evaluator interface.
|
||||
// NewPolynomialEvaluator instantiates a new [PolynomialEvaluator] from a circuit.Evaluator.
|
||||
// The default [hefloat.Evaluator] is compliant to the circuit.Evaluator interface.
|
||||
// This method is allocation free.
|
||||
func NewPolynomialEvaluator(params Parameters, eval he.Evaluator) *PolynomialEvaluator {
|
||||
return &PolynomialEvaluator{
|
||||
@@ -41,7 +41,7 @@ func NewPolynomialEvaluator(params Parameters, eval he.Evaluator) *PolynomialEva
|
||||
// ct' = scale * ct + offset before the polynomial evaluation to ensure correctness.
|
||||
// The values `scale` and `offet` can be obtained from the polynomial with the method .ChangeOfBasis().
|
||||
//
|
||||
// pol: a *bignum.Polynomial, *Polynomial or *PolynomialVector
|
||||
// pol: a *[bignum.Polynomial], *[Polynomial] or *[PolynomialVector]
|
||||
// targetScale: the desired output scale. This value shouldn't differ too much from the original ciphertext scale. It can
|
||||
// for example be used to correct small deviations in the ciphertext scale and reset it to the default scale.
|
||||
func (eval PolynomialEvaluator) Evaluate(ct *rlwe.Ciphertext, p interface{}, targetScale rlwe.Scale) (opOut *rlwe.Ciphertext, err error) {
|
||||
@@ -62,7 +62,7 @@ func (eval PolynomialEvaluator) Evaluate(ct *rlwe.Ciphertext, p interface{}, tar
|
||||
}
|
||||
|
||||
// EvaluateFromPowerBasis evaluates a polynomial using the provided PowerBasis, holding pre-computed powers of X.
|
||||
// This method is the same as Evaluate except that the encrypted input is a PowerBasis.
|
||||
// This method is the same as Evaluate except that the encrypted input is a [he.PowerBasis].
|
||||
// See Evaluate for additional information.
|
||||
func (eval PolynomialEvaluator) EvaluateFromPowerBasis(pb he.PowerBasis, p interface{}, targetScale rlwe.Scale) (opOut *rlwe.Ciphertext, err error) {
|
||||
|
||||
@@ -86,14 +86,14 @@ func (eval PolynomialEvaluator) EvaluateFromPowerBasis(pb he.PowerBasis, p inter
|
||||
}
|
||||
|
||||
// CoefficientGetter is a struct that implements the
|
||||
// he.CoefficientGetter[*bignum.Complex] interface.
|
||||
// [he.CoefficientGetter][*[bignum.Complex]] interface.
|
||||
type CoefficientGetter struct {
|
||||
Values []*bignum.Complex
|
||||
}
|
||||
|
||||
// GetVectorCoefficient return a slice []*bignum.Complex containing the k-th coefficient
|
||||
// of each polynomial of PolynomialVector indexed by its Mapping.
|
||||
// See PolynomialVector for additional information about the Mapping.
|
||||
// GetVectorCoefficient return a slice []*[bignum.Complex] containing the k-th coefficient
|
||||
// of each polynomial of [PolynomialVector] indexed by its Mapping.
|
||||
// See [PolynomialVector] for additional information about the Mapping.
|
||||
func (c CoefficientGetter) GetVectorCoefficient(pol he.PolynomialVector, k int) (values []*bignum.Complex) {
|
||||
|
||||
values = c.Values
|
||||
@@ -113,22 +113,22 @@ func (c CoefficientGetter) GetVectorCoefficient(pol he.PolynomialVector, k int)
|
||||
return
|
||||
}
|
||||
|
||||
// GetSingleCoefficient returns the k-th coefficient of Polynomial as the type *bignum.Complex.
|
||||
// GetSingleCoefficient returns the k-th coefficient of Polynomial as the type *[bignum.Complex].
|
||||
func (c CoefficientGetter) GetSingleCoefficient(pol he.Polynomial, k int) (value *bignum.Complex) {
|
||||
return pol.Coeffs[k]
|
||||
}
|
||||
|
||||
// ShallowCopy returns a thread-safe copy of the original CoefficientGetter.
|
||||
// ShallowCopy returns a thread-safe copy of the original [CoefficientGetter].
|
||||
func (c CoefficientGetter) ShallowCopy() he.CoefficientGetter[*bignum.Complex] {
|
||||
return &CoefficientGetter{Values: make([]*bignum.Complex, len(c.Values))}
|
||||
}
|
||||
|
||||
// defaultCircuitEvaluatorForPolynomial is a struct implementing the interface he.EvaluatorForPolynomial.
|
||||
// defaultCircuitEvaluatorForPolynomial is a struct implementing the interface [he.EvaluatorForPolynomial].
|
||||
type defaultCircuitEvaluatorForPolynomial struct {
|
||||
he.Evaluator
|
||||
}
|
||||
|
||||
// EvaluatePatersonStockmeyerPolynomialVector evaluates a pre-decomposed PatersonStockmeyerPolynomialVector on a pre-computed power basis [1, X^{1}, X^{2}, ..., X^{2^{n}}, X^{2^{n+1}}, ..., X^{2^{m}}]
|
||||
// EvaluatePatersonStockmeyerPolynomialVector evaluates a pre-decomposed [he.PatersonStockmeyerPolynomialVector] on a pre-computed power basis [1, X^{1}, X^{2}, ..., X^{2^{n}}, X^{2^{n+1}}, ..., X^{2^{m}}]
|
||||
func (eval defaultCircuitEvaluatorForPolynomial) EvaluatePatersonStockmeyerPolynomialVector(poly he.PatersonStockmeyerPolynomialVector, pb he.PowerBasis) (res *rlwe.Ciphertext, err error) {
|
||||
coeffGetter := he.CoefficientGetter[*bignum.Complex](&CoefficientGetter{Values: make([]*bignum.Complex, pb.Value[1].Slots())})
|
||||
return he.EvaluatePatersonStockmeyerPolynomialVector(eval, poly, coeffGetter, pb)
|
||||
|
||||
@@ -15,8 +15,8 @@ func (e intEncoder[T, U]) Encode(values []T, metadata *rlwe.MetaData, output U)
|
||||
return e.Embed(values, false, metadata, output)
|
||||
}
|
||||
|
||||
// Diagonals is a wrapper of he.Diagonals.
|
||||
// See he.Diagonals for the documentation.
|
||||
// Diagonals is a wrapper of [he.Diagonals].
|
||||
// See [he.Diagonals] for the documentation.
|
||||
type Diagonals[T Integer] he.Diagonals[T]
|
||||
|
||||
// DiagonalsIndexList returns the list of the non-zero diagonals of the square matrix.
|
||||
@@ -25,12 +25,12 @@ func (m Diagonals[T]) DiagonalsIndexList() (indexes []int) {
|
||||
return he.Diagonals[T](m).DiagonalsIndexList()
|
||||
}
|
||||
|
||||
// LinearTransformationParameters is a wrapper of he.LinearTransformationParameters.
|
||||
// See he.LinearTransformationParameters for the documentation.
|
||||
// LinearTransformationParameters is a wrapper of [he.LinearTransformationParameters].
|
||||
// See [he.LinearTransformationParameters] for the documentation.
|
||||
type LinearTransformationParameters he.LinearTransformationParameters
|
||||
|
||||
// LinearTransformation is a wrapper of he.LinearTransformation.
|
||||
// See he.LinearTransformation for the documentation.
|
||||
// LinearTransformation is a wrapper of [he.LinearTransformation].
|
||||
// See [he.LinearTransformation] for the documentation.
|
||||
type LinearTransformation he.LinearTransformation
|
||||
|
||||
// GaloisElements returns the list of Galois elements required to evaluate the linear transformation.
|
||||
@@ -38,14 +38,14 @@ func (lt LinearTransformation) GaloisElements(params rlwe.ParameterProvider) []u
|
||||
return he.LinearTransformation(lt).GaloisElements(params)
|
||||
}
|
||||
|
||||
// NewLinearTransformation instantiates a new LinearTransformation and is a wrapper of he.LinearTransformation.
|
||||
// NewLinearTransformation instantiates a new [LinearTransformation] and is a wrapper of [he.LinearTransformation].
|
||||
// See he.LinearTransformation for the documentation.
|
||||
func NewLinearTransformation(params rlwe.ParameterProvider, lt LinearTransformationParameters) LinearTransformation {
|
||||
return LinearTransformation(he.NewLinearTransformation(params, he.LinearTransformationParameters(lt)))
|
||||
}
|
||||
|
||||
// EncodeLinearTransformation is a method used to encode EncodeLinearTransformation and a wrapper of he.EncodeLinearTransformation.
|
||||
// See he.EncodeLinearTransformation for the documentation.
|
||||
// EncodeLinearTransformation is a method used to encode EncodeLinearTransformation and a wrapper of [he.EncodeLinearTransformation].
|
||||
// See [he.EncodeLinearTransformation] for the documentation.
|
||||
func EncodeLinearTransformation[T Integer](ecd *Encoder, diagonals Diagonals[T], allocated LinearTransformation) (err error) {
|
||||
return he.EncodeLinearTransformation[T](
|
||||
&intEncoder[T, ringqp.Poly]{ecd},
|
||||
@@ -58,15 +58,15 @@ func GaloisElementsForLinearTransformation(params rlwe.ParameterProvider, lt Lin
|
||||
return he.GaloisElementsForLinearTransformation(params, lt.DiagonalsIndexList, 1<<lt.LogDimensions.Cols, lt.LogBabyStepGianStepRatio)
|
||||
}
|
||||
|
||||
// LinearTransformationEvaluator is a struct for evaluating linear transformations on rlwe.Ciphertexts.
|
||||
// LinearTransformationEvaluator is a struct for evaluating linear transformations on [rlwe.Ciphertexts].
|
||||
// All fields of this struct are public, enabling custom instantiations.
|
||||
type LinearTransformationEvaluator struct {
|
||||
he.EvaluatorForLinearTransformation
|
||||
he.EvaluatorForDiagonalMatrix
|
||||
}
|
||||
|
||||
// NewLinearTransformationEvaluator instantiates a new LinearTransformationEvaluator from a circuit.EvaluatorForLinearTransformation.
|
||||
// The default heint.Evaluator is compliant to the circuit.EvaluatorForLinearTransformation interface.
|
||||
// NewLinearTransformationEvaluator instantiates a new [LinearTransformationEvaluator] from a circuit.EvaluatorForLinearTransformation.
|
||||
// The default [heint.Evaluator] is compliant to the circuit.EvaluatorForLinearTransformation interface.
|
||||
func NewLinearTransformationEvaluator(eval he.EvaluatorForLinearTransformation) (linTransEval *LinearTransformationEvaluator) {
|
||||
return &LinearTransformationEvaluator{
|
||||
EvaluatorForLinearTransformation: eval,
|
||||
@@ -123,7 +123,7 @@ func (eval LinearTransformationEvaluator) EvaluateSequential(ctIn *rlwe.Cipherte
|
||||
return he.EvaluateLinearTranformationSequential(eval.EvaluatorForLinearTransformation, eval.EvaluatorForDiagonalMatrix, ctIn, circuitLTs, opOut)
|
||||
}
|
||||
|
||||
// defaultDiagonalMatrixEvaluator is a struct implementing the interface he.EvaluatorForDiagonalMatrix.
|
||||
// defaultDiagonalMatrixEvaluator is a struct implementing the interface [he.EvaluatorForDiagonalMatrix].
|
||||
type defaultDiagonalMatrixEvaluator struct {
|
||||
he.EvaluatorForLinearTransformation
|
||||
}
|
||||
@@ -139,8 +139,8 @@ func (eval defaultDiagonalMatrixEvaluator) GetPreRotatedCiphertextForDiagonalMat
|
||||
return he.GetPreRotatedCiphertextForDiagonalMatrixMultiplication(levelQ, eval, ctIn, BuffDecompQP, rots, ctPreRot)
|
||||
}
|
||||
|
||||
// MultiplyByDiagMatrix multiplies the Ciphertext "ctIn" by the plaintext matrix "matrix" and returns the result on the Ciphertext
|
||||
// "opOut". Memory buffers for the decomposed ciphertext BuffDecompQP, BuffDecompQP must be provided, those are list of poly of ringQ and ringP
|
||||
// MultiplyByDiagMatrix multiplies the Ciphertext ctIn by the plaintext matrix and returns the result on the Ciphertext
|
||||
// opOut. Memory buffers for the decomposed ciphertext BuffDecompQP, BuffDecompQP must be provided, those are list of poly of ringQ and ringP
|
||||
// respectively, each of size params.Beta().
|
||||
// The naive approach is used (single hoisting and no baby-step giant-step), which is faster than MultiplyByDiagMatrixBSGS
|
||||
// for matrix of only a few non-zero diagonals but uses more keys.
|
||||
@@ -148,7 +148,7 @@ func (eval defaultDiagonalMatrixEvaluator) MultiplyByDiagMatrix(ctIn *rlwe.Ciphe
|
||||
return he.MultiplyByDiagMatrix(eval.EvaluatorForLinearTransformation, ctIn, matrix, BuffDecompQP, opOut)
|
||||
}
|
||||
|
||||
// MultiplyByDiagMatrixBSGS multiplies the Ciphertext "ctIn" by the plaintext matrix "matrix" and returns the result on the Ciphertext "opOut".
|
||||
// MultiplyByDiagMatrixBSGS multiplies the Ciphertext ctIn by the plaintext matrix and returns the result on the Ciphertext opOut.
|
||||
// ctInPreRotated can be obtained with GetPreRotatedCiphertextForDiagonalMatrixMultiplication.
|
||||
// The BSGS approach is used (double hoisting with baby-step giant-step), which is faster than MultiplyByDiagMatrix
|
||||
// for matrix with more than a few non-zero diagonals and uses significantly less keys.
|
||||
|
||||
@@ -5,18 +5,18 @@ import (
|
||||
"github.com/tuneinsight/lattigo/v5/utils/bignum"
|
||||
)
|
||||
|
||||
// Polynomial is a type wrapping the type he.Polynomial.
|
||||
// Polynomial is a type wrapping the type [he.Polynomial].
|
||||
type Polynomial he.Polynomial
|
||||
|
||||
// NewPolynomial creates a new Polynomial from a list of coefficients []T.
|
||||
// NewPolynomial creates a new [Polynomial] from a list of coefficients []T.
|
||||
func NewPolynomial[T Integer](coeffs []T) Polynomial {
|
||||
return Polynomial(he.NewPolynomial(bignum.NewPolynomial(bignum.Monomial, coeffs, nil)))
|
||||
}
|
||||
|
||||
// PolynomialVector is a type wrapping the type he.PolynomialVector.
|
||||
// PolynomialVector is a type wrapping the type [he.PolynomialVector].
|
||||
type PolynomialVector he.PolynomialVector
|
||||
|
||||
// Depth returns the depth of the target PolynomialVector.
|
||||
// Depth returns the depth of the target [PolynomialVector].
|
||||
func (p PolynomialVector) Depth() int {
|
||||
return p.Value[0].Depth()
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/tuneinsight/lattigo/v5/utils/bignum"
|
||||
)
|
||||
|
||||
// PolynomialEvaluator is a wrapper of the he.PolynomialEvaluator.
|
||||
// PolynomialEvaluator is a wrapper of the [he.PolynomialEvaluator].
|
||||
// All fields of this struct are public, enabling custom instantiations.
|
||||
type PolynomialEvaluator struct {
|
||||
he.EvaluatorForPolynomial
|
||||
@@ -26,8 +26,8 @@ func NewPowerBasis(ct *rlwe.Ciphertext) he.PowerBasis {
|
||||
return he.NewPowerBasis(ct, bignum.Monomial)
|
||||
}
|
||||
|
||||
// NewPolynomialEvaluator instantiates a new PolynomialEvaluator from a circuit.Evaluator.
|
||||
// The default heint.Evaluator is compliant to the circuit.Evaluator interface.
|
||||
// NewPolynomialEvaluator instantiates a new [PolynomialEvaluator] from a circuit.Evaluator.
|
||||
// The default [heint.Evaluator] is compliant to the circuit.Evaluator interface.
|
||||
// InvariantTensoring is a boolean that specifies if the evaluator performed the invariant tensoring (BFV-style) or
|
||||
// the regular tensoring (BGB-style).
|
||||
func NewPolynomialEvaluator(params Parameters, eval he.Evaluator, InvariantTensoring bool) *PolynomialEvaluator {
|
||||
@@ -65,7 +65,7 @@ func NewPolynomialEvaluator(params Parameters, eval he.Evaluator, InvariantTenso
|
||||
// Returns an error if something is wrong with the scale.
|
||||
// If the polynomial is given in Chebyshev basis, then a change of basis ct' = (2/(b-a)) * (ct + (-a-b)/(b-a))
|
||||
// is necessary before the polynomial evaluation to ensure correctness.
|
||||
// pol: a *bignum.Polynomial, *Polynomial or *PolynomialVector
|
||||
// pol: a *[bignum.Polynomial], *[Polynomial] or *[PolynomialVector]
|
||||
// targetScale: the desired output scale. This value shouldn't differ too much from the original ciphertext scale. It can
|
||||
// for example be used to correct small deviations in the ciphertext scale and reset it to the default scale.
|
||||
func (eval PolynomialEvaluator) Evaluate(ct *rlwe.Ciphertext, p interface{}, targetScale rlwe.Scale) (opOut *rlwe.Ciphertext, err error) {
|
||||
@@ -105,7 +105,7 @@ func (eval PolynomialEvaluator) EvaluateFromPowerBasis(pb he.PowerBasis, p inter
|
||||
return he.EvaluatePolynomial(eval.EvaluatorForPolynomial, pb, phe, targetScale, 1, &simEvaluator{eval.Parameters, eval.InvariantTensoring})
|
||||
}
|
||||
|
||||
// scaleInvariantEvaluator is a struct implementing the interface he.Evaluator with
|
||||
// scaleInvariantEvaluator is a struct implementing the interface [he.Evaluator] with
|
||||
// scale invariant tensoring (BFV-style).
|
||||
type scaleInvariantEvaluator struct {
|
||||
*bgv.Evaluator
|
||||
@@ -132,14 +132,14 @@ func (polyEval scaleInvariantEvaluator) Rescale(op0, op1 *rlwe.Ciphertext) (err
|
||||
}
|
||||
|
||||
// CoefficientGetter is a struct that implements the
|
||||
// he.CoefficientGetter[uint64] interface.
|
||||
// [he.CoefficientGetter][uint64] interface.
|
||||
type CoefficientGetter struct {
|
||||
Values []uint64
|
||||
}
|
||||
|
||||
// GetVectorCoefficient return a slice []uint64 containing the k-th coefficient
|
||||
// of each polynomial of PolynomialVector indexed by its Mapping.
|
||||
// See PolynomialVector for additional information about the Mapping.
|
||||
// See [he.PolynomialVector] for additional information about the Mapping.
|
||||
func (c CoefficientGetter) GetVectorCoefficient(pol he.PolynomialVector, k int) (values []uint64) {
|
||||
|
||||
values = c.Values
|
||||
@@ -164,17 +164,17 @@ func (c CoefficientGetter) GetSingleCoefficient(pol he.Polynomial, k int) (value
|
||||
return pol.Coeffs[k].Uint64()
|
||||
}
|
||||
|
||||
// ShallowCopy returns a thread-safe copy of the original CoefficientGetter.
|
||||
// ShallowCopy returns a thread-safe copy of the original [CoefficientGetter].
|
||||
func (c CoefficientGetter) ShallowCopy() he.CoefficientGetter[uint64] {
|
||||
return &CoefficientGetter{Values: make([]uint64, len(c.Values))}
|
||||
}
|
||||
|
||||
// defaultCircuitEvaluatorForPolynomial is a struct implementing the interface he.EvaluatorForPolynomial.
|
||||
// defaultCircuitEvaluatorForPolynomial is a struct implementing the interface [he.EvaluatorForPolynomial].
|
||||
type defaultCircuitEvaluatorForPolynomial struct {
|
||||
he.Evaluator
|
||||
}
|
||||
|
||||
// EvaluatePatersonStockmeyerPolynomialVector evaluates a pre-decomposed PatersonStockmeyerPolynomialVector on a pre-computed power basis [1, X^{1}, X^{2}, ..., X^{2^{n}}, X^{2^{n+1}}, ..., X^{2^{m}}]
|
||||
// EvaluatePatersonStockmeyerPolynomialVector evaluates a pre-decomposed [he.PatersonStockmeyerPolynomialVector] on a pre-computed power basis [1, X^{1}, X^{2}, ..., X^{2^{n}}, X^{2^{n+1}}, ..., X^{2^{m}}]
|
||||
func (eval defaultCircuitEvaluatorForPolynomial) EvaluatePatersonStockmeyerPolynomialVector(poly he.PatersonStockmeyerPolynomialVector, pb he.PowerBasis) (res *rlwe.Ciphertext, err error) {
|
||||
coeffGetter := he.CoefficientGetter[uint64](&CoefficientGetter{Values: make([]uint64, pb.Value[1].Slots())})
|
||||
return he.EvaluatePatersonStockmeyerPolynomialVector(eval, poly, coeffGetter, pb)
|
||||
|
||||
@@ -135,7 +135,7 @@ func (lt LinearTransformation) BSGSIndex() (index map[int][]int, n1, n2 []int) {
|
||||
return BSGSIndex(utils.GetKeys(lt.Vec), 1<<lt.LogDimensions.Cols, lt.N1)
|
||||
}
|
||||
|
||||
// NewLinearTransformation allocates a new LinearTransformation with zero values according to the parameters specified by the LinearTransformationParameters.
|
||||
// NewLinearTransformation allocates a new LinearTransformation with zero values according to the parameters specified by the [LinearTransformationParameters].
|
||||
func NewLinearTransformation(params rlwe.ParameterProvider, ltparams LinearTransformationParameters) LinearTransformation {
|
||||
|
||||
p := params.GetRLWEParameters()
|
||||
@@ -190,7 +190,7 @@ func NewLinearTransformation(params rlwe.ParameterProvider, ltparams LinearTrans
|
||||
}
|
||||
}
|
||||
|
||||
// EncodeLinearTransformation encodes on a pre-allocated LinearTransformation a set of non-zero diagonaes of a matrix representing a linear transformation.
|
||||
// EncodeLinearTransformation encodes on a pre-allocated [LinearTransformation] a set of non-zero diagonaes of a matrix representing a linear transformation.
|
||||
func EncodeLinearTransformation[T any](encoder Encoder[T, ringqp.Poly], diagonals Diagonals[T], allocated LinearTransformation) (err error) {
|
||||
|
||||
rows := 1 << allocated.LogDimensions.Rows
|
||||
@@ -281,7 +281,7 @@ func rotateAndEncodeDiagonal[T any](v []T, encoder Encoder[T, ringqp.Poly], rot
|
||||
}
|
||||
|
||||
// GaloisElementsForLinearTransformation returns the list of Galois elements needed for the evaluation of a linear transformation
|
||||
// given the index of its non-zero diagonals, the number of slots in the plaintext and the LogBabyStepGianStepRatio (see LinearTransformationParameters).
|
||||
// given the index of its non-zero diagonals, the number of slots in the plaintext and the LogBabyStepGianStepRatio (see [LinearTransformationParameters]).
|
||||
func GaloisElementsForLinearTransformation(params rlwe.ParameterProvider, diags []int, slots, logBabyStepGianStepRatio int) (galEls []uint64) {
|
||||
|
||||
p := params.GetRLWEParameters()
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/tuneinsight/lattigo/v5/utils"
|
||||
)
|
||||
|
||||
// EvaluatorForLinearTransformation defines a set of common and scheme agnostic method necessary to instantiate an LinearTransformationEvaluator.
|
||||
// EvaluatorForLinearTransformation defines a set of common and scheme agnostic method necessary to instantiate a [EvaluatorForLinearTransformation].
|
||||
type EvaluatorForLinearTransformation interface {
|
||||
rlwe.ParameterProvider
|
||||
Rescale(op1, op2 *rlwe.Ciphertext) (err error)
|
||||
@@ -137,8 +137,8 @@ func EvaluateLinearTranformationSequential(evalLT EvaluatorForLinearTransformati
|
||||
return
|
||||
}
|
||||
|
||||
// MultiplyByDiagMatrix multiplies the Ciphertext "ctIn" by the plaintext matrix "matrix" and returns the result on the Ciphertext
|
||||
// "opOut". Memory buffers for the decomposed ciphertext BuffDecompQP, BuffDecompQP must be provided, those are list of poly of ringQ and ringP
|
||||
// MultiplyByDiagMatrix multiplies the Ciphertext ctIn by the plaintext matrix and returns the result on the Ciphertext
|
||||
// opOut. Memory buffers for the decomposed ciphertext BuffDecompQP, BuffDecompQP must be provided, those are list of poly of ringQ and ringP
|
||||
// respectively, each of size params.Beta().
|
||||
// The naive approach is used (single hoisting and no baby-step giant-step), which is faster than MultiplyByDiagMatrixBSGS
|
||||
// for matrix of only a few non-zero diagonals but uses more keys.
|
||||
@@ -256,7 +256,7 @@ func MultiplyByDiagMatrix(eval EvaluatorForLinearTransformation, ctIn *rlwe.Ciph
|
||||
return
|
||||
}
|
||||
|
||||
// MultiplyByDiagMatrixBSGS multiplies the Ciphertext "ctIn" by the plaintext matrix "matrix" and returns the result on the Ciphertext "opOut".
|
||||
// MultiplyByDiagMatrixBSGS multiplies the Ciphertext ctIn by the plaintext matrix and returns the result on the Ciphertext opOut.
|
||||
// ctInPreRotated can be obtained with GetPreRotatedCiphertextForDiagonalMatrixMultiplication.
|
||||
// The BSGS approach is used (double hoisting with baby-step giant-step), which is faster than MultiplyByDiagMatrix
|
||||
// for matrix with more than a few non-zero diagonals and uses significantly less keys.
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
|
||||
// Polynomial is a struct for representing plaintext polynomials
|
||||
// for their homomorphic evaluation in an encrypted point. The
|
||||
// type wraps a bignum.Polynomial along with several evaluation-
|
||||
// type wraps a [bignum.Polynomial] along with several evaluation-
|
||||
// related parameters.
|
||||
type Polynomial struct {
|
||||
bignum.Polynomial
|
||||
@@ -23,7 +23,7 @@ type Polynomial struct {
|
||||
}
|
||||
|
||||
// NewPolynomial returns an instantiated Polynomial for the
|
||||
// provided bignum.Polynomial.
|
||||
// provided [bignum.Polynomial].
|
||||
func NewPolynomial(poly bignum.Polynomial) Polynomial {
|
||||
return Polynomial{
|
||||
Polynomial: poly,
|
||||
@@ -157,7 +157,7 @@ type PolynomialVector struct {
|
||||
Mapping map[int][]int
|
||||
}
|
||||
|
||||
// NewPolynomialVector instantiates a new PolynomialVector from a set of bignum.Polynomial and a mapping indicating
|
||||
// NewPolynomialVector instantiates a new [PolynomialVector] from a set of [bignum.Polynomial] and a mapping indicating
|
||||
// which polynomial has to be evaluated on which slot.
|
||||
// For example, if we are given two polynomials P0(X) and P1(X) and the folling mapping: map[int][]int{0:[0, 1, 2], 1:[3, 4, 5]},
|
||||
// then the polynomial evaluation on a vector [a, b, c, d, e, f, g, h] will evaluate to [P0(a), P0(b), P0(c), P1(d), P1(e), P1(f), 0, 0]
|
||||
@@ -226,7 +226,7 @@ func (p PolynomialVector) Factorize(n int) (polyq, polyr PolynomialVector) {
|
||||
|
||||
// PatersonStockmeyerPolynomialVector is a struct implementing the
|
||||
// Paterson Stockmeyer decomposition of a PolynomialVector.
|
||||
// See PatersonStockmeyerPolynomial for additional information.
|
||||
// See [PatersonStockmeyerPolynomial] for additional information.
|
||||
type PatersonStockmeyerPolynomialVector struct {
|
||||
Value []PatersonStockmeyerPolynomial
|
||||
Mapping map[int][]int
|
||||
|
||||
@@ -30,7 +30,7 @@ type CoefficientGetter[T any] interface {
|
||||
ShallowCopy() CoefficientGetter[T]
|
||||
}
|
||||
|
||||
// EvaluatePolynomial is a generic and scheme agnostic method to evaluate polynomials on rlwe.Ciphertexts.
|
||||
// EvaluatePolynomial is a generic and scheme agnostic method to evaluate polynomials on [rlwe.Ciphertexts].
|
||||
func EvaluatePolynomial(eval EvaluatorForPolynomial, input interface{}, p interface{}, targetScale rlwe.Scale, levelsConsumedPerRescaling int, SimEval SimEvaluator) (opOut *rlwe.Ciphertext, err error) {
|
||||
|
||||
var polyVec PolynomialVector
|
||||
@@ -101,7 +101,7 @@ type BabyStep struct {
|
||||
Value *rlwe.Ciphertext
|
||||
}
|
||||
|
||||
// EvaluatePatersonStockmeyerPolynomialVector evaluates a pre-decomposed PatersonStockmeyerPolynomialVector on a pre-computed power basis [1, X^{1}, X^{2}, ..., X^{2^{n}}, X^{2^{n+1}}, ..., X^{2^{m}}]
|
||||
// EvaluatePatersonStockmeyerPolynomialVector evaluates a pre-decomposed [PatersonStockmeyerPolynomialVector] on a pre-computed power basis [1, X^{1}, X^{2}, ..., X^{2^{n}}, X^{2^{n+1}}, ..., X^{2^{m}}]
|
||||
func EvaluatePatersonStockmeyerPolynomialVector[T any](eval Evaluator, poly PatersonStockmeyerPolynomialVector, cg CoefficientGetter[T], pb PowerBasis) (res *rlwe.Ciphertext, err error) {
|
||||
|
||||
split := len(poly.Value[0].Value)
|
||||
@@ -253,7 +253,7 @@ func EvaluateMonomial(a, b, xpow *rlwe.Ciphertext, eval Evaluator) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// EvaluatePolynomialVectorFromPowerBasis a method that complies to the interface he.PolynomialVectorEvaluator. This method evaluates P(ct) = sum c_i * ct^{i}.
|
||||
// EvaluatePolynomialVectorFromPowerBasis a method that complies to the interface [he.PolynomialVectorEvaluator]. This method evaluates P(ct) = sum c_i * ct^{i}.
|
||||
func EvaluatePolynomialVectorFromPowerBasis[T any](eval Evaluator, targetLevel int, pol PolynomialVector, cg CoefficientGetter[T], pb PowerBasis, targetScale rlwe.Scale) (res *rlwe.Ciphertext, err error) {
|
||||
|
||||
// Map[int] of the powers [X^{0}, X^{1}, X^{2}, ...]
|
||||
|
||||
@@ -18,9 +18,9 @@ type PowerBasis struct {
|
||||
Value structs.Map[int, rlwe.Ciphertext]
|
||||
}
|
||||
|
||||
// NewPowerBasis creates a new PowerBasis. It takes as input a ciphertext
|
||||
// NewPowerBasis creates a new [PowerBasis]. It takes as input a ciphertext
|
||||
// and a basis type. The struct treats the input ciphertext as a monomial X and
|
||||
// can be used to generates power of this monomial X^{n} in the given BasisType.
|
||||
// can be used to generates power of this monomial X^{n} in the given [BasisType].
|
||||
func NewPowerBasis(ct *rlwe.Ciphertext, basis bignum.Basis) (p PowerBasis) {
|
||||
return PowerBasis{
|
||||
Value: map[int]*rlwe.Ciphertext{1: ct.CopyNew()},
|
||||
@@ -180,15 +180,15 @@ func (p PowerBasis) BinarySize() (size int) {
|
||||
return 1 + p.Value.BinarySize()
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// WriteTo writes the object on an [io.Writer]. It implements the [io.WriterTo]
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
//
|
||||
// Unless w implements the buffer.Writer interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a bufio.Writer. Since this requires allocations, it
|
||||
// is preferable to pass a buffer.Writer directly:
|
||||
// Unless w implements the [buffer.Writer] interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a [bufio.Writer]. Since this requires allocations, it
|
||||
// is preferable to pass a [buffer.Writer] directly:
|
||||
//
|
||||
// - When writing multiple times to a io.Writer, it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// - When writing multiple times to a [io.Writer], it is preferable to first wrap the
|
||||
// [io.Writer] in a pre-allocated [bufio.Writer].
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (p PowerBasis) WriteTo(w io.Writer) (n int64, err error) {
|
||||
@@ -213,15 +213,15 @@ func (p PowerBasis) WriteTo(w io.Writer) (n int64, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// [io.ReaderFrom] interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a [buffer.Reader] directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// - When reading multiple values from a [io.Reader], it is preferable to first
|
||||
// first wrap [io.Reader] in a pre-allocated [bufio.Reader].
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (p *PowerBasis) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
@@ -260,7 +260,7 @@ func (p PowerBasis) MarshalBinary() (data []byte, err error) {
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
// [PowerBasis.MarshalBinary] or [PowerBasis.WriteTo] on the object.
|
||||
func (p *PowerBasis) UnmarshalBinary(data []byte) (err error) {
|
||||
_, err = p.ReadFrom(buffer.NewBuffer(data))
|
||||
return
|
||||
|
||||
@@ -23,7 +23,7 @@ func NewAdditiveShare(r *ring.Ring) AdditiveShare {
|
||||
return AdditiveShare{Value: r.NewPoly()}
|
||||
}
|
||||
|
||||
// NewAdditiveShareBigint instantiates a new additive share struct composed of n big.Int elements.
|
||||
// NewAdditiveShareBigint instantiates a new additive share struct composed of n [big.Int] elements.
|
||||
func NewAdditiveShareBigint(n int) AdditiveShareBigint {
|
||||
v := make([]*big.Int, n)
|
||||
for i := range v {
|
||||
|
||||
@@ -26,7 +26,7 @@ type PublicKeyGenCRP struct {
|
||||
Value ringqp.Poly
|
||||
}
|
||||
|
||||
// NewPublicKeyGenProtocol creates a new PublicKeyGenProtocol instance
|
||||
// NewPublicKeyGenProtocol creates a new [PublicKeyGenProtocol] instance
|
||||
func NewPublicKeyGenProtocol(params rlwe.ParameterProvider) PublicKeyGenProtocol {
|
||||
ckg := PublicKeyGenProtocol{}
|
||||
ckg.params = *params.GetRLWEParameters()
|
||||
@@ -87,15 +87,15 @@ func (ckg PublicKeyGenProtocol) AggregateShares(share1, share2 PublicKeyGenShare
|
||||
ckg.params.RingQP().Add(share1.Value, share2.Value, shareOut.Value)
|
||||
}
|
||||
|
||||
// GenPublicKey return the current aggregation of the received shares as a bfv.PublicKey.
|
||||
// GenPublicKey return the current aggregation of the received shares as a [rlwe.PublicKey].
|
||||
func (ckg PublicKeyGenProtocol) GenPublicKey(roundShare PublicKeyGenShare, crp PublicKeyGenCRP, pubkey *rlwe.PublicKey) {
|
||||
pubkey.Value[0].Copy(roundShare.Value)
|
||||
pubkey.Value[1].Copy(crp.Value)
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of PublicKeyGenProtocol in which all the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of [PublicKeyGenProtocol] in which all the read-only data-structures are
|
||||
// shared with the receiver and the temporary buffers are reallocated. The receiver and the returned
|
||||
// PublicKeyGenProtocol can be used concurrently.
|
||||
// [PublicKeyGenProtocol] can be used concurrently.
|
||||
func (ckg PublicKeyGenProtocol) ShallowCopy() PublicKeyGenProtocol {
|
||||
prng, err := sampling.NewPRNG()
|
||||
|
||||
@@ -119,30 +119,30 @@ func (share PublicKeyGenShare) BinarySize() int {
|
||||
return share.Value.BinarySize()
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// WriteTo writes the object on an [io.Writer]. It implements the [io.WriterTo]
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
//
|
||||
// Unless w implements the buffer.Writer interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a bufio.Writer. Since this requires allocations, it
|
||||
// is preferable to pass a buffer.Writer directly:
|
||||
// Unless w implements the [buffer.Writer] interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a [bufio.Writer]. Since this requires allocations, it
|
||||
// is preferable to pass a [buffer.Writer] directly:
|
||||
//
|
||||
// - When writing multiple times to a io.Writer, it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// io.Writer in a pre-allocated [bufio.Writer].
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (share PublicKeyGenShare) WriteTo(w io.Writer) (n int64, err error) {
|
||||
return share.Value.WriteTo(w)
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// [io.ReaderFrom] interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a [buffer.Reader] directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// first wrap [io.Reader] in a pre-allocated bufio.Reader.
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (share *PublicKeyGenShare) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
@@ -155,7 +155,7 @@ func (share PublicKeyGenShare) MarshalBinary() (p []byte, err error) {
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
// [PublicKeyGenShare.MarshalBinary] or [PublicKeyGenShare.WriteTo] on the object.
|
||||
func (share *PublicKeyGenShare) UnmarshalBinary(p []byte) (err error) {
|
||||
return share.Value.UnmarshalBinary(p)
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ type EvaluationKeyGenProtocol struct {
|
||||
gaussianSamplerQ ring.Sampler
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of EvaluationKeyGenProtocol in which all the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of [EvaluationKeyGenProtocol] in which all the read-only data-structures are
|
||||
// shared with the receiver and the temporary buffers are reallocated. The receiver and the returned
|
||||
// EvaluationKeyGenProtocol can be used concurrently.
|
||||
// [EvaluationKeyGenProtocol] can be used concurrently.
|
||||
func (evkg EvaluationKeyGenProtocol) ShallowCopy() EvaluationKeyGenProtocol {
|
||||
prng, err := sampling.NewPRNG()
|
||||
|
||||
@@ -47,7 +47,7 @@ func (evkg EvaluationKeyGenProtocol) ShallowCopy() EvaluationKeyGenProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
// NewEvaluationKeyGenProtocol creates a EvaluationKeyGenProtocol instance.
|
||||
// NewEvaluationKeyGenProtocol creates a [EvaluationKeyGenProtocol] instance.
|
||||
func NewEvaluationKeyGenProtocol(params rlwe.ParameterProvider) (evkg EvaluationKeyGenProtocol) {
|
||||
|
||||
prng, err := sampling.NewPRNG()
|
||||
@@ -306,30 +306,30 @@ func (share EvaluationKeyGenShare) BinarySize() int {
|
||||
return share.GadgetCiphertext.BinarySize()
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// WriteTo writes the object on an [io.Writer]. It implements the [io.WriterTo]
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
//
|
||||
// Unless w implements the buffer.Writer interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a bufio.Writer. Since this requires allocations, it
|
||||
// is preferable to pass a buffer.Writer directly:
|
||||
// Unless w implements the [buffer.Writer] interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a [bufio.Writer]. Since this requires allocations, it
|
||||
// is preferable to pass a [buffer.Writer] directly:
|
||||
//
|
||||
// - When writing multiple times to a io.Writer, it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// io.Writer in a pre-allocated [bufio.Writer].
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (share EvaluationKeyGenShare) WriteTo(w io.Writer) (n int64, err error) {
|
||||
return share.GadgetCiphertext.WriteTo(w)
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// [io.ReaderFrom] interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a [buffer.Reader] directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// first wrap [io.Reader] in a pre-allocated bufio.Reader.
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (share *EvaluationKeyGenShare) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
@@ -342,7 +342,7 @@ func (share EvaluationKeyGenShare) MarshalBinary() (p []byte, err error) {
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
// [EvaluationKeyGenShare.MarshalBinary] or [EvaluationKeyGenShare.WriteTo] on the object.
|
||||
func (share *EvaluationKeyGenShare) UnmarshalBinary(p []byte) (err error) {
|
||||
return share.GadgetCiphertext.UnmarshalBinary(p)
|
||||
}
|
||||
|
||||
@@ -28,14 +28,14 @@ type GaloisKeyGenCRP struct {
|
||||
EvaluationKeyGenCRP
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of GaloisKeyGenProtocol in which all the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of [GaloisKeyGenProtocol] in which all the read-only data-structures are
|
||||
// shared with the receiver and the temporary buffers are reallocated. The receiver and the returned
|
||||
// GaloisKeyGenProtocol can be used concurrently.
|
||||
// [GaloisKeyGenProtocol] can be used concurrently.
|
||||
func (gkg GaloisKeyGenProtocol) ShallowCopy() GaloisKeyGenProtocol {
|
||||
return GaloisKeyGenProtocol{EvaluationKeyGenProtocol: gkg.EvaluationKeyGenProtocol.ShallowCopy(), skOut: gkg.params.RingQP().NewPoly()}
|
||||
}
|
||||
|
||||
// NewGaloisKeyGenProtocol creates a GaloisKeyGenProtocol instance.
|
||||
// NewGaloisKeyGenProtocol creates a [GaloisKeyGenProtocol] instance.
|
||||
func NewGaloisKeyGenProtocol(params rlwe.ParameterProvider) (gkg GaloisKeyGenProtocol) {
|
||||
return GaloisKeyGenProtocol{EvaluationKeyGenProtocol: NewEvaluationKeyGenProtocol(params), skOut: params.GetRLWEParameters().RingQP().NewPoly()}
|
||||
}
|
||||
@@ -104,15 +104,15 @@ func (share GaloisKeyGenShare) BinarySize() int {
|
||||
return 8 + share.EvaluationKeyGenShare.BinarySize()
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// WriteTo writes the object on an [io.Writer]. It implements the [io.WriterTo]
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
//
|
||||
// Unless w implements the buffer.Writer interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a bufio.Writer. Since this requires allocations, it
|
||||
// is preferable to pass a buffer.Writer directly:
|
||||
// Unless w implements the [buffer.Writer] interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a [bufio.Writer]. Since this requires allocations, it
|
||||
// is preferable to pass a [buffer.Writer] directly:
|
||||
//
|
||||
// - When writing multiple times to a io.Writer, it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// io.Writer in a pre-allocated [bufio.Writer].
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (share GaloisKeyGenShare) WriteTo(w io.Writer) (n int64, err error) {
|
||||
@@ -139,15 +139,15 @@ func (share GaloisKeyGenShare) WriteTo(w io.Writer) (n int64, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// [io.ReaderFrom] interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a [buffer.Reader] directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// first wrap [io.Reader] in a pre-allocated bufio.Reader.
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (share *GaloisKeyGenShare) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
@@ -178,7 +178,7 @@ func (share GaloisKeyGenShare) MarshalBinary() (p []byte, err error) {
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
// [GaloisKeyGenShare.MarshalBinary] or [GaloisKeyGenShare.WriteTo] on the object.
|
||||
func (share *GaloisKeyGenShare) UnmarshalBinary(p []byte) (err error) {
|
||||
_, err = share.ReadFrom(buffer.NewBuffer(p))
|
||||
return
|
||||
|
||||
@@ -31,9 +31,9 @@ type RelinearizationKeyGenCRP struct {
|
||||
Value structs.Matrix[ringqp.Poly]
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of RelinearizationKeyGenProtocol in which all the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of [RelinearizationKeyGenProtocol] in which all the read-only data-structures are
|
||||
// shared with the receiver and the temporary buffers are reallocated. The receiver and the returned
|
||||
// RelinearizationKeyGenProtocol can be used concurrently.
|
||||
// [RelinearizationKeyGenProtocol] can be used concurrently.
|
||||
func (ekg *RelinearizationKeyGenProtocol) ShallowCopy() RelinearizationKeyGenProtocol {
|
||||
var err error
|
||||
prng, err := sampling.NewPRNG()
|
||||
@@ -122,7 +122,7 @@ func (ekg RelinearizationKeyGenProtocol) SampleCRP(crs CRS, evkParams ...rlwe.Ev
|
||||
return RelinearizationKeyGenCRP{Value: structs.Matrix[ringqp.Poly](m)}
|
||||
}
|
||||
|
||||
// GenShareRoundOne is the first of three rounds of the RelinearizationKeyGenProtocol protocol. Each party generates a pseudo encryption of
|
||||
// GenShareRoundOne is the first of three rounds of the [RelinearizationKeyGenProtocol] protocol. Each party generates a pseudo encryption of
|
||||
// its secret share of the key s_i under its ephemeral key u_i : [-u_i*a + s_i*w + e_i] and broadcasts it to the other
|
||||
// j-1 parties.
|
||||
//
|
||||
@@ -221,15 +221,11 @@ func (ekg RelinearizationKeyGenProtocol) GenShareRoundOne(sk *rlwe.SecretKey, cr
|
||||
}
|
||||
}
|
||||
|
||||
// GenShareRoundTwo is the second of three rounds of the RelinearizationKeyGenProtocol protocol. Upon receiving the j-1 shares, each party computes :
|
||||
// GenShareRoundTwo is the second of three rounds of the [RelinearizationKeyGenProtocol] protocol. Upon receiving the j-1 shares, each party computes :
|
||||
//
|
||||
// round1 = sum([-u_i * a + s_i * P + e_0i, s_i* a + e_i1])
|
||||
// - round1 = sum([-u_i * a + s_i * P + e_0i, s_i* a + e_i1]) = [u * a + s * P + e0, s * a + e1]
|
||||
//
|
||||
// = [u * a + s * P + e0, s * a + e1]
|
||||
//
|
||||
// round2 = [s_i * round1[0] + e_i2, (u_i - s_i) * round1[1] + e_i3]
|
||||
//
|
||||
// = [s_i * {u * a + s * P + e0} + e_i2, (u_i - s_i) * {s * a + e1} + e_i3]
|
||||
// - round2 = [s_i * round1[0] + e_i2, (u_i - s_i) * round1[1] + e_i3] = [s_i * {u * a + s * P + e0} + e_i2, (u_i - s_i) * {s * a + e1} + e_i3]
|
||||
//
|
||||
// and broadcasts both values to the other j-1 parties.
|
||||
func (ekg RelinearizationKeyGenProtocol) GenShareRoundTwo(ephSk, sk *rlwe.SecretKey, round1 RelinearizationKeyGenShare, shareOut *RelinearizationKeyGenShare) {
|
||||
@@ -300,15 +296,9 @@ func (ekg RelinearizationKeyGenProtocol) AggregateShares(share1, share2 Relinear
|
||||
|
||||
// GenRelinearizationKey computes the generated RLK from the public shares and write the result in evalKeyOut.
|
||||
//
|
||||
// round1 = [u * a + s * P + e0, s * a + e1]
|
||||
//
|
||||
// round2 = sum([s_i * {u * a + s * P + e0} + e_i2, (u_i - s_i) * {s * a + e1} + e_i3])
|
||||
//
|
||||
// = [-sua + P*s^2 + s*e0 + e2, sua + ue1 - s^2a -s*e1 + e3]
|
||||
//
|
||||
// [round2[0] + round2[1], round1[1]] = [- s^2a - s*e1 + P*s^2 + s*e0 + u*e1 + e2 + e3, s * a + e1]
|
||||
//
|
||||
// = [s * b + P * s^2 + s*e0 + u*e1 + e2 + e3, b]
|
||||
// - round1 = [u * a + s * P + e0, s * a + e1]
|
||||
// - round2 = sum([s_i * {u * a + s * P + e0} + e_i2, (u_i - s_i) * {s * a + e1} + e_i3]) = [-sua + P*s^2 + s*e0 + e2, sua + ue1 - s^2a -s*e1 + e3]
|
||||
// - [round2[0] + round2[1], round1[1]] = [- s^2a - s*e1 + P*s^2 + s*e0 + u*e1 + e2 + e3, s * a + e1] = [s * b + P * s^2 + s*e0 + u*e1 + e2 + e3, b]
|
||||
func (ekg RelinearizationKeyGenProtocol) GenRelinearizationKey(round1 RelinearizationKeyGenShare, round2 RelinearizationKeyGenShare, evalKeyOut *rlwe.RelinearizationKey) {
|
||||
|
||||
levelQ := round1.LevelQ()
|
||||
@@ -346,30 +336,30 @@ func (share RelinearizationKeyGenShare) BinarySize() int {
|
||||
return share.GadgetCiphertext.BinarySize()
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// WriteTo writes the object on an [io.Writer]. It implements the [io.WriterTo]
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
//
|
||||
// Unless w implements the buffer.Writer interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a bufio.Writer. Since this requires allocations, it
|
||||
// is preferable to pass a buffer.Writer directly:
|
||||
// Unless w implements the [buffer.Writer] interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a [bufio.Writer]. Since this requires allocations, it
|
||||
// is preferable to pass a [buffer.Writer] directly:
|
||||
//
|
||||
// - When writing multiple times to a io.Writer, it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// io.Writer in a pre-allocated [bufio.Writer].
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (share RelinearizationKeyGenShare) WriteTo(w io.Writer) (n int64, err error) {
|
||||
return share.GadgetCiphertext.WriteTo(w)
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// [io.ReaderFrom] interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a [buffer.Reader] directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// first wrap [io.Reader] in a pre-allocated bufio.Reader.
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (share *RelinearizationKeyGenShare) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
@@ -382,7 +372,7 @@ func (share RelinearizationKeyGenShare) MarshalBinary() (data []byte, err error)
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
// [RelinearizationKeyGenShare.MarshalBinary] or [RelinearizationKeyGenShare.WriteTo] on the object.
|
||||
func (share *RelinearizationKeyGenShare) UnmarshalBinary(data []byte) (err error) {
|
||||
return share.GadgetCiphertext.UnmarshalBinary(data)
|
||||
}
|
||||
|
||||
@@ -136,9 +136,9 @@ func (pcks PublicKeySwitchProtocol) KeySwitch(ctIn *rlwe.Ciphertext, combined Pu
|
||||
opOut.Value[1].CopyLvl(level, combined.Value[1])
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of PublicKeySwitchProtocol in which all the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of [PublicKeySwitchProtocol] in which all the read-only data-structures are
|
||||
// shared with the receiver and the temporary bufers are reallocated. The receiver and the returned
|
||||
// PublicKeySwitchProtocol can be used concurrently.
|
||||
// [PublicKeySwitchProtocol] can be used concurrently.
|
||||
func (pcks PublicKeySwitchProtocol) ShallowCopy() PublicKeySwitchProtocol {
|
||||
prng, err := sampling.NewPRNG()
|
||||
|
||||
@@ -170,30 +170,30 @@ func (share PublicKeySwitchShare) BinarySize() int {
|
||||
return share.Element.BinarySize()
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// WriteTo writes the object on an [io.Writer]. It implements the [io.WriterTo]
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
//
|
||||
// Unless w implements the buffer.Writer interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a bufio.Writer. Since this requires allocations, it
|
||||
// is preferable to pass a buffer.Writer directly:
|
||||
// Unless w implements the [buffer.Writer] interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a [bufio.Writer]. Since this requires allocations, it
|
||||
// is preferable to pass a [buffer.Writer] directly:
|
||||
//
|
||||
// - When writing multiple times to a io.Writer, it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// - When writing multiple times to a [io.Writer], it is preferable to first wrap the
|
||||
// [io.Writer] in a pre-allocated [bufio.Writer].
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (share PublicKeySwitchShare) WriteTo(w io.Writer) (n int64, err error) {
|
||||
return share.Element.WriteTo(w)
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// [io.ReaderFrom] interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a [buffer.Reader] directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// - When reading multiple values from a [io.Reader], it is preferable to first
|
||||
// first wrap [io.Reader] in a pre-allocated [bufio.Reader].
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (share *PublicKeySwitchShare) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
@@ -206,7 +206,7 @@ func (share PublicKeySwitchShare) MarshalBinary() (p []byte, err error) {
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
// [PublicKeySwitchShare.MarshalBinary] or [PublicKeySwitchShare.WriteTo] on the object.
|
||||
func (share *PublicKeySwitchShare) UnmarshalBinary(p []byte) (err error) {
|
||||
return share.Element.UnmarshalBinary(p)
|
||||
}
|
||||
|
||||
@@ -26,9 +26,9 @@ type KeySwitchShare struct {
|
||||
Value ring.Poly
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of KeySwitchProtocol in which all the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of [KeySwitchProtocol] in which all the read-only data-structures are
|
||||
// shared with the receiver and the temporary bufers are reallocated. The receiver and the returned
|
||||
// KeySwitchProtocol can be used concurrently.
|
||||
// [KeySwitchProtocol] can be used concurrently.
|
||||
func (cks KeySwitchProtocol) ShallowCopy() KeySwitchProtocol {
|
||||
prng, err := sampling.NewPRNG()
|
||||
|
||||
@@ -60,7 +60,7 @@ type KeySwitchCRP struct {
|
||||
Value ring.Poly
|
||||
}
|
||||
|
||||
// NewKeySwitchProtocol creates a new KeySwitchProtocol that will be used to perform a collective key-switching on a ciphertext encrypted under a collective public-key, whose
|
||||
// NewKeySwitchProtocol creates a new [KeySwitchProtocol] that will be used to perform a collective key-switching on a ciphertext encrypted under a collective public-key, whose
|
||||
// secret-shares are distributed among j parties, re-encrypting the ciphertext under another public-key, whose secret-shares are also known to the
|
||||
// parties.
|
||||
func NewKeySwitchProtocol(params rlwe.ParameterProvider, noiseFlooding ring.DistributionParameters) (KeySwitchProtocol, error) {
|
||||
@@ -112,7 +112,7 @@ func (cks KeySwitchProtocol) SampleCRP(level int, crs CRS) KeySwitchCRP {
|
||||
}
|
||||
|
||||
// GenShare computes a party's share in the KeySwitchcol from secret-key skInput to secret-key skOutput.
|
||||
// ct is the rlwe.Ciphertext to keyswitch. Note that ct.Value[0] is not used by the function and can be nil/zero.
|
||||
// ct is the [rlwe.Ciphertext] to keyswitch. Note that ct.Value[0] is not used by the function and can be nil/zero.
|
||||
//
|
||||
// Expected noise: ctNoise + encFreshSk + smudging
|
||||
func (cks KeySwitchProtocol) GenShare(skInput, skOutput *rlwe.SecretKey, ct *rlwe.Ciphertext, shareOut *KeySwitchShare) {
|
||||
@@ -148,7 +148,7 @@ func (cks KeySwitchProtocol) GenShare(skInput, skOutput *rlwe.SecretKey, ct *rlw
|
||||
}
|
||||
}
|
||||
|
||||
// AggregateShares is the second part of the unique round of the KeySwitchProtocol protocol. Upon receiving the j-1 elements each party computes :
|
||||
// AggregateShares is the second part of the unique round of the [KeySwitchProtocol] protocol. Upon receiving the j-1 elements each party computes:
|
||||
//
|
||||
// [ctx[0] + sum((skInput_i - skOutput_i) * ctx[0] + e_i), ctx[1]]
|
||||
func (cks KeySwitchProtocol) AggregateShares(share1, share2 KeySwitchShare, shareOut *KeySwitchShare) (err error) {
|
||||
@@ -187,30 +187,30 @@ func (ckss KeySwitchShare) BinarySize() int {
|
||||
return ckss.Value.BinarySize()
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// WriteTo writes the object on an [io.Writer]. It implements the [io.WriterTo]
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
//
|
||||
// Unless w implements the buffer.Writer interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a bufio.Writer. Since this requires allocations, it
|
||||
// is preferable to pass a buffer.Writer directly:
|
||||
// Unless w implements the [buffer.Writer] interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a [bufio.Writer]. Since this requires allocations, it
|
||||
// is preferable to pass a [buffer.Writer] directly:
|
||||
//
|
||||
// - When writing multiple times to a io.Writer, it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// - When writing multiple times to a [io.Writer], it is preferable to first wrap the
|
||||
// [io.Writer] in a pre-allocated [bufio.Writer].
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (ckss KeySwitchShare) WriteTo(w io.Writer) (n int64, err error) {
|
||||
return ckss.Value.WriteTo(w)
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// [io.ReaderFrom] interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a [buffer.Reader] directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// - When reading multiple values from a [io.Reader], it is preferable to first
|
||||
// first wrap [io.Reader] in a pre-allocated [bufio.Reader].
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (ckss *KeySwitchShare) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
@@ -223,7 +223,7 @@ func (ckss KeySwitchShare) MarshalBinary() (p []byte, err error) {
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
// [KeySwitchShare.MarshalBinary] or[KeySwitchShare.WriteTo] on the object.
|
||||
func (ckss *KeySwitchShare) UnmarshalBinary(p []byte) (err error) {
|
||||
return ckss.Value.UnmarshalBinary(p)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Package mhefloat implements homomorphic decryption to Linear-Secret-Shared-Shares (LSSS)
|
||||
// and homomorphic re-encryption from LSSS, as well as interactive bootstrapping for the package `he/hefloat`
|
||||
// See `mhe/README.md` for additional information on multiparty schemes.
|
||||
// and homomorphic re-encryption from LSSS, as well as interactive bootstrapping for the package [he/hefloat]
|
||||
// See mhe/README.md for additional information on multiparty schemes.
|
||||
package mhefloat
|
||||
|
||||
@@ -13,7 +13,7 @@ type RefreshProtocol struct {
|
||||
MaskedLinearTransformationProtocol
|
||||
}
|
||||
|
||||
// NewRefreshProtocol creates a new Refresh protocol instance.
|
||||
// NewRefreshProtocol creates a new [RefreshProtocol] instance.
|
||||
// prec : the log2 of decimal precision of the internal encoder.
|
||||
func NewRefreshProtocol(params hefloat.Parameters, prec uint, noise ring.DistributionParameters) (rfp RefreshProtocol, err error) {
|
||||
rfp = RefreshProtocol{}
|
||||
@@ -22,9 +22,9 @@ func NewRefreshProtocol(params hefloat.Parameters, prec uint, noise ring.Distrib
|
||||
return rfp, err
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of RefreshProtocol in which all the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of [RefreshProtocol] in which all the read-only data-structures are
|
||||
// shared with the receiver and the temporary buffers are reallocated. The receiver and the returned
|
||||
// RefreshProtocol can be used concurrently.
|
||||
// [RefreshProtocol] can be used concurrently.
|
||||
func (rfp RefreshProtocol) ShallowCopy() RefreshProtocol {
|
||||
return RefreshProtocol{rfp.MaskedLinearTransformationProtocol.ShallowCopy()}
|
||||
}
|
||||
@@ -35,11 +35,13 @@ func (rfp RefreshProtocol) AllocateShare(inputLevel, outputLevel int) mhe.Refres
|
||||
}
|
||||
|
||||
// GenShare generates a share for the Refresh protocol.
|
||||
// This protocol requires additional inputs which are :
|
||||
// logBound : the bit length of the masks
|
||||
// ct1 : the degree 1 element the ciphertext to refresh, i.e. ct1 = ckk.Ciphetext.Value[1].
|
||||
// scale : the scale of the ciphertext entering the refresh.
|
||||
// The method "GetMinimumLevelForBootstrapping" should be used to get the minimum level at which the refresh can be called while still ensure 128-bits of security, as well as the
|
||||
// This protocol requires additional inputs which are:
|
||||
//
|
||||
// - logBound : the bit length of the masks
|
||||
// - ct1 : the degree 1 element the ciphertext to refresh, i.e. ct1 = ckk.Ciphetext.Value[1].
|
||||
// - scale : the scale of the ciphertext entering the refresh.
|
||||
//
|
||||
// The method [GetMinimumLevelForRefresh] should be used to get the minimum level at which the refresh can be called while still ensure 128-bits of security, as well as the
|
||||
// value for logBound.
|
||||
func (rfp RefreshProtocol) GenShare(sk *rlwe.SecretKey, logBound uint, ct *rlwe.Ciphertext, crs mhe.KeySwitchCRP, shareOut *mhe.RefreshShare) (err error) {
|
||||
return rfp.MaskedLinearTransformationProtocol.GenShare(sk, sk, logBound, ct, crs, nil, shareOut)
|
||||
|
||||
@@ -35,9 +35,9 @@ func NewAdditiveShare(params hefloat.Parameters, logSlots int) mhe.AdditiveShare
|
||||
return mhe.NewAdditiveShareBigint(nValues)
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of EncToShareProtocol in which all the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of [EncToShareProtocol] in which all the read-only data-structures are
|
||||
// shared with the receiver and the temporary buffers are reallocated. The receiver and the returned
|
||||
// EncToShareProtocol can be used concurrently.
|
||||
// [EncToShareProtocol] can be used concurrently.
|
||||
func (e2s EncToShareProtocol) ShallowCopy() EncToShareProtocol {
|
||||
|
||||
maskBigint := make([]*big.Int, len(e2s.maskBigint))
|
||||
@@ -54,7 +54,7 @@ func (e2s EncToShareProtocol) ShallowCopy() EncToShareProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
// NewEncToShareProtocol creates a new EncToShareProtocol struct from the passed parameters.
|
||||
// NewEncToShareProtocol creates a new [EncToShareProtocol] struct from the passed parameters.
|
||||
func NewEncToShareProtocol(params hefloat.Parameters, noise ring.DistributionParameters) (EncToShareProtocol, error) {
|
||||
e2s := EncToShareProtocol{}
|
||||
|
||||
@@ -80,11 +80,13 @@ func (e2s EncToShareProtocol) AllocateShare(level int) (share mhe.KeySwitchShare
|
||||
|
||||
// GenShare generates a party's share in the encryption-to-shares protocol. This share consist in the additive secret-share of the party
|
||||
// which is written in secretShareOut and in the public masked-decryption share written in publicShareOut.
|
||||
// This protocol requires additional inputs which are :
|
||||
// logBound : the bit length of the masks
|
||||
// ct: the ciphertext to share
|
||||
// This protocol requires additional inputs which are:
|
||||
//
|
||||
// - logBound : the bit length of the masks
|
||||
// - ct: the ciphertext to share
|
||||
//
|
||||
// publicShareOut is always returned in the NTT domain.
|
||||
// The method "GetMinimumLevelForBootstrapping" should be used to get the minimum level at which EncToShare can be called while still ensure 128-bits of security, as well as the
|
||||
// The method [GetMinimumLevelForRefresh] should be used to get the minimum level at which EncToShare can be called while still ensure 128-bits of security, as well as the
|
||||
// value for logBound.
|
||||
func (e2s EncToShareProtocol) GenShare(sk *rlwe.SecretKey, logBound uint, ct *rlwe.Ciphertext, secretShareOut *mhe.AdditiveShareBigint, publicShareOut *mhe.KeySwitchShare) (err error) {
|
||||
|
||||
@@ -143,7 +145,7 @@ func (e2s EncToShareProtocol) GenShare(sk *rlwe.SecretKey, logBound uint, ct *rl
|
||||
|
||||
// GetShare is the final step of the encryption-to-share protocol. It performs the masked decryption of the target ciphertext followed by a
|
||||
// the removal of the caller's secretShare as generated in the GenShare method.
|
||||
// If the caller is not secret-key-share holder (i.e., didn't generate a decryption share), `secretShare` can be set to nil.
|
||||
// If the caller is not secret-key-share holder (i.e., didn't generate a decryption share), secretShare can be set to nil.
|
||||
// Therefore, in order to obtain an additive sharing of the message, only one party should call this method, and the other parties should use
|
||||
// the secretShareOut output of the GenShare method.
|
||||
func (e2s EncToShareProtocol) GetShare(secretShare *mhe.AdditiveShareBigint, aggregatePublicShare mhe.KeySwitchShare, ct *rlwe.Ciphertext, secretShareOut *mhe.AdditiveShareBigint) {
|
||||
@@ -194,9 +196,9 @@ type ShareToEncProtocol struct {
|
||||
zero *rlwe.SecretKey
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of ShareToEncProtocol in which all the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of [ShareToEncProtocol] in which all the read-only data-structures are
|
||||
// shared with the receiver and the temporary buffers are reallocated. The receiver and the returned
|
||||
// ShareToEncProtocol can be used concurrently.
|
||||
// [ShareToEncProtocol] can be used concurrently.
|
||||
func (s2e ShareToEncProtocol) ShallowCopy() ShareToEncProtocol {
|
||||
return ShareToEncProtocol{
|
||||
KeySwitchProtocol: s2e.KeySwitchProtocol.ShallowCopy(),
|
||||
@@ -207,7 +209,7 @@ func (s2e ShareToEncProtocol) ShallowCopy() ShareToEncProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
// NewShareToEncProtocol creates a new ShareToEncProtocol struct from the passed parameters.
|
||||
// NewShareToEncProtocol creates a new [ShareToEncProtocol] struct from the passed parameters.
|
||||
func NewShareToEncProtocol(params hefloat.Parameters, noise ring.DistributionParameters) (ShareToEncProtocol, error) {
|
||||
s2e := ShareToEncProtocol{}
|
||||
|
||||
@@ -228,8 +230,8 @@ func (s2e ShareToEncProtocol) AllocateShare(level int) (share mhe.KeySwitchShare
|
||||
return s2e.KeySwitchProtocol.AllocateShare(level)
|
||||
}
|
||||
|
||||
// GenShare generates a party's in the shares-to-encryption protocol given the party's secret-key share `sk`, a common
|
||||
// polynomial sampled from the CRS `crs` and the party's secret share of the message.
|
||||
// GenShare generates a party's in the shares-to-encryption protocol given the party's secret-key share sk, a common
|
||||
// polynomial sampled from the CRS crs and the party's secret share of the message.
|
||||
func (s2e ShareToEncProtocol) GenShare(sk *rlwe.SecretKey, crs mhe.KeySwitchCRP, metadata *rlwe.MetaData, secretShare mhe.AdditiveShareBigint, c0ShareOut *mhe.KeySwitchShare) (err error) {
|
||||
|
||||
if crs.Value.Level() != c0ShareOut.Value.Level() {
|
||||
@@ -260,8 +262,8 @@ func (s2e ShareToEncProtocol) GenShare(sk *rlwe.SecretKey, crs mhe.KeySwitchCRP,
|
||||
return
|
||||
}
|
||||
|
||||
// GetEncryption computes the final encryption of the secret-shared message when provided with the aggregation `c0Agg` of the parties'
|
||||
// share in the protocol and with the common, CRS-sampled polynomial `crs`.
|
||||
// GetEncryption computes the final encryption of the secret-shared message when provided with the aggregation c0Agg of the parties'
|
||||
// share in the protocol and with the common, CRS-sampled polynomial crs.
|
||||
func (s2e ShareToEncProtocol) GetEncryption(c0Agg mhe.KeySwitchShare, crs mhe.KeySwitchCRP, opOut *rlwe.Ciphertext) (err error) {
|
||||
|
||||
if opOut.Degree() != 1 {
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"github.com/tuneinsight/lattigo/v5/utils/sampling"
|
||||
)
|
||||
|
||||
// MaskedLinearTransformationProtocol is a struct storing the parameters for the MaskedLinearTransformationProtocol protocol.
|
||||
// MaskedLinearTransformationProtocol is a struct storing the parameters for the [MaskedLinearTransformationProtocol] protocol.
|
||||
type MaskedLinearTransformationProtocol struct {
|
||||
e2s EncToShareProtocol
|
||||
s2e ShareToEncProtocol
|
||||
@@ -27,9 +27,9 @@ type MaskedLinearTransformationProtocol struct {
|
||||
encoder *hefloat.Encoder
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of MaskedLinearTransformationProtocol in which all the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of [MaskedLinearTransformationProtocol] in which all the read-only data-structures are
|
||||
// shared with the receiver and the temporary buffers are reallocated. The receiver and the returned
|
||||
// MaskedLinearTransformationProtocol can be used concurrently.
|
||||
// [MaskedLinearTransformationProtocol] can be used concurrently.
|
||||
func (mltp MaskedLinearTransformationProtocol) ShallowCopy() MaskedLinearTransformationProtocol {
|
||||
|
||||
mask := make([]*big.Int, mltp.e2s.params.N())
|
||||
@@ -47,7 +47,7 @@ func (mltp MaskedLinearTransformationProtocol) ShallowCopy() MaskedLinearTransfo
|
||||
}
|
||||
}
|
||||
|
||||
// WithParams creates a shallow copy of the target MaskedLinearTransformationProtocol but with new output parameters.
|
||||
// WithParams creates a shallow copy of the target [MaskedLinearTransformationProtocol] but with new output parameters.
|
||||
// The expected input parameters remain unchanged.
|
||||
func (mltp MaskedLinearTransformationProtocol) WithParams(paramsOut hefloat.Parameters) MaskedLinearTransformationProtocol {
|
||||
|
||||
@@ -79,12 +79,14 @@ func (mltp MaskedLinearTransformationProtocol) WithParams(paramsOut hefloat.Para
|
||||
|
||||
// MaskedLinearTransformationFunc represents a user-defined in-place function that can be evaluated on masked float plaintexts, as a part of the
|
||||
// Masked Transform Protocol.
|
||||
// The function is called with a vector of *Complex modulo hefloat.Parameters.Slots() as input, and must write
|
||||
// The function is called with a vector of *[bignum.Complex] modulo [hefloat.Parameters.Slots]() as input, and must write
|
||||
// its output on the same buffer.
|
||||
// Transform can be the identity.
|
||||
// Decode: if true, then the masked float plaintext will be decoded before applying Transform.
|
||||
// Recode: if true, then the masked float plaintext will be recoded after applying Transform.
|
||||
// i.e. : Decode (true/false) -> Transform -> Recode (true/false).
|
||||
//
|
||||
// - Decode: if true, then the masked float plaintext will be decoded before applying Transform.
|
||||
// - Recode: if true, then the masked float plaintext will be recoded after applying Transform.
|
||||
//
|
||||
// Decode (true/false) -> Transform -> Recode (true/false).
|
||||
type MaskedLinearTransformationFunc struct {
|
||||
Decode bool
|
||||
Func func(coeffs []*bignum.Complex)
|
||||
@@ -92,9 +94,11 @@ type MaskedLinearTransformationFunc struct {
|
||||
}
|
||||
|
||||
// NewMaskedLinearTransformationProtocol creates a new instance of the PermuteProtocol.
|
||||
// paramsIn: the hefloat.Parameters of the ciphertext before the protocol.
|
||||
// paramsOut: the hefloat.Parameters of the ciphertext after the protocol.
|
||||
// prec : the log2 of decimal precision of the internal encoder.
|
||||
//
|
||||
// - paramsIn: the [hefloat.Parameters] of the ciphertext before the protocol.
|
||||
// - paramsOut: the [hefloat.Parameters] of the ciphertext after the protocol.
|
||||
// - prec : the log2 of decimal precision of the internal encoder.
|
||||
//
|
||||
// The method will return an error if the maximum number of slots of the output parameters is smaller than the number of slots of the input ciphertext.
|
||||
func NewMaskedLinearTransformationProtocol(paramsIn, paramsOut hefloat.Parameters, prec uint, noise ring.DistributionParameters) (mltp MaskedLinearTransformationProtocol, err error) {
|
||||
|
||||
@@ -138,13 +142,15 @@ func (mltp MaskedLinearTransformationProtocol) SampleCRP(level int, crs sampling
|
||||
}
|
||||
|
||||
// GenShare generates the shares of the PermuteProtocol
|
||||
// This protocol requires additional inputs which are :
|
||||
// skIn : the secret-key if the input ciphertext.
|
||||
// skOut : the secret-key of the output ciphertext.
|
||||
// logBound : the bit length of the masks.
|
||||
// ct1 : the degree 1 element the ciphertext to refresh, i.e. ct1 = ckk.Ciphetext.Value[1].
|
||||
// scale : the scale of the ciphertext when entering the refresh.
|
||||
// The method "GetMinimumLevelForBootstrapping" should be used to get the minimum level at which the masked transform can be called while still ensure 128-bits of security, as well as the
|
||||
// This protocol requires additional inputs which are:
|
||||
//
|
||||
// - skIn : the secret-key if the input ciphertext.
|
||||
// - skOut : the secret-key of the output ciphertext.
|
||||
// - logBound : the bit length of the masks.
|
||||
// - ct1 : the degree 1 element the ciphertext to refresh, i.e. ct1 = ckk.Ciphetext.Value[1].
|
||||
// - scale : the scale of the ciphertext when entering the refresh.
|
||||
//
|
||||
// The method [GetMinimumLevelForRefresh] should be used to get the minimum level at which the masked transform can be called while still ensure 128-bits of security, as well as the
|
||||
// value for logBound.
|
||||
func (mltp MaskedLinearTransformationProtocol) GenShare(skIn, skOut *rlwe.SecretKey, logBound uint, ct *rlwe.Ciphertext, crs mhe.KeySwitchCRP, transform *MaskedLinearTransformationFunc, shareOut *mhe.RefreshShare) (err error) {
|
||||
|
||||
|
||||
@@ -8,10 +8,11 @@ import (
|
||||
|
||||
// GetMinimumLevelForRefresh takes the security parameter lambda, the ciphertext scale, the number of parties and the moduli chain
|
||||
// and returns the minimum level at which the collective refresh can be called with a security of at least 128-bits.
|
||||
// It returns 3 parameters :
|
||||
// minLevel : the minimum level at which the collective refresh must be called to ensure correctness
|
||||
// logBound : the bit length of the masks to be sampled to mask the plaintext and ensure 128-bits of statistical indistinguishability
|
||||
// ok : a boolean flag, which is set to false if no such instance exist
|
||||
// It returns 3 parameters:
|
||||
//
|
||||
// - minLevel : the minimum level at which the collective refresh must be called to ensure correctness
|
||||
// - logBound : the bit length of the masks to be sampled to mask the plaintext and ensure 128-bits of statistical indistinguishability
|
||||
// - ok : a boolean flag, which is set to false if no such instance exist
|
||||
func GetMinimumLevelForRefresh(lambda int, scale rlwe.Scale, nParties int, moduli []uint64) (minLevel int, logBound uint, ok bool) {
|
||||
logBound = uint(lambda + int(math.Ceil(math.Log2(scale.Float64()))))
|
||||
maxBound := math.Ceil(float64(logBound) + math.Log2(float64(nParties)))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Package mheint implements homomorphic decryption to Linear-Secret-Shared-Shares (LSSS)
|
||||
// and homomorphic re-encryption from LSSS, as well as interactive bootstrapping for the package `he/heint`
|
||||
// See `mhe/README.md` for additional information on multiparty schemes.
|
||||
// and homomorphic re-encryption from LSSS, as well as interactive bootstrapping for the package [he/heint]
|
||||
// See mhe/README.md for additional information on multiparty schemes.
|
||||
package mheint
|
||||
|
||||
@@ -13,9 +13,9 @@ type RefreshProtocol struct {
|
||||
MaskedTransformProtocol
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of RefreshProtocol in which all the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of [RefreshProtocol] in which all the read-only data-structures are
|
||||
// shared with the receiver and the temporary buffers are reallocated. The receiver and the returned
|
||||
// RefreshProtocol can be used concurrently.
|
||||
// [RefreshProtocol] can be used concurrently.
|
||||
func (rfp *RefreshProtocol) ShallowCopy() RefreshProtocol {
|
||||
return RefreshProtocol{rfp.MaskedTransformProtocol.ShallowCopy()}
|
||||
}
|
||||
@@ -34,7 +34,7 @@ func (rfp RefreshProtocol) AllocateShare(inputLevel, outputLevel int) mhe.Refres
|
||||
}
|
||||
|
||||
// GenShare generates a share for the Refresh protocol.
|
||||
// ct1 is degree 1 element of a rlwe.Ciphertext, i.e. rlwe.Ciphertext.Value[1].
|
||||
// ct1 is degree 1 element of a [rlwe.Ciphertext], i.e., [rlwe.Ciphertext.Value][1].
|
||||
func (rfp RefreshProtocol) GenShare(sk *rlwe.SecretKey, ct *rlwe.Ciphertext, crp mhe.KeySwitchCRP, shareOut *mhe.RefreshShare) (err error) {
|
||||
return rfp.MaskedTransformProtocol.GenShare(sk, sk, ct, crp, nil, shareOut)
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@ func NewAdditiveShare(params heint.Parameters) mhe.AdditiveShare {
|
||||
return mhe.NewAdditiveShare(params.RingT())
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of EncToShareProtocol in which all the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of [EncToShareProtocol] in which all the read-only data-structures are
|
||||
// shared with the receiver and the temporary buffers are reallocated. The receiver and the returned
|
||||
// EncToShareProtocol can be used concurrently.
|
||||
// [EncToShareProtocol] can be used concurrently.
|
||||
func (e2s EncToShareProtocol) ShallowCopy() EncToShareProtocol {
|
||||
|
||||
params := e2s.params
|
||||
@@ -54,7 +54,7 @@ func (e2s EncToShareProtocol) ShallowCopy() EncToShareProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
// NewEncToShareProtocol creates a new EncToShareProtocol struct from the passed heint.Parameters.
|
||||
// NewEncToShareProtocol creates a new [EncToShareProtocol] struct from the passed [heint.Parameters].
|
||||
func NewEncToShareProtocol(params heint.Parameters, noiseFlooding ring.DistributionParameters) (EncToShareProtocol, error) {
|
||||
e2s := EncToShareProtocol{}
|
||||
|
||||
@@ -87,7 +87,7 @@ func (e2s EncToShareProtocol) AllocateShare(level int) (share mhe.KeySwitchShare
|
||||
|
||||
// GenShare generates a party's share in the encryption-to-shares protocol. This share consist in the additive secret-share of the party
|
||||
// which is written in secretShareOut and in the public masked-decryption share written in publicShareOut.
|
||||
// ct1 is degree 1 element of a rlwe.Ciphertext, i.e. rlwe.Ciphertext.Value[1].
|
||||
// ct1 is degree 1 element of a [rlwe.Ciphertext], i.e., [rlwe.Ciphertext.Value][1].
|
||||
func (e2s EncToShareProtocol) GenShare(sk *rlwe.SecretKey, ct *rlwe.Ciphertext, secretShareOut *mhe.AdditiveShare, publicShareOut *mhe.KeySwitchShare) {
|
||||
level := utils.Min(ct.Level(), publicShareOut.Value.Level())
|
||||
e2s.KeySwitchProtocol.GenShare(sk, e2s.zero, ct, publicShareOut)
|
||||
@@ -99,8 +99,8 @@ func (e2s EncToShareProtocol) GenShare(sk *rlwe.SecretKey, ct *rlwe.Ciphertext,
|
||||
}
|
||||
|
||||
// GetShare is the final step of the encryption-to-share protocol. It performs the masked decryption of the target ciphertext followed by a
|
||||
// the removal of the caller's secretShare as generated in the GenShare method.
|
||||
// If the caller is not secret-key-share holder (i.e., didn't generate a decryption share), `secretShare` can be set to nil.
|
||||
// the removal of the caller's secretShare as generated in the [EncToShareProtocol.GenShare] method.
|
||||
// If the caller is not secret-key-share holder (i.e., didn't generate a decryption share), secretShare can be set to nil.
|
||||
// Therefore, in order to obtain an additive sharing of the message, only one party should call this method, and the other parties should use
|
||||
// the secretShareOut output of the GenShare method.
|
||||
func (e2s EncToShareProtocol) GetShare(secretShare *mhe.AdditiveShare, aggregatePublicShare mhe.KeySwitchShare, ct *rlwe.Ciphertext, secretShareOut *mhe.AdditiveShare) {
|
||||
@@ -149,7 +149,7 @@ func (s2e ShareToEncProtocol) AllocateShare(level int) (share mhe.KeySwitchShare
|
||||
return s2e.KeySwitchProtocol.AllocateShare(level)
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of ShareToEncProtocol in which all the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of [ShareToEncProtocol] in which all the read-only data-structures are
|
||||
// shared with the receiver and the temporary buffers are reallocated. The receiver and the returned
|
||||
// ShareToEncProtocol can be used concurrently.
|
||||
func (s2e ShareToEncProtocol) ShallowCopy() ShareToEncProtocol {
|
||||
@@ -163,8 +163,8 @@ func (s2e ShareToEncProtocol) ShallowCopy() ShareToEncProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
// GenShare generates a party's in the shares-to-encryption protocol given the party's secret-key share `sk`, a common
|
||||
// polynomial sampled from the CRS `crp` and the party's secret share of the message.
|
||||
// GenShare generates a party's in the shares-to-encryption protocol given the party's secret-key share sk, a common
|
||||
// polynomial sampled from the CRS crp and the party's secret share of the message.
|
||||
func (s2e ShareToEncProtocol) GenShare(sk *rlwe.SecretKey, crp mhe.KeySwitchCRP, secretShare mhe.AdditiveShare, c0ShareOut *mhe.KeySwitchShare) (err error) {
|
||||
|
||||
if crp.Value.Level() != c0ShareOut.Value.Level() {
|
||||
@@ -183,8 +183,8 @@ func (s2e ShareToEncProtocol) GenShare(sk *rlwe.SecretKey, crp mhe.KeySwitchCRP,
|
||||
return
|
||||
}
|
||||
|
||||
// GetEncryption computes the final encryption of the secret-shared message when provided with the aggregation `c0Agg` of the parties'
|
||||
// shares in the protocol and with the common, CRS-sampled polynomial `crp`.
|
||||
// GetEncryption computes the final encryption of the secret-shared message when provided with the aggregation c0Agg of the parties'
|
||||
// shares in the protocol and with the common, CRS-sampled polynomial crp.
|
||||
func (s2e ShareToEncProtocol) GetEncryption(c0Agg mhe.KeySwitchShare, crp mhe.KeySwitchCRP, opOut *rlwe.Ciphertext) (err error) {
|
||||
if opOut.Degree() != 1 {
|
||||
return fmt.Errorf("cannot GetEncryption: opOut must have degree 1")
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/tuneinsight/lattigo/v5/utils/sampling"
|
||||
)
|
||||
|
||||
// MaskedTransformProtocol is a struct storing the parameters for the MaskedTransformProtocol protocol.
|
||||
// MaskedTransformProtocol is a struct storing the parameters for the [MaskedTransformProtocol] protocol.
|
||||
type MaskedTransformProtocol struct {
|
||||
e2s EncToShareProtocol
|
||||
s2e ShareToEncProtocol
|
||||
@@ -21,9 +21,9 @@ type MaskedTransformProtocol struct {
|
||||
tmpMaskPerm ring.Poly
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of MaskedTransformProtocol in which all the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of [MaskedTransformProtocol] in which all the read-only data-structures are
|
||||
// shared with the receiver and the temporary buffers are reallocated. The receiver and the returned
|
||||
// MaskedTransformProtocol can be used concurrently.
|
||||
// [MaskedTransformProtocol] can be used concurrently.
|
||||
func (rfp MaskedTransformProtocol) ShallowCopy() MaskedTransformProtocol {
|
||||
params := rfp.e2s.params
|
||||
|
||||
@@ -38,12 +38,14 @@ func (rfp MaskedTransformProtocol) ShallowCopy() MaskedTransformProtocol {
|
||||
|
||||
// MaskedTransformFunc is a struct containing a user-defined in-place function that can be applied to masked integer plaintexts, as a part of the
|
||||
// Masked Transform Protocol.
|
||||
// The function is called with a vector of integers modulo heint.Parameters.PlaintextModulus() of size heint.Parameters.N() as input, and must write
|
||||
// The function is called with a vector of integers modulo [heint.Parameters.PlaintextModulus]() of size [heint.Parameters.N]() as input, and must write
|
||||
// its output on the same buffer.
|
||||
// Transform can be the identity.
|
||||
// Decode: if true, then the masked BFV plaintext will be decoded before applying Transform.
|
||||
// Recode: if true, then the masked BFV plaintext will be recoded after applying Transform.
|
||||
// i.e. : Decode (true/false) -> Transform -> Recode (true/false).
|
||||
//
|
||||
// - Decode: if true, then the masked BFV plaintext will be decoded before applying Transform.
|
||||
// - Recode: if true, then the masked BFV plaintext will be recoded after applying Transform.
|
||||
//
|
||||
// Decode (true/false) -> Transform -> Recode (true/false).
|
||||
type MaskedTransformFunc struct {
|
||||
Decode bool
|
||||
Func func(coeffs []uint64)
|
||||
@@ -84,7 +86,7 @@ func (rfp MaskedTransformProtocol) AllocateShare(levelDecrypt, levelRecrypt int)
|
||||
}
|
||||
|
||||
// GenShare generates the shares of the PermuteProtocol.
|
||||
// ct1 is the degree 1 element of a rlwe.Ciphertext, i.e. rlwe.Ciphertext.Value[1].
|
||||
// ct1 is the degree 1 element of a [rlwe.Ciphertext], i.e., [rlwe.Ciphertext.Value][1].
|
||||
func (rfp MaskedTransformProtocol) GenShare(skIn, skOut *rlwe.SecretKey, ct *rlwe.Ciphertext, crs mhe.KeySwitchCRP, transform *MaskedTransformFunc, shareOut *mhe.RefreshShare) (err error) {
|
||||
|
||||
if ct.Level() < shareOut.EncToShareShare.Value.Level() {
|
||||
|
||||
@@ -20,15 +20,15 @@ func (share RefreshShare) BinarySize() int {
|
||||
return share.EncToShareShare.BinarySize() + share.ShareToEncShare.BinarySize() + share.MetaData.BinarySize()
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// WriteTo writes the object on an [io.Writer]. It implements the [io.WriterTo]
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
//
|
||||
// Unless w implements the buffer.Writer interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a bufio.Writer. Since this requires allocations, it
|
||||
// is preferable to pass a buffer.Writer directly:
|
||||
// Unless w implements the [buffer.Writer] interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a [bufio.Writer]. Since this requires allocations, it
|
||||
// is preferable to pass a [buffer.Writer] directly:
|
||||
//
|
||||
// - When writing multiple times to a io.Writer, it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// - When writing multiple times to a [io.Writer], it is preferable to first wrap the
|
||||
// [io.Writer] in a pre-allocated [bufio.Writer].
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (share RefreshShare) WriteTo(w io.Writer) (n int64, err error) {
|
||||
@@ -54,15 +54,15 @@ func (share RefreshShare) WriteTo(w io.Writer) (n int64, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// [io.ReaderFrom] interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a [buffer.Reader] directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// - When reading multiple values from a [io.Reader], it is preferable to first
|
||||
// first wrap [io.Reader] in a pre-allocated [bufio.Reader].
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (share *RefreshShare) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
@@ -96,7 +96,7 @@ func (share RefreshShare) MarshalBinary() (p []byte, err error) {
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
// [RefreshShare.MarshalBinary] or [RefreshShare.WriteTo] on the object.
|
||||
func (share *RefreshShare) UnmarshalBinary(p []byte) (err error) {
|
||||
_, err = share.ReadFrom(buffer.NewBuffer(p))
|
||||
return
|
||||
|
||||
@@ -13,11 +13,11 @@ import (
|
||||
|
||||
// Thresholdizer is a type for generating secret-shares of ringqp.Poly types such that
|
||||
// the resulting sharing has a t-out-of-N-threshold access-structure. It implements the
|
||||
// `Thresholdize` operation as presented in "An Efficient Threshold Access-Structure
|
||||
// "Thresholdize" operation as presented in "An Efficient Threshold Access-Structure
|
||||
// for RLWE-Based Multiparty Homomorphic Encryption" (2022) by Mouchet, C., Bertrand, E.,
|
||||
// and Hubaux, J. P. (https://eprint.iacr.org/2022/780).
|
||||
//
|
||||
// See the `mhe` package README.md.
|
||||
// See the [mhe] package README.md.
|
||||
type Thresholdizer struct {
|
||||
params *rlwe.Parameters
|
||||
ringQP *ringqp.Ring
|
||||
@@ -25,7 +25,7 @@ type Thresholdizer struct {
|
||||
}
|
||||
|
||||
// Combiner is a type for generating t-out-of-t additive shares from local t-out-of-N
|
||||
// shares. It implements the `Combine` operation as presented in "An Efficient Threshold
|
||||
// shares. It implements the "Combine" operation as presented in "An Efficient Threshold
|
||||
// Access-Structure for RLWE-Based Multiparty Homomorphic Encryption" (2022) by Mouchet, C.,
|
||||
// Bertrand, E., and Hubaux, J. P. (https://eprint.iacr.org/2022/780).
|
||||
type Combiner struct {
|
||||
@@ -39,25 +39,25 @@ type Combiner struct {
|
||||
// ShamirPublicPoint is a type for Shamir public point associated with a party identity within
|
||||
// the t-out-of-N-threshold scheme.
|
||||
//
|
||||
// See Thresholdizer and Combiner types.
|
||||
// See [Thresholdizer] and [Combiner] types.
|
||||
type ShamirPublicPoint uint64
|
||||
|
||||
// ShamirPolynomial represents a polynomial with ringqp.Poly coefficients. It is used by the
|
||||
// Thresholdizer type to produce t-out-of-N-threshold shares of an ringqp.Poly.
|
||||
// ShamirPolynomial represents a polynomial with [ringqp.Poly] coefficients. It is used by the
|
||||
// Thresholdizer type to produce t-out-of-N-threshold shares of an [ringqp.Poly].
|
||||
//
|
||||
// See Thresholdizer type.
|
||||
// See [Thresholdizer] type.
|
||||
type ShamirPolynomial struct {
|
||||
Value structs.Vector[ringqp.Poly]
|
||||
}
|
||||
|
||||
// ShamirSecretShare represents a t-out-of-N-threshold secret-share.
|
||||
//
|
||||
// See Thresholdizer and Combiner types.
|
||||
// See [Thresholdizer] and [Combiner] types.
|
||||
type ShamirSecretShare struct {
|
||||
ringqp.Poly
|
||||
}
|
||||
|
||||
// NewThresholdizer creates a new Thresholdizer instance from parameters.
|
||||
// NewThresholdizer creates a new [Thresholdizer] instance from parameters.
|
||||
func NewThresholdizer(params rlwe.ParameterProvider) Thresholdizer {
|
||||
|
||||
thr := Thresholdizer{}
|
||||
@@ -76,7 +76,7 @@ func NewThresholdizer(params rlwe.ParameterProvider) Thresholdizer {
|
||||
return thr
|
||||
}
|
||||
|
||||
// GenShamirPolynomial generates a new secret ShamirPolynomial to be used in the Thresholdizer.GenShamirSecretShare method.
|
||||
// GenShamirPolynomial generates a new secret [ShamirPolynomial] to be used in the [Thresholdizer.GenShamirSecretShare] method.
|
||||
// It does so by sampling a random polynomial of degree threshold - 1 and with its constant term equal to secret.
|
||||
func (thr Thresholdizer) GenShamirPolynomial(threshold int, secret *rlwe.SecretKey) (ShamirPolynomial, error) {
|
||||
if threshold < 1 {
|
||||
@@ -92,18 +92,18 @@ func (thr Thresholdizer) GenShamirPolynomial(threshold int, secret *rlwe.SecretK
|
||||
return ShamirPolynomial{Value: structs.Vector[ringqp.Poly](gen)}, nil
|
||||
}
|
||||
|
||||
// AllocateThresholdSecretShare allocates a ShamirSecretShare struct.
|
||||
// AllocateThresholdSecretShare allocates a [ShamirSecretShare] struct.
|
||||
func (thr Thresholdizer) AllocateThresholdSecretShare() ShamirSecretShare {
|
||||
return ShamirSecretShare{thr.ringQP.NewPoly()}
|
||||
}
|
||||
|
||||
// GenShamirSecretShare generates a secret share for the given recipient, identified by its ShamirPublicPoint.
|
||||
// GenShamirSecretShare generates a secret share for the given recipient, identified by its [ShamirPublicPoint].
|
||||
// The result is stored in ShareOut and should be sent to this party.
|
||||
func (thr Thresholdizer) GenShamirSecretShare(recipient ShamirPublicPoint, secretPoly ShamirPolynomial, shareOut *ShamirSecretShare) {
|
||||
thr.ringQP.EvalPolyScalar(secretPoly.Value, uint64(recipient), shareOut.Poly)
|
||||
}
|
||||
|
||||
// AggregateShares aggregates two ShamirSecretShare and stores the result in outShare.
|
||||
// AggregateShares aggregates two [ShamirSecretShare] and stores the result in outShare.
|
||||
func (thr Thresholdizer) AggregateShares(share1, share2 ShamirSecretShare, outShare *ShamirSecretShare) (err error) {
|
||||
if share1.LevelQ() != share2.LevelQ() || share1.LevelQ() != outShare.LevelQ() || share1.LevelP() != share2.LevelP() || share1.LevelP() != outShare.LevelP() {
|
||||
return fmt.Errorf("cannot AggregateShares: shares level do not match")
|
||||
@@ -112,8 +112,8 @@ func (thr Thresholdizer) AggregateShares(share1, share2 ShamirSecretShare, outSh
|
||||
return
|
||||
}
|
||||
|
||||
// NewCombiner creates a new Combiner struct from the parameters and the set of ShamirPublicPoints. Note that the other
|
||||
// parameter may contain the instantiator's own ShamirPublicPoint.
|
||||
// NewCombiner creates a new [Combiner] struct from the parameters and the set of [ShamirPublicPoints]. Note that the other
|
||||
// parameter may contain the instantiator's own [ShamirPublicPoint].
|
||||
func NewCombiner(params rlwe.Parameters, own ShamirPublicPoint, others []ShamirPublicPoint, threshold int) Combiner {
|
||||
cmb := Combiner{}
|
||||
cmb.ringQP = params.RingQP()
|
||||
@@ -144,7 +144,7 @@ func NewCombiner(params rlwe.Parameters, own ShamirPublicPoint, others []ShamirP
|
||||
}
|
||||
|
||||
// GenAdditiveShare generates a t-out-of-t additive share of the secret from a local aggregated share ownSecret and the set of active identities, identified
|
||||
// by their ShamirPublicPoint. It stores the resulting additive share in skOut.
|
||||
// by their [ShamirPublicPoint]. It stores the resulting additive share in skOut.
|
||||
func (cmb Combiner) GenAdditiveShare(activesPoints []ShamirPublicPoint, ownPoint ShamirPublicPoint, ownShare ShamirSecretShare, skOut *rlwe.SecretKey) (err error) {
|
||||
|
||||
if len(activesPoints) < cmb.threshold {
|
||||
@@ -183,30 +183,30 @@ func (s ShamirSecretShare) BinarySize() int {
|
||||
return s.Poly.BinarySize()
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// WriteTo writes the object on an [io.Writer]. It implements the [io.WriterTo]
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
//
|
||||
// Unless w implements the buffer.Writer interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a bufio.Writer. Since this requires allocations, it
|
||||
// is preferable to pass a buffer.Writer directly:
|
||||
// Unless w implements the [buffer.Writer] interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a [bufio.Writer]. Since this requires allocations, it
|
||||
// is preferable to pass a [buffer.Writer] directly:
|
||||
//
|
||||
// - When writing multiple times to a io.Writer, it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// - When writing multiple times to a [io.Writer], it is preferable to first wrap the
|
||||
// [io.Writer] in a pre-allocated [bufio.Writer].
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (s ShamirSecretShare) WriteTo(w io.Writer) (n int64, err error) {
|
||||
return s.Poly.WriteTo(w)
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
// ReadFrom reads on the object from an [io.Writer]. It implements the
|
||||
// [io.ReaderFrom] interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
// Unless r implements the [buffer.Reader] interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a [bufio.Reader]. Since this requires allocation, it
|
||||
// is preferable to pass a [buffer.Reader] directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// - When reading multiple values from a [io.Reader], it is preferable to first
|
||||
// first wrap [io.Reader] in a pre-allocated [bufio.Reader].
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (s *ShamirSecretShare) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
@@ -219,7 +219,7 @@ func (s ShamirSecretShare) MarshalBinary() (p []byte, err error) {
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
// [ShamirSecretShare.MarshalBinary] or [ShamirSecretShare.WriteTo] on the object.
|
||||
func (s *ShamirSecretShare) UnmarshalBinary(p []byte) (err error) {
|
||||
return s.Poly.UnmarshalBinary(p)
|
||||
}
|
||||
|
||||
@@ -10,12 +10,12 @@ import (
|
||||
"github.com/tuneinsight/lattigo/v5/schemes/bgv"
|
||||
)
|
||||
|
||||
// NewPlaintext allocates a new rlwe.Plaintext from the BFV parameters, at the
|
||||
// NewPlaintext allocates a new [rlwe.Plaintext] from the BFV parameters, at the
|
||||
// specified level. If the level argument is not provided, the plaintext is
|
||||
// initialized at level params.MaxLevelQ().
|
||||
//
|
||||
// The plaintext is initialized with its metadata so that it can be passed to a,
|
||||
// bfv.Encoder. Before doing so, the user can update the MetaData field to set
|
||||
// [bfv.Encoder]. Before doing so, the user can update the MetaData field to set
|
||||
// a specific scaling factor,
|
||||
// plaintext dimensions (if applicable) or encoding domain.
|
||||
func NewPlaintext(params Parameters, level ...int) (pt *rlwe.Plaintext) {
|
||||
@@ -26,7 +26,7 @@ func NewPlaintext(params Parameters, level ...int) (pt *rlwe.Plaintext) {
|
||||
return
|
||||
}
|
||||
|
||||
// NewCiphertext allocates a new rlwe.Ciphertext from the BFV parameters,
|
||||
// NewCiphertext allocates a new [rlwe.Ciphertext] from the BFV parameters,
|
||||
// at the specified level and ciphertext degree. If the level argument is not
|
||||
// provided, the ciphertext is initialized at level params.MaxLevelQ().
|
||||
//
|
||||
@@ -40,19 +40,19 @@ func NewCiphertext(params Parameters, degree int, level ...int) (ct *rlwe.Cipher
|
||||
return
|
||||
}
|
||||
|
||||
// NewEncryptor instantiates a new rlwe.Encryptor from the given BFV parameters and
|
||||
// encryption key. This key can be either a *rlwe.SecretKey or a *rlwe.PublicKey.
|
||||
// NewEncryptor instantiates a new [rlwe.Encryptor] from the given BFV parameters and
|
||||
// encryption key. This key can be either a *[rlwe.SecretKey] or a *[rlwe.PublicKey].
|
||||
func NewEncryptor(params Parameters, key rlwe.EncryptionKey) *rlwe.Encryptor {
|
||||
return rlwe.NewEncryptor(params, key)
|
||||
}
|
||||
|
||||
// NewDecryptor instantiates a new rlwe.Decryptor from the given BFV parameters and
|
||||
// NewDecryptor instantiates a new [rlwe.Decryptor] from the given BFV parameters and
|
||||
// secret decryption key.
|
||||
func NewDecryptor(params Parameters, key *rlwe.SecretKey) *rlwe.Decryptor {
|
||||
return rlwe.NewDecryptor(params, key)
|
||||
}
|
||||
|
||||
// NewKeyGenerator instantiates a new rlwe.KeyGenerator from the given
|
||||
// NewKeyGenerator instantiates a new [rlwe.KeyGenerator] from the given
|
||||
// BFV parameters.
|
||||
func NewKeyGenerator(params Parameters) *rlwe.KeyGenerator {
|
||||
return rlwe.NewKeyGenerator(params)
|
||||
@@ -63,12 +63,12 @@ type Encoder struct {
|
||||
*bgv.Encoder
|
||||
}
|
||||
|
||||
// NewEncoder creates a new Encoder from the provided parameters.
|
||||
// NewEncoder creates a new [Encoder] from the provided parameters.
|
||||
func NewEncoder(params Parameters) *Encoder {
|
||||
return &Encoder{bgv.NewEncoder(params.Parameters)}
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of this Encoder in which the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of this [Encoder] in which the read-only data-structures are
|
||||
// shared with the receiver.
|
||||
func (e Encoder) ShallowCopy() *Encoder {
|
||||
return &Encoder{Encoder: e.Encoder.ShallowCopy()}
|
||||
@@ -80,20 +80,20 @@ type Evaluator struct {
|
||||
*bgv.Evaluator
|
||||
}
|
||||
|
||||
// NewEvaluator creates a new Evaluator, that can be used to do homomorphic
|
||||
// NewEvaluator creates a new [Evaluator], that can be used to do homomorphic
|
||||
// operations on ciphertexts and/or plaintexts. It stores a memory buffer
|
||||
// and ciphertexts that will be used for intermediate values.
|
||||
func NewEvaluator(params Parameters, evk rlwe.EvaluationKeySet) *Evaluator {
|
||||
return &Evaluator{bgv.NewEvaluator(params.Parameters, evk)}
|
||||
}
|
||||
|
||||
// WithKey creates a shallow copy of this Evaluator in which the read-only data-structures are
|
||||
// shared with the receiver but the EvaluationKey is evaluationKey.
|
||||
// WithKey creates a shallow copy of this [Evaluator] in which the read-only data-structures are
|
||||
// shared with the receiver but for which the evaluation key is set to the provided [rlwe.EvaluationKeySet].
|
||||
func (eval Evaluator) WithKey(evk rlwe.EvaluationKeySet) *Evaluator {
|
||||
return &Evaluator{eval.Evaluator.WithKey(evk)}
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of this Evaluator in which the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of this [Evaluator] in which the read-only data-structures are
|
||||
// shared with the receiver.
|
||||
func (eval Evaluator) ShallowCopy() *Evaluator {
|
||||
return &Evaluator{eval.Evaluator.ShallowCopy()}
|
||||
@@ -101,12 +101,12 @@ func (eval Evaluator) ShallowCopy() *Evaluator {
|
||||
|
||||
// Mul multiplies op0 with op1 without relinearization and returns the result in opOut.
|
||||
// inputs:
|
||||
// - op0: an *rlwe.Ciphertext
|
||||
// - op0: an *[rlwe.Ciphertext]
|
||||
// - op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - [rlwe.ElementInterface][ring.Poly]
|
||||
// - *big.Int, uint64, int64, int
|
||||
// - []uint64 or []int64 (of size at most N where N is the smallest integer satisfying PlaintextModulus = 1 mod 2N)
|
||||
// - opOut: an *rlwe.Ciphertext
|
||||
// - opOut: an *[rlwe.Ciphertext]
|
||||
//
|
||||
// The procedure will return an error if either op0 or op1 are have a degree higher than 1.
|
||||
// The procedure will return an error if opOut.Degree != op0.Degree + op1.Degree.
|
||||
@@ -124,12 +124,12 @@ func (eval Evaluator) Mul(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ci
|
||||
|
||||
// MulNew multiplies op0 with op1 without relinearization and returns the result in a new opOut.
|
||||
// inputs:
|
||||
// - op0: an *rlwe.Ciphertext
|
||||
// - op0: an *[rlwe.Ciphertext]
|
||||
// - op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - *big.Int, uint64, int64, int
|
||||
// - []uint64 or []int64 (of size at most N where N is the smallest integer satisfying PlaintextModulus = 1 mod 2N)
|
||||
// - opOut: an *rlwe.Ciphertext
|
||||
// - opOut: an *[rlwe.Ciphertext]
|
||||
//
|
||||
// The procedure will return an error if either op0.Degree or op1.Degree > 1.
|
||||
func (eval Evaluator) MulNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut *rlwe.Ciphertext, err error) {
|
||||
@@ -145,12 +145,12 @@ func (eval Evaluator) MulNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut *rlw
|
||||
|
||||
// MulRelinNew multiplies op0 with op1 with relinearization and returns the result in a new opOut.
|
||||
// inputs:
|
||||
// - op0: an *rlwe.Ciphertext
|
||||
// - op0: an *[rlwe.Ciphertext]
|
||||
// - op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - *big.Int, uint64, int64, int
|
||||
// - []uint64 or []int64 (of size at most N where N is the smallest integer satisfying PlaintextModulus = 1 mod 2N)
|
||||
// - opOut: an *rlwe.Ciphertext
|
||||
// - opOut: an *[rlwe.Ciphertext]
|
||||
//
|
||||
// The procedure will return an error if either op0.Degree or op1.Degree > 1.
|
||||
// The procedure will return an error if the evaluator was not created with an relinearization key.
|
||||
@@ -160,12 +160,12 @@ func (eval Evaluator) MulRelinNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut
|
||||
|
||||
// MulRelin multiplies op0 with op1 with relinearization and returns the result in opOut.
|
||||
// inputs:
|
||||
// - op0: an *rlwe.Ciphertext
|
||||
// - op0: an *[rlwe.Ciphertext]
|
||||
// - op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - *big.Int, uint64, int64, int
|
||||
// - []uint64 or []int64 (of size at most N where N is the smallest integer satisfying PlaintextModulus = 1 mod 2N)
|
||||
// - opOut: an *rlwe.Ciphertext
|
||||
// - opOut: an *[rlwe.Ciphertext]
|
||||
//
|
||||
// The procedure will return an error if either op0.Degree or op1.Degree > 1.
|
||||
// The procedure will return an error if opOut.Degree != op0.Degree + op1.Degree.
|
||||
|
||||
@@ -10,17 +10,17 @@ import (
|
||||
|
||||
// NewParameters instantiate a set of BFV parameters from the generic RLWE parameters and a plaintext modulus t.
|
||||
// User must ensure that t = 1 mod 2n for 4 < n <= N, where N is the ring degree.
|
||||
// It returns the empty parameters Parameters{} and a non-nil error if the specified parameters are invalid.
|
||||
// It returns the empty parameters [Parameters]{} and a non-nil error if the specified parameters are invalid.
|
||||
func NewParameters(rlweParams rlwe.Parameters, t uint64) (p Parameters, err error) {
|
||||
var pbgv bgv.Parameters
|
||||
pbgv, err = bgv.NewParameters(rlweParams, t)
|
||||
return Parameters{pbgv}, err
|
||||
}
|
||||
|
||||
// NewParametersFromLiteral instantiate a set of BFV parameters from a ParametersLiteral specification.
|
||||
// It returns the empty parameters Parameters{} and a non-nil error if the specified parameters are invalid.
|
||||
// NewParametersFromLiteral instantiate a set of BFV parameters from a [ParametersLiteral] specification.
|
||||
// It returns the empty parameters [Parameters]{} and a non-nil error if the specified parameters are invalid.
|
||||
//
|
||||
// See `rlwe.NewParametersFromLiteral` for default values of the optional fields.
|
||||
// See [rlwe.NewParametersFromLiteral] for default values of the optional fields.
|
||||
func NewParametersFromLiteral(pl ParametersLiteral) (p Parameters, err error) {
|
||||
var pbgv bgv.Parameters
|
||||
pbgv, err = bgv.NewParametersFromLiteral(bgv.ParametersLiteral(pl))
|
||||
@@ -29,7 +29,7 @@ func NewParametersFromLiteral(pl ParametersLiteral) (p Parameters, err error) {
|
||||
|
||||
// ParametersLiteral is a literal representation of BFV parameters. It has public
|
||||
// fields and is used to express unchecked user-defined parameters literally into
|
||||
// Go programs. The NewParametersFromLiteral function is used to generate the actual
|
||||
// Go programs. The [NewParametersFromLiteral] function is used to generate the actual
|
||||
// checked parameters from the literal representation.
|
||||
//
|
||||
// Users must set the polynomial degree (LogN) and the coefficient modulus, by either setting
|
||||
@@ -39,16 +39,16 @@ func NewParametersFromLiteral(pl ParametersLiteral) (p Parameters, err error) {
|
||||
//
|
||||
// Optionally, users may specify the error variance (Sigma) and secrets' density (H). If left
|
||||
// unset, standard default values for these field are substituted at parameter creation (see
|
||||
// NewParametersFromLiteral).
|
||||
// [NewParametersFromLiteral]).
|
||||
type ParametersLiteral bgv.ParametersLiteral
|
||||
|
||||
// GetRLWEParametersLiteral returns the rlwe.ParametersLiteral from the target bfv.ParametersLiteral.
|
||||
// GetRLWEParametersLiteral returns the [rlwe.ParametersLiteral] from the target [bfv.ParametersLiteral].
|
||||
func (p ParametersLiteral) GetRLWEParametersLiteral() rlwe.ParametersLiteral {
|
||||
return bgv.ParametersLiteral(p).GetRLWEParametersLiteral()
|
||||
}
|
||||
|
||||
// Parameters represents a parameter set for the BFV cryptosystem. Its fields are private and
|
||||
// immutable. See ParametersLiteral for user-specified parameters.
|
||||
// immutable. See [ParametersLiteral] for user-specified parameters.
|
||||
type Parameters struct {
|
||||
bgv.Parameters
|
||||
}
|
||||
@@ -63,7 +63,7 @@ func (p *Parameters) UnmarshalBinary(data []byte) (err error) {
|
||||
return p.Parameters.UnmarshalJSON(data)
|
||||
}
|
||||
|
||||
// UnmarshalJSON reads a JSON representation of a parameter set into the receiver Parameter. See `Unmarshal` from the `encoding/json` package.
|
||||
// UnmarshalJSON reads a JSON representation of a parameter set into the receiver Parameter. See Unmarshal from the [encoding/json] package.
|
||||
func (p *Parameters) UnmarshalJSON(data []byte) (err error) {
|
||||
return p.Parameters.UnmarshalJSON(data)
|
||||
}
|
||||
|
||||
@@ -5,15 +5,15 @@ import (
|
||||
"github.com/tuneinsight/lattigo/v5/core/rlwe"
|
||||
)
|
||||
|
||||
// NewPlaintext allocates a new rlwe.Plaintext.
|
||||
// NewPlaintext allocates a new [rlwe.Plaintext].
|
||||
//
|
||||
// inputs:
|
||||
// - params: an rlwe.ParameterProvider interface
|
||||
// - params: an [rlwe.ParameterProvider] interface
|
||||
// - level: the level of the plaintext
|
||||
//
|
||||
// output: a newly allocated rlwe.Plaintext at the specified level.
|
||||
// output: a newly allocated [rlwe.Plaintext] at the specified level.
|
||||
//
|
||||
// Note: the user can update the field `MetaData` to set a specific scaling factor,
|
||||
// Note: the user can update the field MetaData to set a specific scaling factor,
|
||||
// plaintext dimensions (if applicable) or encoding domain, before encoding values
|
||||
// on the created plaintext.
|
||||
func NewPlaintext(params Parameters, level int) (pt *rlwe.Plaintext) {
|
||||
@@ -24,14 +24,14 @@ func NewPlaintext(params Parameters, level int) (pt *rlwe.Plaintext) {
|
||||
return
|
||||
}
|
||||
|
||||
// NewCiphertext allocates a new rlwe.Ciphertext.
|
||||
// NewCiphertext allocates a new [rlwe.Ciphertext].
|
||||
//
|
||||
// inputs:
|
||||
// - params: an rlwe.ParameterProvider interface
|
||||
// - params: an [rlwe.ParameterProvider] interface
|
||||
// - degree: the degree of the ciphertext
|
||||
// - level: the level of the Ciphertext
|
||||
//
|
||||
// output: a newly allocated rlwe.Ciphertext of the specified degree and level.
|
||||
// output: a newly allocated [rlwe.Ciphertext] of the specified degree and level.
|
||||
func NewCiphertext(params Parameters, degree, level int) (ct *rlwe.Ciphertext) {
|
||||
ct = rlwe.NewCiphertext(params, degree, level)
|
||||
ct.IsBatched = true
|
||||
@@ -40,34 +40,34 @@ func NewCiphertext(params Parameters, degree, level int) (ct *rlwe.Ciphertext) {
|
||||
return
|
||||
}
|
||||
|
||||
// NewEncryptor instantiates a new rlwe.Encryptor.
|
||||
// NewEncryptor instantiates a new [rlwe.Encryptor].
|
||||
//
|
||||
// inputs:
|
||||
// - params: an rlwe.ParameterProvider interface
|
||||
// - key: *rlwe.SecretKey or *rlwe.PublicKey
|
||||
// - params: an [rlwe.ParameterProvider] interface
|
||||
// - key: *[rlwe.SecretKey] or *[rlwe.PublicKey]
|
||||
//
|
||||
// output: an rlwe.Encryptor instantiated with the provided key.
|
||||
// output: an [rlwe.Encryptor] instantiated with the provided key.
|
||||
func NewEncryptor(params Parameters, key rlwe.EncryptionKey) *rlwe.Encryptor {
|
||||
return rlwe.NewEncryptor(params, key)
|
||||
}
|
||||
|
||||
// NewDecryptor instantiates a new rlwe.Decryptor.
|
||||
// NewDecryptor instantiates a new [rlwe.Decryptor].
|
||||
//
|
||||
// inputs:
|
||||
// - params: an rlwe.ParameterProvider interface
|
||||
// - key: *rlwe.SecretKey
|
||||
// - params: an [rlwe.ParameterProvider] interface
|
||||
// - key: *[rlwe.SecretKey]
|
||||
//
|
||||
// output: an rlwe.Decryptor instantiated with the provided key.
|
||||
// output: an [rlwe.Decryptor] instantiated with the provided key.
|
||||
func NewDecryptor(params Parameters, key *rlwe.SecretKey) *rlwe.Decryptor {
|
||||
return rlwe.NewDecryptor(params, key)
|
||||
}
|
||||
|
||||
// NewKeyGenerator instantiates a new rlwe.KeyGenerator.
|
||||
// NewKeyGenerator instantiates a new [rlwe.KeyGenerator].
|
||||
//
|
||||
// inputs:
|
||||
// - params: an rlwe.ParameterProvider interface
|
||||
// - params: an [rlwe.ParameterProvider] interface
|
||||
//
|
||||
// output: an rlwe.KeyGenerator.
|
||||
// output: an [rlwe.KeyGenerator].
|
||||
func NewKeyGenerator(params Parameters) *rlwe.KeyGenerator {
|
||||
return rlwe.NewKeyGenerator(params)
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ type Encoder struct {
|
||||
tInvModQ []*big.Int
|
||||
}
|
||||
|
||||
// NewEncoder creates a new Encoder from the provided parameters.
|
||||
// NewEncoder creates a new [Encoder] from the provided parameters.
|
||||
func NewEncoder(parameters Parameters) *Encoder {
|
||||
|
||||
ringQ := parameters.RingQ()
|
||||
@@ -119,12 +119,12 @@ func permuteMatrix(logN int) (perm []uint64) {
|
||||
return perm
|
||||
}
|
||||
|
||||
// GetRLWEParameters returns the underlying rlwe.Parameters of the target object.
|
||||
// GetRLWEParameters returns the underlying [rlwe.Parameters] of the target object.
|
||||
func (ecd Encoder) GetRLWEParameters() *rlwe.Parameters {
|
||||
return &ecd.parameters.Parameters
|
||||
}
|
||||
|
||||
// Encode encodes an IntegerSlice of size at most N, where N is the smallest value satisfying PlaintextModulus = 1 mod 2N,
|
||||
// Encode encodes an [IntegerSlice] of size at most N, where N is the smallest value satisfying PlaintextModulus = 1 mod 2N,
|
||||
// on a pre-allocated plaintext.
|
||||
func (ecd Encoder) Encode(values IntegerSlice, pt *rlwe.Plaintext) (err error) {
|
||||
|
||||
@@ -180,7 +180,7 @@ func (ecd Encoder) Encode(values IntegerSlice, pt *rlwe.Plaintext) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// EncodeRingT encodes an IntegerSlice at the given scale on a polynomial pT with coefficients modulo the plaintext modulus PlaintextModulus.
|
||||
// EncodeRingT encodes an [IntegerSlice] at the given scale on a polynomial pT with coefficients modulo the plaintext modulus PlaintextModulus.
|
||||
func (ecd Encoder) EncodeRingT(values IntegerSlice, scale rlwe.Scale, pT ring.Poly) (err error) {
|
||||
perm := ecd.indexMatrix
|
||||
|
||||
@@ -240,10 +240,10 @@ func (ecd Encoder) EncodeRingT(values IntegerSlice, scale rlwe.Scale, pT ring.Po
|
||||
return nil
|
||||
}
|
||||
|
||||
// Embed is a generic method to encode an IntegerSlice on ringqp.Poly or *ring.Poly.
|
||||
// Embed is a generic method to encode an IntegerSlice on [ringqp.Poly] or *[ring.Poly].
|
||||
// If scaleUp is true, then the values will to be multiplied by PlaintextModulus^{-1} mod Q after being encoded on the polynomial.
|
||||
// Encoding is done according to the metadata.
|
||||
// Accepted polyOut.(type) are a ringqp.Poly and *ring.Poly
|
||||
// Accepted polyOut.(type) are a [ringqp.Poly] and *[ring.Poly]
|
||||
func (ecd Encoder) Embed(values IntegerSlice, scaleUp bool, metadata *rlwe.MetaData, polyOut interface{}) (err error) {
|
||||
|
||||
pT := ecd.bufT
|
||||
@@ -310,7 +310,7 @@ func (ecd Encoder) Embed(values IntegerSlice, scaleUp bool, metadata *rlwe.MetaD
|
||||
return
|
||||
}
|
||||
|
||||
// DecodeRingT decodes a polynomial pT with coefficients modulo the plaintext modulu PlaintextModulus on an InterSlice at the given scale.
|
||||
// DecodeRingT decodes a polynomial pT with coefficients modulo the plaintext modulu PlaintextModulus on an [InterSlice] at the given scale.
|
||||
func (ecd Encoder) DecodeRingT(pT ring.Poly, scale rlwe.Scale, values IntegerSlice) (err error) {
|
||||
ringT := ecd.parameters.RingT()
|
||||
ringT.MulScalar(pT, ring.ModExp(scale.Uint64(), ringT.SubRings[0].Modulus-2, ringT.SubRings[0].Modulus), ecd.bufT)
|
||||
|
||||
@@ -109,7 +109,7 @@ func newEvaluatorBuffer(params Parameters) *evaluatorBuffers {
|
||||
}
|
||||
}
|
||||
|
||||
// NewEvaluator creates a new Evaluator, that can be used to do homomorphic
|
||||
// NewEvaluator creates a new [Evaluator], that can be used to do homomorphic
|
||||
// operations on ciphertexts and/or plaintexts. It stores a memory buffer
|
||||
// and ciphertexts that will be used for intermediate values.
|
||||
func NewEvaluator(parameters Parameters, evk rlwe.EvaluationKeySet) *Evaluator {
|
||||
@@ -122,12 +122,12 @@ func NewEvaluator(parameters Parameters, evk rlwe.EvaluationKeySet) *Evaluator {
|
||||
return ev
|
||||
}
|
||||
|
||||
// GetParameters returns a pointer to the underlying bgv.Parameters.
|
||||
// GetParameters returns a pointer to the underlying [bgv.Parameters].
|
||||
func (eval Evaluator) GetParameters() *Parameters {
|
||||
return &eval.Encoder.parameters
|
||||
}
|
||||
|
||||
// ShallowCopy creates a shallow copy of this Evaluator in which the read-only data-structures are
|
||||
// ShallowCopy creates a shallow copy of this [Evaluator] in which the read-only data-structures are
|
||||
// shared with the receiver.
|
||||
func (eval Evaluator) ShallowCopy() *Evaluator {
|
||||
return &Evaluator{
|
||||
@@ -138,8 +138,8 @@ func (eval Evaluator) ShallowCopy() *Evaluator {
|
||||
}
|
||||
}
|
||||
|
||||
// WithKey creates a shallow copy of this Evaluator in which the read-only data-structures are
|
||||
// shared with the receiver but the EvaluationKey is evaluationKey.
|
||||
// WithKey creates a shallow copy of this [Evaluator] in which the read-only data-structures are
|
||||
// shared with the receiver but the evaluation key is set to the provided [rlwe.EvaluationKeySet].
|
||||
func (eval Evaluator) WithKey(evk rlwe.EvaluationKeySet) *Evaluator {
|
||||
return &Evaluator{
|
||||
evaluatorBase: eval.evaluatorBase,
|
||||
@@ -151,14 +151,14 @@ func (eval Evaluator) WithKey(evk rlwe.EvaluationKeySet) *Evaluator {
|
||||
|
||||
// Add adds op1 to op0 and returns the result in opOut.
|
||||
// inputs:
|
||||
// - op0: an *rlwe.Ciphertext
|
||||
// - op0: an *[rlwe.Ciphertext]
|
||||
// - op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - *big.Int, uint64, int64, int
|
||||
// - []uint64 or []int64 (of size at most N where N is the smallest integer satisfying PlaintextModulus = 1 mod 2N)
|
||||
// - opOut: an *rlwe.Ciphertext
|
||||
// - opOut: an *[rlwe.Ciphertext]
|
||||
//
|
||||
// If op1 is an rlwe.ElementInterface[ring.Poly] and the scales of op0, op1 and opOut do not match, then a scale matching operation will
|
||||
// If op1 is an [rlwe.ElementInterface][[ring.Poly]] and the scales of op0, op1 and opOut do not match, then a scale matching operation will
|
||||
// be automatically carried out to ensure that addition is performed between operands of the same scale.
|
||||
// This scale matching operation will increase the noise by a small factor.
|
||||
// For this reason it is preferable to ensure that all operands are already at the same scale when calling this method.
|
||||
@@ -294,15 +294,15 @@ func (eval Evaluator) newCiphertextBinary(op0, op1 rlwe.ElementInterface[ring.Po
|
||||
return NewCiphertext(*eval.GetParameters(), utils.Max(op0.Degree(), op1.Degree()), utils.Min(op0.Level(), op1.Level()))
|
||||
}
|
||||
|
||||
// AddNew adds op1 to op0 and returns the result on a new *rlwe.Ciphertext opOut.
|
||||
// AddNew adds op1 to op0 and returns the result on a new *[rlwe.Ciphertext] opOut.
|
||||
// inputs:
|
||||
// - op0: an *rlwe.Ciphertext
|
||||
// - op0: an *[rlwe.Ciphertext]
|
||||
// - op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - *big.Int, uint64, int64, int
|
||||
// - []uint64 or []int64 (of size at most N where N is the smallest integer satisfying PlaintextModulus = 1 mod 2N)
|
||||
//
|
||||
// If op1 is an rlwe.ElementInterface[ring.Poly] and the scales of op0 and op1 not match, then a scale matching operation will
|
||||
// If op1 is an [rlwe.ElementInterface][[ring.Poly]] and the scales of op0 and op1 not match, then a scale matching operation will
|
||||
// be automatically carried out to ensure that addition is performed between operands of the same scale.
|
||||
// This scale matching operation will increase the noise by a small factor.
|
||||
// For this reason it is preferable to ensure that all operands are already at the same scale when calling this method.
|
||||
@@ -320,14 +320,14 @@ func (eval Evaluator) AddNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut *rlw
|
||||
|
||||
// Sub subtracts op1 to op0 and returns the result in opOut.
|
||||
// inputs:
|
||||
// - op0: an *rlwe.Ciphertext
|
||||
// - op0: an *[rlwe.Ciphertext]
|
||||
// - op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - *big.Int, uint64, int64, int
|
||||
// - []uint64 or []int64 (of size at most N where N is the smallest integer satisfying PlaintextModulus = 1 mod 2N)
|
||||
// - opOut: an *rlwe.Ciphertext
|
||||
// - opOut: an *[rlwe.Ciphertext]
|
||||
//
|
||||
// If op1 is an rlwe.ElementInterface[ring.Poly] and the scales of op0, op1 and opOut do not match, then a scale matching operation will
|
||||
// If op1 is an [rlwe.ElementInterface][[ring.Poly]] and the scales of op0, op1 and opOut do not match, then a scale matching operation will
|
||||
// be automatically carried out to ensure that the subtraction is performed between operands of the same scale.
|
||||
// This scale matching operation will increase the noise by a small factor.
|
||||
// For this reason it is preferable to ensure that all operands are already at the same scale when calling this method.
|
||||
@@ -394,15 +394,15 @@ func (eval Evaluator) Sub(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ci
|
||||
return
|
||||
}
|
||||
|
||||
// SubNew subtracts op1 to op0 and returns the result in a new *rlwe.Ciphertext opOut.
|
||||
// SubNew subtracts op1 to op0 and returns the result in a new *[rlwe.Ciphertext] opOut.
|
||||
// inputs:
|
||||
// - op0: an *rlwe.Ciphertext
|
||||
// - op0: an *[rlwe.Ciphertext]
|
||||
// - op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - *big.Int, uint64, int64, int
|
||||
// - []uint64 or []int64 (of size at most N where N is the smallest integer satisfying PlaintextModulus = 1 mod 2N)
|
||||
//
|
||||
// If op1 is an rlwe.ElementInterface[ring.Poly] and the scales of op0, op1 and opOut do not match, then a scale matching operation will
|
||||
// If op1 is an [rlwe.ElementInterface][[ring.Poly]] and the scales of op0, op1 and opOut do not match, then a scale matching operation will
|
||||
// be automatically carried out to ensure that the subtraction is performed between operands of the same scale.
|
||||
// This scale matching operation will increase the noise by a small factor.
|
||||
// For this reason it is preferable to ensure that all operands are already at the same scale when calling this method.
|
||||
@@ -430,14 +430,14 @@ func (eval Evaluator) DropLevel(op0 *rlwe.Ciphertext, levels int) {
|
||||
// The procedure will return an error if opOut.Degree != op0.Degree + op1.Degree.
|
||||
//
|
||||
// inputs:
|
||||
// - op0: an *rlwe.Ciphertext
|
||||
// - op0: an *[rlwe.Ciphertext]
|
||||
// - op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - *big.Int, uint64, int64, int
|
||||
// - []uint64 or []int64 (of size at most N where N is the smallest integer satisfying PlaintextModulus = 1 mod 2N)
|
||||
// - opOut: an *rlwe.Ciphertext
|
||||
// - opOut: an *[rlwe.Ciphertext]
|
||||
//
|
||||
// If op1 is an rlwe.ElementInterface[ring.Poly]:
|
||||
// If op1 is an [rlwe.ElementInterface][[ring.Poly]]:
|
||||
// - the level of opOut will be updated to min(op0.Level(), op1.Level())
|
||||
// - the scale of opOut will be updated to op0.Scale * op1.Scale
|
||||
func (eval Evaluator) Mul(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error) {
|
||||
@@ -521,19 +521,19 @@ func (eval Evaluator) Mul(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ci
|
||||
return
|
||||
}
|
||||
|
||||
// MulNew multiplies op0 with op1 without relinearization and using standard tensoring (BGV/CKKS-style), and returns the result in a new *rlwe.Ciphertext opOut.
|
||||
// MulNew multiplies op0 with op1 without relinearization and using standard tensoring (BGV/CKKS-style), and returns the result in a new *[rlwe.Ciphertext] opOut.
|
||||
// This tensoring increases the noise by a multiplicative factor of the plaintext and noise norms of the operands and will usually
|
||||
// require to be followed by a rescaling operation to avoid an exponential growth of the noise from subsequent multiplications.
|
||||
// The procedure will return an error if either op0 or op1 are have a degree higher than 1.
|
||||
//
|
||||
// inputs:
|
||||
// - op0: an *rlwe.Ciphertext
|
||||
// - op0: an *[rlwe.Ciphertext]
|
||||
// - op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - *big.Int, uint64, int64, int
|
||||
// - []uint64 or []int64 (of size at most N where N is the smallest integer satisfying PlaintextModulus = 1 mod 2N)
|
||||
//
|
||||
// If op1 is an rlwe.ElementInterface[ring.Poly]:
|
||||
// If op1 is an [rlwe.ElementInterface][[ring.Poly]]:
|
||||
// - the degree of opOut will be op0.Degree() + op1.Degree()
|
||||
// - the level of opOut will be to min(op0.Level(), op1.Level())
|
||||
// - the scale of opOut will be to op0.Scale * op1.Scale
|
||||
@@ -556,14 +556,14 @@ func (eval Evaluator) MulNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut *rlw
|
||||
// The procedure will return an error if the evaluator was not created with an relinearization key.
|
||||
//
|
||||
// inputs:
|
||||
// - op0: an *rlwe.Ciphertext
|
||||
// - op0: an *[rlwe.Ciphertext]
|
||||
// - op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - *big.Int, uint64, int64, int
|
||||
// - []uint64 or []int64 (of size at most N where N is the smallest integer satisfying PlaintextModulus = 1 mod 2N)
|
||||
// - opOut: an *rlwe.Ciphertext
|
||||
// - opOut: an *[rlwe.Ciphertext]
|
||||
//
|
||||
// If op1 is an rlwe.ElementInterface[ring.Poly]:
|
||||
// If op1 is an [rlwe.ElementInterface][[ring.Poly]]:
|
||||
// - the level of opOut will be updated to min(op0.Level(), op1.Level())
|
||||
// - the scale of opOut will be updated to op0.Scale * op1.Scale
|
||||
func (eval Evaluator) MulRelin(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error) {
|
||||
@@ -590,20 +590,20 @@ func (eval Evaluator) MulRelin(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rl
|
||||
return
|
||||
}
|
||||
|
||||
// MulRelinNew multiplies op0 with op1 with relinearization and and using standard tensoring (BGV/CKKS-style), returns the result in a new *rlwe.Ciphertext opOut.
|
||||
// MulRelinNew multiplies op0 with op1 with relinearization and and using standard tensoring (BGV/CKKS-style), returns the result in a new *[rlwe.Ciphertext] opOut.
|
||||
// This tensoring increases the noise by a multiplicative factor of the plaintext and noise norms of the operands and will usually
|
||||
// require to be followed by a rescaling operation to avoid an exponential growth of the noise from subsequent multiplications.
|
||||
// The procedure will return an error if either op0.Degree or op1.Degree > 1.
|
||||
// The procedure will return an error if the evaluator was not created with an relinearization key.
|
||||
//
|
||||
// inputs:
|
||||
// - op0: an *rlwe.Ciphertext
|
||||
// - op0: an *[rlwe.Ciphertext]
|
||||
// - op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - *big.Int, uint64, int64, int
|
||||
// - []uint64 or []int64 (of size at most N where N is the smallest integer satisfying PlaintextModulus = 1 mod 2N)
|
||||
//
|
||||
// If op1 is an rlwe.ElementInterface[ring.Poly]:
|
||||
// If op1 is an [rlwe.ElementInterface][[ring.Poly]]:
|
||||
// - the level of opOut will be to min(op0.Level(), op1.Level())
|
||||
// - the scale of opOut will be to op0.Scale * op1.Scale
|
||||
func (eval Evaluator) MulRelinNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut *rlwe.Ciphertext, err error) {
|
||||
@@ -713,14 +713,14 @@ func (eval Evaluator) tensorStandard(op0 *rlwe.Ciphertext, op1 *rlwe.Element[rin
|
||||
// The procedure will return an error if the evaluator was not created with an relinearization key.
|
||||
//
|
||||
// inputs:
|
||||
// - op0: an *rlwe.Ciphertext
|
||||
// - op0: an *[rlwe.Ciphertext]
|
||||
// - op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - *big.Int, uint64, int64, int
|
||||
// - []uint64 or []int64 (of size at most N where N is the smallest integer satisfying PlaintextModulus = 1 mod 2N)
|
||||
// - opOut: an *rlwe.Ciphertext
|
||||
// - opOut: an *[rlwe.Ciphertext]
|
||||
//
|
||||
// If op1 is an rlwe.ElementInterface[ring.Poly]:
|
||||
// If op1 is an [rlwe.ElementInterface][[ring.Poly]]:
|
||||
// - the level of opOut will be updated to min(op0.Level(), op1.Level())
|
||||
// - the scale of opOut will be to op0.Scale * op1.Scale * (-Q mod T)^{-1} mod T
|
||||
func (eval Evaluator) MulScaleInvariant(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error) {
|
||||
@@ -784,7 +784,7 @@ func (eval Evaluator) MulScaleInvariant(op0 *rlwe.Ciphertext, op1 rlwe.Operand,
|
||||
return
|
||||
}
|
||||
|
||||
// MulScaleInvariantNew multiplies op0 with op1 without relinearization and using scale invariant tensoring (BFV-style), and returns the result in a new *rlwe.Ciphertext opOut.
|
||||
// MulScaleInvariantNew multiplies op0 with op1 without relinearization and using scale invariant tensoring (BFV-style), and returns the result in a new *[rlwe.Ciphertext] opOut.
|
||||
// This tensoring increases the noise by a constant factor regardless of the current noise, thus no rescaling is required with subsequent multiplications if they are
|
||||
// performed with the invariant tensoring procedure. Rescaling can still be useful to reduce the size of the ciphertext, once the noise is higher than the prime
|
||||
// that will be used for the rescaling or to ensure that the noise is minimal before using the regular tensoring.
|
||||
@@ -792,13 +792,13 @@ func (eval Evaluator) MulScaleInvariant(op0 *rlwe.Ciphertext, op1 rlwe.Operand,
|
||||
// The procedure will return an error if the evaluator was not created with an relinearization key.
|
||||
//
|
||||
// inputs:
|
||||
// - op0: an *rlwe.Ciphertext
|
||||
// - op0: an *[rlwe.Ciphertext]
|
||||
// - op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - *big.Int, uint64, int64, int
|
||||
// - []uint64 or []int64 (of size at most N where N is the smallest integer satisfying PlaintextModulus = 1 mod 2N)
|
||||
//
|
||||
// If op1 is an rlwe.ElementInterface[ring.Poly]:
|
||||
// If op1 is an [rlwe.ElementInterface][[ring.Poly]]:
|
||||
// - the level of opOut will be to min(op0.Level(), op1.Level())
|
||||
// - the scale of opOut will be to op0.Scale * op1.Scale * (-Q mod PlaintextModulus)^{-1} mod PlaintextModulus
|
||||
func (eval Evaluator) MulScaleInvariantNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut *rlwe.Ciphertext, err error) {
|
||||
@@ -819,14 +819,14 @@ func (eval Evaluator) MulScaleInvariantNew(op0 *rlwe.Ciphertext, op1 rlwe.Operan
|
||||
// The procedure will return an error if the evaluator was not created with an relinearization key.
|
||||
//
|
||||
// inputs:
|
||||
// - op0: an *rlwe.Ciphertext
|
||||
// - op0: an *[rlwe.Ciphertext]
|
||||
// - op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - *big.Int, uint64, int64, int
|
||||
// - []uint64 or []int64 (of size at most N where N is the smallest integer satisfying PlaintextModulus = 1 mod 2N)
|
||||
// - opOut: an *rlwe.Ciphertext
|
||||
// - opOut: an *[rlwe.Ciphertext]
|
||||
//
|
||||
// If op1 is an rlwe.ElementInterface[ring.Poly]:
|
||||
// If op1 is an [rlwe.ElementInterface][[ring.Poly]]:
|
||||
// - the level of opOut will be updated to min(op0.Level(), op1.Level())
|
||||
// - the scale of opOut will be to op0.Scale * op1.Scale * (-Q mod PlaintextModulus)^{-1} mod PlaintextModulus
|
||||
func (eval Evaluator) MulRelinScaleInvariant(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error) {
|
||||
@@ -895,7 +895,7 @@ func (eval Evaluator) MulRelinScaleInvariant(op0 *rlwe.Ciphertext, op1 rlwe.Oper
|
||||
return
|
||||
}
|
||||
|
||||
// MulRelinScaleInvariantNew multiplies op0 with op1 with relinearization and using scale invariant tensoring (BFV-style), and returns the result in a new *rlwe.Ciphertext opOut.
|
||||
// MulRelinScaleInvariantNew multiplies op0 with op1 with relinearization and using scale invariant tensoring (BFV-style), and returns the result in a new *[rlwe.Ciphertext] opOut.
|
||||
// This tensoring increases the noise by a constant factor regardless of the current noise, thus no rescaling is required with subsequent multiplications if they are
|
||||
// performed with the invariant tensoring procedure. Rescaling can still be useful to reduce the size of the ciphertext, once the noise is higher than the prime
|
||||
// that will be used for the rescaling or to ensure that the noise is minimal before using the regular tensoring.
|
||||
@@ -903,13 +903,13 @@ func (eval Evaluator) MulRelinScaleInvariant(op0 *rlwe.Ciphertext, op1 rlwe.Oper
|
||||
// The procedure will return an error if the evaluator was not created with an relinearization key.
|
||||
//
|
||||
// inputs:
|
||||
// - op0: an *rlwe.Ciphertext
|
||||
// - op0: an *[rlwe.Ciphertext]
|
||||
// - op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - *big.Int, uint64, int64, int
|
||||
// - []uint64 or []int64 (of size at most N where N is the smallest integer satisfying PlaintextModulus = 1 mod 2N)
|
||||
//
|
||||
// If op1 is an rlwe.ElementInterface[ring.Poly]:
|
||||
// If op1 is an [rlwe.ElementInterface][[ring.Poly]]:
|
||||
// - the level of opOut will be to min(op0.Level(), op1.Level())
|
||||
// - the scale of opOut will be to op0.Scale * op1.Scale * (-Q mod PlaintextModulus)^{-1} mod PlaintextModulus
|
||||
func (eval Evaluator) MulRelinScaleInvariantNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut *rlwe.Ciphertext, err error) {
|
||||
@@ -1083,14 +1083,14 @@ func (eval Evaluator) quantize(level, levelQMul int, c2Q1, c2Q2 ring.Poly) {
|
||||
// The procedure will return an error if either op0 == opOut or op1 == opOut.
|
||||
//
|
||||
// inputs:
|
||||
// - op0: an *rlwe.Ciphertext
|
||||
// - op0: an *[rlwe.Ciphertext]
|
||||
// - op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - *big.Int, uint64, int64, int
|
||||
// - []uint64 or []int64 (of size at most N where N is the smallest integer satisfying PlaintextModulus = 1 mod 2N)
|
||||
// - opOut: an *rlwe.Ciphertext
|
||||
// - opOut: an *[rlwe.Ciphertext]
|
||||
//
|
||||
// If op1 is an rlwe.ElementInterface[ring.Poly] and opOut.Scale != op1.Scale * op0.Scale, then a scale matching operation will
|
||||
// If op1 is an [rlwe.ElementInterface][[ring.Poly]] and opOut.Scale != op1.Scale * op0.Scale, then a scale matching operation will
|
||||
// be automatically carried out to ensure that addition is performed between operands of the same scale.
|
||||
// This scale matching operation will increase the noise by a small factor.
|
||||
// For this reason it is preferable to ensure that opOut.Scale == op1.Scale * op0.Scale when calling this method.
|
||||
@@ -1205,14 +1205,14 @@ func (eval Evaluator) MulThenAdd(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *
|
||||
// The procedure will return an error if either op0 == opOut or op1 == opOut.
|
||||
//
|
||||
// inputs:
|
||||
// - op0: an *rlwe.Ciphertext
|
||||
// - op0: an *[rlwe.Ciphertext]
|
||||
// - op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - *big.Int, uint64, int64, int
|
||||
// - []uint64 or []int64 (of size at most N where N is the smallest integer satisfying PlaintextModulus = 1 mod 2N)
|
||||
// - opOut: an *rlwe.Ciphertext
|
||||
// - opOut: an *[rlwe.Ciphertext]
|
||||
//
|
||||
// If op1 is an rlwe.ElementInterface[ring.Poly] and opOut.Scale != op1.Scale * op0.Scale, then a scale matching operation will
|
||||
// If op1 is an [rlwe.ElementInterface][[ring.Poly]] and opOut.Scale != op1.Scale * op0.Scale, then a scale matching operation will
|
||||
// be automatically carried out to ensure that addition is performed between operands of the same scale.
|
||||
// This scale matching operation will increase the noise by a small factor.
|
||||
// For this reason it is preferable to ensure that opOut.Scale == op1.Scale * op0.Scale when calling this method.
|
||||
@@ -1401,7 +1401,7 @@ func (eval Evaluator) RelinearizeNew(op0 *rlwe.Ciphertext) (opOut *rlwe.Cipherte
|
||||
}
|
||||
|
||||
// ApplyEvaluationKeyNew re-encrypts op0 under a different key and returns the result in a new opOut.
|
||||
// It requires a EvaluationKey, which is computed from the key under which the Ciphertext is currently encrypted,
|
||||
// It requires a [rlwe.EvaluationKey], which is computed from the key under which the Ciphertext is currently encrypted,
|
||||
// and the key under which the Ciphertext will be re-encrypted.
|
||||
// The procedure will return an error if either op0.Degree() or opOut.Degree() != 1.
|
||||
func (eval Evaluator) ApplyEvaluationKeyNew(op0 *rlwe.Ciphertext, evk *rlwe.EvaluationKey) (opOut *rlwe.Ciphertext, err error) {
|
||||
|
||||
@@ -18,7 +18,7 @@ const (
|
||||
|
||||
// ParametersLiteral is a literal representation of BGV parameters. It has public
|
||||
// fields and is used to express unchecked user-defined parameters literally into
|
||||
// Go programs. The NewParametersFromLiteral function is used to generate the actual
|
||||
// Go programs. The [NewParametersFromLiteral] function is used to generate the actual
|
||||
// checked parameters from the literal representation.
|
||||
//
|
||||
// Users must set the polynomial degree (LogN) and the coefficient modulus, by either setting
|
||||
@@ -44,8 +44,8 @@ type ParametersLiteral struct {
|
||||
PlaintextModulus uint64 // Plaintext modulus
|
||||
}
|
||||
|
||||
// GetRLWEParametersLiteral returns the rlwe.ParametersLiteral from the target bgv.ParametersLiteral.
|
||||
// See the ParametersLiteral type for details on the BGV parameters.
|
||||
// GetRLWEParametersLiteral returns the [rlwe.ParametersLiteral] from the target [bgv.ParametersLiteral].
|
||||
// See the [ParametersLiteral] type for details on the BGV parameters.
|
||||
func (p ParametersLiteral) GetRLWEParametersLiteral() rlwe.ParametersLiteral {
|
||||
return rlwe.ParametersLiteral{
|
||||
LogN: p.LogN,
|
||||
@@ -63,7 +63,7 @@ func (p ParametersLiteral) GetRLWEParametersLiteral() rlwe.ParametersLiteral {
|
||||
}
|
||||
|
||||
// Parameters represents a parameter set for the BGV cryptosystem. Its fields are private and
|
||||
// immutable. See ParametersLiteral for user-specified parameters.
|
||||
// immutable. See [ParametersLiteral] for user-specified parameters.
|
||||
type Parameters struct {
|
||||
rlwe.Parameters
|
||||
ringQMul *ring.Ring
|
||||
@@ -71,8 +71,8 @@ type Parameters struct {
|
||||
}
|
||||
|
||||
// NewParameters instantiate a set of BGV parameters from the generic RLWE parameters and the BGV-specific ones.
|
||||
// It returns the empty parameters Parameters{} and a non-nil error if the specified parameters are invalid.
|
||||
// See the ParametersLiteral type for more details on the BGV parameters.
|
||||
// It returns the empty parameters [Parameters]{} and a non-nil error if the specified parameters are invalid.
|
||||
// See the [ParametersLiteral] type for more details on the BGV parameters.
|
||||
func NewParameters(rlweParams rlwe.Parameters, t uint64) (p Parameters, err error) {
|
||||
|
||||
if !rlweParams.NTTFlag() {
|
||||
@@ -127,10 +127,10 @@ func NewParameters(rlweParams rlwe.Parameters, t uint64) (p Parameters, err erro
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewParametersFromLiteral instantiate a set of BGV parameters from a ParametersLiteral specification.
|
||||
// It returns the empty parameters Parameters{} and a non-nil error if the specified parameters are invalid.
|
||||
// NewParametersFromLiteral instantiate a set of BGV parameters from a [ParametersLiteral] specification.
|
||||
// It returns the empty parameters [Parameters]{} and a non-nil error if the specified parameters are invalid.
|
||||
//
|
||||
// See `rlwe.NewParametersFromLiteral` for default values of the optional fields and other details on the BGV
|
||||
// See [rlwe.NewParametersFromLiteral] for default values of the optional fields and other details on the BGV
|
||||
// parameters.
|
||||
func NewParametersFromLiteral(pl ParametersLiteral) (Parameters, error) {
|
||||
rlweParams, err := rlwe.NewParametersFromLiteral(pl.GetRLWEParametersLiteral())
|
||||
@@ -140,7 +140,7 @@ func NewParametersFromLiteral(pl ParametersLiteral) (Parameters, error) {
|
||||
return NewParameters(rlweParams, pl.PlaintextModulus)
|
||||
}
|
||||
|
||||
// ParametersLiteral returns the ParametersLiteral of the target Parameters.
|
||||
// ParametersLiteral returns the [ParametersLiteral] of the target Parameters.
|
||||
func (p Parameters) ParametersLiteral() ParametersLiteral {
|
||||
return ParametersLiteral{
|
||||
LogN: p.LogN(),
|
||||
@@ -182,14 +182,14 @@ func (p Parameters) LogMaxDimensions() ring.Dimensions {
|
||||
}
|
||||
}
|
||||
|
||||
// MaxSlots returns the total number of entries (`slots`) that a plaintext can store.
|
||||
// MaxSlots returns the total number of entries (slots) that a plaintext can store.
|
||||
// This value is obtained by multiplying all dimensions from MaxDimensions.
|
||||
func (p Parameters) MaxSlots() int {
|
||||
dims := p.MaxDimensions()
|
||||
return dims.Rows * dims.Cols
|
||||
}
|
||||
|
||||
// LogMaxSlots returns the total number of entries (`slots`) that a plaintext can store.
|
||||
// LogMaxSlots returns the total number of entries (slots) that a plaintext can store.
|
||||
// This value is obtained by summing all log dimensions from LogDimensions.
|
||||
func (p Parameters) LogMaxSlots() int {
|
||||
dims := p.LogMaxDimensions()
|
||||
@@ -254,7 +254,7 @@ func (p Parameters) GaloisElementForRowRotation() uint64 {
|
||||
}
|
||||
|
||||
// GaloisElementsForInnerSum returns the list of Galois elements necessary to apply the method
|
||||
// `InnerSum` operation with parameters `batch` and `n`.
|
||||
// InnerSum operation with parameters batch and n.
|
||||
func (p Parameters) GaloisElementsForInnerSum(batch, n int) (galEls []uint64) {
|
||||
galEls = rlwe.GaloisElementsForInnerSum(p, batch, n)
|
||||
if n > p.N()>>1 {
|
||||
@@ -264,7 +264,7 @@ func (p Parameters) GaloisElementsForInnerSum(batch, n int) (galEls []uint64) {
|
||||
}
|
||||
|
||||
// GaloisElementsForReplicate returns the list of Galois elements necessary to perform the
|
||||
// `Replicate` operation with parameters `batch` and `n`.
|
||||
// Replicate operation with parameters batch and n.
|
||||
func (p Parameters) GaloisElementsForReplicate(batch, n int) (galEls []uint64) {
|
||||
galEls = rlwe.GaloisElementsForReplicate(p, batch, n)
|
||||
if n > p.N()>>1 {
|
||||
@@ -273,19 +273,19 @@ func (p Parameters) GaloisElementsForReplicate(batch, n int) (galEls []uint64) {
|
||||
return
|
||||
}
|
||||
|
||||
// GaloisElementsForTrace returns the list of Galois elements requored for the for the `Trace` operation.
|
||||
// GaloisElementsForTrace returns the list of Galois elements requored for the for the Trace operation.
|
||||
// Trace maps X -> sum((-1)^i * X^{i*n+1}) for 2^{LogN} <= i < N.
|
||||
func (p Parameters) GaloisElementsForTrace(logN int) []uint64 {
|
||||
return rlwe.GaloisElementsForTrace(p, logN)
|
||||
}
|
||||
|
||||
// GaloisElementsForExpand returns the list of Galois elements required
|
||||
// to perform the `Expand` operation with parameter `logN`.
|
||||
// to perform the Expand operation with parameter logN.
|
||||
func (p Parameters) GaloisElementsForExpand(logN int) []uint64 {
|
||||
return rlwe.GaloisElementsForExpand(p, logN)
|
||||
}
|
||||
|
||||
// GaloisElementsForPack returns the list of Galois elements required to perform the `Pack` operation.
|
||||
// GaloisElementsForPack returns the list of Galois elements required to perform the Pack operation.
|
||||
func (p Parameters) GaloisElementsForPack(logN int) []uint64 {
|
||||
return rlwe.GaloisElementsForPack(p, logN)
|
||||
}
|
||||
@@ -307,12 +307,12 @@ func (p *Parameters) UnmarshalBinary(data []byte) (err error) {
|
||||
return p.UnmarshalJSON(data)
|
||||
}
|
||||
|
||||
// MarshalJSON returns a JSON representation of this parameter set. See `Marshal` from the `encoding/json` package.
|
||||
// MarshalJSON returns a JSON representation of this parameter set. See Marshal from the [encoding/json] package.
|
||||
func (p Parameters) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(p.ParametersLiteral())
|
||||
}
|
||||
|
||||
// UnmarshalJSON reads a JSON representation of a parameter set into the receiver Parameter. See `Unmarshal` from the `encoding/json` package.
|
||||
// UnmarshalJSON reads a JSON representation of a parameter set into the receiver Parameter. See Unmarshal from the [encoding/json] package.
|
||||
func (p *Parameters) UnmarshalJSON(data []byte) (err error) {
|
||||
var params ParametersLiteral
|
||||
if err = json.Unmarshal(data, ¶ms); err != nil {
|
||||
|
||||
@@ -17,10 +17,10 @@ type DomainSwitcher struct {
|
||||
automorphismIndex []uint64
|
||||
}
|
||||
|
||||
// NewDomainSwitcher instantiate a new DomainSwitcher type. It may be instantiated from parameters from either RingType.
|
||||
// NewDomainSwitcher instantiate a new [DomainSwitcher] type. It may be instantiated from parameters from either RingType.
|
||||
// The method returns an error if the parameters cannot support the switching (e.g., the NTTs are undefined for
|
||||
// either of the two ring types).
|
||||
// The comlexToRealEvk and comlexToRealEvk EvaluationKeys can be generated using the rlwe.KeyGenerator.GenEvaluationKeysForRingSwap(*).
|
||||
// The comlexToRealEvk and comlexToRealEvk EvaluationKeys can be generated using [rlwe.KeyGenerator.GenEvaluationKeysForRingSwap].
|
||||
func NewDomainSwitcher(params Parameters, comlexToRealEvk, realToComplexEvk *rlwe.EvaluationKey) (DomainSwitcher, error) {
|
||||
|
||||
s := DomainSwitcher{
|
||||
@@ -44,8 +44,8 @@ func NewDomainSwitcher(params Parameters, comlexToRealEvk, realToComplexEvk *rlw
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// ComplexToReal switches the provided ciphertext `ctIn` from the standard domain to the conjugate
|
||||
// invariant domain and writes the result into `opOut`.
|
||||
// ComplexToReal switches the provided ciphertext ctIn from the standard domain to the conjugate
|
||||
// invariant domain and writes the result into opOut.
|
||||
// Given ctInCKKS = enc(real(m) + imag(m)) in Z[X](X^N + 1), returns opOutCI = enc(real(m))
|
||||
// in Z[X+X^-1]/(X^N + 1) in compressed form (N/2 coefficients).
|
||||
// The scale of the output ciphertext is twice the scale of the input one.
|
||||
@@ -86,13 +86,13 @@ func (switcher DomainSwitcher) ComplexToReal(eval *Evaluator, ctIn, opOut *rlwe.
|
||||
return
|
||||
}
|
||||
|
||||
// RealToComplex switches the provided ciphertext `ctIn` from the conjugate invariant domain to the
|
||||
// standard domain and writes the result into `opOut`.
|
||||
// RealToComplex switches the provided ciphertext ctIn from the conjugate invariant domain to the
|
||||
// standard domain and writes the result into opOut.
|
||||
// Given ctInCI = enc(real(m)) in Z[X+X^-1]/(X^2N+1) in compressed form (N coefficients), returns
|
||||
// opOutCKKS = enc(real(m) + imag(0)) in Z[X]/(X^2N+1).
|
||||
// Requires the ring degree of opOut to be twice the ring degree of ctIn.
|
||||
// The security is changed from Z[X]/(X^N+1) to Z[X]/(X^2N+1).
|
||||
// The method will return an error if the DomainSwitcher was not initialized with a the appropriate EvaluationKeys.
|
||||
// The method will return an error if the [DomainSwitcher] was not initialized with a the appropriate EvaluationKeys.
|
||||
func (switcher DomainSwitcher) RealToComplex(eval *Evaluator, ctIn, opOut *rlwe.Ciphertext) (err error) {
|
||||
|
||||
evalRLWE := eval.Evaluator
|
||||
|
||||
@@ -6,15 +6,15 @@ import (
|
||||
"github.com/tuneinsight/lattigo/v5/core/rlwe"
|
||||
)
|
||||
|
||||
// NewPlaintext allocates a new rlwe.Plaintext.
|
||||
// NewPlaintext allocates a new [rlwe.Plaintext].
|
||||
//
|
||||
// inputs:
|
||||
// - params: an rlwe.ParameterProvider interface
|
||||
// - params: an [rlwe.ParameterProvider] interface
|
||||
// - level: the level of the plaintext
|
||||
//
|
||||
// output: a newly allocated rlwe.Plaintext at the specified level.
|
||||
// output: a newly allocated [rlwe.Plaintext] at the specified level.
|
||||
//
|
||||
// Note: the user can update the field `MetaData` to set a specific scaling factor,
|
||||
// Note: the user can update the field MetaData to set a specific scaling factor,
|
||||
// plaintext dimensions (if applicable) or encoding domain, before encoding values
|
||||
// on the created plaintext.
|
||||
func NewPlaintext(params Parameters, level int) (pt *rlwe.Plaintext) {
|
||||
@@ -25,14 +25,14 @@ func NewPlaintext(params Parameters, level int) (pt *rlwe.Plaintext) {
|
||||
return
|
||||
}
|
||||
|
||||
// NewCiphertext allocates a new rlwe.Ciphertext.
|
||||
// NewCiphertext allocates a new [rlwe.Ciphertext].
|
||||
//
|
||||
// inputs:
|
||||
// - params: an rlwe.ParameterProvider interface
|
||||
// - params: an [rlwe.ParameterProvider] interface
|
||||
// - degree: the degree of the ciphertext
|
||||
// - level: the level of the Ciphertext
|
||||
//
|
||||
// output: a newly allocated rlwe.Ciphertext of the specified degree and level.
|
||||
// output: a newly allocated [rlwe.Ciphertext] of the specified degree and level.
|
||||
func NewCiphertext(params Parameters, degree, level int) (ct *rlwe.Ciphertext) {
|
||||
ct = rlwe.NewCiphertext(params, degree, level)
|
||||
ct.IsBatched = true
|
||||
@@ -41,34 +41,34 @@ func NewCiphertext(params Parameters, degree, level int) (ct *rlwe.Ciphertext) {
|
||||
return
|
||||
}
|
||||
|
||||
// NewEncryptor instantiates a new rlwe.Encryptor.
|
||||
// NewEncryptor instantiates a new [rlwe.Encryptor].
|
||||
//
|
||||
// inputs:
|
||||
// - params: an rlwe.ParameterProvider interface
|
||||
// - key: *rlwe.SecretKey or *rlwe.PublicKey
|
||||
// - params: an [rlwe.ParameterProvider] interface
|
||||
// - key: *[rlwe.SecretKey] or *[rlwe.PublicKey]
|
||||
//
|
||||
// output: an rlwe.Encryptor instantiated with the provided key.
|
||||
// output: an [rlwe.Encryptor] instantiated with the provided key.
|
||||
func NewEncryptor(params Parameters, key rlwe.EncryptionKey) *rlwe.Encryptor {
|
||||
return rlwe.NewEncryptor(params, key)
|
||||
}
|
||||
|
||||
// NewDecryptor instantiates a new rlwe.Decryptor.
|
||||
// NewDecryptor instantiates a new [rlwe.Decryptor].
|
||||
//
|
||||
// inputs:
|
||||
// - params: an rlwe.ParameterProvider interface
|
||||
// - key: *rlwe.SecretKey
|
||||
// - params: an [rlwe.ParameterProvider] interface
|
||||
// - key: *[rlwe.SecretKey]
|
||||
//
|
||||
// output: an rlwe.Decryptor instantiated with the provided key.
|
||||
// output: an [rlwe.Decryptor] instantiated with the provided key.
|
||||
func NewDecryptor(params Parameters, key *rlwe.SecretKey) *rlwe.Decryptor {
|
||||
return rlwe.NewDecryptor(params, key)
|
||||
}
|
||||
|
||||
// NewKeyGenerator instantiates a new rlwe.KeyGenerator.
|
||||
// NewKeyGenerator instantiates a new [rlwe.KeyGenerator].
|
||||
//
|
||||
// inputs:
|
||||
// - params: an rlwe.ParameterProvider interface
|
||||
// - params: an [rlwe.ParameterProvider] interface
|
||||
//
|
||||
// output: an rlwe.KeyGenerator.
|
||||
// output: an [rlwe.KeyGenerator].
|
||||
func NewKeyGenerator(params Parameters) *rlwe.KeyGenerator {
|
||||
return rlwe.NewKeyGenerator(params)
|
||||
}
|
||||
|
||||
@@ -28,17 +28,17 @@ type FloatSlice interface {
|
||||
const GaloisGen uint64 = ring.GaloisGen
|
||||
|
||||
// Encoder is a type that implements the encoding and decoding interface for the CKKS scheme. It provides methods to encode/decode
|
||||
// []complex128/[]*bignum.Complex and []float64/[]*big.Float types into/from Plaintext types.
|
||||
// []complex128/[]*[bignum.Complex] and []float64/[]*[big.Float] types into/from Plaintext types.
|
||||
//
|
||||
// Two different encodings domains are provided:
|
||||
//
|
||||
// - Coefficients: The coefficients are directly embedded on the plaintext. This encoding only allows to encode []float64/[]*big.Float slices,
|
||||
// - Coefficients: The coefficients are directly embedded on the plaintext. This encoding only allows to encode []float64/[]*[big.Float] slices,
|
||||
// but of size up to N (N being the ring degree) and does not preserve the point-wise multiplication. A ciphertext multiplication will result
|
||||
// in a negacyclic polynomial convolution in the plaintext domain. This encoding does not provide native slot cyclic rotation.
|
||||
// Other operations, like addition or constant multiplication, behave as usual.
|
||||
//
|
||||
// - Slots: The coefficients are first subjected to a special Fourier transform before being embedded in the plaintext by using Coeffs encoding.
|
||||
// This encoding can embed []complex128/[]*bignum.Complex and []float64/[]*big.Float slices of size at most N/2 (N being the ring degree) and
|
||||
// This encoding can embed []complex128/[]*[bignum.Complex] and []float64/[]*[big.Float] slices of size at most N/2 (N being the ring degree) and
|
||||
// leverages the convolution property of the DFT to preserve point-wise complex multiplication in the plaintext domain, i.e. a ciphertext
|
||||
// multiplication will result in an element-wise multiplication in the plaintext domain. It also enables cyclic rotations on plaintext slots.
|
||||
// Other operations, like constant multiplication, behave as usual. It is considered the default encoding method for CKKS.
|
||||
@@ -65,10 +65,10 @@ type Encoder struct {
|
||||
buffCmplx interface{}
|
||||
}
|
||||
|
||||
// NewEncoder creates a new Encoder from the target parameters.
|
||||
// NewEncoder creates a new [Encoder] from the target parameters.
|
||||
// Optional field `precision` can be given. If precision is empty
|
||||
// or <= 53, then float64 and complex128 types will be used to
|
||||
// perform the encoding. Else *big.Float and *bignum.Complex will be used.
|
||||
// perform the encoding. Else *[big.Float] and *[bignum.Complex] will be used.
|
||||
func NewEncoder(parameters Parameters, precision ...uint) (ecd *Encoder) {
|
||||
|
||||
m := int(parameters.RingQ().NthRoot())
|
||||
@@ -119,7 +119,7 @@ func NewEncoder(parameters Parameters, precision ...uint) (ecd *Encoder) {
|
||||
}
|
||||
|
||||
// Prec returns the precision in bits used by the target Encoder.
|
||||
// A precision <= 53 will use float64, else *big.Float.
|
||||
// A precision <= 53 will use float64, else *[big.Float].
|
||||
func (ecd Encoder) Prec() uint {
|
||||
return ecd.prec
|
||||
}
|
||||
@@ -128,11 +128,11 @@ func (ecd Encoder) GetRLWEParameters() rlwe.Parameters {
|
||||
return ecd.parameters.Parameters
|
||||
}
|
||||
|
||||
// Encode encodes a FloatSlice on the target plaintext.
|
||||
// Encode encodes a [FloatSlice] on the target plaintext.
|
||||
// Encoding is done at the level and scale of the plaintext.
|
||||
// Encoding domain is done according to the metadata of the plaintext.
|
||||
// User must ensure that 1 <= len(values) <= 2^pt.LogMaxDimensions < 2^logN.
|
||||
// The imaginary part will be discarded if ringType == ring.ConjugateInvariant.
|
||||
// The imaginary part will be discarded if ringType == [ring.ConjugateInvariant].
|
||||
func (ecd Encoder) Encode(values FloatSlice, pt *rlwe.Plaintext) (err error) {
|
||||
|
||||
if pt.IsBatched {
|
||||
@@ -167,23 +167,23 @@ func (ecd Encoder) Encode(values FloatSlice, pt *rlwe.Plaintext) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Decode decodes the input plaintext on a new FloatSlice.
|
||||
// Decode decodes the input plaintext on a new [FloatSlice].
|
||||
func (ecd Encoder) Decode(pt *rlwe.Plaintext, values FloatSlice) (err error) {
|
||||
return ecd.DecodePublic(pt, values, 0)
|
||||
}
|
||||
|
||||
// DecodePublic decodes the input plaintext on a FloatSlice.
|
||||
// DecodePublic decodes the input plaintext on a [FloatSlice].
|
||||
// It adds, before the decoding step (i.e. in the Ring) noise that follows the given distribution parameters.
|
||||
// If the underlying ringType is ConjugateInvariant, the imaginary part (and its related error) are zero.
|
||||
// If the underlying ringType is [ring.ConjugateInvariant], the imaginary part (and its related error) are zero.
|
||||
func (ecd Encoder) DecodePublic(pt *rlwe.Plaintext, values FloatSlice, logprec float64) (err error) {
|
||||
return ecd.decodePublic(pt, values, logprec)
|
||||
}
|
||||
|
||||
// Embed is a generic method to encode a FloatSlice on the target polyOut.
|
||||
// Embed is a generic method to encode a [FloatSlice] on the target polyOut.
|
||||
// This method it as the core of the slot encoding.
|
||||
// Values are encoded according to the provided metadata.
|
||||
// Accepted polyOut.(type) are ringqp.Poly and ring.Poly.
|
||||
// The imaginary part will be discarded if ringType == ring.ConjugateInvariant.
|
||||
// Accepted polyOut.(type) are [ringqp.Poly] and [ring.Poly].
|
||||
// The imaginary part will be discarded if ringType == [ring.ConjugateInvariant].
|
||||
func (ecd Encoder) Embed(values FloatSlice, metadata *rlwe.MetaData, polyOut interface{}) (err error) {
|
||||
if ecd.prec <= 53 {
|
||||
return ecd.embedDouble(values, metadata, polyOut)
|
||||
@@ -194,7 +194,7 @@ func (ecd Encoder) Embed(values FloatSlice, metadata *rlwe.MetaData, polyOut int
|
||||
|
||||
// embedDouble encode a FloatSlice on polyOut using FFT with complex128 arithmetic.
|
||||
// Values are encoded according to the provided metadata.
|
||||
// Accepted polyOut.(type) are ringqp.Poly and ring.Poly.
|
||||
// Accepted polyOut.(type) are [ringqp.Poly] and [ring.Poly].
|
||||
func (ecd Encoder) embedDouble(values FloatSlice, metadata *rlwe.MetaData, polyOut interface{}) (err error) {
|
||||
|
||||
if maxLogCols := ecd.parameters.LogMaxDimensions().Cols; metadata.LogDimensions.Cols < 0 || metadata.LogDimensions.Cols > maxLogCols {
|
||||
@@ -315,7 +315,7 @@ func (ecd Encoder) embedDouble(values FloatSlice, metadata *rlwe.MetaData, polyO
|
||||
|
||||
// embedArbitrary encode a FloatSlice on polyOut using FFT with *bignum.Complex arithmetic.
|
||||
// Values are encoded according to the provided metadata.
|
||||
// Accepted polyOut.(type) are ringqp.Poly and ring.Poly.
|
||||
// Accepted polyOut.(type) are [ringqp.Poly] and [ring.Poly].
|
||||
func (ecd Encoder) embedArbitrary(values FloatSlice, metadata *rlwe.MetaData, polyOut interface{}) (err error) {
|
||||
|
||||
if maxLogCols := ecd.parameters.LogMaxDimensions().Cols; metadata.LogDimensions.Cols < 0 || metadata.LogDimensions.Cols > maxLogCols {
|
||||
@@ -447,7 +447,7 @@ func (ecd Encoder) embedArbitrary(values FloatSlice, metadata *rlwe.MetaData, po
|
||||
return
|
||||
}
|
||||
|
||||
// plaintextToComplex maps a CRT polynomial to a complex valued FloatSlice.
|
||||
// plaintextToComplex maps a CRT polynomial to a complex valued [FloatSlice].
|
||||
func (ecd Encoder) plaintextToComplex(level int, scale rlwe.Scale, logSlots int, p ring.Poly, values FloatSlice) (err error) {
|
||||
|
||||
isreal := ecd.parameters.RingType() == ring.ConjugateInvariant
|
||||
@@ -457,7 +457,7 @@ func (ecd Encoder) plaintextToComplex(level int, scale rlwe.Scale, logSlots int,
|
||||
return polyToComplexCRT(p, ecd.bigintCoeffs, values, scale, logSlots, isreal, ecd.parameters.RingQ().AtLevel(level))
|
||||
}
|
||||
|
||||
// plaintextToFloat maps a CRT polynomial to a real valued FloatSlice.
|
||||
// plaintextToFloat maps a CRT polynomial to a real valued [FloatSlice].
|
||||
func (ecd Encoder) plaintextToFloat(level int, scale rlwe.Scale, logSlots int, p ring.Poly, values FloatSlice) (err error) {
|
||||
if level == 0 {
|
||||
return ecd.polyToFloatNoCRT(p.Coeffs[0], values, scale, logSlots, ecd.parameters.RingQ().AtLevel(level))
|
||||
@@ -465,7 +465,7 @@ func (ecd Encoder) plaintextToFloat(level int, scale rlwe.Scale, logSlots int, p
|
||||
return ecd.polyToFloatCRT(p, values, scale, logSlots, ecd.parameters.RingQ().AtLevel(level))
|
||||
}
|
||||
|
||||
// decodePublic decode a plaintext to a FloatSlice.
|
||||
// decodePublic decode a plaintext to a [FloatSlice].
|
||||
// The method will add a flooding noise before the decoding process following the defined distribution if it is not nil.
|
||||
func (ecd Encoder) decodePublic(pt *rlwe.Plaintext, values FloatSlice, logprec float64) (err error) {
|
||||
|
||||
@@ -728,7 +728,7 @@ func (ecd Encoder) decodePublic(pt *rlwe.Plaintext, values FloatSlice, logprec f
|
||||
return
|
||||
}
|
||||
|
||||
// IFFT evaluates the special 2^{LogN}-th encoding discrete Fourier transform on FloatSlice.
|
||||
// IFFT evaluates the special 2^{LogN}-th encoding discrete Fourier transform on [FloatSlice].
|
||||
func (ecd Encoder) IFFT(values FloatSlice, logN int) (err error) {
|
||||
switch values := values.(type) {
|
||||
case []complex128:
|
||||
@@ -757,7 +757,7 @@ func (ecd Encoder) IFFT(values FloatSlice, logN int) (err error) {
|
||||
|
||||
}
|
||||
|
||||
// FFT evaluates the special 2^{LogN}-th decoding discrete Fourier transform on FloatSlice.
|
||||
// FFT evaluates the special 2^{LogN}-th decoding discrete Fourier transform on [FloatSlice].
|
||||
func (ecd Encoder) FFT(values FloatSlice, logN int) (err error) {
|
||||
switch values := values.(type) {
|
||||
case []complex128:
|
||||
@@ -786,7 +786,7 @@ func (ecd Encoder) FFT(values FloatSlice, logN int) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// polyToComplexNoCRT decodes a single-level CRT poly on a complex valued FloatSlice.
|
||||
// polyToComplexNoCRT decodes a single-level CRT poly on a complex valued [FloatSlice].
|
||||
func polyToComplexNoCRT(coeffs []uint64, values FloatSlice, scale rlwe.Scale, logSlots int, isreal bool, ringQ *ring.Ring) (err error) {
|
||||
|
||||
slots := 1 << logSlots
|
||||
@@ -882,7 +882,7 @@ func polyToComplexNoCRT(coeffs []uint64, values FloatSlice, scale rlwe.Scale, lo
|
||||
return
|
||||
}
|
||||
|
||||
// polyToComplexNoCRT decodes a multiple-level CRT poly on a complex valued FloatSlice.
|
||||
// polyToComplexNoCRT decodes a multiple-level CRT poly on a complex valued [FloatSlice].
|
||||
func polyToComplexCRT(poly ring.Poly, bigintCoeffs []*big.Int, values FloatSlice, scale rlwe.Scale, logSlots int, isreal bool, ringQ *ring.Ring) (err error) {
|
||||
|
||||
maxCols := int(ringQ.NthRoot() >> 2)
|
||||
@@ -990,7 +990,7 @@ func polyToComplexCRT(poly ring.Poly, bigintCoeffs []*big.Int, values FloatSlice
|
||||
return
|
||||
}
|
||||
|
||||
// polyToFloatCRT decodes a multiple-level CRT poly on a real valued FloatSlice.
|
||||
// polyToFloatCRT decodes a multiple-level CRT poly on a real valued [FloatSlice].
|
||||
func (ecd *Encoder) polyToFloatCRT(p ring.Poly, values FloatSlice, scale rlwe.Scale, logSlots int, r *ring.Ring) (err error) {
|
||||
|
||||
var slots int
|
||||
@@ -1073,7 +1073,7 @@ func (ecd *Encoder) polyToFloatCRT(p ring.Poly, values FloatSlice, scale rlwe.Sc
|
||||
return
|
||||
}
|
||||
|
||||
// polyToFloatNoCRT decodes a single-level CRT poly on a real valued FloatSlice.
|
||||
// polyToFloatNoCRT decodes a single-level CRT poly on a real valued [FloatSlice].
|
||||
func (ecd *Encoder) polyToFloatNoCRT(coeffs []uint64, values FloatSlice, scale rlwe.Scale, logSlots int, r *ring.Ring) (err error) {
|
||||
|
||||
Q := r.SubRings[0].Modulus
|
||||
|
||||
@@ -19,7 +19,7 @@ type Evaluator struct {
|
||||
*rlwe.Evaluator
|
||||
}
|
||||
|
||||
// NewEvaluator creates a new Evaluator, that can be used to do homomorphic
|
||||
// NewEvaluator creates a new [Evaluator], that can be used to do homomorphic
|
||||
// operations on the Ciphertexts and/or Plaintexts. It stores a memory buffer
|
||||
// and Ciphertexts that will be used for intermediate values.
|
||||
func NewEvaluator(parameters Parameters, evk rlwe.EvaluationKeySet) *Evaluator {
|
||||
@@ -30,12 +30,12 @@ func NewEvaluator(parameters Parameters, evk rlwe.EvaluationKeySet) *Evaluator {
|
||||
}
|
||||
}
|
||||
|
||||
// GetParameters returns a pointer to the underlying ckks.Parameters.
|
||||
// GetParameters returns a pointer to the underlying [ckks.Parameters].
|
||||
func (eval Evaluator) GetParameters() *Parameters {
|
||||
return &eval.Encoder.parameters
|
||||
}
|
||||
|
||||
// GetRLWEParameters returns a pointer to the underlying rlwe.Parameters.
|
||||
// GetRLWEParameters returns a pointer to the underlying [rlwe.Parameters].
|
||||
func (eval Evaluator) GetRLWEParameters() *rlwe.Parameters {
|
||||
return &eval.Encoder.parameters.Parameters
|
||||
}
|
||||
@@ -58,9 +58,9 @@ func newEvaluatorBuffers(parameters Parameters) *evaluatorBuffers {
|
||||
|
||||
// Add adds op1 to op0 and returns the result in opOut.
|
||||
// The following types are accepted for op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - complex128, float64, int, int64, uint, uint64, *big.Int, *big.Float, *bignum.Complex
|
||||
// - []complex128, []float64, []*big.Float or []*bignum.Complex of size at most params.MaxSlots()
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - complex128, float64, int, int64, uint, uint64, *[big.Int], *[big.Float], *[bignum.Complex]
|
||||
// - []complex128, []float64, []*[big.Float] or []*[bignum.Complex] of size at most params.MaxSlots()
|
||||
//
|
||||
// Passing an invalid type will return an error.
|
||||
func (eval Evaluator) Add(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error) {
|
||||
@@ -136,9 +136,9 @@ func (eval Evaluator) Add(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ci
|
||||
|
||||
// AddNew adds op1 to op0 and returns the result in a newly created element opOut.
|
||||
// The following types are accepted for op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - complex128, float64, int, int64, uint, uint64, *big.Int, *big.Float, *bignum.Complex
|
||||
// - []complex128, []float64, []*big.Float or []*bignum.Complex of size at most params.MaxSlots()
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - complex128, float64, int, int64, uint, uint64, *[big.Int], *[big.Float], *[bignum.Complex]
|
||||
// - []complex128, []float64, []*[big.Float] or []*[bignum.Complex] of size at most params.MaxSlots()
|
||||
//
|
||||
// Passing an invalid type will return an error.
|
||||
func (eval Evaluator) AddNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut *rlwe.Ciphertext, err error) {
|
||||
@@ -148,9 +148,9 @@ func (eval Evaluator) AddNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut *rlw
|
||||
|
||||
// Sub subtracts op1 from op0 and returns the result in opOut.
|
||||
// The following types are accepted for op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - complex128, float64, int, int64, uint, uint64, *big.Int, *big.Float, *bignum.Complex
|
||||
// - []complex128, []float64, []*big.Float or []*bignum.Complex of size at most params.MaxSlots()
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - complex128, float64, int, int64, uint, uint64, *[big.Int], *[big.Float], *[bignum.Complex]
|
||||
// - []complex128, []float64, []*[big.Float] or []*[bignum.Complex] of size at most params.MaxSlots()
|
||||
//
|
||||
// Passing an invalid type will return an error.
|
||||
func (eval Evaluator) Sub(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error) {
|
||||
@@ -233,9 +233,9 @@ func (eval Evaluator) Sub(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ci
|
||||
|
||||
// SubNew subtracts op1 from op0 and returns the result in a newly created element opOut.
|
||||
// The following types are accepted for op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - complex128, float64, int, int64, uint, uint64, *big.Int, *big.Float, *bignum.Complex
|
||||
// - []complex128, []float64, []*big.Float or []*bignum.Complex of size at most params.MaxSlots()
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - complex128, float64, int, int64, uint, uint64, *[big.Int], *[big.Float], *[bignum.Complex]
|
||||
// - []complex128, []float64, []*[big.Float] or []*[bignum.Complex] of size at most params.MaxSlots()
|
||||
//
|
||||
// Passing an invalid type will return an error.
|
||||
func (eval Evaluator) SubNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut *rlwe.Ciphertext, err error) {
|
||||
@@ -604,9 +604,9 @@ func (eval Evaluator) RescaleTo(op0 *rlwe.Ciphertext, minScale rlwe.Scale, opOut
|
||||
// MulNew multiplies op0 with op1 without relinearization and returns the result in a newly created element opOut.
|
||||
//
|
||||
// op1.(type) can be
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - complex128, float64, int, int64, uint, uint64, *big.Int, *big.Float, *bignum.Complex
|
||||
// - []complex128, []float64, []*big.Float or []*bignum.Complex of size at most params.MaxSlots()
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - complex128, float64, int, int64, uint, uint64, *[big.Int], *[big.Float], *[bignum.Complex]
|
||||
// - []complex128, []float64, []*[big.Float] or []*[bignum.Complex] of size at most params.MaxSlots()
|
||||
//
|
||||
// If op1.(type) == rlwe.ElementInterface[ring.Poly]:
|
||||
// - The procedure will return an error if either op0.Degree or op1.Degree > 1.
|
||||
@@ -618,13 +618,13 @@ func (eval Evaluator) MulNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut *rlw
|
||||
// Mul multiplies op0 with op1 without relinearization and returns the result in opOut.
|
||||
//
|
||||
// The following types are accepted for op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - complex128, float64, int, int64, uint, uint64, *big.Int, *big.Float, *bignum.Complex
|
||||
// - []complex128, []float64, []*big.Float or []*bignum.Complex of size at most params.MaxSlots()
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - complex128, float64, int, int64, uint, uint64, *[big.Int], *[big.Float], *[bignum.Complex]
|
||||
// - []complex128, []float64, []*[big.Float] or []*[bignum.Complex] of size at most params.MaxSlots()
|
||||
//
|
||||
// Passing an invalid type will return an error.
|
||||
//
|
||||
// If op1.(type) == rlwe.ElementInterface[ring.Poly]:
|
||||
// If op1.(type) == [rlwe.ElementInterface][[ring.Poly]]:
|
||||
// - The procedure will return an error if either op0 or op1 are have a degree higher than 1.
|
||||
// - The procedure will return an error if opOut.Degree != op0.Degree + op1.Degree.
|
||||
func (eval Evaluator) Mul(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ciphertext) (err error) {
|
||||
@@ -730,9 +730,9 @@ func (eval Evaluator) Mul(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *rlwe.Ci
|
||||
// MulRelinNew multiplies op0 with op1 with relinearization and returns the result in a newly created element.
|
||||
//
|
||||
// The following types are accepted for op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - complex128, float64, int, int64, uint, uint64, *big.Int, *big.Float, *bignum.Complex
|
||||
// - []complex128, []float64, []*big.Float or []*bignum.Complex of size at most params.MaxSlots()
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - complex128, float64, int, int64, uint, uint64, *[big.Int], *[big.Float], *[bignum.Complex]
|
||||
// - []complex128, []float64, []*[big.Float] or []*[bignum.Complex] of size at most params.MaxSlots()
|
||||
//
|
||||
// Passing an invalid type will return an error.
|
||||
//
|
||||
@@ -752,9 +752,9 @@ func (eval Evaluator) MulRelinNew(op0 *rlwe.Ciphertext, op1 rlwe.Operand) (opOut
|
||||
// MulRelin multiplies op0 with op1 with relinearization and returns the result in opOut.
|
||||
//
|
||||
// The following types are accepted for op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - complex128, float64, int, int64, uint, uint64, *big.Int, *big.Float, *bignum.Complex
|
||||
// - []complex128, []float64, []*big.Float or []*bignum.Complex of size at most params.MaxSlots()
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - complex128, float64, int, int64, uint, uint64, *[big.Int], *[big.Float], *[bignum.Complex]
|
||||
// - []complex128, []float64, []*[big.Float] or []*[bignum.Complex] of size at most params.MaxSlots()
|
||||
//
|
||||
// Passing an invalid type will return an error.
|
||||
//
|
||||
@@ -884,12 +884,12 @@ func (eval Evaluator) mulRelin(op0 *rlwe.Ciphertext, op1 *rlwe.Element[ring.Poly
|
||||
//
|
||||
// The following types are accepted for op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - complex128, float64, int, int64, uint, uint64, *big.Int, *big.Float, *bignum.Complex
|
||||
// - []complex128, []float64, []*big.Float or []*bignum.Complex of size at most params.MaxSlots()
|
||||
// - complex128, float64, int, int64, uint, uint64, *[big.Int], *[big.Float], *[bignum.Complex]
|
||||
// - []complex128, []float64, []*[big.Float] or []*[bignum.Complex] of size at most params.MaxSlots()
|
||||
//
|
||||
// Passing an invalid type will return an error.
|
||||
//
|
||||
// If op1.(type) is complex128, float64, int, int64, uint64. *big.Float, *big.Int or *ring.Complex:
|
||||
// If op1.(type) is complex128, float64, int, int64, uint64. *[big.Float], *[big.Int] or *[ring.Complex]:
|
||||
//
|
||||
// This function will not modify op0 but will multiply opOut by Q[min(op0.Level(), opOut.Level())] if:
|
||||
// - op0.Scale == opOut.Scale
|
||||
@@ -901,13 +901,13 @@ func (eval Evaluator) mulRelin(op0 *rlwe.Ciphertext, op1 *rlwe.Element[ring.Poly
|
||||
// To correctly use this function, make sure that either op0.Scale == opOut.Scale or
|
||||
// opOut.Scale = op0.Scale * Q[min(op0.Level(), opOut.Level())].
|
||||
//
|
||||
// If op1.(type) is []complex128, []float64, []*big.Float or []*bignum.Complex:
|
||||
// If op1.(type) is []complex128, []float64, []*[big.Float] or []*[bignum.Complex]:
|
||||
// - If opOut.Scale == op0.Scale, op1 will be encoded and scaled by Q[min(op0.Level(), opOut.Level())]
|
||||
// - If opOut.Scale > op0.Scale, op1 will be encoded ans scaled by opOut.Scale/op1.Scale.
|
||||
//
|
||||
// Then the method will recurse with op1 given as rlwe.ElementInterface[ring.Poly].
|
||||
// Then the method will recurse with op1 given as [rlwe.ElementInterface][[ring.Poly]].
|
||||
//
|
||||
// If op1.(type) is rlwe.ElementInterface[ring.Poly], the multiplication is carried outwithout relinearization and:
|
||||
// If op1.(type) is [rlwe.ElementInterface][[ring.Poly]], the multiplication is carried outwithout relinearization and:
|
||||
//
|
||||
// This function will return an error if op0.Scale > opOut.Scale and user must ensure that opOut.Scale <= op0.Scale * op1.Scale.
|
||||
// If opOut.Scale < op0.Scale * op1.Scale, then scales up opOut before adding the result.
|
||||
@@ -1048,9 +1048,9 @@ func (eval Evaluator) MulThenAdd(op0 *rlwe.Ciphertext, op1 rlwe.Operand, opOut *
|
||||
// MulRelinThenAdd multiplies op0 with op1 with relinearization and adds the result on opOut.
|
||||
//
|
||||
// The following types are accepted for op1:
|
||||
// - rlwe.ElementInterface[ring.Poly]
|
||||
// - complex128, float64, int, int64, uint, uint64, *big.Int, *big.Float, *bignum.Complex
|
||||
// - []complex128, []float64, []*big.Float or []*bignum.Complex of size at most params.MaxSlots()
|
||||
// - [rlwe.ElementInterface][[ring.Poly]]
|
||||
// - complex128, float64, int, int64, uint, uint64, *[big.Int], *[big.Float], *[bignum.Complex]
|
||||
// - []complex128, []float64, []*[big.Float] or []*[bignum.Complex] of size at most params.MaxSlots()
|
||||
//
|
||||
// Passing an invalid type will return an error.
|
||||
//
|
||||
@@ -1229,7 +1229,7 @@ func (eval Evaluator) Conjugate(op0 *rlwe.Ciphertext, opOut *rlwe.Ciphertext) (e
|
||||
}
|
||||
|
||||
// RotateHoistedNew takes an input Ciphertext and a list of rotations and returns a map of Ciphertext, where each element of the map is the input Ciphertext
|
||||
// rotation by one element of the list. It is much faster than sequential calls to Rotate.
|
||||
// rotation by one element of the list. It is much faster than sequential calls to [Evaluator.Rotate].
|
||||
func (eval Evaluator) RotateHoistedNew(ctIn *rlwe.Ciphertext, rotations []int) (opOut map[int]*rlwe.Ciphertext, err error) {
|
||||
opOut = make(map[int]*rlwe.Ciphertext)
|
||||
for _, i := range rotations {
|
||||
@@ -1241,7 +1241,7 @@ func (eval Evaluator) RotateHoistedNew(ctIn *rlwe.Ciphertext, rotations []int) (
|
||||
|
||||
// RotateHoisted takes an input Ciphertext and a list of rotations and populates a map of pre-allocated Ciphertexts,
|
||||
// where each element of the map is the input Ciphertext rotation by one element of the list.
|
||||
// It is much faster than sequential calls to Rotate.
|
||||
// It is much faster than sequential calls to [Evaluator.Rotate].
|
||||
func (eval Evaluator) RotateHoisted(ctIn *rlwe.Ciphertext, rotations []int, opOut map[int]*rlwe.Ciphertext) (err error) {
|
||||
levelQ := ctIn.Level()
|
||||
eval.DecomposeNTT(levelQ, eval.GetParameters().MaxLevelP(), eval.GetParameters().PCount(), ctIn.Value[1], ctIn.IsNTT, eval.BuffDecompQP)
|
||||
|
||||
@@ -16,11 +16,11 @@ func (eval Evaluator) TraceNew(ctIn *rlwe.Ciphertext, logSlots int) (opOut *rlwe
|
||||
}
|
||||
|
||||
// Average returns the average of vectors of batchSize elements.
|
||||
// The operation assumes that ctIn encrypts SlotCount/'batchSize' sub-vectors of size 'batchSize'.
|
||||
// The operation assumes that ctIn encrypts SlotCount/batchSize sub-vectors of size batchSize.
|
||||
// It then replaces all values of those sub-vectors by the component-wise average between all the sub-vectors.
|
||||
// Example for batchSize=4 and slots=8: [{a, b, c, d}, {e, f, g, h}] -> [0.5*{a+e, b+f, c+g, d+h}, 0.5*{a+e, b+f, c+g, d+h}]
|
||||
// Operation requires log2(SlotCout/'batchSize') rotations.
|
||||
// Required rotation keys can be generated with 'RotationsForInnerSumLog(batchSize, SlotCount/batchSize)”
|
||||
// Operation requires log2(SlotCout/batchSize) rotations.
|
||||
// Required rotation keys can be generated with RotationsForInnerSumLog(batchSize, SlotCount/batchSize).
|
||||
func (eval Evaluator) Average(ctIn *rlwe.Ciphertext, logBatchSize int, opOut *rlwe.Ciphertext) (err error) {
|
||||
|
||||
if ctIn.Degree() != 1 || opOut.Degree() != 1 {
|
||||
|
||||
@@ -16,8 +16,8 @@ import (
|
||||
// This also sets how many primes are consumed per rescaling.
|
||||
//
|
||||
// There are currently two modes supported:
|
||||
// - PREC64 (one 64 bit word)
|
||||
// - PREC128 (two 64 bit words)
|
||||
// - PREC64 (one 64-bit word)
|
||||
// - PREC128 (two 64-bit words)
|
||||
//
|
||||
// PREC64 is the default mode and supports reference plaintext scaling
|
||||
// factors of up to 2^{64}, while PREC128 scaling factors of up to 2^{128}.
|
||||
@@ -34,7 +34,7 @@ const (
|
||||
|
||||
// ParametersLiteral is a literal representation of CKKS parameters. It has public
|
||||
// fields and is used to express unchecked user-defined parameters literally into
|
||||
// Go programs. The NewParametersFromLiteral function is used to generate the actual
|
||||
// Go programs. The [NewParametersFromLiteral] function is used to generate the actual
|
||||
// checked parameters from the literal representation.
|
||||
//
|
||||
// Users must set the polynomial degree (in log_2, LogN) and the coefficient modulus, by either setting
|
||||
@@ -57,7 +57,7 @@ type ParametersLiteral struct {
|
||||
LogDefaultScale int
|
||||
}
|
||||
|
||||
// GetRLWEParametersLiteral returns the rlwe.ParametersLiteral from the target ckks.ParameterLiteral.
|
||||
// GetRLWEParametersLiteral returns the [rlwe.ParametersLiteral] from the target [ckks.ParameterLiteral].
|
||||
func (p ParametersLiteral) GetRLWEParametersLiteral() rlwe.ParametersLiteral {
|
||||
return rlwe.ParametersLiteral{
|
||||
LogN: p.LogN,
|
||||
@@ -75,19 +75,19 @@ func (p ParametersLiteral) GetRLWEParametersLiteral() rlwe.ParametersLiteral {
|
||||
}
|
||||
|
||||
// Parameters represents a parameter set for the CKKS cryptosystem. Its fields are private and
|
||||
// immutable. See ParametersLiteral for user-specified parameters.
|
||||
// immutable. See [ParametersLiteral] for user-specified parameters.
|
||||
type Parameters struct {
|
||||
rlwe.Parameters
|
||||
precisionMode PrecisionMode
|
||||
}
|
||||
|
||||
// NewParametersFromLiteral instantiate a set of CKKS parameters from a ParametersLiteral specification.
|
||||
// It returns the empty parameters Parameters{} and a non-nil error if the specified parameters are invalid.
|
||||
// NewParametersFromLiteral instantiate a set of CKKS parameters from a [ParametersLiteral] specification.
|
||||
// It returns the empty parameters [Parameters]{} and a non-nil error if the specified parameters are invalid.
|
||||
//
|
||||
// If the `LogSlots` field is left unset, its value is set to `LogN-1` for the Standard ring and to `LogN` for
|
||||
// If the LogSlots field is left unset, its value is set to LogN-1 for the Standard ring and to LogN for
|
||||
// the conjugate-invariant ring.
|
||||
//
|
||||
// See `rlwe.NewParametersFromLiteral` for default values of the other optional fields.
|
||||
// See [rlwe.NewParametersFromLiteral] for default values of the other optional fields.
|
||||
func NewParametersFromLiteral(pl ParametersLiteral) (Parameters, error) {
|
||||
rlweParams, err := rlwe.NewParametersFromLiteral(pl.GetRLWEParametersLiteral())
|
||||
if err != nil {
|
||||
@@ -119,7 +119,7 @@ func (p Parameters) StandardParameters() (pckks Parameters, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// ParametersLiteral returns the ParametersLiteral of the target Parameters.
|
||||
// ParametersLiteral returns the [ParametersLiteral] of the target [Parameters].
|
||||
func (p Parameters) ParametersLiteral() (pLit ParametersLiteral) {
|
||||
return ParametersLiteral{
|
||||
LogN: p.LogN(),
|
||||
@@ -169,14 +169,14 @@ func (p Parameters) LogMaxDimensions() ring.Dimensions {
|
||||
}
|
||||
}
|
||||
|
||||
// MaxSlots returns the total number of entries (`slots`) that a plaintext can store.
|
||||
// MaxSlots returns the total number of entries (slots) that a plaintext can store.
|
||||
// This value is obtained by multiplying all dimensions from MaxDimensions.
|
||||
func (p Parameters) MaxSlots() int {
|
||||
dims := p.MaxDimensions()
|
||||
return dims.Rows * dims.Cols
|
||||
}
|
||||
|
||||
// LogMaxSlots returns the total number of entries (`slots`) that a plaintext can store.
|
||||
// LogMaxSlots returns the total number of entries (slots) that a plaintext can store.
|
||||
// This value is obtained by summing all log dimensions from LogDimensions.
|
||||
func (p Parameters) LogMaxSlots() int {
|
||||
dims := p.LogMaxDimensions()
|
||||
@@ -202,7 +202,7 @@ func (p Parameters) EncodingPrecision() (prec uint) {
|
||||
}
|
||||
|
||||
// PrecisionMode returns the precision mode of the parameters.
|
||||
// This value can be ckks.PREC64 or ckks.PREC128.
|
||||
// This value can be [ckks.PREC64] or [ckks.PREC128].
|
||||
func (p Parameters) PrecisionMode() PrecisionMode {
|
||||
return p.precisionMode
|
||||
}
|
||||
@@ -231,7 +231,7 @@ func (p Parameters) LogQLvl(level int) int {
|
||||
return tmp.BitLen()
|
||||
}
|
||||
|
||||
// QLvl returns the product of the moduli at the given level as a big.Int
|
||||
// QLvl returns the product of the moduli at the given level as a [big.Int]
|
||||
func (p Parameters) QLvl(level int) *big.Int {
|
||||
tmp := bignum.NewInt(1)
|
||||
for _, qi := range p.Q()[:level+1] {
|
||||
@@ -284,30 +284,30 @@ func (p Parameters) GaloisElementForComplexConjugation() uint64 {
|
||||
}
|
||||
|
||||
// GaloisElementsForInnerSum returns the list of Galois elements necessary to apply the method
|
||||
// `InnerSum` operation with parameters `batch` and `n`.
|
||||
// `InnerSum` operation with parameters batch and n.
|
||||
func (p Parameters) GaloisElementsForInnerSum(batch, n int) []uint64 {
|
||||
return rlwe.GaloisElementsForInnerSum(p, batch, n)
|
||||
}
|
||||
|
||||
// GaloisElementsForReplicate returns the list of Galois elements necessary to perform the
|
||||
// `Replicate` operation with parameters `batch` and `n`.
|
||||
// `Replicate` operation with parameters batch and n.
|
||||
func (p Parameters) GaloisElementsForReplicate(batch, n int) []uint64 {
|
||||
return rlwe.GaloisElementsForReplicate(p, batch, n)
|
||||
}
|
||||
|
||||
// GaloisElementsForTrace returns the list of Galois elements requored for the for the `Trace` operation.
|
||||
// GaloisElementsForTrace returns the list of Galois elements requored for the for the Trace operation.
|
||||
// Trace maps X -> sum((-1)^i * X^{i*n+1}) for 2^{LogN} <= i < N.
|
||||
func (p Parameters) GaloisElementsForTrace(logN int) []uint64 {
|
||||
return rlwe.GaloisElementsForTrace(p, logN)
|
||||
}
|
||||
|
||||
// GaloisElementsForExpand returns the list of Galois elements required
|
||||
// to perform the `Expand` operation with parameter `logN`.
|
||||
// to perform the Expand operation with parameter logN.
|
||||
func (p Parameters) GaloisElementsForExpand(logN int) []uint64 {
|
||||
return rlwe.GaloisElementsForExpand(p, logN)
|
||||
}
|
||||
|
||||
// GaloisElementsForPack returns the list of Galois elements required to perform the `Pack` operation.
|
||||
// GaloisElementsForPack returns the list of Galois elements required to perform the Pack operation.
|
||||
func (p Parameters) GaloisElementsForPack(logN int) []uint64 {
|
||||
return rlwe.GaloisElementsForPack(p, logN)
|
||||
}
|
||||
@@ -328,12 +328,12 @@ func (p *Parameters) UnmarshalBinary(data []byte) (err error) {
|
||||
return p.UnmarshalJSON(data)
|
||||
}
|
||||
|
||||
// MarshalJSON returns a JSON representation of this parameter set. See `Marshal` from the `encoding/json` package.
|
||||
// MarshalJSON returns a JSON representation of this parameter set. See Marshal from the [encoding/json] package.
|
||||
func (p Parameters) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(p.ParametersLiteral())
|
||||
}
|
||||
|
||||
// UnmarshalJSON reads a JSON representation of a parameter set into the receiver Parameter. See `Unmarshal` from the `encoding/json` package.
|
||||
// UnmarshalJSON reads a JSON representation of a parameter set into the receiver Parameter. See Unmarshal from the [encoding/json] package.
|
||||
func (p *Parameters) UnmarshalJSON(data []byte) (err error) {
|
||||
var params ParametersLiteral
|
||||
if err = json.Unmarshal(data, ¶ms); err != nil {
|
||||
|
||||
@@ -55,7 +55,7 @@ func (prec PrecisionStats) String() string {
|
||||
prec.MedianPrecision.Real, prec.MedianPrecision.Imag, prec.MedianPrecision.L2)
|
||||
}
|
||||
|
||||
// GetPrecisionStats generates a PrecisionStats struct from the reference values and the decrypted values
|
||||
// GetPrecisionStats generates a [PrecisionStats] struct from the reference values and the decrypted values
|
||||
// vWant.(type) must be either []complex128 or []float64
|
||||
// element.(type) must be either *Plaintext, *Ciphertext, []complex128 or []float64. If not *Ciphertext, then decryptor can be nil.
|
||||
func GetPrecisionStats(params Parameters, encoder *Encoder, decryptor *rlwe.Decryptor, want, have interface{}, logprec float64, computeDCF bool) (prec PrecisionStats) {
|
||||
|
||||
Reference in New Issue
Block a user