|
| 1 | +// RUN: heir-opt --validate-scale --verify-diagnostics --split-input-file %s |
| 2 | + |
| 3 | +// Case 1: Valid bootstrap (should pass) |
| 4 | +module attributes {ckks.schemeParam = #ckks.scheme_param<logN = 13, Q = [36028797019389953, 35184372121601], P = [36028797019488257], logDefaultScale = 45>, scheme.ckks} { |
| 5 | + func.func @bootstrap_success(%arg0: !secret.secret<f32> {mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 54>}) -> !secret.secret<f32> { |
| 6 | + %0 = secret.generic(%arg0 : !secret.secret<f32> {mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 54>}) { |
| 7 | + ^body(%input0: f32): |
| 8 | + // first-mod-bits = round(log2(36028797019389953)) = 55 |
| 9 | + // input scale 54 <= 55 - 1 (54) -> OK |
| 10 | + // output scale 45 == logDefaultScale (45) -> OK |
| 11 | + %1 = mgmt.bootstrap %input0 {id = 0 : i64, mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 45>} : f32 |
| 12 | + secret.yield %1 : f32 |
| 13 | + } -> (!secret.secret<f32> {mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 45>}) |
| 14 | + return %0 : !secret.secret<f32> |
| 15 | + } |
| 16 | +} |
| 17 | + |
| 18 | +// ----- |
| 19 | + |
| 20 | +// Case 2: Input scale too large |
| 21 | +module attributes {ckks.schemeParam = #ckks.scheme_param<logN = 13, Q = [36028797019389953, 35184372121601], P = [36028797019488257], logDefaultScale = 45>, scheme.ckks} { |
| 22 | + func.func @bootstrap_input_scale_too_large(%arg0: !secret.secret<f32> {mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 55>}) -> !secret.secret<f32> { |
| 23 | + %0 = secret.generic(%arg0 : !secret.secret<f32> {mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 55>}) { |
| 24 | + ^body(%input0: f32): |
| 25 | + // first-mod-bits = 55 |
| 26 | + // input scale 55 > 55 - 1 (54) -> Fail |
| 27 | + // expected-error @+1 {{input scale must be less than or equal to first-mod-bits - 1}} |
| 28 | + %1 = mgmt.bootstrap %input0 {id = 0 : i64, mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 45>} : f32 |
| 29 | + secret.yield %1 : f32 |
| 30 | + } -> (!secret.secret<f32> {mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 45>}) |
| 31 | + return %0 : !secret.secret<f32> |
| 32 | + } |
| 33 | +} |
| 34 | + |
| 35 | +// ----- |
| 36 | + |
| 37 | +// Case 3: Output scale mismatch |
| 38 | +module attributes {ckks.schemeParam = #ckks.scheme_param<logN = 13, Q = [36028797019389953, 35184372121601], P = [36028797019488257], logDefaultScale = 45>, scheme.ckks} { |
| 39 | + func.func @bootstrap_output_scale_mismatch(%arg0: !secret.secret<f32> {mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 45>}) -> !secret.secret<f32> { |
| 40 | + %0 = secret.generic(%arg0 : !secret.secret<f32> {mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 45>}) { |
| 41 | + ^body(%input0: f32): |
| 42 | + // output scale 46 != logDefaultScale (45) -> Fail |
| 43 | + // expected-error @+1 {{output scale must match the default scale}} |
| 44 | + %1 = mgmt.bootstrap %input0 {id = 0 : i64, mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 46>} : f32 |
| 45 | + secret.yield %1 : f32 |
| 46 | + } -> (!secret.secret<f32> {mgmt.mgmt = #mgmt.mgmt<level = 1, scale = 46>}) |
| 47 | + return %0 : !secret.secret<f32> |
| 48 | + } |
| 49 | +} |
0 commit comments