Cython:如何转换包含赋值的 C 宏
Cython: How to convert C macro containing assignments
假设我有以下要转换为 Cython 的 C 宏。问题是第二个和第三个修改了它们的参数值。如何将其转换为 Cython 中的等效项?
示例(siphash24中使用的一些宏):
#define ROTATE(x, b) (uint64_t)( ((x) << (b)) | ( (x) >> (64 - (b))) )
#define HALF_ROUND(a,b,c,d,s,t) \
a += b; c += d; \
b = ROTATE(b, s) ^ a; \
d = ROTATE(d, t) ^ c; \
a = ROTATE(a, 32);
#define DOUBLE_ROUND(v0,v1,v2,v3) \
HALF_ROUND(v0,v1,v2,v3,13,16); \
HALF_ROUND(v2,v1,v0,v3,17,21); \
HALF_ROUND(v0,v1,v2,v3,13,16); \
HALF_ROUND(v2,v1,v0,v3,17,21);
我试过的:
我开始使用 f-strings 扩展宏,但它有点乱:
def ROTATE(x, b):
return f'<uint64_t>( (({x}) << ({b})) | ( ({x}) >> (64 - ({b}))) )'
def HALF_ROUND(a, b, c, d, s, t):
return f"""
{a} += {b}
{c} += {d}
{b} = {ROTATE(b, s)} ^ {a}
{d} = {ROTATE(d, t)} ^ {c}
{a} = {ROTATE(a, 32)}
"""
def DOUBLE_ROUND(v0, v1, v2, v3):
return f"""
{HALF_ROUND(v0,v1,v2,v3,13,16)}
{HALF_ROUND(v2,v1,v0,v3,17,21)}
{HALF_ROUND(v0,v1,v2,v3,13,16)}
{HALF_ROUND(v2,v1,v0,v3,17,21)}
"""
因此,例如,DOUBLE_ROUND('v0','v1','v2','v3')
扩展为:
v0 += v1
v2 += v3
v1 = <uint64_t>( ((v1) << (13)) | ( (v1) >> (64 - (13))) ) ^ v0
v3 = <uint64_t>( ((v3) << (16)) | ( (v3) >> (64 - (16))) ) ^ v2
v0 = <uint64_t>( ((v0) << (32)) | ( (v0) >> (64 - (32))) )
v2 += v1
v0 += v3
v1 = <uint64_t>( ((v1) << (17)) | ( (v1) >> (64 - (17))) ) ^ v2
v3 = <uint64_t>( ((v3) << (21)) | ( (v3) >> (64 - (21))) ) ^ v0
v2 = <uint64_t>( ((v2) << (32)) | ( (v2) >> (64 - (32))) )
v0 += v1
v2 += v3
v1 = <uint64_t>( ((v1) << (13)) | ( (v1) >> (64 - (13))) ) ^ v0
v3 = <uint64_t>( ((v3) << (16)) | ( (v3) >> (64 - (16))) ) ^ v2
v0 = <uint64_t>( ((v0) << (32)) | ( (v0) >> (64 - (32))) )
v2 += v1
v0 += v3
v1 = <uint64_t>( ((v1) << (17)) | ( (v1) >> (64 - (17))) ) ^ v2
v3 = <uint64_t>( ((v3) << (21)) | ( (v3) >> (64 - (21))) ) ^ v0
v2 = <uint64_t>( ((v2) << (32)) | ( (v2) >> (64 - (32))) )
是否有更好的(输出更易读)的方法?
如果您乐于使用 cdef
函数(即只能从 Cython 调用),那么惯用的方法可能是传递指针而不是值:
cdef void half_round(int* a, int* b, int* c, int* d, int s, int t):
a[0] += b[0]; c[0] += d[0]
b[0] = ROTATE(b[0], s) ^ a[0]
d[0] = ROTATE(d[0], t) ^ c[0]
a[0] = ROTATE(a[0], 32)
您必须取消对指针的引用,这可以像我在此处所做的那样使用 [0]
或 cython.operator.dereference
来完成。你会称它为
half_round(&a, &b, &c, &d, s, t)
如果你想让它更灵活以便它适用于 int
以外的类型,你可以使用 fused types
如果您希望函数可以从 Python 调用,那么您需要使用 def
函数,这会带来 Python 数字不可变的问题。最好的方法可能涉及返回新值的元组:
def half_round(a, b, c, d, s, t):
a += b; c += d
b = rotate(b, s)^a
d = rotate(d, t)^c
a = rotate(a, 32)
return (a, b, c, d)
你称之为:
a, b, c, d = half_round(a, b, c, d, s, t)
假设我有以下要转换为 Cython 的 C 宏。问题是第二个和第三个修改了它们的参数值。如何将其转换为 Cython 中的等效项?
示例(siphash24中使用的一些宏):
#define ROTATE(x, b) (uint64_t)( ((x) << (b)) | ( (x) >> (64 - (b))) )
#define HALF_ROUND(a,b,c,d,s,t) \
a += b; c += d; \
b = ROTATE(b, s) ^ a; \
d = ROTATE(d, t) ^ c; \
a = ROTATE(a, 32);
#define DOUBLE_ROUND(v0,v1,v2,v3) \
HALF_ROUND(v0,v1,v2,v3,13,16); \
HALF_ROUND(v2,v1,v0,v3,17,21); \
HALF_ROUND(v0,v1,v2,v3,13,16); \
HALF_ROUND(v2,v1,v0,v3,17,21);
我试过的:
我开始使用 f-strings 扩展宏,但它有点乱:
def ROTATE(x, b):
return f'<uint64_t>( (({x}) << ({b})) | ( ({x}) >> (64 - ({b}))) )'
def HALF_ROUND(a, b, c, d, s, t):
return f"""
{a} += {b}
{c} += {d}
{b} = {ROTATE(b, s)} ^ {a}
{d} = {ROTATE(d, t)} ^ {c}
{a} = {ROTATE(a, 32)}
"""
def DOUBLE_ROUND(v0, v1, v2, v3):
return f"""
{HALF_ROUND(v0,v1,v2,v3,13,16)}
{HALF_ROUND(v2,v1,v0,v3,17,21)}
{HALF_ROUND(v0,v1,v2,v3,13,16)}
{HALF_ROUND(v2,v1,v0,v3,17,21)}
"""
因此,例如,DOUBLE_ROUND('v0','v1','v2','v3')
扩展为:
v0 += v1
v2 += v3
v1 = <uint64_t>( ((v1) << (13)) | ( (v1) >> (64 - (13))) ) ^ v0
v3 = <uint64_t>( ((v3) << (16)) | ( (v3) >> (64 - (16))) ) ^ v2
v0 = <uint64_t>( ((v0) << (32)) | ( (v0) >> (64 - (32))) )
v2 += v1
v0 += v3
v1 = <uint64_t>( ((v1) << (17)) | ( (v1) >> (64 - (17))) ) ^ v2
v3 = <uint64_t>( ((v3) << (21)) | ( (v3) >> (64 - (21))) ) ^ v0
v2 = <uint64_t>( ((v2) << (32)) | ( (v2) >> (64 - (32))) )
v0 += v1
v2 += v3
v1 = <uint64_t>( ((v1) << (13)) | ( (v1) >> (64 - (13))) ) ^ v0
v3 = <uint64_t>( ((v3) << (16)) | ( (v3) >> (64 - (16))) ) ^ v2
v0 = <uint64_t>( ((v0) << (32)) | ( (v0) >> (64 - (32))) )
v2 += v1
v0 += v3
v1 = <uint64_t>( ((v1) << (17)) | ( (v1) >> (64 - (17))) ) ^ v2
v3 = <uint64_t>( ((v3) << (21)) | ( (v3) >> (64 - (21))) ) ^ v0
v2 = <uint64_t>( ((v2) << (32)) | ( (v2) >> (64 - (32))) )
是否有更好的(输出更易读)的方法?
如果您乐于使用 cdef
函数(即只能从 Cython 调用),那么惯用的方法可能是传递指针而不是值:
cdef void half_round(int* a, int* b, int* c, int* d, int s, int t):
a[0] += b[0]; c[0] += d[0]
b[0] = ROTATE(b[0], s) ^ a[0]
d[0] = ROTATE(d[0], t) ^ c[0]
a[0] = ROTATE(a[0], 32)
您必须取消对指针的引用,这可以像我在此处所做的那样使用 [0]
或 cython.operator.dereference
来完成。你会称它为
half_round(&a, &b, &c, &d, s, t)
如果你想让它更灵活以便它适用于 int
以外的类型,你可以使用 fused types
如果您希望函数可以从 Python 调用,那么您需要使用 def
函数,这会带来 Python 数字不可变的问题。最好的方法可能涉及返回新值的元组:
def half_round(a, b, c, d, s, t):
a += b; c += d
b = rotate(b, s)^a
d = rotate(d, t)^c
a = rotate(a, 32)
return (a, b, c, d)
你称之为:
a, b, c, d = half_round(a, b, c, d, s, t)