// File: /workspace/github_cpp_makefile_star2_O3/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
movl $0xa, %esi
movq -0x18(%rax), %rdi
addq %rbx, %rdi
callq 0x2210
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2160
movl $0x1, %eax
jmp 0x2a7a
leaq -0x6d0(%rbp), %r14
movq %rsi, %rbx
movq %r14, %rdi
callq 0x2380
leaq 0x2a0d(%rip), %rsi      # 0x5027
movl $0x14, %edx
movq %r14, %rdi
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
movq 0x10(%rbx), %rbx
movl %eax, %r14d
leaq -0x8d8(%rbp), %rdi
callq 0x2270
leaq -0x8d8(%rbp), %rdi
movl $0x8, %edx
movq %rbx, %rsi
callq 0x2140
leaq -0x8d8(%rbp), %rdi
leaq -0x2c(%rbp), %rsi
callq 0x3c55
movl -0x2c(%rbp), %ecx
movl %r14d, -0x30(%rbp)
movq %rsp, -0x90(%rbp)
decl %ecx
movzbl (%rax,%rcx), %ecx
movl %ecx, %edx
movl %ecx, -0x38(%rbp)
shrl %edx
andl $0x1, %ecx
leal (%rdx,%rcx), %esi
leal 0xf(%rdx,%rcx), %ecx
movq %rsp, %rdx
andl $-0x10, %ecx
subq %rcx, %rdx
movq %rdx, -0x88(%rbp)
movq %rdx, %rsp
movq %rsi, -0x80(%rbp)
movq %rax, -0x78(%rbp)
testl %esi, %esi
je 0x27c7
xorl %r13d, %r13d
xorl %ebx, %ebx
xorl %r15d, %r15d
xorl %r12d, %r12d
movslq %r15d, %rdx
movq %rbx, -0x40(%rbp)
movzbl (%rax,%rdx), %ecx
cmpl %ecx, %r12d
jb 0x273f
leal -0x1(%rdx), %r15d
addq %rax, %rdx
movzbl (%rdx), %ecx
incl %r15d
incq %rdx
cmpl %ecx, %r12d
jae 0x2731
leal 0x2(%r12), %eax
movl $0x2, %r14d
cmpl %eax, -0x38(%rbp)
movq -0x88(%rbp), %rax
sbbl $0x0, %r14d
vcvtsi2sd %r14d, %xmm1, %xmm0
movb %r14b, (%rax,%r13)
callq 0x21e0
movl -0x2c(%rbp), %edx
movl -0x30(%rbp), %ebx
vaddsd %xmm0, %xmm0, %xmm0
vcvttsd2si %xmm0, %eax
movzbl %al, %ecx
subl %r15d, %edx
imull %ebx, %edx
leaq -0x4d0(%rbp), %rdi
leaq -0x2d0(%rbp), %rsi
movl $0x4, %r8d
movl $0x1, %r9d
callq 0x3743
movl -0x2c(%rbp), %edx
movq -0x78(%rbp), %rax
addl %r12d, %r14d
incq %r13
movl %r14d, %r12d
movl %edx, %ecx
subl %r15d, %ecx
imull %ebx, %ecx
movq -0x40(%rbp), %rbx
addq %rcx, %rbx
cmpq -0x80(%rbp), %r13
jne 0x271a
jmp 0x27cc
movl -0x2c(%rbp), %edx
xorl %ebx, %ebx
movl %edx, %esi
movl %edx, %ecx
shrl %ecx
andl $0x1, %esi
movq %rsp, %rdi
addl %ecx, %esi
leaq 0xf(%rsi), %rcx
andq $-0x10, %rcx
subq %rcx, %rdi
movq %rdi, -0x40(%rbp)
movq %rdi, %rsp
movq %rsi, -0x38(%rbp)
testl %esi, %esi
je 0x2882
movl -0x30(%rbp), %eax
movl $0xff, %r12d
xorl %r14d, %r14d
xorl %r13d, %r13d
movq %rax, -0x98(%rbp)
andl %r12d, %r13d
movl $0x2, %r15d
leal 0x2(%r13), %eax
cmpl %eax, -0x2c(%rbp)
movq -0x40(%rbp), %rax
sbbl $0x0, %r15d
vcvtsi2sd %r15d, %xmm1, %xmm0
movb %r15b, (%rax,%r14)
callq 0x21e0
vcvttsd2si %xmm0, %eax
leal (%rax,%rax,2), %ecx
andl %r12d, %ecx
movl -0x30(%rbp), %edx
leaq -0x4d0(%rbp), %rdi
leaq -0x2d0(%rbp), %rsi
movl $0x6, %r8d
movl $0x2, %r9d
callq 0x3743
addq -0x98(%rbp), %rbx
addl %r13d, %r15d
incq %r14
movl %r15d, %r13d
cmpq %r14, -0x38(%rbp)
jne 0x280e
movl -0x2c(%rbp), %edx
movl -0x30(%rbp), %ecx
movq -0x78(%rbp), %rax
jmp 0x2885
movl -0x30(%rbp), %ecx
movl %ecx, -0x70(%rbp)
movq -0x80(%rbp), %rcx
movl %edx, -0x6c(%rbp)
movq -0x88(%rbp), %rsi
movl %ecx, -0x68(%rbp)
movq -0x38(%rbp), %rcx
movl %ecx, -0x64(%rbp)
movq -0x40(%rbp), %rcx
movq %rsi, -0x60(%rbp)
leaq -0xd0(%rbp), %rsi
movq %rcx, -0x58(%rbp)
movq %rax, -0x50(%rbp)
movb $0x0, -0x48(%rbp)
movl -0x6c(%rbp), %ecx
movl -0x68(%rbp), %edx
movq -0x60(%rbp), %r8
movq -0x58(%rbp), %r9
movq -0x60(%rbp), %r10
movl -0x70(%rbp), %eax
movl -0x64(%rbp), %edi
movq -0x58(%rbp), %r11
movq %r8, 0x10(%rsi)
movq %r9, 0x18(%rsi)
movl %ecx, 0x4(%rsi)
movl %edx, 0x8(%rsi)
movzwl -0x43(%rbp), %edx
movq %r10, 0x10(%rsi)
movq -0x50(%rbp), %r10
movb -0x48(%rbp), %r9b
movl -0x47(%rbp), %r8d
movb -0x41(%rbp), %cl
movl %eax, (%rsi)
movl %edi, 0xc(%rsi)
movq %r11, 0x18(%rsi)
movq %r10, 0x20(%rsi)
movb %r9b, 0x28(%rsi)
movl %r8d, 0x29(%rsi)
movw %dx, 0x2d(%rsi)
movb %cl, 0x2f(%rsi)
leaq -0x6d0(%rbp), %rdi
callq 0x3a7e
leaq -0xd0(%rbp), %rdi
callq 0x3c54
leaq -0x4d0(%rbp), %rdi
callq 0x21c0
leaq -0x2d0(%rbp), %rdi
callq 0x21c0
movq 0x5689(%rip), %rdi      # 0x7fd8
leaq 0x270d(%rip), %rsi      # 0x5063
movl $0x1b, %edx
callq 0x2290
movq 0x5671(%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 -0x70(%rbp), %rdi
callq 0x3c54
movq -0x90(%rbp), %rsp
leaq -0x8d8(%rbp), %rdi
callq 0x2090
movq 0x55df(%rip), %rax      # 0x7fc8
leaq -0x2c8(%rbp), %rdi
movq (%rax), %r12
movq 0x18(%rax), %r13
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
movl $0xf8, %r15d
addq %rax, %r14
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 0x2abb
jmp 0x2abb
leaq -0xd0(%rbp), %rdi
movq %rax, %rbx
callq 0x3c54
jmp 0x2abe
jmp 0x2acb
jmp 0x2acb
jmp 0x2aa6
jmp 0x2aa6
movq %rax, %rbx
jmp 0x2ada
jmp 0x2aaf
jmp 0x2aaf
movq %rax, %rbx
jmp 0x2ae6
jmp 0x2ab6
movq %rax, %rbx
jmp 0x2af2
movq %rax, %rbx
leaq -0x70(%rbp), %rdi
callq 0x3c54
jmp 0x2ace
jmp 0x2acb
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