basedpl 0.1.71__tar.gz → 0.1.72__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (476) hide show
  1. {basedpl-0.1.71 → basedpl-0.1.72}/.github/workflows/test.yml +11 -4
  2. {basedpl-0.1.71 → basedpl-0.1.72}/Cargo.lock +13 -13
  3. {basedpl-0.1.71 → basedpl-0.1.72}/Cargo.toml +1 -1
  4. {basedpl-0.1.71 → basedpl-0.1.72}/DEV.md +1 -1
  5. {basedpl-0.1.71 → basedpl-0.1.72}/PKG-INFO +1 -1
  6. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/downstile.qmd +1 -3
  7. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/upstile.qmd +1 -3
  8. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/numbers.qmd +2 -3
  9. {basedpl-0.1.71 → basedpl-0.1.72}/py/src/lib.rs +1 -1
  10. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/bpltests.py +3 -1
  11. {basedpl-0.1.71 → basedpl-0.1.72}/src/batch.rs +2 -0
  12. {basedpl-0.1.71 → basedpl-0.1.72}/src/derivative.rs +27 -43
  13. {basedpl-0.1.71 → basedpl-0.1.72}/src/eval/operators.rs +10 -3
  14. {basedpl-0.1.71 → basedpl-0.1.72}/src/fusion.rs +1 -1
  15. {basedpl-0.1.71 → basedpl-0.1.72}/src/pervasive.rs +50 -47
  16. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/core.bpl +6 -3
  17. {basedpl-0.1.71 → basedpl-0.1.72}/tests/speed.txt +44 -42
  18. {basedpl-0.1.71 → basedpl-0.1.72}/tests/wasm.mjs +8 -0
  19. {basedpl-0.1.71 → basedpl-0.1.72}/.cargo/config.toml +0 -0
  20. {basedpl-0.1.71 → basedpl-0.1.72}/.gitattributes +0 -0
  21. {basedpl-0.1.71 → basedpl-0.1.72}/.github/workflows/ci.yml +0 -0
  22. {basedpl-0.1.71 → basedpl-0.1.72}/.github/workflows/docs.yml +0 -0
  23. {basedpl-0.1.71 → basedpl-0.1.72}/.github/workflows/speed.yml +0 -0
  24. {basedpl-0.1.71 → basedpl-0.1.72}/.gitignore +0 -0
  25. {basedpl-0.1.71 → basedpl-0.1.72}/CONTRIBUTING.md +0 -0
  26. {basedpl-0.1.71 → basedpl-0.1.72}/LICENSE +0 -0
  27. {basedpl-0.1.71 → basedpl-0.1.72}/README.md +0 -0
  28. {basedpl-0.1.71 → basedpl-0.1.72}/_config.yml +0 -0
  29. {basedpl-0.1.71 → basedpl-0.1.72}/_layouts/default.html +0 -0
  30. {basedpl-0.1.71 → basedpl-0.1.72}/build.rs +0 -0
  31. {basedpl-0.1.71 → basedpl-0.1.72}/editors/jetbrains/BPL.tmbundle/Syntaxes/bpl.tmLanguage.json +0 -0
  32. {basedpl-0.1.71 → basedpl-0.1.72}/editors/jetbrains/BPL.tmbundle/Syntaxes/hpl.tmLanguage.json +0 -0
  33. {basedpl-0.1.71 → basedpl-0.1.72}/editors/jetbrains/BPL.tmbundle/info.plist +0 -0
  34. {basedpl-0.1.71 → basedpl-0.1.72}/editors/jetbrains/BPL.xml +0 -0
  35. {basedpl-0.1.71 → basedpl-0.1.72}/editors/jetbrains/README.md +0 -0
  36. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-de.bundle/Contents/Info.plist +0 -0
  37. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-de.bundle/Contents/Resources/BasedPL-de.icns +0 -0
  38. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-de.bundle/Contents/Resources/BasedPL-de.keylayout +0 -0
  39. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-de.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  40. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-de.bundle/Contents/version.plist +0 -0
  41. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-de.txt +0 -0
  42. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-es.bundle/Contents/Info.plist +0 -0
  43. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-es.bundle/Contents/Resources/BasedPL-es.icns +0 -0
  44. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-es.bundle/Contents/Resources/BasedPL-es.keylayout +0 -0
  45. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-es.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  46. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-es.bundle/Contents/version.plist +0 -0
  47. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-es.txt +0 -0
  48. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-fr.bundle/Contents/Info.plist +0 -0
  49. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-fr.bundle/Contents/Resources/BasedPL-fr.icns +0 -0
  50. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-fr.bundle/Contents/Resources/BasedPL-fr.keylayout +0 -0
  51. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-fr.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  52. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-fr.bundle/Contents/version.plist +0 -0
  53. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-fr.txt +0 -0
  54. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-uk.bundle/Contents/Info.plist +0 -0
  55. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-uk.bundle/Contents/Resources/BasedPL-uk.icns +0 -0
  56. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-uk.bundle/Contents/Resources/BasedPL-uk.keylayout +0 -0
  57. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-uk.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  58. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-uk.bundle/Contents/version.plist +0 -0
  59. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-uk.txt +0 -0
  60. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-us.bundle/Contents/Info.plist +0 -0
  61. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-us.bundle/Contents/Resources/BasedPL-us.icns +0 -0
  62. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-us.bundle/Contents/Resources/BasedPL-us.keylayout +0 -0
  63. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-us.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  64. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-us.bundle/Contents/version.plist +0 -0
  65. {basedpl-0.1.71 → basedpl-0.1.72}/editors/macos/BasedPL-us.txt +0 -0
  66. {basedpl-0.1.71 → basedpl-0.1.72}/editors/vim/ftdetect/bpl.vim +0 -0
  67. {basedpl-0.1.71 → basedpl-0.1.72}/editors/vim/syntax/bpl.vim +0 -0
  68. {basedpl-0.1.71 → basedpl-0.1.72}/editors/windows/README.md +0 -0
  69. {basedpl-0.1.71 → basedpl-0.1.72}/editors/windows/build.ps1 +0 -0
  70. {basedpl-0.1.71 → basedpl-0.1.72}/editors/windows/install.ps1 +0 -0
  71. {basedpl-0.1.71 → basedpl-0.1.72}/editors/windows/keyboard.c +0 -0
  72. {basedpl-0.1.71 → basedpl-0.1.72}/editors/windows/keyboard.def +0 -0
  73. {basedpl-0.1.71 → basedpl-0.1.72}/editors/windows/keyboard.rc +0 -0
  74. {basedpl-0.1.71 → basedpl-0.1.72}/editors/windows/layout.h +0 -0
  75. {basedpl-0.1.71 → basedpl-0.1.72}/index_files/figure-commonmark/cell-17-output-1.svg +0 -0
  76. {basedpl-0.1.71 → basedpl-0.1.72}/index_files/figure-commonmark/cell-18-output-1.svg +0 -0
  77. {basedpl-0.1.71 → basedpl-0.1.72}/index_files/figure-html/cell-17-output-1.svg +0 -0
  78. {basedpl-0.1.71 → basedpl-0.1.72}/index_files/figure-html/cell-18-output-1.svg +0 -0
  79. {basedpl-0.1.71 → basedpl-0.1.72}/lib/LICENSE-april +0 -0
  80. {basedpl-0.1.71 → basedpl-0.1.72}/lib/README.md +0 -0
  81. {basedpl-0.1.71 → basedpl-0.1.72}/lib/array.bpl +0 -0
  82. {basedpl-0.1.71 → basedpl-0.1.72}/lib/dyalog.bpl +0 -0
  83. {basedpl-0.1.71 → basedpl-0.1.72}/lib/graph.bpl +0 -0
  84. {basedpl-0.1.71 → basedpl-0.1.72}/lib/numeric.bpl +0 -0
  85. {basedpl-0.1.71 → basedpl-0.1.72}/lib/power.bpl +0 -0
  86. {basedpl-0.1.71 → basedpl-0.1.72}/lib/regex.bpl +0 -0
  87. {basedpl-0.1.71 → basedpl-0.1.72}/lib/string.bpl +0 -0
  88. {basedpl-0.1.71 → basedpl-0.1.72}/lib/tree.bpl +0 -0
  89. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/.gitignore +0 -0
  90. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/_quarto.yml +0 -0
  91. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/arrays.ipynb +0 -0
  92. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/assignment.ipynb +0 -0
  93. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/bpl.xml +0 -0
  94. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/bqn.xml +0 -0
  95. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/bracket-types.ipynb +0 -0
  96. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/cli.qmd +0 -0
  97. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/comparison.qmd +0 -0
  98. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/data.ipynb +0 -0
  99. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/dfns.ipynb +0 -0
  100. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/distributions.ipynb +0 -0
  101. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/driver.js +0 -0
  102. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/dyalog.ipynb +0 -0
  103. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/dyalog.xml +0 -0
  104. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/evaluation.qmd +0 -0
  105. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/fonts/LICENSE-SAX2 +0 -0
  106. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/fonts/README.md +0 -0
  107. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/fonts/SAX2B.ttf +0 -0
  108. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/fonts/SAX2B.woff2 +0 -0
  109. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/fonts.css +0 -0
  110. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/gallery/attractor.bpl +0 -0
  111. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/gallery/boids.bpl +0 -0
  112. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/gallery/dragon.bpl +0 -0
  113. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/gallery/flow.bpl +0 -0
  114. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/gallery/mandelbrot.bpl +0 -0
  115. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/gallery/mandelbrot32.bpl +0 -0
  116. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/gallery/orbits.bpl +0 -0
  117. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/gallery/phyllotaxis.bpl +0 -0
  118. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/gallery/prefs.bpl +0 -0
  119. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/gallery/reaction.bpl +0 -0
  120. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/gallery.qmd +0 -0
  121. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/getting-started.ipynb +0 -0
  122. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/_metadata.yml +0 -0
  123. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/alpha-underbar.qmd +0 -0
  124. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/alpha.qmd +0 -0
  125. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/at.qmd +0 -0
  126. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/backslash-bar.qmd +0 -0
  127. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/backslash.qmd +0 -0
  128. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/braces.qmd +0 -0
  129. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/brackets.qmd +0 -0
  130. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/bullet.qmd +0 -0
  131. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/circle-backslash.qmd +0 -0
  132. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/circle-bar.qmd +0 -0
  133. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/circle-diaeresis.qmd +0 -0
  134. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/circle-divide.qmd +0 -0
  135. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/circle-slash.qmd +0 -0
  136. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/circle-star.qmd +0 -0
  137. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/circle-stile.qmd +0 -0
  138. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/circle-times.qmd +0 -0
  139. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/circle.qmd +0 -0
  140. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/colon.qmd +0 -0
  141. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/comma-bar.qmd +0 -0
  142. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/comma.qmd +0 -0
  143. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/del-diaeresis.qmd +0 -0
  144. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/del-stile.qmd +0 -0
  145. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/del.qmd +0 -0
  146. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/delta-stile.qmd +0 -0
  147. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/diaeresis.qmd +0 -0
  148. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/diamond-underbar.qmd +0 -0
  149. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/diamond.qmd +0 -0
  150. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/domino.qmd +0 -0
  151. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/dot.qmd +0 -0
  152. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/down-arrow.qmd +0 -0
  153. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/down-shoe.qmd +0 -0
  154. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/down-tack.qmd +0 -0
  155. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/epsilon-underbar.qmd +0 -0
  156. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/epsilon.qmd +0 -0
  157. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/equal-underbar-slash.qmd +0 -0
  158. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/equal-underbar.qmd +0 -0
  159. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/equals.qmd +0 -0
  160. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/error-guard.qmd +0 -0
  161. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/exclamation.qmd +0 -0
  162. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/greater-than-or-equal.qmd +0 -0
  163. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/greater-than.qmd +0 -0
  164. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/hash.qmd +0 -0
  165. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/hydrant.qmd +0 -0
  166. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/infinity.qmd +0 -0
  167. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/inverted-question.qmd +0 -0
  168. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/iota-underbar.qmd +0 -0
  169. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/iota.qmd +0 -0
  170. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/jot-diaeresis.qmd +0 -0
  171. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/jot.qmd +0 -0
  172. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/lamp.qmd +0 -0
  173. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/left-arrow.qmd +0 -0
  174. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/left-shoe-underbar.qmd +0 -0
  175. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/left-shoe.qmd +0 -0
  176. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/left-tack.qmd +0 -0
  177. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/left-tail-arrow.qmd +0 -0
  178. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/less-than-or-equal.qmd +0 -0
  179. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/less-than.qmd +0 -0
  180. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/minus.qmd +0 -0
  181. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/not-equals.qmd +0 -0
  182. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/obelus.qmd +0 -0
  183. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/omega-underbar.qmd +0 -0
  184. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/omega.qmd +0 -0
  185. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/overbar.qmd +0 -0
  186. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/parentheses.qmd +0 -0
  187. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/partial.qmd +0 -0
  188. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/pi.qmd +0 -0
  189. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/plus.qmd +0 -0
  190. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/quad-colon.qmd +0 -0
  191. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/quad-diamond.qmd +0 -0
  192. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/quad-equal.qmd +0 -0
  193. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/quad-jot.qmd +0 -0
  194. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/quad.qmd +0 -0
  195. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/question.qmd +0 -0
  196. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/quote.qmd +0 -0
  197. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/radical.qmd +0 -0
  198. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/rho.qmd +0 -0
  199. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/right-arrow-from-bar.qmd +0 -0
  200. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/right-left-arrows.qmd +0 -0
  201. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/right-shoe.qmd +0 -0
  202. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/right-tack.qmd +0 -0
  203. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/right-tail-arrow.qmd +0 -0
  204. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/slash-bar.qmd +0 -0
  205. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/slash.qmd +0 -0
  206. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/squad.qmd +0 -0
  207. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/star-diaeresis.qmd +0 -0
  208. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/star.qmd +0 -0
  209. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/stile-tilde.qmd +0 -0
  210. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/stile.qmd +0 -0
  211. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/superscript-b.qmd +0 -0
  212. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/thorn.qmd +0 -0
  213. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/tilde-diaeresis.qmd +0 -0
  214. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/tilde.qmd +0 -0
  215. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/times.qmd +0 -0
  216. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/up-arrow.qmd +0 -0
  217. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/up-down-arrow.qmd +0 -0
  218. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/up-shoe.qmd +0 -0
  219. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/up-tack.qmd +0 -0
  220. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/vee-bar.qmd +0 -0
  221. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/vee.qmd +0 -0
  222. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/wedge-bar.qmd +0 -0
  223. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/wedge.qmd +0 -0
  224. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs/zilde.qmd +0 -0
  225. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs-study.qmd +0 -0
  226. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/glyphs.qmd +0 -0
  227. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/hanzi-notation-zh.ipynb +0 -0
  228. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/hanzi-notation.ipynb +0 -0
  229. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/hpl.xml +0 -0
  230. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/index.ipynb +0 -0
  231. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/indexing.ipynb +0 -0
  232. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/introspection.ipynb +0 -0
  233. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/keyboard.qmd +0 -0
  234. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/keyed.ipynb +0 -0
  235. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/llms.txt +0 -0
  236. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/magics.ipynb +0 -0
  237. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/modules.qmd +0 -0
  238. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/nbdev.yml +0 -0
  239. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/notebooks.ipynb +0 -0
  240. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/overview.ipynb +0 -0
  241. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/papers/aplwiki-arrays.md +0 -0
  242. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/papers/brickman-depth-1-scalars.md +0 -0
  243. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/papers/mercer-based-system.md +0 -0
  244. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/playground/bpl.js +0 -0
  245. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/playground/gallery.js +0 -0
  246. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/playground/hpl.tmLanguage.json +0 -0
  247. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/playground/monaco-worker.js +0 -0
  248. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/playground/page.js +0 -0
  249. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/playground/worker.js +0 -0
  250. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/playground.qmd +0 -0
  251. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/plot.ipynb +0 -0
  252. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/principles.ipynb +0 -0
  253. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/processes.qmd +0 -0
  254. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/puppy.jpg +0 -0
  255. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/python.ipynb +0 -0
  256. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/regex.ipynb +0 -0
  257. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/repl.qmd +0 -0
  258. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/scripts.ipynb +0 -0
  259. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/sidebar.yml +0 -0
  260. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/strings.ipynb +0 -0
  261. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/study/01_basics.ipynb +0 -0
  262. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/study/02_functions.ipynb +0 -0
  263. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/study/03_operators.ipynb +0 -0
  264. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/study/04_nested-arrays.ipynb +0 -0
  265. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/study/05_searching-indexing.ipynb +0 -0
  266. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/study/06_rearranging-arrays.ipynb +0 -0
  267. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/study/07_numerical-tools.ipynb +0 -0
  268. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/style.qmd +0 -0
  269. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/styles.css +0 -0
  270. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/syntax.qmd +0 -0
  271. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/_metadata.yml +0 -0
  272. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/c.qmd +0 -0
  273. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/canvas.qmd +0 -0
  274. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/constants.qmd +0 -0
  275. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/copy.qmd +0 -0
  276. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/csv.qmd +0 -0
  277. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/date.qmd +0 -0
  278. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/decompose.qmd +0 -0
  279. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/deflate.qmd +0 -0
  280. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/delay.qmd +0 -0
  281. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/detach.qmd +0 -0
  282. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/distribution.qmd +0 -0
  283. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/edge.qmd +0 -0
  284. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/element.qmd +0 -0
  285. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/ex.qmd +0 -0
  286. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/explain.qmd +0 -0
  287. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/fetch.qmd +0 -0
  288. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/float.qmd +0 -0
  289. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/hash.qmd +0 -0
  290. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/host.qmd +0 -0
  291. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/image.qmd +0 -0
  292. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/index.qmd +0 -0
  293. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/js.qmd +0 -0
  294. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/json.qmd +0 -0
  295. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/literal.qmd +0 -0
  296. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/load.qmd +0 -0
  297. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/memory.qmd +0 -0
  298. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/metadata.qmd +0 -0
  299. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/mime.qmd +0 -0
  300. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/mkdir.qmd +0 -0
  301. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/nc.qmd +0 -0
  302. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/nget.qmd +0 -0
  303. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/nl.qmd +0 -0
  304. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/normalize.qmd +0 -0
  305. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/nput.qmd +0 -0
  306. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/path.qmd +0 -0
  307. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/plot.qmd +0 -0
  308. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/prefs.qmd +0 -0
  309. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/r.qmd +0 -0
  310. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/rand.qmd +0 -0
  311. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/readdir.qmd +0 -0
  312. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/remove.qmd +0 -0
  313. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/rename.qmd +0 -0
  314. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/signal.qmd +0 -0
  315. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/src.qmd +0 -0
  316. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/storage.qmd +0 -0
  317. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/svg.qmd +0 -0
  318. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/time.qmd +0 -0
  319. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/ucs.qmd +0 -0
  320. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/uuid.qmd +0 -0
  321. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/vfi.qmd +0 -0
  322. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system/xml.qmd +0 -0
  323. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/system-functions.qmd +0 -0
  324. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/terms.qmd +0 -0
  325. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/web.ipynb +0 -0
  326. {basedpl-0.1.71 → basedpl-0.1.72}/nbs/xml.ipynb +0 -0
  327. {basedpl-0.1.71 → basedpl-0.1.72}/package-lock.json +0 -0
  328. {basedpl-0.1.71 → basedpl-0.1.72}/package.json +0 -0
  329. {basedpl-0.1.71 → basedpl-0.1.72}/provenance/README.md +0 -0
  330. {basedpl-0.1.71 → basedpl-0.1.72}/provenance/aplcart.jsonl +0 -0
  331. {basedpl-0.1.71 → basedpl-0.1.72}/provenance/april.jsonl +0 -0
  332. {basedpl-0.1.71 → basedpl-0.1.72}/provenance/bqn.jsonl +0 -0
  333. {basedpl-0.1.71 → basedpl-0.1.72}/provenance/core.jsonl +0 -0
  334. {basedpl-0.1.71 → basedpl-0.1.72}/provenance/dyalog.jsonl +0 -0
  335. {basedpl-0.1.71 → basedpl-0.1.72}/provenance/ngn.jsonl +0 -0
  336. {basedpl-0.1.71 → basedpl-0.1.72}/py/Cargo.toml +0 -0
  337. {basedpl-0.1.71 → basedpl-0.1.72}/py/build.rs +0 -0
  338. {basedpl-0.1.71 → basedpl-0.1.72}/pyproject.toml +0 -0
  339. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/__init__.py +0 -0
  340. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/_modidx.py +0 -0
  341. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/bpl.tmLanguage.json +0 -0
  342. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/dyalog.py +0 -0
  343. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/editors.py +0 -0
  344. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/font.py +0 -0
  345. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/fonts.css +0 -0
  346. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/functions.py +0 -0
  347. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/hpl.tmLanguage.json +0 -0
  348. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/input.js +0 -0
  349. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/ipython.py +0 -0
  350. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/keyboards.json +0 -0
  351. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/keyboards.py +0 -0
  352. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/layout.json +0 -0
  353. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/lb.js +0 -0
  354. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/notebook_runner.py +0 -0
  355. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/notebooks.py +0 -0
  356. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/printing.py +0 -0
  357. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/reference.py +0 -0
  358. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/syntax.py +0 -0
  359. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/windows_keyboard.py +0 -0
  360. {basedpl-0.1.71 → basedpl-0.1.72}/python/basedpl/worker.py +0 -0
  361. {basedpl-0.1.71 → basedpl-0.1.72}/rustfmt.toml +0 -0
  362. {basedpl-0.1.71 → basedpl-0.1.72}/scripts/install-macos.sh +0 -0
  363. {basedpl-0.1.71 → basedpl-0.1.72}/scripts/prep.py +0 -0
  364. {basedpl-0.1.71 → basedpl-0.1.72}/src/agreement.rs +0 -0
  365. {basedpl-0.1.71 → basedpl-0.1.72}/src/array/storage.rs +0 -0
  366. {basedpl-0.1.71 → basedpl-0.1.72}/src/array/text.rs +0 -0
  367. {basedpl-0.1.71 → basedpl-0.1.72}/src/array.rs +0 -0
  368. {basedpl-0.1.71 → basedpl-0.1.72}/src/canvas.js +0 -0
  369. {basedpl-0.1.71 → basedpl-0.1.72}/src/canvas.rs +0 -0
  370. {basedpl-0.1.71 → basedpl-0.1.72}/src/csv.rs +0 -0
  371. {basedpl-0.1.71 → basedpl-0.1.72}/src/data.rs +0 -0
  372. {basedpl-0.1.71 → basedpl-0.1.72}/src/date.rs +0 -0
  373. {basedpl-0.1.71 → basedpl-0.1.72}/src/display.rs +0 -0
  374. {basedpl-0.1.71 → basedpl-0.1.72}/src/distribution.rs +0 -0
  375. {basedpl-0.1.71 → basedpl-0.1.72}/src/element.rs +0 -0
  376. {basedpl-0.1.71 → basedpl-0.1.72}/src/error.rs +0 -0
  377. {basedpl-0.1.71 → basedpl-0.1.72}/src/eval/assign.rs +0 -0
  378. {basedpl-0.1.71 → basedpl-0.1.72}/src/eval/binder.rs +0 -0
  379. {basedpl-0.1.71 → basedpl-0.1.72}/src/eval/bindings.rs +0 -0
  380. {basedpl-0.1.71 → basedpl-0.1.72}/src/eval/dissect.rs +0 -0
  381. {basedpl-0.1.71 → basedpl-0.1.72}/src/eval/idioms.rs +0 -0
  382. {basedpl-0.1.71 → basedpl-0.1.72}/src/eval/session.rs +0 -0
  383. {basedpl-0.1.71 → basedpl-0.1.72}/src/eval/tree.rs +0 -0
  384. {basedpl-0.1.71 → basedpl-0.1.72}/src/eval.rs +0 -0
  385. {basedpl-0.1.71 → basedpl-0.1.72}/src/execution.rs +0 -0
  386. {basedpl-0.1.71 → basedpl-0.1.72}/src/explain.rs +0 -0
  387. {basedpl-0.1.71 → basedpl-0.1.72}/src/files.rs +0 -0
  388. {basedpl-0.1.71 → basedpl-0.1.72}/src/fusion/blocks.rs +0 -0
  389. {basedpl-0.1.71 → basedpl-0.1.72}/src/host.rs +0 -0
  390. {basedpl-0.1.71 → basedpl-0.1.72}/src/host_web.rs +0 -0
  391. {basedpl-0.1.71 → basedpl-0.1.72}/src/image/codecs.rs +0 -0
  392. {basedpl-0.1.71 → basedpl-0.1.72}/src/image/imageio.rs +0 -0
  393. {basedpl-0.1.71 → basedpl-0.1.72}/src/image.rs +0 -0
  394. {basedpl-0.1.71 → basedpl-0.1.72}/src/inspection.rs +0 -0
  395. {basedpl-0.1.71 → basedpl-0.1.72}/src/js.rs +0 -0
  396. {basedpl-0.1.71 → basedpl-0.1.72}/src/json.rs +0 -0
  397. {basedpl-0.1.71 → basedpl-0.1.72}/src/keyed.rs +0 -0
  398. {basedpl-0.1.71 → basedpl-0.1.72}/src/lib.rs +0 -0
  399. {basedpl-0.1.71 → basedpl-0.1.72}/src/linear.rs +0 -0
  400. {basedpl-0.1.71 → basedpl-0.1.72}/src/name.rs +0 -0
  401. {basedpl-0.1.71 → basedpl-0.1.72}/src/number.rs +0 -0
  402. {basedpl-0.1.71 → basedpl-0.1.72}/src/number_theory.rs +0 -0
  403. {basedpl-0.1.71 → basedpl-0.1.72}/src/optimize.rs +0 -0
  404. {basedpl-0.1.71 → basedpl-0.1.72}/src/plot.rs +0 -0
  405. {basedpl-0.1.71 → basedpl-0.1.72}/src/polynomial.rs +0 -0
  406. {basedpl-0.1.71 → basedpl-0.1.72}/src/primitive/indexing.rs +0 -0
  407. {basedpl-0.1.71 → basedpl-0.1.72}/src/primitive/numeric.rs +0 -0
  408. {basedpl-0.1.71 → basedpl-0.1.72}/src/primitive/search.rs +0 -0
  409. {basedpl-0.1.71 → basedpl-0.1.72}/src/primitive/structural.rs +0 -0
  410. {basedpl-0.1.71 → basedpl-0.1.72}/src/primitive.rs +0 -0
  411. {basedpl-0.1.71 → basedpl-0.1.72}/src/protocol.rs +0 -0
  412. {basedpl-0.1.71 → basedpl-0.1.72}/src/reference.rs +0 -0
  413. {basedpl-0.1.71 → basedpl-0.1.72}/src/regex.rs +0 -0
  414. {basedpl-0.1.71 → basedpl-0.1.72}/src/search.rs +0 -0
  415. {basedpl-0.1.71 → basedpl-0.1.72}/src/selection.rs +0 -0
  416. {basedpl-0.1.71 → basedpl-0.1.72}/src/settings.rs +0 -0
  417. {basedpl-0.1.71 → basedpl-0.1.72}/src/symbols.rs +0 -0
  418. {basedpl-0.1.71 → basedpl-0.1.72}/src/syntax.rs +0 -0
  419. {basedpl-0.1.71 → basedpl-0.1.72}/src/system.rs +0 -0
  420. {basedpl-0.1.71 → basedpl-0.1.72}/src/timing.rs +0 -0
  421. {basedpl-0.1.71 → basedpl-0.1.72}/src/transform.rs +0 -0
  422. {basedpl-0.1.71 → basedpl-0.1.72}/src/xml.rs +0 -0
  423. {basedpl-0.1.71 → basedpl-0.1.72}/tests/common/mod.rs +0 -0
  424. {basedpl-0.1.71 → basedpl-0.1.72}/tests/conftest.py +0 -0
  425. {basedpl-0.1.71 → basedpl-0.1.72}/tests/core.rs +0 -0
  426. {basedpl-0.1.71 → basedpl-0.1.72}/tests/derivatives.rs +0 -0
  427. {basedpl-0.1.71 → basedpl-0.1.72}/tests/explain.rs +0 -0
  428. {basedpl-0.1.71 → basedpl-0.1.72}/tests/highlighting.mjs +0 -0
  429. {basedpl-0.1.71 → basedpl-0.1.72}/tests/input.mjs +0 -0
  430. {basedpl-0.1.71 → basedpl-0.1.72}/tests/instructions.txt +0 -0
  431. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/LICENSE-aplcart +0 -0
  432. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/LICENSE-april +0 -0
  433. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/LICENSE-bqn +0 -0
  434. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/LICENSE-bqncrate +0 -0
  435. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/LICENSE-dyalog +0 -0
  436. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/LICENSE-ngn +0 -0
  437. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/README.md +0 -0
  438. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/aplcart.bpl +0 -0
  439. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/april.bpl +0 -0
  440. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/bqn.bpl +0 -0
  441. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/distributions.bpl +0 -0
  442. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/dyalog.bpl +0 -0
  443. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/graphics.bpl +0 -0
  444. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/lib.bpl +0 -0
  445. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/ngn.bpl +0 -0
  446. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/regex.bpl +0 -0
  447. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/static-int32.bpl +0 -0
  448. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/static.bpl +0 -0
  449. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/support/april.bpl +0 -0
  450. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/support/avl.bpl +0 -0
  451. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/support/redblack.bpl +0 -0
  452. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/support/sbst.bpl +0 -0
  453. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference/support/splay.bpl +0 -0
  454. {basedpl-0.1.71 → basedpl-0.1.72}/tests/reference.rs +0 -0
  455. {basedpl-0.1.71 → basedpl-0.1.72}/tests/scaling.rs +0 -0
  456. {basedpl-0.1.71 → basedpl-0.1.72}/tests/settings.rs +0 -0
  457. {basedpl-0.1.71 → basedpl-0.1.72}/tests/speed.rs +0 -0
  458. {basedpl-0.1.71 → basedpl-0.1.72}/tests/test_api.py +0 -0
  459. {basedpl-0.1.71 → basedpl-0.1.72}/tests/test_basic.py +0 -0
  460. {basedpl-0.1.71 → basedpl-0.1.72}/tests/test_bpltests.py +0 -0
  461. {basedpl-0.1.71 → basedpl-0.1.72}/tests/test_glyphs.py +0 -0
  462. {basedpl-0.1.71 → basedpl-0.1.72}/tests/test_graphics.py +0 -0
  463. {basedpl-0.1.71 → basedpl-0.1.72}/tests/test_instructions.py +0 -0
  464. {basedpl-0.1.71 → basedpl-0.1.72}/tests/test_ipython.py +0 -0
  465. {basedpl-0.1.71 → basedpl-0.1.72}/tests/test_kernel.py +0 -0
  466. {basedpl-0.1.71 → basedpl-0.1.72}/tests/test_keylayout.py +0 -0
  467. {basedpl-0.1.71 → basedpl-0.1.72}/tests/test_notebooks.py +0 -0
  468. {basedpl-0.1.71 → basedpl-0.1.72}/tests/test_reference.py +0 -0
  469. {basedpl-0.1.71 → basedpl-0.1.72}/tests/test_repl.py +0 -0
  470. {basedpl-0.1.71 → basedpl-0.1.72}/tests/test_windows_keyboard.py +0 -0
  471. {basedpl-0.1.71 → basedpl-0.1.72}/tests/test_worker.py +0 -0
  472. {basedpl-0.1.71 → basedpl-0.1.72}/tests/units.rs +0 -0
  473. {basedpl-0.1.71 → basedpl-0.1.72}/tests/wasm-pkg.mjs +0 -0
  474. {basedpl-0.1.71 → basedpl-0.1.72}/tests/wasm-speed.mjs +0 -0
  475. {basedpl-0.1.71 → basedpl-0.1.72}/tests/windows_keyboard.c +0 -0
  476. {basedpl-0.1.71 → basedpl-0.1.72}/wheel/data/share/jupyter/kernels/bpl/kernel.json +0 -0
