From 07233ceca0fa220418f1691e70c9e8d49e440737 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Fri, 5 May 2023 20:23:38 +0800 Subject: [PATCH] fixes #21792; enable checks for sum, prod, cumsummed and cumsum (#21793) * enable checks for sum, prod, cumsummed and cumsum * fixes #21792 * add test cases --- lib/pure/math.nim | 123 +++++++++++++++++++++-------------------- tests/stdlib/tmath.nim | 16 +++++- 2 files changed, 78 insertions(+), 61 deletions(-) diff --git a/lib/pure/math.nim b/lib/pure/math.nim index bea655a0e1..fc45a66416 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -326,68 +326,8 @@ func nextPowerOfTwo*(x: int): int = result = result or (result shr 1) result += 1 + ord(x <= 0) -func sum*[T](x: openArray[T]): T = - ## Computes the sum of the elements in `x`. - ## - ## If `x` is empty, 0 is returned. - ## - ## **See also:** - ## * `prod func <#prod,openArray[T]>`_ - ## * `cumsum func <#cumsum,openArray[T]>`_ - ## * `cumsummed func <#cumsummed,openArray[T]>`_ - runnableExamples: - doAssert sum([1, 2, 3, 4]) == 10 - doAssert sum([-4, 3, 5]) == 4 - for i in items(x): result = result + i -func prod*[T](x: openArray[T]): T = - ## Computes the product of the elements in `x`. - ## - ## If `x` is empty, 1 is returned. - ## - ## **See also:** - ## * `sum func <#sum,openArray[T]>`_ - ## * `fac func <#fac,int>`_ - runnableExamples: - doAssert prod([1, 2, 3, 4]) == 24 - doAssert prod([-4, 3, 5]) == -60 - - result = T(1) - for i in items(x): result = result * i - -func cumsummed*[T](x: openArray[T]): seq[T] = - ## Returns the cumulative (aka prefix) summation of `x`. - ## - ## If `x` is empty, `@[]` is returned. - ## - ## **See also:** - ## * `sum func <#sum,openArray[T]>`_ - ## * `cumsum func <#cumsum,openArray[T]>`_ for the in-place version - runnableExamples: - doAssert cumsummed([1, 2, 3, 4]) == @[1, 3, 6, 10] - - let xLen = x.len - if xLen == 0: - return @[] - result.setLen(xLen) - result[0] = x[0] - for i in 1 ..< xLen: result[i] = result[i - 1] + x[i] - -func cumsum*[T](x: var openArray[T]) = - ## Transforms `x` in-place (must be declared as `var`) into its - ## cumulative (aka prefix) summation. - ## - ## **See also:** - ## * `sum func <#sum,openArray[T]>`_ - ## * `cumsummed func <#cumsummed,openArray[T]>`_ for a version which - ## returns a cumsummed sequence - runnableExamples: - var a = [1, 2, 3, 4] - cumsum(a) - doAssert a == @[1, 3, 6, 10] - - for i in 1 ..< x.len: x[i] = x[i - 1] + x[i] when not defined(js): # C func sqrt*(x: float32): float32 {.importc: "sqrtf", header: "".} @@ -1133,6 +1073,69 @@ func sgn*[T: SomeNumber](x: T): int {.inline.} = {.pop.} {.pop.} +func sum*[T](x: openArray[T]): T = + ## Computes the sum of the elements in `x`. + ## + ## If `x` is empty, 0 is returned. + ## + ## **See also:** + ## * `prod func <#prod,openArray[T]>`_ + ## * `cumsum func <#cumsum,openArray[T]>`_ + ## * `cumsummed func <#cumsummed,openArray[T]>`_ + runnableExamples: + doAssert sum([1, 2, 3, 4]) == 10 + doAssert sum([-4, 3, 5]) == 4 + + for i in items(x): result = result + i + +func prod*[T](x: openArray[T]): T = + ## Computes the product of the elements in `x`. + ## + ## If `x` is empty, 1 is returned. + ## + ## **See also:** + ## * `sum func <#sum,openArray[T]>`_ + ## * `fac func <#fac,int>`_ + runnableExamples: + doAssert prod([1, 2, 3, 4]) == 24 + doAssert prod([-4, 3, 5]) == -60 + + result = T(1) + for i in items(x): result = result * i + +func cumsummed*[T](x: openArray[T]): seq[T] = + ## Returns the cumulative (aka prefix) summation of `x`. + ## + ## If `x` is empty, `@[]` is returned. + ## + ## **See also:** + ## * `sum func <#sum,openArray[T]>`_ + ## * `cumsum func <#cumsum,openArray[T]>`_ for the in-place version + runnableExamples: + doAssert cumsummed([1, 2, 3, 4]) == @[1, 3, 6, 10] + + let xLen = x.len + if xLen == 0: + return @[] + result.setLen(xLen) + result[0] = x[0] + for i in 1 ..< xLen: result[i] = result[i - 1] + x[i] + +func cumsum*[T](x: var openArray[T]) = + ## Transforms `x` in-place (must be declared as `var`) into its + ## cumulative (aka prefix) summation. + ## + ## **See also:** + ## * `sum func <#sum,openArray[T]>`_ + ## * `cumsummed func <#cumsummed,openArray[T]>`_ for a version which + ## returns a cumsummed sequence + runnableExamples: + var a = [1, 2, 3, 4] + cumsum(a) + doAssert a == @[1, 3, 6, 10] + + for i in 1 ..< x.len: x[i] = x[i - 1] + x[i] + func `^`*[T: SomeNumber](x: T, y: Natural): T = ## Computes `x` to the power of `y`. ## diff --git a/tests/stdlib/tmath.nim b/tests/stdlib/tmath.nim index 8ddb09bf58..2076a6efff 100644 --- a/tests/stdlib/tmath.nim +++ b/tests/stdlib/tmath.nim @@ -439,6 +439,20 @@ template main() = doAssert lgamma(-0.0) == Inf doAssert lgamma(-1.0) == Inf - static: main() main() + +when not defined(js) and not defined(danger): + block: # bug #21792 + block: + type Digit = 0..9 + var x = [Digit 4, 7] + + doAssertRaises(RangeDefect): + discard sum(x) + + block: + var x = [int8 124, 127] + + doAssertRaises(OverflowDefect): + discard sum(x)