summary refs log tree commit diff stats
path: root/lib/pure
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2018-05-27 13:38:09 +0200
committerAndreas Rumpf <rumpf_a@web.de>2018-05-27 13:38:09 +0200
commit98498087202203e343c782ce24e294bd0b82becf (patch)
tree1bec5f2fa4f14b9925b10622288390f43673175c /lib/pure
parent669a5644926290e19a3fc32fd319c056183ff2d9 (diff)
parent7e8eadb6ba9c94ea429ee7178e8cc8fbcbf558ea (diff)
downloadNim-98498087202203e343c782ce24e294bd0b82becf.tar.gz
Merge branch 'devel' into araq-big-refactoring
Diffstat (limited to 'lib/pure')
-rw-r--r--lib/pure/math.nim32
-rw-r--r--lib/pure/parseutils.nim3
2 files changed, 33 insertions, 2 deletions
diff --git a/lib/pure/math.nim b/lib/pure/math.nim
index 9e590debc..49d87f007 100644
--- a/lib/pure/math.nim
+++ b/lib/pure/math.nim
@@ -21,6 +21,8 @@ include "system/inclrtl"
 {.push debugger:off .} # the user does not want to trace a part
                        # of the standard library!
 
+import bitops
+
 proc binom*(n, k: int): int {.noSideEffect.} =
   ## Computes the binomial coefficient
   if k <= 0: return 1
@@ -455,16 +457,42 @@ proc `^`*[T](x: T, y: Natural): T =
     x *= x
 
 proc gcd*[T](x, y: T): T =
-  ## Computes the greatest common divisor of ``x`` and ``y``.
+  ## Computes the greatest common (positive) divisor of ``x`` and ``y``.
   ## Note that for floats, the result cannot always be interpreted as
   ## "greatest decimal `z` such that ``z*N == x and z*M == y``
   ## where N and M are positive integers."
-  var (x,y) = (x,y)
+  var (x, y) = (x, y)
   while y != 0:
     x = x mod y
     swap x, y
   abs x
 
+proc gcd*(x, y: SomeInteger): SomeInteger =
+  ## Computes the greatest common (positive) divisor of ``x`` and ``y``.
+  ## Using binary GCD (aka Stein's) algorithm.
+  when x is SomeSignedInt:
+    var x = abs(x)
+  else:
+    var x = x
+  when y is SomeSignedInt:
+    var y = abs(y)
+  else:
+    var y = y
+
+  if x == 0:
+    return y
+  if y == 0:
+    return x
+
+  let shift = countTrailingZeroBits(x or y)
+  y = y shr countTrailingZeroBits(y)
+  while x != 0:
+    x = x shr countTrailingZeroBits(x)
+    if y > x:
+      swap y, x
+    x -= y
+  y shl shift
+
 proc lcm*[T](x, y: T): T =
   ## Computes the least common multiple of ``x`` and ``y``.
   x div gcd(x, y) * y
diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim
index d77790fe0..d54f1454b 100644
--- a/lib/pure/parseutils.nim
+++ b/lib/pure/parseutils.nim
@@ -197,6 +197,9 @@ proc parseUntil*(s: string, token: var string, until: string,
   ## parses a token and stores it in ``token``. Returns
   ## the number of the parsed characters or 0 in case of an error. A token
   ## consists of any character that comes before the `until`  token.
+  if until.len == 0:
+    token.setLen(0)
+    return 0
   var i = start
   while i < s.len:
     if s[i] == until[0]: