OpenFHE 使用样例

参考文献:

  • 编译 OpenFHE
  • OpenFHE 源码解析:PKE 部分
  • [ABB+22] Al Badawi A, Bates J, Bergamaschi F, et al. Openfhe: Open-source fully homomorphic encryption library[C]//Proceedings of the 10th Workshop on Encrypted Computing & Applied Homomorphic Cryptography. 2022: 53-63.

VSCode 的配置

编辑器

c_cpp_properties.json 如下:

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**",
                "/usr/local/include/openfhe/pke",
                "/usr/local/include/openfhe/core",
                "/usr/local/include/openfhe",
                "/usr/local/include/openfhe/binfhe"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c17",
            "cppStandard": "c++14",
            "intelliSenseMode": "macos-gcc-x64"
        }
    ],
    "version": 4
}

调试器

tasks.json 如下:

{
    "tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: gcc 生成活动文件",
            "command": "/usr/bin/gcc",
            "args": [
                "-fdiagnostics-color=always",
                "-g",
                "${file}",
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}",
                "-I/usr/local/include/openfhe",
                "-I/usr/local/include/openfhe/pke",
                "-I/usr/local/include/openfhe/core",
                "-I/usr/local/include/openfhe/binfhe",
                "-I/usr/local/include/openfhe/cereal",
                "-L/usr/local/lib",
                "-lOPENFHEcore",
                "-lOPENFHEpke",
                "-lOPENFHEbinfhe",
                "-lssl",
                "-lntl",
                "-lgmp",
                "-lgf2x",
                "-lstdc++",
                "-lm",
                "-fopenmp",
                "-fPIC",
                "-Wl,--copy-dt-needed-entries"
            ],
            "options": {
                "cwd": "${fileDirname}"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "调试器生成的任务。"
        }
    ],
    "version": "2.0.0"
}

GCC 的配置

CMakeLists.txt 如下:

cmake_minimum_required(VERSION 3.10)

project(MyCode CXX)

set(CMAKE_CXX_COMPILER "g++")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

#配置编译选项
add_compile_options(
    -march=native -O3 
    -lstdc++ -lm -lssl -lgmp -lntl -pthread -fopenmp -fPIC
    -mavx2 -mno-avx256-split-unaligned-load -mno-avx256-split-unaligned-store
    -Wno-unused-command-line-argument -Wwrite-strings -v
)

#配置头文件和静态库的路径
add_compile_options(
    -I/usr/local/include/openfhe
    -I/usr/local/include/openfhe/core
    -I/usr/local/include/openfhe/pke
    -I/usr/local/include/openfhe/binfhe
    -I/usr/local/include/openfhe/cereal
    -L/usr/local/lib
)

#SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
#SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib/)

set(CMAKE_EXE_LINKER_FLAGS "-Wl,--copy-dt-needed-entries") #递归获取动态库的依赖项

add_executable(use_ckks use_ckks.cpp)
target_link_libraries(use_ckks OPENFHEcore OPENFHEpke OPENFHEbinfhe)

add_executable(use_bgv use_bgv.cpp)
target_link_libraries(use_bgv OPENFHEcore OPENFHEpke OPENFHEbinfhe)

add_executable(use_bfv use_bfv.cpp)
target_link_libraries(use_bfv OPENFHEcore OPENFHEpke OPENFHEbinfhe)

BFV

代码

BFV 方案使用 MSD 纠错码,不需要模切换。在 Ciphertext<DCRTPoly> 密文中,GetLevel() 总是等于 0 0 0GetNoiseScaleDeg() 记录了乘法深度GetElements().size() 是密文中环元素向量的长度。

对于 CoefPackedPlaintext 打包,明文模数可以是任意的整数,不仅仅是素数或者素数幂。

系数打包的 BFV 用例,

#include <vector>
#include <iostream>
#include "openfhe.h"
#include "cputimer.h"

using namespace std;
using namespace lbcrypto;

#define endl2 endl << endl
#define pn puts("")

#define print_param(ct)                                         \
    cout << "Level = " << ct->GetLevel() << " | "               \
         << "Depth = " << ct->GetNoiseScaleDeg() << " | "       \
         << "SKDeg = " << ct->GetElements().size() - 1 << " | " \
         << endl;

#define print_pt(pt) \
    cout << "Result: " << pt << endl2;

int main()
{
    GetFrequency();
    cout << endl;

    size_t ringDim = 16384;       // 必须是二的幂次
    size_t plaintextModulus = 17; // 系数打包可以是任意整数
    size_t multDepth = 10;
    size_t maxRelinSkDeg = 4;

    CCParams<CryptoContextBFVRNS> parameters;
    parameters.SetSecurityLevel(HEStd_NotSet); // 如果不设置安全级别,则需要手动给出环维度
    parameters.SetRingDim(ringDim);
    parameters.SetPlaintextModulus(plaintextModulus);
    parameters.SetMultiplicativeDepth(multDepth);
    parameters.SetMaxRelinSkDeg(maxRelinSkDeg);
    parameters.SetKeySwitchTechnique(HYBRID);

    // BEHZ,整数指令的 RNS 扩展,乘法速度很慢
    // HPSPOVERQLEVELED,浮点指令的 RNS 扩展,并且隐式模切换
    parameters.SetMultiplicationTechnique(HPSPOVERQLEVELED);

    CryptoContext<DCRTPoly> cc = GenCryptoContext(parameters);
    cc->Enable(PKE);
    cc->Enable(KEYSWITCH);
    cc->Enable(LEVELEDSHE);

    cout << "CyclotomicOrder = " << cc->GetCyclotomicOrder() << endl
         << "RingDimension = " << cc->GetRingDimension() << endl
         << "Level = " << cc->GetKeyGenLevel() << endl
         << "Modulus = " << cc->GetModulus() << endl
         << "ModulusBits = " << cc->GetModulus().GetLengthForBase(2) << endl
         << "RootOfUnity = " << cc->GetRootOfUnity() << endl
         << "PlaintextModulus = " << cc->GetEncodingParams()->GetPlaintextModulus() << endl
         << "BatchSize = " << cc->GetEncodingParams()->GetBatchSize() << endl
         << "PlaintextGenerator = " << cc->GetEncodingParams()->GetPlaintextGenerator() << endl
         << endl2;

    /***************************************************************************************************/

    auto keys = cc->KeyGen();
    cc->EvalMultKeysGen(keys.secretKey);
    cc->EvalRotateKeyGen(keys.secretKey, {1, -2});

    // 生成元 g = 5 mod N, ord(g) = N/2
    map<usint, EvalKey<DCRTPoly>> evk_map = *cc->EvalAutomorphismKeyGen(keys.secretKey, {1u, 5u, 25u});

    vector<int64_t> x1 = {1, 2, 3, 4, 5, 6, 7, 8};
    vector<int64_t> x2 = {1, 0, 0, 0, 0, 0, 0, -1};
    Plaintext pt1 = cc->MakeCoefPackedPlaintext(x1);
    Plaintext pt2 = cc->MakeCoefPackedPlaintext(x2);

    print_pt(pt1);
    print_pt(pt2);

    /***************************************************************************************************/

    auto ct1 = cc->Encrypt(keys.publicKey, pt1);
    auto ct2 = cc->Encrypt(keys.publicKey, pt2);

    Plaintext pt;
    print_param(ct1);
    pn;

    cc->Decrypt(keys.secretKey, ct1, &pt);
    print_pt(pt);

    cc->Decrypt(keys.secretKey, ct2, &pt);
    print_pt(pt);

    Ciphertext<DCRTPoly> ct;
    cout.precision(8);

    /***************************************************************************************************/

    Timer("+", ct = ct1 + ct2;); // 比 cc->EvalAdd 要快
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Add #1", ct = cc->EvalAdd(ct1, ct2);); // 首先会 type 检查
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Scale", ct = cc->EvalMult(ct, cc->MakeCoefPackedPlaintext({0, 2}));); // 必须把 scale 先构造为 Plaintext
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Add #2", ct = cc->EvalAdd(ct, ct2);); // 相同 Level 不同 ScalingFactorInt 的加法,正确
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    /***************************************************************************************************/

    Timer("*", ct = ct1 * ct2;); // 和 cc->EvalMult 一样,但是不检查 type
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Mult", ct = cc->EvalMult(ct1, ct2);); // 总是自动密钥切换,和 cc->EvalMultAndRelinearize 完全一样
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Add #3", ct = cc->EvalAdd(ct, ct2);); // 不同 Level 不同 ScalingFactorInt 的加法,正确
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Mult And Relinearize", ct = cc->EvalMultAndRelinearize(ct1, ct2);); // 和 cc->EvalMult 基本一样
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    /***************************************************************************************************/

    Timer("Mult No Relin #1", ct = cc->EvalMultNoRelin(ct1, ct2);); // 这个才是不做密钥切换的,SKDeg 增长
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Mult No Relin #2", ct = cc->EvalMultNoRelin(ct, ct2);); // 不同 ScalingFactor 不同 Level 的乘法,正确
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Relinear", cc->RelinearizeInPlace(ct);); // 占据几乎全部的时间
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    /***************************************************************************************************/

    Timer("Rotate(1)", ct = cc->EvalRotate(ct1, 1);); // 正数是左旋
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Rotate(-2)", ct = cc->EvalRotate(ct1, -2);); // 负数是右旋
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    /***************************************************************************************************/

    Timer("Automorphism(1)", ct = cc->EvalAutomorphism(ct1, 1, evk_map);); // 不旋转
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Automorphism(5)", ct = cc->EvalAutomorphism(ct1, 5, evk_map);); // 数量 N 的明文槽,由 (-5) 生成
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Automorphism(25)", ct = cc->EvalAutomorphism(ct1, 25, evk_map);); // 5^2 mod N
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    /***************************************************************************************************/

    return 0;
}

