#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 */
double floor(double);
double lcg_rand(int N, double SEED, double *DUNIF, int NDIM) {
  int i;
  double DZ, DOVER, DZ1, DZ2, DOVER1, DOVER2;
  double DTWO31, DMDLS, DA1, DA2;
  DTWO31 = 2147483648.0;
  DMDLS = 2147483647.0;
  DA1 = 41160.0;
  DA2 = 950665216.0;
  DZ = SEED;
  if (N > NDIM)
    N = NDIM;
  for (i = 1; i <= N; i++) {
    DZ = floor(DZ);
    DZ1 = DZ * DA1;
    DZ2 = DZ * DA2;
    DOVER1 = floor(DZ1 / DTWO31);
    DOVER2 = floor(DZ2 / DTWO31);
    DZ1 = DZ1 - DOVER1 * DTWO31;
    DZ2 = DZ2 - DOVER2 * DTWO31;
    DZ = DZ1 + DZ2 + DOVER1 + DOVER2;
    DOVER = floor(DZ / DMDLS);
    DZ = DZ - DOVER * DMDLS;
    DUNIF[i - 1] = DZ / DMDLS;
    SEED = DZ;
  }
  return SEED;
}


x86 assembly (clang, -O0):
<lcg_rand>:
push   %rbp
mov    %rsp,%rbp
sub    $0x70,%rsp
mov    %edi,-0x4(%rbp)
movsd  %xmm0,-0x10(%rbp)
mov    %rsi,-0x18(%rbp)
mov    %edx,-0x1c(%rbp)
movsd  0xee9(%rip),%xmm0
movsd  %xmm0,-0x58(%rbp)
movsd  0xed4(%rip),%xmm0
movsd  %xmm0,-0x60(%rbp)
movsd  0xebf(%rip),%xmm0
movsd  %xmm0,-0x68(%rbp)
movsd  0xeaa(%rip),%xmm0
movsd  %xmm0,-0x70(%rbp)
movsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
mov    -0x4(%rbp),%eax
cmp    -0x1c(%rbp),%eax
jle    1177 <lcg_rand+0x67>
mov    -0x1c(%rbp),%eax
mov    %eax,-0x4(%rbp)
movl   $0x1,-0x20(%rbp)
mov    -0x20(%rbp),%eax
cmp    -0x4(%rbp),%eax
jg     12d9 <lcg_rand+0x1c9>
movsd  -0x28(%rbp),%xmm0
call   1030 <floor@plt>
movsd  %xmm0,-0x28(%rbp)
movsd  -0x28(%rbp),%xmm0
mulsd  -0x68(%rbp),%xmm0
movsd  %xmm0,-0x38(%rbp)
movsd  -0x28(%rbp),%xmm0
mulsd  -0x70(%rbp),%xmm0
movsd  %xmm0,-0x40(%rbp)
movsd  -0x38(%rbp),%xmm0
divsd  -0x58(%rbp),%xmm0
call   1030 <floor@plt>
movsd  %xmm0,-0x48(%rbp)
movsd  -0x40(%rbp),%xmm0
divsd  -0x58(%rbp),%xmm0
call   1030 <floor@plt>
movsd  %xmm0,-0x50(%rbp)
movsd  -0x38(%rbp),%xmm1
movsd  -0x48(%rbp),%xmm0
movsd  -0x58(%rbp),%xmm2
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x38(%rbp)
movsd  -0x40(%rbp),%xmm1
movsd  -0x50(%rbp),%xmm0
movsd  -0x58(%rbp),%xmm2
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x40(%rbp)
movsd  -0x38(%rbp),%xmm0
addsd  -0x40(%rbp),%xmm0
addsd  -0x48(%rbp),%xmm0
addsd  -0x50(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x28(%rbp),%xmm0
divsd  -0x60(%rbp),%xmm0
call   1030 <floor@plt>
movsd  %xmm0,-0x30(%rbp)
movsd  -0x28(%rbp),%xmm1
movsd  -0x30(%rbp),%xmm0
movsd  -0x60(%rbp),%xmm2
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x28(%rbp),%xmm0
divsd  -0x60(%rbp),%xmm0
mov    -0x18(%rbp),%rax
mov    -0x20(%rbp),%ecx
sub    $0x1,%ecx
movslq %ecx,%rcx
movsd  %xmm0,(%rax,%rcx,8)
movsd  -0x28(%rbp),%xmm0
movsd  %xmm0,-0x10(%rbp)
mov    -0x20(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x20(%rbp)
jmp    117e <lcg_rand+0x6e>
movsd  -0x10(%rbp),%xmm0
add    $0x70,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<lcg_rand>:
push   %r15
push   %r14
push   %rbx
sub    $0x30,%rsp
movapd %xmm0,%xmm1
cmp    %edx,%edi
cmovg  %edx,%edi
test   %edi,%edi
jle    11fb <lcg_rand+0xeb>
mov    %rsi,%r14
mov    %edi,%r15d
xor    %ebx,%ebx
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
movapd %xmm1,%xmm0
call   1030 <floor@plt>
unpcklpd %xmm0,%xmm0
mulpd  0xeab(%rip),%xmm0
movapd %xmm0,(%rsp)
mulpd  0xeae(%rip),%xmm0
movapd %xmm0,0x10(%rsp)
call   1030 <floor@plt>
movapd %xmm0,0x20(%rsp)
movapd 0x10(%rsp),%xmm0
unpckhpd %xmm0,%xmm0
call   1030 <floor@plt>
movapd 0x20(%rsp),%xmm2
unpcklpd %xmm0,%xmm2
movapd %xmm2,%xmm1
mulpd  0xe88(%rip),%xmm1
addpd  (%rsp),%xmm1
movapd %xmm1,%xmm3
unpckhpd %xmm1,%xmm3
addsd  %xmm1,%xmm3
addsd  %xmm2,%xmm3
addsd  %xmm0,%xmm3
movapd %xmm3,(%rsp)
movapd %xmm3,%xmm0
movsd  0xe6e(%rip),%xmm1
divsd  %xmm1,%xmm0
call   1030 <floor@plt>
movapd (%rsp),%xmm1
movsd  0xe58(%rip),%xmm2
mulsd  %xmm2,%xmm0
subsd  %xmm0,%xmm1
movapd %xmm1,%xmm0
divsd  %xmm2,%xmm0
movsd  %xmm0,(%r14,%rbx,8)
add    $0x1,%rbx
cmp    %rbx,%r15
jne    1140 <lcg_rand+0x30>
movapd %xmm1,%xmm0
add    $0x30,%rsp
pop    %rbx
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
define double @lcg_rand(i32 %0, double %1, double* %2, i32 %3) {
%5 = alloca i32
%6 = alloca double
%7 = alloca double*
%8 = alloca i32
%9 = alloca i32
%10 = alloca double
%11 = alloca double
%12 = alloca double
%13 = alloca double
%14 = alloca double
%15 = alloca double
%16 = alloca double
%17 = alloca double
%18 = alloca double
%19 = alloca double
store i32 %0, i32* %5
store double %1, double* %6
store double* %2, double** %7
store i32 %3, i32* %8
store double 0x41E0000000000000, double* %16
store double 0x41DFFFFFFFC00000, double* %17
store double 4.116000e+04, double* %18
store double 0x41CC550000000000, double* %19
%20 = load double, double* %6
store double %20, double* %10
%21 = load i32, i32* %5
%22 = load i32, i32* %8
%23 = icmp sgt i32 %21, %22
br i1 %23, label %24, label %26
24: ; preds = %4
%25 = load i32, i32* %8
store i32 %25, i32* %5
br label %26
26: ; preds = %24, %4
store i32 1, i32* %9
br label %27
27: ; preds = %83, %26
%28 = load i32, i32* %9
%29 = load i32, i32* %5
%30 = icmp sle i32 %28, %29
br i1 %30, label %31, label %86
31: ; preds = %27
%32 = load double, double* %10
%33 = call double @llvm.floor.f64(double %32)
store double %33, double* %10
%34 = load double, double* %10
%35 = load double, double* %18
%36 = fmul double %34, %35
store double %36, double* %12
%37 = load double, double* %10
%38 = load double, double* %19
%39 = fmul double %37, %38
store double %39, double* %13
%40 = load double, double* %12
%41 = load double, double* %16
%42 = fdiv double %40, %41
%43 = call double @llvm.floor.f64(double %42)
store double %43, double* %14
%44 = load double, double* %13
%45 = load double, double* %16
%46 = fdiv double %44, %45
%47 = call double @llvm.floor.f64(double %46)
store double %47, double* %15
%48 = load double, double* %12
%49 = load double, double* %14
%50 = load double, double* %16
%51 = fneg double %49
%52 = call double @llvm.fmuladd.f64(double %51, double %50, double %48)
store double %52, double* %12
%53 = load double, double* %13
%54 = load double, double* %15
%55 = load double, double* %16
%56 = fneg double %54
%57 = call double @llvm.fmuladd.f64(double %56, double %55, double %53)
store double %57, double* %13
%58 = load double, double* %12
%59 = load double, double* %13
%60 = fadd double %58, %59
%61 = load double, double* %14
%62 = fadd double %60, %61
%63 = load double, double* %15
%64 = fadd double %62, %63
store double %64, double* %10
%65 = load double, double* %10
%66 = load double, double* %17
%67 = fdiv double %65, %66
%68 = call double @llvm.floor.f64(double %67)
store double %68, double* %11
%69 = load double, double* %10
%70 = load double, double* %11
%71 = load double, double* %17
%72 = fneg double %70
%73 = call double @llvm.fmuladd.f64(double %72, double %71, double %69)
store double %73, double* %10
%74 = load double, double* %10
%75 = load double, double* %17
%76 = fdiv double %74, %75
%77 = load double*, double** %7
%78 = load i32, i32* %9
%79 = sub nsw i32 %78, 1
%80 = sext i32 %79 to i64
%81 = getelementptr inbounds double, double* %77, i64 %80
store double %76, double* %81
%82 = load double, double* %10
store double %82, double* %6
br label %83
83: ; preds = %31
%84 = load i32, i32* %9
%85 = add nsw i32 %84, 1
store i32 %85, i32* %9
br label %27
86: ; preds = %27
%87 = load double, double* %6
ret double %87
}

LLVM IR (-O2):
define double @lcg_rand(i32 %0, double %1, double* nocapture writeonly %2, i32 %3) {
%5 = icmp sgt i32 %0, %3
%6 = select i1 %5, i32 %3, i32 %0
%7 = icmp slt i32 %6, 1
br i1 %7, label %37, label %8
8: ; preds = %4
%9 = add nuw i32 %6, 1
%10 = zext i32 %9 to i64
br label %11
11: ; preds = %8, %11
%12 = phi i64 [ 1, %8 ], [ %35, %11 ]
%13 = phi double [ %1, %8 ], [ %31, %11 ]
%14 = tail call double @llvm.floor.f64(double %13)
%15 = insertelement <2 x double> poison, double %14, i64 0
%16 = shufflevector <2 x double> %15, <2 x double> poison, <2 x i32> zeroinitializer
%17 = fmul <2 x double> %16, <double 4.116000e+04, double 0x41CC550000000000>
%18 = fmul <2 x double> %17, <double 0x3E00000000000000, double 0x3E00000000000000>
%19 = call <2 x double> @llvm.floor.v2f64(<2 x double> %18)
%20 = fneg <2 x double> %19
%21 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %20, <2 x double> <double 0x41E0000000000000, double 0x41E0000000000000>, <2 x double> %17)
%22 = shufflevector <2 x double> %21, <2 x double> poison, <2 x i32> <i32 1, i32 undef>
%23 = fadd <2 x double> %21, %22
%24 = fadd <2 x double> %19, %23
%25 = shufflevector <2 x double> %19, <2 x double> poison, <2 x i32> <i32 1, i32 undef>
%26 = fadd <2 x double> %25, %24
%27 = extractelement <2 x double> %26, i64 0
%28 = fdiv double %27, 0x41DFFFFFFFC00000
%29 = tail call double @llvm.floor.f64(double %28)
%30 = fneg double %29
%31 = tail call double @llvm.fmuladd.f64(double %30, double 0x41DFFFFFFFC00000, double %27)
%32 = fdiv double %31, 0x41DFFFFFFFC00000
%33 = add nsw i64 %12, -1
%34 = getelementptr inbounds double, double* %2, i64 %33
store double %32, double* %34
%35 = add nuw nsw i64 %12, 1
%36 = icmp eq i64 %35, %10
br i1 %36, label %37, label %11
37: ; preds = %11, %4
%38 = phi double [ %1, %4 ], [ %31, %11 ]
ret double %38
}