summaryrefslogtreecommitdiff
path: root/stdlib/complex.ml
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/complex.ml')
-rw-r--r--stdlib/complex.ml25
1 files changed, 15 insertions, 10 deletions
diff --git a/stdlib/complex.ml b/stdlib/complex.ml
index fe2e0388d1..3095534bab 100644
--- a/stdlib/complex.ml
+++ b/stdlib/complex.ml
@@ -62,16 +62,21 @@ let arg x = atan2 x.im x.re
let polar n a = { re = cos a *. n; im = sin a *. n }
-let sqrt x =
- (* Avoid cancellation in computing norm x + x.re
- when x.re < 0 and x.im is small *)
- if x.re >= 0.0 then begin
- let r = sqrt(0.5 *. norm x +. 0.5 *. x.re) in
- { re = r; im = if r = 0.0 then 0.0 else 0.5 *. x.im /. r }
- end else begin
- let s = sqrt(0.5 *. norm x -. 0.5 *. x.re) in
- { re = if s = 0.0 then 0.0 else 0.5 *. abs_float x.im /. s;
- im = if x.im >= 0.0 then s else -. s }
+let sqrt x =
+ if x.re = 0.0 && x.im = 0.0 then { re = 0.0; im = 0.0 }
+ else begin
+ let r = abs_float x.re and i = abs_float x.im in
+ let w =
+ if r >= i then begin
+ let q = i /. r in
+ sqrt(r) *. sqrt(0.5 *. (1.0 +. sqrt(1.0 +. q *. q)))
+ end else begin
+ let q = r /. i in
+ sqrt(i) *. sqrt(0.5 *. (q +. sqrt(1.0 +. q *. q)))
+ end in
+ if x.re >= 0.0
+ then { re = w; im = 0.5 *. x.im /. w }
+ else { re = 0.5 *. i /. w; im = if x.im >= 0.0 then w else -. w }
end
let exp x =