结果

使用 BEHZ 乘法

CPU Frequency = 2918913687

CyclotomicOrder = 2048
RingDimension = 1024
Level = 0
Modulus = 1532495540865662914854395520533418584588770550682052609
ModulusBits = 180
RootOfUnity = 0
PlaintextModulus = 17
BatchSize = 1024
PlaintextGenerator = 0


Result: ( 1 2 3 4 5 6 7 8 ... )

Result: ( 1 0 0 0 0 0 0 -1 ... )

Level = 0 | Depth = 1 | SKDeg = 1 | 

Result: ( 1 2 3 4 5 6 7 8 ... )

Result: ( 1 0 0 0 0 0 0 -1 ... )

Running Time of <+>:         99032 cycles (  0.033928 ms)
Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 2 2 3 4 5 6 7 7 ... )

Running Time of <Add #1>:          2736272 cycles (  0.937428 ms)
Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 2 2 3 4 5 6 7 7 ... )

Running Time of <Scale>:           2735077 cycles (  0.937019 ms)
Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 0 4 4 6 8 -7 -5 -3 -3 ... )

Running Time of <Add #2>:          1133253 cycles (  0.388245 ms)
Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 1 4 4 6 8 -7 -5 -4 -3 ... )

Running Time of <*>:     253469802 cycles ( 86.837032 ms)
Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 1 2 3 4 5 6 7 7 -2 -3 -4 -5 -6 -7 -8 ... )

Running Time of <Mult>:  187670910 cycles ( 64.294779 ms)
Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 1 2 3 4 5 6 7 7 -2 -3 -4 -5 -6 -7 -8 ... )

Running Time of <Add #3>:           435927 cycles (  0.149346 ms)
Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 2 2 3 4 5 6 7 6 -2 -3 -4 -5 -6 -7 -8 ... )

Running Time of <Mult And Relinearize>:  126839959 cycles ( 43.454508 ms)
Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 1 2 3 4 5 6 7 7 -2 -3 -4 -5 -6 -7 -8 ... )

Running Time of <Mult No Relin #1>:      130843571 cycles ( 44.826119 ms)
Level = 0 | Depth = 2 | SKDeg = 2 | 
Result: ( 1 2 3 4 5 6 7 7 -2 -3 -4 -5 -6 -7 -8 ... )

Running Time of <Mult No Relin #2>:      172007707 cycles ( 58.928672 ms)
Level = 0 | Depth = 3 | SKDeg = 3 | 
Result: ( 1 2 3 4 5 6 7 6 -4 -6 -8 7 5 3 2 2 3 4 5 6 7 8 ... )

Running Time of <Relinear>:      208823169 cycles ( 71.541399 ms)
Level = 0 | Depth = 3 | SKDeg = 1 | 
Result: ( 1 2 3 4 5 6 7 6 -4 -6 -8 7 5 3 2 2 3 4 5 6 7 8 ... )

Running Time of <Rotate(1)>:     115388270 cycles ( 39.531237 ms)
Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 1 0 0 0 0 2 0 0 0 0 3 0 0 0 0 4 0 0 0 0 5 0 0 0 0 6 0 0 0 0 7 0 0 0 0 8 ... )

Running Time of <Rotate(-2)>:     70254530 cycles ( 24.068725 ms)
Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -8 ... )

Running Time of <Automorphism(1)>:        83246053 cycles ( 28.519532 ms)
Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 1 2 3 4 5 6 7 8 ... )

Running Time of <Automorphism(5)>:        74563676 cycles ( 25.545009 ms)
Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 1 0 0 0 0 2 0 0 0 0 3 0 0 0 0 4 0 0 0 0 5 0 0 0 0 6 0 0 0 0 7 0 0 0 0 8 ... )

Running Time of <Automorphism(25)>:       67644689 cycles ( 23.174611 ms)
Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 ... )

使用 HPSPOVERQLEVELED 乘法

CPU Frequency = 2918959071

CyclotomicOrder = 2048
RingDimension = 1024
Level = 0
Modulus = 1532495540865662914854395520533418584588770550682052609
ModulusBits = 180
RootOfUnity = 0
PlaintextModulus = 17
BatchSize = 1024
PlaintextGenerator = 0


Result: ( 1 2 3 4 5 6 7 8 ... )

Result: ( 1 0 0 0 0 0 0 -1 ... )

Level = 0 | Depth = 1 | SKDeg = 1 | 

Result: ( 1 2 3 4 5 6 7 8 ... )

Result: ( 1 0 0 0 0 0 0 -1 ... )

Running Time of <+>:        115828 cycles (  0.039681 ms)
Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 2 2 3 4 5 6 7 7 ... )

Running Time of <Add #1>:          4293174 cycles (  1.470789 ms)
Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 2 2 3 4 5 6 7 7 ... )

Running Time of <Scale>:            894332 cycles (  0.306387 ms)
Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 0 4 4 6 8 -7 -5 -3 -3 ... )

