// File: /workspace/github_c_makefile_star2_O0/an4[P]Applied-Security-Mod/modmul.c
// Function: Test_montgomery
void Test_montgomery() {
    mpz_t Mp;
	mpz_t Mp_test;
    mpz_t N;
    mpz_t BASE;
	mpz_t Mw;
	mpz_t Mw_test;
	mpz_t Mp_sq;
	mpz_t Mp_sq_test;
	mpz_t x;
    mpz_t x_test;
    mpz_t Mx;
    mpz_t one;
    mpz_t Nx;
    mpz_t y;
    mpz_t r_test;
    mpz_t r;

	// Base 2^64
	// 18446744073709551616
	initialize_and_read(BASE);
	// 18446744073709551629
	initialize_and_read(N);
	// 0x100000000000000000000000000000000
	initialize_and_read(Mp_test);
	// 2^60
	initialize_and_read(x);
    // 2^50-1
    initialize_and_read(y);

	// Test montgomery rho
    montgomery_Mp(Mp, N, BASE);
    assert(mpz_cmp(Mp, Mp_test) == 0);

	// Generate test omega
	mpz_init(Mw_test);
	mpz_invert(Mw_test, N, BASE);
	mpz_neg(Mw_test, Mw_test);
	mpz_add(Mw_test, Mw_test, BASE);
	// 0xb13b13b13b13b13b

	// Test montgomery omega
	montgomery_Mw(Mw, N, BASE);
	assert(mpz_cmp(Mw, Mw_test) == 0);

	// Generate test rho squared
	mpz_init(Mp_sq_test);
	mpz_mul(Mp_sq_test, Mp, Mp);
	mpz_mod(Mp_sq_test, Mp_sq_test, N);
	// 6f91

	// Test montgomery rho squared
	montgomery_Mp_sq(Mp_sq, N);
	assert(mpz_cmp(Mp_sq, Mp_sq_test) == 0);

	// Generate x in montgomery form
    // x = x * p mod N
    mpz_init(x_test);
    mpz_mul(x_test, x, Mp);
    mpz_mod(x_test, x_test, N);
    // 8fffffffffffff7e

    // Test montgomery form
    montgomery_multiplication(Mx, x, Mp_sq, BASE, N, Mw);
    assert(mpz_cmp(Mx, x_test) == 0);

    // Test normal form from montgomery form
    mpz_init_set_ui(one, 1);
    montgomery_multiplication(Nx, Mx, one, BASE, N, Mw);
    assert(mpz_cmp(Nx, x) == 0);

    // Modular multiplication
    mpz_init(r_test);
    mpz_mul(r_test, x, y);
    mpz_mod(r_test, r_test, N);

    // Montgomery modular multiplication
    montgomery(r, x, y, N);
    assert(mpz_cmp(r, r_test) == 0);

    mpz_clear(r);
    mpz_clear(y);
    mpz_clear(r_test);
    mpz_clear(Nx);
    mpz_clear(one);
    mpz_clear(Mp);
    mpz_clear(Mp_test);
    mpz_clear(N);
    mpz_clear(BASE);
    mpz_clear(Mw);
    mpz_clear(Mw_test);
    mpz_clear(Mp_sq);
    mpz_clear(Mp_sq_test);
    mpz_clear(x);
    mpz_clear(x_test);
    mpz_clear(Mx);
}

