Merge branch 'devel' into araq-big-refactoring

This commit is contained in:
Andreas Rumpf 2018-05-27 13:38:09 +02:00
commit 9849808720
9 changed files with 115 additions and 41 deletions

View file

@ -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

View file

@ -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]:

View file

@ -70,8 +70,9 @@ type
bump: pointer
head, tail: Chunk
nextChunkSize, totalSize: int
freeLists: array[MaxSmallObject div MemAlign, FreeEntry]
holes: SizedFreeEntry
when false:
freeLists: array[MaxSmallObject div MemAlign, FreeEntry]
holes: SizedFreeEntry
when hasThreadSupport:
lock: SysLock
@ -145,21 +146,22 @@ proc allocSlowPath(r: var MemRegion; size: int) =
r.remaining = s - sizeof(BaseChunk)
proc allocFast(r: var MemRegion; size: int): pointer =
if size <= MaxSmallObject:
var it = r.freeLists[size div MemAlign]
if it != nil:
r.freeLists[size div MemAlign] = it.next
return pointer(it)
else:
var it = r.holes
var prev: SizedFreeEntry = nil
while it != nil:
if it.size >= size:
if prev != nil: prev.next = it.next
else: r.holes = it.next
when false:
if size <= MaxSmallObject:
var it = r.freeLists[size div MemAlign]
if it != nil:
r.freeLists[size div MemAlign] = it.next
return pointer(it)
prev = it
it = it.next
else:
var it = r.holes
var prev: SizedFreeEntry = nil
while it != nil:
if it.size >= size:
if prev != nil: prev.next = it.next
else: r.holes = it.next
return pointer(it)
prev = it
it = it.next
if size > r.remaining:
allocSlowPath(r, size)
sysAssert(size <= r.remaining, "size <= r.remaining")
@ -184,15 +186,16 @@ proc dealloc(r: var MemRegion; p: pointer; size: int) =
# it is benefitial to not use the free lists here:
if r.bump -! size == p:
dec r.bump, size
elif size <= MaxSmallObject:
let it = cast[FreeEntry](p)
it.next = r.freeLists[size div MemAlign]
r.freeLists[size div MemAlign] = it
else:
let it = cast[SizedFreeEntry](p)
it.size = size
it.next = r.holes
r.holes = it
when false:
if size <= MaxSmallObject:
let it = cast[FreeEntry](p)
it.next = r.freeLists[size div MemAlign]
r.freeLists[size div MemAlign] = it
else:
let it = cast[SizedFreeEntry](p)
it.size = size
it.next = r.holes
r.holes = it
proc deallocAll(r: var MemRegion; head: Chunk) =
var it = head
@ -220,9 +223,10 @@ proc setObstackPtr*(r: var MemRegion; sp: StackPtr) =
if sp.current.next != nil:
deallocAll(r, sp.current.next)
sp.current.next = nil
# better leak this memory than be sorry:
for i in 0..high(r.freeLists): r.freeLists[i] = nil
r.holes = nil
when false:
# better leak this memory than be sorry:
for i in 0..high(r.freeLists): r.freeLists[i] = nil
r.holes = nil
#else:
# deallocAll(r, r.head)
# r.head = nil

View file

@ -332,7 +332,7 @@ proc cmpStrings(a, b: string): int {.asmNoStackFrame, compilerProc.} =
return `a`.length - `b`.length;
"""
proc cmp(x, y: string): int =
proc cmp(x, y: string): int =
return cmpStrings(x, y)
proc eqStrings(a, b: string): bool {.asmNoStackFrame, compilerProc.} =
@ -750,3 +750,16 @@ when defined(nodejs):
else:
# Deprecated. Use `alert` defined in dom.nim
proc alert*(s: cstring) {.importc, nodecl, deprecated.}
# Workaround for IE, IE up to version 11 lacks 'Math.trunc'. We produce
# 'Math.trunc' for Nim's ``div`` and ``mod`` operators:
when not defined(nodejs):
{.emit: """
if (!Math.trunc) {
Math.trunc = function(v) {
v = +v;
if (!isFinite(v)) return v;
return (v - v % 1) || (v < 0 ? -0 : v === 0 ? v : 0);
};
}""".}

View file

@ -390,7 +390,7 @@ proc ERR_peek_last_error*(): cInt{.cdecl, dynlib: DLLUtilName, importc.}
proc OPENSSL_config*(configName: cstring){.cdecl, dynlib: DLLSSLName, importc.}
when not useWinVersion and not defined(macosx) and not defined(android):
when not useWinVersion and not defined(macosx) and not defined(android) and not defined(nimNoAllocForSSL):
proc CRYPTO_set_mem_functions(a,b,c: pointer){.cdecl,
dynlib: DLLUtilName, importc.}
@ -404,7 +404,7 @@ when not useWinVersion and not defined(macosx) and not defined(android):
if p != nil: dealloc(p)
proc CRYPTO_malloc_init*() =
when not useWinVersion and not defined(macosx) and not defined(android):
when not useWinVersion and not defined(macosx) and not defined(android) and not defined(nimNoAllocForSSL):
CRYPTO_set_mem_functions(allocWrapper, reallocWrapper, deallocWrapper)
proc SSL_CTX_ctrl*(ctx: SslCtx, cmd: cInt, larg: int, parg: pointer): int{.