Running Time of <Add #2>:           987738 cycles (  0.338387 ms)
Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 1 4 4 6 8 -7 -5 -4 -3 ... )

Running Time of <*>:     236847696 cycles ( 81.141150 ms)
Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 1 2 3 4 5 6 7 7 -2 -3 -4 -5 -6 -7 -8 ... )

Running Time of <Mult>:  162997593 cycles ( 55.841000 ms)
Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 1 2 3 4 5 6 7 7 -2 -3 -4 -5 -6 -7 -8 ... )

Running Time of <Add #3>:           311286 cycles (  0.106643 ms)
Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 2 2 3 4 5 6 7 6 -2 -3 -4 -5 -6 -7 -8 ... )

Running Time of <Mult And Relinearize>:  152945198 cycles ( 52.397171 ms)
Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 1 2 3 4 5 6 7 7 -2 -3 -4 -5 -6 -7 -8 ... )

Running Time of <Mult No Relin #1>:      108039418 cycles ( 37.012995 ms)
Level = 0 | Depth = 2 | SKDeg = 2 | 
Result: ( 1 2 3 4 5 6 7 7 -2 -3 -4 -5 -6 -7 -8 ... )

Running Time of <Mult No Relin #2>:      183090958 cycles ( 62.724743 ms)
Level = 0 | Depth = 3 | SKDeg = 3 | 
Result: ( 1 2 3 4 5 6 7 6 -4 -6 -8 7 5 3 2 2 3 4 5 6 7 8 ... )

Running Time of <Relinear>:      116302449 cycles ( 39.843809 ms)
Level = 0 | Depth = 3 | SKDeg = 1 | 
Result: ( 1 2 3 4 5 6 7 6 -4 -6 -8 7 5 3 2 2 3 4 5 6 7 8 ... )

Running Time of <Rotate(1)>:      88811197 cycles ( 30.425640 ms)
Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 1 0 0 0 0 2 0 0 0 0 3 0 0 0 0 4 0 0 0 0 5 0 0 0 0 6 0 0 0 0 7 0 0 0 0 8 ... )

Running Time of <Rotate(-2)>:     87308745 cycles ( 29.910918 ms)
Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -8 ... )

Running Time of <Automorphism(1)>:        87723653 cycles ( 30.053060 ms)
Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 1 2 3 4 5 6 7 8 ... )

Running Time of <Automorphism(5)>:        97097626 cycles ( 33.264470 ms)
Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 1 0 0 0 0 2 0 0 0 0 3 0 0 0 0 4 0 0 0 0 5 0 0 0 0 6 0 0 0 0 7 0 0 0 0 8 ... )

Running Time of <Automorphism(25)>:       80256150 cycles ( 27.494784 ms)
Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 ... )

BGV

代码

BGV 方案使用 LSD 纠错码,需要模切换。在 Ciphertext<DCRTPoly> 密文中,GetScalingFactorInt() 记录了扭曲因子GetLevel() 记录了乘法深度GetNoiseScaleDeg() 记录了扭曲因子的指数GetElements().size() 是密文中环元素向量的长度。

对于 PackedPlaintext 打包,明文模数必须是满足 NTT 的大素数,槽旋转对应的自同构指标由 5 mod{2*N} 生成。

槽打包的 BGV 用例,

#include <vector>
#include <iostream>
#include "openfhe.h"
#include "cputimer.h"

using namespace std;
using namespace lbcrypto;

#define endl2 endl << endl
#define pn puts("")

#define print_param(ct)                                                            \
    cout << "ScalingFactorInt = " << ct->GetScalingFactorInt().ToString() << " | " \
         << "Level = " << ct->GetLevel() << " | "                                  \
         << "Depth = " << ct->GetNoiseScaleDeg() << " | "                          \
         << "SKDeg = " << ct->GetElements().size() - 1 << " | "                    \
         << endl;

#define print_pt(pt) \
    cout << "Result: " << pt << endl2;

int main()
{
    GetFrequency();
    cout << endl;

    size_t ringDim = 16384;          // 必须是二的幂次
    size_t plaintextModulus = 65537; // 槽打包必须是大素数
    size_t multDepth = 10;
    size_t maxRelinSkDeg = 4;

    CCParams<CryptoContextBGVRNS> parameters;
    parameters.SetSecurityLevel(HEStd_NotSet); // 如果不设置安全级别,则需要手动给出环维度
    parameters.SetRingDim(ringDim);
    parameters.SetPlaintextModulus(plaintextModulus);
    parameters.SetMultiplicativeDepth(multDepth);
    parameters.SetMaxRelinSkDeg(maxRelinSkDeg);
    parameters.SetKeySwitchTechnique(HYBRID);

    // FIXEDMANUAL 手动模切换,ScalingFactorInt 总是 1
    // FLEXIBLEAUTO 自动模切换,ScalingFactorInt 会在 [0, plaintextModulus] 内变换
    parameters.SetScalingTechnique(FLEXIBLEAUTO);

    CryptoContext<DCRTPoly> cc = GenCryptoContext(parameters);
    cc->Enable(PKE);
    cc->Enable(KEYSWITCH);
    cc->Enable(LEVELEDSHE);

    cout << "CyclotomicOrder = " << cc->GetCyclotomicOrder() << endl
         << "RingDimension = " << cc->GetRingDimension() << endl
         << "Level = " << cc->GetKeyGenLevel() << endl
         << "Modulus = " << cc->GetModulus() << endl
         << "ModulusBits = " << cc->GetModulus().GetLengthForBase(2) << endl
         << "RootOfUnity = " << cc->GetRootOfUnity() << endl
         << "PlaintextModulus = " << cc->GetEncodingParams()->GetPlaintextModulus() << endl
         << "BatchSize = " << cc->GetEncodingParams()->GetBatchSize() << endl
         << "PlaintextGenerator = " << cc->GetEncodingParams()->GetPlaintextGenerator() << endl
         << endl2;

    /***************************************************************************************************/

    auto keys = cc->KeyGen();
    cc->EvalMultKeysGen(keys.secretKey);
    cc->EvalRotateKeyGen(keys.secretKey, {1, -2});

    // 生成元 g = 5 mod N, ord(g) = N/2
    map<usint, EvalKey<DCRTPoly>> evk_map = *cc->EvalAutomorphismKeyGen(keys.secretKey, {1u, 5u, 25u});

    vector<int64_t> x1 = {1, 2, 3, 4, 5, 6, 7, 8};
    vector<int64_t> x2 = {4, 3, 2, 1, 1, 2, 3, 4};
    Plaintext pt1 = cc->MakePackedPlaintext(x1);
    Plaintext pt2 = cc->MakePackedPlaintext(x2);

    print_pt(pt1);
    print_pt(pt2);

    /***************************************************************************************************/

    auto ct1 = cc->Encrypt(keys.publicKey, pt1);
    auto ct2 = cc->Encrypt(keys.publicKey, pt2);

    Plaintext pt;
    print_param(ct1);
    pn;

    cc->Decrypt(keys.secretKey, ct1, &pt);
    print_pt(pt);

    cc->Decrypt(keys.secretKey, ct2, &pt);
    print_pt(pt);

    Ciphertext<DCRTPoly> ct;
    cout.precision(8);

    /***************************************************************************************************/

    Timer("+", ct = ct1 + ct2;); // 比 cc->EvalAdd 要快
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Add #1", ct = cc->EvalAdd(ct1, ct2);); // 首先会 type 检查
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Scale", ct = cc->EvalMult(ct, cc->MakePackedPlaintext(
                                             vector<int64_t>(cc->GetEncodingParams()->GetBatchSize(), 4)));); // 必须把 scale 先构造为 Plaintext
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Add #2", ct = cc->EvalAdd(ct, ct2);); // 相同 Level 不同 ScalingFactorInt 的加法,正确
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    /***************************************************************************************************/

    Timer("*", ct = ct1 * ct2;); // 和 cc->EvalMult 一样,但是不检查 type
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Mult", ct = cc->EvalMult(ct1, ct2);); // 总是自动密钥切换,和 cc->EvalMultAndRelinearize 完全一样
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Composed Mult #1", ct = cc->ComposedEvalMult(ct1, ct2);); // 密钥切换 + 模切换
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Composed Mult #2", ct = cc->ComposedEvalMult(ct, ct2);); // FLEXIBLEAUTO  在乘法之前做模切换,EXT 第一次乘法之前也做模切换
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Add #3", ct = cc->EvalAdd(ct, ct2);); // 不同 Level 不同 ScalingFactorInt 的加法,正确
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Mult And Relinearize", ct = cc->EvalMultAndRelinearize(ct1, ct2);); // 和 cc->EvalMult 基本一样
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    /***************************************************************************************************/

    Timer("Mult No Relin #1", ct = cc->EvalMultNoRelin(ct1, ct2);); // 这个才是不做密钥切换的,SKDeg 增长
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    // cc->ModReduceInPlace(ct);

    Timer("Mult No Relin #2", ct = cc->EvalMultNoRelin(ct, ct2);); // 不同 ScalingFactor 不同 Level 的乘法,正确
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Relinear", cc->RelinearizeInPlace(ct);); // 占据几乎全部的时间
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("ModReduce", cc->ModReduceInPlace(ct);); // 降低一层的缩放
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    /***************************************************************************************************/

    Timer("Rotate(1)", ct = cc->EvalRotate(ct1, 1);); // 正数是左旋
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Rotate(-2)", ct = cc->EvalRotate(ct1, -2);); // 负数是右旋
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    /***************************************************************************************************/

    Timer("Automorphism(1)", ct = cc->EvalAutomorphism(ct1, 1, evk_map);); // 不旋转
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Automorphism(5)", ct = cc->EvalAutomorphism(ct1, 5, evk_map);); // 数量 N 的明文槽,由 (-5) 生成
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Automorphism(25)", ct = cc->EvalAutomorphism(ct1, 25, evk_map);); // 5^2 mod N
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    /***************************************************************************************************/

    return 0;
}

