Ptxt.h
1 /* Copyright (C) 2019-2020 IBM Corp.
2  * This program is Licensed under the Apache License, Version 2.0
3  * (the "License"); you may not use this file except in compliance
4  * with the License. You may obtain a copy of the License at
5  * http://www.apache.org/licenses/LICENSE-2.0
6  * Unless required by applicable law or agreed to in writing, software
7  * distributed under the License is distributed on an "AS IS" BASIS,
8  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9  * See the License for the specific language governing permissions and
10  * limitations under the License. See accompanying LICENSE file.
11  */
12 
13 #ifndef HELIB_PTXT_H
14 #define HELIB_PTXT_H
15 
16 #include <type_traits>
17 #include <vector>
18 #include <algorithm>
19 #include <numeric>
20 #include <iomanip>
21 
22 #include <helib/Context.h>
23 #include <helib/EncryptedArray.h>
24 #include <helib/assertions.h>
25 #include <helib/PolyMod.h>
26 #include <helib/keys.h>
27 #include <helib/scheme.h>
28 #include <helib/EncodedPtxt.h>
29 
35 namespace helib {
36 
37 // Utility functions
38 
47 template <typename From, typename Scheme>
48 inline std::vector<typename Scheme::SlotType> convertDataToSlotVector(
49  const std::vector<From>& data,
50  const Context& context)
51 {
52  static_assert(std::is_same<Scheme, CKKS>::value ||
53  std::is_same<Scheme, BGV>::value,
54  "Can only call convertDataToSlotVector with Scheme equals to "
55  "CKKS or BGV");
56  using To = typename Scheme::SlotType;
57  std::vector<To> res(data.size(), Ptxt<Scheme>::convertToSlot(context, 0l));
58  for (std::size_t i = 0; i < data.size(); ++i) {
59  res[i] = data[i];
60  }
61  return res;
62 }
63 
73 template <typename Scheme>
75  const std::vector<Ptxt<Scheme>>& first_vec,
76  const std::vector<Ptxt<Scheme>>& second_vec)
77 {
78  static_assert(std::is_same<Scheme, CKKS>::value ||
79  std::is_same<Scheme, BGV>::value,
80  "Can only call innerProduct with Scheme equals to CKKS or BGV");
81  for (std::size_t i = 0; i < first_vec.size(); ++i) {
82  assertTrue<RuntimeError>(first_vec[i].isValid(),
83  "Cannot call innerProduct on default-constructed"
84  " Ptxt as first argument at index " +
85  std::to_string(i));
86  }
87  for (std::size_t i = 0; i < second_vec.size(); ++i) {
88  assertTrue<RuntimeError>(second_vec[i].isValid(),
89  "Cannot call innerProduct on default-constructed"
90  " Ptxt as second argument at index " +
91  std::to_string(i));
92  }
93  long n = std::min(first_vec.size(), second_vec.size());
94  if (n <= 0) {
95  result.clear();
96  return;
97  }
98  result = first_vec[0];
99  result *= second_vec[0];
100  for (long i = 1; i < n; ++i)
101  result += (first_vec[i] * second_vec[i]);
102 }
103 
104 // Forward declaration as function is a friend of the templated `Ptxt` class.
127 template <typename Scheme>
128 std::istream& operator>>(std::istream& is, Ptxt<Scheme>& ptxt);
129 
130 // Forward declaration as function is a friend of the templated `Ptxt` class.
146 template <typename Scheme>
147 std::ostream& operator<<(std::ostream& is, const Ptxt<Scheme>& ptxt);
148 
186 template <typename Scheme>
187 class Ptxt
188 {
189  static_assert(std::is_same<Scheme, CKKS>::value ||
190  std::is_same<Scheme, BGV>::value,
191  "Can only create plaintext object parameterized by the crypto "
192  "scheme (CKKS or BGV)");
193 
194 public:
199  static constexpr std::string_view typeName = "Ptxt";
200 
206  using SlotType = typename Scheme::SlotType;
207 
212  Ptxt();
213 
218  explicit Ptxt(const Context& context);
219 
225  explicit Ptxt(const PubKey& pk) : Ptxt(pk.getContext()){};
226 
232  Ptxt(const Context& context, const SlotType& value);
233 
241  template <typename U = Scheme,
242  std::enable_if_t<std::is_same<U, BGV>::value>* = nullptr>
243  Ptxt(const Context& context, const NTL::ZZX& value);
244 
250  Ptxt(const Context& context, const std::vector<SlotType>& data);
251 
257  template <typename T>
258  Ptxt(const Context& context, const std::vector<T>& data) :
259  Ptxt<Scheme>(context, convertDataToSlotVector<T, Scheme>(data, context))
260  {}
261 
266  Ptxt(const Ptxt<Scheme>& other) = default;
267 
272  Ptxt(Ptxt<Scheme>&& other) noexcept = default;
273 
278  Ptxt<Scheme>& operator=(const Ptxt<Scheme>& v) = default;
279 
284  Ptxt<Scheme>& operator=(Ptxt<Scheme>&& v) noexcept = default;
285 
289  ~Ptxt() = default;
290 
295  bool isValid() const;
296 
301  size_t size() const;
302 
307  long lsize() const;
308 
313  const Context& getContext() const { return *context; }
314 
319  void setData(const std::vector<SlotType>& data);
320 
325  void setData(const SlotType& value);
326 
332  template <typename T = Scheme,
333  typename std::enable_if_t<std::is_same<T, BGV>::value>* = nullptr>
334  void setData(const NTL::ZZX& value);
335 
342  template <typename T = Scheme,
343  typename std::enable_if_t<std::is_same<T, BGV>::value>* = nullptr>
344  void decodeSetData(const NTL::ZZX& data);
345 
349  void clear();
350 
355  Ptxt<Scheme>& random();
356 
361  const std::vector<SlotType>& getSlotRepr() const;
362 
369  NTL::ZZX getPolyRepr() const;
370 
375  void encode(EncodedPtxt& eptxt,
376  double mag = -1,
377  OptLong prec = OptLong()) const;
378 
384  SlotType& operator[](long i);
385 
391  SlotType operator[](long i) const;
392 
399  SlotType& at(long i);
400 
407  SlotType at(long i) const;
408 
414  bool operator==(const Ptxt<Scheme>& other) const;
415 
421  bool operator!=(const Ptxt<Scheme>& other) const;
422 
428  Ptxt<Scheme> operator*(const Ptxt<Scheme>& rhs) const;
429 
435  Ptxt<Scheme> operator+(const Ptxt<Scheme>& rhs) const;
436 
442  Ptxt<Scheme> operator-(const Ptxt<Scheme>& rhs) const;
443 
449  Ptxt<Scheme>& operator*=(const Ptxt<Scheme>& otherPtxt);
450 
456  Ptxt<Scheme>& operator*=(const SlotType& scalar);
457 
463  template <typename Scalar>
464  Ptxt<Scheme>& operator*=(const Scalar& scalar)
465  {
466  assertTrue<RuntimeError>(isValid(),
467  "Cannot call operator*= on "
468  "default-constructed Ptxt");
469  for (std::size_t i = 0; i < this->slots.size(); i++) {
470  this->slots[i] *= scalar;
471  }
472  return *this;
473  }
474 
480  Ptxt<Scheme>& operator+=(const Ptxt<Scheme>& otherPtxt);
481 
487  Ptxt<Scheme>& operator+=(const SlotType& scalar);
488 
494  template <typename Scalar>
495  Ptxt<Scheme>& operator+=(const Scalar& scalar)
496  {
497  assertTrue<RuntimeError>(isValid(),
498  "Cannot call operator+= on "
499  "default-constructed Ptxt");
500  for (std::size_t i = 0; i < this->slots.size(); i++) {
501  this->slots[i] += scalar;
502  }
503  return *this;
504  }
505 
511  Ptxt<Scheme>& operator-=(const Ptxt<Scheme>& otherPtxt);
512 
518  Ptxt<Scheme>& operator-=(const SlotType& scalar);
519 
525  template <typename Scalar>
526  Ptxt<Scheme>& operator-=(const Scalar& scalar)
527  {
528  assertTrue<RuntimeError>(isValid(),
529  "Cannot call operator-= on "
530  "default-constructed Ptxt");
531  for (std::size_t i = 0; i < this->slots.size(); i++) {
532  this->slots[i] -= scalar;
533  }
534  return *this;
535  }
536 
541  Ptxt<Scheme>& negate();
542 
548  template <typename T = Scheme,
549  typename Scalar,
550  typename std::enable_if_t<std::is_same<T, BGV>::value>* = nullptr>
551  Ptxt<Scheme>& addConstant(const Scalar& scalar)
552  {
553  return *this += scalar;
554  }
555 
561  template <typename T = Scheme,
562  typename Scalar,
563  typename std::enable_if_t<std::is_same<T, CKKS>::value>* = nullptr>
564  Ptxt<Scheme>& addConstantCKKS(const Scalar& scalar)
565  {
566  return *this += scalar;
567  }
568 
575  Ptxt<Scheme>& multiplyBy(const Ptxt<Scheme>& otherPtxt);
576 
583  Ptxt<Scheme>& multiplyBy2(const Ptxt& otherPtxt1, const Ptxt& otherPtxt2);
584 
589  Ptxt<Scheme>& square();
590 
595  Ptxt<Scheme>& cube();
596 
603  Ptxt<Scheme>& power(long e);
604 
611  Ptxt<Scheme>& rotate(long amount);
612 
619  Ptxt<Scheme>& rotate1D(long dim, long amount);
620 
627  Ptxt<Scheme>& shift(long amount);
628 
636  Ptxt<Scheme>& shift1D(long dim, long amount);
637 
645 
652  template <typename T = Scheme,
653  std::enable_if_t<std::is_same<T, BGV>::value>* = nullptr>
655 
661  Ptxt<Scheme>& replicate(long pos);
662 
670  std::vector<Ptxt<Scheme>> replicateAll() const;
671 
678  template <typename T = Scheme,
679  std::enable_if_t<std::is_same<T, CKKS>::value>* = nullptr>
681 
687  template <typename T = Scheme,
688  std::enable_if_t<std::is_same<T, CKKS>::value>* = nullptr>
690 
696  template <typename T = Scheme,
697  std::enable_if_t<std::is_same<T, CKKS>::value>* = nullptr>
699 
706 
713 
720 
727 
733 
747  void writeToJSON(std::ostream& os) const;
748 
762  JsonWrapper writeToJSON() const;
763 
783  static Ptxt<Scheme> readFromJSON(std::istream& is, const Context& context);
784 
804  static Ptxt<Scheme> readFromJSON(const JsonWrapper& jw,
805  const Context& context);
806 
829  void readJSON(std::istream& is);
830 
853  void readJSON(const JsonWrapper& jw);
854 
855  friend std::istream& operator>><Scheme>(std::istream& is, Ptxt& ptxt);
856 
857  friend std::ostream& operator<<<Scheme>(std::ostream& os, const Ptxt& ptxt);
858 
865  static SlotType convertToSlot(const Context& context, long slot);
866 
872  Ptxt<Scheme>& cleanUp() { return *this; }
873 
874 private:
875  const Context* context;
876 
879  std::vector<SlotType> slots;
880 
890  long coordToIndex(const std::vector<long>& coords);
891 
901  std::vector<long> indexToCoord(long index);
902 
909  template <typename type>
910  typename type::RX slotsToRX() const;
911 
922  void assertSlotsCompatible(const std::vector<SlotType>& slots) const;
923 
933  template <typename type>
934  NTL::ZZX automorph_internal(long k);
935 };
936 } // namespace helib
937 
938 #endif // HELIB_PTXT_H
Maintaining the HE scheme parameters.
Definition: Context.h:100
Definition: EncodedPtxt.h:143
Represents the set of long int's plus a distinguished value that can be used to denote "undefined"....
Definition: NumbTh.h:998
An object that mimics the functionality of the Ctxt object, and acts as a convenient entry point for ...
Definition: Ptxt.h:188
Ptxt(const PubKey &pk)
Public key only constructor, defaults all slots to 0.
Definition: Ptxt.h:225
size_t size() const
Returns the size (number of slots) of a Ptxt.
Definition: Ptxt.cpp:91
bool isValid() const
Check if a Ptxt is valid.
Definition: Ptxt.cpp:85
void clear()
Sets all slots to 0.
Definition: Ptxt.cpp:150
void encode(EncodedPtxt &eptxt, double mag=-1, OptLong prec=OptLong()) const
Converts the slot data in this to a corresponding EncodedPtxt object. mag,prec must be defaulted for ...
Ptxt< Scheme > & addConstantCKKS(const Scalar &scalar)
Add a constant to a CKKS Ptxt.
Definition: Ptxt.h:564
~Ptxt()=default
Default destructor.
Ptxt< Scheme > & rotate(long amount)
Rotate slots right by specified amount (slot i goes to slot i+1 mod size).
Definition: Ptxt.cpp:543
static SlotType convertToSlot(const Context &context, long slot)
Conversion function from long to SlotType.
Ptxt< Scheme > & replicate(long pos)
Replicate single slot across all slots.
Definition: Ptxt.cpp:719
Ptxt< Scheme > & negate()
Negate a Ptxt.
Definition: Ptxt.cpp:436
Ptxt< Scheme > & operator+=(const Ptxt< Scheme > &otherPtxt)
Plus equals operator with another Ptxt.
Definition: Ptxt.cpp:376
Ptxt(const Context &context, const NTL::ZZX &value)
BGV plaintext polynomial constructor, set all slots to the value polynomial.
void setData(const NTL::ZZX &value)
Set the Ptxt data replicating the input polynomial on all slots.
long lsize() const
Returns the size (number of slots) of a Ptxt as long.
Definition: Ptxt.cpp:99
Ptxt< Scheme > & incrementalProduct()
Compute the incremental product (each slot is the product of the previous slots).
Definition: Ptxt.cpp:802
SlotType & at(long i)
at accessor operator.
Definition: Ptxt.cpp:268
Ptxt< Scheme > & runningSums()
Compute the running sum (each slot is the sum of the previous slots).
Definition: Ptxt.cpp:778
void decodeSetData(const NTL::ZZX &data)
Set the Ptxt slots using values from decoding data to slot representation.
Ptxt(const Context &context, const std::vector< T > &data)
Generic slot vector constructor.
Definition: Ptxt.h:258
const std::vector< SlotType > & getSlotRepr() const
Get the data held in the slots as a std::vector<SlotType>.
Definition: Ptxt.cpp:190
Ptxt< Scheme > & random()
Populate slots with random data.
Definition: Ptxt.cpp:182
static constexpr std::string_view typeName
Class label to be added to JSON serialization as object type information.
Definition: Ptxt.h:199
Ptxt< Scheme > & multiplyBy(const Ptxt< Scheme > &otherPtxt)
Multiplication function between two Ptxt objects.
Definition: Ptxt.cpp:447
void readJSON(std::istream &is)
In-place function to deserialize a Ptxt<Scheme> from a JSON stream.
Definition: Ptxt.cpp:997
Ptxt()
Default constructor results in invalid Ptxt object which throws if used.
Definition: Ptxt.cpp:35
Ptxt< Scheme > & multiplyBy2(const Ptxt &otherPtxt1, const Ptxt &otherPtxt2)
Multiplication function between three Ptxt objects.
Definition: Ptxt.cpp:465
Ptxt< Scheme > & totalProduct()
Compute the total product (each slot contains the total product of every slot).
Definition: Ptxt.cpp:813
Ptxt< Scheme > & cleanUp()
To be inline with the Ctxt interface. However for Ptxt this means do nothing.
Definition: Ptxt.h:872
Ptxt< Scheme > & operator-=(const Scalar &scalar)
Minus equals operator with a scalar.
Definition: Ptxt.h:526
Ptxt< Scheme > & shift(long amount)
Shifts slots right by specified amount with 0 fill (slot i goes to slot i+1 mod size).
Definition: Ptxt.cpp:602
Ptxt< Scheme > imag() const
Extract the imaginary part of a CKKS plaintext.
typename Scheme::SlotType SlotType
Alias for type to be stored in the slots.
Definition: Ptxt.h:206
Ptxt< Scheme > & frobeniusAutomorph(long j)
Apply the frobenius automorphism a(X) -> a(X^(p^j)) mod Phi_m(X).
const Context & getContext() const
Returns the context used to initialize the Ptxt
Definition: Ptxt.h:313
void setData(const std::vector< SlotType > &data)
Set the data.
Definition: Ptxt.cpp:107
Ptxt< Scheme > & operator=(Ptxt< Scheme > &&v) noexcept=default
Move assignment operator with other Ptxt.
static Ptxt< Scheme > readFromJSON(std::istream &is, const Context &context)
Function to deserialize and return a Ptxt<Scheme> from a JSON stream.
Definition: Ptxt.cpp:979
SlotType & operator[](long i)
Square bracket accessor operator.
Definition: Ptxt.cpp:250
Ptxt< Scheme > operator*(const Ptxt< Scheme > &rhs) const
Infix multiplication operator.
Definition: Ptxt.cpp:295
Ptxt< Scheme > & addConstant(const Scalar &scalar)
Add a constant to a BGV Ptxt.
Definition: Ptxt.h:551
Ptxt< Scheme > & operator-=(const Ptxt< Scheme > &otherPtxt)
Minus equals operator with another Ptxt.
Definition: Ptxt.cpp:406
Ptxt< Scheme > & mapTo01()
Map all non-zero slots to 1, keeping zero slots as zero.
Definition: Ptxt.cpp:826
Ptxt< Scheme > & automorph(long k)
Apply the automorphism a(X) -> a(X^k) mod Phi_m(X).
Ptxt< Scheme > & rotate1D(long dim, long amount)
Rotate slots right by specified amount along a specific dimension.
Definition: Ptxt.cpp:559
bool operator==(const Ptxt< Scheme > &other) const
Equals operator between two Ptxt objects.
Definition: Ptxt.cpp:282
std::vector< Ptxt< Scheme > > replicateAll() const
Generate a vector of plaintexts with each slot replicated in each plaintext.
Definition: Ptxt.cpp:729
bool operator!=(const Ptxt< Scheme > &other) const
Not equals operator between two Ptxt objects.
Definition: Ptxt.cpp:289
Ptxt< Scheme > & operator*=(const Scalar &scalar)
Times equals operator with a scalar.
Definition: Ptxt.h:464
NTL::ZZX getPolyRepr() const
Converts the slot data in this to its single polynomial representation.
Ptxt(const Ptxt< Scheme > &other)=default
Default copy constructor.
Ptxt< Scheme > & power(long e)
Power operation to raise a Ptxt to an arbitrary non-negative power.
Definition: Ptxt.cpp:516
Ptxt< Scheme > & complexConj()
Apply complex conjugate of complex numbers in slots of a CKKS Ptxt object.
Ptxt< Scheme > & square()
Square operation on a Ptxt.
Definition: Ptxt.cpp:500
Ptxt< Scheme > & operator+=(const Scalar &scalar)
Plus equals operator with a scalar.
Definition: Ptxt.h:495
Ptxt< Scheme > operator+(const Ptxt< Scheme > &rhs) const
Infix addition operator.
Definition: Ptxt.cpp:312
Ptxt< Scheme > & totalSums()
Compute the total sum (each slot contains the total sum of every slot).
Definition: Ptxt.cpp:789
Ptxt(Ptxt< Scheme > &&other) noexcept=default
Default move constructor.
Ptxt< Scheme > & cube()
Cube operation on a Ptxt.
Definition: Ptxt.cpp:508
Ptxt< Scheme > & shift1D(long dim, long amount)
Shift slots right in one dimension of the hypercube structure with 0 fill.
Definition: Ptxt.cpp:622
Ptxt< Scheme > & operator*=(const Ptxt< Scheme > &otherPtxt)
Times equals operator with another Ptxt.
Definition: Ptxt.cpp:346
Ptxt< Scheme > & operator=(const Ptxt< Scheme > &v)=default
Copy assignment operator with other Ptxt.
JsonWrapper writeToJSON() const
Function to serialize this Ptxt<Scheme>.
Definition: Ptxt.cpp:956
Ptxt< Scheme > operator-(const Ptxt< Scheme > &rhs) const
Infix subtraction operator.
Definition: Ptxt.cpp:329
Ptxt< Scheme > real() const
Extract the real part of a CKKS plaintext.
The public key.
Definition: keys.h:45
Definition: apiAttributes.h:21
void innerProduct(Ctxt &result, const CtPtrs &v1, const CtPtrs &v2)
Definition: Ctxt.cpp:2853
std::istream & operator>>(std::istream &s, CtxtPart &p)
Definition: Ctxt.cpp:2762
std::ostream & operator<<(std::ostream &os, const ContextBuilder< SCHEME > &cb)
ostream operator for serializing the ContextBuilder object.
std::vector< typename Scheme::SlotType > convertDataToSlotVector(const std::vector< From > &data, const Context &context)
Converts std::vector<From> to std::vector<Scheme::SlotType>.
Definition: Ptxt.h:48
Definition: JsonWrapper.h:9