#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 /*<<< orphan*/ Copy_Vector(double *, double *, int);
int /*<<< orphan*/ Identity_Matrix_ut(double *, int);
int /*<<< orphan*/ Minimize_Down_the_Line(double (*)(double *), double *,
                                          double, double *, double *, double *,
                                          double, double, double, int);
int /*<<< orphan*/ Multiply_Sym_Matrix_by_Vector_ut(double *, double *,
                                                    double *, int);
int /*<<< orphan*/ Subtract_Vectors(double *, double *, double *, int);
int /*<<< orphan*/ Update_H(double *, double *, double *, double *, int);
int /*<<< orphan*/ free(double *);
scalar_t__ malloc(int);
int Fletcher_Powell_Davidon(double (*f)(double *),
                            void (*df)(double *, double *),
                            int (*Stopping_Rule)(double *, double *, int, int),
                            double *a, double *dfa, double line_search_cutoff,
                            double line_search_cutoff_scale_factor,
                            double line_search_tolerance, int n) {
  double *x;
  double *dx;
  double *dg;
  double *H;
  double *Hg;
  double *v;
  double p;
  int iteration = 0;
  int count_between_resets = n;
  int err = 0;
  x = (double *)malloc(n * sizeof(double));
  v = (double *)malloc(n * sizeof(double));
  dx = (double *)malloc(n * sizeof(double));
  dg = (double *)malloc(n * sizeof(double));
  Hg = (double *)malloc(n * sizeof(double));
  H = (double *)malloc(((n * (n + 1)) >> 1) * sizeof(double));
  if (H == 0)
    err = -1;
  else {
    df(a, dfa);
    do {
      iteration++;
      count_between_resets++;
      if (count_between_resets > n) {
        Identity_Matrix_ut(H, n);
        count_between_resets = 1;
      }
      Multiply_Sym_Matrix_by_Vector_ut(v, H, dfa, n);
      Minimize_Down_the_Line(f, a, f(a), &p, v, x, line_search_cutoff,
                             line_search_cutoff_scale_factor,
                             line_search_tolerance, n);
      Subtract_Vectors(dx, x, a, n);
      Copy_Vector(a, x, n);
      Copy_Vector(x, dfa, n);
      df(a, dfa);
      Subtract_Vectors(dg, dfa, x, n);
      Update_H(H, dx, dg, Hg, n);
      err = Stopping_Rule(dx, dfa, iteration, n);
    } while (!err);
  }
  free(Hg);
  free(H);
  free(dg);
  free(dx);
  free(v);
  free(x);
  return err;
}


