// File: /workspace/github_cpp_makefile_star2_O2/occivink[P]pyct/monocypher.cpp
// Function: invsqrt(int*, int const*)
static int invsqrt(fe isr, const fe x)
{
    fe t0, t1, t2;

    // t0 = x^((p-5)/8)
    // Can be achieved with a simple double & add ladder,
    // but it would be slower.
    fe_sq(t0, x);
    fe_sq(t1,t0);                   fe_sq(t1, t1);  fe_mul(t1, x, t1);
    fe_mul(t0, t0, t1);
    fe_sq(t0, t0);                                  fe_mul(t0, t1, t0);
    fe_sq(t1, t0);  FOR (i, 1,   5) fe_sq(t1, t1);  fe_mul(t0, t1, t0);
    fe_sq(t1, t0);  FOR (i, 1,  10) fe_sq(t1, t1);  fe_mul(t1, t1, t0);
    fe_sq(t2, t1);  FOR (i, 1,  20) fe_sq(t2, t2);  fe_mul(t1, t2, t1);
    fe_sq(t1, t1);  FOR (i, 1,  10) fe_sq(t1, t1);  fe_mul(t0, t1, t0);
    fe_sq(t1, t0);  FOR (i, 1,  50) fe_sq(t1, t1);  fe_mul(t1, t1, t0);
    fe_sq(t2, t1);  FOR (i, 1, 100) fe_sq(t2, t2);  fe_mul(t1, t2, t1);
    fe_sq(t1, t1);  FOR (i, 1,  50) fe_sq(t1, t1);  fe_mul(t0, t1, t0);
    fe_sq(t0, t0);  FOR (i, 1,   2) fe_sq(t0, t0);  fe_mul(t0, t0, x);

    // quartic = x^((p-1)/4)
    i32 *quartic = t1;
    fe_sq (quartic, t0);
    fe_mul(quartic, quartic, x);

    i32 *check = t2;
    fe_0  (check);          int z0 = fe_isequal(x      , check);
    fe_1  (check);          int p1 = fe_isequal(quartic, check);
    fe_neg(check, check );  int m1 = fe_isequal(quartic, check);
    fe_neg(check, sqrtm1);  int ms = fe_isequal(quartic, check);

    // if quartic == -1 or sqrt(-1)
    // then  isr = x^((p-1)/4) * sqrt(-1)
    // else  isr = x^((p-1)/4)
    fe_mul(isr, t0, sqrtm1);
    fe_ccopy(isr, t0, 1 - (m1 | ms));

    WIPE_BUFFER(t0);
    WIPE_BUFFER(t1);
    WIPE_BUFFER(t2);
    return p1 | m1 | z0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movq %rsi, %r14
movq %rdi, 0x8(%rsp)
leaq 0x40(%rsp), %rbx
movq %rbx, %rdi
callq 0x76c3
leaq 0x10(%rsp), %r15
movq %r15, %rdi
movq %rbx, %rsi
callq 0x76c3
movq %r15, %rdi
movq %r15, %rsi
callq 0x76c3
movq %r15, %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x65a5
movq %rbx, %rdi
movq %rbx, %rsi
movq %r15, %rdx
callq 0x65a5
movq %rbx, %rdi
movq %rbx, %rsi
callq 0x76c3
movq %rbx, %rdi
movq %r15, %rsi
movq %rbx, %rdx
callq 0x65a5
movq %r15, %rdi
movq %rbx, %rsi
callq 0x76c3
pushq $0x4
popq %rbx
subq $0x1, %rbx
jb 0x7c2e
movq %r15, %rdi
movq %r15, %rsi
callq 0x76c3
jmp 0x7c1b
leaq 0x10(%rsp), %rbx
leaq 0x40(%rsp), %r15
movq %r15, %rdi
movq %rbx, %rsi
movq %r15, %rdx
callq 0x65a5
movq %rbx, %rdi
movq %r15, %rsi
callq 0x76c3
pushq $0x9
popq %r15
subq $0x1, %r15
jb 0x7c68
movq %rbx, %rdi
movq %rbx, %rsi
callq 0x76c3
jmp 0x7c55
leaq 0x10(%rsp), %r15
leaq 0x40(%rsp), %rdx
movq %r15, %rdi
movq %r15, %rsi
callq 0x65a5
leaq 0x70(%rsp), %rbx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x76c3
pushq $0x13
popq %r15
subq $0x1, %r15
jb 0x7ca4
movq %rbx, %rdi
movq %rbx, %rsi
callq 0x76c3
jmp 0x7c91
leaq 0x70(%rsp), %rsi
leaq 0x10(%rsp), %rbx
movq %rbx, %rdi
movq %rbx, %rdx
callq 0x65a5
movq %rbx, %rdi
movq %rbx, %rsi
callq 0x76c3
pushq $0x9
popq %r15
subq $0x1, %r15
jb 0x7cdb
movq %rbx, %rdi
movq %rbx, %rsi
callq 0x76c3
jmp 0x7cc8
leaq 0x10(%rsp), %rbx
leaq 0x40(%rsp), %r15
movq %r15, %rdi
movq %rbx, %rsi
movq %r15, %rdx
callq 0x65a5
movq %rbx, %rdi
movq %r15, %rsi
callq 0x76c3
pushq $0x31
popq %r15
subq $0x1, %r15
jb 0x7d15
movq %rbx, %rdi
movq %rbx, %rsi
callq 0x76c3
jmp 0x7d02
leaq 0x10(%rsp), %r15
leaq 0x40(%rsp), %rdx
movq %r15, %rdi
movq %r15, %rsi
callq 0x65a5
leaq 0x70(%rsp), %rbx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x76c3
pushq $0x63
popq %r15
subq $0x1, %r15
jb 0x7d51
movq %rbx, %rdi
movq %rbx, %rsi
callq 0x76c3
jmp 0x7d3e
leaq 0x70(%rsp), %rsi
leaq 0x10(%rsp), %rbx
movq %rbx, %rdi
movq %rbx, %rdx
callq 0x65a5
movq %rbx, %rdi
movq %rbx, %rsi
callq 0x76c3
pushq $0x31
popq %r15
subq $0x1, %r15
jb 0x7d88
movq %rbx, %rdi
movq %rbx, %rsi
callq 0x76c3
jmp 0x7d75
leaq 0x10(%rsp), %r15
leaq 0x40(%rsp), %r12
movq %r12, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x65a5
movq %r12, %rdi
movq %r12, %rsi
callq 0x76c3
movq %r12, %rdi
movq %r12, %rsi
callq 0x76c3
movq %r12, %rdi
movq %r12, %rsi
movq %r14, %rdx
callq 0x65a5
movq %r15, %rdi
movq %r12, %rsi
callq 0x76c3
movq %r15, %rdi
movq %r15, %rsi
movq %r14, %rdx
callq 0x65a5
leaq 0x70(%rsp), %r13
movq %r13, %rdi
callq 0x8b07
movq %r14, %rdi
movq %r13, %rsi
callq 0x90bb
movl %eax, 0x4(%rsp)
movq %r13, %rdi
callq 0x8aee
movq %r15, %rdi
movq %r13, %rsi
callq 0x90bb
movl %eax, %r14d
movq %r13, %rdi
movq %r13, %rsi
callq 0x7ed8
movq %r15, %rdi
movq %r13, %rsi
callq 0x90bb
movl %eax, %ebx
leaq 0x4322(%rip), %rsi      # 0xc150
movq %r13, %rdi
callq 0x7ed8
movq %r15, %rdi
movq %r13, %rsi
callq 0x90bb
movl %eax, %r15d
movq 0x8(%rsp), %rbp
movq %rbp, %rdi
movq %r12, %rsi
leaq 0x42fa(%rip), %rdx      # 0xc150
callq 0x65a5
orl %ebx, %r15d
xorl $0x1, %r15d
movq %rbp, %rdi
movq %r12, %rsi
movl %r15d, %edx
callq 0x7eb4
pushq $0x28
popq %r15
movq %r12, %rdi
movq %r15, %rsi
callq 0x25a4
leaq 0x10(%rsp), %rdi
movq %r15, %rsi
callq 0x25a4
movq %r13, %rdi
movq %r15, %rsi
callq 0x25a4
orl 0x4(%rsp), %r14d
orl %ebx, %r14d
movl %r14d, %eax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq