1212// See the License for the specific language governing permissions and
1313// limitations under the License.
1414
15+ public import AsyncAlgorithms
16+
1517/// Ciphertext type.
1618public struct Ciphertext < Scheme: HeScheme , Format: PolyFormat > : Equatable , Sendable {
1719 public typealias Scalar = Scheme . Scalar
@@ -28,7 +30,7 @@ public struct Ciphertext<Scheme: HeScheme, Format: PolyFormat>: Equatable, Senda
2830 ///
2931 /// After a fresh encryption, the ciphertext has ``HeScheme/freshCiphertextPolyCount`` polynomials.
3032 /// The count may change during the course of HE operations, e.g. increase during ciphertext multiplication,
31- /// or decrease during relinearization ``Ciphertext/relinearize(using:)``.
33+ /// or decrease during relinearization ``Ciphertext/relinearize(using:)-41bsm ``.
3234 public var polyCount : Int {
3335 polys. count
3436 }
@@ -314,7 +316,7 @@ public struct Ciphertext<Scheme: HeScheme, Format: PolyFormat>: Equatable, Senda
314316 ///
315317 /// If the ciphertext already has a single modulus, this is a no-op.
316318 /// - Throws: Error upon failure to modulus switch.
317- /// - seealso: ``Ciphertext/modSwitchDown()`` for more information and an alternative API.
319+ /// - seealso: ``Ciphertext/modSwitchDown()-4an2b `` for more information and an alternative API.
318320 @inlinable
319321 public mutating func modSwitchDownToSingle( ) throws where Format == Scheme . CanonicalCiphertextFormat {
320322 try Scheme . modSwitchDownToSingle ( & self )
@@ -535,22 +537,31 @@ extension Ciphertext where Format == Scheme.CanonicalCiphertextFormat {
535537}
536538
537539extension Collection {
540+ /// Sums together the ciphertexts in the collection.
541+ /// - Throws: Precondition failure if the collection is empty.
542+ /// - Returns: The sum.
538543 @inlinable
539- func sum< Scheme> ( ) throws -> Element where Element == Ciphertext < Scheme , Eval > {
544+ public func sum< Scheme> ( ) throws -> Element where Element == Ciphertext < Scheme , Eval > {
540545 precondition ( !isEmpty)
541546 // swiftlint:disable:next force_unwrapping
542547 return try dropFirst ( ) . reduce ( first!) { try $0 + $1 }
543548 }
544549
550+ /// Sums together the ciphertexts in the collection.
551+ /// - Throws: Precondition failure if the collection is empty.
552+ /// - Returns: The sum.
545553 @inlinable
546- func sum< Scheme> ( ) throws -> Element where Element == Ciphertext < Scheme , Coeff > {
554+ public func sum< Scheme> ( ) throws -> Element where Element == Ciphertext < Scheme , Coeff > {
547555 precondition ( !isEmpty)
548556 // swiftlint:disable:next force_unwrapping
549557 return try dropFirst ( ) . reduce ( first!) { try $0 + $1 }
550558 }
551559
560+ /// Sums together the ciphertexts in the collection.
561+ /// - Throws: Precondition failure if the collection is empty.
562+ /// - Returns: The sum.
552563 @inlinable
553- func sum< Scheme> ( ) throws -> Element where Element == Ciphertext < Scheme , Scheme . CanonicalCiphertextFormat > {
564+ public func sum< Scheme> ( ) throws -> Element where Element == Ciphertext < Scheme , Scheme . CanonicalCiphertextFormat > {
554565 precondition ( !isEmpty)
555566 // swiftlint:disable:next force_unwrapping
556567 return try dropFirst ( ) . reduce ( first!) { try $0 + $1 }
@@ -993,7 +1004,7 @@ extension Ciphertext {
9931004 ///
9941005 /// If the ciphertext already has a single modulus, this is a no-op.
9951006 /// - Throws: Error upon failure to modulus switch.
996- /// - seealso: ``Ciphertext/modSwitchDown()`` for more information and an alternative API.
1007+ /// - seealso: ``Ciphertext/modSwitchDown()-4an2b `` for more information and an alternative API.
9971008 @inlinable
9981009 public mutating func modSwitchDownToSingle( ) async throws where Format == Scheme . CanonicalCiphertextFormat {
9991010 try await Scheme . modSwitchDownToSingleAsync ( & self )
@@ -1024,3 +1035,80 @@ extension Ciphertext where Format == Scheme.CanonicalCiphertextFormat {
10241035 try await Scheme . relinearizeAsync ( & self , using: key)
10251036 }
10261037}
1038+
1039+ // MARK: - Async collection extensions
1040+
1041+ extension Collection {
1042+ /// Sums together the ciphertexts in the collection.
1043+ /// - Throws: Precondition failure if the collection is empty.
1044+ /// - Returns: The sum.
1045+ @inlinable
1046+ public func sum< Scheme> ( ) async throws -> Element where Element == Ciphertext < Scheme , Eval > {
1047+ precondition ( !isEmpty)
1048+ // swiftlint:disable:next force_unwrapping
1049+ return try await dropFirst ( ) . async . reduce ( first!) { try await $0 + $1 }
1050+ }
1051+
1052+ /// Sums together the ciphertexts in the collection.
1053+ /// - Throws: Precondition failure if the collection is empty.
1054+ /// - Returns: The sum.
1055+ @inlinable
1056+ public func sum< Scheme> ( ) async throws -> Element where Element == Ciphertext < Scheme , Coeff > {
1057+ precondition ( !isEmpty)
1058+ // swiftlint:disable:next force_unwrapping
1059+ return try await dropFirst ( ) . async . reduce ( first!) { try await $0 + $1 }
1060+ }
1061+
1062+ /// Sums together the ciphertexts in the collection.
1063+ /// - Throws: Precondition failure if the collection is empty.
1064+ /// - Returns: The sum.
1065+ @inlinable
1066+ public func sum< Scheme> ( ) async throws -> Element where
1067+ Element == Ciphertext < Scheme , Scheme . CanonicalCiphertextFormat >
1068+ {
1069+ precondition ( !isEmpty)
1070+ // swiftlint:disable:next force_unwrapping
1071+ return try await dropFirst ( ) . async . reduce ( first!) { try await $0 + $1 }
1072+ }
1073+
1074+ /// Asynchronously computes an inner product between self and a collection of (optional) plaintexts in ``Eval``
1075+ /// format.
1076+ ///
1077+ /// The inner product encrypts `sum_{i, plaintexts[i] != nil} self[i] * plaintexts[i]`. `plaintexts[i]`
1078+ /// may be `nil`, which denotes a zero plaintext.
1079+ /// - Parameter plaintexts: Plaintexts. Must not be empty and have `count` matching `self.count`.
1080+ /// - Returns: A ciphertext encrypting the inner product.
1081+ /// - Throws: Error upon failure to compute inner product.
1082+ @inlinable
1083+ public func innerProduct< Scheme> ( plaintexts: some Collection < Plaintext < Scheme , Eval > ? > ) async throws -> Element
1084+ where Element == Ciphertext < Scheme , Eval >
1085+ {
1086+ try await Scheme . innerProductAsync ( ciphertexts: self , plaintexts: plaintexts)
1087+ }
1088+
1089+ /// Asynchronously computes an inner product between self and a collection of plaintexts in ``Eval`` format.
1090+ ///
1091+ /// The inner product encrypts `sum_{i} self[i] * plaintexts[i]`.
1092+ /// - Parameter plaintexts: Plaintexts. Must not be empty and have `count` matching `self.count`.
1093+ /// - Returns: A ciphertext encrypting the inner product.
1094+ /// - Throws: Error upon failure to compute inner product.
1095+ @inlinable
1096+ public func innerProduct< Scheme> ( plaintexts: some Collection < Plaintext < Scheme , Eval > > ) async throws -> Element
1097+ where Element == Ciphertext < Scheme , Eval >
1098+ {
1099+ try await Scheme . innerProductAsync ( ciphertexts: self , plaintexts: plaintexts)
1100+ }
1101+
1102+ /// Asynchronously computes an inner product between self and another collection of ciphertexts.
1103+ ///
1104+ /// The inner product encrypts `sum_{i} self[i] * ciphertexts[i]`.
1105+ /// - Parameter ciphertexts: Ciphertexts. Must not be empty and have `count` matching `self.count`.
1106+ /// - Returns: A ciphertext encrypting the inner product.
1107+ /// - Throws: Error upon failure to compute inner product.
1108+ @inlinable
1109+ public func innerProduct< Scheme> ( ciphertexts: some Collection < Element > ) async throws -> Element
1110+ where Element == Ciphertext < Scheme , Scheme . CanonicalCiphertextFormat >
1111+ {
1112+ try await Scheme . innerProductAsync ( self , ciphertexts)
1113+ }
1114+ }
0 commit comments