// Assembly:
subq $0x108, %rsp            # imm = 0x108
leaq 0xc0(%rsp), %rdi
callq 0x22f0
leaq 0xd0(%rsp), %rdi
callq 0x22f0
leaq 0xe0(%rsp), %rdi
callq 0x22f0
leaq 0x70(%rsp), %rdi
callq 0x22f0
leaq 0x20(%rsp), %rdi
callq 0x22f0
leaq 0xf0(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
leaq 0xc0(%rsp), %rdx
callq 0x2760
leaq 0xf0(%rsp), %rdi
leaq 0xe0(%rsp), %rsi
callq 0x4490
cmpl $0x0, %eax
jne 0x38fb
jmp 0x391a
leaq 0x33725(%rip), %rdi     # 0x37027
leaq 0x33738(%rip), %rsi     # 0x37041
movl $0x257, %edx            # imm = 0x257
leaq 0x33735(%rip), %rcx     # 0x3704a
callq 0x20c0
leaq 0xa0(%rsp), %rdi
callq 0x4a80
leaq 0xa0(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
leaq 0xc0(%rsp), %rdx
callq 0x4aa0
leaq 0xa0(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
callq 0x53a0
leaq 0xa0(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
leaq 0xc0(%rsp), %rdx
callq 0x40c0
leaq 0xb0(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
leaq 0xc0(%rsp), %rdx
callq 0x27c0
leaq 0xb0(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
callq 0x4490
cmpl $0x0, %eax
jne 0x39af
jmp 0x39ce
leaq 0x336ab(%rip), %rdi     # 0x37061
leaq 0x33684(%rip), %rsi     # 0x37041
movl $0x262, %edx            # imm = 0x262
leaq 0x33681(%rip), %rcx     # 0x3704a
callq 0x20c0
leaq 0x80(%rsp), %rdi
callq 0x4a80
leaq 0x80(%rsp), %rdi
leaq 0xf0(%rsp), %rsi
leaq 0xf0(%rsp), %rdx
callq 0x4ed0
leaq 0x80(%rsp), %rdi
leaq 0x80(%rsp), %rsi
leaq 0xd0(%rsp), %rdx
callq 0x4d60
leaq 0x90(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
callq 0x2890
leaq 0x90(%rsp), %rdi
leaq 0x80(%rsp), %rsi
callq 0x4490
cmpl $0x0, %eax
jne 0x3a46
jmp 0x3a65
leaq 0x3362e(%rip), %rdi     # 0x3707b
leaq 0x335ed(%rip), %rsi     # 0x37041
movl $0x26c, %edx            # imm = 0x26C
leaq 0x335ea(%rip), %rcx     # 0x3704a
callq 0x20c0
leaq 0x60(%rsp), %rdi
callq 0x4a80
leaq 0x60(%rsp), %rdi
leaq 0x70(%rsp), %rsi
leaq 0xf0(%rsp), %rdx
callq 0x4ed0
leaq 0x60(%rsp), %rdi
leaq 0x60(%rsp), %rsi
leaq 0xd0(%rsp), %rdx
callq 0x4d60
leaq 0x50(%rsp), %rdi
leaq 0x70(%rsp), %rsi
leaq 0x90(%rsp), %rdx
leaq 0xc0(%rsp), %rcx
leaq 0xd0(%rsp), %r8
leaq 0xb0(%rsp), %r9
callq 0x2930
leaq 0x50(%rsp), %rdi
leaq 0x60(%rsp), %rsi
callq 0x4490
cmpl $0x0, %eax
jne 0x3ae2
jmp 0x3b01
leaq 0x335b2(%rip), %rdi     # 0x3709b
leaq 0x33551(%rip), %rsi     # 0x37041
movl $0x277, %edx            # imm = 0x277
leaq 0x3354e(%rip), %rcx     # 0x3704a
callq 0x20c0
leaq 0x40(%rsp), %rdi
movl $0x1, %esi
callq 0x4d20
leaq 0x30(%rsp), %rdi
leaq 0x50(%rsp), %rsi
leaq 0x40(%rsp), %rdx
leaq 0xc0(%rsp), %rcx
leaq 0xd0(%rsp), %r8
leaq 0xb0(%rsp), %r9
callq 0x2930
leaq 0x30(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x4490
cmpl $0x0, %eax
jne 0x3b52
jmp 0x3b71
leaq 0x3355b(%rip), %rdi     # 0x370b4
leaq 0x334e1(%rip), %rsi     # 0x37041
movl $0x27c, %edx            # imm = 0x27C
leaq 0x334de(%rip), %rcx     # 0x3704a
callq 0x20c0
leaq 0x10(%rsp), %rdi
callq 0x4a80
leaq 0x10(%rsp), %rdi
leaq 0x70(%rsp), %rsi
leaq 0x20(%rsp), %rdx
callq 0x4ed0
leaq 0x10(%rsp), %rdi
leaq 0x10(%rsp), %rsi
leaq 0xd0(%rsp), %rdx
callq 0x4d60
movq %rsp, %rdi
leaq 0x70(%rsp), %rsi
leaq 0x20(%rsp), %rdx
leaq 0xd0(%rsp), %rcx
callq 0x2b40
movq %rsp, %rdi
leaq 0x10(%rsp), %rsi
callq 0x4490
cmpl $0x0, %eax
jne 0x3bd4
jmp 0x3bf3
leaq 0x334ed(%rip), %rdi     # 0x370c8
leaq 0x3345f(%rip), %rsi     # 0x37041
movl $0x285, %edx            # imm = 0x285
leaq 0x3345c(%rip), %rcx     # 0x3704a
callq 0x20c0
movq %rsp, %rdi
callq 0x4460
leaq 0x20(%rsp), %rdi
callq 0x4460
leaq 0x10(%rsp), %rdi
callq 0x4460
leaq 0x30(%rsp), %rdi
callq 0x4460
leaq 0x40(%rsp), %rdi
callq 0x4460
leaq 0xf0(%rsp), %rdi
callq 0x4460
leaq 0xe0(%rsp), %rdi
callq 0x4460
leaq 0xd0(%rsp), %rdi
callq 0x4460
leaq 0xc0(%rsp), %rdi
callq 0x4460
leaq 0xb0(%rsp), %rdi
callq 0x4460
leaq 0xa0(%rsp), %rdi
callq 0x4460
leaq 0x90(%rsp), %rdi
callq 0x4460
leaq 0x80(%rsp), %rdi
callq 0x4460
leaq 0x70(%rsp), %rdi
callq 0x4460
leaq 0x60(%rsp), %rdi
callq 0x4460
leaq 0x50(%rsp), %rdi
callq 0x4460
addq $0x108, %rsp            # imm = 0x108
retq
nopw %cs:(%rax,%rax)