int Graggs_Method(int (*f)(double, double *, double *, void *), double y0[],
                  double t0, double t, int number_of_steps, void *params,
                  double yres[]) {
  double y1[1], y05[1], y15[1], y2[1], y25[1], yaux[1];
  double h = (t - t0) / (double)number_of_steps;
  double h2 = h + h;
  yaux[0] = y0[0];
  (*f)(t0, yaux, y05, params);
  y1[0] = yaux[0] + h * y05[0];
  while (--number_of_steps) {
    t0 += h;
    (*f)(t0, y1, y15, params);
    y2[0] = yaux[0] + h2 * y15[0];
    yaux[0] = y1[0];
    y1[0] = y2[0];
  }
  (*f)(t, y1, y25, params);
  yres[0] = 0.5 * (yaux[0] + y1[0] + h * y25[0]);
  return 0;
}


x86 assembly (clang, -O0):
<Graggs_Method>:
push   %rbp
mov    %rsp,%rbp
sub    $0x80,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
movsd  %xmm0,-0x18(%rbp)
movsd  %xmm1,-0x20(%rbp)
mov    %edx,-0x24(%rbp)
mov    %rcx,-0x30(%rbp)
mov    %r8,-0x38(%rbp)
movsd  -0x20(%rbp),%xmm0
subsd  -0x18(%rbp),%xmm0
cvtsi2sdl -0x24(%rbp),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x70(%rbp)
movsd  -0x70(%rbp),%xmm0
addsd  -0x70(%rbp),%xmm0
movsd  %xmm0,-0x78(%rbp)
mov    -0x10(%rbp),%rax
movsd  (%rax),%xmm0
movsd  %xmm0,-0x68(%rbp)
mov    -0x8(%rbp),%rax
movsd  -0x18(%rbp),%xmm0
lea    -0x68(%rbp),%rdi
lea    -0x48(%rbp),%rsi
mov    -0x30(%rbp),%rdx
call   *%rax
movsd  -0x68(%rbp),%xmm1
movsd  -0x70(%rbp),%xmm0
movsd  -0x48(%rbp),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x40(%rbp)
mov    -0x24(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x24(%rbp)
cmp    $0x0,%eax
je     11fc <Graggs_Method+0xfc>
movsd  -0x70(%rbp),%xmm0
addsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
mov    -0x8(%rbp),%rax
movsd  -0x18(%rbp),%xmm0
lea    -0x40(%rbp),%rdi
lea    -0x50(%rbp),%rsi
mov    -0x30(%rbp),%rdx
call   *%rax
movsd  -0x68(%rbp),%xmm1
movsd  -0x78(%rbp),%xmm0
movsd  -0x50(%rbp),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x58(%rbp)
movsd  -0x40(%rbp),%xmm0
movsd  %xmm0,-0x68(%rbp)
movsd  -0x58(%rbp),%xmm0
movsd  %xmm0,-0x40(%rbp)
jmp    118f <Graggs_Method+0x8f>
mov    -0x8(%rbp),%rax
movsd  -0x20(%rbp),%xmm0
lea    -0x40(%rbp),%rdi
lea    -0x60(%rbp),%rsi
mov    -0x30(%rbp),%rdx
call   *%rax
movsd  -0x68(%rbp),%xmm0
addsd  -0x40(%rbp),%xmm0
movsd  -0x70(%rbp),%xmm1
movsd  -0x60(%rbp),%xmm2
mulsd  %xmm2,%xmm1
addsd  %xmm0,%xmm1
movsd  0xdc9(%rip),%xmm0
mulsd  %xmm1,%xmm0
mov    -0x38(%rbp),%rax
movsd  %xmm0,(%rax)
xor    %eax,%eax
add    $0x80,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<Graggs_Method>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x48,%rsp
mov    %r8,%r14
mov    %rcx,%r15
mov    %edx,%ebp
mov    %rdi,%rbx
movsd  %xmm1,0x20(%rsp)
movapd %xmm1,%xmm2
xorps  %xmm1,%xmm1
cvtsi2sd %edx,%xmm1
subsd  %xmm0,%xmm2
divsd  %xmm1,%xmm2
movsd  %xmm2,0x10(%rsp)
movsd  (%rsi),%xmm1
movsd  %xmm1,(%rsp)
mov    %rsp,%rdi
lea    0x40(%rsp),%rsi
movsd  %xmm0,0x18(%rsp)
mov    %rcx,%rdx
call   *%rbx
movsd  0x40(%rsp),%xmm0
mulsd  0x10(%rsp),%xmm0
addsd  (%rsp),%xmm0
movsd  %xmm0,0x8(%rsp)
add    $0xffffffff,%ebp
je     11d4 <Graggs_Method+0xd4>
movsd  0x10(%rsp),%xmm0
addsd  %xmm0,%xmm0
movsd  %xmm0,0x28(%rsp)
lea    0x8(%rsp),%r12
lea    0x38(%rsp),%r13
nopw   0x0(%rax,%rax,1)
movsd  0x18(%rsp),%xmm0
addsd  0x10(%rsp),%xmm0
movsd  %xmm0,0x18(%rsp)
mov    %r12,%rdi
mov    %r13,%rsi
mov    %r15,%rdx
call   *%rbx
movsd  0x38(%rsp),%xmm0
mulsd  0x28(%rsp),%xmm0
addsd  (%rsp),%xmm0
movsd  0x8(%rsp),%xmm1
movsd  %xmm1,(%rsp)
movsd  %xmm0,0x8(%rsp)
add    $0xffffffff,%ebp
jne    1190 <Graggs_Method+0x90>
lea    0x8(%rsp),%rdi
lea    0x30(%rsp),%rsi
movsd  0x20(%rsp),%xmm0
mov    %r15,%rdx
call   *%rbx
movsd  (%rsp),%xmm0
addsd  0x8(%rsp),%xmm0
movsd  0x10(%rsp),%xmm1
mulsd  0x30(%rsp),%xmm1
addsd  %xmm0,%xmm1
mulsd  0xdf4(%rip),%xmm1
movsd  %xmm1,(%r14)
xor    %eax,%eax
add    $0x48,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

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

LLVM IR (-O2):
define i32 @Graggs_Method(i32 (double, double*, double*, i8*)* nocapture %0, double* nocapture %1, double %2, double %3, i32 %4, i8* %5, double* nocapture writeonly %6) {
%8 = alloca [1 x double]
%9 = alloca [1 x double]
%10 = alloca [1 x double]
%11 = alloca [1 x double]
%12 = alloca [1 x double]
%13 = bitcast [1 x double]* %8 to i8*
%14 = bitcast [1 x double]* %9 to i8*
%15 = bitcast [1 x double]* %10 to i8*
%16 = bitcast [1 x double]* %11 to i8*
%17 = bitcast [1 x double]* %12 to i8*
%18 = fsub double %3, %2
%19 = sitofp i32 %4 to double
%20 = fdiv double %18, %19
%21 = fadd double %20, %20
%22 = load double, double* %1
%23 = getelementptr inbounds [1 x double], [1 x double]* %12, i64 0, i64 0
store double %22, double* %23
%24 = getelementptr inbounds [1 x double], [1 x double]* %9, i64 0, i64 0
%25 = call i32 %0(double %2, double* %23, double* %24, i8* %5)
%26 = load double, double* %23
%27 = load double, double* %24
%28 = call double @llvm.fmuladd.f64(double %20, double %27, double %26)
%29 = getelementptr inbounds [1 x double], [1 x double]* %8, i64 0, i64 0
store double %28, double* %29
%30 = add nsw i32 %4, -1
%31 = icmp eq i32 %30, 0
br i1 %31, label %45, label %32
32: ; preds = %7
%33 = getelementptr inbounds [1 x double], [1 x double]* %10, i64 0, i64 0
br label %34
34: ; preds = %32, %34
%35 = phi i32 [ %30, %32 ], [ %43, %34 ]
%36 = phi double [ %2, %32 ], [ %37, %34 ]
%37 = fadd double %20, %36
%38 = call i32 %0(double %37, double* %29, double* %33, i8* %5)
%39 = load double, double* %23
%40 = load double, double* %33
%41 = call double @llvm.fmuladd.f64(double %21, double %40, double %39)
%42 = load double, double* %29
store double %42, double* %23
store double %41, double* %29
%43 = add nsw i32 %35, -1
%44 = icmp eq i32 %43, 0
br i1 %44, label %45, label %34
45: ; preds = %34, %7
%46 = getelementptr inbounds [1 x double], [1 x double]* %11, i64 0, i64 0
%47 = call i32 %0(double %3, double* %29, double* %46, i8* %5)
%48 = load double, double* %23
%49 = load double, double* %29
%50 = fadd double %48, %49
%51 = load double, double* %46
%52 = call double @llvm.fmuladd.f64(double %20, double %51, double %50)
%53 = fmul double %52, 5.000000e-01
store double %53, double* %6
ret i32 0
}