@@ -8,31 +8,37 @@ on:
8
8
  permissions:
9
9
  contents: read
10
10
 
11
+ # In each job, every test step after the first runs even when an earlier step fails, to report every test's result in one run.
11
12
  jobs:
12
13
  test:
13
14
  runs-on: ubicloud-standard-4
14
15
  steps:
15
16
  - uses: actions/checkout@v7
16
- - run: node tests/input.mjs
17
17
  # `tests/highlighting.mjs` reads the TextMate grammar through `shiki`, which `package.json` pins.
18
18
  - run: npm ci
19
- - run: node tests/highlighting.mjs
20
19
  - uses: dtolnay/rust-toolchain@stable
21
20
  # The repository has no `Cargo.lock`. Creating one first makes rust-cache's key change when a dependency publishes a new version.
22
21
  - run: cargo generate-lockfile
23
22
  - uses: Swatinem/rust-cache@v2
24
23
  with:
25
24
  shared-key: native
26
- # With `BASEDPL_COSTS`, the speed tests here and in the `wasm` job log every case's cost, which `basedpl.bpltests.logged_costs` reads.
27
- - run: BASEDPL_COSTS=1 cargo test
28
25
  - uses: actions/setup-python@v7
29
26
  with:
30
27
  python-version: '3.12'
