diff --git a/c/buildasm/copy.asm.ejs b/c/buildasm/copy.asm.ejs index d851c5f..6f469b1 100644 --- a/c/buildasm/copy.asm.ejs +++ b/c/buildasm/copy.asm.ejs @@ -79,3 +79,55 @@ u64toLong_adjust_neg: mov [rdi + <%= (i+1)*8 %>], rax <% } %> ret + +;;;;;;;;;;;;;;;;;;;;;; +; toInt +;;;;;;;;;;;;;;;;;;;;;; +; Convert a 64 bit integer to a long format field element +; Params: +; rsi <= Pointer to the element +; Returs: +; rax <= The value +;;;;;;;;;;;;;;;;;;;;;;; +<%=name%>_toInt: + mov rax, [rdi] + bt rax, 63 + jc <%=name%>_long + movsx rax, eax + ret + +<%=name%>_long: + mov rax, [rdi + 8] + mov rcx, rax + shr rcx, 31 + jnz <%=name%>_longNeg +<% for (let i=1; i< n64; i++) { %> + mov rcx, [rdi + <%= i*8+8 %>] + test rcx, rcx + jnz <%=name%>_longNeg +<% } %> + ret + +<%=name%>_longNeg: + mov rax, [rdi + 8] + sub rax, [q] + jnc <%=name%>_longErr +<% for (let i=1; i + mov rcx, [rdi + <%= i*8+8 %>] + sbb rcx, [q + <%= i*8 %>] + jnc <%=name%>_longErr +<% } %> + mov rcx, rax + sar rcx, 31 + add rcx, 1 + jnz <%=name%>_longErr + ret + +<%=name%>_longErr: + push rdi + mov rdi, 0 + call <%=name%>_fail + pop rdi + + + diff --git a/c/buildasm/fr.asm b/c/buildasm/fr.asm index 258fe13..597b1b6 100644 --- a/c/buildasm/fr.asm +++ b/c/buildasm/fr.asm @@ -23,7 +23,10 @@ global Fr_toNormal global Fr_toLongNormal global Fr_toMontgomery + global Fr_toInt + global Fr_isTrue global Fr_q + extern Fr_fail DEFAULT REL section .text @@ -150,6 +153,74 @@ u64toLong_adjust_neg: ret +;;;;;;;;;;;;;;;;;;;;;; +; toInt +;;;;;;;;;;;;;;;;;;;;;; +; Convert a 64 bit integer to a long format field element +; Params: +; rsi <= Pointer to the element +; Returs: +; rax <= The value +;;;;;;;;;;;;;;;;;;;;;;; +Fr_toInt: + mov rax, [rdi] + bt rax, 63 + jc Fr_long + movsx rax, eax + ret + +Fr_long: + mov rax, [rdi + 8] + mov rcx, rax + shr rcx, 31 + jnz Fr_longNeg + + mov rcx, [rdi + 16] + test rcx, rcx + jnz Fr_longNeg + + mov rcx, [rdi + 24] + test rcx, rcx + jnz Fr_longNeg + + mov rcx, [rdi + 32] + test rcx, rcx + jnz Fr_longNeg + + ret + +Fr_longNeg: + mov rax, [rdi + 8] + sub rax, [q] + jnc Fr_longErr + + mov rcx, [rdi + 16] + sbb rcx, [q + 8] + jnc Fr_longErr + + mov rcx, [rdi + 24] + sbb rcx, [q + 16] + jnc Fr_longErr + + mov rcx, [rdi + 32] + sbb rcx, [q + 24] + jnc Fr_longErr + + mov rcx, rax + sar rcx, 31 + add rcx, 1 + jnz Fr_longErr + ret + +Fr_longErr: + push rdi + mov rdi, 0 + call Fr_fail + pop rdi + + + + @@ -1432,6 +1503,7 @@ toLongNormal_fromShort: movsx rsi, eax call rawCopyS2L mov rsi, r8 ; recover rsi + ret @@ -5699,6 +5771,62 @@ lnot_retOne: ret +;;;;;;;;;;;;;;;;;;;;;; +; isTrue +;;;;;;;;;;;;;;;;;;;;;; +; Convert a 64 bit integer to a long format field element +; Params: +; rsi <= Pointer to the element +; Returs: +; rax <= 1 if true 0 if false +;;;;;;;;;;;;;;;;;;;;;;; +Fr_isTrue: + + + + + + + mov rax, [rdi] + bt rax, 63 + jc tmp_64 + + test eax, eax + jz retZero_66 + jmp retOne_65 + +tmp_64: + + mov rax, [rdi + 8] + test rax, rax + jnz retOne_65 + + mov rax, [rdi + 16] + test rax, rax + jnz retOne_65 + + mov rax, [rdi + 24] + test rax, rax + jnz retOne_65 + + mov rax, [rdi + 32] + test rax, rax + jnz retOne_65 + + +retZero_66: + mov qword rax, 0 + jmp done_67 + +retOne_65: + mov qword rax, 1 + +done_67: + + ret + + + section .data diff --git a/c/buildasm/fr.asm.ejs b/c/buildasm/fr.asm.ejs index 83c76a9..6819ec7 100644 --- a/c/buildasm/fr.asm.ejs +++ b/c/buildasm/fr.asm.ejs @@ -23,7 +23,10 @@ global <%=name%>_toNormal global <%=name%>_toLongNormal global <%=name%>_toMontgomery + global <%=name%>_toInt + global <%=name%>_isTrue global <%=name%>_q + extern <%=name%>_fail DEFAULT REL section .text diff --git a/c/buildasm/fr.c b/c/buildasm/fr.c index 37daa3a..62c4d57 100644 --- a/c/buildasm/fr.c +++ b/c/buildasm/fr.c @@ -179,32 +179,7 @@ void Fr_div(PFrElement r, PFrElement a, PFrElement b) { Fr_mul(r, a, &tmp); } -int Fr_isTrue(PFrElement pE) { - if (!(pE->type & Fr_LONG)) return pE->shortVal != 0; - for (int i=0; i< Fr_N64; i++) { - if (pE->longVal[i]) return 1; - } - return 0; -} - -int Fr_toInt(PFrElement pE) { - Fr_toNormal(pE); - if (!(pE->type & Fr_LONG)) { - return pE->shortVal; - } else { - mpz_t ma; - mpz_init(ma); - Fr_toMpz(ma, pE); - if (mpz_fits_sint_p(ma)) { - return mpz_get_si(ma); - } - - mpz_sub(ma, ma, q); - if (mpz_fits_sint_p(ma)) { - return mpz_get_si(ma); - } else { - assert(false); - } - } +void Fr_fail() { + assert(false); } diff --git a/c/buildasm/fr.c.ejs b/c/buildasm/fr.c.ejs index 4ab9200..99033ed 100644 --- a/c/buildasm/fr.c.ejs +++ b/c/buildasm/fr.c.ejs @@ -179,32 +179,7 @@ void <%=name%>_div(P<%=name%>Element r, P<%=name%>Element a, P<%=name%>Element b <%=name%>_mul(r, a, &tmp); } -int <%=name%>_isTrue(P<%=name%>Element pE) { - if (!(pE->type & <%=name%>_LONG)) return pE->shortVal != 0; - for (int i=0; i< <%=name%>_N64; i++) { - if (pE->longVal[i]) return 1; - } - return 0; -} - -int <%=name%>_toInt(P<%=name%>Element pE) { - Fr_toNormal(pE); - if (!(pE->type & <%=name%>_LONG)) { - return pE->shortVal; - } else { - mpz_t ma; - mpz_init(ma); - <%=name%>_toMpz(ma, pE); - if (mpz_fits_sint_p(ma)) { - return mpz_get_si(ma); - } - - mpz_sub(ma, ma, q); - if (mpz_fits_sint_p(ma)) { - return mpz_get_si(ma); - } else { - assert(false); - } - } +void <%=name%>_fail() { + assert(false); } diff --git a/c/buildasm/fr.h b/c/buildasm/fr.h index 6bb0760..31a181a 100644 --- a/c/buildasm/fr.h +++ b/c/buildasm/fr.h @@ -36,6 +36,16 @@ extern "C" void Fr_lnot(PFrElement r, PFrElement a); extern "C" void Fr_toNormal(PFrElement pE); extern "C" void Fr_toLongNormal(PFrElement pE); extern "C" void Fr_toMontgomery(PFrElement pE); + +extern "C" int Fr_isTrue(PFrElement pE); +extern "C" int Fr_toInt(PFrElement pE); + +extern "C" void Fr_fail(); + +extern FrElement Fr_q; + +// Pending functions to convert + void Fr_str2element(PFrElement pE, char const*s); char *Fr_element2str(PFrElement pE); void Fr_idiv(PFrElement r, PFrElement a, PFrElement b); @@ -46,12 +56,9 @@ void Fr_shl(PFrElement r, PFrElement a, PFrElement b); void Fr_shr(PFrElement r, PFrElement a, PFrElement b); void Fr_pow(PFrElement r, PFrElement a, PFrElement b); -int Fr_isTrue(PFrElement pE); -int Fr_toInt(PFrElement pE); void Fr_init(); -extern FrElement Fr_q; #endif // __FR_H diff --git a/c/buildasm/fr.h.ejs b/c/buildasm/fr.h.ejs index ad5fd0f..19e155e 100644 --- a/c/buildasm/fr.h.ejs +++ b/c/buildasm/fr.h.ejs @@ -36,6 +36,16 @@ extern "C" void <%=name%>_lnot(P<%=name%>Element r, P<%=name%>Element a); extern "C" void <%=name%>_toNormal(P<%=name%>Element pE); extern "C" void <%=name%>_toLongNormal(P<%=name%>Element pE); extern "C" void <%=name%>_toMontgomery(P<%=name%>Element pE); + +extern "C" int <%=name%>_isTrue(P<%=name%>Element pE); +extern "C" int <%=name%>_toInt(P<%=name%>Element pE); + +extern "C" void <%=name%>_fail(); + +extern <%=name%>Element <%=name%>_q; + +// Pending functions to convert + void <%=name%>_str2element(P<%=name%>Element pE, char const*s); char *<%=name%>_element2str(P<%=name%>Element pE); void <%=name%>_idiv(P<%=name%>Element r, P<%=name%>Element a, P<%=name%>Element b); @@ -46,12 +56,9 @@ void <%=name%>_shl(P<%=name%>Element r, P<%=name%>Element a, P<%=name%>Element b void <%=name%>_shr(P<%=name%>Element r, P<%=name%>Element a, P<%=name%>Element b); void <%=name%>_pow(P<%=name%>Element r, P<%=name%>Element a, P<%=name%>Element b); -int <%=name%>_isTrue(P<%=name%>Element pE); -int <%=name%>_toInt(P<%=name%>Element pE); void <%=name%>_init(); -extern <%=name%>Element <%=name%>_q; #endif // __<%=name.toUpperCase()%>_H diff --git a/c/buildasm/fr.o b/c/buildasm/fr.o index 3255705..e352655 100644 Binary files a/c/buildasm/fr.o and b/c/buildasm/fr.o differ diff --git a/c/buildasm/logicalops.asm.ejs b/c/buildasm/logicalops.asm.ejs index 1fbbed3..00d90e8 100644 --- a/c/buildasm/logicalops.asm.ejs +++ b/c/buildasm/logicalops.asm.ejs @@ -80,3 +80,18 @@ lnot_retOne: ret +;;;;;;;;;;;;;;;;;;;;;; +; isTrue +;;;;;;;;;;;;;;;;;;;;;; +; Convert a 64 bit integer to a long format field element +; Params: +; rsi <= Pointer to the element +; Returs: +; rax <= 1 if true 0 if false +;;;;;;;;;;;;;;;;;;;;;;; +<%=name%>_isTrue: + <%= isTrue("rax", "rdi") %> + ret + + + diff --git a/c/buildasm/main.c b/c/buildasm/main.c index 7eb607f..d33cefb 100644 --- a/c/buildasm/main.c +++ b/c/buildasm/main.c @@ -1,13 +1,15 @@ #include #include +#include #include "fr.h" int main() { - + Fr_init(); +/* FrElement a = { 0, Fr_LONGMONTGOMERY, {1,1,1,1}}; FrElement b = { 0, Fr_LONGMONTGOMERY, {2,2,2,2}}; -/* + FrElement a={0x43e1f593f0000000ULL,0x2833e84879b97091ULL,0xb85045b68181585dULL,0x30644e72e131a029ULL}; FrElement b = {3,0,0,0}; @@ -24,6 +26,7 @@ int main() { Fr_mul(&c,&a, &b); */ +/* FrElement a1[10]; FrElement a2[10]; for (int i=0; i<10; i++) { @@ -43,6 +46,19 @@ int main() { free(c1); free(c2); } +*/ + + int tests[7] = { 0, 1, 2, -1, -2, 0x7FFFFFFF, (int)0x80000000}; + for (int i=0; i<7;i++) { + FrElement a = { tests[i], Fr_SHORT, {0,0,0,0}}; + Fr_toLongNormal(&a); + int b = Fr_toInt(&a); + int c = Fr_isTrue(&a); + printf("%d, %d, %d\n", tests[i], b, c); + } + + FrElement err = { 0, Fr_LONGMONTGOMERY, {1,1,1,1}}; + Fr_toInt(&err); // printf("%llu, %llu, %llu, %llu\n", c.longVal[0], c.longVal[1], c.longVal[2], c.longVal[3]); } diff --git a/c/buildasm/montgomery.asm.ejs b/c/buildasm/montgomery.asm.ejs index 097fad7..6cb2f58 100644 --- a/c/buildasm/montgomery.asm.ejs +++ b/c/buildasm/montgomery.asm.ejs @@ -338,4 +338,5 @@ toLongNormal_fromShort: movsx rsi, eax call rawCopyS2L mov rsi, r8 ; recover rsi + ret diff --git a/c/buildasm/tester.cpp b/c/buildasm/tester.cpp index 07792ce..95b2d2a 100644 --- a/c/buildasm/tester.cpp +++ b/c/buildasm/tester.cpp @@ -139,6 +139,7 @@ void processLine(std::string &line) { int main(void) { + Fr_init(); fillMap(); std::string line; int i=0; diff --git a/test/fieldasm.js b/test/fieldasm.js index 20d5a75..60146ec 100644 --- a/test/fieldasm.js +++ b/test/fieldasm.js @@ -13,7 +13,6 @@ const mnt6753r = new bigInt("418984909679189534023442147912406371281707099199539 describe("field asm test", function () { this.timeout(1000000000); -/* it("bn128r add", async () => { const tv = buildTestVector2(bn128r, "add"); await tester(bn128r, tv); @@ -255,7 +254,6 @@ describe("field asm test", function () { const tv = buildTestVector2(mnt6753q, "div"); await tester(mnt6753q, tv); }); -*/ it("bn128r square", async () => { const tv = buildTestVector1(bn128r, "square"); await tester(bn128r, tv);