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 
33 namespace helib {
34 
38 struct CKKS
39 {
43  using SlotType = std::complex<double>;
44 };
45 
49 struct BGV
50 {
55  using SlotType = PolyMod;
56 };
57 
58 // Utility functions
59 
68 template <typename From, typename Scheme>
69 inline std::vector<typename Scheme::SlotType> convertDataToSlotVector(
70  const std::vector<From>& data,
71  const Context& context)
72 {
73  static_assert(std::is_same<Scheme, CKKS>::value ||
74  std::is_same<Scheme, BGV>::value,
75  "Can only call convertDataToSlotVector with Scheme equals to "
76  "CKKS or BGV");
77  using To = typename Scheme::SlotType;
78  std::vector<To> res(data.size(), Ptxt<Scheme>::convertToSlot(context, 0l));
79  for (std::size_t i = 0; i < data.size(); ++i) {
80  res[i] = data[i];
81  }
82  return res;
83 }
84 
94 template <typename Scheme>
96  const std::vector<Ptxt<Scheme>>& first_vec,
97  const std::vector<Ptxt<Scheme>>& second_vec)
98 {
99  static_assert(std::is_same<Scheme, CKKS>::value ||
100  std::is_same<Scheme, BGV>::value,
101  "Can only call innerProduct with Scheme equals to CKKS or BGV");
102  for (std::size_t i = 0; i < first_vec.size(); ++i) {
103  assertTrue<RuntimeError>(first_vec[i].isValid(),
104  "Cannot call innerProduct on default-constructed"
105  " Ptxt as first argument at index " +
106  std::to_string(i));
107  }
108  for (std::size_t i = 0; i < second_vec.size(); ++i) {
109  assertTrue<RuntimeError>(second_vec[i].isValid(),
110  "Cannot call innerProduct on default-constructed"
111  " Ptxt as second argument at index " +
112  std::to_string(i));
113  }
114  long n = std::min(first_vec.size(), second_vec.size());
115  if (n <= 0) {
116  result.clear();
117  return;
118  }
119  result = first_vec[0];
120  result *= second_vec[0];
121  for (long i = 1; i < n; ++i)
122  result += (first_vec[i] * second_vec[i]);
123 }
124 
136 void deserialize(std::istream& is, std::complex<double>& num);
137 
146 void serialize(std::ostream& os, const std::complex<double>& num);
147 
148 // Forward declaration as function is a friend of the templated `Ptxt` class.
173 template <typename Scheme>
174 void deserialize(std::istream& is, Ptxt<Scheme>& ptxt);
175 
176 // Forward declaration as function is a friend of the templated `Ptxt` class.
193 template <typename Scheme>
194 void serialize(std::ostream& os, const Ptxt<Scheme>& ptxt);
195 
196 // Forward declaration as function is a friend of the templated `Ptxt` class.
219 template <typename Scheme>
220 std::istream& operator>>(std::istream& is, Ptxt<Scheme>& ptxt);
221 
222 // Forward declaration as function is a friend of the templated `Ptxt` class.
238 template <typename Scheme>
239 std::ostream& operator<<(std::ostream& is, const Ptxt<Scheme>& ptxt);
240 
278 template <typename Scheme>
279 class Ptxt
280 {
281  static_assert(std::is_same<Scheme, CKKS>::value ||
282  std::is_same<Scheme, BGV>::value,
283  "Can only create plaintext object parameterized by the crypto "
284  "scheme (CKKS or BGV)");
285 
286 public:
292  using SlotType = typename Scheme::SlotType;
293 
298  Ptxt();
299 
304  explicit Ptxt(const Context& context);
305 
311  Ptxt(const Context& context, const SlotType& value);
312 
320  template <typename U = Scheme,
321  std::enable_if_t<std::is_same<U, BGV>::value>* = nullptr>
322  Ptxt(const Context& context, const NTL::ZZX& value);
323 
329  Ptxt(const Context& context, const std::vector<SlotType>& data);
330 
336  template <typename T>
337  Ptxt(const Context& context, const std::vector<T>& data) :
338  Ptxt<Scheme>(context, convertDataToSlotVector<T, Scheme>(data, context))
339  {}
340 
345  Ptxt(const Ptxt<Scheme>& other) = default;
346 
351  Ptxt(Ptxt<Scheme>&& other) noexcept = default;
352 
357  Ptxt<Scheme>& operator=(const Ptxt<Scheme>& v) = default;
358 
363  Ptxt<Scheme>& operator=(Ptxt<Scheme>&& v) noexcept = default;
364 
368  ~Ptxt() = default;
369 
374  bool isValid() const;
375 
380  size_t size() const;
381 
386  long lsize() const;
387 
392  const Context& getContext() const { return *context; }
393 
398  void setData(const std::vector<SlotType>& data);
399 
404  void setData(const SlotType& value);
405 
411  template <typename T = Scheme,
412  typename std::enable_if_t<std::is_same<T, BGV>::value>* = nullptr>
413  void setData(const NTL::ZZX& value);
414 
421  template <typename T = Scheme,
422  typename std::enable_if_t<std::is_same<T, BGV>::value>* = nullptr>
423  void decodeSetData(const NTL::ZZX& data);
424 
428  void clear();
429 
434  Ptxt<Scheme>& random();
435 
440  const std::vector<SlotType>& getSlotRepr() const;
441 
448  NTL::ZZX getPolyRepr() const;
449 
455  SlotType& operator[](long i);
456 
462  SlotType operator[](long i) const;
463 
470  SlotType& at(long i);
471 
478  SlotType at(long i) const;
479 
485  bool operator==(const Ptxt<Scheme>& other) const;
486 
492  bool operator!=(const Ptxt<Scheme>& other) const;
493 
499  Ptxt<Scheme> operator*(const Ptxt<Scheme>& rhs) const;
500 
506  Ptxt<Scheme> operator+(const Ptxt<Scheme>& rhs) const;
507 
513  Ptxt<Scheme> operator-(const Ptxt<Scheme>& rhs) const;
514 
520  Ptxt<Scheme>& operator*=(const Ptxt<Scheme>& otherPtxt);
521 
527  Ptxt<Scheme>& operator*=(const SlotType& scalar);
528 
534  template <typename Scalar>
535  Ptxt<Scheme>& operator*=(const Scalar& scalar)
536  {
537  assertTrue<RuntimeError>(isValid(),
538  "Cannot call operator*= on "
539  "default-constructed Ptxt");
540  for (std::size_t i = 0; i < this->slots.size(); i++) {
541  this->slots[i] *= scalar;
542  }
543  return *this;
544  }
545 
551  Ptxt<Scheme>& operator+=(const Ptxt<Scheme>& otherPtxt);
552 
558  Ptxt<Scheme>& operator+=(const SlotType& scalar);
559 
565  template <typename Scalar>
566  Ptxt<Scheme>& operator+=(const Scalar& scalar)
567  {
568  assertTrue<RuntimeError>(isValid(),
569  "Cannot call operator+= on "
570  "default-constructed Ptxt");
571  for (std::size_t i = 0; i < this->slots.size(); i++) {
572  this->slots[i] += scalar;
573  }
574  return *this;
575  }
576 
582  Ptxt<Scheme>& operator-=(const Ptxt<Scheme>& otherPtxt);
583 
589  Ptxt<Scheme>& operator-=(const SlotType& scalar);
590 
596  template <typename Scalar>
597  Ptxt<Scheme>& operator-=(const Scalar& scalar)
598  {
599  assertTrue<RuntimeError>(isValid(),
600  "Cannot call operator-= on "
601  "default-constructed Ptxt");
602  for (std::size_t i = 0; i < this->slots.size(); i++) {
603  this->slots[i] -= scalar;
604  }
605  return *this;
606  }
607 
612  Ptxt<Scheme>& negate();
613 
619  template <typename T = Scheme,
620  typename Scalar,
621  typename std::enable_if_t<std::is_same<T, BGV>::value>* = nullptr>
622  Ptxt<Scheme>& addConstant(const Scalar& scalar)
623  {
624  return *this += scalar;
625  }
626 
632  template <typename T = Scheme,
633  typename Scalar,
634  typename std::enable_if_t<std::is_same<T, CKKS>::value>* = nullptr>
635  Ptxt<Scheme>& addConstantCKKS(const Scalar& scalar)
636  {
637  return *this += scalar;
638  }
639 
646  Ptxt<Scheme>& multiplyBy(const Ptxt<Scheme>& otherPtxt);
647 
654  Ptxt<Scheme>& multiplyBy2(const Ptxt& otherPtxt1, const Ptxt& otherPtxt2);
655 
660  Ptxt<Scheme>& square();
661 
666  Ptxt<Scheme>& cube();
667 
674  Ptxt<Scheme>& power(long e);
675 
682  Ptxt<Scheme>& rotate(long amount);
683 
690  Ptxt<Scheme>& rotate1D(long dim, long amount);
691 
698  Ptxt<Scheme>& shift(long amount);
699 
707  Ptxt<Scheme>& shift1D(long dim, long amount);
708 
716 
723  template <typename T = Scheme,
724  std::enable_if_t<std::is_same<T, BGV>::value>* = nullptr>
726 
732  Ptxt<Scheme>& replicate(long pos);
733 
741  std::vector<Ptxt<Scheme>> replicateAll() const;
742 
749  template <typename T = Scheme,
750  std::enable_if_t<std::is_same<T, CKKS>::value>* = nullptr>
752 
758  template <typename T = Scheme,
759  std::enable_if_t<std::is_same<T, CKKS>::value>* = nullptr>
761 
767  template <typename T = Scheme,
768  std::enable_if_t<std::is_same<T, CKKS>::value>* = nullptr>
770 
777 
784 
791 
798 
804 
805  // No docs as the four functions have been forward-declared with docs.
806  friend void deserialize<Scheme>(std::istream& is, Ptxt& ptxt);
807 
808  friend void serialize<Scheme>(std::ostream& os, const Ptxt& ptxt);
809 
810  friend std::istream& operator>><Scheme>(std::istream& is, Ptxt& ptxt);
811 
812  friend std::ostream& operator<<<Scheme>(std::ostream& os, const Ptxt& ptxt);
813 
820  static SlotType convertToSlot(const Context& context, long slot);
821 
827  Ptxt<Scheme>& cleanUp() { return *this; }
828 
829 private:
830  const Context* context;
831 
834  std::vector<SlotType> slots;
835 
845  long coordToIndex(const std::vector<long>& coords);
846 
856  std::vector<long> indexToCoord(long index);
857 
864  template <typename type>
865  typename type::RX slotsToRX() const;
866 
877  void assertSlotsCompatible(const std::vector<SlotType>& slots) const;
878 
888  template <typename type>
889  NTL::ZZX automorph_internal(long k);
890 };
891 } // namespace helib
892 
893 #endif // HELIB_PTXT_H
typename Scheme::SlotType SlotType
Alias for type to be stored in the slots.
Definition: Ptxt.h:292
An object that mimics the functionality of the Ctxt object, and acts as a convenient entry point for ...
Definition: Ptxt.h:280
void deserialize(std::istream &is, std::complex< double > &num)
Deserialize a std::complex<double> from the input stream is delimited by '[' and ']' (instead of the ...
Definition: Ptxt.cpp:19
Ptxt< Scheme > real() const
Extract the real part of a CKKS plaintext.
Ptxt< Scheme > & totalSums()
Compute the total sum (each slot contains the total sum of every slot).
Definition: Ptxt.cpp:812
Ptxt< Scheme > & operator=(Ptxt< Scheme > &&v) noexcept=default
Move assignment operator with other Ptxt.
Ptxt< Scheme > & random()
Populate slots with random data.
Definition: Ptxt.cpp:222
Ptxt< Scheme > & incrementalProduct()
Compute the incremental product (each slot is the product of the previous slots).
Definition: Ptxt.cpp:825
const std::vector< SlotType > & getSlotRepr() const
Get the data held in the slots as a std::vector<SlotType>.
Definition: Ptxt.cpp:230
Ptxt< Scheme > imag() const
Extract the imaginary part of a CKKS plaintext.
void clear()
Sets all slots to 0.
Definition: Ptxt.cpp:194
long lsize() const
Returns the size (number of slots) of a Ptxt as long.
Definition: Ptxt.cpp:143
Ptxt< Scheme > & frobeniusAutomorph(long j)
Apply the frobenius automorphism a(X) -> a(X^(p^j)) mod Phi_m(X).
Ptxt< Scheme > & replicate(long pos)
Replicate single slot across all slots.
Definition: Ptxt.cpp:742
Ptxt< Scheme > & rotate(long amount)
Rotate slots right by specified amount (slot i goes to slot i+1 mod size).
Definition: Ptxt.cpp:567
Ptxt< Scheme > & multiplyBy(const Ptxt< Scheme > &otherPtxt)
Multiplication function between two Ptxt objects.
Definition: Ptxt.cpp:471
Ptxt< Scheme > operator+(const Ptxt< Scheme > &rhs) const
Infix addition operator.
Definition: Ptxt.cpp:336
Type for BGV scheme, to be used as template parameter.
Definition: Ptxt.h:50
Ptxt< Scheme > & square()
Square operation on a Ptxt.
Definition: Ptxt.cpp:524
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:69
std::complex< double > SlotType
Slot type used for CKKS plaintexts: std::complex<double>.
Definition: Ptxt.h:43
Ptxt< Scheme > & rotate1D(long dim, long amount)
Rotate slots right by specified amount along a specific dimension.
Definition: Ptxt.cpp:583
Ptxt< Scheme > & power(long e)
Power operation to raise a Ptxt to an arbitrary non-negative power.
Definition: Ptxt.cpp:540
bool isValid() const
Check if a Ptxt is valid.
Definition: Ptxt.cpp:129
Ptxt< Scheme > & addConstantCKKS(const Scalar &scalar)
Add a constant to a CKKS Ptxt.
Definition: Ptxt.h:635
Ptxt< Scheme > & multiplyBy2(const Ptxt &otherPtxt1, const Ptxt &otherPtxt2)
Multiplication function between three Ptxt objects.
Definition: Ptxt.cpp:489
Type for CKKS scheme, to be used as template parameter.
Definition: Ptxt.h:39
Ptxt< Scheme > & complexConj()
Apply complex conjugate of complex numbers in slots of a CKKS Ptxt object.
Ptxt< Scheme > & addConstant(const Scalar &scalar)
Add a constant to a BGV Ptxt.
Definition: Ptxt.h:622
void serialize(std::ostream &os, const std::complex< double > &num)
Serialize a std::complex<double> to the output stream os delimited by '[' and ']' (instead of the def...
Definition: Ptxt.cpp:47
bool operator!=(const Ptxt< Scheme > &other) const
Not equals operator between two Ptxt objects.
Definition: Ptxt.cpp:313
Ptxt< Scheme > & automorph(long k)
Apply the automorphism a(X) -> a(X^k) mod Phi_m(X).
Ptxt(const Context &context, const NTL::ZZX &value)
BGV plaintext polynomial constructor, set all slots to the value polynomial.
SlotType & at(long i)
at accessor operator.
Definition: Ptxt.cpp:292
void setData(const NTL::ZZX &value)
Set the Ptxt data replicating the input polynomial on all slots.
Ptxt(Ptxt< Scheme > &&other) noexcept=default
Default move constructor.
Ptxt< Scheme > & shift1D(long dim, long amount)
Shift slots right in one dimension of the hypercube structure with 0 fill.
Definition: Ptxt.cpp:646
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:626
~Ptxt()=default
Default destructor.
Ptxt< Scheme > & operator-=(const Ptxt< Scheme > &otherPtxt)
Minus equals operator with another Ptxt.
Definition: Ptxt.cpp:430
void setData(const std::vector< SlotType > &data)
Set the data.
Definition: Ptxt.cpp:151
Ptxt< Scheme > & cleanUp()
To be inline with the Ctxt interface. However for Ptxt this means do nothing.
Definition: Ptxt.h:827
Ptxt< Scheme > & negate()
Negate a Ptxt.
Definition: Ptxt.cpp:460
Ptxt< Scheme > & cube()
Cube operation on a Ptxt.
Definition: Ptxt.cpp:532
Ptxt< Scheme > & runningSums()
Compute the running sum (each slot is the sum of the previous slots).
Definition: Ptxt.cpp:801
void innerProduct(Ctxt &result, const CtPtrs &v1, const CtPtrs &v2)
Definition: Ctxt.cpp:2318
static SlotType convertToSlot(const Context &context, long slot)
Conversion function from long to SlotType.
Definition: apiAttributes.h:21
Ptxt< Scheme > & mapTo01()
Map all non-zero slots to 1, keeping zero slots as zero.
Definition: Ptxt.cpp:849
Ptxt< Scheme > & operator+=(const Scalar &scalar)
Plus equals operator with a scalar.
Definition: Ptxt.h:566
Ptxt< Scheme > & operator+=(const Ptxt< Scheme > &otherPtxt)
Plus equals operator with another Ptxt.
Definition: Ptxt.cpp:400
Ptxt< Scheme > operator-(const Ptxt< Scheme > &rhs) const
Infix subtraction operator.
Definition: Ptxt.cpp:353
std::ostream & operator<<(std::ostream &s, const SKHandle &handle)
Definition: Ctxt.h:190
Ptxt< Scheme > & operator-=(const Scalar &scalar)
Minus equals operator with a scalar.
Definition: Ptxt.h:597
const Context & getContext() const
Returns the context used to initialize the Ptxt
Definition: Ptxt.h:392
std::vector< Ptxt< Scheme > > replicateAll() const
Generate a vector of plaintexts with each slot replicated in each plaintext.
Definition: Ptxt.cpp:752
Ptxt(const Ptxt< Scheme > &other)=default
Default copy constructor.
Ptxt< Scheme > & operator*=(const Scalar &scalar)
Times equals operator with a scalar.
Definition: Ptxt.h:535
Maintaining the parameters.
Definition: Context.h:121
NTL::ZZX getPolyRepr() const
Converts the slot data in this to its single polynomial representation.
Ptxt< Scheme > & operator*=(const Ptxt< Scheme > &otherPtxt)
Times equals operator with another Ptxt.
Definition: Ptxt.cpp:370
Ptxt< Scheme > operator*(const Ptxt< Scheme > &rhs) const
Infix multiplication operator.
Definition: Ptxt.cpp:319
An object that contains an NTL::ZZX polynomial along with a coefficient modulus p2r and a polynomial ...
Definition: PolyMod.h:47
Ptxt(const Context &context, const std::vector< T > &data)
Generic slot vector constructor.
Definition: Ptxt.h:337
std::istream & operator>>(std::istream &s, CtxtPart &p)
Definition: Ctxt.cpp:2206
SlotType & operator[](long i)
Square bracket accessor operator.
Definition: Ptxt.cpp:274
Ptxt()
Default constructor results in invalid Ptxt object which throws if used.
Definition: Ptxt.cpp:79
size_t size() const
Returns the size (number of slots) of a Ptxt.
Definition: Ptxt.cpp:135
Ptxt< Scheme > & operator=(const Ptxt< Scheme > &v)=default
Copy assignment operator with other Ptxt.
Ptxt< Scheme > & totalProduct()
Compute the total product (each slot contains the total product of every slot).
Definition: Ptxt.cpp:836
bool operator==(const Ptxt< Scheme > &other) const
Equals operator between two Ptxt objects.
Definition: Ptxt.cpp:306
void decodeSetData(const NTL::ZZX &data)
Set the Ptxt slots using values from decoding data to slot representation.