// File: /workspace/github_cpp_makefile_star2_O3/SilentAssassinMa[P]Sudoku-Solver/SudokuSolver.cpp
// Function: SudokuSolver::SimulatedAnnealing(double, int)
void SudokuSolver::SimulatedAnnealing(double temp, int steps)
{
    if (!isSolvable)
    {
        cout << "Error : The Input Sudoku Is Not Solvable" << endl;
        return;
    }

    /* 
    Here we use 243 - (sum of unique elements) as the energy of the sudoku,
    and we initialize it so that each subsquare containes all integers once only
    */
    cout << "The Original Sudoku is " << endl;
    PrintSudoku(OriginalSudoku);
    cout << endl;

    // Initialization
    for (int i = 1; i <= 9; i++)
    {
        for (int j = 1; j <= 9; j++)
        {
            if ((i % 3) == 1 && (j % 3) == 1)
            {
                int subsquare[10] = {0};
                // Find the missing integers
                for (int m = 0; m < 3; m++)
                {
                    for (int n = 0; n < 3; n++)
                    {
                        if (FindElement(OriginalSudoku, i + m, j + n) != 0)
                        {
                            subsquare[FindElement(OriginalSudoku, i + m, j + n)] = 1;
                        }
                    }
                }

                // Fill the rest
                for (int m = 0; m < 3; m++)
                {
                    for (int n = 0; n < 3; n++)
                    {

                        if (isChangeable[9 * (i + m - 1) + j + n - 1])
                        {
                            for (int l = 1; l <= 9; l++)
                            {
                                if (subsquare[l] == 0)
                                {
                                    Current[9 * (i + m - 1) + j + n - 1] = l;
                                    subsquare[l] = 1;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    srand((unsigned)time(NULL));

    double Temperature = temp < 0 ? 0.25 : temp;
    int MaxSteps = steps <= 0 ? 1e6 : steps;

    int Ebefore = 243 - UniqueElements(Current);

    // start loop
    int step;
    for (step = 0; step < MaxSteps; step++)
    {
        // pick a random block and two random changeable elements

        int xblock = 3 * (rand() % 3) + 1;
        int yblock = 3 * (rand() % 3) + 1;
        int x1, x2, y1, y2;

        do
        {
            x1 = rand() % 3 + xblock;
            y1 = rand() % 3 + yblock;
            x2 = rand() % 3 + xblock;
            y2 = rand() % 3 + yblock;
        } while (!isChangeable[9 * (x1 - 1) + (y1 - 1)] || !isChangeable[9 * (x2 - 1) + (y2 - 1)] ||
                 (x1 == x2 && y1 == y2));

        // exchange the chosen elements
        int temp;
        temp = Current[9 * (x1 - 1) + (y1 - 1)];
        Current[9 * (x1 - 1) + (y1 - 1)] = Current[9 * (x2 - 1) + (y2 - 1)];
        Current[9 * (x2 - 1) + (y2 - 1)] = temp;

        int Eafter = 243 - UniqueElements(Current);

        if (Eafter < Ebefore)
        {
            // cout << step << " " << Eafter << endl;
        }

        if (Eafter == 0)
            break;

        if (exp((Ebefore - Eafter) / Temperature) > (rand() % 10000 / (double)10001))
        {
            Ebefore = Eafter;
        }
        else
        {
            temp = Current[9 * (x1 - 1) + (y1 - 1)];
            Current[9 * (x1 - 1) + (y1 - 1)] = Current[9 * (x2 - 1) + (y2 - 1)];
            Current[9 * (x2 - 1) + (y2 - 1)] = temp;
        }
    }

    if (CheckConsistency(Current))
    {
        cout << "The Filled Sudoku is " << endl;
        PrintSudoku(Current);
    }
    else
    {
        cout << "The Sudoku is not solved, try more steps or different temperature" << endl;
    }

    cout << endl;
    cout << "Total Steps : " << step << endl;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
cmpb $0x0, 0x2e1(%rdi)
je 0x3174
movl %esi, %ebp
movq %rdi, %r14
movapd %xmm0, 0x10(%rsp)
movq 0x3253(%rip), %rbx      # 0x5fd8
leaq 0x1352(%rip), %rsi      # 0x40de
movl $0x17, %edx
movq %rbx, %rdi
callq 0x2190
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2150
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2100
leaq 0x8(%r14), %r12
movq (%r14), %rax
movq %r14, %rdi
movq %r12, %rsi
callq *0x40(%rax)
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2150
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2100
leaq 0x14c(%r14), %r15
movl $0x1, %eax
movl $0xaaaaaaab, %ecx       # imm = 0xAAAAAAAB
xorpd %xmm0, %xmm0
movl %eax, %edx
imulq %rcx, %rdx
shrq $0x21, %rdx
leal (%rdx,%rdx,2), %esi
movl %eax, %edx
subl %esi, %edx
movq %r12, %rsi
movl $0x1, %edi
cmpl $0x1, %edx
jne 0x2ef2
movzbl %dil, %r8d
imull $0xab, %r8d, %r8d
shrl $0x9, %r8d
leal (%r8,%r8,2), %r8d
movl %edi, %r9d
subb %r8b, %r9b
cmpb $0x1, %r9b
jne 0x2ef2
movapd %xmm0, 0x40(%rsp)
movapd %xmm0, 0x30(%rsp)
movq $0x0, 0x50(%rsp)
leaq -0xa(%rdi), %r8
movq %rsi, %r9
xorl %r10d, %r10d
xorl %r11d, %r11d
movslq (%r9,%r11,4), %rbx
testq %rbx, %rbx
je 0x2e84
movl $0x1, 0x30(%rsp,%rbx,4)
incq %r11
cmpq $0x3, %r11
jne 0x2e73
incq %r10
addq $0x24, %r9
cmpq $0x3, %r10
jne 0x2e70
xorl %r9d, %r9d
leaq (%r9,%rax), %r10
leaq (%r10,%r10,8), %r10
addq %r8, %r10
xorl %r11d, %r11d
leaq (%r10,%r11), %rbx
cmpb $0x1, 0x290(%r14,%rbx)
jne 0x2ee0
movl $0x1, %r13d
cmpl $0x0, 0x30(%rsp,%r13,4)
je 0x2ed3
incq %r13
cmpq $0xa, %r13
jne 0x2ec0
jmp 0x2ee0
movl %r13d, (%r15,%rbx,4)
movl $0x1, 0x30(%rsp,%r13,4)
incq %r11
cmpq $0x3, %r11
jne 0x2eab
incq %r9
cmpq $0x3, %r9
jne 0x2e9d
incq %rdi
addq $0x4, %rsi
cmpq $0xa, %rdi
jne 0x2e25
incq %rax
addq $0x24, %r12
cmpq $0xa, %rax
jne 0x2e0c
xorl %r13d, %r13d
xorl %edi, %edi
callq 0x2130
movl %eax, %edi
callq 0x2140
xorpd %xmm0, %xmm0
movapd 0x10(%rsp), %xmm2
movapd %xmm2, %xmm1
cmpltsd %xmm0, %xmm1
movsd 0x1110(%rip), %xmm0     # 0x4050
andpd %xmm1, %xmm0
andnpd %xmm2, %xmm1
orpd %xmm0, %xmm1
movapd %xmm1, 0x60(%rsp)
movq (%r14), %rax
movq %r14, %rdi
movq %r15, %rsi
callq *0x38(%rax)
movl $0xf3, %r12d
subl %eax, %r12d
testl %ebp, %ebp
movl $0xf4240, %eax          # imm = 0xF4240
cmovgl %ebp, %eax
movl %eax, 0x8(%rsp)
movl %r12d, 0xc(%rsp)
movq %r13, 0x28(%rsp)
callq 0x2060
cltq
imulq $0x55555556, %rax, %rcx # imm = 0x55555556
movq %rcx, %rdx
shrq $0x3f, %rdx
shrq $0x20, %rcx
addl %edx, %ecx
leal (%rcx,%rcx,2), %ecx
subl %ecx, %eax
leal (%rax,%rax,2), %ebx
callq 0x2060
cltq
imulq $0x55555556, %rax, %rcx # imm = 0x55555556
movq %rcx, %rdx
shrq $0x3f, %rdx
shrq $0x20, %rcx
addl %edx, %ecx
leal (%rcx,%rcx,2), %ecx
subl %ecx, %eax
leal (%rax,%rax,2), %r8d
movq %rbx, 0x10(%rsp)
movq %r8, %rbx
callq 0x2060
movslq %eax, %r13
imulq $0x55555556, %r13, %rax # imm = 0x55555556
movq %rax, %rcx
shrq $0x3f, %rcx
shrq $0x20, %rax
addl %ecx, %eax
leal (%rax,%rax,2), %eax
subl %eax, %r13d
callq 0x2060
movslq %eax, %r12
imulq $0x55555556, %r12, %rax # imm = 0x55555556
movq %rax, %rcx
shrq $0x3f, %rcx
shrq $0x20, %rax
addl %ecx, %eax
leal (%rax,%rax,2), %eax
subl %eax, %r12d
callq 0x2060
movl %eax, %ebp
callq 0x2060
movq %rbx, %r8
movq 0x10(%rsp), %rdi
leal (%rdi,%r13), %ecx
leal (%rcx,%rcx,8), %ecx
addl %r12d, %ecx
addl %ebx, %ecx
movslq %ecx, %rbx
cmpb $0x1, 0x290(%r14,%rbx)
jne 0x2fcb
movslq %ebp, %rcx
imulq $0x55555556, %rcx, %rdx # imm = 0x55555556
movq %rdx, %rsi
shrq $0x3f, %rsi
shrq $0x20, %rdx
addl %esi, %edx
leal (%rdx,%rdx,2), %edx
subl %edx, %ecx
cltq
imulq $0x55555556, %rax, %rdx # imm = 0x55555556
movq %rdx, %rsi
shrq $0x3f, %rsi
shrq $0x20, %rdx
addl %esi, %edx
leal (%rdx,%rdx,2), %edx
subl %edx, %eax
leal (%rcx,%rdi), %edx
leal (%rdx,%rdx,8), %edx
addl %eax, %edx
addl %r8d, %edx
movslq %edx, %rbp
cmpb $0x1, 0x290(%r14,%rbp)
jne 0x2fcb
cmpl %ecx, %r13d
jne 0x30a2
cmpl %eax, %r12d
je 0x2fcb
movl 0x14c(%r14,%rbx,4), %eax
movl 0x14c(%r14,%rbp,4), %ecx
movl %ecx, 0x14c(%r14,%rbx,4)
movl %eax, 0x14c(%r14,%rbp,4)
movq (%r14), %rax
movq %r14, %rdi
movq %r15, %rsi
callq *0x38(%rax)
cmpl $0xf3, %eax
je 0x3194
movl $0xf3, %r12d
subl %eax, %r12d
movl 0xc(%rsp), %eax
subl %r12d, %eax
cvtsi2sd %eax, %xmm0
divsd 0x60(%rsp), %xmm0
callq 0x2230
movsd %xmm0, 0x10(%rsp)
callq 0x2060
cltq
imulq $0x68db8bad, %rax, %rcx # imm = 0x68DB8BAD
movq %rcx, %rdx
shrq $0x3f, %rdx
sarq $0x2c, %rcx
addl %edx, %ecx
imull $0x2710, %ecx, %ecx     # imm = 0x2710
subl %ecx, %eax
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
divsd 0xf28(%rip), %xmm0      # 0x4058
movsd 0x10(%rsp), %xmm1
ucomisd %xmm0, %xmm1
movq 0x28(%rsp), %r13
ja 0x3156
movl (%r15,%rbx,4), %eax
movl (%r15,%rbp,4), %ecx
movl %ecx, (%r15,%rbx,4)
movl %eax, (%r15,%rbp,4)
movl 0xc(%rsp), %r12d
incl %r13d
cmpl 0x8(%rsp), %r13d
jne 0x2f75
movl 0x8(%rsp), %eax
movl %eax, %r12d
movq 0x2e66(%rip), %rbx      # 0x5fd8
jmp 0x31a0
movq 0x2e5d(%rip), %rbx      # 0x5fd8
leaq 0xf33(%rip), %rsi       # 0x40b5
movl $0x28, %edx
movq %rbx, %rdi
callq 0x2190
jmp 0x327d
movq 0x2e3d(%rip), %rbx      # 0x5fd8
movq 0x28(%rsp), %r12
movq (%r14), %rax
movq %r14, %rdi
movq %r15, %rsi
callq *0x20(%rax)
testb %al, %al
je 0x31f9
leaq 0xf3f(%rip), %rsi       # 0x40f6
movl $0x15, %edx
movq %rbx, %rdi
callq 0x2190
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2150
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2100
movq (%r14), %rax
movq %r14, %rdi
movq %r15, %rsi
callq *0x40(%rax)
jmp 0x3234
leaq 0xf1b(%rip), %rsi       # 0x411b
movl $0x41, %edx
movq %rbx, %rdi
callq 0x2190
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2150
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2100
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2150
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2100
leaq 0xeaa(%rip), %rsi       # 0x410c
movl $0xe, %edx
movq %rbx, %rdi
callq 0x2190
movq %rbx, %rdi
movl %r12d, %esi
callq 0x2210
movq %rax, %rbx
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2150
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2100