From 17b55f9b29484f47e0008666cf638f6e26a782e2 Mon Sep 17 00:00:00 2001 From: John Novak Date: Fri, 16 Jun 2017 05:00:18 +1000 Subject: Add sgn() function to the math module (#5971) --- lib/pure/math.nim | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'lib/pure/math.nim') diff --git a/lib/pure/math.nim b/lib/pure/math.nim index a8432b6f0..a1b2690a2 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -395,6 +395,12 @@ proc radToDeg*[T: float32|float64](d: T): T {.inline.} = ## Convert from radians to degrees result = T(d) / RadPerDeg +proc sgn*[T: SomeNumber](x: T): int {.inline.} = + ## Sign function. Returns -1 for negative numbers and `NegInf`, 1 for + ## positive numbers and `Inf`, and 0 for positive zero, negative zero and + ## `NaN`. + ord(T(0) < x) - ord(x < T(0)) + proc `mod`*[T: float32|float64](x, y: T): T = ## Computes the modulo operation for float operators. Equivalent ## to ``x - y * floor(x/y)``. Note that the remainder will always @@ -447,6 +453,7 @@ when isMainModule and not defined(JS): assert(lgamma(1.0) == 0.0) # ln(1.0) == 0.0 assert(erf(6.0) > erf(5.0)) assert(erfc(6.0) < erfc(5.0)) + when isMainModule: # Function for approximate comparison of floats proc `==~`(x, y: float): bool = (abs(x-y) < 1e-9) @@ -509,3 +516,21 @@ when isMainModule: doAssert(classify(trunc(-1e1000000'f32)) == fcNegInf) doAssert(classify(trunc(f_nan.float32)) == fcNan) doAssert(classify(trunc(0.0'f32)) == fcZero) + + block: # sgn() tests + assert sgn(1'i8) == 1 + assert sgn(1'i16) == 1 + assert sgn(1'i32) == 1 + assert sgn(1'i64) == 1 + assert sgn(1'u8) == 1 + assert sgn(1'u16) == 1 + assert sgn(1'u32) == 1 + assert sgn(1'u64) == 1 + assert sgn(-12342.8844'f32) == -1 + assert sgn(123.9834'f64) == 1 + assert sgn(0'i32) == 0 + assert sgn(0'f32) == 0 + assert sgn(NegInf) == -1 + assert sgn(Inf) == 1 + assert sgn(NaN) == 0 + -- cgit 1.4.1-2-gfad0 From a6e0494a6fc6149a53908cf5c58da58679a539c8 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Tue, 20 Jun 2017 12:11:09 +0200 Subject: fixes #5966 --- lib/pure/math.nim | 11 +++++++---- lib/pure/random.nim | 3 ++- tests/stdlib/tmath.nim | 23 ++++++++++++++++++++++- 3 files changed, 31 insertions(+), 6 deletions(-) (limited to 'lib/pure/math.nim') diff --git a/lib/pure/math.nim b/lib/pure/math.nim index a1b2690a2..8037b31b0 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -235,7 +235,7 @@ when not defined(JS): x = x and (not (1'u64 shl (64'u64-12'u64-e) - 1'u64)) result = cast[float64](x) - + proc truncImpl(f: float32): float32 = const mask : uint32 = 0xFF @@ -255,7 +255,7 @@ when not defined(JS): x = x and (not (1'u32 shl (32'u32-9'u32-e) - 1'u32)) result = cast[float32](x) - + proc trunc*(x: float64): float64 = if classify(x) in {fcZero, fcNegZero, fcNan, fcInf, fcNegInf}: return x result = truncImpl(x) @@ -413,10 +413,13 @@ proc `mod`*[T: float32|float64](x, y: T): T = {.pop.} {.pop.} -proc `^`*[T](x, y: T): T = +proc `^`*[T](x: T, y: Natural): T = ## Computes ``x`` to the power ``y`. ``x`` must be non-negative, use ## `pow <#pow,float,float>` for negative exponents. - assert y >= T(0) + when compiles(y >= T(0)): + assert y >= T(0) + else: + assert T(y) >= T(0) var (x, y) = (x, y) result = 1 diff --git a/lib/pure/random.nim b/lib/pure/random.nim index 1f750edcd..8a32f7d9a 100644 --- a/lib/pure/random.nim +++ b/lib/pure/random.nim @@ -123,7 +123,8 @@ when not defined(nimscript): proc getMil(t: Time): int {.importcpp: "getTime", nodecl.} randomize(getMil times.getTime()) else: - randomize(int times.getTime()) + let time = int(times.epochTime() * 1_000_000_000) + randomize(time) {.pop.} diff --git a/tests/stdlib/tmath.nim b/tests/stdlib/tmath.nim index 538582ba8..581308a7e 100644 --- a/tests/stdlib/tmath.nim +++ b/tests/stdlib/tmath.nim @@ -1,4 +1,15 @@ -import math, random +discard """ + action: run + output: '''[Suite] random int + +[Suite] random float + +[Suite] ^ + +''' +""" + +import math, random, os import unittest import sets @@ -26,6 +37,7 @@ suite "random int": test "randomize() again gives new numbers": randomize() var rand1 = random(1000000) + os.sleep(200) randomize() var rand2 = random(1000000) check rand1 != rand2 @@ -55,7 +67,16 @@ suite "random float": test "randomize() again gives new numbers": randomize() var rand1:float = random(1000000.0) + os.sleep(200) randomize() var rand2:float = random(1000000.0) check rand1 != rand2 +suite "^": + test "compiles for valid types": + check: compiles(5 ^ 2) + check: compiles(5.5 ^ 2) + check: compiles(5.5 ^ 2.int8) + check: compiles(5.5 ^ 2.uint) + check: compiles(5.5 ^ 2.uint8) + check: not compiles(5.5 ^ 2.2) \ No newline at end of file -- cgit 1.4.1-2-gfad0