// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using Microsoft.Research.SEAL.Tools;
using System;
namespace Microsoft.Research.SEAL
{
///
/// Encodes integers into plaintext polynomials that Encryptor can encrypt. An instance of
/// the IntegerEncoder class converts an integer into a plaintext polynomial by placing its
/// binary digits as the coefficients of the polynomial. Decoding the integer amounts to
/// evaluating the plaintext polynomial at x=2.
///
/// Addition and multiplication on the integer side translate into addition and multiplication
/// on the encoded plaintext polynomial side, provided that the length of the polynomial
/// never grows to be of the size of the polynomial modulus (PolyModulus), and that the
/// coefficients of the plaintext polynomials appearing throughout the computations never
/// experience coefficients larger than the plaintext modulus (PlainModulus).
///
///
///
/// Negative Integers
/// Negative integers are represented by using -1 instead of 1 in the binary representation,
/// and the negative coefficients are stored in the plaintext polynomials as unsigned integers
/// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1
/// would be stored as a polynomial coefficient PlainModulus-1.
///
///
public class IntegerEncoder : NativeObject
{
///
/// Creates a IntegerEncoder object. The constructor takes as input a pointer to
/// a SEALContext object which contains the plaintext modulus.
///
/// The SEALContext
/// if context is null
/// if the context is not set
/// if the PlainModulus set in context is not
/// at least 2
public IntegerEncoder(SEALContext context)
{
if (null == context)
throw new ArgumentNullException(nameof(context));
if (!context.ParametersSet)
throw new ArgumentException("Encryption parameters are not set correctly");
SEALContext.ContextData contextData = context.FirstContextData;
if (contextData.Parms.Scheme != SchemeType.BFV)
throw new ArgumentException("Unsupported scheme");
NativeMethods.IntegerEncoder_Create(context.NativePtr, out IntPtr encoderPtr);
NativePtr = encoderPtr;
}
///
/// Encodes an unsigned integer (represented by ulong) into a plaintext polynomial.
///
/// The unsigned integer to encode
public Plaintext Encode(ulong value)
{
Plaintext plain = new Plaintext();
NativeMethods.IntegerEncoder_Encode(NativePtr, value, plain.NativePtr);
return plain;
}
///
/// Encodes an unsigned integer(represented by ulong) into a plaintext polynomial.
///
/// The unsigned integer to encode
/// The plaintext to overwrite with the encoding
/// if destination is null
public void Encode(ulong value, Plaintext destination)
{
if (null == destination)
throw new ArgumentNullException(nameof(destination));
NativeMethods.IntegerEncoder_Encode(NativePtr, value, destination.NativePtr);
}
///
/// Decodes a plaintext polynomial and returns the result as uint. Mathematically
/// this amounts to evaluating the input polynomial at X = 2.
///
/// The plaintext to be decoded
/// if plain is null
/// if plain does not represent a valid plaintext polynomial
/// if the output does not fit in uint
public uint DecodeUInt32(Plaintext plain)
{
if (null == plain)
throw new ArgumentNullException(nameof(plain));
NativeMethods.IntegerEncoder_DecodeUInt32(NativePtr, plain.NativePtr, out uint result);
return result;
}
///
/// Decodes a plaintext polynomial and returns the result as ulong. Mathematically
/// this amounts to evaluating the input polynomial at X=2.
///
/// The plaintext to be decoded
/// if plain is null
/// if plain does not represent a valid plaintext polynomial
/// if the output does not fit in ulong
public ulong DecodeUInt64(Plaintext plain)
{
if (null == plain)
throw new ArgumentNullException(nameof(plain));
NativeMethods.IntegerEncoder_DecodeUInt64(NativePtr, plain.NativePtr, out ulong result);
return result;
}
///
/// Encodes a signed integer (represented by long) into a plaintext polynomial.
///
///
///
/// Negative Integers
/// Negative integers are represented by using -1 instead of 1 in the binary representation,
/// and the negative coefficients are stored in the plaintext polynomials as unsigned integers
/// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1
/// would be stored as a polynomial coefficient PlainModulus-1.
///
///
/// The signed integer to encode
public Plaintext Encode(long value)
{
Plaintext plain = new Plaintext();
NativeMethods.IntegerEncoder_Encode(NativePtr, value, plain.NativePtr);
return plain;
}
///
/// Encodes a signed integer(represented by long) into a plaintext polynomial.
///
///
///
/// Negative Integers
/// Negative integers are represented by using -1 instead of 1 in the binary representation,
/// and the negative coefficients are stored in the plaintext polynomials as unsigned integers
/// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1
/// would be stored as a polynomial coefficient PlainModulus-1.
///
///
/// The signed integer to encode
/// The plaintext to overwrite with the encoding
public void Encode(long value, Plaintext destination)
{
if (null == destination)
throw new ArgumentNullException(nameof(destination));
NativeMethods.IntegerEncoder_Encode(NativePtr, value, destination.NativePtr);
}
///
/// Encodes an unsigned integer(represented by BigUInt) into a plaintext polynomial.
///
/// The unsigned integer to encode
/// if value is null
public Plaintext Encode(BigUInt value)
{
if (null == value)
throw new ArgumentNullException(nameof(value));
Plaintext plain = new Plaintext();
NativeMethods.IntegerEncoder_Encode(NativePtr, value.NativePtr, plain.NativePtr);
return plain;
}
///
/// Encodes an unsigned integer(represented by BigUInt) into a plaintext polynomial.
///
/// The unsigned integer to encode
/// The plaintext to overwrite with the encoding
/// if either value or destination are null
public void Encode(BigUInt value, Plaintext destination)
{
if (null == value)
throw new ArgumentNullException(nameof(value));
if (null == destination)
throw new ArgumentNullException(nameof(destination));
NativeMethods.IntegerEncoder_Encode(NativePtr, value.NativePtr, destination.NativePtr);
}
///
/// Decodes a plaintext polynomial and returns the result as int. Mathematically
/// this amounts to evaluating the input polynomial at X = 2.
///
/// The plaintext to be decoded
/// if plain is null
/// if plain does not represent a valid plaintext polynomial
/// if the output does not fit in int
public int DecodeInt32(Plaintext plain)
{
if (null == plain)
throw new ArgumentNullException(nameof(plain));
NativeMethods.IntegerEncoder_DecodeInt32(NativePtr, plain.NativePtr, out int result);
return result;
}
///
/// Decodes a plaintext polynomial and returns the result as long. Mathematically
/// this amounts to evaluating the input polynomial at X = 2.
///
/// The plaintext to be decoded
/// if plain is null
/// if plain does not represent a valid plaintext polynomial
/// if the output does not fit in long
public long DecodeInt64(Plaintext plain)
{
if (null == plain)
throw new ArgumentNullException(nameof(plain));
NativeMethods.IntegerEncoder_DecodeInt64(NativePtr, plain.NativePtr, out long result);
return result;
}
///
/// Decodes a plaintext polynomial and returns the result as BigUInt.
/// Mathematically this amounts to evaluating the input polynomial at X = 2.
///
/// The plaintext to be decoded
/// if plain is null
/// if plain does not represent a valid plaintext polynomial
/// if the output is negative
public BigUInt DecodeBigUInt(Plaintext plain)
{
if (null == plain)
throw new ArgumentNullException(nameof(plain));
NativeMethods.IntegerEncoder_DecodeBigUInt(NativePtr, plain.NativePtr, out IntPtr buiPtr);
BigUInt bui = new BigUInt(buiPtr);
return bui;
}
///
/// Encodes a signed integer(represented by int) into a plaintext polynomial.
///
///
///
/// Negative Integers
/// Negative integers are represented by using -1 instead of 1 in the binary representation,
/// and the negative coefficients are stored in the plaintext polynomials as unsigned integers
/// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1
/// would be stored as a polynomial coefficient PlainModulus-1.
///
///
/// The signed integer to encode
public Plaintext Encode(int value)
{
Plaintext plain = new Plaintext();
NativeMethods.IntegerEncoder_Encode(NativePtr, value, plain.NativePtr);
return plain;
}
///
/// Encodes an unsigned integer(represented by uint) into a plaintext polynomial.
///
/// The unsigned integer to encode
public Plaintext Encode(uint value)
{
Plaintext plain = new Plaintext();
NativeMethods.IntegerEncoder_Encode(NativePtr, value, plain.NativePtr);
return plain;
}
///
/// Encodes a signed integer(represented by int) into a plaintext polynomial.
///
///
///
/// Negative Integers
/// Negative integers are represented by using -1 instead of 1 in the binary representation,
/// and the negative coefficients are stored in the plaintext polynomials as unsigned integers
/// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1
/// would be stored as a polynomial coefficient PlainModulus-1.
///
///
/// The signed integer to encode
/// The plaintext to overwrite with the encoding
/// if destination is null
public void Encode(int value, Plaintext destination)
{
if (null == destination)
throw new ArgumentNullException(nameof(destination));
NativeMethods.IntegerEncoder_Encode(NativePtr, value, destination.NativePtr);
}
///
/// Encodes an unsigned integer(represented by uint) into a plaintext polynomial.
///
/// The unsigned integer to encode
/// The plaintext to overwrite with the encoding
/// if destination is null
public void Encode(uint value, Plaintext destination)
{
if (null == destination)
throw new ArgumentNullException(nameof(destination));
NativeMethods.IntegerEncoder_Encode(NativePtr, value, destination.NativePtr);
}
///
/// Get a copy of the plaintext modulus.
///
public Modulus PlainModulus
{
get
{
NativeMethods.IntegerEncoder_PlainModulus(NativePtr, out IntPtr sm);
Modulus result = new Modulus(sm);
return result;
}
}
///
/// Destroy the native object
///
protected override void DestroyNativeObject()
{
NativeMethods.IntegerEncoder_Destroy(NativePtr);
}
}
}