#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 */

/* Variables and functions */
int logf(float);
float smrand_gaussianv();
float smrand_uniform_do();
float sqrtf(int);
void smrand_gaussian(int n, float *y) {
  float u1, u2, s;
  if (n % 2) {
    y[--n] = smrand_gaussianv();
  }
  while (n--) {
    do {
      u1 = smrand_uniform_do();
      u2 = smrand_uniform_do();
      s = u1 * u1 + u2 * u2;
    } while (s >= 1);
    s = sqrtf(-2 * logf(s) / s);
    y[n--] = s * u1;
    y[n] = s * u2;
  }
}


x86 assembly (clang, -O0):
<smrand_gaussian>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
mov    %edi,-0x4(%rbp)
mov    %rsi,-0x10(%rbp)
mov    -0x4(%rbp),%eax
mov    $0x2,%ecx
cltd
idiv   %ecx
cmp    $0x0,%edx
je     117f <smrand_gaussian+0x3f>
mov    $0x0,%al
call   1040 <smrand_gaussianv@plt>
mov    -0x10(%rbp),%rax
mov    -0x4(%rbp),%ecx
add    $0xffffffff,%ecx
mov    %ecx,-0x4(%rbp)
movslq %ecx,%rcx
movss  %xmm0,(%rax,%rcx,4)
jmp    1184 <smrand_gaussian+0x44>
mov    -0x4(%rbp),%eax
mov    %eax,%ecx
add    $0xffffffff,%ecx
mov    %ecx,-0x4(%rbp)
cmp    $0x0,%eax
je     1250 <smrand_gaussian+0x110>
jmp    119d <smrand_gaussian+0x5d>
mov    $0x0,%al
call   1060 <smrand_uniform_do@plt>
movss  %xmm0,-0x14(%rbp)
mov    $0x0,%al
call   1060 <smrand_uniform_do@plt>
movss  %xmm0,-0x18(%rbp)
movss  -0x14(%rbp),%xmm0
movss  -0x14(%rbp),%xmm2
movss  -0x18(%rbp),%xmm1
mulss  -0x18(%rbp),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
movss  %xmm0,-0x1c(%rbp)
movss  -0x1c(%rbp),%xmm0
movss  0xe1d(%rip),%xmm1
ucomiss %xmm1,%xmm0
jae    119d <smrand_gaussian+0x5d>
movss  -0x1c(%rbp),%xmm0
call   1030 <logf@plt>
imul   $0xfffffffe,%eax,%eax
cvtsi2ss %eax,%xmm0
divss  -0x1c(%rbp),%xmm0
cvttss2si %xmm0,%edi
call   1050 <sqrtf@plt>
movss  %xmm0,-0x1c(%rbp)
movss  -0x1c(%rbp),%xmm0
mulss  -0x14(%rbp),%xmm0
mov    -0x10(%rbp),%rax
mov    -0x4(%rbp),%ecx
mov    %ecx,%edx
add    $0xffffffff,%edx
mov    %edx,-0x4(%rbp)
movslq %ecx,%rcx
movss  %xmm0,(%rax,%rcx,4)
movss  -0x1c(%rbp),%xmm0
mulss  -0x18(%rbp),%xmm0
mov    -0x10(%rbp),%rax
movslq -0x4(%rbp),%rcx
movss  %xmm0,(%rax,%rcx,4)
jmp    1184 <smrand_gaussian+0x44>
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<smrand_gaussian>:
push   %rbp
push   %rbx
sub    $0x18,%rsp
mov    %rsi,%rbx
mov    %edi,%ebp
test   $0x1,%bpl
je     1164 <smrand_gaussian+0x24>
xor    %eax,%eax
call   1040 <smrand_gaussianv@plt>
movslq %ebp,%rax
add    $0xffffffff,%ebp
movss  %xmm0,-0x4(%rbx,%rax,4)
test   %ebp,%ebp
je     11ff <smrand_gaussian+0xbf>
movslq %ebp,%rbp
nop
xor    %eax,%eax
call   1060 <smrand_uniform_do@plt>
movss  %xmm0,0xc(%rsp)
xor    %eax,%eax
call   1060 <smrand_uniform_do@plt>
movaps %xmm0,%xmm1
movaps %xmm0,%xmm2
mulss  %xmm0,%xmm2
movss  0xc(%rsp),%xmm0
mulss  %xmm0,%xmm0
addss  %xmm2,%xmm0
ucomiss 0xe5d(%rip),%xmm0
jae    1170 <smrand_gaussian+0x30>
movss  %xmm1,0x14(%rsp)
movss  %xmm0,0x10(%rsp)
call   1030 <logf@plt>
add    %eax,%eax
neg    %eax
xorps  %xmm0,%xmm0
cvtsi2ss %eax,%xmm0
divss  0x10(%rsp),%xmm0
cvttss2si %xmm0,%edi
call   1050 <sqrtf@plt>
movss  0xc(%rsp),%xmm1
mulss  %xmm0,%xmm1
movss  %xmm1,-0x4(%rbx,%rbp,4)
movss  0x14(%rsp),%xmm1
mulss  %xmm0,%xmm1
movss  %xmm1,-0x8(%rbx,%rbp,4)
lea    -0x2(%rbp),%rax
mov    %rax,%rbp
test   %eax,%eax
jne    1170 <smrand_gaussian+0x30>
add    $0x18,%rsp
pop    %rbx
pop    %rbp
ret

