// File: /workspace/github_c_makefile_star2_O1/openshmem-org[P]openshmem-examples/c/cpi.c
// Function: main
int
main(int argc, char *argv[])
{
    struct utsname u;
    int myid, numprocs, i;
    double h, sum;
    struct timeval startwtime, endwtime;
    double *pWrkR;              /* symmetric reduction workspace */

    uname(&u);

    shmem_init();
    numprocs = shmem_n_pes();
    myid = shmem_my_pe();

    printf("PE %d on host \"%s\"\n", myid, u.nodename);

    if (myid == 0) {
        if (argc > 1)
            n = atoi(argv[1]);  /* # rectangles on command line */
        else
            n = 10000;          /* default # of rectangles */

        gettimeofday(&startwtime, NULL);
    }

    /* reduction of 1 value: size the workspace accordingly */
    {
        const long pWrkRSize = max2(1 / 2 + 1, SHMEM_REDUCE_MIN_WRKDATA_SIZE);

        pWrkR = (double *) shmem_malloc(pWrkRSize * sizeof(*pWrkR));
    }

    /* initialize sync arrays */
    for (i = 0; i < SHMEM_BCAST_SYNC_SIZE; i += 1) {
        pSyncB[i] = SHMEM_SYNC_VALUE;
    }
    for (i = 0; i < SHMEM_REDUCE_SYNC_SIZE; i += 1) {
        pSyncR[i] = SHMEM_SYNC_VALUE;
    }

    shmem_barrier_all();

    /* -=- set up done -=- */

    /* send "n" out to everyone */
    shmem_broadcast32(&n, &n, 1, 0, 0, 0, numprocs, pSyncB);

    /* do partial computation */
    h = 1.0 / (double) n;
    sum = 0.0;
    /* A slightly better approach starts from large i and works back */
    for (i = myid + 1; i <= n; i += numprocs) {
        const double x = h * ((double) i - 0.5);
        sum += f(x);
    }
    mypi = h * sum;

    /* wait for everyone to finish */
    shmem_barrier_all();

    /* add up partial pi computations into PI */
    shmem_double_sum_to_all(&pi, &mypi, 1, 0, 0, numprocs, pWrkR, pSyncR);

    /* "master" PE summarizes */
    if (myid == 0) {
        double elapsed;
        gettimeofday(&endwtime, NULL);
        elapsed = (endwtime.tv_sec - startwtime.tv_sec) * 1000.0;   /* sec to ms */
        elapsed += (endwtime.tv_usec - startwtime.tv_usec) / 1000.0;    /* us to ms */
        printf("pi is approximately %.16f, Error is %.16f\n",
               pi, fabs(pi - PI25DT));
        printf("run time = %f ms\n", elapsed);
        fflush(stdout);
    }

    shmem_free(pWrkR);

    shmem_finalize();

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x1b0, %rsp            # imm = 0x1B0
movq %rsi, %rbx
movl %edi, %ebp
leaq 0x2a(%rsp), %rdi
callq 0x1040
callq 0x10e0
callq 0x1070
movl %eax, %r15d
callq 0x10a0
movl %eax, %r14d
leaq 0x6b(%rsp), %rdx
leaq 0xdf5(%rip), %rdi       # 0x2040
movl %eax, %esi
xorl %eax, %eax
callq 0x1030
testl %r14d, %r14d
jne 0x127e
movl $0x2710, %eax           # imm = 0x2710
cmpl $0x2, %ebp
jl 0x126c
movq 0x8(%rbx), %rdi
callq 0x10b0
movl %eax, 0x2e3e(%rip)      # 0x40b0
leaq 0x8(%rsp), %rdi
xorl %esi, %esi
callq 0x1050
movl $0x8, %edi
callq 0x10c0
movq %rax, %rbx
pcmpeqd %xmm0, %xmm0
movdqa %xmm0, 0x2e29(%rip)     # 0x40c0
leaq 0x2e22(%rip), %r12      # 0x40c0
movdqa %xmm0, 0x2e2a(%rip)     # 0x40d0
movq $-0x1, 0x2e2f(%rip) # 0x40e0
callq 0x10d0
leaq 0x2df3(%rip), %rdi      # 0x40b0
movl $0x1, %edx
movq %rdi, %rsi
xorl %ecx, %ecx
xorl %r8d, %r8d
xorl %r9d, %r9d
pushq %r12
pushq %r15
callq 0x1060
addq $0x10, %rsp
movl 0x2dd0(%rip), %eax      # 0x40b0
cvtsi2sd %eax, %xmm2
movsd 0xd1c(%rip), %xmm1      # 0x2008
movapd %xmm1, %xmm0
divsd %xmm2, %xmm0
xorpd %xmm2, %xmm2
cmpl %eax, %r14d
jge 0x133b
leal 0x1(%r14), %ecx
movsd 0xd07(%rip), %xmm3      # 0x2010
movsd 0xd07(%rip), %xmm4      # 0x2018
xorps %xmm5, %xmm5
cvtsi2sd %ecx, %xmm5
addsd %xmm3, %xmm5
mulsd %xmm0, %xmm5
mulsd %xmm5, %xmm5
addsd %xmm1, %xmm5
movapd %xmm4, %xmm6
divsd %xmm5, %xmm6
addsd %xmm6, %xmm2
addl %r15d, %ecx
cmpl %eax, %ecx
jle 0x1311
mulsd %xmm2, %xmm0
movsd %xmm0, 0x2da1(%rip)     # 0x40e8
leaq 0x2d9a(%rip), %r12      # 0x40e8
callq 0x10d0
leaq 0x2d76(%rip), %rax      # 0x40d0
leaq 0x2d8f(%rip), %rdi      # 0x40f0
movq %r12, %rsi
movl $0x1, %edx
xorl %ecx, %ecx
xorl %r8d, %r8d
movl %r15d, %r9d
pushq %rax
pushq %rbx
callq 0x1080
addq $0x10, %rsp
testl %r14d, %r14d
jne 0x141a
leaq 0x18(%rsp), %r14
movq %r14, %rdi
xorl %esi, %esi
callq 0x1050
movq (%r14), %rax
subq 0x8(%rsp), %rax
movq 0x8(%r14), %rcx
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
movsd 0xc70(%rip), %xmm1      # 0x2020
subq 0x10(%rsp), %rcx
xorps %xmm2, %xmm2
cvtsi2sd %rcx, %xmm2
mulsd %xmm1, %xmm0
divsd %xmm1, %xmm2
addsd %xmm0, %xmm2
movsd %xmm2, (%rsp)
movsd 0x2d1a(%rip), %xmm0     # 0x40f0
movsd 0xc4a(%rip), %xmm1      # 0x2028
addsd %xmm0, %xmm1
andpd 0xc46(%rip), %xmm1      # 0x2030
leaq 0xc63(%rip), %rdi       # 0x2054
movb $0x2, %al
callq 0x1030
leaq 0xc80(%rip), %rdi       # 0x207f
movsd (%rsp), %xmm0
movb $0x1, %al
callq 0x1030
movq 0x2be6(%rip), %rax      # 0x3ff8
movq (%rax), %rdi
callq 0x1100
movq %rbx, %rdi
callq 0x10f0
callq 0x1090
xorl %eax, %eax
addq $0x1b0, %rsp            # imm = 0x1B0
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq