iterators_1.nim 4.9 KB

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