#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */
typedef double c;

/* Variables and functions */
scalar_t__ frand();
int /*<<< orphan*/ printf(char *, double, double);
int rand_disc(int n, double *p) {
  int i;
  double c = 0.0, r = (double)frand();
  for (i = 0; i < n; i++) {
    c += p[i];
    if (r <= c) {
      return i + 1;
    }
  }
  if (!((((c) - (1.0)) < 0.0 ? -((c) - (1.0)) : ((c) - (1.0))) > 0.000001
            ? 0
            : 1)) {
    printf("*** rand_disc warning : \n"
           "    r = %g, probabilities do not add up to 1.0 : c = %f\n",
           r, c);
  }
  return n;
}


x86 assembly (clang, -O0):
<rand_disc>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
mov    %edi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x20(%rbp)
mov    $0x0,%al
call   1040 <frand@plt>
cvtsi2sd %rax,%xmm0
movsd  %xmm0,-0x28(%rbp)
movl   $0x0,-0x14(%rbp)
mov    -0x14(%rbp),%eax
cmp    -0x8(%rbp),%eax
jge    11a7 <rand_disc+0x87>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
addsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  -0x28(%rbp),%xmm1
movsd  -0x20(%rbp),%xmm0
ucomisd %xmm1,%xmm0
jb     1194 <rand_disc+0x74>
mov    -0x14(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x4(%rbp)
jmp    125e <rand_disc+0x13e>
jmp    1199 <rand_disc+0x79>
mov    -0x14(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x14(%rbp)
jmp    114f <rand_disc+0x2f>
movsd  -0x20(%rbp),%xmm1
movsd  0xe4c(%rip),%xmm0
subsd  %xmm0,%xmm1
xorps  %xmm0,%xmm0
ucomisd %xmm1,%xmm0
jbe    11f7 <rand_disc+0xd7>
movsd  -0x20(%rbp),%xmm0
movsd  0xe2e(%rip),%xmm1
subsd  %xmm1,%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x30(%rbp)
jmp    120d <rand_disc+0xed>
movsd  -0x20(%rbp),%xmm0
movsd  0xdfc(%rip),%xmm1
subsd  %xmm1,%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x30(%rbp),%xmm0
movsd  0xdee(%rip),%xmm1
ucomisd %xmm1,%xmm0
jbe    1233 <rand_disc+0x113>
xor    %eax,%eax
test   $0x1,%al
jne    1258 <rand_disc+0x138>
jmp    1242 <rand_disc+0x122>
mov    $0x1,%al
test   $0x1,%al
jne    1258 <rand_disc+0x138>
jmp    1242 <rand_disc+0x122>
movsd  -0x28(%rbp),%xmm0
movsd  -0x20(%rbp),%xmm1
lea    0xdbd(%rip),%rdi
call   1030 <printf@plt>
mov    -0x8(%rbp),%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<rand_disc>:
push   %rbp
push   %rbx
push   %rax
mov    %rsi,%rbx
mov    %edi,%ebp
xor    %eax,%eax
call   1040 <frand@plt>
cvtsi2sd %rax,%xmm0
xorpd  %xmm2,%xmm2
xorpd  %xmm1,%xmm1
test   %ebp,%ebp
jle    1164 <rand_disc+0x44>
mov    %ebp,%ecx
xorpd  %xmm1,%xmm1
xor    %eax,%eax
nopl   0x0(%rax,%rax,1)
addsd  (%rbx,%rax,8),%xmm1
ucomisd %xmm0,%xmm1
jae    11a9 <rand_disc+0x89>
add    $0x1,%rax
cmp    %rax,%rcx
jne    1150 <rand_disc+0x30>
movsd  0xe94(%rip),%xmm3
addsd  %xmm1,%xmm3
movapd 0xe98(%rip),%xmm4
xorpd  %xmm3,%xmm4
movapd %xmm3,%xmm5
cmpltsd %xmm2,%xmm5
andpd  %xmm5,%xmm4
andnpd %xmm3,%xmm5
orpd   %xmm4,%xmm5
ucomisd 0xe6f(%rip),%xmm5
jbe    11ae <rand_disc+0x8e>
lea    0xe7e(%rip),%rdi
call   1030 <printf@plt>
jmp    11ae <rand_disc+0x8e>
add    $0x1,%eax
mov    %eax,%ebp
mov    %ebp,%eax
add    $0x8,%rsp
pop    %rbx
pop    %rbp
ret

LLVM IR (-O0):
@.str = [82 x i8] c"*** rand_disc warning : \0A r = %g, probabilities do not add up to 1.0 : c = %f\0A\00"
define i32 @rand_disc(i32 %0, double* %1) {
%3 = alloca i32
%4 = alloca i32
%5 = alloca double*
%6 = alloca i32
%7 = alloca double
%8 = alloca double
store i32 %0, i32* %4
store double* %1, double** %5
store double 0.000000e+00, double* %7
%9 = call i64 (...) @frand()
%10 = sitofp i64 %9 to double
store double %10, double* %8
store i32 0, i32* %6
br label %11
11: ; preds = %30, %2
%12 = load i32, i32* %6
%13 = load i32, i32* %4
%14 = icmp slt i32 %12, %13
br i1 %14, label %15, label %33
15: ; preds = %11
%16 = load double*, double** %5
%17 = load i32, i32* %6
%18 = sext i32 %17 to i64
%19 = getelementptr inbounds double, double* %16, i64 %18
%20 = load double, double* %19
%21 = load double, double* %7
%22 = fadd double %21, %20
store double %22, double* %7
%23 = load double, double* %8
%24 = load double, double* %7
%25 = fcmp ole double %23, %24
br i1 %25, label %26, label %29
26: ; preds = %15
%27 = load i32, i32* %6
%28 = add nsw i32 %27, 1
store i32 %28, i32* %3
br label %55
29: ; preds = %15
br label %30
30: ; preds = %29
%31 = load i32, i32* %6
%32 = add nsw i32 %31, 1
store i32 %32, i32* %6
br label %11
33: ; preds = %11
%34 = load double, double* %7
%35 = fsub double %34, 1.000000e+00
%36 = fcmp olt double %35, 0.000000e+00
br i1 %36, label %37, label %41
37: ; preds = %33
%38 = load double, double* %7
%39 = fsub double %38, 1.000000e+00
%40 = fneg double %39
br label %44
41: ; preds = %33
%42 = load double, double* %7
%43 = fsub double %42, 1.000000e+00
br label %44
44: ; preds = %41, %37
%45 = phi double [ %40, %37 ], [ %43, %41 ]
%46 = fcmp ogt double %45, 0x3EB0C6F7A0B5ED8D
br i1 %46, label %47, label %48
47: ; preds = %44
br i1 false, label %53, label %49
48: ; preds = %44
br i1 true, label %53, label %49
49: ; preds = %48, %47
%50 = load double, double* %8
%51 = load double, double* %7
%52 = call i32 @printf(i8* getelementptr inbounds ([82 x i8], [82 x i8]* @.str, i64 0, i64 0), double %50, double %51)
br label %53
53: ; preds = %49, %48, %47
%54 = load i32, i32* %4
store i32 %54, i32* %3
br label %55
55: ; preds = %53, %26
%56 = load i32, i32* %3
ret i32 %56
}

LLVM IR (-O2):
@.str = [82 x i8] c"*** rand_disc warning : \0A r = %g, probabilities do not add up to 1.0 : c = %f\0A\00"
define i32 @rand_disc(i32 %0, double* nocapture %1) {
%3 = tail call i64 (...) @frand()
%4 = sitofp i64 %3 to double
%5 = icmp sgt i32 %0, 0
br i1 %5, label %6, label %21
6: ; preds = %2
%7 = zext i32 %0 to i64
br label %8
8: ; preds = %6, %18
%9 = phi i64 [ 0, %6 ], [ %19, %18 ]
%10 = phi double [ 0.000000e+00, %6 ], [ %13, %18 ]
%11 = getelementptr inbounds double, double* %1, i64 %9
%12 = load double, double* %11
%13 = fadd double %10, %12
%14 = fcmp ult double %13, %4
br i1 %14, label %18, label %15
15: ; preds = %8
%16 = trunc i64 %9 to i32
%17 = add nuw nsw i32 %16, 1
br label %30
18: ; preds = %8
%19 = add nuw nsw i64 %9, 1
%20 = icmp eq i64 %19, %7
br i1 %20, label %21, label %8
21: ; preds = %18, %2
%22 = phi double [ 0.000000e+00, %2 ], [ %13, %18 ]
%23 = fadd double %22, -1.000000e+00
%24 = fcmp olt double %23, 0.000000e+00
%25 = fneg double %23
%26 = select i1 %24, double %25, double %23
%27 = fcmp ogt double %26, 0x3EB0C6F7A0B5ED8D
br i1 %27, label %28, label %30
28: ; preds = %21
%29 = tail call i32 @printf(i8* getelementptr inbounds ([82 x i8], [82 x i8]* @.str, i64 0, i64 0), double %4, double %22)
br label %30
30: ; preds = %28, %21, %15
%31 = phi i32 [ %17, %15 ], [ %0, %21 ], [ %0, %28 ]
ret i32 %31
}