31
28
  - run: pip install -e '.[dev]'
32
29
  - run: cargo develop
30
+ - run: node tests/input.mjs
31
+ - run: node tests/highlighting.mjs
32
+ if: ${{ !cancelled() }}
33
+ # With `BASEDPL_COSTS`, the speed tests here and in the `wasm` job log every case's cost, which `basedpl.bpltests.logged_costs` reads.
34
+ - run: BASEDPL_COSTS=1 cargo test
35
+ if: ${{ !cancelled() }}
33
36
  - run: pytest -q
37
+ if: ${{ !cancelled() }}
34
38
  - run: bpl-nb
39
+ if: ${{ !cancelled() }}
35
40
  - run: nbdev-test
41
+ if: ${{ !cancelled() }}
36
42
 
37
43
  wasm:
38
44
  runs-on: ubicloud-standard-4
@@ -49,3 +55,4 @@ jobs:
49
55
  - run: cargo wasm --strip
50
56
  - run: node --test tests/wasm.mjs
51
57
  - run: BASEDPL_COSTS=1 node --no-liftoff --test tests/wasm-speed.mjs
58
+ if: ${{ !cancelled() }}
@@ -93,7 +93,7 @@ checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5"
93
93
 
94
94
  [[package]]
95
95
  name = "basedpl"
