mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-27 17:53:58 +00:00
Add divmod (#22102)
* Adding divmod * Adding support to VM * Wrapped C structs and funcs * Fix javascript impl * Fixing struct compat * Segregate tests, better compiletime defs * Using `inline` and switch back to `func` * Apply suggestions from code review * Explicit structures --------- Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
This commit is contained in:
@@ -39,6 +39,13 @@ proc setResult*(a: VmArgs; v: seq[string]) =
|
||||
for x in v: n.add newStrNode(nkStrLit, x)
|
||||
a.slots[a.ra].node = n
|
||||
|
||||
proc setResult*(a: VmArgs; v: (BiggestInt, BiggestInt)) =
|
||||
a.slots[a.ra].ensureKind(rkNode)
|
||||
var tuplen = newNode(nkTupleConstr)
|
||||
tuplen.add newIntNode(nkIntLit, v[0])
|
||||
tuplen.add newIntNode(nkIntLit, v[1])
|
||||
a.slots[a.ra].node = tuplen
|
||||
|
||||
template getReg(a, i): untyped =
|
||||
doAssert i < a.rc-1
|
||||
a.slots[i+a.rb+1].unsafeAddr
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
from std/math import sqrt, ln, log10, log2, exp, round, arccos, arcsin,
|
||||
arctan, arctan2, cos, cosh, hypot, sinh, sin, tan, tanh, pow, trunc,
|
||||
floor, ceil, `mod`, cbrt, arcsinh, arccosh, arctanh, erf, erfc, gamma,
|
||||
lgamma
|
||||
lgamma, divmod
|
||||
from std/sequtils import toSeq
|
||||
when declared(math.copySign):
|
||||
# pending bug #18762, avoid renaming math
|
||||
@@ -80,6 +80,11 @@ template wrap2fMath(op) {.dirty.} =
|
||||
setResult(a, op(getFloat(a, 0), getFloat(a, 1)))
|
||||
mathop op
|
||||
|
||||
template wrap2iMath(op) {.dirty.} =
|
||||
proc `op Wrapper`(a: VmArgs) {.nimcall.} =
|
||||
setResult(a, op(getInt(a, 0), getInt(a, 1)))
|
||||
mathop op
|
||||
|
||||
template wrap0(op, modop) {.dirty.} =
|
||||
proc `op Wrapper`(a: VmArgs) {.nimcall.} =
|
||||
setResult(a, op())
|
||||
@@ -224,6 +229,7 @@ proc registerAdditionalOps*(c: PCtx) =
|
||||
wrap1fMath(erfc)
|
||||
wrap1fMath(gamma)
|
||||
wrap1fMath(lgamma)
|
||||
wrap2iMath(divmod)
|
||||
|
||||
when declared(copySign):
|
||||
wrap2fMath(copySign)
|
||||
|
||||
@@ -77,6 +77,36 @@ when defined(c) or defined(cpp):
|
||||
importc: "frexpf", header: "<math.h>".}
|
||||
func c_frexp2(x: cdouble, exponent: var cint): cdouble {.
|
||||
importc: "frexp", header: "<math.h>".}
|
||||
|
||||
type
|
||||
div_t {.importc, header: "<stdlib.h>".} = object
|
||||
quot: cint
|
||||
rem: cint
|
||||
ldiv_t {.importc, header: "<stdlib.h>".} = object
|
||||
quot: clong
|
||||
rem: clong
|
||||
lldiv_t {.importc, header: "<stdlib.h>".} = object
|
||||
quot: clonglong
|
||||
rem: clonglong
|
||||
|
||||
when cint isnot clong:
|
||||
func divmod_c(x, y: cint): div_t {.importc: "div", header: "<stdlib.h>".}
|
||||
when clong isnot clonglong:
|
||||
func divmod_c(x, y: clonglong): lldiv_t {.importc: "lldiv", header: "<stdlib.h>".}
|
||||
func divmod_c(x, y: clong): ldiv_t {.importc: "ldiv", header: "<stdlib.h>".}
|
||||
func divmod*[T: SomeInteger](x, y: T): (T, T) {.inline.} =
|
||||
## Specialized instructions for computing both division and modulus.
|
||||
## Return structure is: (quotient, remainder)
|
||||
runnableExamples:
|
||||
doAssert divmod(5, 2) == (2, 1)
|
||||
doAssert divmod(5, -3) == (-1, 2)
|
||||
when T is cint | clong | clonglong:
|
||||
let res = divmod_c(x, y)
|
||||
result[0] = res.quot
|
||||
result[1] = res.rem
|
||||
else:
|
||||
result[0] = x div y
|
||||
result[1] = x mod y
|
||||
|
||||
func binom*(n, k: int): int =
|
||||
## Computes the [binomial coefficient](https://en.wikipedia.org/wiki/Binomial_coefficient).
|
||||
@@ -793,6 +823,14 @@ else: # JS
|
||||
doAssert -6.5 mod 2.5 == -1.5
|
||||
doAssert 6.5 mod -2.5 == 1.5
|
||||
doAssert -6.5 mod -2.5 == -1.5
|
||||
|
||||
func divmod*(num, denom: int): (int, int) =
|
||||
runnableExamples:
|
||||
doAssert divmod(5, 2) == (2, 1)
|
||||
doAssert divmod(5, -3) == (-1, 2)
|
||||
result[0] = num div denom
|
||||
result[1] = num mod denom
|
||||
|
||||
|
||||
func round*[T: float32|float64](x: T, places: int): T =
|
||||
## Decimal rounding on a binary floating point number.
|
||||
|
||||
@@ -186,7 +186,15 @@ template main() =
|
||||
when not defined(nimTmathCase2):
|
||||
doAssert classify(trunc(f_nan.float32)) == fcNan
|
||||
doAssert classify(trunc(0.0'f32)) == fcZero
|
||||
|
||||
|
||||
block: # divmod
|
||||
doAssert divmod(int.high, 1) == (int.high, 0)
|
||||
doAssert divmod(-1073741823, 17) == (-63161283, -12)
|
||||
when not defined(js):
|
||||
doAssert divmod(int32.high, 1.int32) == (int32.high, 0.int32)
|
||||
doAssert divmod(1073741823.int32, 5.int32) == (214748364.int32, 3.int32)
|
||||
doAssert divmod(4611686018427387903.int64, 5.int64) == (922337203685477580.int64, 3.int64)
|
||||
|
||||
block: # log
|
||||
doAssert log(4.0, 3.0) ==~ ln(4.0) / ln(3.0)
|
||||
doAssert log2(8.0'f64) == 3.0'f64
|
||||
|
||||
Reference in New Issue
Block a user