mplang-nightly 0.1.dev142__py3-none-any.whl → 0.1.dev143__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mplang/backend/phe.py +1448 -91
- mplang/frontend/phe.py +140 -3
- {mplang_nightly-0.1.dev142.dist-info → mplang_nightly-0.1.dev143.dist-info}/METADATA +1 -1
- {mplang_nightly-0.1.dev142.dist-info → mplang_nightly-0.1.dev143.dist-info}/RECORD +7 -7
- {mplang_nightly-0.1.dev142.dist-info → mplang_nightly-0.1.dev143.dist-info}/WHEEL +0 -0
- {mplang_nightly-0.1.dev142.dist-info → mplang_nightly-0.1.dev143.dist-info}/entry_points.txt +0 -0
- {mplang_nightly-0.1.dev142.dist-info → mplang_nightly-0.1.dev143.dist-info}/licenses/LICENSE +0 -0
mplang/frontend/phe.py
CHANGED
@@ -52,10 +52,9 @@ def add(operand1: TensorType, operand2: TensorType) -> TensorType:
|
|
52
52
|
@_PHE_MOD.simple_op()
|
53
53
|
def mul(ciphertext: TensorType, plaintext: TensorType) -> TensorType:
|
54
54
|
"""Multiply a PHE ciphertext with a plaintext value (ciphertext dtype preserved)."""
|
55
|
-
if
|
55
|
+
if plaintext.dtype.is_floating:
|
56
56
|
raise ValueError(
|
57
|
-
"PHE multiplication does not support
|
58
|
-
"Consider using mixed types (float x int) or integer types instead."
|
57
|
+
"PHE multiplication does not support floating-point plaintext."
|
59
58
|
)
|
60
59
|
return ciphertext
|
61
60
|
|
@@ -65,3 +64,141 @@ def decrypt(ciphertext: TensorType, private_key: TensorType) -> TensorType:
|
|
65
64
|
"""Decrypt ciphertext using PHE private key: returns plaintext with same semantic type as ciphertext."""
|
66
65
|
_ = private_key
|
67
66
|
return ciphertext
|
67
|
+
|
68
|
+
|
69
|
+
@_PHE_MOD.simple_op()
|
70
|
+
def dot(ciphertext: TensorType, plaintext: TensorType) -> TensorType:
|
71
|
+
"""Compute dot product of ciphertext with plaintext.
|
72
|
+
|
73
|
+
Args:
|
74
|
+
ciphertext: The ciphertext operand (first argument)
|
75
|
+
plaintext: The plaintext operand (second argument)
|
76
|
+
|
77
|
+
Returns:
|
78
|
+
TensorType: Result tensor type with computed shape following numpy dot product rules
|
79
|
+
"""
|
80
|
+
# For dot product, we need to calculate the result shape
|
81
|
+
# This follows numpy dot product rules
|
82
|
+
import numpy as np
|
83
|
+
|
84
|
+
# Create dummy arrays to determine result shape
|
85
|
+
dummy_ct = np.zeros(ciphertext.shape)
|
86
|
+
dummy_pt = np.zeros(plaintext.shape)
|
87
|
+
dummy_result = np.dot(dummy_ct, dummy_pt)
|
88
|
+
|
89
|
+
return TensorType(ciphertext.dtype, dummy_result.shape)
|
90
|
+
|
91
|
+
|
92
|
+
@_PHE_MOD.simple_op()
|
93
|
+
def gather(ciphertext: TensorType, indices: TensorType, *, axis: int = 0) -> TensorType:
|
94
|
+
"""Gather elements from ciphertext using indices.
|
95
|
+
|
96
|
+
Args:
|
97
|
+
ciphertext: The ciphertext to gather from
|
98
|
+
indices: The indices to gather
|
99
|
+
axis: The axis along which to gather (default: 0)
|
100
|
+
"""
|
101
|
+
# Calculate result shape based on axis parameter
|
102
|
+
ct_shape = list(ciphertext.shape)
|
103
|
+
indices_shape = list(indices.shape)
|
104
|
+
|
105
|
+
# Normalize negative axis
|
106
|
+
normalized_axis = axis if axis >= 0 else len(ct_shape) + axis
|
107
|
+
|
108
|
+
# Result shape: replace the axis dimension with indices shape
|
109
|
+
result_shape = (
|
110
|
+
ct_shape[:normalized_axis] + indices_shape + ct_shape[normalized_axis + 1 :]
|
111
|
+
)
|
112
|
+
return TensorType(ciphertext.dtype, tuple(result_shape))
|
113
|
+
|
114
|
+
|
115
|
+
@_PHE_MOD.simple_op()
|
116
|
+
def scatter(
|
117
|
+
ciphertext: TensorType,
|
118
|
+
indices: TensorType,
|
119
|
+
updates: TensorType,
|
120
|
+
*,
|
121
|
+
axis: int = 0,
|
122
|
+
) -> TensorType:
|
123
|
+
"""Scatter updates into ciphertext at specified indices.
|
124
|
+
|
125
|
+
Args:
|
126
|
+
ciphertext: The ciphertext to scatter into
|
127
|
+
indices: The indices to scatter at
|
128
|
+
updates: The ciphertext updates to scatter
|
129
|
+
axis: The axis along which to scatter (default: 0)
|
130
|
+
|
131
|
+
Returns:
|
132
|
+
TensorType: Result tensor type with same shape and dtype as original ciphertext
|
133
|
+
"""
|
134
|
+
return ciphertext
|
135
|
+
|
136
|
+
|
137
|
+
@_PHE_MOD.simple_op()
|
138
|
+
def concat(operand0: TensorType, operand1: TensorType, *, axis: int = 0) -> TensorType:
|
139
|
+
"""Concatenate ciphertext tensors along specified axis.
|
140
|
+
|
141
|
+
Args:
|
142
|
+
operand0: The first ciphertext operand to concatenate
|
143
|
+
operand1: The second ciphertext operand to concatenate
|
144
|
+
axis: Axis along which to concatenate
|
145
|
+
|
146
|
+
Returns:
|
147
|
+
TensorType: Result tensor type with computed shape following numpy concatenation rules
|
148
|
+
"""
|
149
|
+
# All operands should have same dtype
|
150
|
+
first_dtype = operand0.dtype
|
151
|
+
if operand1.dtype != first_dtype:
|
152
|
+
raise ValueError("All operands must have the same dtype for concatenation")
|
153
|
+
|
154
|
+
# Calculate result shape using numpy concatenation logic
|
155
|
+
import numpy as np
|
156
|
+
|
157
|
+
dummy_arrays = [np.zeros(operand0.shape), np.zeros(operand1.shape)]
|
158
|
+
dummy_result = np.concatenate(dummy_arrays, axis=axis)
|
159
|
+
|
160
|
+
return TensorType(first_dtype, dummy_result.shape)
|
161
|
+
|
162
|
+
|
163
|
+
@_PHE_MOD.simple_op()
|
164
|
+
def reshape(ciphertext: TensorType, *, new_shape: tuple[int, ...]) -> TensorType:
|
165
|
+
"""Reshape ciphertext to new shape.
|
166
|
+
|
167
|
+
Args:
|
168
|
+
ciphertext: The ciphertext to reshape
|
169
|
+
new_shape: The target shape (can contain -1 for inferred dimension)
|
170
|
+
|
171
|
+
Returns:
|
172
|
+
TensorType: Result tensor type with computed shape following numpy reshape rules
|
173
|
+
"""
|
174
|
+
# Calculate the actual result shape (handling -1 inference)
|
175
|
+
import numpy as np
|
176
|
+
|
177
|
+
dummy_array = np.zeros(ciphertext.shape)
|
178
|
+
# use this to check the correctness of new_shape
|
179
|
+
dummy_result = dummy_array.reshape(new_shape)
|
180
|
+
actual_shape = dummy_result.shape
|
181
|
+
|
182
|
+
return TensorType(ciphertext.dtype, actual_shape)
|
183
|
+
|
184
|
+
|
185
|
+
@_PHE_MOD.simple_op()
|
186
|
+
def transpose(
|
187
|
+
ciphertext: TensorType, *, axes: tuple[int, ...] | None = None
|
188
|
+
) -> TensorType:
|
189
|
+
"""Transpose ciphertext by permuting axes.
|
190
|
+
|
191
|
+
Args:
|
192
|
+
ciphertext: The ciphertext to transpose
|
193
|
+
axes: Permutation of axes (None for default reverse order)
|
194
|
+
|
195
|
+
Returns:
|
196
|
+
TensorType: Result tensor type with computed shape following numpy transpose rules
|
197
|
+
"""
|
198
|
+
# Calculate result shape using numpy transpose logic
|
199
|
+
import numpy as np
|
200
|
+
|
201
|
+
dummy_array = np.zeros(ciphertext.shape)
|
202
|
+
dummy_result = np.transpose(dummy_array, axes)
|
203
|
+
|
204
|
+
return TensorType(ciphertext.dtype, dummy_result.shape)
|
@@ -7,7 +7,7 @@ mplang/backend/__init__.py,sha256=Pn1MGW7FZ8ZQWcx_r2Io4Q1JbrMINCpefQt7yCNq_dc,74
|
|
7
7
|
mplang/backend/base.py,sha256=zaofB1MPC9Af8FS-rx7q6utFxiu9Mppr2gWaKFZ70Os,9863
|
8
8
|
mplang/backend/builtin.py,sha256=Mk1uUO2Vpw3meqZ0B7B0hG-wndea6cmFv2Uk1vM_uTg,7052
|
9
9
|
mplang/backend/crypto.py,sha256=H_s5HI7lUP7g0xz-a9qMbSn6dhJStUilKbn3-7SIh0I,3812
|
10
|
-
mplang/backend/phe.py,sha256=
|
10
|
+
mplang/backend/phe.py,sha256=uNqmrbDAbd97TWS_O6D5sopastHy6J20R7knFE4M4uc,65247
|
11
11
|
mplang/backend/spu.py,sha256=i6Qqgeg-Anwpb5xX5Uz8GdmTWNkRy_pjp-xptIvlxl4,9273
|
12
12
|
mplang/backend/sql_duckdb.py,sha256=WFEiJk3t68DMpjV9xZz5bJj3v8UMx4X5QWleLIE4Aq0,1499
|
13
13
|
mplang/backend/stablehlo.py,sha256=GOxy-qgOxyEdtBkt6LASKzaZnPewZhvHYSPOgFFXgIM,2612
|
@@ -41,7 +41,7 @@ mplang/frontend/builtin.py,sha256=8qrlbe_SSy6QTXTnMG6_ADB8jSklVZGFBrkoR-p02FE,93
|
|
41
41
|
mplang/frontend/crypto.py,sha256=Nf8zT4Eko7MIs4R2tgZecKVd7d6Hvd_CGGmANhs3Ghs,3651
|
42
42
|
mplang/frontend/ibis_cc.py,sha256=01joUdFS_Ja9--PkezBhEcW_a9mkDrLgOhu5320s_bQ,4167
|
43
43
|
mplang/frontend/jax_cc.py,sha256=ssP6rCvyWQ5VAr80-7z9QZUE2mWXyozJCGpq1dYQYY8,6374
|
44
|
-
mplang/frontend/phe.py,sha256=
|
44
|
+
mplang/frontend/phe.py,sha256=tDsCvStjVJ1Fs07yF3idkFnugUCA1zdFApPx7Uuulik,6795
|
45
45
|
mplang/frontend/spu.py,sha256=yvnXH8HU55t7j_jaTpxa3Nbh0SqXufVDyZBTYCsRTK4,4994
|
46
46
|
mplang/frontend/sql.py,sha256=DFdvjEPQX28VCRgUMeHYR0rwwOaoCH15bpvvlclLtHA,1999
|
47
47
|
mplang/frontend/tee.py,sha256=EigmlbYDGvXkZCMHSYRAiOboSl9TG0ewoudbgl3_V6M,1393
|
@@ -69,8 +69,8 @@ mplang/utils/crypto.py,sha256=rvPomBFtznRHc3RPi6Aip9lsU8zW2oxBqGv1K3vn7Rs,1052
|
|
69
69
|
mplang/utils/func_utils.py,sha256=vCJcZmu0bEbqhOQKdpttV2_MBllIcPSN0b8U4WjNGGo,5164
|
70
70
|
mplang/utils/spu_utils.py,sha256=S3L9RBkBe2AvSuMSQQ12cBY5Y1NPthubvErSX_7nj1A,4158
|
71
71
|
mplang/utils/table_utils.py,sha256=aC-IZOKkSmFkpr3NZchLM0Wt0GOn-rg_xHBHREWBwAU,2202
|
72
|
-
mplang_nightly-0.1.
|
73
|
-
mplang_nightly-0.1.
|
74
|
-
mplang_nightly-0.1.
|
75
|
-
mplang_nightly-0.1.
|
76
|
-
mplang_nightly-0.1.
|
72
|
+
mplang_nightly-0.1.dev143.dist-info/METADATA,sha256=BvANiZEEU0N7uAY_k8Yd4p1rZKGPpdbrM5giBinXzdA,16547
|
73
|
+
mplang_nightly-0.1.dev143.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
74
|
+
mplang_nightly-0.1.dev143.dist-info/entry_points.txt,sha256=mG1oJT-GAjQR834a62_QIWb7litzWPPyVnwFqm-rWuY,55
|
75
|
+
mplang_nightly-0.1.dev143.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
76
|
+
mplang_nightly-0.1.dev143.dist-info/RECORD,,
|
File without changes
|
{mplang_nightly-0.1.dev142.dist-info → mplang_nightly-0.1.dev143.dist-info}/entry_points.txt
RENAMED
File without changes
|
{mplang_nightly-0.1.dev142.dist-info → mplang_nightly-0.1.dev143.dist-info}/licenses/LICENSE
RENAMED
File without changes
|