double RoundUp(val)
double val;
{
  int exponent, idx;
  exponent = (int)floor((val == 0.0 ? 0.0 : log10(val) + 1e-15));
  if (exponent < 0) {
    for (idx = exponent; idx < 0; idx++) {
      val *= 10.0;
    }
  } else {
    for (idx = 0; idx < exponent; idx++) {
      val /= 10.0;
    }
  }
  if (val > 5.0)
    val = 10.0;
  else if (val > 2.0)
    val = 5.0;
  else if (val > 1.0)
    val = 2.0;
  else
    val = 1.0;
  if (exponent < 0) {
    for (idx = exponent; idx < 0; idx++) {
      val /= 10.0;
    }
  } else {
    for (idx = 0; idx < exponent; idx++) {
      val *= 10.0;
    }
  }
  return val;
}


x86 assembly (clang, -O0):
<RoundUp>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jne    1152 <RoundUp+0x32>
jp     1152 <RoundUp+0x32>
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x18(%rbp)
jmp    116d <RoundUp+0x4d>
movsd  -0x8(%rbp),%xmm0
call   1030 <log10@plt>
movsd  0xe9c(%rip),%xmm1
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  -0x18(%rbp),%xmm0
call   1040 <floor@plt>
cvttsd2si %xmm0,%eax
mov    %eax,-0xc(%rbp)
cmpl   $0x0,-0xc(%rbp)
jge    11bd <RoundUp+0x9d>
mov    -0xc(%rbp),%eax
mov    %eax,-0x10(%rbp)
cmpl   $0x0,-0x10(%rbp)
jge    11b8 <RoundUp+0x98>
movsd  0xe68(%rip),%xmm0
mulsd  -0x8(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
mov    -0x10(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x10(%rbp)
jmp    118e <RoundUp+0x6e>
jmp    11f9 <RoundUp+0xd9>
movl   $0x0,-0x10(%rbp)
mov    -0x10(%rbp),%eax
cmp    -0xc(%rbp),%eax
jge    11f4 <RoundUp+0xd4>
movsd  -0x8(%rbp),%xmm0
movsd  0xe2b(%rip),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x8(%rbp)
mov    -0x10(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x10(%rbp)
jmp    11c4 <RoundUp+0xa4>
jmp    11f9 <RoundUp+0xd9>
movsd  -0x8(%rbp),%xmm0
movsd  0xe0a(%rip),%xmm1
ucomisd %xmm1,%xmm0
jbe    1222 <RoundUp+0x102>
movsd  0xdf0(%rip),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    128b <RoundUp+0x16b>
movsd  -0x8(%rbp),%xmm0
movsd  0xde9(%rip),%xmm1
ucomisd %xmm1,%xmm0
jbe    124b <RoundUp+0x12b>
movsd  0xdcf(%rip),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1286 <RoundUp+0x166>
movsd  -0x8(%rbp),%xmm0
movsd  0xdc8(%rip),%xmm1
ucomisd %xmm1,%xmm0
jbe    1274 <RoundUp+0x154>
movsd  0xdae(%rip),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1281 <RoundUp+0x161>
movsd  0xda4(%rip),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1286 <RoundUp+0x166>
jmp    128b <RoundUp+0x16b>
cmpl   $0x0,-0xc(%rbp)
jge    12ce <RoundUp+0x1ae>
mov    -0xc(%rbp),%eax
mov    %eax,-0x10(%rbp)
cmpl   $0x0,-0x10(%rbp)
jge    12c9 <RoundUp+0x1a9>
movsd  -0x8(%rbp),%xmm0
movsd  0xd56(%rip),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x8(%rbp)
mov    -0x10(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x10(%rbp)
jmp    129b <RoundUp+0x17b>
jmp    1306 <RoundUp+0x1e6>
movl   $0x0,-0x10(%rbp)
mov    -0x10(%rbp),%eax
cmp    -0xc(%rbp),%eax
jge    1301 <RoundUp+0x1e1>
movsd  0xd1f(%rip),%xmm0
mulsd  -0x8(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
mov    -0x10(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x10(%rbp)
jmp    12d5 <RoundUp+0x1b5>
jmp    1306 <RoundUp+0x1e6>
movsd  -0x8(%rbp),%xmm0
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<RoundUp>:
push   %rax
movapd %xmm0,%xmm1
xorpd  %xmm0,%xmm0
movsd  %xmm1,(%rsp)
ucomisd %xmm0,%xmm1
jne    1136 <RoundUp+0x16>
jnp    1148 <RoundUp+0x28>
movsd  (%rsp),%xmm0
call   1030 <log10@plt>
addsd  0xeb8(%rip),%xmm0
call   1040 <floor@plt>
cvttsd2si %xmm0,%eax
test   %eax,%eax
js     11be <RoundUp+0x9e>
je     11f6 <RoundUp+0xd6>
lea    -0x1(%rax),%edx
mov    %eax,%ecx
and    $0x3,%ecx
cmp    $0x3,%edx
movsd  (%rsp),%xmm1
jb     1195 <RoundUp+0x75>
mov    %eax,%edx
and    $0xfffffffc,%edx
movsd  0xe8e(%rip),%xmm0
nopw   0x0(%rax,%rax,1)
divsd  %xmm0,%xmm1
divsd  %xmm0,%xmm1
divsd  %xmm0,%xmm1
divsd  %xmm0,%xmm1
add    $0xfffffffc,%edx
jne    1180 <RoundUp+0x60>
test   %ecx,%ecx
je     1245 <RoundUp+0x125>
movsd  0xe63(%rip),%xmm0
cs nopw 0x0(%rax,%rax,1)
nop
divsd  %xmm0,%xmm1
add    $0xffffffff,%ecx
jne    11b0 <RoundUp+0x90>
jmp    1245 <RoundUp+0x125>
mov    %eax,%ecx
neg    %ecx
and    $0x7,%ecx
je     11fd <RoundUp+0xdd>
neg    %ecx
xor    %edx,%edx
movsd  0xe35(%rip),%xmm0
movsd  (%rsp),%xmm1
nopl   0x0(%rax,%rax,1)
mulsd  %xmm0,%xmm1
add    $0xffffffff,%edx
cmp    %edx,%ecx
jne    11e0 <RoundUp+0xc0>
mov    %eax,%ecx
sub    %edx,%ecx
cmp    $0xfffffff8,%eax
jbe    1209 <RoundUp+0xe9>
jmp    1245 <RoundUp+0x125>
movsd  (%rsp),%xmm1
jmp    1245 <RoundUp+0x125>
mov    %eax,%ecx
movsd  (%rsp),%xmm1
cmp    $0xfffffff8,%eax
ja     1245 <RoundUp+0x125>
movsd  0xdf7(%rip),%xmm0
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
mulsd  %xmm0,%xmm1
mulsd  %xmm0,%xmm1
mulsd  %xmm0,%xmm1
mulsd  %xmm0,%xmm1
mulsd  %xmm0,%xmm1
mulsd  %xmm0,%xmm1
mulsd  %xmm0,%xmm1
mulsd  %xmm0,%xmm1
add    $0x8,%ecx
jne    1220 <RoundUp+0x100>
ucomisd 0xdc3(%rip),%xmm1
jbe    1260 <RoundUp+0x140>
movsd  0xdb1(%rip),%xmm0
test   %eax,%eax
jns    127e <RoundUp+0x15e>
jmp    130f <RoundUp+0x1ef>
ucomisd 0xdb0(%rip),%xmm1
jbe    12ee <RoundUp+0x1ce>
movsd  0xd9a(%rip),%xmm0
test   %eax,%eax
js     130f <RoundUp+0x1ef>
je     1375 <RoundUp+0x255>
lea    -0x1(%rax),%edx
mov    %eax,%ecx
and    $0x7,%ecx
cmp    $0x7,%edx
jb     12c5 <RoundUp+0x1a5>
and    $0xfffffff8,%eax
movsd  0xd6c(%rip),%xmm1
nopl   0x0(%rax)
mulsd  %xmm1,%xmm0
mulsd  %xmm1,%xmm0
mulsd  %xmm1,%xmm0
mulsd  %xmm1,%xmm0
mulsd  %xmm1,%xmm0
mulsd  %xmm1,%xmm0
mulsd  %xmm1,%xmm0
mulsd  %xmm1,%xmm0
add    $0xfffffff8,%eax
jne    12a0 <RoundUp+0x180>
test   %ecx,%ecx
je     1375 <RoundUp+0x255>
movsd  0xd33(%rip),%xmm1
cs nopw 0x0(%rax,%rax,1)
nop
mulsd  %xmm1,%xmm0
add    $0xffffffff,%ecx
jne    12e0 <RoundUp+0x1c0>
jmp    1375 <RoundUp+0x255>
xor    %ecx,%ecx
ucomisd 0xd28(%rip),%xmm1
seta   %cl
lea    0xd26(%rip),%rdx
movsd  (%rdx,%rcx,8),%xmm0
test   %eax,%eax
jns    127e <RoundUp+0x15e>
mov    %eax,%ecx
neg    %ecx
and    $0x3,%ecx
je     1346 <RoundUp+0x226>
neg    %ecx
xor    %edx,%edx
movsd  0xce4(%rip),%xmm1
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
divsd  %xmm1,%xmm0
add    $0xffffffff,%edx
cmp    %edx,%ecx
jne    1330 <RoundUp+0x210>
mov    %eax,%ecx
sub    %edx,%ecx
cmp    $0xfffffffc,%eax
jbe    134d <RoundUp+0x22d>
jmp    1375 <RoundUp+0x255>
mov    %eax,%ecx
cmp    $0xfffffffc,%eax
ja     1375 <RoundUp+0x255>
movsd  0xcb3(%rip),%xmm1
cs nopw 0x0(%rax,%rax,1)
nop
divsd  %xmm1,%xmm0
divsd  %xmm1,%xmm0
divsd  %xmm1,%xmm0
divsd  %xmm1,%xmm0
add    $0x4,%ecx
jne    1360 <RoundUp+0x240>
pop    %rax
ret

LLVM IR (-O0):
define double @RoundUp(double %0) {
%2 = alloca double
%3 = alloca i32
%4 = alloca i32
store double %0, double* %2
%5 = load double, double* %2
%6 = fcmp oeq double %5, 0.000000e+00
br i1 %6, label %7, label %8
7: ; preds = %1
br label %12
8: ; preds = %1
%9 = load double, double* %2
%10 = call double @log10(double %9)
%11 = fadd double %10, 1.000000e-15
br label %12
12: ; preds = %8, %7
%13 = phi double [ 0.000000e+00, %7 ], [ %11, %8 ]
%14 = call double @llvm.floor.f64(double %13)
%15 = fptosi double %14 to i32
store i32 %15, i32* %3
%16 = load i32, i32* %3
%17 = icmp slt i32 %16, 0
br i1 %17, label %18, label %30
18: ; preds = %12
%19 = load i32, i32* %3
store i32 %19, i32* %4
br label %20
20: ; preds = %26, %18
%21 = load i32, i32* %4
%22 = icmp slt i32 %21, 0
br i1 %22, label %23, label %29
23: ; preds = %20
%24 = load double, double* %2
%25 = fmul double %24, 1.000000e+01
store double %25, double* %2
br label %26
26: ; preds = %23
%27 = load i32, i32* %4
%28 = add nsw i32 %27, 1
store i32 %28, i32* %4
br label %20
29: ; preds = %20
br label %42
30: ; preds = %12
store i32 0, i32* %4
br label %31
31: ; preds = %38, %30
%32 = load i32, i32* %4
%33 = load i32, i32* %3
%34 = icmp slt i32 %32, %33
br i1 %34, label %35, label %41
35: ; preds = %31
%36 = load double, double* %2
%37 = fdiv double %36, 1.000000e+01
store double %37, double* %2
br label %38
38: ; preds = %35
%39 = load i32, i32* %4
%40 = add nsw i32 %39, 1
store i32 %40, i32* %4
br label %31
41: ; preds = %31
br label %42
42: ; preds = %41, %29
%43 = load double, double* %2
%44 = fcmp ogt double %43, 5.000000e+00
br i1 %44, label %45, label %46
45: ; preds = %42
store double 1.000000e+01, double* %2
br label %57
46: ; preds = %42
%47 = load double, double* %2
%48 = fcmp ogt double %47, 2.000000e+00
br i1 %48, label %49, label %50
49: ; preds = %46
store double 5.000000e+00, double* %2
br label %56
50: ; preds = %46
%51 = load double, double* %2
%52 = fcmp ogt double %51, 1.000000e+00
br i1 %52, label %53, label %54
53: ; preds = %50
store double 2.000000e+00, double* %2
br label %55
54: ; preds = %50
store double 1.000000e+00, double* %2
br label %55
55: ; preds = %54, %53
br label %56
56: ; preds = %55, %49
br label %57
57: ; preds = %56, %45
%58 = load i32, i32* %3
%59 = icmp slt i32 %58, 0
br i1 %59, label %60, label %72
60: ; preds = %57
%61 = load i32, i32* %3
store i32 %61, i32* %4
br label %62
62: ; preds = %68, %60
%63 = load i32, i32* %4
%64 = icmp slt i32 %63, 0
br i1 %64, label %65, label %71
65: ; preds = %62
%66 = load double, double* %2
%67 = fdiv double %66, 1.000000e+01
store double %67, double* %2
br label %68
68: ; preds = %65
%69 = load i32, i32* %4
%70 = add nsw i32 %69, 1
store i32 %70, i32* %4
br label %62
71: ; preds = %62
br label %84
72: ; preds = %57
store i32 0, i32* %4
br label %73
73: ; preds = %80, %72
%74 = load i32, i32* %4
%75 = load i32, i32* %3
%76 = icmp slt i32 %74, %75
br i1 %76, label %77, label %83
77: ; preds = %73
%78 = load double, double* %2
%79 = fmul double %78, 1.000000e+01
store double %79, double* %2
br label %80
80: ; preds = %77
%81 = load i32, i32* %4
%82 = add nsw i32 %81, 1
store i32 %82, i32* %4
br label %73
83: ; preds = %73
br label %84
84: ; preds = %83, %71
%85 = load double, double* %2
ret double %85
}

LLVM IR (-O2):
define double @RoundUp(double %0) {
%2 = fcmp oeq double %0, 0.000000e+00
br i1 %2, label %6, label %3
3: ; preds = %1
%4 = tail call double @log10(double %0)
%5 = fadd double %4, 1.000000e-15
br label %6
6: ; preds = %1, %3
%7 = phi double [ %5, %3 ], [ 0.000000e+00, %1 ]
%8 = tail call double @llvm.floor.f64(double %7)
%9 = fptosi double %8 to i32
%10 = icmp slt i32 %9, 0
br i1 %10, label %11, label %28
11: ; preds = %6
%12 = sub i32 0, %9
%13 = and i32 %12, 7
%14 = icmp eq i32 %13, 0
br i1 %14, label %23, label %15
15: ; preds = %11, %15
%16 = phi i32 [ %20, %15 ], [ %9, %11 ]
%17 = phi double [ %19, %15 ], [ %0, %11 ]
%18 = phi i32 [ %21, %15 ], [ 0, %11 ]
%19 = fmul double %17, 1.000000e+01
%20 = add i32 %16, 1
%21 = add i32 %18, 1
%22 = icmp eq i32 %21, %13
br i1 %22, label %23, label %15
23: ; preds = %15, %11
%24 = phi double [ undef, %11 ], [ %19, %15 ]
%25 = phi i32 [ %9, %11 ], [ %20, %15 ]
%26 = phi double [ %0, %11 ], [ %19, %15 ]
%27 = icmp ugt i32 %9, -8
br i1 %27, label %68, label %36
28: ; preds = %6
%29 = icmp eq i32 %9, 0
br i1 %29, label %68, label %30
30: ; preds = %28
%31 = add i32 %9, -1
%32 = and i32 %9, 3
%33 = icmp ult i32 %31, 3
br i1 %33, label %58, label %34
34: ; preds = %30
%35 = and i32 %9, -4
br label %49
36: ; preds = %23, %36
%37 = phi i32 [ %47, %36 ], [ %25, %23 ]
%38 = phi double [ %46, %36 ], [ %26, %23 ]
%39 = fmul double %38, 1.000000e+01
%40 = fmul double %39, 1.000000e+01
%41 = fmul double %40, 1.000000e+01
%42 = fmul double %41, 1.000000e+01
%43 = fmul double %42, 1.000000e+01
%44 = fmul double %43, 1.000000e+01
%45 = fmul double %44, 1.000000e+01
%46 = fmul double %45, 1.000000e+01
%47 = add i32 %37, 8
%48 = icmp eq i32 %47, 0
br i1 %48, label %68, label %36
49: ; preds = %49, %34
%50 = phi double [ %0, %34 ], [ %55, %49 ]
%51 = phi i32 [ 0, %34 ], [ %56, %49 ]
%52 = fdiv double %50, 1.000000e+01
%53 = fdiv double %52, 1.000000e+01
%54 = fdiv double %53, 1.000000e+01
%55 = fdiv double %54, 1.000000e+01
%56 = add i32 %51, 4
%57 = icmp eq i32 %56, %35
br i1 %57, label %58, label %49
58: ; preds = %49, %30
%59 = phi double [ undef, %30 ], [ %55, %49 ]
%60 = phi double [ %0, %30 ], [ %55, %49 ]
%61 = icmp eq i32 %32, 0
br i1 %61, label %68, label %62
62: ; preds = %58, %62
%63 = phi double [ %65, %62 ], [ %60, %58 ]
%64 = phi i32 [ %66, %62 ], [ 0, %58 ]
%65 = fdiv double %63, 1.000000e+01
%66 = add i32 %64, 1
%67 = icmp eq i32 %66, %32
br i1 %67, label %68, label %62
68: ; preds = %58, %62, %23, %36, %28
%69 = phi double [ %0, %28 ], [ %24, %23 ], [ %46, %36 ], [ %59, %58 ], [ %65, %62 ]
%70 = fcmp ogt double %69, 5.000000e+00
br i1 %70, label %76, label %71
71: ; preds = %68
%72 = fcmp ogt double %69, 2.000000e+00
br i1 %72, label %76, label %73
73: ; preds = %71
%74 = fcmp ogt double %69, 1.000000e+00
%75 = select i1 %74, double 2.000000e+00, double 1.000000e+00
br label %76
76: ; preds = %73, %71, %68
%77 = phi double [ 1.000000e+01, %68 ], [ 5.000000e+00, %71 ], [ %75, %73 ]
br i1 %10, label %78, label %95
78: ; preds = %76
%79 = sub i32 0, %9
%80 = and i32 %79, 3
%81 = icmp eq i32 %80, 0
br i1 %81, label %90, label %82
82: ; preds = %78, %82
%83 = phi i32 [ %87, %82 ], [ %9, %78 ]
%84 = phi double [ %86, %82 ], [ %77, %78 ]
%85 = phi i32 [ %88, %82 ], [ 0, %78 ]
%86 = fdiv double %84, 1.000000e+01
%87 = add i32 %83, 1
%88 = add i32 %85, 1
%89 = icmp eq i32 %88, %80
br i1 %89, label %90, label %82
90: ; preds = %82, %78
%91 = phi double [ undef, %78 ], [ %86, %82 ]
%92 = phi i32 [ %9, %78 ], [ %87, %82 ]
%93 = phi double [ %77, %78 ], [ %86, %82 ]
%94 = icmp ugt i32 %9, -4
br i1 %94, label %135, label %103
95: ; preds = %76
%96 = icmp eq i32 %9, 0
br i1 %96, label %135, label %97
97: ; preds = %95
%98 = add i32 %9, -1
%99 = and i32 %9, 7
%100 = icmp ult i32 %98, 7
br i1 %100, label %125, label %101
101: ; preds = %97
%102 = and i32 %9, -8
br label %112
103: ; preds = %90, %103
%104 = phi i32 [ %110, %103 ], [ %92, %90 ]
%105 = phi double [ %109, %103 ], [ %93, %90 ]
%106 = fdiv double %105, 1.000000e+01
%107 = fdiv double %106, 1.000000e+01
%108 = fdiv double %107, 1.000000e+01
%109 = fdiv double %108, 1.000000e+01
%110 = add i32 %104, 4
%111 = icmp eq i32 %110, 0
br i1 %111, label %135, label %103
112: ; preds = %112, %101
%113 = phi double [ %77, %101 ], [ %122, %112 ]
%114 = phi i32 [ 0, %101 ], [ %123, %112 ]
%115 = fmul double %113, 1.000000e+01
%116 = fmul double %115, 1.000000e+01
%117 = fmul double %116, 1.000000e+01
%118 = fmul double %117, 1.000000e+01
%119 = fmul double %118, 1.000000e+01
%120 = fmul double %119, 1.000000e+01
%121 = fmul double %120, 1.000000e+01
%122 = fmul double %121, 1.000000e+01
%123 = add i32 %114, 8
%124 = icmp eq i32 %123, %102
br i1 %124, label %125, label %112
125: ; preds = %112, %97
%126 = phi double [ undef, %97 ], [ %122, %112 ]
%127 = phi double [ %77, %97 ], [ %122, %112 ]
%128 = icmp eq i32 %99, 0
br i1 %128, label %135, label %129
129: ; preds = %125, %129
%130 = phi double [ %132, %129 ], [ %127, %125 ]
%131 = phi i32 [ %133, %129 ], [ 0, %125 ]
%132 = fmul double %130, 1.000000e+01
%133 = add i32 %131, 1
%134 = icmp eq i32 %133, %99
br i1 %134, label %135, label %129
135: ; preds = %125, %129, %90, %103, %95
%136 = phi double [ %77, %95 ], [ %91, %90 ], [ %109, %103 ], [ %126, %125 ], [ %132, %129 ]
ret double %136
}