void decompose(value, uncer, nbasis, basis, count) double value;
double uncer;
int nbasis;
double *basis;
double *count;
{
  int i;
  for (i = 0; i < nbasis; i++) {
    double r = fmod(value, basis[i]);
    if (((2 * r) < 0 ? -(2 * r) : (2 * r)) > basis[i])
      r += r > 0 ? -basis[i] : basis[i];
    if (((r) < 0 ? -(r) : (r)) <= uncer) {
      double half = value < 0 ? -basis[i] / 2 : basis[i] / 2;
      modf((value + half) / basis[i], count + i);
      break;
    }
    value = basis[i] * modf(value / basis[i], count + i);
  }
  if (i >= nbasis) {
    count[--i] += value;
  } else {
    for (i++; i < nbasis; i++)
      count[i] = 0;
  }
}


x86 assembly (clang, -O0):
<decompose>:
push   %rbp
mov    %rsp,%rbp
sub    $0x70,%rsp
movsd  %xmm0,-0x8(%rbp)
movsd  %xmm1,-0x10(%rbp)
mov    %edi,-0x14(%rbp)
mov    %rsi,-0x20(%rbp)
mov    %rdx,-0x28(%rbp)
movl   $0x0,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    1388 <decompose+0x268>
movsd  -0x8(%rbp),%xmm0
mov    -0x20(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm1
call   1030 <fmod@plt>
movsd  %xmm0,-0x38(%rbp)
movsd  0xe8c(%rip),%xmm1
mulsd  -0x38(%rbp),%xmm1
xorps  %xmm0,%xmm0
ucomisd %xmm1,%xmm0
jbe    11b4 <decompose+0x94>
movsd  0xe72(%rip),%xmm0
mulsd  -0x38(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x48(%rbp)
jmp    11c6 <decompose+0xa6>
movsd  0xe44(%rip),%xmm0
mulsd  -0x38(%rbp),%xmm0
movsd  %xmm0,-0x48(%rbp)
movsd  -0x48(%rbp),%xmm0
mov    -0x20(%rbp),%rax
movslq -0x2c(%rbp),%rcx
ucomisd (%rax,%rcx,8),%xmm0
jbe    123f <decompose+0x11f>
movsd  -0x38(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jbe    121e <decompose+0xfe>
mov    -0x20(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x50(%rbp)
jmp    1230 <decompose+0x110>
mov    -0x20(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,-0x50(%rbp)
movsd  -0x50(%rbp),%xmm0
addsd  -0x38(%rbp),%xmm0
movsd  %xmm0,-0x38(%rbp)
xorps  %xmm0,%xmm0
ucomisd -0x38(%rbp),%xmm0
jbe    1273 <decompose+0x153>
movsd  -0x38(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x58(%rbp)
jmp    127d <decompose+0x15d>
movsd  -0x38(%rbp),%xmm0
movsd  %xmm0,-0x58(%rbp)
movsd  -0x58(%rbp),%xmm1
movsd  -0x10(%rbp),%xmm0
ucomisd %xmm1,%xmm0
jb     1331 <decompose+0x211>
xorps  %xmm0,%xmm0
ucomisd -0x8(%rbp),%xmm0
jbe    12d9 <decompose+0x1b9>
mov    -0x20(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  0xd35(%rip),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x60(%rbp)
jmp    12f7 <decompose+0x1d7>
mov    -0x20(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
movsd  0xd12(%rip),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x60(%rbp)
movsd  -0x60(%rbp),%xmm0
movsd  %xmm0,-0x40(%rbp)
movsd  -0x8(%rbp),%xmm0
addsd  -0x40(%rbp),%xmm0
mov    -0x20(%rbp),%rax
movslq -0x2c(%rbp),%rcx
divsd  (%rax,%rcx,8),%xmm0
mov    -0x28(%rbp),%rdi
movslq -0x2c(%rbp),%rax
shl    $0x3,%rax
add    %rax,%rdi
call   1040 <modf@plt>
jmp    1388 <decompose+0x268>
mov    -0x20(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,-0x68(%rbp)
movsd  -0x8(%rbp),%xmm0
mov    -0x20(%rbp),%rax
movslq -0x2c(%rbp),%rcx
divsd  (%rax,%rcx,8),%xmm0
mov    -0x28(%rbp),%rdi
movslq -0x2c(%rbp),%rax
shl    $0x3,%rax
add    %rax,%rdi
call   1040 <modf@plt>
movaps %xmm0,%xmm1
movsd  -0x68(%rbp),%xmm0
mulsd  %xmm1,%xmm0
movsd  %xmm0,-0x8(%rbp)
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    1144 <decompose+0x24>
mov    -0x2c(%rbp),%eax
cmp    -0x14(%rbp),%eax
jl     13b8 <decompose+0x298>
movsd  -0x8(%rbp),%xmm0
mov    -0x28(%rbp),%rax
mov    -0x2c(%rbp),%ecx
add    $0xffffffff,%ecx
mov    %ecx,-0x2c(%rbp)
movslq %ecx,%rcx
addsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,(%rax,%rcx,8)
jmp    13f0 <decompose+0x2d0>
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    13eb <decompose+0x2cb>
mov    -0x28(%rbp),%rax
movslq -0x2c(%rbp),%rcx
xorps  %xmm0,%xmm0
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    13c1 <decompose+0x2a1>
jmp    13f0 <decompose+0x2d0>
add    $0x70,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<decompose>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x18,%rsp
mov    %rdx,%r14
movsd  %xmm1,0x10(%rsp)
test   %edi,%edi
jle    123f <decompose+0x10f>
mov    %rsi,%r12
mov    %edi,%r15d
mov    %edi,%ebp
xor    %ebx,%ebx
mov    %r14,%r13
nopl   0x0(%rax)
movsd  (%r12,%rbx,8),%xmm1
movsd  %xmm0,(%rsp)
call   1030 <fmod@plt>
movapd %xmm0,%xmm1
addsd  %xmm0,%xmm1
movapd %xmm1,%xmm2
movsd  0xe7c(%rip),%xmm5
xorpd  %xmm5,%xmm2
movapd %xmm1,%xmm3
xorpd  %xmm6,%xmm6
cmpltsd %xmm6,%xmm3
andpd  %xmm3,%xmm2
andnpd %xmm1,%xmm3
orpd   %xmm2,%xmm3
movsd  (%r12,%rbx,8),%xmm7
movapd %xmm7,%xmm1
xorpd  %xmm5,%xmm1
xorpd  %xmm2,%xmm2
cmpltsd %xmm0,%xmm2
movapd %xmm2,%xmm4
andnpd %xmm7,%xmm4
andpd  %xmm1,%xmm2
orpd   %xmm4,%xmm2
movapd %xmm7,%xmm1
cmpltsd %xmm3,%xmm1
andpd  %xmm1,%xmm2
andnpd %xmm5,%xmm1
orpd   %xmm2,%xmm1
addsd  %xmm0,%xmm1
movapd %xmm1,%xmm0
xorpd  %xmm5,%xmm0
movapd %xmm1,%xmm2
cmpltsd %xmm6,%xmm2
andpd  %xmm2,%xmm0
andnpd %xmm1,%xmm2
orpd   %xmm0,%xmm2
movsd  0x10(%rsp),%xmm0
ucomisd %xmm2,%xmm0
jae    1254 <decompose+0x124>
movsd  (%rsp),%xmm0
divsd  %xmm7,%xmm0
mov    %r13,%rdi
movapd %xmm7,(%rsp)
call   1040 <modf@plt>
mulsd  (%rsp),%xmm0
add    $0x1,%rbx
add    $0x8,%r13
cmp    %rbx,%rbp
jne    1160 <decompose+0x30>
add    $0xffffffff,%r15d
movslq %r15d,%rax
jmp    1246 <decompose+0x116>
mov    $0xffffffffffffffff,%rax
addsd  (%r14,%rax,8),%xmm0
movsd  %xmm0,(%r14,%rax,8)
jmp    12ac <decompose+0x17c>
xorpd  %xmm0,%xmm0
xor    %eax,%eax
movsd  (%rsp),%xmm1
ucomisd %xmm1,%xmm0
seta   %al
lea    0xd9b(%rip),%rcx
movsd  (%rcx,%rax,8),%xmm0
mulsd  %xmm7,%xmm0
addsd  %xmm1,%xmm0
divsd  %xmm7,%xmm0
mov    %r13,%rdi
call   1040 <modf@plt>
lea    0x1(%rbx),%eax
cmp    %r15d,%eax
jge    12ac <decompose+0x17c>
lea    (%r14,%rbx,8),%rdi
add    $0x8,%rdi
sub    %ebx,%r15d
add    $0xfffffffe,%r15d
lea    0x8(,%r15,8),%rdx
xor    %esi,%esi
call   1050 <memset@plt>
add    $0x18,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

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

LLVM IR (-O2):
define void @decompose(double %0, double %1, i32 %2, double* nocapture %3, double* nocapture %4) {
%6 = icmp sgt i32 %2, 0
br i1 %6, label %7, label %61
7: ; preds = %5
%8 = zext i32 %2 to i64
br label %9
9: ; preds = %7, %51
%10 = phi i64 [ 0, %7 ], [ %56, %51 ]
%11 = phi double [ %0, %7 ], [ %55, %51 ]
%12 = getelementptr inbounds double, double* %3, i64 %10
%13 = load double, double* %12
%14 = tail call double @fmod(double %11, double %13)
%15 = fmul double %14, 2.000000e+00
%16 = fcmp olt double %15, 0.000000e+00
%17 = fneg double %15
%18 = select i1 %16, double %17, double %15
%19 = load double, double* %12
%20 = fcmp ogt double %18, %19
%21 = fcmp ogt double %14, 0.000000e+00
%22 = fneg double %19
%23 = select i1 %21, double %22, double %19
%24 = select i1 %20, double %23, double -0.000000e+00
%25 = fadd double %14, %24
%26 = fcmp olt double %25, 0.000000e+00
%27 = fneg double %25
%28 = select i1 %26, double %27, double %25
%29 = fcmp ugt double %28, %1
br i1 %29, label %51, label %30
30: ; preds = %9
%31 = trunc i64 %10 to i32
%32 = and i64 %10, 4294967295
%33 = fcmp olt double %11, 0.000000e+00
%34 = select i1 %33, double -5.000000e-01, double 5.000000e-01
%35 = fmul double %34, %19
%36 = fadd double %11, %35
%37 = fdiv double %36, %19
%38 = getelementptr inbounds double, double* %4, i64 %32
%39 = tail call double @modf(double %37, double* %38)
%40 = add nuw nsw i32 %31, 1
%41 = icmp slt i32 %40, %2
br i1 %41, label %42, label %67
42: ; preds = %30
%43 = add nuw nsw i64 %10, 1
%44 = getelementptr double, double* %4, i64 %43
%45 = bitcast double* %44 to i8*
%46 = add i32 %2, -2
%47 = sub i32 %46, %31
%48 = zext i32 %47 to i64
%49 = shl nuw nsw i64 %48, 3
%50 = add nuw nsw i64 %49, 8
br label %67
51: ; preds = %9
%52 = fdiv double %11, %19
%53 = getelementptr inbounds double, double* %4, i64 %10
%54 = tail call double @modf(double %52, double* %53)
%55 = fmul double %19, %54
%56 = add nuw nsw i64 %10, 1
%57 = icmp eq i64 %56, %8
br i1 %57, label %58, label %9
58: ; preds = %51
%59 = add i32 %2, -1
%60 = sext i32 %59 to i64
br label %61
61: ; preds = %58, %5
%62 = phi i64 [ -1, %5 ], [ %60, %58 ]
%63 = phi double [ %0, %5 ], [ %55, %58 ]
%64 = getelementptr inbounds double, double* %4, i64 %62
%65 = load double, double* %64
%66 = fadd double %63, %65
store double %66, double* %64
br label %67
67: ; preds = %42, %30, %61
ret void
}