#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 frexp(int /*<<< orphan*/, int *);
double ldexp(double, int);
double sqrt(double);
int /*<<< orphan*/ vinfnorm(double const *, int);
double v2norm(const double *v, int n) {
  double s;
  int sb;
  s = frexp(vinfnorm(v, n), &sb);
  if (s > 0 && s <= 1) {
    double vis;
    double d2;
    int i;
    d2 = 0;
    s = ldexp(1.0, -sb);
    for (i = 0; i < n; i++) {
      vis = v[i] * s;
      d2 += vis * vis;
    }
    return ldexp(sqrt(d2), sb);
  } else
    return s;
}


x86 assembly (clang, -O0):
<v2norm>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
mov    -0x10(%rbp),%rdi
mov    -0x14(%rbp),%esi
call   1050 <vinfnorm@plt>
mov    %eax,%edi
lea    -0x24(%rbp),%rsi
call   1040 <frexp@plt>
movsd  %xmm0,-0x20(%rbp)
movsd  -0x20(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jbe    121f <v2norm+0xdf>
movsd  0xe7b(%rip),%xmm0
ucomisd -0x20(%rbp),%xmm0
jb     121f <v2norm+0xdf>
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x38(%rbp)
xor    %edi,%edi
sub    -0x24(%rbp),%edi
movsd  0xe5b(%rip),%xmm0
call   1030 <ldexp@plt>
movsd  %xmm0,-0x20(%rbp)
movl   $0x0,-0x3c(%rbp)
mov    -0x3c(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    1203 <v2norm+0xc3>
mov    -0x10(%rbp),%rax
movslq -0x3c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
mulsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x30(%rbp),%xmm0
movsd  -0x30(%rbp),%xmm2
movsd  -0x38(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x38(%rbp)
mov    -0x3c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x3c(%rbp)
jmp    11b6 <v2norm+0x76>
movsd  -0x38(%rbp),%xmm0
call   1060 <sqrt@plt>
mov    -0x24(%rbp),%edi
call   1030 <ldexp@plt>
movsd  %xmm0,-0x8(%rbp)
jmp    1229 <v2norm+0xe9>
movsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<v2norm>:
push   %rbp
push   %r14
push   %rbx
sub    $0x10,%rsp
mov    %esi,%ebp
mov    %rdi,%rbx
call   1050 <vinfnorm@plt>
lea    0xc(%rsp),%rsi
mov    %eax,%edi
call   1040 <frexp@plt>
xorpd  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jbe    11b6 <v2norm+0x76>
movsd  0xe90(%rip),%xmm1
ucomisd %xmm0,%xmm1
jb     11b6 <v2norm+0x76>
mov    0xc(%rsp),%r14d
mov    %r14d,%edi
neg    %edi
movsd  0xe78(%rip),%xmm0
call   1030 <ldexp@plt>
xorpd  %xmm2,%xmm2
xorpd  %xmm1,%xmm1
test   %ebp,%ebp
jle    124a <v2norm+0x10a>
mov    %ebp,%ecx
lea    -0x1(%rcx),%rdx
mov    %ecx,%eax
and    $0x3,%eax
cmp    $0x3,%rdx
jae    11bf <v2norm+0x7f>
xorpd  %xmm1,%xmm1
xor    %edx,%edx
jmp    1220 <v2norm+0xe0>
add    $0x10,%rsp
pop    %rbx
pop    %r14
pop    %rbp
ret
and    $0xfffffffc,%ecx
xorpd  %xmm1,%xmm1
xor    %edx,%edx
nopl   0x0(%rax,%rax,1)
movsd  (%rbx,%rdx,8),%xmm3
mulsd  %xmm0,%xmm3
mulsd  %xmm3,%xmm3
addsd  %xmm1,%xmm3
movsd  0x8(%rbx,%rdx,8),%xmm1
mulsd  %xmm0,%xmm1
mulsd  %xmm1,%xmm1
addsd  %xmm3,%xmm1
movsd  0x10(%rbx,%rdx,8),%xmm3
mulsd  %xmm0,%xmm3
mulsd  %xmm3,%xmm3
addsd  %xmm1,%xmm3
movsd  0x18(%rbx,%rdx,8),%xmm1
mulsd  %xmm0,%xmm1
mulsd  %xmm1,%xmm1
addsd  %xmm3,%xmm1
add    $0x4,%rdx
cmp    %rdx,%rcx
jne    11d0 <v2norm+0x90>
test   %rax,%rax
je     124a <v2norm+0x10a>
lea    (%rbx,%rdx,8),%rcx
xor    %edx,%edx
nopl   0x0(%rax,%rax,1)
movsd  (%rcx,%rdx,8),%xmm3
mulsd  %xmm0,%xmm3
mulsd  %xmm3,%xmm3
addsd  %xmm3,%xmm1
add    $0x1,%rdx
cmp    %rdx,%rax
jne    1230 <v2norm+0xf0>
ucomisd %xmm2,%xmm1
jb     1259 <v2norm+0x119>
xorps  %xmm0,%xmm0
sqrtsd %xmm1,%xmm0
jmp    1262 <v2norm+0x122>
movapd %xmm1,%xmm0
call   1060 <sqrt@plt>
mov    %r14d,%edi
add    $0x10,%rsp
pop    %rbx
pop    %r14
pop    %rbp
jmp    1030 <ldexp@plt>

LLVM IR (-O0):
define double @v2norm(double* %0, i32 %1) {
%3 = alloca double
%4 = alloca double*
%5 = alloca i32
%6 = alloca double
%7 = alloca i32
%8 = alloca double
%9 = alloca double
%10 = alloca i32
store double* %0, double** %4
store i32 %1, i32* %5
%11 = load double*, double** %4
%12 = load i32, i32* %5
%13 = call i32 @vinfnorm(double* %11, i32 %12)
%14 = call double @frexp(i32 %13, i32* %7)
store double %14, double* %6
%15 = load double, double* %6
%16 = fcmp ogt double %15, 0.000000e+00
br i1 %16, label %17, label %48
17: ; preds = %2
%18 = load double, double* %6
%19 = fcmp ole double %18, 1.000000e+00
br i1 %19, label %20, label %48
20: ; preds = %17
store double 0.000000e+00, double* %9
%21 = load i32, i32* %7
%22 = sub nsw i32 0, %21
%23 = call double @ldexp(double 1.000000e+00, i32 %22)
store double %23, double* %6
store i32 0, i32* %10
br label %24
24: ; preds = %40, %20
%25 = load i32, i32* %10
%26 = load i32, i32* %5
%27 = icmp slt i32 %25, %26
br i1 %27, label %28, label %43
28: ; preds = %24
%29 = load double*, double** %4
%30 = load i32, i32* %10
%31 = sext i32 %30 to i64
%32 = getelementptr inbounds double, double* %29, i64 %31
%33 = load double, double* %32
%34 = load double, double* %6
%35 = fmul double %33, %34
store double %35, double* %8
%36 = load double, double* %8
%37 = load double, double* %8
%38 = load double, double* %9
%39 = call double @llvm.fmuladd.f64(double %36, double %37, double %38)
store double %39, double* %9
br label %40
40: ; preds = %28
%41 = load i32, i32* %10
%42 = add nsw i32 %41, 1
store i32 %42, i32* %10
br label %24
43: ; preds = %24
%44 = load double, double* %9
%45 = call double @sqrt(double %44)
%46 = load i32, i32* %7
%47 = call double @ldexp(double %45, i32 %46)
store double %47, double* %3
br label %50
48: ; preds = %17, %2
%49 = load double, double* %6
store double %49, double* %3
br label %50
50: ; preds = %48, %43
%51 = load double, double* %3
ret double %51
}

LLVM IR (-O2):
define double @v2norm(double* %0, i32 %1) {
%3 = alloca i32
%4 = bitcast i32* %3 to i8*
%5 = tail call i32 @vinfnorm(double* %0, i32 %1)
%6 = call double @frexp(i32 %5, i32* %3)
%7 = fcmp ogt double %6, 0.000000e+00
%8 = fcmp ole double %6, 1.000000e+00
%9 = and i1 %7, %8
br i1 %9, label %10, label %68
10: ; preds = %2
%11 = load i32, i32* %3
%12 = sub nsw i32 0, %11
%13 = tail call double @ldexp(double 1.000000e+00, i32 %12)
%14 = icmp sgt i32 %1, 0
br i1 %14, label %15, label %64
15: ; preds = %10
%16 = zext i32 %1 to i64
%17 = add nsw i64 %16, -1
%18 = and i64 %16, 3
%19 = icmp ult i64 %17, 3
br i1 %19, label %48, label %20
20: ; preds = %15
%21 = and i64 %16, 4294967292
br label %22
22: ; preds = %22, %20
%23 = phi i64 [ 0, %20 ], [ %45, %22 ]
%24 = phi double [ 0.000000e+00, %20 ], [ %44, %22 ]
%25 = phi i64 [ 0, %20 ], [ %46, %22 ]
%26 = getelementptr inbounds double, double* %0, i64 %23
%27 = load double, double* %26
%28 = fmul double %13, %27
%29 = tail call double @llvm.fmuladd.f64(double %28, double %28, double %24)
%30 = or i64 %23, 1
%31 = getelementptr inbounds double, double* %0, i64 %30
%32 = load double, double* %31
%33 = fmul double %13, %32
%34 = tail call double @llvm.fmuladd.f64(double %33, double %33, double %29)
%35 = or i64 %23, 2
%36 = getelementptr inbounds double, double* %0, i64 %35
%37 = load double, double* %36
%38 = fmul double %13, %37
%39 = tail call double @llvm.fmuladd.f64(double %38, double %38, double %34)
%40 = or i64 %23, 3
%41 = getelementptr inbounds double, double* %0, i64 %40
%42 = load double, double* %41
%43 = fmul double %13, %42
%44 = tail call double @llvm.fmuladd.f64(double %43, double %43, double %39)
%45 = add nuw nsw i64 %23, 4
%46 = add i64 %25, 4
%47 = icmp eq i64 %46, %21
br i1 %47, label %48, label %22
48: ; preds = %22, %15
%49 = phi double [ undef, %15 ], [ %44, %22 ]
%50 = phi i64 [ 0, %15 ], [ %45, %22 ]
%51 = phi double [ 0.000000e+00, %15 ], [ %44, %22 ]
%52 = icmp eq i64 %18, 0
br i1 %52, label %64, label %53
53: ; preds = %48, %53
%54 = phi i64 [ %61, %53 ], [ %50, %48 ]
%55 = phi double [ %60, %53 ], [ %51, %48 ]
%56 = phi i64 [ %62, %53 ], [ 0, %48 ]
%57 = getelementptr inbounds double, double* %0, i64 %54
%58 = load double, double* %57
%59 = fmul double %13, %58
%60 = tail call double @llvm.fmuladd.f64(double %59, double %59, double %55)
%61 = add nuw nsw i64 %54, 1
%62 = add i64 %56, 1
%63 = icmp eq i64 %62, %18
br i1 %63, label %64, label %53
64: ; preds = %48, %53, %10
%65 = phi double [ 0.000000e+00, %10 ], [ %49, %48 ], [ %60, %53 ]
%66 = tail call double @sqrt(double %65)
%67 = tail call double @ldexp(double %66, i32 %11)
br label %68
68: ; preds = %2, %64
%69 = phi double [ %67, %64 ], [ %6, %2 ]
ret double %69
}