Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up ciphertext add and subtract APIs #30

Merged
merged 1 commit into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions Sources/HomomorphicEncryption/Bfv/Bfv.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,23 @@ public enum Bfv<T: ScalarType>: HeScheme {
}

@inlinable
public static func addAssign<F: PolyFormat>(
public static func addAssignCoeff<F: PolyFormat>(
_ lhs: inout Ciphertext<Bfv<T>, F>,
_ rhs: Ciphertext<Bfv<T>, F>) throws
{
try addAssignSameType(&lhs, rhs)
}

@inlinable
public static func addAssignEval<F: PolyFormat>(
_ lhs: inout Ciphertext<Bfv<T>, F>,
_ rhs: Ciphertext<Bfv<T>, F>) throws
{
try addAssignSameType(&lhs, rhs)
}

@inlinable
public static func addAssignSameType<F: PolyFormat>(
_ lhs: inout Ciphertext<Bfv<T>, F>,
_ rhs: Ciphertext<Bfv<T>, F>) throws
{
Expand All @@ -47,7 +63,23 @@ public enum Bfv<T: ScalarType>: HeScheme {
}

@inlinable
public static func subAssign<F: PolyFormat>(
public static func subAssignCoeff<F: PolyFormat>(
_ lhs: inout Ciphertext<Bfv<T>, F>,
_ rhs: Ciphertext<Bfv<T>, F>) throws
{
try subAssignSameType(&lhs, rhs)
}

@inlinable
public static func subAssignEval<F: PolyFormat>(
_ lhs: inout Ciphertext<Bfv<T>, F>,
_ rhs: Ciphertext<Bfv<T>, F>) throws
{
try subAssignSameType(&lhs, rhs)
}

@inlinable
static func subAssignSameType<F: PolyFormat>(
_ lhs: inout Ciphertext<Bfv<T>, F>,
_ rhs: Ciphertext<Bfv<T>, F>) throws
{
Expand Down
112 changes: 5 additions & 107 deletions Sources/HomomorphicEncryption/Ciphertext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,35 +46,15 @@ public struct Ciphertext<Scheme: HeScheme, Format: PolyFormat>: Equatable, Senda
// MARK: ciphertext += ciphertext

@inlinable
public static func += (lhs: inout Ciphertext<Scheme, Format>, rhs: Ciphertext<Scheme, Format>) throws
where Format == Coeff
{
try Scheme.validateEquality(of: lhs.context, and: rhs.context)
try Scheme.addAssign(&lhs, rhs)
}

@inlinable
public static func += (lhs: inout Ciphertext<Scheme, Format>, rhs: Ciphertext<Scheme, Format>) throws
where Format == Eval
{
try Scheme.validateEquality(of: lhs.context, and: rhs.context)
try Scheme.addAssign(&lhs, rhs)
}

@inlinable
public static func += (lhs: inout Ciphertext<Scheme, Format>, rhs: Ciphertext<Scheme, Format>) throws
where Format == Scheme.CanonicalCiphertextFormat
{
public static func += (lhs: inout Ciphertext<Scheme, Format>, rhs: Ciphertext<Scheme, some PolyFormat>) throws {
try Scheme.validateEquality(of: lhs.context, and: rhs.context)
try Scheme.addAssign(&lhs, rhs)
}

// MARK: ciphertext -= ciphertext

@inlinable
public static func -= (lhs: inout Ciphertext<Scheme, Format>, rhs: Ciphertext<Scheme, Format>) throws
where Format == Scheme.CanonicalCiphertextFormat
{
public static func -= (lhs: inout Ciphertext<Scheme, Format>, rhs: Ciphertext<Scheme, some PolyFormat>) throws {
try Scheme.validateEquality(of: lhs.context, and: rhs.context)
try Scheme.subAssign(&lhs, rhs)
}
Expand All @@ -90,24 +70,6 @@ public struct Ciphertext<Scheme: HeScheme, Format: PolyFormat>: Equatable, Senda
try Scheme.subAssign(&ciphertext, plaintext)
}

// MARK: ciphertext -= ciphertext

@inlinable
public static func -= (lhs: inout Ciphertext<Scheme, Format>, rhs: Ciphertext<Scheme, Format>) throws
where Format == Coeff
{
try Scheme.validateEquality(of: lhs.context, and: rhs.context)
try Scheme.subAssign(&lhs, rhs)
}

@inlinable
public static func -= (lhs: inout Ciphertext<Scheme, Format>, rhs: Ciphertext<Scheme, Format>) throws
where Format == Eval
{
try Scheme.validateEquality(of: lhs.context, and: rhs.context)
try Scheme.subAssign(&lhs, rhs)
}

// MARK: ciphertext *= plaintext

@inlinable
Expand Down Expand Up @@ -347,7 +309,7 @@ public struct Ciphertext<Scheme: HeScheme, Format: PolyFormat>: Equatable, Senda
/// - Warning: The ciphertext must have at least ``HeScheme/minNoiseBudget`` noise to ensure accurate decryption.
/// - seealso: The noise budget can be computed using
/// ``HeScheme/noiseBudget(of:using:variableTime:)-5p5m0``.
/// - seealso: ``HeScheme/decrypt(_:using:)-32dcy`` for an alternative API.
/// - seealso: ``HeScheme/decrypt(_:using:)`` for an alternative API.
@inlinable
public func decrypt(using secretKey: SecretKey<Scheme>) throws -> Scheme.CoeffPlaintext {
try Scheme.decrypt(self, using: secretKey)
Expand Down Expand Up @@ -481,39 +443,7 @@ extension Ciphertext {
/// - Returns: A ciphertext encrypting the sum `lhs + rhs'.
/// - Throws: Error upon failure to add.
@inlinable
public static func + (lhs: Ciphertext<Scheme, Format>, rhs: Ciphertext<Scheme, Format>) throws -> Self
where Format == Coeff
{
var result = lhs
try result += rhs
return result
}

/// Ciphertext addition.
/// - Parameters:
/// - lhs: Ciphertext to add.
/// - rhs: Plaintext to add.
/// - Returns: A ciphertext encrypting the sum `lhs + rhs'.
/// - Throws: Error upon failure to add.
@inlinable
public static func + (lhs: Ciphertext<Scheme, Format>, rhs: Ciphertext<Scheme, Format>) throws -> Self
where Format == Eval
{
var result = lhs
try result += rhs
return result
}

/// Ciphertext addition.
/// - Parameters:
/// - lhs: Ciphertext to add.
/// - rhs: Plaintext to add.
/// - Returns: A ciphertext encrypting the sum `lhs + rhs'.
/// - Throws: Error upon failure to add.
@inlinable
public static func + (lhs: Ciphertext<Scheme, Format>, rhs: Ciphertext<Scheme, Format>) throws -> Self
where Format == Scheme.CanonicalCiphertextFormat
{
public static func + (lhs: Ciphertext<Scheme, Format>, rhs: Ciphertext<Scheme, some PolyFormat>) throws -> Self {
var result = lhs
try result += rhs
return result
Expand All @@ -528,39 +458,7 @@ extension Ciphertext {
/// - Returns: A ciphertext encrypting the difference `lhs - rhs'.
/// - Throws: Error upon failure to subtract.
@inlinable
public static func - (lhs: Ciphertext<Scheme, Format>, rhs: Ciphertext<Scheme, Format>) throws -> Self
where Format == Coeff
{
var result = lhs
try result -= rhs
return result
}

/// Ciphertext subtraction.
/// - Parameters:
/// - lhs: Ciphertext to subtract from.
/// - rhs: Ciphertext to subtract.
/// - Returns: A ciphertext encrypting the difference `lhs - rhs'.
/// - Throws: Error upon failure to subtract.
@inlinable
public static func - (lhs: Ciphertext<Scheme, Format>, rhs: Ciphertext<Scheme, Format>) throws -> Self
where Format == Eval
{
var result = lhs
try result -= rhs
return result
}

/// Ciphertext subtraction.
/// - Parameters:
/// - lhs: Ciphertext to subtract from.
/// - rhs: Ciphertext to subtract.
/// - Returns: A ciphertext encrypting the difference `lhs - rhs'.
/// - Throws: Error upon failure to subtract.
@inlinable
public static func - (lhs: Ciphertext<Scheme, Format>, rhs: Ciphertext<Scheme, Format>) throws -> Self
where Format == Scheme.CanonicalCiphertextFormat
{
public static func - (lhs: Ciphertext<Scheme, Format>, rhs: Ciphertext<Scheme, some PolyFormat>) throws -> Self {
var result = lhs
try result -= rhs
return result
Expand Down
86 changes: 77 additions & 9 deletions Sources/HomomorphicEncryption/HeScheme.swift
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ public protocol HeScheme {
/// - Warning: The ciphertext must have at least ``HeScheme/minNoiseBudget`` noise to ensure accurate decryption.
/// - seealso: The noise budget can be computed using
/// ``HeScheme/noiseBudget(of:using:variableTime:)-143f3``.
/// - seealso: ``Ciphertext/decrypt(using:)-4n5b2`` for an alternative API.
/// - seealso: ``Ciphertext/decrypt(using:)`` for an alternative API.
static func decryptCoeff(_ ciphertext: CoeffCiphertext, using secretKey: SecretKey) throws -> CoeffPlaintext

/// Decryption of a ciphertext in evaluation format.
Expand All @@ -285,7 +285,7 @@ public protocol HeScheme {
/// - Warning: The ciphertext must have at least ``HeScheme/minNoiseBudget`` noise to ensure accurate decryption.
/// - seealso: The noise budget can be computed using
/// ``HeScheme/noiseBudget(of:using:variableTime:)-7vpza``.
/// - seealso: ``Ciphertext/decrypt(using:)-62y2c`` for an alternative API.
/// - seealso: ``Ciphertext/decrypt(using:)`` for an alternative API.
static func decryptEval(_ ciphertext: EvalCiphertext, using secretKey: SecretKey) throws -> CoeffPlaintext

/// Rotates the columns of a ciphertext.
Expand Down Expand Up @@ -353,29 +353,29 @@ public protocol HeScheme {
/// - lhs: Ciphertext to add; will store the sum.
/// - rhs: Ciphertext to add.
/// - Throws: Error upon failure to add.
static func addAssign(_ lhs: inout CoeffCiphertext, _ rhs: CoeffCiphertext) throws
static func addAssignCoeff(_ lhs: inout CoeffCiphertext, _ rhs: CoeffCiphertext) throws

/// In-place ciphertext addition: `lhs += rhs`.
/// - Parameters:
/// - lhs: Ciphertext to add; will store the sum.
/// - rhs: Ciphertext to add.
/// - Throws: Error upon failure to add.
static func addAssign(_ lhs: inout EvalCiphertext, _ rhs: EvalCiphertext) throws
static func addAssignEval(_ lhs: inout EvalCiphertext, _ rhs: EvalCiphertext) throws

/// In-place ciphertext subtraction: `lhs -= rhs`.
/// - Parameters:
/// - lhs: Ciphertext to subtract from; will store the difference.
/// - rhs: Ciphertext to subtract.
/// - Throws: Error upon failure to subtract.
static func subAssign(_ lhs: inout CoeffCiphertext, _ rhs: CoeffCiphertext) throws
static func subAssignCoeff(_ lhs: inout CoeffCiphertext, _ rhs: CoeffCiphertext) throws

/// In-place ciphertext subtraction: `lhs -= rhs`.
///
/// - Parameters:
/// - lhs: Ciphertext to subtract from; will store the difference.
/// - rhs: Ciphertext to subtract.
/// - Throws: Error upon failure to subtract.
static func subAssign(_ lhs: inout EvalCiphertext, _ rhs: EvalCiphertext) throws
static func subAssignEval(_ lhs: inout EvalCiphertext, _ rhs: EvalCiphertext) throws

/// In-place ciphertext-plaintext addition: `ciphertext += plaintext`.
///
Expand Down Expand Up @@ -663,7 +663,7 @@ extension HeScheme {
/// - Warning: The ciphertext must have at least ``HeScheme/minNoiseBudget`` noise to ensure accurate decryption.
/// - seealso: The noise budget can be computed using
/// ``HeScheme/noiseBudget(of:using:variableTime:)-5p5m0``.
/// - seealso: ``Ciphertext/decrypt(using:)-9qn9g`` for an alternative API.
/// - seealso: ``Ciphertext/decrypt(using:)`` for an alternative API.
@inlinable
public static func decrypt<Format: PolyFormat>(_ ciphertext: Ciphertext<Self, Format>,
using secretKey: SecretKey) throws -> CoeffPlaintext
Expand Down Expand Up @@ -692,7 +692,7 @@ extension HeScheme {
{
// swiftlint:disable force_cast
if CiphertextFormat.self == Coeff.self {
var coeffCiphertext = ciphertext as! Ciphertext<Self, Coeff>
var coeffCiphertext = ciphertext as! CoeffCiphertext
if PlaintextFormat.self == Coeff.self {
try addAssignCoeff(&coeffCiphertext, plaintext as! CoeffPlaintext)
} else if PlaintextFormat.self == Eval.self {
Expand All @@ -702,7 +702,7 @@ extension HeScheme {
}
ciphertext = coeffCiphertext as! Ciphertext<Self, CiphertextFormat>
} else if CiphertextFormat.self == Eval.self {
var evalCiphertext = ciphertext as! Ciphertext<Self, Eval>
var evalCiphertext = ciphertext as! EvalCiphertext
if PlaintextFormat.self == Coeff.self {
try addAssignEvalCoeff(&evalCiphertext, plaintext as! CoeffPlaintext)
} else if PlaintextFormat.self == Eval.self {
Expand All @@ -717,6 +717,40 @@ extension HeScheme {
// swiftlint:enable force_cast
}

/// In-place ciphertext addition: `lhs += rhs`.
///
/// - Parameters:
/// - lhs: Ciphertext to add; will store the sum.
/// - rhs: Ciphertext to add.
/// - Throws: Error upon failure to add.
@inlinable
public static func addAssign<LhsFormat: PolyFormat, RhsFormat: PolyFormat>(
_ lhs: inout Ciphertext<Self, LhsFormat>,
_ rhs: Ciphertext<Self, RhsFormat>) throws
{
// swiftlint:disable force_cast
if LhsFormat.self == Coeff.self {
var lhsCoeffCiphertext = lhs as! CoeffCiphertext
if RhsFormat.self == Coeff.self {
try addAssignCoeff(&lhsCoeffCiphertext, rhs as! CoeffCiphertext)
} else {
fatalError("Unsupported Format \(RhsFormat.description)")
}
lhs = lhsCoeffCiphertext as! Ciphertext<Self, LhsFormat>
} else if LhsFormat.self == Eval.self {
var lhsEvalCiphertext = lhs as! EvalCiphertext
if RhsFormat.self == Eval.self {
try addAssignEval(&lhsEvalCiphertext, rhs as! EvalCiphertext)
} else {
fatalError("Unsupported Format \(RhsFormat.description)")
}
lhs = lhsEvalCiphertext as! Ciphertext<Self, LhsFormat>
} else {
fatalError("Unsupported Format \(LhsFormat.description)")
}
// swiftlint:enable force_cast
}

/// In-place ciphertext-plaintext subtraction: `ciphertext -= plaintext`.
///
/// - Parameters:
Expand Down Expand Up @@ -754,6 +788,40 @@ extension HeScheme {
}
// swiftlint:enable force_cast
}

/// In-place ciphertext subtraction: `lhs -= rhs`.
///
/// - Parameters:
/// - lhs: Ciphertext to subtract from; will store the difference.
/// - rhs: Ciphertext to subtract.
/// - Throws: Error upon failure to subtract.
@inlinable
public static func subAssign<LhsFormat: PolyFormat, RhsFormat: PolyFormat>(
_ lhs: inout Ciphertext<Self, LhsFormat>,
_ rhs: Ciphertext<Self, RhsFormat>) throws
{
// swiftlint:disable force_cast
if LhsFormat.self == Coeff.self {
var lhsCoeffCiphertext = lhs as! CoeffCiphertext
if RhsFormat.self == Coeff.self {
try subAssignCoeff(&lhsCoeffCiphertext, rhs as! CoeffCiphertext)
} else {
fatalError("Unsupported Format \(RhsFormat.description)")
}
lhs = lhsCoeffCiphertext as! Ciphertext<Self, LhsFormat>
} else if LhsFormat.self == Eval.self {
var lhsEvalCiphertext = lhs as! EvalCiphertext
if RhsFormat.self == Eval.self {
try subAssignEval(&lhsEvalCiphertext, rhs as! EvalCiphertext)
} else {
fatalError("Unsupported Format \(RhsFormat.description)")
}
lhs = lhsEvalCiphertext as! Ciphertext<Self, LhsFormat>
} else {
fatalError("Unsupported Format \(LhsFormat.description)")
}
// swiftlint:enable force_cast
}
}

extension HeScheme {
Expand Down
8 changes: 4 additions & 4 deletions Sources/HomomorphicEncryption/NoOpScheme.swift
Original file line number Diff line number Diff line change
Expand Up @@ -189,24 +189,24 @@ public enum NoOpScheme: HeScheme {

// MARK: ciphertext += ciphertext

public static func addAssign(_ lhs: inout CoeffCiphertext, _ rhs: CoeffCiphertext) throws {
public static func addAssignCoeff(_ lhs: inout CoeffCiphertext, _ rhs: CoeffCiphertext) throws {
try validateEquality(of: lhs.context, and: rhs.context)
lhs.polys[0] += rhs.polys[0]
}

public static func addAssign(_ lhs: inout EvalCiphertext, _ rhs: EvalCiphertext) throws {
public static func addAssignEval(_ lhs: inout EvalCiphertext, _ rhs: EvalCiphertext) throws {
try validateEquality(of: lhs.context, and: rhs.context)
lhs.polys[0] += rhs.polys[0]
}

// MARK: ciphertext -= ciphertext

public static func subAssign(_ lhs: inout CoeffCiphertext, _ rhs: CoeffCiphertext) throws {
public static func subAssignCoeff(_ lhs: inout CoeffCiphertext, _ rhs: CoeffCiphertext) throws {
try validateEquality(of: lhs.context, and: rhs.context)
lhs.polys[0] -= rhs.polys[0]
}

public static func subAssign(_ lhs: inout EvalCiphertext, _ rhs: EvalCiphertext) throws {
public static func subAssignEval(_ lhs: inout EvalCiphertext, _ rhs: EvalCiphertext) throws {
try validateEquality(of: lhs.context, and: rhs.context)
lhs.polys[0] -= rhs.polys[0]
}
Expand Down
Loading