double sqrt_n(int n) {
  if (n <= 0) {
    return 0;
  }
  double x0, y0, x1, y1;
  x0 = n / 2.0;
  y0 = x0 * x0 - n;
  while (y0 < -0.001 || y0 > 0.001) {
    x1 = x0 - y0 / (2 * x0);
    y1 = x1 * x1 - n;
    if (y0 > 0 && y1 > 0) {
      x0 = x0 / 2;
    } else if (y0 < 0 && y1 < 0) {
      x0 = 2 * x0;
    } else {
      x0 = (x0 + x1) / 2;
    }
    y0 = x0 * x0 - n;
  }
  return x0;
}


x86 assembly (clang, -O0):
<sqrt_n>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0xc(%rbp)
cmpl   $0x0,-0xc(%rbp)
jg     111e <sqrt_n+0x1e>
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    12d1 <sqrt_n+0x1d1>
cvtsi2sdl -0xc(%rbp),%xmm0
movsd  0xed5(%rip),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  -0x18(%rbp),%xmm0
movsd  -0x18(%rbp),%xmm2
cvtsi2sdl -0xc(%rbp),%xmm1
movq   %xmm1,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x20(%rbp)
mov    $0x1,%al
movsd  0xe97(%rip),%xmm0
ucomisd -0x20(%rbp),%xmm0
mov    %al,-0x31(%rbp)
ja     1196 <sqrt_n+0x96>
movsd  -0x20(%rbp),%xmm0
movsd  0xe84(%rip),%xmm1
ucomisd %xmm1,%xmm0
seta   %al
mov    %al,-0x31(%rbp)
mov    -0x31(%rbp),%al
test   $0x1,%al
jne    11a6 <sqrt_n+0xa6>
jmp    12c7 <sqrt_n+0x1c7>
movsd  -0x18(%rbp),%xmm0
movsd  -0x20(%rbp),%xmm1
movsd  0xe48(%rip),%xmm2
mulsd  -0x18(%rbp),%xmm2
divsd  %xmm2,%xmm1
subsd  %xmm1,%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x28(%rbp),%xmm0
movsd  -0x28(%rbp),%xmm2
cvtsi2sdl -0xc(%rbp),%xmm1
movq   %xmm1,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x20(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jbe    123c <sqrt_n+0x13c>
movsd  -0x30(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jbe    123c <sqrt_n+0x13c>
movsd  -0x18(%rbp),%xmm0
movsd  0xdd2(%rip),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
jmp    128f <sqrt_n+0x18f>
xorps  %xmm0,%xmm0
ucomisd -0x20(%rbp),%xmm0
jbe    126f <sqrt_n+0x16f>
xorps  %xmm0,%xmm0
ucomisd -0x30(%rbp),%xmm0
jbe    126f <sqrt_n+0x16f>
movsd  0xda0(%rip),%xmm0
mulsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
jmp    128a <sqrt_n+0x18a>
movsd  -0x18(%rbp),%xmm0
addsd  -0x28(%rbp),%xmm0
movsd  0xd7f(%rip),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
jmp    128f <sqrt_n+0x18f>
movsd  -0x18(%rbp),%xmm0
movsd  -0x18(%rbp),%xmm2
cvtsi2sdl -0xc(%rbp),%xmm1
movq   %xmm1,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x20(%rbp)
jmp    1167 <sqrt_n+0x67>
movsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<sqrt_n>:
test   %edi,%edi
jle    113d <sqrt_n+0x3d>
cvtsi2sd %edi,%xmm1
movsd  0xef0(%rip),%xmm5
mulsd  %xmm1,%xmm5
movapd %xmm5,%xmm7
mulsd  %xmm5,%xmm7
subsd  %xmm1,%xmm7
movsd  0xee0(%rip),%xmm2
ucomisd %xmm7,%xmm2
ja     1141 <sqrt_n+0x41>
ucomisd 0xeda(%rip),%xmm7
ja     1141 <sqrt_n+0x41>
movapd %xmm5,%xmm0
ret
xorps  %xmm0,%xmm0
ret
xorpd  0xed7(%rip),%xmm1
xorpd  %xmm4,%xmm4
movsd  0xeaa(%rip),%xmm9
movsd  0xeb1(%rip),%xmm8
nop
movapd %xmm5,%xmm0
addsd  %xmm5,%xmm0
movapd %xmm7,%xmm3
divsd  %xmm0,%xmm3
movapd %xmm5,%xmm6
subsd  %xmm3,%xmm6
movapd %xmm6,%xmm3
mulsd  %xmm6,%xmm3
addsd  %xmm1,%xmm3
ucomisd %xmm4,%xmm7
jbe    1190 <sqrt_n+0x90>
ucomisd %xmm4,%xmm3
ja     11a0 <sqrt_n+0xa0>
ucomisd %xmm7,%xmm4
jbe    119c <sqrt_n+0x9c>
ucomisd %xmm3,%xmm4
ja     11a9 <sqrt_n+0xa9>
addsd  %xmm6,%xmm5
mulsd  %xmm9,%xmm5
movapd %xmm5,%xmm0
movapd %xmm0,%xmm7
mulsd  %xmm0,%xmm7
addsd  %xmm1,%xmm7
ucomisd %xmm7,%xmm2
movapd %xmm0,%xmm5
ja     1160 <sqrt_n+0x60>
ucomisd %xmm8,%xmm7
movapd %xmm0,%xmm5
ja     1160 <sqrt_n+0x60>
ret

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

LLVM IR (-O2):
define double @sqrt_n(i32 %0) {
%2 = icmp slt i32 %0, 1
br i1 %2, label %36, label %3
3: ; preds = %1
%4 = sitofp i32 %0 to double
%5 = fmul double %4, 5.000000e-01
%6 = fneg double %4
%7 = tail call double @llvm.fmuladd.f64(double %5, double %5, double %6)
%8 = fcmp olt double %7, -1.000000e-03
%9 = fcmp ogt double %7, 1.000000e-03
%10 = or i1 %8, %9
br i1 %10, label %11, label %36
11: ; preds = %3, %30
%12 = phi double [ %31, %30 ], [ %5, %3 ]
%13 = phi double [ %32, %30 ], [ %7, %3 ]
%14 = fmul double %12, 2.000000e+00
%15 = fdiv double %13, %14
%16 = fsub double %12, %15
%17 = tail call double @llvm.fmuladd.f64(double %16, double %16, double %6)
%18 = fcmp ogt double %13, 0.000000e+00
%19 = fcmp ogt double %17, 0.000000e+00
%20 = select i1 %18, i1 %19, i1 false
br i1 %20, label %21, label %23
21: ; preds = %11
%22 = fmul double %12, 5.000000e-01
br label %30
23: ; preds = %11
%24 = fcmp olt double %13, 0.000000e+00
%25 = fcmp olt double %17, 0.000000e+00
%26 = select i1 %24, i1 %25, i1 false
br i1 %26, label %30, label %27
27: ; preds = %23
%28 = fadd double %12, %16
%29 = fmul double %28, 5.000000e-01
br label %30
30: ; preds = %23, %27, %21
%31 = phi double [ %22, %21 ], [ %29, %27 ], [ %14, %23 ]
%32 = tail call double @llvm.fmuladd.f64(double %31, double %31, double %6)
%33 = fcmp olt double %32, -1.000000e-03
%34 = fcmp ogt double %32, 1.000000e-03
%35 = or i1 %33, %34
br i1 %35, label %11, label %36
36: ; preds = %30, %3, %1
%37 = phi double [ 0.000000e+00, %1 ], [ %5, %3 ], [ %31, %30 ]
ret double %37
}