1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use Result;
use ;
use ;
use crate::;
/// Multiplication and division of a ciphertext by a power of two.
///
/// These operations shift the torus polynomial by `bits` positions. Their
/// metadata effects are **asymmetric**: `mul_pow2` preserves `log_delta` and
/// only loses `log_budget` if the destination is undersized, while `div_pow2`
/// transfers `bits` from `log_budget` to `log_delta` (a precision-aware
/// rescale) and again loses extra bits if the destination is undersized.
///
/// # Metadata
///
/// ## Multiply by `2^bits` (`ckks_mul_pow2_into` / `ckks_mul_pow2_assign`)
///
/// The polynomial is left-shifted by `bits` positions. The encrypted value
/// becomes `message * 2^bits`, encoded at the same precision `log_delta`.
///
/// For `_into` variants:
///
/// ```text
/// offset = max(0, src.effective_k() − dst.max_k())
///
/// log_delta_out = src.log_delta
/// log_budget_out = src.log_budget − offset
/// ```
///
/// For `_assign` variants `offset = 0` and metadata is unchanged.
///
/// **Note**: the metadata does not account for the increased magnitude of the
/// encrypted value. It is the caller's responsibility to ensure that
/// `message * 2^bits` still fits within the nominal `log_budget` headroom.
///
/// ## Divide by `2^bits` (`ckks_div_pow2_into` / `ckks_div_pow2_assign`)
///
/// The polynomial is right-shifted by `bits` positions, increasing precision
/// at the cost of capacity.
///
/// For `_into` variants:
///
/// ```text
/// offset = max(0, src.effective_k() − dst.max_k())
///
/// log_delta_out = src.log_delta + bits
/// log_budget_out = src.log_budget − bits − offset
/// ```
///
/// For `_assign` variants `offset = 0`:
///
/// ```text
/// log_delta_out = dst.log_delta + bits
/// log_budget_out = dst.log_budget − bits
/// ```
///
/// **Capacity consumed**: `bits` bits (plus `offset` for undersized destinations).
/// Errors with `InsufficientHomomorphicCapacity` if `bits (+ offset) > src.log_budget`.