96
- version = "0.1.71"
96
+ version = "0.1.72"
97
97
  dependencies = [
98
98
  "base64 0.23.1",
99
99
  "bytemuck",
@@ -137,7 +137,7 @@ dependencies = [
137
137
 
138
138
  [[package]]
139
139
  name = "basedpl-cli"
140
- version = "0.1.71"
140
+ version = "0.1.72"
141
141
  dependencies = [
142
142
  "async-trait",
143
143
  "basedpl",
@@ -150,7 +150,7 @@ dependencies = [
150
150
 
151
151
  [[package]]
152
152
  name = "basedpl-py"
153
- version = "0.1.71"
153
+ version = "0.1.72"
154
154
  dependencies = [
155
155
  "basedpl",
156
156
  "num-bigint",
@@ -165,7 +165,7 @@ dependencies = [
165
165
 
166
166
  [[package]]
167
167
  name = "basedpl-wasm"
168
- version = "0.1.71"
168
+ version = "0.1.72"
169
169
  dependencies = [
170
170
  "basedpl",
171
171
  "js-sys",
@@ -256,9 +256,9 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
256
256
 
257
257
  [[package]]
258
258
  name = "cc"
259
- version = "1.9.0"
259
+ version = "1.10.0"
260
260
  source = "registry+https://github.com/rust-lang/crates.io-index"
261
- checksum = "877bf67ac8e52449eb2f9e98a344ea163beb70dd1f9eebe3cc5357dcfeaee4df"
261
+ checksum = "86e055fa6e3e40ad6187ba25b6855eeb635d5271f8e0f0e1e9a5826b8d75bea0"
262
262
  dependencies = [
263
263
  "find-msvc-tools",
264
264
  "shlex",
@@ -303,9 +303,9 @@ dependencies = [
303
303
 
304
304
  [[package]]
305
305
  name = "clipboard-win"
306
- version = "5.4.1"
306
+ version = "5.4.3"
307
307
  source = "registry+https://github.com/rust-lang/crates.io-index"
308
- checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4"
308
+ checksum = "052af7878466feccda12ba7a6a67d019d712f296809559b47c12c8cc196d3a9a"
309
309
  dependencies = [
310
310
  "error-code",
311
311
  ]
@@ -1413,9 +1413,9 @@ dependencies = [
1413
1413
 
1414
1414
  [[package]]
1415
1415
  name = "rustymath"
1416
- version = "0.1.45"
1416
+ version = "0.1.46"
1417
1417
  source = "registry+https://github.com/rust-lang/crates.io-index"
1418
- checksum = "539dbd536cc6c64e9080a2c0bc346b6cf2f5308f0e29f814bfefd244bce87d07"
1418
+ checksum = "f160fb701304e3888885ade3929ef93b7c7d1aaab5ae61f16c0ec0e01f270cab"
1419
1419
  dependencies = [
1420
1420
  "foldhash",
1421
1421
  "half",
@@ -1434,9 +1434,9 @@ dependencies = [
1434
1434
 
1435
1435
  [[package]]
1436
1436
  name = "rustymath-buffer"
1437
- version = "0.1.45"
1437
+ version = "0.1.46"
1438
1438
  source = "registry+https://github.com/rust-lang/crates.io-index"
1439
- checksum = "1b3f549d927a69037ffe1ec3d11a318d89bbb115ac26c071d19150207e62a811"
1439
+ checksum = "1c1457056dae79ecf521f89d600f82a2a954e601ecd8d478e495b65cb6145010"
1440
1440
  dependencies = [
1441
1441
  "pyo3",
1442
1442
  "rustymath",
@@ -2086,7 +2086,7 @@ checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc"
2086
2086
 
2087
2087
  [[package]]
2088
2088
  name = "xtask"
2089
- version = "0.1.71"
2089
+ version = "0.1.72"
2090
2090
  dependencies = [
2091
2091
  "anyhow",
2092
2092
  "rustymath",
@@ -5,7 +5,7 @@ members = ["py"]
5
5
  join_comments = true
6
6
 
7
7
  [workspace.package]
8
- version = "0.1.71"
8
+ version = "0.1.72"
9
9
  edition = "2024"
10
10
  rust-version = "1.98"
11
11
  license = "Apache-2.0"
@@ -184,7 +184,7 @@ Bare numbers, empty literals and NaN use the parsed float width. Top-level `eval
184
184
 
185
185
  Float operations compute at the wider operand width. Exact operands round to the width an operation computes at. f16 operations run on f32 copies. `Numeric::halving` decides when: for a call with an f16 operand, or any call while the default width is 16 bits. `pervasive::halves` applies it to whole operations and `Number::halves` to scalar arithmetic and comparisons. `fusion::defer` declines those calls. Exact inputs convert once, to f32, and float outputs round back to f16. The scalar `Number` path rounds each f16 step. Complex parts have f32/f64 widths; f16 becoming complex uses f32 parts. Scalar Complex32 arithmetic computes at Complex64 and rounds, while kernels can compute at f32. These paths need not agree in their last bits.
186
186
 
187
- Floats use IEEE NaN, infinity and signed zero. Comparison treats NaN as unequal; match/search treat it as one value, and grade puts it last. Exact arithmetic involving division by zero can produce those float values. Floor/ceiling retain an exact operand beside infinity, and beside NaN give the right argument, as a float. Their folds, scans and products start at the identity and put each item on the left, so a NaN item changes no running result. Monadic floor/ceiling/sign turn whole finite results into exact integers, including big integers; nonfinite results remain floats. Use `Number::float(value, width)` and explicit-width array construction outside `number.rs` instead of implicit f64 conversion.
187
+ Floats use IEEE NaN, infinity and signed zero. Comparison treats NaN as unequal; match/search treat it as one value, and grade puts it last. Exact arithmetic involving division by zero can produce those float values. Floor/ceiling retain an exact operand beside infinity. Beside NaN the language leaves their result open: NaN or the other argument, varying by platform. Their folds, scans, windows, products and repeated writes give NaN or the maximum or minimum of the items that aren't NaN, never another number, by the rule in rustymath's `Folds` doc. A loop that folds by them either passes its running result as the right argument, which `rustymath::reduce::maximum` keeps beside NaN, or folds through rustymath's `Max` and `Min`, as `Dyad::extremum` does. Monadic floor/ceiling/sign turn whole finite results into exact integers, including big integers; nonfinite results remain floats. Use `Number::float(value, width)` and explicit-width array construction outside `number.rs` instead of implicit f64 conversion.
188
188
 
189
189
  Under `•prefs ["kinds":"static"]`, a result's kind follows from its arguments' kinds alone, as `meta/kinds.md` describes. `Numeric` carries `kinds` and `int`. `pervasive::map` chooses a dyadic call's kind through `joined`, which applies rustymath's `DType::common` after `Numeric::kind`. Atoms promote as arrays do. Python's API makes its scalar arguments weak through `Value::weakened`. The loops keep the failed results that `keeps` names: floats' NaNs, and the wrapped integers of objects that report `WRAPS`. The kernel tables choose float `⌊ ⌈ ×` and wrapping negation from `run.numeric()`. `Stored::build_at` keeps complex results complex. `Primitive::number` gives every pervasive result on numbers, as well as each step of the fold of numbers, and `statically` adjusts it. `Number::parse` keeps complex literals and checks integer literals against the `int` width.
190
190
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: basedpl
3
- Version: 0.1.71
3
+ Version: 0.1.72
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Requires-Dist: fastcore
@@ -15,12 +15,10 @@ Complex floor uses APL's Gaussian-integer rule.
15
15
  ⌊1.5j0.5 ⍝ 1j1
16
16
  ```
17
17
 
18
- `X⌊Y` takes the real minimum, and for characters the one with the lower code point. A number is less than any character, as [`⍋`](delta-stile.qmd) orders them. Pervasive. Beside NaN it gives `Y`: `$n⌊3` is `3`, and `3⌊$n` is `$n`. A reduction or scan starts at `∞` and puts each item on the left, so it leaves NaN items out: `⌊/$n 1` is `1`, and `⌊/$n $n` is `∞`. A NaN seed stays NaN. Empty reduction identity: `∞`.
18
+ `X⌊Y` takes the real minimum, and for characters the one with the lower code point. A number is less than any character, as [`⍋`](delta-stile.qmd) orders them. Pervasive. Beside NaN it gives NaN or the other argument. Which one can vary by platform. A reduction, scan, window or inner product by `⌊`, or a write by `⌊←` to one position more than once, gives NaN or the least of the items that aren't NaN, and never another number. Empty reduction identity: `∞`.
19
19
 
20
20
  ```bpl
21
21
  3⌊1 5 ⍝ 1 3
22
- 3⌊1 $n 5 ⍝ 1 $n 3
23
- ⌊\1 $n 3 ⍝ 1 1 1
24
22
  "abc"⌊"bab" ⍝ "aab"
25
23
  3⌊'a' ⍝ 3
26
24
  ```
@@ -9,12 +9,10 @@ Function. Keys: `Alt-s`. Hanzi: `上`. Ranks: `0` monadic, `0 0` dyadic
9
9
  ⌈3r2 ⍝ 2ₓ
10
10
  ```
11
11
 
12
- `X⌈Y` takes the real maximum, and for characters the one with the higher code point. A character is greater than any number, as [`⍋`](delta-stile.qmd) orders them. Pervasive. Beside NaN it gives `Y`: `$n⌈3` is `3`, and `3⌈$n` is `$n`. A reduction or scan starts at `¯∞` and puts each item on the left, so it leaves NaN items out: `⌈/$n 1` is `1`, and `⌈/$n $n` is `¯∞`. A NaN seed stays NaN. Empty reduction identity: `¯∞`.
12
+ `X⌈Y` takes the real maximum, and for characters the one with the higher code point. A character is greater than any number, as [`⍋`](delta-stile.qmd) orders them. Pervasive. Beside NaN it gives NaN or the other argument. Which one can vary by platform. A reduction, scan, window or inner product by `⌈`, or a write by `⌈←` to one position more than once, gives NaN or the greatest of the items that aren't NaN, and never another number. Empty reduction identity: `¯∞`.
13
13
 
14
14
  ```bpl
15
15
  3⌈1 5 ⍝ 3 5
16
- 3⌈1 $n 5 ⍝ 3 $n 5
17
- ⌈\1 $n 3 ⍝ 1 1 3
18
16
  "abc"⌈"bab" ⍝ "bbc"
19
17
  3⌈'a' ⍝ 'a'
20
18
  ```
@@ -199,14 +199,13 @@ An infinity or NaN is a float. Joining one to exact integers makes them floats,
199
199
 
200
200
  CSV and JSON imports give NaN for a missing number. An integer column with gaps then becomes floats. A column that also holds an integer too large for a float to hold exactly keeps each item's kind, in mixed storage.
201
201
 
202
- `⌊` and `⌈` return an exact argument unchanged beside an infinity. Beside NaN they give NaN:
202
+ `⌊` and `⌈` return an exact argument unchanged beside an infinity:
203
203
 
204
204
  ```bpl
205
205
  3ₓ⌊∞ ⍝ 3ₓ
206
- 3ₓ⌊$n ⍝ $n
207
206
  ```
208
207
 
209
- Arithmetic with an infinity gives floats.
208
+ The [`⌈`](glyphs/upstile.qmd) and [`⌊`](glyphs/downstile.qmd) pages give their results beside NaN. Arithmetic with an infinity gives floats.
210
209
 
211
210
  ## Static kinds
212
211
 
@@ -208,7 +208,7 @@ fn selection(value: &Value, index: &Bound<'_, PyAny>, convert: &Bound<'_, PyAny>
208
208
  match v {
209
209
  None => Some(rustymath_buffer::selection::selector(layout, axis, p, || unreachable!("a native selector decodes without converting"))),
210
210
  Some(v) => match v.view() {
211
- Some(mask @ View::Booleans(_)) => Some(rustymath_buffer::selection::array_selector(layout, axis, v.core_layout().clone(), mask, false)),
211
+ Some(View::Booleans(_)) => Some(rustymath_buffer::selection::array_selector(layout, axis, v.core_layout().clone(), std::sync::Arc::new(v.clone()))),
212
212
  _ => None,
213
213
  },
214
214
  }
@@ -2,6 +2,7 @@
2
2
  import json, math, os, re, statistics, subprocess, sys, tempfile, time, tomllib
3
3
  from concurrent.futures import ThreadPoolExecutor
4
4
  from collections import defaultdict
5
+ from itertools import accumulate
5
6
  from decimal import Context, Decimal, ROUND_CEILING
6
7
  from dataclasses import dataclass, field, replace
7
8
  from pathlib import Path
@@ -336,7 +337,8 @@ def instructions(
336
337
  def steps(code):
337
338
  if counts: return counts
338
339
  rough = max(1, (count(code, 1_000, 1) - count(code, 0, 1)) / 1_000)
339
- return [round((_SETTLE + i*_SPAN)/rough) for i in range(4)]
340
+ # Each value is at least one more than the last, for a case that retires more than `_SPAN` instructions a step, whose warm-up is then a small share of a step.
341
+ return list(accumulate((round((_SETTLE + i*_SPAN)/rough) for i in range(4)), lambda last, n: max(n, last + 1)))
340
342
  def per_step(code):
341
343
  ns = steps(code)
342
344
  cs = [count(code, n) for n in ns]
@@ -31,6 +31,8 @@ impl Batch {
31
31
  pub(crate) fn rank(&self) -> usize { self.whole.shape().len() - self.frame }
32
32
  /// The number of cells: the product of the frame's lengths.
33
33
  pub(crate) fn cells(&self) -> usize { self.whole.shape()[..self.frame].iter().product() }
34
+ /// The array that holds every cell, with the frame's axes first.
35
+ pub(crate) fn whole(&self) -> &Value { &self.whole }
34
36
  /// The frame's layout: the whole's first `frame` axes, with their keys and names.
35
37
  fn frame_layout(&self) -> Layout { self.whole.layout().axes(0..self.frame) }
36
38
  /// One `Steps` for each frame axis, reading item `start` of each cell of the whole, cell by cell.
@@ -806,7 +806,7 @@ fn product_dual(left: &Value, right: &Value, tag: u64, stacked: bool, span: &Spa
806
806
 
807
807
  /// The primal and tangent of a fold or scan by `p`, which is `×`, `⌈` or `⌊`, of `x` with tangent `tx`, through the linear operations that reverse mode transposes. A product's tangent scales each item's tangent by the product of the others and sums: the product of the nonzero items, times the sum of `tx÷x` where no item is zero, or times the zero item's tangent where one is, and 0 where more are. A maximum's or minimum's tangent gathers the tangent of the item that gives it, the first of any ties, as dyadic `⌈` and `⌊` give a tie to their left argument.
808
808
  fn fold_rule(p: Primitive, kind: FoldKind, axis: Option<usize>, x: &Value, tx: &Value, span: &Span) -> Result<(Value, Value), Error> {
809
- use {crate::array::Lanes, Arithmetic::*, Comparison::{Equal, NotEqual}};
809
+ use {crate::array::Lanes, Arithmetic::*, Comparison::Equal};
810
810
  let call = |p: Primitive, a: &Value, b: &Value, span: &Span| p.call(Some(a), b, span);
811
811
  let fold = |p: Primitive, v: &Value| Operation::Fold(p, kind).call(Pairing::Axis(axis), None, v, span);
812
812
  let (times, plus) = (Primitive::Arithmetic(Times), Primitive::Arithmetic(Plus));
@@ -823,51 +823,35 @@ fn fold_rule(p: Primitive, kind: FoldKind, axis: Option<usize>, x: &Value, tx: &
823
823
  let one = call(times, &call(times, &rest, &call(Primitive::Compare(Equal), &zeros, &Value::integer(1), span)?, span)?, &one, span)?;
824
824
  call(plus, &none, &one, span)?
825
825
  } else {
826
- let shape = x.shape();
827
- let along = axis.unwrap_or(kind.default_axis(shape.len()));
828
- let lanes = Lanes::new(shape, along)?;
829
- let Lanes { outer, len: n, inner } = lanes;
830
- let booleans = |v: Value| v.as_booleans().map(<[bool]>::to_vec).unwrap_or_else(|| v.elements().map(|e| matches!(e, Value::Number(n) if !n.is_zero())).collect());
831
- let (offsets, one_per_lane) = if kind.scan {
832
- // A running maximum or minimum changes only where an item gives a new extreme, whose tangent it then follows. Where it doesn't change, the earlier item keeps it.
833
- let drop = |d: i64, span: &Span| {
834
- let spec = Value::integers(vec![along + 1], (0..=along).map(|a| if a == along { d } else { 0 }).collect()).described("invalid drop")?;
835
- Primitive::Drop.call(Some(&spec), &r, span)
836
- };
837
- let changed = booleans(call(Primitive::Compare(NotEqual), &drop(1, span)?, &drop(-1, span)?, span)?);
838
- let mut offsets = Vec::with_capacity(outer * n * inner);
839
- for o in 0..outer {
840
- for k in 0..n {
841
- for i in 0..inner {
842
- let at = lanes.offset(o, k, i);
843
- offsets.push(if k == 0 || changed[(o * (n - 1) + k - 1) * inner + i] { at as i64 } else { offsets[at - inner] });
844
- }
845
- }
826
+ let along = axis.unwrap_or(kind.default_axis(x.shape().len()));
827
+ // One pick on a batch's whole, with the frame's axes first, serves every cell. A batch's scan stops the run, and its map calls the operand once for each cell, because a scan's tangent gathers at each cell's own positions.
828
+ let batch = x.carrier().and_then(Carrier::batch);
829
+ if let (Some(b), true) = (batch, kind.scan) { return Err(Stop::new(b.level, Cause::Rule).into()); }
830
+ let all = batch.map_or(x, |b| b.whole());
831
+ let lanes = Lanes::new(all.shape(), batch.map_or(0, |b| b.frame) + along)?;
832
+ // Windows that slide along the fold's axis give their extremes' positions from their source, with no windows built.
833
+ let windows = (batch.is_none() && along == kind.default_axis(x.shape().len())).then(|| crate::fusion::picks(x, p, kind)).flatten();
834
+ let one_per_lane = !kind.scan && windows.is_none();
835
+ let offsets = match windows {
836
+ Some(offsets) => offsets,
837
+ None => {
838
+ let Lanes { outer, len: n, inner } = lanes;
839
+ let numbers = || Error::domain("∂ takes ⌈ and ⌊ of numbers");
840
+ // Mixed storage picks among its numbers as floats. Two different exact integers beyond 2⁵³ can round to one float. They then tie, and the earlier one is picked.
841
+ let floats = match all.view() { Some(_) => None, None => Some(all.to_float_width(FloatWidth::F64).map_err(|_| numbers())?) };
842
+ let view = floats.as_ref().unwrap_or(all).view().ok_or_else(numbers)?;
843
+ let of = if kind.scan { rustymath::reduce::Picks::Running } else { rustymath::reduce::Picks::Lanes };
844
+ let rows = crate::pervasive::picks(p, view, [outer, n, inner], of).ok_or_else(numbers)?;
845
+ // Each running fold's pick, or each lane's, as a position in the ravel.
846
+ rows.into_iter().enumerate().map(|(j, row)| lanes.offset(if kind.scan { j / (n * inner) } else { j / inner }, row, j % inner) as i64).collect()
846
847
  }
847
- (offsets, false)
848
- } else if let Some(offsets) = (along == kind.default_axis(shape.len())).then(|| crate::fusion::picks(x, p, kind)).flatten() {
849
- // Windows that slide along the fold's axis give their extremes' positions from their source, with no windows built.
850
- (offsets, false)
851
- } else {
852
- // `r` takes a length-1 axis in place of the folded axis to pair with `x`, unless the fold removed the last axis.
853
- let back = if along + 1 < shape.len() {
854
- let mut shape = r.shape().iter().map(|&n| n as i64).collect::<Vec<_>>();
855
- shape.insert(along, 1);
856
- Primitive::Shape.call(Some(&Value::integers(vec![shape.len()], shape).described("invalid shape")?), &r, span)?
857
- } else { r.clone() };
858
- let hit = booleans(call(Primitive::Compare(Equal), x, &back, span)?);
859
- // The first item of each lane that gives its extreme, or the lane's first item where none does, as for NaN.
860
- let firsts = (0..outer)
861
- .flat_map(|o| (0..inner).map(move |i| (o, i)))
862
- .map(|(o, i)| (0..n).map(|k| lanes.offset(o, k, i)).find(|&at| hit[at]).unwrap_or(lanes.offset(o, 0, i)) as i64)
863
- .collect::<Vec<_>>();
864
- (firsts, true)
865
848
  };
866
- // Where reverse mode records one item from each lane, the tangent folds the tangent times a mask of the chosen items. Its transpose reads: each item takes its lane's cotangent where it was chosen, and 0 elsewhere. A gather's transpose would scatter.
867
- if one_per_lane && tx.carried() {
868
- let mut chosen = vec![false; x.len()];
849
+ // Where reverse mode records one item from each lane, or `x` is a batch, the tangent folds the tangent times a mask of the chosen items. Its transpose reads: each item takes its lane's cotangent where it was chosen, and 0 elsewhere. A gather's transpose would scatter.
850
+ if one_per_lane && (tx.carried() || batch.is_some()) {
851
+ let mut chosen = vec![false; all.len()];
869
852
  for &at in &offsets { chosen[at as usize] = true; }
870
- let mask = x.layout().booleans(chosen).described("invalid mask")?;
853
+ let mask = all.layout().booleans(chosen).described("invalid mask")?;
854
+ let mask = match batch { Some(b) => crate::batch::batch(b.level, mask, b.frame), None => mask };
871
855
  return Ok((r, fold(plus, &call(times, &mask, tx, span)?)?));
872
856
  }
873
857
  let offsets = Value::integers(vec![offsets.len()], offsets).described("invalid positions")?.enclose().expect("positions enclose");
@@ -1612,14 +1612,14 @@ pub(crate) fn primitive_fold(p: Primitive, kind: FoldKind, axis: Option<usize>,
1612
1612
  let active = crate::transform::carried(None, right);
1613
1613
  let (along, plan) = FoldPlan::new(kind, axis, seed, right, || identity(p, &right.prototype(), span))?;
1614
1614
  let result = match plan {
1615
- FoldPlan::One(item) => match seed { Some(seed) if kind.scan => call(seed, &item)?, Some(seed) => call(&item, seed)?, None => lone(item) },
1615
+ FoldPlan::One(item) => match seed { Some(seed) if kind.scan => scan_step(p, call)(seed, &item)?, Some(seed) => call(&item, seed)?, None => lone(item) },
1616
1616
  FoldPlan::Whole => lone(right.clone()),
1617
1617
  FoldPlan::Done(result) => result,
1618
1618
  FoldPlan::Lanes { lanes, shape } if kind.scan => {
1619
1619
  if let Some(result) = (!active).then(|| crate::pervasive::scan(p, right, seed, &lanes)).flatten() { result }
1620
1620
  else if let (Primitive::Arithmetic(op), false, true) = (p, active, right.all_numbers() && seed.is_none_or(|a| matches!(a, Value::Number(_)))) {
1621
1621
  number_lanes(op, true, right, seed, &lanes, shape)?
1622
- } else { item_lanes(true, &lanes, shape, seed, right, call, active)? }
1622
+ } else { item_lanes(true, &lanes, shape, seed, right, scan_step(p, call), active)? }
1623
1623
  }
1624
1624
  FoldPlan::Lanes { lanes, shape } => {
1625
1625
  // Where `p`'s kernel folds in any order, a number seed joins each lane's result after the fold, as one more item would. The fold then takes the fusion and kernel routes of a fold with no seed. A level that carries `right` keeps the seed in its items, because its kernels don't apply there. So do Booleans under a `ᵇ` table that `sets_high_bits`: they fold by the logical function, and a number seed turns the fold to the integer function.
@@ -1672,7 +1672,7 @@ fn number_lanes(
1672
1672
  let (item, seed) = (|i| number(right.at(i)), seed.cloned().map(number));
1673
1673
  let (p, t) = (Primitive::Arithmetic(op), Numeric::current());
1674
1674
  let step = |x: &crate::Number, y: &crate::Number| { check()?; p.number(Some(x), y, t).map_err(Error::from) };
1675
- let data = if scan { scan_items(axis, seed, item, step)? } else { fold_items(axis, seed.as_ref(), item, step)? };
1675
+ let data = if scan { scan_items(axis, seed, item, scan_step(p, step))? } else { fold_items(axis, seed.as_ref(), item, step)? };
1676
1676
  Value::new(shape, data.into_iter().map(Value::Number).collect()).described("invalid numeric result")
1677
1677
  }
1678
1678
 
@@ -1690,6 +1690,13 @@ fn fold_items<T: Clone>(axis: &Lanes, seed: Option<&T>, item: impl Fn(usize) ->
1690
1690
  Ok(data)
1691
1691
  }
1692
1692
 
1693
+ /// `apply` as a step of `p`'s scan, which takes the running result and the next item in the order that keeps rustymath's rule beside NaN. `⌈` and `⌊` take the item on the left, because a maximum or minimum keeps its right argument beside NaN. Every other function takes the running result on the left, as a scan from the left does.
1694
+ fn scan_step<V>(p: Primitive, mut apply: impl FnMut(&V, &V) -> Result<V, Error>) -> impl FnMut(&V, &V) -> Result<V, Error> {
1695
+ let turned = matches!(p, Primitive::Math(crate::number::Math::Ceiling | crate::number::Math::Floor));
1696
+ move |total, item| if turned { apply(item, total) } else { apply(total, item) }
1697
+ }
1698
+
1699
+ /// Each lane of `axis` scanned from the left, starting from `seed` or else the lane's first item: `apply(result, item)`.
1693
1700
  fn scan_items<T: Clone>(axis: &Lanes, seed: Option<T>, item: impl Fn(usize) -> T, mut apply: impl FnMut(&T, &T) -> Result<T, Error>) -> Result<Vec<T>, Error> {
1694
1701
  let mut data = vec![item(0); axis.outer * axis.len * axis.inner];
1695
1702
  for i in 0..axis.outer {
@@ -486,7 +486,7 @@ pub(crate) fn picks(value: &Value, p: Primitive, kind: FoldKind) -> Option<Vec<i
486
486
  let shape = value.shape();
487
487
  let (_, tables) = w.folded(shape, k, width);
488
488
  if !Steps::in_order(&tables) { return None; }
489
- let rows = pervasive::sliding_picks(p, w.region()?, w.rows, width)?;
489
+ let rows = pervasive::picks(p, w.region()?, w.rows, rustymath::reduce::Picks::Windows(width))?;
490
490
  // Each window starts at the position along `q` that the copy's other axes along `q` reach. Its pick lies that many rows before.
491
491
  let strides = strides(shape);
492
492
  let rest: Vec<usize> = (0..shape.len()).filter(|&r| r != k).collect();
@@ -32,6 +32,8 @@ pub(crate) trait Dyad<A> {
32
32
  fn many(self, f: impl rustymath::Binary<A, Out = A> + Copy + Sync) -> Self::Output;
33
33
  /// `f`, which gives Booleans, on each pair of items, through its slice form where the loop has slices of items, and its scalar form elsewhere.
34
34
  fn booleans(self, f: impl rustymath::Binary<A, Out = bool> + Copy + Sync) -> Self::Output;
35
+ /// `f`, a maximum or minimum, as `many` runs it. A loop that folds values into a running result, as `Scatter` does at a place it writes more than once, folds them by `M` instead. `M`'s step keeps the running result beside a NaN value, where `f`'s keeps the value.
36
+ fn extremum<M: Reduction<A, Total = A>>(self, f: impl rustymath::Binary<A, Out = A> + Copy + Sync, _: M) -> Self::Output where Self: Sized { self.many(f) }
35
37
  /// `f`, a comparison, on each pair of items, as `booleans` runs it. A loop that writes floats in place of Booleans writes 1 where `f` holds and 0 elsewhere, through `rustymath::tolerant::Indicator`. The nodes of a fused graph before its last write a comparison this way.
36
38
  fn compared<K: rustymath::Binary<A, Out = bool> + Copy + Sync>(self, f: K) -> Self::Output where Self: Sized, rustymath::tolerant::Indicator<K>: rustymath::Binary<A, Out = A> { self.booleans(f) }
37
39
  /// The left and the right argument, each when it is one number that every item pairs with. A kernel can then run a loop of its own for that number, as `x*2` squares each item.
@@ -166,8 +168,8 @@ mod float_kernels {
166
168
  },
167
169
  Primitive::Math(Pi) => run.many(rustymath::PiTimes),
168
170
  Primitive::Math(Log) => run.many(rustymath::Logb),
169
- Primitive::Math(Ceiling) => run.many(reduce::Maximum),
170
- Primitive::Math(Floor) => run.many(reduce::Minimum),
171
+ Primitive::Math(Ceiling) => run.extremum(reduce::Maximum, reduce::Max),
172
+ Primitive::Math(Floor) => run.extremum(reduce::Minimum, reduce::Min),
171
173
  Primitive::Math(Magnitude) => run.many(rustymath::tolerant::Residue(t)),
172
174
  Primitive::Math(Root) => match run.constants() {
173
175
  (Some(n), _) if n == 2.0 => run.many(Right(rustymath::Sqrt)),
@@ -537,6 +539,9 @@ impl<A: Stored> Dyad<A> for Scatter<'_, A> {
537
539
  self.writes.combine(self.out, self.values, move |x, y| f.one(x, y));
538
540
  Some(Route::InPlace)
539
541
  }
542
+ fn extremum<M: Reduction<A, Total = A>>(self, _: impl rustymath::Binary<A, Out = A> + Copy + Sync, _: M) -> Option<Route> {
543
+ self.writes.fold::<M, A>(self.out, self.values).then_some(Route::InPlace)
544
+ }
540
545
  fn booleans(self, _: impl rustymath::Binary<A, Out = bool> + Copy + Sync) -> Option<Route> { None }
541
546
  }
542
547
 
@@ -1298,24 +1303,20 @@ impl<'a, A: Stored> Fold<'a, A> {
1298
1303
  let tail = match tail { None => None, Some(view) => Some(carried::<A>(view)?) };
1299
1304
  Some(Self { data, dims, tail, numeric })
1300
1305
  }
1301
- /// The fold by `f`, which gives `None` where a step fails.
1306
+ /// The fold by `f` through rustymath's right fold. `None` where a step fails, unless `kept` keeps its failed results, as static kinds keep wrapped integers.
1302
1307
  #[inline]
1303
- fn by(self, f: impl Fn(A, A) -> Option<A> + Copy + Sync) -> Option<Buffer> {
1304
- Some(A::buffer(reduce::right_fold(self.data, self.dims, self.tail.as_deref(), f, |x| x)?))
1308
+ fn by<O: Element + Source<A>>(self, f: &impl rustymath::Binary<A, Out = O>) -> Option<Buffer> {
1309
+ let (out, ok) = reduce::right_fold(f, self.data, self.dims, self.tail.as_deref());
1310
+ (ok || kept(f, self.numeric)).then(|| O::buffer(out))
1305
1311
  }
1306
1312
  }
1307
1313
  impl<A: Stored> Dyad<A> for Fold<'_, A> where bool: Source<A> {
1308
1314
  type Output = Option<Buffer>;
1309
1315
  fn numeric(&self) -> Numeric { self.numeric }
1310
- /// Each step through `f`'s scalar form. A step that fails gives `None`, unless `keeps` keeps `f`'s failed results, as static kinds keep wrapped integers. An object none of whose steps fails compiles only the first loop.
1311
1316
  #[inline]
1312
- fn many(self, f: impl rustymath::Binary<A, Out = A> + Copy + Sync) -> Self::Output {
1313
- if total(&f) || kept(&f, self.numeric) { self.by(move |x, y| Some(f.one(x, y))) } else { self.by(move |x, y| f.checked(x, y)) }
1314
- }
1317
+ fn many(self, f: impl rustymath::Binary<A, Out = A> + Copy + Sync) -> Self::Output { self.by(&f) }
1315
1318
  #[inline]
1316
- fn booleans(self, f: impl rustymath::Binary<A, Out = bool> + Copy + Sync) -> Self::Output {
1317
- Some(bool::buffer(reduce::right_fold(self.data, self.dims, self.tail.as_deref(), move |x, y| f.checked(x, y), Source::<A>::read)?))
1318
- }
1319
+ fn booleans(self, f: impl rustymath::Binary<A, Out = bool> + Copy + Sync) -> Self::Output { self.by(&f) }
1319
1320
  }
1320
1321
 
1321
1322
  /// A scan of compact values along `axis` by successive left accumulation, as the general scan does. Kernels of approximate numbers compare within the tolerance of their width in the current settings.
@@ -1389,9 +1390,17 @@ fn scanned_under(p: Primitive, right: &Value, seed: Option<&Value>, axis: &Lanes
1389
1390
  }
1390
1391
  match right.as_items() {
1391
1392
  // The logical functions and comparisons keep Booleans, and scan through their truth tables. Other functions read Booleans as integers.
1392
- Items::Compact(View::Booleans(data)) => match bool::dyad(p, LogicalScan(plan(numeric.exact()).of(data)?)) {
1393
- Some(result) => result, None => integers(Ints::U8(truth_bytes(data)))
1394
- },
1393
+ Items::Compact(View::Booleans(data)) => {
1394
+ let scan = plan(numeric.exact()).of(data)?;
1395
+ match (scan.inverse, logical(p)) {
1396
+ (false, Some(table)) => {
1397
+ let mut result = Vec::with_capacity(data.len());
1398
+ table.scan_along(data, scan.axis.dims(), scan.seed, &mut result);
1399
+ bool::build(scan.shape, result)
1400
+ }
1401
+ _ => match bool::dyad(p, scan) { Some(result) => result, None => integers(Ints::U8(truth_bytes(data))) },
1402
+ }
1403
+ }
1395
1404
  Items::Compact(View::Floats(data)) => with_floats!(kernel data, |data| float_scan(p, plan(numeric), data)),
1396
1405
  Items::Compact(View::Integers(ints)) => integers(ints),
1397
1406
  Items::Compact(View::Complexes(data)) => with_complexes!(data, |data| complex_scan(p, plan(numeric), data)),
@@ -1443,36 +1452,25 @@ impl<'a> ScanPlan<'a> {
1443
1452
  }
1444
1453
  }
1445
1454
 
1446
- /// A scan of Booleans by a function that keeps them Boolean, through rustymath's scan of the function's truth table. The runner reads the table by calling the kernel on the four pairs of Booleans. An inverse scan, or a kernel that fails on a pair, runs through `Scan`.
1447
- struct LogicalScan<'a>(Scan<'a, bool>);
1448
- impl Dyad<bool> for LogicalScan<'_> {
1449
- type Output = Option<Value>;
1450
- fn numeric(&self) -> Numeric { self.0.numeric }
1451
- #[inline]
1452
- fn many(self, f: impl rustymath::Binary<bool, Out = bool> + Copy + Sync) -> Option<Value> {
1453
- let scan = self.0;
1454
- let row = |r| Some([f.checked(r, false)?, f.checked(r, true)?]);
1455
- let (false, Some(lo), Some(hi)) = (scan.inverse, row(false), row(true)) else { return scan.many(f) };
1456
- let mut result = Vec::with_capacity(scan.data.len());
1457
- reduce::Logical([lo, hi]).scan_along(scan.data, scan.axis.dims(), scan.seed, &mut result);
1458
- bool::build(scan.shape, result)
1459
- }
1460
- #[inline]
1461
- fn booleans(self, f: impl rustymath::Binary<bool, Out = bool> + Copy + Sync) -> Option<Value> { self.many(f) }
1462
- }
1455
+ /// The truth table of `p`'s kernel on Booleans, where `p` has one that gives a Boolean for every pair. Folds and scans of Booleans by `p` run through it.
1456
+ fn logical(p: Primitive) -> Option<reduce::Logical> { bool::dyad(p, Truths)? }
1463
1457
 
1464
- /// The truth table, indexed by `2*x+y`, of `p`'s kernel on Booleans, where `p` has one that gives a Boolean for every pair. A dyadic call, fold or scan of `gᵇ` with such a `g` runs as `Primitive::Bitwise` of the table (`Function::dyadic_primitive`).
1465
- pub(crate) fn truth_table(p: Primitive) -> Option<u8> { bool::dyad(p, Truths)? }
1458
+ /// [`logical`]'s table, indexed by `2*x+y`. A dyadic call, fold or scan of `gᵇ` with such a `g` runs as `Primitive::Bitwise` of the table (`Function::dyadic_primitive`).
1459
+ pub(crate) fn truth_table(p: Primitive) -> Option<u8> {
1460
+ let reduce::Logical(t) = logical(p)?;
1461
+ Some((0..4).fold(0u8, |table, i| table | u8::from(t[i >> 1][i & 1]) << i))
1462
+ }
1466
1463
 
1467
- /// The runner that reads a Boolean kernel's truth table for `truth_table`, by calling it on the four pairs of Booleans.
1464
+ /// The runner that reads a Boolean kernel's truth table for [`logical`], by calling it on the four pairs of Booleans.
1468
1465
  struct Truths;
1469
1466
  impl Dyad<bool> for Truths {
1470
- type Output = Option<u8>;
1467
+ type Output = Option<reduce::Logical>;
1471
1468
  fn numeric(&self) -> Numeric { Numeric::EXACT }
1472
- fn many(self, f: impl rustymath::Binary<bool, Out = bool> + Copy + Sync) -> Option<u8> {
1473
- (0..4u8).try_fold(0, |table, i| Some(table | u8::from(f.checked(i & 2 != 0, i & 1 != 0)?) << i))
1469
+ fn many(self, f: impl rustymath::Binary<bool, Out = bool> + Copy + Sync) -> Option<reduce::Logical> {
1470
+ let row = |x| Some([f.checked(x, false)?, f.checked(x, true)?]);
1471
+ Some(reduce::Logical([row(false)?, row(true)?]))
1474
1472
  }
1475
- fn booleans(self, f: impl rustymath::Binary<bool, Out = bool> + Copy + Sync) -> Option<u8> { self.many(f) }
1473
+ fn booleans(self, f: impl rustymath::Binary<bool, Out = bool> + Copy + Sync) -> Option<reduce::Logical> { self.many(f) }
1476
1474
  }
1477
1475
 
1478
1476
  /// A scan of integers at their own width, or at rustymath's total type for a reduction: `⌈\`, `⌊\` and the scans of `ᵇ`'s and, or, xor and xnor run through rustymath's running reductions, and any other function through its kernel. `None` where a result doesn't fit.
@@ -1509,12 +1507,12 @@ struct Scan<'a, A> {
1509
1507
  data: &'a [A], seed: Option<A>, starts: Option<&'a [bool]>, axis: &'a Lanes, shape: Vec<usize>, numeric: Numeric, inverse: bool, flip: bool
1510
1508
  }
1511
1509
  impl<A: Stored> Scan<'_, A> {
1512
- /// The scan by `f`, which adds the next item to a running total.
1510
+ /// The scan by `f` through rustymath's left scan, each running total stepped by the next item. `None` where a step fails, unless `kept` keeps its failed results, as `Fold::by` does.
1513
1511
  #[inline]
1514
- fn running(self, f: impl Fn(A, A) -> Option<A> + Copy + Sync) -> Option<Value> {
1512
+ fn running<O: Element + Source<A>>(self, f: &impl rustymath::Binary<A, Out = O>) -> Option<Value> {
1515
1513
  if self.inverse { return None; }
1516
1514
  let mut result = Vec::with_capacity(self.data.len());
1517
- if !reduce::left_scan(self.data, self.axis.dims(), self.seed, f, &mut result) { return None; }
1515
+ if !reduce::left_scan(f, self.data, self.axis.dims(), self.seed, &mut result) && !kept(f, self.numeric) { return None; }
1518
1516
  A::build_narrowed(self.shape, result)
1519
1517
  }
1520
1518
  /// The scan by rustymath's reduction `R` along the axis, at `R`'s total type, through `reduce::scan_along`. `None` where a result doesn't fit.
@@ -1572,13 +1570,13 @@ impl<A: Stored> Dyad<A> for Scan<'_, A> where bool: Source<A> {
1572
1570
  /// A scan runs through `running`, each step through `f`'s scalar form, and its inverse through `paired`, with `f`'s slice form.
1573
1571
  #[inline]
1574
1572
  fn many(self, f: impl rustymath::Binary<A, Out = A> + Copy + Sync) -> Option<Value> {
1575
- if self.inverse { self.paired(move |x, y, n, out| f.many(x, y, n, out)) } else { self.running(move |x, y| f.checked(x, y)) }
1573
+ if self.inverse { self.paired(move |x, y, n, out| f.many(x, y, n, out)) } else { self.running(&f) }
1576
1574
  }
1577
1575
  /// A comparison runs through `compared`, with `f`'s slice form. Its inverse, and a scan from a seed of the items' type, which only functions other than comparisons get, step through `f`'s scalar form, with the Booleans converted back to the item type.
1578
1576
  #[inline]
1579
1577
  fn booleans(self, f: impl rustymath::Binary<A, Out = bool> + Copy + Sync) -> Option<Value> {
1580
1578
  if self.inverse { return self.paired(move |x, y, n, out| pairs(x, y, n, out, |a, b| item_result(f.checked(a, b).map(Source::<A>::read)))); }
1581
- if self.seed.is_some() { return self.running(move |x, y| f.checked(x, y).map(Source::<A>::read)); }
1579
+ if self.seed.is_some() { return self.running(&f); }
1582
1580
  self.compared(&move |t, xs, out| f.many(t, Arg::Many(xs), xs.len(), out))
1583
1581
  }
1584
1582
  }
@@ -1696,6 +1694,11 @@ fn untransposed(s: Value, m: Mapping, shape @ [rows, _]: [usize; 2]) -> ((Value,
1696
1694
  fn native_fold(p: Primitive, data: View<'_>, dims: [usize; 3], tail: Option<View<'_>>, len: usize, numeric: Numeric) -> Option<Buffer> {
1697
1695
  match data {
1698
1696
  View::Booleans(data) => with_truth_reduction!(p, len, R => reduced::<_, R>(data, dims, tail, false)).flatten()
1697
+ .or_else(|| {
1698
+ if !reduce::Logical::folds(dims) { return None; }
1699
+ let tail = match tail { Some(v) => Some(carried::<bool>(v)?), None => None };
1700
+ Some(bool::buffer(logical(p)?.fold(data, dims[1], tail.as_deref())))
1701
+ })
1699
1702
  .or_else(|| bool::dyad(p, Fold::new(data, dims, tail, Numeric::EXACT)?)?)
1700
1703
  .or_else(|| integer_fold(p, truth_bytes(data), dims, tail, numeric)),
1701
1704
  View::Integers(data) => with_ints!(data, |data| integer_fold(p, data, dims, tail, numeric)),
@@ -1710,10 +1713,10 @@ pub(crate) fn sliding(p: Primitive, data: View<'_>, dims: [usize; 3], width: usi
1710
1713
  with_reduction!(p, data, width, Numeric::current().is_static(), |data, R, kept| fitting(reduce::sliding::<_, R>(data, dims, width), kept))
1711
1714
  }
1712
1715
 
1713
- /// The row of the first item that gives the maximum, for `⌈`, or the minimum, for `⌊`, of each window of `width` rows along the middle axis of `data`, an array of shape `dims`, as `sliding` folds the windows. Each row counts from the start of its lane. `None` for any other function, and for storage other than integers and 32- and 64-bit floats.
1714
- pub(crate) fn sliding_picks(p: Primitive, data: View<'_>, dims: [usize; 3], width: usize) -> Option<Vec<usize>> {
1716
+ /// The row of the first item that gives the maximum, for `⌈`, or the minimum, for `⌊`, of each of the folds that `of` chooses along the middle axis of `data`, an array of shape `dims`. Each row counts from the start of its lane. `None` for any other function, and for storage other than Booleans, integers and 32- and 64-bit floats.
1717
+ pub(crate) fn picks(p: Primitive, data: View<'_>, dims: [usize; 3], of: reduce::Picks) -> Option<Vec<usize>> {
1715
1718
  let max = match p { Primitive::Math(Math::Ceiling) => true, Primitive::Math(Math::Floor) => false, _ => return None };
1716
- reduce::view_sliding_picks(data, dims, width, max)
1719
+ reduce::view_picks(data, dims, of, max)
1717
1720
  }
1718
1721
 
1719
1722
  fn carried<A: Element>(view: View<'_>) -> Option<Cow<'_, [A]>> {