// File: /workspace/github_cpp_makefile_star2_O1/jBlinden[P]private-codis/GenerateOTs.cpp
// Function: main
int main(int argc, char **argv)
{
    if (argc < 3)
    {
        cout << "usage: ./GenerateOTs N config-file" << endl;
        return 1;
    }

    ofstream protocolArgsFile;
    protocolArgsFile.open("./data/info.txt", ios::out | ios::binary);

    ofstream senderOTs1;
    senderOTs1.open("./data/server/sOT.txt", ios::out | ios::binary);

    size_t senderOTFileBytes = senderOTs1.tellp();

    ofstream recieverOTs1;
    recieverOTs1.open("./data/client/rOT.txt", ios::out | ios::binary);
    
    size_t recieverOTFileBytes = recieverOTs1.tellp();

    uint32_t N = atoi(argv[1]);
    char* configFile = argv[2];

    ifstream configReader;
    configReader.open(configFile, ios::in);
    
    uint32_t C;
    uint8_t* bits_per_component = ReadInConfigFile(configReader, C);
    

    uint64_t number_of_OT_correlations = 0;
    uint8_t highest_number_bits = bits_per_component[C - 1];
    uint32_t number_rounds_FSM1 = highest_number_bits / FSM1_StepSize + (highest_number_bits % FSM1_StepSize != 0);
    uint8_t iteration_count_arr_FSM1[number_rounds_FSM1];

    int l = 0;
    int smallest_number_of_bits = 0;
    for (int i = 0; i < number_rounds_FSM1; i++)
    {
        if (l >= bits_per_component[smallest_number_of_bits])
        {
            while(l >= bits_per_component[smallest_number_of_bits])
                smallest_number_of_bits ++;
        }

        int round_step = l + FSM1_StepSize <= highest_number_bits ? FSM1_StepSize : 1;
        iteration_count_arr_FSM1[i] = round_step;

        uint8_t num_states = 2 * pow(2, round_step);
        CreateAndExportOTCorrelation(senderOTs1, recieverOTs1, N * (C - smallest_number_of_bits), num_states, bits_FSM1, bits_FSM1_SOT);
        number_of_OT_correlations += N * (C - smallest_number_of_bits);
        l += round_step;
    }

    uint32_t number_rounds_FSM2 = C / FSM2_StepSize + (C % FSM2_StepSize != 0);

    uint8_t iteration_count_arr_FSM2[number_rounds_FSM2];

    uint8_t count = 0;
    for (int i = 0; i < number_rounds_FSM2; i++)
    {
        int round_step = count + FSM2_StepSize <= C ? FSM2_StepSize : 1;

        iteration_count_arr_FSM2[i] = round_step;
        uint8_t num_states = pow(2, round_step);

        CreateAndExportOTCorrelation(senderOTs1, recieverOTs1, N, 3 * num_states, bits_FSM2, bits_FSM2_SOT);
        number_of_OT_correlations += N;
        count += round_step;
    }

    struct ProtocolArgs pArgs(N, C, iteration_count_arr_FSM1, iteration_count_arr_FSM2, number_rounds_FSM1, number_rounds_FSM2, bits_per_component);

    WriteProtocolArgs(protocolArgsFile, pArgs);

    senderOTFileBytes = (size_t)senderOTs1.tellp() - senderOTFileBytes;
    recieverOTFileBytes = (size_t)recieverOTs1.tellp() - recieverOTFileBytes;
    
    cout << "Number of OT correlations: " << number_of_OT_correlations << endl;
    
    recieverOTs1.close();
    senderOTs1.close();
    protocolArgsFile.close();
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x8b8, %rsp            # imm = 0x8B8
cmpl $0x2, %edi
jg 0x2601
movq 0x5a1c(%rip), %rbx      # 0x7fd8
leaq 0x2a41(%rip), %rsi      # 0x5004
movl $0x22, %edx
movq %rbx, %rdi
callq 0x2290
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2210
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2160
movl $0x1, %eax
jmp 0x2a7b
movq %rsi, %rbx
leaq -0x6d0(%rbp), %r14
movq %r14, %rdi
callq 0x2380
leaq 0x2a0d(%rip), %rsi      # 0x5027
movq %r14, %rdi
movl $0x14, %edx
callq 0x2060
leaq -0x4d0(%rbp), %rdi
callq 0x2380
leaq 0x29fd(%rip), %rsi      # 0x5037
leaq -0x4d0(%rbp), %rdi
movl $0x14, %edx
callq 0x2060
leaq -0x4d0(%rbp), %rdi
callq 0x21c0
leaq -0x2d0(%rbp), %rdi
callq 0x2380
leaq 0x29e3(%rip), %rsi      # 0x504d
leaq -0x2d0(%rbp), %rdi
movl $0x14, %edx
callq 0x2060
leaq -0x2d0(%rbp), %rdi
callq 0x21c0
movq 0x8(%rbx), %rdi
callq 0x2350
movl %eax, %r14d
movq 0x10(%rbx), %rbx
leaq -0x8d8(%rbp), %rdi
callq 0x2270
leaq -0x8d8(%rbp), %rdi
movq %rbx, %rsi
movl $0x8, %edx
callq 0x2140
leaq -0x8d8(%rbp), %rdi
leaq -0x2c(%rbp), %rsi
callq 0x3c41
movl %r14d, -0x30(%rbp)
movq %rsp, -0xa0(%rbp)
movl -0x2c(%rbp), %ecx
decl %ecx
movzbl (%rax,%rcx), %ecx
movl %ecx, %edx
shrl %edx
movl %ecx, -0x48(%rbp)
andl $0x1, %ecx
leal (%rdx,%rcx), %esi
leal 0xf(%rdx,%rcx), %ecx
andl $-0x10, %ecx
movq %rsp, %rdx
subq %rcx, %rdx
movq %rdx, -0x90(%rbp)
movq %rdx, %rsp
xorl %r13d, %r13d
testl %esi, %esi
movq %rax, -0x88(%rbp)
movl %esi, -0x4c(%rbp)
je 0x27cf
movl %esi, %ecx
movq %rcx, -0x40(%rbp)
xorl %r12d, %r12d
xorl %ebx, %ebx
xorl %r15d, %r15d
movq %rbx, -0x38(%rbp)
movslq %r13d, %rdx
movzbl (%rax,%rdx), %ecx
cmpl %ecx, %r15d
jb 0x2747
leal -0x1(%rdx), %r13d
addq %rax, %rdx
movzbl (%rdx), %ecx
incl %r13d
incq %rdx
cmpl %ecx, %r15d
jae 0x2739
leal 0x2(%r15), %eax
cmpl %eax, -0x48(%rbp)
movl $0x2, %r14d
sbbl $0x0, %r14d
movq -0x90(%rbp), %rax
movb %r14b, (%rax,%r12)
vcvtsi2sd %r14d, %xmm1, %xmm0
callq 0x21e0
vaddsd %xmm0, %xmm0, %xmm0
vcvttsd2si %xmm0, %eax
movl -0x2c(%rbp), %edx
subl %r13d, %edx
movl -0x30(%rbp), %ebx
imull %ebx, %edx
movzbl %al, %ecx
leaq -0x4d0(%rbp), %rdi
leaq -0x2d0(%rbp), %rsi
movl $0x4, %r8d
movl $0x1, %r9d
callq 0x372b
movl -0x2c(%rbp), %eax
subl %r13d, %eax
imull %ebx, %eax
movq -0x38(%rbp), %rbx
addq %rax, %rbx
addl %r15d, %r14d
incq %r12
movl %r14d, %r15d
cmpq -0x40(%rbp), %r12
movq -0x88(%rbp), %rax
jne 0x2722
jmp 0x27d1
xorl %ebx, %ebx
movl -0x2c(%rbp), %ecx
movl %ecx, %eax
shrl %eax
andl $0x1, %ecx
addl %eax, %ecx
leaq 0xf(%rcx), %rax
andq $-0x10, %rax
movq %rsp, %rdx
subq %rax, %rdx
movq %rdx, -0x38(%rbp)
movq %rdx, %rsp
testl %ecx, %ecx
movq %rcx, -0x98(%rbp)
je 0x287b
movl -0x30(%rbp), %eax
movq %rax, -0x48(%rbp)
movl %ecx, %eax
movq %rax, -0x40(%rbp)
xorl %r14d, %r14d
movl $0xff, %r12d
xorl %r15d, %r15d
andl %r12d, %r15d
leal 0x2(%r15), %eax
cmpl %eax, -0x2c(%rbp)
movl $0x2, %r13d
sbbl $0x0, %r13d
movq -0x38(%rbp), %rax
movb %r13b, (%rax,%r14)
vcvtsi2sd %r13d, %xmm1, %xmm0
callq 0x21e0
vcvttsd2si %xmm0, %eax
leal (%rax,%rax,2), %ecx
andl %r12d, %ecx
leaq -0x4d0(%rbp), %rdi
leaq -0x2d0(%rbp), %rsi
movl -0x30(%rbp), %edx
movl $0x6, %r8d
movl $0x2, %r9d
callq 0x372b
addq -0x48(%rbp), %rbx
addl %r15d, %r13d
incq %r14
movl %r13d, %r15d
cmpq %r14, -0x40(%rbp)
jne 0x2816
movl -0x2c(%rbp), %eax
movl -0x30(%rbp), %ecx
movl %ecx, -0x80(%rbp)
movl %eax, -0x7c(%rbp)
movl -0x4c(%rbp), %eax
movl %eax, -0x78(%rbp)
movq -0x98(%rbp), %rax
movl %eax, -0x74(%rbp)
movq -0x90(%rbp), %rax
movq %rax, -0x70(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x88(%rbp), %rax
movq %rax, -0x60(%rbp)
movb $0x0, -0x58(%rbp)
movl -0x80(%rbp), %eax
movl -0x7c(%rbp), %ecx
movl -0x78(%rbp), %edx
movl -0x74(%rbp), %edi
movq -0x70(%rbp), %r8
movq -0x68(%rbp), %r9
leaq -0xd0(%rbp), %rsi
movl %eax, (%rsi)
movl %ecx, 0x4(%rsi)
movl %edx, 0x8(%rsi)
movl %edi, 0xc(%rsi)
movq %r8, 0x10(%rsi)
movq %r9, 0x18(%rsi)
movq -0x70(%rbp), %rax
movq %rax, 0x10(%rsi)
movq -0x68(%rbp), %rax
movq %rax, 0x18(%rsi)
movq -0x60(%rbp), %rax
movq %rax, 0x20(%rsi)
movb -0x58(%rbp), %al
movb %al, 0x28(%rsi)
movl -0x57(%rbp), %eax
movl %eax, 0x29(%rsi)
movzwl -0x53(%rbp), %eax
movw %ax, 0x2d(%rsi)
movb -0x51(%rbp), %al
movb %al, 0x2f(%rsi)
leaq -0x6d0(%rbp), %rdi
callq 0x3a6b
leaq -0xd0(%rbp), %rdi
callq 0x3c40
leaq -0x4d0(%rbp), %rdi
callq 0x21c0
leaq -0x2d0(%rbp), %rdi
callq 0x21c0
movq 0x5688(%rip), %rdi      # 0x7fd8
leaq 0x270c(%rip), %rsi      # 0x5063
movl $0x1b, %edx
callq 0x2290
movq 0x5670(%rip), %rdi      # 0x7fd8
movq %rbx, %rsi
callq 0x2150
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2210
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2160
leaq -0x2d0(%rbp), %r15
movq %r15, %rdi
callq 0x2300
leaq -0x4d0(%rbp), %r14
movq %r14, %rdi
callq 0x2300
leaq -0x6d0(%rbp), %rbx
movq %rbx, %rdi
callq 0x2300
leaq -0x80(%rbp), %rdi
callq 0x3c40
movq -0xa0(%rbp), %rsp
leaq -0x8d8(%rbp), %rdi
callq 0x2090
movq 0x55de(%rip), %rax      # 0x7fc8
movq (%rax), %r12
movq 0x18(%rax), %r13
leaq -0x2c8(%rbp), %rdi
movq %r12, -0x8(%rdi)
movq -0x18(%r12), %rax
movq %r13, -0x2d0(%rbp,%rax)
callq 0x21b0
movl $0xf8, %eax
addq %rax, %r15
movq %r15, %rdi
callq 0x20d0
leaq -0x4c8(%rbp), %rdi
movq %r12, -0x8(%rdi)
movq -0x18(%r12), %rax
movq %r13, -0x4d0(%rbp,%rax)
callq 0x21b0
movl $0xf8, %eax
addq %rax, %r14
movl $0xf8, %r15d
movq %r14, %rdi
callq 0x20d0
leaq -0x6c8(%rbp), %rdi
movq %r12, -0x8(%rdi)
movq -0x18(%r12), %rax
movq %r13, -0x6d0(%rbp,%rax)
callq 0x21b0
addq %r15, %rbx
movq %rbx, %rdi
callq 0x20d0
xorl %eax, %eax
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x2abc
jmp 0x2abc
movq %rax, %rbx
leaq -0xd0(%rbp), %rdi
callq 0x3c40
jmp 0x2abf
jmp 0x2acc
jmp 0x2acc
jmp 0x2aa7
jmp 0x2aa7
movq %rax, %rbx
jmp 0x2adb
jmp 0x2ab0
jmp 0x2ab0
movq %rax, %rbx
jmp 0x2ae7
jmp 0x2ab7
movq %rax, %rbx
jmp 0x2af3
movq %rax, %rbx
leaq -0x80(%rbp), %rdi
callq 0x3c40
jmp 0x2acf
jmp 0x2acc
movq %rax, %rbx
leaq -0x8d8(%rbp), %rdi
callq 0x2090
leaq -0x2d0(%rbp), %rdi
callq 0x2320
leaq -0x4d0(%rbp), %rdi
callq 0x2320
leaq -0x6d0(%rbp), %rdi
callq 0x2320
movq %rbx, %rdi
callq 0x23c0
nop