x86 assembly (clang, -O0):
<Fletcher_Powell_Davidon>:
push   %rbp
mov    %rsp,%rbp
sub    $0xa0,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    %r8,-0x28(%rbp)
movsd  %xmm0,-0x30(%rbp)
movsd  %xmm1,-0x38(%rbp)
movsd  %xmm2,-0x40(%rbp)
mov    %r9d,-0x44(%rbp)
movl   $0x0,-0x84(%rbp)
mov    -0x44(%rbp),%eax
mov    %eax,-0x88(%rbp)
movl   $0x0,-0x8c(%rbp)
movslq -0x44(%rbp),%rax
shl    $0x3,%rax
mov    %eax,%edi
call   1080 <malloc@plt>
mov    %rax,-0x50(%rbp)
movslq -0x44(%rbp),%rax
shl    $0x3,%rax
mov    %eax,%edi
call   1080 <malloc@plt>
mov    %rax,-0x78(%rbp)
movslq -0x44(%rbp),%rax
shl    $0x3,%rax
mov    %eax,%edi
call   1080 <malloc@plt>
mov    %rax,-0x58(%rbp)
movslq -0x44(%rbp),%rax
shl    $0x3,%rax
mov    %eax,%edi
call   1080 <malloc@plt>
mov    %rax,-0x60(%rbp)
movslq -0x44(%rbp),%rax
shl    $0x3,%rax
mov    %eax,%edi
call   1080 <malloc@plt>
mov    %rax,-0x70(%rbp)
mov    -0x44(%rbp),%eax
mov    -0x44(%rbp),%ecx
add    $0x1,%ecx
imul   %ecx,%eax
sar    $0x1,%eax
cltq
shl    $0x3,%rax
mov    %eax,%edi
call   1080 <malloc@plt>
mov    %rax,-0x68(%rbp)
cmpq   $0x0,-0x68(%rbp)
jne    1268 <Fletcher_Powell_Davidon+0xe8>
movl   $0xffffffff,-0x8c(%rbp)
ff ff ff
jmp    13c4 <Fletcher_Powell_Davidon+0x244>
mov    -0x10(%rbp),%rax
mov    -0x20(%rbp),%rdi
mov    -0x28(%rbp),%rsi
call   *%rax
mov    -0x84(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x84(%rbp)
mov    -0x88(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x88(%rbp)
mov    -0x88(%rbp),%eax
cmp    -0x44(%rbp),%eax
jle    12b9 <Fletcher_Powell_Davidon+0x139>
mov    -0x68(%rbp),%rdi
mov    -0x44(%rbp),%esi
call   1060 <Identity_Matrix_ut@plt>
movl   $0x1,-0x88(%rbp)
mov    -0x78(%rbp),%rdi
mov    -0x68(%rbp),%rsi
mov    -0x28(%rbp),%rdx
mov    -0x44(%rbp),%ecx
call   1090 <Multiply_Sym_Matrix_by_Vector_ut@plt>
mov    -0x8(%rbp),%rax
mov    %rax,-0xa0(%rbp)
mov    -0x20(%rbp),%rax
mov    %rax,-0x98(%rbp)
mov    -0x8(%rbp),%rax
mov    -0x20(%rbp),%rdi
call   *%rax
mov    -0xa0(%rbp),%rdi
mov    -0x98(%rbp),%rsi
mov    -0x78(%rbp),%rcx
mov    -0x50(%rbp),%r8
movsd  -0x30(%rbp),%xmm1
movsd  -0x38(%rbp),%xmm2
movsd  -0x40(%rbp),%xmm3
mov    -0x44(%rbp),%r9d
lea    -0x80(%rbp),%rdx
call   1040 <Minimize_Down_the_Line@plt>
mov    -0x58(%rbp),%rdi
mov    -0x50(%rbp),%rsi
mov    -0x20(%rbp),%rdx
mov    -0x44(%rbp),%ecx
call   1070 <Subtract_Vectors@plt>
mov    -0x20(%rbp),%rdi
mov    -0x50(%rbp),%rsi
mov    -0x44(%rbp),%edx
call   1050 <Copy_Vector@plt>
mov    -0x50(%rbp),%rdi
mov    -0x28(%rbp),%rsi
mov    -0x44(%rbp),%edx
call   1050 <Copy_Vector@plt>
mov    -0x10(%rbp),%rax
mov    -0x20(%rbp),%rdi
mov    -0x28(%rbp),%rsi
call   *%rax
mov    -0x60(%rbp),%rdi
mov    -0x28(%rbp),%rsi
mov    -0x50(%rbp),%rdx
mov    -0x44(%rbp),%ecx
call   1070 <Subtract_Vectors@plt>
mov    -0x68(%rbp),%rdi
mov    -0x58(%rbp),%rsi
mov    -0x60(%rbp),%rdx
mov    -0x70(%rbp),%rcx
mov    -0x44(%rbp),%r8d
call   10a0 <Update_H@plt>
mov    -0x18(%rbp),%rax
mov    -0x58(%rbp),%rdi
mov    -0x28(%rbp),%rsi
mov    -0x84(%rbp),%edx
mov    -0x44(%rbp),%ecx
call   *%rax
mov    %eax,-0x8c(%rbp)
cmpl   $0x0,-0x8c(%rbp)
setne  %al
xor    $0xff,%al
test   $0x1,%al
jne    1276 <Fletcher_Powell_Davidon+0xf6>
jmp    13c4 <Fletcher_Powell_Davidon+0x244>
mov    -0x70(%rbp),%rdi
call   1030 <free@plt>
mov    -0x68(%rbp),%rdi
call   1030 <free@plt>
mov    -0x60(%rbp),%rdi
call   1030 <free@plt>
mov    -0x58(%rbp),%rdi
call   1030 <free@plt>
mov    -0x78(%rbp),%rdi
call   1030 <free@plt>
mov    -0x50(%rbp),%rdi
call   1030 <free@plt>
mov    -0x8c(%rbp),%eax
add    $0xa0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<Fletcher_Powell_Davidon>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x88,%rsp
mov    %r9d,%r12d
movsd  %xmm2,0x78(%rsp)
movsd  %xmm1,0x70(%rsp)
movsd  %xmm0,0x68(%rsp)
mov    %r8,%rbx
mov    %rcx,%r15
mov    %rdx,0x60(%rsp)
mov    %rsi,%rbp
mov    %rdi,0x58(%rsp)
lea    0x0(,%r12,8),%r14d
mov    %r14d,%edi
call   1080 <malloc@plt>
mov    %rax,0x38(%rsp)
mov    %r14d,%edi
call   1080 <malloc@plt>
mov    %rax,0x40(%rsp)
mov    %r14d,%edi
call   1080 <malloc@plt>
mov    %rax,0x30(%rsp)
mov    %r14d,%edi
call   1080 <malloc@plt>
mov    %rax,0x28(%rsp)
mov    %r14d,%edi
call   1080 <malloc@plt>
mov    %rax,0x20(%rsp)
lea    0x1(%r12),%edi
imul   %r12d,%edi
shl    $0x2,%edi
and    $0xfffffff8,%edi
call   1080 <malloc@plt>
mov    %rax,0x10(%rsp)
test   %rax,%rax
je     1368 <Fletcher_Powell_Davidon+0x1e8>
mov    %r15,0x48(%rsp)
mov    %r15,%rdi
mov    %rbx,%rsi
mov    %rbp,0x50(%rsp)
call   *%rbp
mov    $0x1,%ebp
mov    %r12d,%eax
mov    0x10(%rsp),%r15
jmp    134f <Fletcher_Powell_Davidon+0x1cf>
nopl   0x0(%rax,%rax,1)
mov    %r15,%rdi
mov    %r12d,%esi
call   1060 <Identity_Matrix_ut@plt>
movl   $0x1,0xc(%rsp)
mov    0x40(%rsp),%rbp
mov    %rbp,%rdi
mov    %r15,%rsi
mov    %rbx,%r13
mov    %rbx,%rdx
mov    %r12d,%ecx
call   1090 <Multiply_Sym_Matrix_by_Vector_ut@plt>
mov    0x48(%rsp),%r15
mov    %r15,%rdi
mov    0x58(%rsp),%rbx
call   *%rbx
mov    %rbx,%rdi
mov    %r15,%rsi
lea    0x80(%rsp),%rdx
mov    %rbp,%rcx
mov    0x38(%rsp),%rbp
mov    %rbp,%r8
movsd  0x68(%rsp),%xmm1
movsd  0x70(%rsp),%xmm2
movsd  0x78(%rsp),%xmm3
mov    %r12d,%r9d
call   1040 <Minimize_Down_the_Line@plt>
mov    0x30(%rsp),%r14
mov    %r14,%rdi
mov    %rbp,%rsi
mov    %r15,%rdx
mov    %r12d,%ecx
call   1070 <Subtract_Vectors@plt>
mov    %r15,%rdi
mov    %rbp,%rsi
mov    %r12d,%edx
call   1050 <Copy_Vector@plt>
mov    %rbp,%rdi
mov    %r13,%rsi
mov    %r12d,%edx
call   1050 <Copy_Vector@plt>
mov    %r15,%rdi
mov    0x10(%rsp),%r15
mov    %r13,%rsi
call   *0x50(%rsp)
mov    0x28(%rsp),%rbx
mov    %rbx,%rdi
mov    %r13,%rsi
mov    %rbp,%rdx
mov    %r12d,%ecx
call   1070 <Subtract_Vectors@plt>
mov    %r15,%rdi
mov    %r14,%rsi
mov    %rbx,%rdx
mov    0x20(%rsp),%rcx
mov    %r12d,%r8d
call   10a0 <Update_H@plt>
mov    %r14,%rdi
mov    %r13,%rbx
mov    %r13,%rsi
mov    0x1c(%rsp),%ebp
mov    %ebp,%edx
mov    %r12d,%ecx
call   *0x60(%rsp)
mov    %eax,%r14d
add    $0x1,%ebp
test   %eax,%eax
mov    0xc(%rsp),%eax
jne    1373 <Fletcher_Powell_Davidon+0x1f3>
cmp    %r12d,%eax
mov    %ebp,0x1c(%rsp)
jge    1250 <Fletcher_Powell_Davidon+0xd0>
add    $0x1,%eax
mov    %eax,0xc(%rsp)
jmp    1263 <Fletcher_Powell_Davidon+0xe3>
mov    $0xffffffff,%r14d
mov    0x10(%rsp),%r15
mov    0x20(%rsp),%rdi
call   1030 <free@plt>
mov    %r15,%rdi
call   1030 <free@plt>
mov    0x28(%rsp),%rdi
call   1030 <free@plt>
mov    0x30(%rsp),%rdi
call   1030 <free@plt>
mov    0x40(%rsp),%rdi
call   1030 <free@plt>
mov    0x38(%rsp),%rdi
call   1030 <free@plt>
mov    %r14d,%eax
add    $0x88,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define i32 @Fletcher_Powell_Davidon(double (double*)* %0, void (double*, double*)* %1, i32 (double*, double*, i32, i32)* %2, double* %3, double* %4, double %5, double %6, double %7, i32 %8) {
%10 = alloca double (double*)*
%11 = alloca void (double*, double*)*
%12 = alloca i32 (double*, double*, i32, i32)*
%13 = alloca double*
%14 = alloca double*
%15 = alloca double
%16 = alloca double
%17 = alloca double
%18 = alloca i32
%19 = alloca double*
%20 = alloca double*
%21 = alloca double*
%22 = alloca double*
%23 = alloca double*
%24 = alloca double*
%25 = alloca double
%26 = alloca i32
%27 = alloca i32
%28 = alloca i32
store double (double*)* %0, double (double*)** %10
store void (double*, double*)* %1, void (double*, double*)** %11
store i32 (double*, double*, i32, i32)* %2, i32 (double*, double*, i32, i32)** %12
store double* %3, double** %13
store double* %4, double** %14
store double %5, double* %15
store double %6, double* %16
store double %7, double* %17
store i32 %8, i32* %18
store i32 0, i32* %26
%29 = load i32, i32* %18
store i32 %29, i32* %27
store i32 0, i32* %28
%30 = load i32, i32* %18
%31 = sext i32 %30 to i64
%32 = mul i64 %31, 8
%33 = trunc i64 %32 to i32
%34 = call i64 @malloc(i32 %33)
%35 = inttoptr i64 %34 to double*
store double* %35, double** %19
%36 = load i32, i32* %18
%37 = sext i32 %36 to i64
%38 = mul i64 %37, 8
%39 = trunc i64 %38 to i32
%40 = call i64 @malloc(i32 %39)
%41 = inttoptr i64 %40 to double*
store double* %41, double** %24
%42 = load i32, i32* %18
%43 = sext i32 %42 to i64
%44 = mul i64 %43, 8
%45 = trunc i64 %44 to i32
%46 = call i64 @malloc(i32 %45)
%47 = inttoptr i64 %46 to double*
store double* %47, double** %20
%48 = load i32, i32* %18
%49 = sext i32 %48 to i64
%50 = mul i64 %49, 8
%51 = trunc i64 %50 to i32
%52 = call i64 @malloc(i32 %51)
%53 = inttoptr i64 %52 to double*
store double* %53, double** %21
%54 = load i32, i32* %18
%55 = sext i32 %54 to i64
%56 = mul i64 %55, 8
%57 = trunc i64 %56 to i32
%58 = call i64 @malloc(i32 %57)
%59 = inttoptr i64 %58 to double*
store double* %59, double** %23
%60 = load i32, i32* %18
%61 = load i32, i32* %18
%62 = add nsw i32 %61, 1
%63 = mul nsw i32 %60, %62
%64 = ashr i32 %63, 1
%65 = sext i32 %64 to i64
%66 = mul i64 %65, 8
%67 = trunc i64 %66 to i32
%68 = call i64 @malloc(i32 %67)
%69 = inttoptr i64 %68 to double*
store double* %69, double** %22
%70 = load double*, double** %22
%71 = icmp eq double* %70, null
br i1 %71, label %72, label %73
72: ; preds = %9
store i32 -1, i32* %28
br label %145
73: ; preds = %9
%74 = load void (double*, double*)*, void (double*, double*)** %11
%75 = load double*, double** %13
%76 = load double*, double** %14
br label %77
77: ; preds = %140, %73
%78 = load i32, i32* %26
%79 = add nsw i32 %78, 1
store i32 %79, i32* %26
%80 = load i32, i32* %27
%81 = add nsw i32 %80, 1
store i32 %81, i32* %27
%82 = load i32, i32* %27
%83 = load i32, i32* %18
%84 = icmp sgt i32 %82, %83
br i1 %84, label %85, label %89
85: ; preds = %77
%86 = load double*, double** %22
%87 = load i32, i32* %18
%88 = call i32 @Identity_Matrix_ut(double* %86, i32 %87)
store i32 1, i32* %27
br label %89
89: ; preds = %85, %77
%90 = load double*, double** %24
%91 = load double*, double** %22
%92 = load double*, double** %14
%93 = load i32, i32* %18
%94 = call i32 @Multiply_Sym_Matrix_by_Vector_ut(double* %90, double* %91, double* %92, i32 %93)
%95 = load double (double*)*, double (double*)** %10
%96 = load double*, double** %13
%97 = load double (double*)*, double (double*)** %10
%98 = load double*, double** %13
%99 = call double %97(double* %98)
%100 = load double*, double** %24
%101 = load double*, double** %19
%102 = load double, double* %15
%103 = load double, double* %16
%104 = load double, double* %17
%105 = load i32, i32* %18
%106 = call i32 @Minimize_Down_the_Line(double (double*)* %95, double* %96, double %99, double* %25, double* %100, double* %101, double %102, double %103, double %104, i32 %105)
%107 = load double*, double** %20
%108 = load double*, double** %19
%109 = load double*, double** %13
%110 = load i32, i32* %18
%111 = call i32 @Subtract_Vectors(double* %107, double* %108, double* %109, i32 %110)
%112 = load double*, double** %13
%113 = load double*, double** %19
%114 = load i32, i32* %18
%115 = call i32 @Copy_Vector(double* %112, double* %113, i32 %114)
%116 = load double*, double** %19
%117 = load double*, double** %14
%118 = load i32, i32* %18
%119 = call i32 @Copy_Vector(double* %116, double* %117, i32 %118)
%120 = load void (double*, double*)*, void (double*, double*)** %11
%121 = load double*, double** %13
%122 = load double*, double** %14
%123 = load double*, double** %21
%124 = load double*, double** %14
%125 = load double*, double** %19
%126 = load i32, i32* %18
%127 = call i32 @Subtract_Vectors(double* %123, double* %124, double* %125, i32 %126)
%128 = load double*, double** %22
%129 = load double*, double** %20
%130 = load double*, double** %21
%131 = load double*, double** %23
%132 = load i32, i32* %18
%133 = call i32 @Update_H(double* %128, double* %129, double* %130, double* %131, i32 %132)
%134 = load i32 (double*, double*, i32, i32)*, i32 (double*, double*, i32, i32)** %12
%135 = load double*, double** %20
%136 = load double*, double** %14
%137 = load i32, i32* %26
%138 = load i32, i32* %18
%139 = call i32 %134(double* %135, double* %136, i32 %137, i32 %138)
store i32 %139, i32* %28
br label %140
140: ; preds = %89
%141 = load i32, i32* %28
%142 = icmp ne i32 %141, 0
%143 = xor i1 %142, true
br i1 %143, label %77, label %144
144: ; preds = %140
br label %145
145: ; preds = %144, %72
%146 = load double*, double** %23
%147 = call i32 @free(double* %146)
%148 = load double*, double** %22
%149 = call i32 @free(double* %148)
%150 = load double*, double** %21
%151 = call i32 @free(double* %150)
%152 = load double*, double** %20
%153 = call i32 @free(double* %152)
%154 = load double*, double** %24
%155 = call i32 @free(double* %154)
%156 = load double*, double** %19
%157 = call i32 @free(double* %156)
%158 = load i32, i32* %28
ret i32 %158
}

LLVM IR (-O2):
define i32 @Fletcher_Powell_Davidon(double (double*)* %0, void (double*, double*)* nocapture %1, i32 (double*, double*, i32, i32)* nocapture %2, double* %3, double* %4, double %5, double %6, double %7, i32 %8) {
%10 = alloca double
%11 = bitcast double* %10 to i8*
%12 = shl i32 %8, 3
%13 = tail call i64 @malloc(i32 %12)
%14 = inttoptr i64 %13 to double*
%15 = tail call i64 @malloc(i32 %12)
%16 = inttoptr i64 %15 to double*
%17 = tail call i64 @malloc(i32 %12)
%18 = inttoptr i64 %17 to double*
%19 = tail call i64 @malloc(i32 %12)
%20 = inttoptr i64 %19 to double*
%21 = tail call i64 @malloc(i32 %12)
%22 = inttoptr i64 %21 to double*
%23 = add nsw i32 %8, 1
%24 = shl i32 %8, 2
%25 = mul i32 %24, %23
%26 = and i32 %25, -8
%27 = tail call i64 @malloc(i32 %26)
%28 = inttoptr i64 %27 to double*
%29 = icmp eq i64 %27, 0
br i1 %29, label %51, label %30
30: ; preds = %9
tail call void %1(double* %3, double* %4)
br label %31
31: ; preds = %39, %30
%32 = phi i32 [ 0, %30 ], [ %34, %39 ]
%33 = phi i32 [ %8, %30 ], [ %40, %39 ]
%34 = add nuw nsw i32 %32, 1
%35 = add nsw i32 %33, 1
%36 = icmp slt i32 %33, %8
br i1 %36, label %39, label %37
37: ; preds = %31
%38 = call i32 @Identity_Matrix_ut(double* %28, i32 %8)
br label %39
39: ; preds = %37, %31
%40 = phi i32 [ 1, %37 ], [ %35, %31 ]
%41 = call i32 @Multiply_Sym_Matrix_by_Vector_ut(double* %16, double* %28, double* %4, i32 %8)
%42 = call double %0(double* %3)
%43 = call i32 @Minimize_Down_the_Line(double (double*)* %0, double* %3, double %42, double* %10, double* %16, double* %14, double %5, double %6, double %7, i32 %8)
%44 = call i32 @Subtract_Vectors(double* %18, double* %14, double* %3, i32 %8)
%45 = call i32 @Copy_Vector(double* %3, double* %14, i32 %8)
%46 = call i32 @Copy_Vector(double* %14, double* %4, i32 %8)
%47 = call i32 @Subtract_Vectors(double* %20, double* %4, double* %14, i32 %8)
%48 = call i32 @Update_H(double* %28, double* %18, double* %20, double* %22, i32 %8)
%49 = call i32 %2(double* %18, double* %4, i32 %34, i32 %8)
%50 = icmp eq i32 %49, 0
br i1 %50, label %31, label %51
51: ; preds = %39, %9
%52 = phi i32 [ -1, %9 ], [ %49, %39 ]
%53 = call i32 @free(double* %22)
%54 = call i32 @free(double* %28)
%55 = call i32 @free(double* %20)
%56 = call i32 @free(double* %18)
%57 = call i32 @free(double* %16)
%58 = call i32 @free(double* %14)
ret i32 %52
}