Merge branch 'devel' into araq-big-refactoring
This commit is contained in:
commit
9849808720
9 changed files with 115 additions and 41 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
}""".}
|
||||
|
|
|
|||
|
|
@ -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{.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue