iterators_1.nim 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. when sizeof(int) <= 2:
  2. type IntLikeForCount = int|int8|int16|char|bool|uint8|enum
  3. else:
  4. type IntLikeForCount = int|int8|int16|int32|char|bool|uint8|uint16|enum
  5. iterator countdown*[T](a, b: T, step: Positive = 1): T {.inline.} =
  6. ## Counts from ordinal value `a` down to `b` (inclusive) with the given
  7. ## step count.
  8. ##
  9. ## `T` may be any ordinal type, `step` may only be positive.
  10. ##
  11. ## **Note**: This fails to count to `low(int)` if T = int for
  12. ## efficiency reasons.
  13. runnableExamples:
  14. import std/sugar
  15. let x = collect(newSeq):
  16. for i in countdown(7, 3):
  17. i
  18. assert x == @[7, 6, 5, 4, 3]
  19. let y = collect(newseq):
  20. for i in countdown(9, 2, 3):
  21. i
  22. assert y == @[9, 6, 3]
  23. when T is (uint|uint64):
  24. var res = a
  25. while res >= b:
  26. yield res
  27. if res == b: break
  28. dec(res, step)
  29. elif T is IntLikeForCount and T is Ordinal:
  30. var res = int(a)
  31. while res >= int(b):
  32. yield T(res)
  33. dec(res, step)
  34. else:
  35. var res = a
  36. while res >= b:
  37. yield res
  38. dec(res, step)
  39. iterator countup*[T](a, b: T, step: Positive = 1): T {.inline.} =
  40. ## Counts from ordinal value `a` to `b` (inclusive) with the given
  41. ## step count.
  42. ##
  43. ## `T` may be any ordinal type, `step` may only be positive.
  44. ##
  45. ## **Note**: This fails to count to `high(int)` if T = int for
  46. ## efficiency reasons.
  47. runnableExamples:
  48. import std/sugar
  49. let x = collect(newSeq):
  50. for i in countup(3, 7):
  51. i
  52. assert x == @[3, 4, 5, 6, 7]
  53. let y = collect(newseq):
  54. for i in countup(2, 9, 3):
  55. i
  56. assert y == @[2, 5, 8]
  57. mixin inc
  58. when T is IntLikeForCount and T is Ordinal:
  59. var res = int(a)
  60. while res <= int(b):
  61. yield T(res)
  62. inc(res, step)
  63. else:
  64. var res = a
  65. while res <= b:
  66. yield res
  67. inc(res, step)
  68. iterator `..`*[T](a, b: T): T {.inline.} =
  69. ## An alias for `countup(a, b, 1)`.
  70. ##
  71. ## See also:
  72. ## * [..<](#..<.i,T,T)
  73. runnableExamples:
  74. import std/sugar
  75. let x = collect(newSeq):
  76. for i in 3 .. 7:
  77. i
  78. assert x == @[3, 4, 5, 6, 7]
  79. mixin inc
  80. when T is IntLikeForCount and T is Ordinal:
  81. var res = int(a)
  82. while res <= int(b):
  83. yield T(res)
  84. inc(res)
  85. else:
  86. var res = a
  87. while res <= b:
  88. yield res
  89. inc(res)
  90. template dotdotImpl(t) {.dirty.} =
  91. iterator `..`*(a, b: t): t {.inline.} =
  92. ## A type specialized version of `..` for convenience so that
  93. ## mixing integer types works better.
  94. ##
  95. ## See also:
  96. ## * [..<](#..<.i,T,T)
  97. var res = a
  98. while res <= b:
  99. yield res
  100. inc(res)
  101. dotdotImpl(int64)
  102. dotdotImpl(int32)
  103. dotdotImpl(uint64)
  104. dotdotImpl(uint32)
  105. iterator `..<`*[T](a, b: T): T {.inline.} =
  106. mixin inc
  107. var i = a
  108. while i < b:
  109. yield i
  110. inc i
  111. template dotdotLessImpl(t) {.dirty.} =
  112. iterator `..<`*(a, b: t): t {.inline.} =
  113. ## A type specialized version of `..<` for convenience so that
  114. ## mixing integer types works better.
  115. var res = a
  116. while res < b:
  117. yield res
  118. inc(res)
  119. dotdotLessImpl(int64)
  120. dotdotLessImpl(int32)
  121. dotdotLessImpl(uint64)
  122. dotdotLessImpl(uint32)
  123. iterator `||`*[S, T](a: S, b: T, annotation: static string = "parallel for"): T {.
  124. inline, magic: "OmpParFor", sideEffect.} =
  125. ## OpenMP parallel loop iterator. Same as `..` but the loop may run in parallel.
  126. ##
  127. ## `annotation` is an additional annotation for the code generator to use.
  128. ## The default annotation is `parallel for`.
  129. ## Please refer to the `OpenMP Syntax Reference
  130. ## <https://www.openmp.org/wp-content/uploads/OpenMP-4.5-1115-CPP-web.pdf>`_
  131. ## for further information.
  132. ##
  133. ## Note that the compiler maps that to
  134. ## the `#pragma omp parallel for` construct of `OpenMP`:idx: and as
  135. ## such isn't aware of the parallelism in your code! Be careful! Later
  136. ## versions of `||` will get proper support by Nim's code generator
  137. ## and GC.
  138. discard
  139. iterator `||`*[S, T](a: S, b: T, step: Positive, annotation: static string = "parallel for"): T {.
  140. inline, magic: "OmpParFor", sideEffect.} =
  141. ## OpenMP parallel loop iterator with stepping.
  142. ## Same as `countup` but the loop may run in parallel.
  143. ##
  144. ## `annotation` is an additional annotation for the code generator to use.
  145. ## The default annotation is `parallel for`.
  146. ## Please refer to the `OpenMP Syntax Reference
  147. ## <https://www.openmp.org/wp-content/uploads/OpenMP-4.5-1115-CPP-web.pdf>`_
  148. ## for further information.
  149. ##
  150. ## Note that the compiler maps that to
  151. ## the `#pragma omp parallel for` construct of `OpenMP`:idx: and as
  152. ## such isn't aware of the parallelism in your code! Be careful! Later
  153. ## versions of `||` will get proper support by Nim's code generator
  154. ## and GC.
  155. discard