结果

使用 FIXEDMANUAL 模切换

CPU Frequency = 2919164586

CyclotomicOrder = 2048
RingDimension = 1024
Level = 0
Modulus = 101915945247153194422621674945726031044678923861288323567523751344699549609876260625831851757818456743873649587405440263849024730822259572880063879169
ModulusBits = 495
RootOfUnity = 0
PlaintextModulus = 65537
BatchSize = 1024
PlaintextGenerator = 0


Result: ( 1 2 3 4 5 6 7 8 ... )

Result: ( 4 3 2 1 1 2 3 4 ... )

ScalingFactorInt = 1 | Level = 0 | Depth = 1 | SKDeg = 1 | 

Result: ( 1 2 3 4 5 6 7 8 ... )

Result: ( 4 3 2 1 1 2 3 4 ... )

Running Time of <+>:        928928 cycles (  0.318217 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 5 5 5 5 6 8 10 12 ... )

Running Time of <Add #1>:           918166 cycles (  0.314530 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 5 5 5 5 6 8 10 12 ... )

Running Time of <Scale>:           1406846 cycles (  0.481934 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 20 20 20 20 24 32 40 48 ... )

Running Time of <Add #2>:           721196 cycles (  0.247056 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 24 23 22 21 25 34 43 52 ... )

Running Time of <*>:      98448862 cycles ( 33.725012 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 4 6 6 4 5 12 21 32 ... )

Running Time of <Mult>:   74771761 cycles ( 25.614096 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 4 6 6 4 5 12 21 32 ... )

Running Time of <Composed Mult #1>:      103001350 cycles ( 35.284530 ms)
ScalingFactorInt = 1 | Level = 1 | Depth = 1 | SKDeg = 1 | 
Result: ( 4 6 6 4 5 12 21 32 ... )

Running Time of <Composed Mult #2>:       97931103 cycles ( 33.547647 ms)
ScalingFactorInt = 1 | Level = 2 | Depth = 1 | SKDeg = 1 | 
Result: ( 16 18 12 4 5 24 63 128 ... )

Running Time of <Add #3>:           660204 cycles (  0.226162 ms)
ScalingFactorInt = 1 | Level = 2 | Depth = 1 | SKDeg = 1 | 
Result: ( 20 21 14 5 6 26 66 132 ... )

Running Time of <Mult And Relinearize>:  121328656 cycles ( 41.562801 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 4 6 6 4 5 12 21 32 ... )

Running Time of <Mult No Relin #1>:        1237702 cycles (  0.423992 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 2 | SKDeg = 2 | 
Result: ( 4 6 6 4 5 12 21 32 ... )

Running Time of <Mult No Relin #2>:        1619596 cycles (  0.554815 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 3 | SKDeg = 3 | 
Result: ( 16 18 12 4 5 24 63 128 ... )

Running Time of <Relinear>:      207136845 cycles ( 70.957577 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 3 | SKDeg = 1 | 
Result: ( 16 18 12 4 5 24 63 128 ... )

Running Time of <ModReduce>:        991996 cycles (  0.339822 ms)
ScalingFactorInt = 1 | Level = 1 | Depth = 2 | SKDeg = 1 | 
Result: ( 16 18 12 4 5 24 63 128 ... )

Running Time of <Rotate(1)>:      82565072 cycles ( 28.283802 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 2 3 4 5 6 7 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 ... )

Running Time of <Rotate(-2)>:    118772481 cycles ( 40.687148 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 0 0 1 2 3 4 5 6 7 8 ... )

Running Time of <Automorphism(1)>:        98264131 cycles ( 33.661730 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 1 2 3 4 5 6 7 8 ... )

Running Time of <Automorphism(5)>:       104197049 cycles ( 35.694133 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 2 3 4 5 6 7 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 ... )

Running Time of <Automorphism(25)>:       96996770 cycles ( 33.227578 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 3 4 5 6 7 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 ... )

使用 FLEXIBLEAUTO 模切换

CPU Frequency = 2919001454

CyclotomicOrder = 2048
RingDimension = 1024
Level = 0
Modulus = 11090766327926935557496534795450603891404351373393750077990741913791395272295156970046992897184754308334673051240449197703818432513
ModulusBits = 433
RootOfUnity = 0
PlaintextModulus = 65537
BatchSize = 1024
PlaintextGenerator = 0


Result: ( 1 2 3 4 5 6 7 8 ... )

Result: ( 4 3 2 1 1 2 3 4 ... )

ScalingFactorInt = 20731 | Level = 0 | Depth = 1 | SKDeg = 1 | 

Result: ( 1 2 3 4 5 6 7 8 ... )

Result: ( 4 3 2 1 1 2 3 4 ... )

Running Time of <+>:        876028 cycles (  0.300112 ms)
ScalingFactorInt = 20731 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 5 5 5 5 6 8 10 12 ... )

