安全类型:Array (Array accessible by public index.)
所有代码的头两行:
from Compiler import types
n = 5
无特殊说明,测试代码的编译命令:test_array是我的文件名。
./compile.py test_array
测试代码的执行命令:
./emulate.x test_array
目录
2. assign(self, other, base=0)
11. reveal()、reveal_list()、reveal_nested()
14.get_vector 和 get_part_vector
1. __init__()
__init__
(length, value_type, address=None, debug=None, alloc=True)
Parameters: |
|
---|
# test code
n = 5
a = Array(n,sfix)
print_ln("%s", a.reveal())
a.__init__(6,sint)
print_ln("%s", a.reveal())
Array.__init__(a,7,cint)
print_ln("%s", a.reveal())
执行结果:
2. assign(self, other, base=0)
作用:为数组赋值。other代表为数组赋的值的数组。
a = Array(n, sfix)
b = Array(n, sfix)
t = [2,15,21,33,41]
t1 = [100,101,200,12,90]
a.assign(t)
print_ln("a = %s", a.reveal())
b.assign(a)
print_ln("b = %s", b.reveal())
a.assign_vector(t1)
print_ln("a = %s", a.reveal())
a.assign_part_vector(t)
print_ln("a = %s", a.reveal())
另外两个函数与assign一模一样。也就是assign=assign_vector=assign_part_vector。
3. assign_all
assign_all
(value, use_threads=True, conv=True)
Assign the same value to all entries.
Parameters: | value – convertible to basic type |
---|
为一个数组所有元素赋相同的值。
a = Array(n, sfix)
a.assign_all(45)
print_ln("a = %s", a.reveal())
4. __getitem__()
__getitem__
(index)
Reading from array.
Parameters: | index – public (regint/cint/int/slice) |
---|---|
Returns: | array if slice is given, basic type otherwise |
获得数组指定位置的值。
a = Array(n, sfix)
t = [2,15,21,33,41]
a.assign(t)
b = Array.__getitem__(a,1)
print_ln("a = %s", a.__getitem__(2).reveal())
print_ln("b = %s", b.reveal())
5. __setitem__()
__setitem__
(index, value)
Writing to array.
Parameters: |
|
---|
为指定位置的元素赋值。
a = Array(n, sfix)
a.assign([2,15,21,33,41])
print_ln("a = %s", a.reveal())
a.__setitem__(2,99)
print_ln("a = %s", a.reveal())
6. __len__(), total_size()
返回数组的长度。
a = Array(6, sfix)
a.assign([2,15,21,33,41,12])
print_ln("a = %s", a.__len__())
print_ln("a = %s", a.total_size())
这两个函数应该是有区别的,但是我还不知道。想仔细探究的同学可以看看他们的源码。欢迎评论区交流。
7. __iter__()
返回元素的值。源码中使用到了表达式yield,不懂的可以百度下,这里不多解释了。
#源代码
def __iter__(self):
for i in range(self.length):
yield self[i]
#test code
a = Array(6, sfix)
a.assign([2,15,21,33,41,12])
b = a.__iter__()
print_ln("a = %s", b)
print_ln("a = %s", next(b).reveal())
print_ln("a = %s", next(b).reveal())
print_ln("a = %s", next(b).reveal())
print_ln("a = %s", next(b).reveal())
print_ln("a = %s", next(b).reveal())
print_ln("a = %s", next(b).reveal())
8. same_shape()
创建一个和原来数组相同“形状”的数组。这里的“形状”是指新数组与原数组长度相同,元素值的类型相同,但是元素的值并不是复制原数组。
a = Array(6, sfix)
a.assign([2,15,21,33,41,12])
b = Array.same_shape(a)
print_ln("a = %s", a.reveal())
print_ln("b = %s", b.reveal())
9. __str__()
输出数组的信息,包括:数组元素类型、长度、地址。
a = Array(6, sfix)
a.assign([2,15,21,33,41,12])
print_ln("a = %s", a.__str__())
b = Array(10, cint)
b.assign([2,15,21,1,23,34,11,33,41,12])
print_ln("b = %s", b.__str__())
10. create_from()
将一个迭代器转换为一个数组。这是一个类方法(@classmethod)。类方法与某个具体实例本身无关,可以用实例调用它执行相应功能。在这个例子中,我们将迭代器l转换为数组b,迭代器l的属性与数组l0有关,与数组a无关,我们只是使用实例a来调用了函数,但是并没有用到实例a本身的属性和值。
l0 = Array(5, sint)
l = iter(l0)
a = Array(10, cint)
b = a.create_from(l)
print_ln("b = %s", b.reveal())
11. reveal()、reveal_list()、reveal_nested()
返回整个数组的值,其中后两个函数将数组转换成立list输出,这两个函数完全相等(reveal_list=reveal_nested)。
a = Array(6, sfix)
a.assign([2,15,21,33,41,12])
print_ln("a = %s", a.reveal())
print_ln("a = %s", a.reveal_list())
print_ln("a = %s", a.reveal_nested())
12. get()
get(self, indices)。得到指定位置的值。
a = Array(6, sfix)
a.assign([2,15,21,33,41,12])
@for_range(6)
def _(i):
t = sint(i)
c = a.get(t.reveal())
print_ln("a[%s] = %s",i, c.reveal())
13. get_address()
get_address(self, index)。获取数组指定位置的地址。
a = Array(6, sfix)
a.assign([2,15,21,33,41,12])
@for_range(6)
def _(i):
print_ln("a[%s] = %s, a[%s].adress = %s", i, a[i].reveal(), i, a.get_address(i))
14.get_vector 和 get_part_vector
get_vector(self, base=0, size=None)。这两个函数是等价的。
获取从指定位置(base)开始,指定长度(size)的数组。
a = Array(10, sfix)
a.assign([98,75,10,2,21,15,81,33,41,12])
b = a.get_vector(2,5)
c = Array.get_part_vector(a,3,6)
for i in range(0,b.__len__()):
print_str("%s ",b[i].reveal())
print_ln()
for i in range(0,c.__len__()):
print_str("%s ",c[i].reveal())
print_ln()
数组b从数组a的二元素(a[2])开始,截取长度为5
数组c从数组a的三元素(a[3])开始,截取长度为6
注意,数组b,c并不是Array类型的,不能使用
print_ln("b = %s",b.reveal())
来打印,否则会报错。也不能使用@for_range()循环来打印,只能用普通的循环。数组b、c根据函数名字可能是个vector类型,但是spdz并没有vector这个类型,所以不确定它是什么类型。
15. get_mem_value()
get_mem_value(self, index)
返回数组指定位置的值。这里的返回值是一个MemValue类型。
a = Array(10, sfix)
a.assign([98,75,10,2,21,15,81,33,41,12])
b = a.get_mem_value(2)
print_ln("b = %s", b.reveal())
16. get_slice()
get_slice(self, index). 我也不知道这函数是干嘛的,有什么意义。Sorry~~~
传入的index是一个类,这个类包含三个属性:start、stop、step。调用函数就会输出传入的类的属性。
class index:
def __init__(self):
self.start = 0
self.stop = 0
self.step = 0
i = index()
i.start = 12
i.stop = 554
i.step = 4433
a = Array(10, sfix)
a.assign([98,75,10,2,21,15,81,33,41,12])
b = a.get_slice(i)
print_ln("b = %s", b)
17. get_range()
get_range(self, start, size) 获取从指定位置开始,指定长度的数组。与get_vector类似,但是它返回的是list类型,但是元素的类型可以是任何安全类型。
所以打印时要注意,如果你加reveal()会报错list没有这个方法,而不加会报错安全类型的值不能直接打印。
我的方法是把他转换成了Array类型,这样就可以加reve()打印了。
a = Array(10, sfix)
a.assign([98,75,10,2,21,15,81,33,41,12])
b = a.get_range(2,5)
c = Array(len(b),sfix)
c.assign(b)
print_ln("c = %s", c.reveal())
18. set_range()
set_range(self, start, values)
对数组,从指定位置开始,为该位置及以后的元素赋值。start是一个数,values是一个list
a = Array(10, sfix)
a.assign([98,75,10,2,21,15,81,33,41,12])
b = [1,2,3,4]
a.set_range(3,b)
print_ln("a = %s", a.reveal())
19. alloc()、delete()
alloc(): 如果一个数组没有分配内存地址,则为数组分配地址。一般情况你定义一个Array他会自动分配地址的。
delete(): 删除一个数组。通过删除内存地址的方式。
a = Array(10,sfix)
print_ln("a.address: %s", a.address)
a.delete()
print_ln("delete: %s", a.address)
a.alloc()
print_ln("alloc: %s", a.address)
20. _load(), _store()
通过内存地址的方式访问数组数据
_load(self, address):访问内存地址为“address”的数据并返回该数据。
_store(self, value, address):对内存地址为“address”的元素赋值(value)
a = Array(10,sfix)
print_ln("a.address: %s", a.address)
print_ln("a = %s", a.reveal())
b = Array._load(a,a.get_address(1))
print_ln("b = %s", b.reveal())
a._store(12,a.get_address(1))
print_ln("a = %s", a.reveal())
21. expand_to_vector()
expand_to_vector(self, index, size)
返回:复制size个第index个位置的值组成一个数组,这个数组不是Array类型也不是list,与get_vector的返回值类型相同。
a = Array(10,sfix)
a.assign([98,75,10,2,21,15,81,33,41,12])
print_ln("a = %s", a.reveal())
b = a.expand_to_vector(2,5)
for i in range(b.__len__()):
print_str("%s ",b[i].reveal())
print_ln()
22. shuffle()
shuffle(self) shuffle就是洗牌的意思。这个函数可以将一个数组的元素重新打乱顺序,没有返回值。
a = Array(10,sfix)
a.assign([98,75,10,2,21,15,81,33,41,12])
print_ln("a = %s", a.reveal())
for i in range(5):
a.shuffle()
print_ln("a = %s", a.reveal())
23. input_from()
input_from(self, player, budget=None, raw=False) 从参与者手中接收数据。
a = Array(5,sfix)
a.input_from(0)
print_ln("a = %s", a.reveal())
编译程序:
生成证书:
输入数据:
执行程序:
24. 运算
这里的运算都被当作向量运算,它将Array类型转换成之前提到过的“vector”,然后进行运算。返回的结果也是“vector”
__add__() = __radd__():加法:__add__(self, other)
__mul__() = __rmul__():乘法:__mul__(self, value) 元素的值*value
__pow__():幂:__pow__(self, value) 元素的值**value
__sub__():减法:__sub__(self, other)
注意,编译程序时要指定环的模数大小:
./compile.py -R 128 test_array
a = Array(5,sfix)
b = Array(5,sfix)
a.assign([3,4,5,6,7])
b.assign([2,2,2,2,2])
print_ln("a = %s", a.reveal())
print_ln("b = %s", b.reveal())
c = a.__add__(b.get_vector())
print_str("add = ")
for i in range(c.__len__()):
print_str("%s ",c[i].reveal())
print_ln()
d = a.__sub__(b.get_vector())
print_str("sub = ")
for i in range(d.__len__()):
print_str("%s ",d[i].reveal())
print_ln()
c = a.__mul__(3)
print_str("mul = ")
for i in range(c.__len__()):
print_str("%s ",c[i].reveal())
print_ln()
c = a.__pow__(3)
print_str("pow = ")
for i in range(c.__len__()):
print_str("%s ",c[i].reveal())
print_ln()
这里就是Array类型的所有方法了,历时2天半终于写完。呼~~~
大家看到有什么错误的、不对的或者要补充的、要解答的,欢迎在评论区交流~~~