diff --git a/README.md b/README.md index 5a019bde8..75dab8e16 100644 --- a/README.md +++ b/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 diff --git a/core/rgsw/elements.go b/core/rgsw/elements.go index b83fdffb7..a682df831 100644 --- a/core/rgsw/elements.go +++ b/core/rgsw/elements.go @@ -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) diff --git a/core/rgsw/encryptor.go b/core/rgsw/encryptor.go index b926e7398..958c682c4 100644 --- a/core/rgsw/encryptor.go +++ b/core/rgsw/encryptor.go @@ -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 { diff --git a/core/rgsw/evaluator.go b/core/rgsw/evaluator.go index cec20fb5e..7572980c7 100644 --- a/core/rgsw/evaluator.go +++ b/core/rgsw/evaluator.go @@ -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)} diff --git a/core/rgsw/rgsw.go b/core/rgsw/rgsw.go index 5cf45d33b..9dd82d789 100644 --- a/core/rgsw/rgsw.go +++ b/core/rgsw/rgsw.go @@ -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 diff --git a/core/rlwe/ciphertext.go b/core/rlwe/ciphertext.go index 16375bb4f..c31947331 100644 --- a/core/rlwe/ciphertext.go +++ b/core/rlwe/ciphertext.go @@ -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()) diff --git a/core/rlwe/decryptor.go b/core/rlwe/decryptor.go index 69895984a..7d8816ed7 100644 --- a/core/rlwe/decryptor.go +++ b/core/rlwe/decryptor.go @@ -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, diff --git a/core/rlwe/element.go b/core/rlwe/element.go index ba0d968c8..852e4e984 100644 --- a/core/rlwe/element.go +++ b/core/rlwe/element.go @@ -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 diff --git a/core/rlwe/encryptor.go b/core/rlwe/encryptor.go index 9f940172b..3c504bf8c 100644 --- a/core/rlwe/encryptor.go +++ b/core/rlwe/encryptor.go @@ -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) { diff --git a/core/rlwe/evaluator.go b/core/rlwe/evaluator.go index 6d4072eb8..74c6a4f92 100644 --- a/core/rlwe/evaluator.go +++ b/core/rlwe/evaluator.go @@ -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 diff --git a/core/rlwe/evaluator_automorphism.go b/core/rlwe/evaluator_automorphism.go index 7e03555f2..4355f4271 100644 --- a/core/rlwe/evaluator_automorphism.go +++ b/core/rlwe/evaluator_automorphism.go @@ -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) { diff --git a/core/rlwe/evaluator_evaluationkey.go b/core/rlwe/evaluator_evaluationkey.go index 7b90cd01a..1efe725ed 100644 --- a/core/rlwe/evaluator_evaluationkey.go +++ b/core/rlwe/evaluator_evaluationkey.go @@ -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: diff --git a/core/rlwe/gadgetciphertext.go b/core/rlwe/gadgetciphertext.go index 4503c20f4..9b8235613 100644 --- a/core/rlwe/gadgetciphertext.go +++ b/core/rlwe/gadgetciphertext.go @@ -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) { diff --git a/core/rlwe/inner_sum.go b/core/rlwe/inner_sum.go index 7291c7d7f..f55728013 100644 --- a/core/rlwe/inner_sum.go +++ b/core/rlwe/inner_sum.go @@ -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) } diff --git a/core/rlwe/keygenerator.go b/core/rlwe/keygenerator.go index 547f52df4..5ec6c8f8e 100644 --- a/core/rlwe/keygenerator.go +++ b/core/rlwe/keygenerator.go @@ -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() diff --git a/core/rlwe/keys.go b/core/rlwe/keys.go index 7ac9de07a..a93705e07 100644 --- a/core/rlwe/keys.go +++ b/core/rlwe/keys.go @@ -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 diff --git a/core/rlwe/metadata.go b/core/rlwe/metadata.go index f6621edb9..dbbd34657 100644 --- a/core/rlwe/metadata.go +++ b/core/rlwe/metadata.go @@ -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) } diff --git a/core/rlwe/packing.go b/core/rlwe/packing.go index a000aad0f..6a45eda92 100644 --- a/core/rlwe/packing.go +++ b/core/rlwe/packing.go @@ -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() diff --git a/core/rlwe/params.go b/core/rlwe/params.go index 74929f0ee..15d54b90a 100644 --- a/core/rlwe/params.go +++ b/core/rlwe/params.go @@ -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 { diff --git a/core/rlwe/plaintext.go b/core/rlwe/plaintext.go index f375e6f60..46293d4f8 100644 --- a/core/rlwe/plaintext.go +++ b/core/rlwe/plaintext.go @@ -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) { diff --git a/core/rlwe/scale.go b/core/rlwe/scale.go index 2c9357367..a82ab7aa5 100644 --- a/core/rlwe/scale.go +++ b/core/rlwe/scale.go @@ -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) } diff --git a/core/rlwe/utils.go b/core/rlwe/utils.go index 809102f80..6a37ad8d6 100644 --- a/core/rlwe/utils.go +++ b/core/rlwe/utils.go @@ -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 diff --git a/he/hebin/evaluator.go b/he/hebin/evaluator.go index c662d2e39..b29a75317 100644 --- a/he/hebin/evaluator.go +++ b/he/hebin/evaluator.go @@ -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) { diff --git a/he/hebin/keys.go b/he/hebin/keys.go index 93d94fd7f..89b8cb664 100644 --- a/he/hebin/keys.go +++ b/he/hebin/keys.go @@ -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 diff --git a/he/hefloat/bootstrapping/bootstrapper.go b/he/hefloat/bootstrapping/bootstrapper.go index 0d6832dd3..72f43ed02 100644 --- a/he/hefloat/bootstrapping/bootstrapper.go +++ b/he/hefloat/bootstrapping/bootstrapper.go @@ -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. diff --git a/he/hefloat/bootstrapping/bootstrapping.go b/he/hefloat/bootstrapping/bootstrapping.go index 449954fe7..85214038a 100644 --- a/he/hefloat/bootstrapping/bootstrapping.go +++ b/he/hefloat/bootstrapping/bootstrapping.go @@ -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) { diff --git a/he/hefloat/bootstrapping/evaluator.go b/he/hefloat/bootstrapping/evaluator.go index 77e302d31..4bd9c6e6a 100644 --- a/he/hefloat/bootstrapping/evaluator.go +++ b/he/hefloat/bootstrapping/evaluator.go @@ -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 { diff --git a/he/hefloat/bootstrapping/keys.go b/he/hefloat/bootstrapping/keys.go index 6a366f0ae..f1a344762 100644 --- a/he/hefloat/bootstrapping/keys.go +++ b/he/hefloat/bootstrapping/keys.go @@ -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) diff --git a/he/hefloat/bootstrapping/parameters.go b/he/hefloat/bootstrapping/parameters.go index 719bfe4cb..7a53ae01a 100644 --- a/he/hefloat/bootstrapping/parameters.go +++ b/he/hefloat/bootstrapping/parameters.go @@ -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) } diff --git a/he/hefloat/bootstrapping/parameters_literal.go b/he/hefloat/bootstrapping/parameters_literal.go index 4efc6a09e..77e7aa898 100644 --- a/he/hefloat/bootstrapping/parameters_literal.go +++ b/he/hefloat/bootstrapping/parameters_literal.go @@ -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) { diff --git a/he/hefloat/bootstrapping/sk_bootstrapper.go b/he/hefloat/bootstrapping/sk_bootstrapper.go index 00ad33ecb..da515989e 100644 --- a/he/hefloat/bootstrapping/sk_bootstrapper.go +++ b/he/hefloat/bootstrapping/sk_bootstrapper.go @@ -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 diff --git a/he/hefloat/dft.go b/he/hefloat/dft.go index 58d2f0de1..73b8084a2 100644 --- a/he/hefloat/dft.go +++ b/he/hefloat/dft.go @@ -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 diff --git a/he/hefloat/inverse.go b/he/hefloat/inverse.go index 845f067dd..82cb1af3a 100644 --- a/he/hefloat/inverse.go +++ b/he/hefloat/inverse.go @@ -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) { diff --git a/he/hefloat/linear_transformation.go b/he/hefloat/linear_transformation.go index 7d5427d4c..c9a92bf8a 100644 --- a/he/hefloat/linear_transformation.go +++ b/he/hefloat/linear_transformation.go @@ -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< 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) { diff --git a/mhe/mhefloat/utils.go b/mhe/mhefloat/utils.go index 4e727a1ab..6a62f1364 100644 --- a/mhe/mhefloat/utils.go +++ b/mhe/mhefloat/utils.go @@ -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))) diff --git a/mhe/mheint/mheint.go b/mhe/mheint/mheint.go index c12921ee2..221fb3467 100644 --- a/mhe/mheint/mheint.go +++ b/mhe/mheint/mheint.go @@ -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 diff --git a/mhe/mheint/refresh.go b/mhe/mheint/refresh.go index 50aa74352..2a9dda5d9 100644 --- a/mhe/mheint/refresh.go +++ b/mhe/mheint/refresh.go @@ -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) } diff --git a/mhe/mheint/sharing.go b/mhe/mheint/sharing.go index 38195b297..39a440329 100644 --- a/mhe/mheint/sharing.go +++ b/mhe/mheint/sharing.go @@ -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") diff --git a/mhe/mheint/transform.go b/mhe/mheint/transform.go index 6f51d3e13..34d1b3024 100644 --- a/mhe/mheint/transform.go +++ b/mhe/mheint/transform.go @@ -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() { diff --git a/mhe/refresh.go b/mhe/refresh.go index 2a0e22ca7..633db51fd 100644 --- a/mhe/refresh.go +++ b/mhe/refresh.go @@ -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 diff --git a/mhe/threshold.go b/mhe/threshold.go index ce1f63565..39bbcc0c9 100644 --- a/mhe/threshold.go +++ b/mhe/threshold.go @@ -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) } diff --git a/schemes/bfv/bfv.go b/schemes/bfv/bfv.go index 5fe2ea7a5..3cec73048 100644 --- a/schemes/bfv/bfv.go +++ b/schemes/bfv/bfv.go @@ -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. diff --git a/schemes/bfv/params.go b/schemes/bfv/params.go index e2f00c507..a080f0d2b 100644 --- a/schemes/bfv/params.go +++ b/schemes/bfv/params.go @@ -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) } diff --git a/schemes/bgv/bgv.go b/schemes/bgv/bgv.go index 8688fb99a..c5872975e 100644 --- a/schemes/bgv/bgv.go +++ b/schemes/bgv/bgv.go @@ -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) } diff --git a/schemes/bgv/encoder.go b/schemes/bgv/encoder.go index cfa9d0987..586fde330 100644 --- a/schemes/bgv/encoder.go +++ b/schemes/bgv/encoder.go @@ -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) diff --git a/schemes/bgv/evaluator.go b/schemes/bgv/evaluator.go index 54ad16478..cc5fabe4b 100644 --- a/schemes/bgv/evaluator.go +++ b/schemes/bgv/evaluator.go @@ -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) { diff --git a/schemes/bgv/params.go b/schemes/bgv/params.go index 8b354b9b8..8999cc202 100644 --- a/schemes/bgv/params.go +++ b/schemes/bgv/params.go @@ -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 { diff --git a/schemes/ckks/bridge.go b/schemes/ckks/bridge.go index a2a639070..23c93332a 100644 --- a/schemes/ckks/bridge.go +++ b/schemes/ckks/bridge.go @@ -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 diff --git a/schemes/ckks/ckks.go b/schemes/ckks/ckks.go index f9cee8dbb..c3033620b 100644 --- a/schemes/ckks/ckks.go +++ b/schemes/ckks/ckks.go @@ -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) } diff --git a/schemes/ckks/encoder.go b/schemes/ckks/encoder.go index 77ef2a266..ea52e2a16 100644 --- a/schemes/ckks/encoder.go +++ b/schemes/ckks/encoder.go @@ -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 diff --git a/schemes/ckks/evaluator.go b/schemes/ckks/evaluator.go index 40279f864..4b6842143 100644 --- a/schemes/ckks/evaluator.go +++ b/schemes/ckks/evaluator.go @@ -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) diff --git a/schemes/ckks/linear_transformation.go b/schemes/ckks/linear_transformation.go index 94cff69c0..98d4c0e35 100644 --- a/schemes/ckks/linear_transformation.go +++ b/schemes/ckks/linear_transformation.go @@ -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 { diff --git a/schemes/ckks/params.go b/schemes/ckks/params.go index 3c189bb54..545879b67 100644 --- a/schemes/ckks/params.go +++ b/schemes/ckks/params.go @@ -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 { diff --git a/schemes/ckks/precision.go b/schemes/ckks/precision.go index 306a310e3..1450c8173 100644 --- a/schemes/ckks/precision.go +++ b/schemes/ckks/precision.go @@ -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) {