Running Time of <Add #1>:           882874 cycles (  0.302458 ms)
ScalingFactorInt = 20731 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 5 5 5 5 6 8 10 12 ... )

Running Time of <Scale>:           1067962 cycles (  0.365866 ms)
ScalingFactorInt = 48252 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 20 20 20 20 24 32 40 48 ... )

Running Time of <Add #2>:           903446 cycles (  0.309505 ms)
ScalingFactorInt = 48252 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 24 23 22 21 25 34 43 52 ... )

Running Time of <*>:      79417215 cycles ( 27.206980 ms)
ScalingFactorInt = 48252 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 4 6 6 4 5 12 21 32 ... )

Running Time of <Mult>:   96562770 cycles ( 33.080754 ms)
ScalingFactorInt = 48252 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 4 6 6 4 5 12 21 32 ... )

Running Time of <Composed Mult #1>:       74693744 cycles ( 25.588800 ms)
ScalingFactorInt = 48252 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 4 6 6 4 5 12 21 32 ... )

Running Time of <Composed Mult #2>:       98139791 cycles ( 33.621015 ms)
ScalingFactorInt = 48252 | Level = 1 | Depth = 2 | SKDeg = 1 | 
Result: ( 16 18 12 4 5 24 63 128 ... )

Running Time of <Add #3>:           923506 cycles (  0.316377 ms)
ScalingFactorInt = 48252 | Level = 1 | Depth = 2 | SKDeg = 1 | 
Result: ( 20 21 14 5 6 26 66 132 ... )

Running Time of <Mult And Relinearize>:   94704513 cycles ( 32.444147 ms)
ScalingFactorInt = 48252 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ( 4 6 6 4 5 12 21 32 ... )

Running Time of <Mult No Relin #1>:        1258456 cycles (  0.431126 ms)
ScalingFactorInt = 48252 | Level = 0 | Depth = 2 | SKDeg = 2 | 
Result: ( 4 6 6 4 5 12 21 32 ... )

Running Time of <Mult No Relin #2>:        2055410 cycles (  0.704148 ms)
ScalingFactorInt = 48252 | Level = 1 | Depth = 2 | SKDeg = 3 | 
Result: ( 16 18 12 4 5 24 63 128 ... )

Running Time of <Relinear>:      179685843 cycles ( 61.557298 ms)
ScalingFactorInt = 48252 | Level = 1 | Depth = 2 | SKDeg = 1 | 
Result: ( 16 18 12 4 5 24 63 128 ... )

Running Time of <ModReduce>:          6682 cycles (  0.002289 ms)
ScalingFactorInt = 48252 | Level = 1 | Depth = 2 | SKDeg = 1 | 
Result: ( 16 18 12 4 5 24 63 128 ... )

Running Time of <Rotate(1)>:     109469187 cycles ( 37.502272 ms)
ScalingFactorInt = 20731 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 2 3 4 5 6 7 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 ... )

Running Time of <Rotate(-2)>:     74563389 cycles ( 25.544142 ms)
ScalingFactorInt = 20731 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 0 0 1 2 3 4 5 6 7 8 ... )

Running Time of <Automorphism(1)>:        84518442 cycles ( 28.954573 ms)
ScalingFactorInt = 20731 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 1 2 3 4 5 6 7 8 ... )

Running Time of <Automorphism(5)>:       104449053 cycles ( 35.782460 ms)
ScalingFactorInt = 20731 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 2 3 4 5 6 7 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 ... )

Running Time of <Automorphism(25)>:       75254525 cycles ( 25.780914 ms)
ScalingFactorInt = 20731 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ( 3 4 5 6 7 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 ... )

CKKS

代码

CKKS 方案不使用纠错码,但是把浮点数缩放为整数,需要重缩放。在 Ciphertext<DCRTPoly> 密文中,GetScalingFactor() 记录了缩放因子GetLevel() 记录了乘法深度GetNoiseScaleDeg() 记录了缩放因子的指数GetElements().size() 是密文中环元素向量的长度。

对于 CKKSPackedPlaintext 打包,仅支持 Real() 部分的加解密。SetScalingModSize() 用于设置缩放因子的比特数SetBatchSize() 用于设置明文槽的个数。对于 BatchSize <= RingDim/2,打包成维度 2*BatchSize子环,槽旋转对应的自同构指标由 5 mod{4*BatchSize} 生成。

槽打包的 CKKS 用例,

#include <vector>
#include <iostream>
#include "openfhe.h"
#include "cputimer.h"

using namespace std;
using namespace lbcrypto;

#define endl2 endl << endl
#define pn puts("")

#define print_param(ct)                                           \
    cout << "ScalingFactor = " << ct->GetScalingFactor() << " | " \
         << "Level = " << ct->GetLevel() << " | "                 \
         << "Depth = " << ct->GetNoiseScaleDeg() << " | "         \
         << "SKDeg = " << ct->GetElements().size() - 1 << " | "   \
         << endl;

#define print_pt(pt)    \
    cout << "Result: "; \
    PrintComplex(pt);   \
    cout << "Estimated precision in bits: " << pt->GetLogPrecision() << endl2;

void PrintComplex(Plaintext pt)
{
    vector<complex<double>> value = pt->GetCKKSPackedValue();
    size_t len = pt->GetLength();

    cout << "(";
    while (--len > 0)
        if (value[len] != complex<double>(0, 0))
            break;

    for (int i = 0; i <= len; i++)
    {
        cout << value[i] << ", ";
    }

    cout << " ... ); "
         << "Estimated precision: " << pt->GetLogPrecision() << " bits" << endl;
}