LLVM IR (-O0):
define void @smrand_gaussian(i32 %0, float* %1) {
%3 = alloca i32
%4 = alloca float*
%5 = alloca float
%6 = alloca float
%7 = alloca float
store i32 %0, i32* %3
store float* %1, float** %4
%8 = load i32, i32* %3
%9 = srem i32 %8, 2
%10 = icmp ne i32 %9, 0
br i1 %10, label %11, label %18
11: ; preds = %2
%12 = call float (...) @smrand_gaussianv()
%13 = load float*, float** %4
%14 = load i32, i32* %3
%15 = add nsw i32 %14, -1
store i32 %15, i32* %3
%16 = sext i32 %15 to i64
%17 = getelementptr inbounds float, float* %13, i64 %16
store float %12, float* %17
br label %18
18: ; preds = %11, %2
br label %19
19: ; preds = %36, %18
%20 = load i32, i32* %3
%21 = add nsw i32 %20, -1
store i32 %21, i32* %3
%22 = icmp ne i32 %20, 0
br i1 %22, label %23, label %60
23: ; preds = %19
br label %24
24: ; preds = %33, %23
%25 = call float (...) @smrand_uniform_do()
store float %25, float* %5
%26 = call float (...) @smrand_uniform_do()
store float %26, float* %6
%27 = load float, float* %5
%28 = load float, float* %5
%29 = load float, float* %6
%30 = load float, float* %6
%31 = fmul float %29, %30
%32 = call float @llvm.fmuladd.f32(float %27, float %28, float %31)
store float %32, float* %7
br label %33
33: ; preds = %24
%34 = load float, float* %7
%35 = fcmp oge float %34, 1.000000e+00
br i1 %35, label %24, label %36
36: ; preds = %33
%37 = load float, float* %7
%38 = call i32 @logf(float %37)
%39 = mul nsw i32 -2, %38
%40 = sitofp i32 %39 to float
%41 = load float, float* %7
%42 = fdiv float %40, %41
%43 = fptosi float %42 to i32
%44 = call float @sqrtf(i32 %43)
store float %44, float* %7
%45 = load float, float* %7
%46 = load float, float* %5
%47 = fmul float %45, %46
%48 = load float*, float** %4
%49 = load i32, i32* %3
%50 = add nsw i32 %49, -1
store i32 %50, i32* %3
%51 = sext i32 %49 to i64
%52 = getelementptr inbounds float, float* %48, i64 %51
store float %47, float* %52
%53 = load float, float* %7
%54 = load float, float* %6
%55 = fmul float %53, %54
%56 = load float*, float** %4
%57 = load i32, i32* %3
%58 = sext i32 %57 to i64
%59 = getelementptr inbounds float, float* %56, i64 %58
store float %55, float* %59
br label %19
60: ; preds = %19
ret void
}

LLVM IR (-O2):
define void @smrand_gaussian(i32 %0, float* nocapture writeonly %1) {
%3 = and i32 %0, 1
%4 = icmp eq i32 %3, 0
br i1 %4, label %10, label %5
5: ; preds = %2
%6 = tail call float (...) @smrand_gaussianv()
%7 = add nsw i32 %0, -1
%8 = sext i32 %7 to i64
%9 = getelementptr inbounds float, float* %1, i64 %8
store float %6, float* %9
br label %10
10: ; preds = %5, %2
%11 = phi i32 [ %7, %5 ], [ %0, %2 ]
%12 = icmp eq i32 %11, 0
br i1 %12, label %38, label %13
13: ; preds = %10
%14 = sext i32 %11 to i64
br label %15
15: ; preds = %13, %23
%16 = phi i64 [ %14, %13 ], [ %32, %23 ]
br label %17
17: ; preds = %15, %17
%18 = tail call float (...) @smrand_uniform_do()
%19 = tail call float (...) @smrand_uniform_do()
%20 = fmul float %19, %19
%21 = tail call float @llvm.fmuladd.f32(float %18, float %18, float %20)
%22 = fcmp ult float %21, 1.000000e+00
br i1 %22, label %23, label %17
23: ; preds = %17
%24 = add nsw i64 %16, -1
%25 = tail call i32 @logf(float %21)
%26 = mul nsw i32 %25, -2
%27 = sitofp i32 %26 to float
%28 = fdiv float %27, %21
%29 = fptosi float %28 to i32
%30 = tail call float @sqrtf(i32 %29)
%31 = fmul float %18, %30
%32 = add i64 %16, -2
%33 = getelementptr inbounds float, float* %1, i64 %24
store float %31, float* %33
%34 = fmul float %19, %30
%35 = getelementptr inbounds float, float* %1, i64 %32
store float %34, float* %35
%36 = trunc i64 %32 to i32
%37 = icmp eq i32 %36, 0
br i1 %37, label %38, label %15
38: ; preds = %23, %10
ret void
}