int main()
{
    GetFrequency();
    cout << endl;

    size_t ringDim = 16384;   // 必须是二的幂次
    size_t batchSize = 8;     // 必须是 N/2 的因子,二的幂次
    size_t scaleModSize = 50; // 仅支持至多 60-bit 尾数
    size_t multDepth = 10;
    size_t maxRelinSkDeg = 4;

    CCParams<CryptoContextCKKSRNS> parameters;
    parameters.SetSecurityLevel(HEStd_NotSet); // 如果不设置安全级别,则需要手动给出环维度
    parameters.SetRingDim(ringDim);
    parameters.SetBatchSize(batchSize);
    parameters.SetScalingModSize(scaleModSize);
    parameters.SetMultiplicativeDepth(multDepth);
    parameters.SetMaxRelinSkDeg(maxRelinSkDeg);
    parameters.SetKeySwitchTechnique(HYBRID);

    // FIXEDMANUAL 手动模切换,ScalingFactor 会变
    // FLEXIBLEAUTO 自动模切换,ScalingFactor 总是 2^scaleModSize
    parameters.SetScalingTechnique(FIXEDMANUAL);

    CryptoContext<DCRTPoly> cc = GenCryptoContext(parameters);
    cc->Enable(PKE);
    cc->Enable(KEYSWITCH);
    cc->Enable(LEVELEDSHE);
    cc->Enable(ADVANCEDSHE);

    cout << "CyclotomicOrder = " << cc->GetCyclotomicOrder() << endl
         << "RingDimension = " << cc->GetRingDimension() << endl
         << "Level = " << cc->GetKeyGenLevel() << endl
         << "Modulus = " << cc->GetModulus() << endl
         << "ModulusBits = " << cc->GetModulus().GetLengthForBase(2) << endl
         << "RootOfUnity = " << cc->GetRootOfUnity() << endl
         << "PlaintextModulus = " << cc->GetEncodingParams()->GetPlaintextModulus() << endl
         << "BatchSize = " << cc->GetEncodingParams()->GetBatchSize() << endl
         << "PlaintextGenerator = " << cc->GetEncodingParams()->GetPlaintextGenerator() << endl
         << endl2;

    /***************************************************************************************************/

    auto keys = cc->KeyGen();
    cc->EvalMultKeysGen(keys.secretKey);
    cc->EvalRotateKeyGen(keys.secretKey, {1, -2});

    // 生成元 g = 5 mod{4*batchSize}, ord(g) = batchSize
    map<usint, EvalKey<DCRTPoly>> evk_map = *cc->EvalAutomorphismKeyGen(keys.secretKey, {1u, 5u, 25u, 29u, 17u, 21u, 9u, 13u});

    vector<complex<double>> x1 = {{0.25, 0.5}, {0.5, 1}, {0.75, 1.5}, {1, 2}, {2, 4}, {3, 6}, {4, 8}, {5, 10}};
    vector<double> x2 = {5, 4, 3, 2, 1, 0.75, 0.5, 0.25};
    Plaintext pt1 = cc->MakeCKKSPackedPlaintext(x1);
    Plaintext pt2 = cc->MakeCKKSPackedPlaintext(x2);

    print_pt(pt1); // 明文编码了 Re 以及 Im
    print_pt(pt2);

    /***************************************************************************************************/

    auto ct1 = cc->Encrypt(keys.publicKey, pt1);
    auto ct2 = cc->Encrypt(keys.publicKey, pt2);

    Plaintext pt;
    print_param(ct1);
    pn;

    cc->Decrypt(keys.secretKey, ct1, &pt); // 但是仅加密 Re 部分,丢弃 Im 部分,复制在 Z_{4*batchSize}^* = <-1, 5> 中的 <5> 和 <-5> 两行
    print_pt(pt);

    cc->Decrypt(keys.secretKey, ct2, &pt);
    print_pt(pt);

    Ciphertext<DCRTPoly> ct;
    cout.precision(8);

    /***************************************************************************************************/

    Timer("+", ct = ct1 + ct2;); // 比 cc->EvalAdd 要快
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Add #1", ct = cc->EvalAdd(ct1, ct2);); // 首先会 type 检查
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Scale", ct = cc->EvalMult(ct1, 4);); // 速度接近 operator+
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    cc->RescaleInPlace(ct); // 相同 Level 不同 ScalingFactor 的加法,错误

    Timer("Add #2", ct = cc->EvalAdd(ct, ct2);); // 相同 ScalingFactor 不同 Level 的加法,正确
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    /***************************************************************************************************/

    Timer("*", ct = ct1 * ct2;); // 和 cc->EvalMult 一样,但是不检查 type
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Mult", ct = cc->EvalMult(ct1, ct2);); // 总是自动密钥切换,和 cc->EvalMultAndRelinearize 完全一样
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Composed Mult #1", ct = cc->ComposedEvalMult(ct1, ct2);); // 密钥切换 + 模切换
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Composed Mult #2", ct = cc->ComposedEvalMult(ct, ct2);); // FLEXIBLEAUTO  在乘法之前做模切换,EXT 第一次乘法之前也做模切换
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Mult And Relinearize", ct = cc->EvalMultAndRelinearize(ct1, ct2);); // 和 cc->EvalMult 基本一样
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    /***************************************************************************************************/

    Timer("Mult No Relin #1", ct = cc->EvalMultNoRelin(ct1, ct2);); // 这个才是不做密钥切换的,SKDeg 增长
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    // cc->RescaleInPlace(ct);

    Timer("Mult No Relin #2", ct = cc->EvalMultNoRelin(ct, ct2);); // 不同 ScalingFactor 不同 Level 的乘法,正确
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Relinear", cc->RelinearizeInPlace(ct);); // 占据几乎全部的时间
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("ModReduce", cc->ModReduceInPlace(ct);); // 降低一层的缩放,和 cc->RescaleInPlace 完全一样
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Rescale", cc->RescaleInPlace(ct);); // 降低一层的缩放,和 cc->ModReduceInPlace 完全一样
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    /***************************************************************************************************/

    Timer("Rotate(1)", ct = cc->EvalRotate(ct1, 1);); // 正数是左旋
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Rotate(-2)", ct = cc->EvalRotate(ct1, -2);); // 负数是右旋
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    /***************************************************************************************************/

    Timer("Automorphism(1)", ct = cc->EvalAutomorphism(ct1, 1, evk_map);); // 不旋转
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Automorphism(5)", ct = cc->EvalAutomorphism(ct1, 5, evk_map);); // 次数 4*batchSize 的子环上,数量 batchSize 的明文槽,由 (-5) 生成
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Automorphism(25)", ct = cc->EvalAutomorphism(ct1, 25, evk_map);); // 5^2 mod 32
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Automorphism(29)", ct = cc->EvalAutomorphism(ct1, 29, evk_map);); // 5^3 mod 32
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Automorphism(17)", ct = cc->EvalAutomorphism(ct1, 17, evk_map););
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Automorphism(21)", ct = cc->EvalAutomorphism(ct1, 21, evk_map););
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Automorphism(9)", ct = cc->EvalAutomorphism(ct1, 9, evk_map););
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    Timer("Automorphism(13)", ct = cc->EvalAutomorphism(ct1, 13, evk_map););
    print_param(ct);
    cc->Decrypt(keys.secretKey, ct, &pt);
    print_pt(pt);

    /***************************************************************************************************/

    return 0;
}

结果

使用 FIXEDMANUAL 模切换

CPU Frequency = 2919133983

CyclotomicOrder = 2048
RingDimension = 1024
Level = 0
Modulus = 3773962425391299449455856105110342697983390191203387110210545988123360807414630715088298851847265236596671914551723351177669086733035396939530237480795634800286060664833
ModulusBits = 561
RootOfUnity = 0
PlaintextModulus = 50
BatchSize = 8
PlaintextGenerator = 0


Result: ((0.25,0.5), (0.5,1), (0.75,1.5), (1,2), (2,4), (3,6), (4,8), (5,10),  ... ); Estimated precision: 50 bits
Estimated precision in bits: 50

Result: ((5,0), (4,0), (3,0), (2,0), (1,0), (0.75,0), (0.5,0), (0.25,0),  ... ); Estimated precision: 50 bits
Estimated precision in bits: 50

ScalingFactor = 1.1259e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 

Result: ((0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), (3,0), (4,0), (5,0),  ... ); Estimated precision: 42 bits
Estimated precision in bits: 42

Result: ((5,0), (4,0), (3,0), (2,0), (1,0), (0.75,0), (0.5,0), (0.25,0),  ... ); Estimated precision: 42 bits
Estimated precision in bits: 42

Running Time of <+>:        232698 cycles (  0.079715 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((5.25,0), (4.5,0), (3.75,0), (3,0), (3,0), (3.75,0), (4.5,0), (5.25,0),  ... ); Estimated precision: 42 bits
Estimated precision in bits: 42

Running Time of <Add #1>:           293886 cycles (  0.100676 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((5.25,0), (4.5,0), (3.75,0), (3,0), (3,0), (3.75,0), (4.5,0), (5.25,0),  ... ); Estimated precision: 42 bits
Estimated precision in bits: 42

Running Time of <Scale>:            218742 cycles (  0.074934 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ((1,0), (2,0), (3,0), (4,0), (8,0), (12,0), (16,0), (20,0),  ... ); Estimated precision: 40 bits
Estimated precision in bits: 40

Running Time of <Add #2>:           138844 cycles (  0.047563 ms)
ScalingFactor = 1.1258999e+15 | Level = 1 | Depth = 1 | SKDeg = 1 | 
Result: ((6,0), (6,0), (6,0), (6,0), (9,0), (12.75,0), (16.5,0), (20.25,0),  ... ); Estimated precision: 40 bits
Estimated precision in bits: 40

Running Time of <*>:      88682107 cycles ( 30.379595 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ((1.25,0), (2,0), (2.25,0), (2,0), (2,0), (2.25,0), (2,0), (1.25,0),  ... ); Estimated precision: 41 bits
Estimated precision in bits: 41

Running Time of <Mult>:   83510222 cycles ( 28.607876 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ((1.25,0), (2,0), (2.25,0), (2,0), (2,0), (2.25,0), (2,0), (1.25,0),  ... ); Estimated precision: 41 bits
Estimated precision in bits: 41

Running Time of <Composed Mult #1>:      125045991 cycles ( 42.836674 ms)
ScalingFactor = 1.1258999e+15 | Level = 1 | Depth = 1 | SKDeg = 1 | 
Result: ((1.25,0), (2,0), (2.25,0), (2,0), (2,0), (2.25,0), (2,0), (1.25,0),  ... ); Estimated precision: 41 bits
Estimated precision in bits: 41

Running Time of <Composed Mult #2>:      126722970 cycles ( 43.411152 ms)
ScalingFactor = 1.1258999e+15 | Level = 2 | Depth = 1 | SKDeg = 1 | 
Result: ((6.25,0), (8,0), (6.75,0), (4,0), (2,0), (1.6875,0), (1,0), (0.3125,0),  ... ); Estimated precision: 40 bits
Estimated precision in bits: 40

Running Time of <Mult And Relinearize>:  100906735 cycles ( 34.567353 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ((1.25,0), (2,0), (2.25,0), (2,0), (2,0), (2.25,0), (2,0), (1.25,0),  ... ); Estimated precision: 41 bits
Estimated precision in bits: 41

Running Time of <Mult No Relin #1>:         477430 cycles (  0.163552 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 2 | 
Result: ((1.25,0), (2,0), (2.25,0), (2,0), (2,0), (2.25,0), (2,0), (1.25,0),  ... ); Estimated precision: 41 bits
Estimated precision in bits: 41

Running Time of <Mult No Relin #2>:        1077588 cycles (  0.369146 ms)
ScalingFactor = 1.4272477e+45 | Level = 0 | Depth = 3 | SKDeg = 3 | 
Result: ((6.25,0), (8,0), (6.75,0), (4,0), (2,0), (1.6875,0), (1,0), (0.3125,0),  ... ); Estimated precision: 40 bits
Estimated precision in bits: 40

Running Time of <Relinear>:      162462043 cycles ( 55.654192 ms)
ScalingFactor = 1.4272477e+45 | Level = 0 | Depth = 3 | SKDeg = 1 | 
Result: ((6.25,0), (8,0), (6.75,0), (4,0), (2,0), (1.6875,0), (1,0), (0.3125,0),  ... ); Estimated precision: 40 bits
Estimated precision in bits: 40

Running Time of <ModReduce>:        390542 cycles (  0.133787 ms)
ScalingFactor = 1.2676506e+30 | Level = 1 | Depth = 2 | SKDeg = 1 | 
Result: ((6.25,0), (8,0), (6.75,0), (4,0), (2,0), (1.6875,0), (1,0), (0.3125,0),  ... ); Estimated precision: 40 bits
Estimated precision in bits: 40

Running Time of <Rescale>:          294642 cycles (  0.100935 ms)
ScalingFactor = 1.1258999e+15 | Level = 2 | Depth = 1 | SKDeg = 1 | 
Result: ((6.25,0), (8,0), (6.75,0), (4,0), (2,0), (1.6875,0), (1,0), (0.3125,0),  ... ); Estimated precision: 40 bits
Estimated precision in bits: 40

Running Time of <Rotate(1)>:      85623396 cycles ( 29.331780 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((0.5,0), (0.75,0), (1,0), (2,0), (3,0), (4,0), (5,0), (0.25,0),  ... ); Estimated precision: 42 bits
Estimated precision in bits: 42

Running Time of <Rotate(-2)>:     85083932 cycles ( 29.146977 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((4,0), (5,0), (0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), (3,0),  ... ); Estimated precision: 42 bits
Estimated precision in bits: 42

Running Time of <Automorphism(1)>:        84371770 cycles ( 28.903014 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), (3,0), (4,0), (5,0),  ... ); Estimated precision: 42 bits
Estimated precision in bits: 42

Running Time of <Automorphism(5)>:        32532042 cycles ( 11.144415 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((0.5,0), (0.75,0), (1,0), (2,0), (3,0), (4,0), (5,0), (0.25,0),  ... ); Estimated precision: 42 bits
Estimated precision in bits: 42

Running Time of <Automorphism(25)>:      102897566 cycles ( 35.249347 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((0.75,0), (1,0), (2,0), (3,0), (4,0), (5,0), (0.25,0), (0.5,0),  ... ); Estimated precision: 42 bits
Estimated precision in bits: 42

Running Time of <Automorphism(29)>:      154811323 cycles ( 53.033305 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((1,0), (2,0), (3,0), (4,0), (5,0), (0.25,0), (0.5,0), (0.75,0),  ... ); Estimated precision: 42 bits
Estimated precision in bits: 42

Running Time of <Automorphism(17)>:       79522168 cycles ( 27.241699 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((2,0), (3,0), (4,0), (5,0), (0.25,0), (0.5,0), (0.75,0), (1,0),  ... ); Estimated precision: 41 bits
Estimated precision in bits: 41

Running Time of <Automorphism(21)>:       72500099 cycles ( 24.836167 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((3,0), (4,0), (5,0), (0.25,0), (0.5,0), (0.75,0), (1,0), (2,0),  ... ); Estimated precision: 42 bits
Estimated precision in bits: 42

Running Time of <Automorphism(9)>:        82870142 cycles ( 28.388605 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((4,0), (5,0), (0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), (3,0),  ... ); Estimated precision: 42 bits
Estimated precision in bits: 42

Running Time of <Automorphism(13)>:       84619741 cycles ( 28.987961 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((5,0), (0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), (3,0), (4,0),  ... ); Estimated precision: 41 bits
Estimated precision in bits: 41

使用 FLEXIBLEAUTO 模切换

CPU Frequency = 2918792554

CyclotomicOrder = 2048
RingDimension = 1024
Level = 0
Modulus = 3773962422988620268549387626283230612775297831378964384076336766063448441293238012679355400777370037636733749256861996141103106549700437881327817936926763295941309458433
ModulusBits = 560
RootOfUnity = 0
PlaintextModulus = 50
BatchSize = 8
PlaintextGenerator = 0


Result: ((0.25,0.5), (0.5,1), (0.75,1.5), (1,2), (2,4), (3,6), (4,8), (5,10),  ... ); Estimated precision: 50 bits
Estimated precision in bits: 50

Result: ((5,0), (4,0), (3,0), (2,0), (1,0), (0.75,0), (0.5,0), (0.25,0),  ... ); Estimated precision: 50 bits
Estimated precision in bits: 50

ScalingFactor = 1.1259e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 

Result: ((0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), (3,0), (4,0), (5,0),  ... ); Estimated precision: 41 bits
Estimated precision in bits: 41

Result: ((5,0), (4,0), (3,0), (2,0), (1,0), (0.75,0), (0.5,0), (0.25,0),  ... ); Estimated precision: 41 bits
Estimated precision in bits: 41

Running Time of <+>:        217702 cycles (  0.074586 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((5.25,0), (4.5,0), (3.75,0), (3,0), (3,0), (3.75,0), (4.5,0), (5.25,0),  ... ); Estimated precision: 41 bits
Estimated precision in bits: 41

Running Time of <Add #1>:           195658 cycles (  0.067034 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((5.25,0), (4.5,0), (3.75,0), (3,0), (3,0), (3.75,0), (4.5,0), (5.25,0),  ... ); Estimated precision: 41 bits
Estimated precision in bits: 41

Running Time of <Scale>:            336894 cycles (  0.115422 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ((1,0), (2,0), (3,0), (4,0), (8,0), (12,0), (16,0), (20,0),  ... ); Estimated precision: 39 bits
Estimated precision in bits: 39

Running Time of <Add #2>:           474080 cycles (  0.162423 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ((6,0), (6,0), (6,0), (6,0), (9,0), (12.75,0), (16.5,0), (20.25,0),  ... ); Estimated precision: 40 bits
Estimated precision in bits: 40

Running Time of <*>:     118372907 cycles ( 40.555437 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ((1.25,0), (2,0), (2.25,0), (2,0), (2,0), (2.25,0), (2,0), (1.25,0),  ... ); Estimated precision: 40 bits
Estimated precision in bits: 40

Running Time of <Mult>:  102517626 cycles ( 35.123300 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ((1.25,0), (2,0), (2.25,0), (2,0), (2,0), (2.25,0), (2,0), (1.25,0),  ... ); Estimated precision: 40 bits
Estimated precision in bits: 40

Running Time of <Composed Mult #1>:       68991449 cycles ( 23.636983 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ((1.25,0), (2,0), (2.25,0), (2,0), (2,0), (2.25,0), (2,0), (1.25,0),  ... ); Estimated precision: 40 bits
Estimated precision in bits: 40

Running Time of <Composed Mult #2>:       83294391 cycles ( 28.537277 ms)
ScalingFactor = 1.2676506e+30 | Level = 1 | Depth = 2 | SKDeg = 1 | 
Result: ((6.25,0), (8,0), (6.75,0), (4,0), (2,0), (1.6875,0), (1,0), (0.3125,0),  ... ); Estimated precision: 40 bits
Estimated precision in bits: 40

Running Time of <Mult And Relinearize>:   83116483 cycles ( 28.476324 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 1 | 
Result: ((1.25,0), (2,0), (2.25,0), (2,0), (2,0), (2.25,0), (2,0), (1.25,0),  ... ); Estimated precision: 40 bits
Estimated precision in bits: 40

Running Time of <Mult No Relin #1>:         661054 cycles (  0.226482 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 2 | 
Result: ((1.25,0), (2,0), (2.25,0), (2,0), (2,0), (2.25,0), (2,0), (1.25,0),  ... ); Estimated precision: 40 bits
Estimated precision in bits: 40

Running Time of <Mult No Relin #2>:        1388252 cycles (  0.475625 ms)
ScalingFactor = 1.2676506e+30 | Level = 1 | Depth = 2 | SKDeg = 3 | 
Result: ((6.25,0), (8,0), (6.75,0), (4,0), (2,0), (1.6875,0), (1,0), (0.3125,0),  ... ); Estimated precision: 38 bits
Estimated precision in bits: 38

Running Time of <Relinear>:      161033258 cycles ( 55.171190 ms)
ScalingFactor = 1.2676506e+30 | Level = 1 | Depth = 2 | SKDeg = 1 | 
Result: ((6.25,0), (8,0), (6.75,0), (4,0), (2,0), (1.6875,0), (1,0), (0.3125,0),  ... ); Estimated precision: 38 bits
Estimated precision in bits: 38

Running Time of <ModReduce>:          7684 cycles (  0.002633 ms)
ScalingFactor = 1.2676506e+30 | Level = 1 | Depth = 2 | SKDeg = 1 | 
Result: ((6.25,0), (8,0), (6.75,0), (4,0), (2,0), (1.6875,0), (1,0), (0.3125,0),  ... ); Estimated precision: 38 bits
Estimated precision in bits: 38

Running Time of <Rescale>:            1646 cycles (  0.000564 ms)
ScalingFactor = 1.2676506e+30 | Level = 1 | Depth = 2 | SKDeg = 1 | 
Result: ((6.25,0), (8,0), (6.75,0), (4,0), (2,0), (1.6875,0), (1,0), (0.3125,0),  ... ); Estimated precision: 38 bits
Estimated precision in bits: 38

Running Time of <Rotate(1)>:      26580736 cycles (  9.106758 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((0.5,0), (0.75,0), (1,0), (2,0), (3,0), (4,0), (5,0), (0.25,0),  ... ); Estimated precision: 42 bits
Estimated precision in bits: 42

Running Time of <Rotate(-2)>:     17406282 cycles (  5.963521 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((4,0), (5,0), (0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), (3,0),  ... ); Estimated precision: 42 bits
Estimated precision in bits: 42

Running Time of <Automorphism(1)>:        41046903 cycles ( 14.062974 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), (3,0), (4,0), (5,0),  ... ); Estimated precision: 42 bits
Estimated precision in bits: 42

Running Time of <Automorphism(5)>:        37049927 cycles ( 12.693580 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((0.5,0), (0.75,0), (1,0), (2,0), (3,0), (4,0), (5,0), (0.25,0),  ... ); Estimated precision: 42 bits
Estimated precision in bits: 42

Running Time of <Automorphism(25)>:       98023806 cycles ( 33.583684 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((0.75,0), (1,0), (2,0), (3,0), (4,0), (5,0), (0.25,0), (0.5,0),  ... ); Estimated precision: 41 bits
Estimated precision in bits: 41

Running Time of <Automorphism(29)>:       92120842 cycles ( 31.561284 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((1,0), (2,0), (3,0), (4,0), (5,0), (0.25,0), (0.5,0), (0.75,0),  ... ); Estimated precision: 41 bits
Estimated precision in bits: 41

Running Time of <Automorphism(17)>:       87246888 cycles ( 29.891432 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((2,0), (3,0), (4,0), (5,0), (0.25,0), (0.5,0), (0.75,0), (1,0),  ... ); Estimated precision: 41 bits
Estimated precision in bits: 41

Running Time of <Automorphism(21)>:      136802988 cycles ( 46.869719 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((3,0), (4,0), (5,0), (0.25,0), (0.5,0), (0.75,0), (1,0), (2,0),  ... ); Estimated precision: 42 bits
Estimated precision in bits: 42

Running Time of <Automorphism(9)>:       103675496 cycles ( 35.519995 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((4,0), (5,0), (0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), (3,0),  ... ); Estimated precision: 42 bits
Estimated precision in bits: 42

Running Time of <Automorphism(13)>:       65311725 cycles ( 22.376282 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 | 
Result: ((5,0), (0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), (3,0), (4,0),  ... ); Estimated precision: 41 bits
Estimated precision in bits: 41
  • 20
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值