basedpl 0.1.71__tar.gz → 0.1.73__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.73}/.github/workflows/test.yml +11 -4
  2. {basedpl-0.1.71 → basedpl-0.1.73}/Cargo.lock +17 -17
  3. {basedpl-0.1.71 → basedpl-0.1.73}/Cargo.toml +3 -3
  4. {basedpl-0.1.71 → basedpl-0.1.73}/DEV.md +11 -17
  5. {basedpl-0.1.71 → basedpl-0.1.73}/PKG-INFO +1 -1
  6. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/evaluation.qmd +1 -0
  7. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/brackets.qmd +1 -1
  8. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/downstile.qmd +1 -3
  9. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/upstile.qmd +1 -3
  10. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/llms.txt +2 -2
  11. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/numbers.qmd +8 -6
  12. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/python.ipynb +1 -1
  13. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/scripts.ipynb +70 -2
  14. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/study/01_basics.ipynb +3 -3
  15. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/syntax.qmd +1 -1
  16. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/explain.qmd +7 -4
  17. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/prefs.qmd +1 -1
  18. {basedpl-0.1.71 → basedpl-0.1.73}/py/src/lib.rs +10 -4
  19. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/bpltests.py +65 -14
  20. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/functions.py +3 -2
  21. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/printing.py +2 -1
  22. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/worker.py +1 -1
  23. {basedpl-0.1.71 → basedpl-0.1.73}/src/array/storage.rs +4 -12
  24. {basedpl-0.1.71 → basedpl-0.1.73}/src/array.rs +41 -15
  25. {basedpl-0.1.71 → basedpl-0.1.73}/src/batch.rs +230 -45
  26. {basedpl-0.1.71 → basedpl-0.1.73}/src/derivative.rs +49 -50
  27. {basedpl-0.1.71 → basedpl-0.1.73}/src/distribution.rs +13 -11
  28. {basedpl-0.1.71 → basedpl-0.1.73}/src/element.rs +6 -0
  29. {basedpl-0.1.71 → basedpl-0.1.73}/src/eval/assign.rs +1 -1
  30. {basedpl-0.1.71 → basedpl-0.1.73}/src/eval/binder.rs +6 -2
  31. {basedpl-0.1.71 → basedpl-0.1.73}/src/eval/idioms.rs +17 -25
  32. {basedpl-0.1.71 → basedpl-0.1.73}/src/eval/operators.rs +62 -20
  33. {basedpl-0.1.71 → basedpl-0.1.73}/src/eval/session.rs +33 -7
  34. {basedpl-0.1.71 → basedpl-0.1.73}/src/eval/tree.rs +1 -1
  35. {basedpl-0.1.71 → basedpl-0.1.73}/src/eval.rs +8 -4
  36. {basedpl-0.1.71 → basedpl-0.1.73}/src/fusion.rs +55 -28
  37. {basedpl-0.1.71 → basedpl-0.1.73}/src/linear.rs +48 -12
  38. {basedpl-0.1.71 → basedpl-0.1.73}/src/number.rs +57 -16
  39. {basedpl-0.1.71 → basedpl-0.1.73}/src/pervasive.rs +193 -114
  40. {basedpl-0.1.71 → basedpl-0.1.73}/src/primitive/indexing.rs +87 -21
  41. {basedpl-0.1.71 → basedpl-0.1.73}/src/primitive/numeric.rs +30 -80
  42. {basedpl-0.1.71 → basedpl-0.1.73}/src/primitive/search.rs +48 -3
  43. {basedpl-0.1.71 → basedpl-0.1.73}/src/primitive/structural.rs +5 -0
  44. {basedpl-0.1.71 → basedpl-0.1.73}/src/primitive.rs +80 -21
  45. {basedpl-0.1.71 → basedpl-0.1.73}/src/search.rs +71 -12
  46. {basedpl-0.1.71 → basedpl-0.1.73}/src/selection.rs +1 -1
  47. {basedpl-0.1.71 → basedpl-0.1.73}/src/syntax.rs +16 -26
  48. {basedpl-0.1.71 → basedpl-0.1.73}/src/timing.rs +16 -16
  49. {basedpl-0.1.71 → basedpl-0.1.73}/src/transform.rs +18 -14
  50. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/core.bpl +102 -15
  51. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/distributions.bpl +2 -2
  52. {basedpl-0.1.71 → basedpl-0.1.73}/tests/settings.rs +1 -0
  53. {basedpl-0.1.71 → basedpl-0.1.73}/tests/speed.rs +2 -2
  54. {basedpl-0.1.71 → basedpl-0.1.73}/tests/speed.txt +128 -72
  55. {basedpl-0.1.71 → basedpl-0.1.73}/tests/test_basic.py +4 -2
  56. {basedpl-0.1.71 → basedpl-0.1.73}/tests/wasm.mjs +8 -0
  57. {basedpl-0.1.71 → basedpl-0.1.73}/.cargo/config.toml +0 -0
  58. {basedpl-0.1.71 → basedpl-0.1.73}/.gitattributes +0 -0
  59. {basedpl-0.1.71 → basedpl-0.1.73}/.github/workflows/ci.yml +0 -0
  60. {basedpl-0.1.71 → basedpl-0.1.73}/.github/workflows/docs.yml +0 -0
  61. {basedpl-0.1.71 → basedpl-0.1.73}/.github/workflows/speed.yml +0 -0
  62. {basedpl-0.1.71 → basedpl-0.1.73}/.gitignore +0 -0
  63. {basedpl-0.1.71 → basedpl-0.1.73}/CONTRIBUTING.md +0 -0
  64. {basedpl-0.1.71 → basedpl-0.1.73}/LICENSE +0 -0
  65. {basedpl-0.1.71 → basedpl-0.1.73}/README.md +0 -0
  66. {basedpl-0.1.71 → basedpl-0.1.73}/_config.yml +0 -0
  67. {basedpl-0.1.71 → basedpl-0.1.73}/_layouts/default.html +0 -0
  68. {basedpl-0.1.71 → basedpl-0.1.73}/build.rs +0 -0
  69. {basedpl-0.1.71 → basedpl-0.1.73}/editors/jetbrains/BPL.tmbundle/Syntaxes/bpl.tmLanguage.json +0 -0
  70. {basedpl-0.1.71 → basedpl-0.1.73}/editors/jetbrains/BPL.tmbundle/Syntaxes/hpl.tmLanguage.json +0 -0
  71. {basedpl-0.1.71 → basedpl-0.1.73}/editors/jetbrains/BPL.tmbundle/info.plist +0 -0
  72. {basedpl-0.1.71 → basedpl-0.1.73}/editors/jetbrains/BPL.xml +0 -0
  73. {basedpl-0.1.71 → basedpl-0.1.73}/editors/jetbrains/README.md +0 -0
  74. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-de.bundle/Contents/Info.plist +0 -0
  75. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-de.bundle/Contents/Resources/BasedPL-de.icns +0 -0
  76. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-de.bundle/Contents/Resources/BasedPL-de.keylayout +0 -0
  77. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-de.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  78. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-de.bundle/Contents/version.plist +0 -0
  79. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-de.txt +0 -0
  80. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-es.bundle/Contents/Info.plist +0 -0
  81. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-es.bundle/Contents/Resources/BasedPL-es.icns +0 -0
  82. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-es.bundle/Contents/Resources/BasedPL-es.keylayout +0 -0
  83. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-es.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  84. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-es.bundle/Contents/version.plist +0 -0
  85. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-es.txt +0 -0
  86. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-fr.bundle/Contents/Info.plist +0 -0
  87. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-fr.bundle/Contents/Resources/BasedPL-fr.icns +0 -0
  88. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-fr.bundle/Contents/Resources/BasedPL-fr.keylayout +0 -0
  89. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-fr.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  90. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-fr.bundle/Contents/version.plist +0 -0
  91. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-fr.txt +0 -0
  92. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-uk.bundle/Contents/Info.plist +0 -0
  93. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-uk.bundle/Contents/Resources/BasedPL-uk.icns +0 -0
  94. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-uk.bundle/Contents/Resources/BasedPL-uk.keylayout +0 -0
  95. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-uk.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  96. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-uk.bundle/Contents/version.plist +0 -0
  97. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-uk.txt +0 -0
  98. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-us.bundle/Contents/Info.plist +0 -0
  99. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-us.bundle/Contents/Resources/BasedPL-us.icns +0 -0
  100. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-us.bundle/Contents/Resources/BasedPL-us.keylayout +0 -0
  101. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-us.bundle/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  102. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-us.bundle/Contents/version.plist +0 -0
  103. {basedpl-0.1.71 → basedpl-0.1.73}/editors/macos/BasedPL-us.txt +0 -0
  104. {basedpl-0.1.71 → basedpl-0.1.73}/editors/vim/ftdetect/bpl.vim +0 -0
  105. {basedpl-0.1.71 → basedpl-0.1.73}/editors/vim/syntax/bpl.vim +0 -0
  106. {basedpl-0.1.71 → basedpl-0.1.73}/editors/windows/README.md +0 -0
  107. {basedpl-0.1.71 → basedpl-0.1.73}/editors/windows/build.ps1 +0 -0
  108. {basedpl-0.1.71 → basedpl-0.1.73}/editors/windows/install.ps1 +0 -0
  109. {basedpl-0.1.71 → basedpl-0.1.73}/editors/windows/keyboard.c +0 -0
  110. {basedpl-0.1.71 → basedpl-0.1.73}/editors/windows/keyboard.def +0 -0
  111. {basedpl-0.1.71 → basedpl-0.1.73}/editors/windows/keyboard.rc +0 -0
  112. {basedpl-0.1.71 → basedpl-0.1.73}/editors/windows/layout.h +0 -0
  113. {basedpl-0.1.71 → basedpl-0.1.73}/index_files/figure-commonmark/cell-17-output-1.svg +0 -0
  114. {basedpl-0.1.71 → basedpl-0.1.73}/index_files/figure-commonmark/cell-18-output-1.svg +0 -0
  115. {basedpl-0.1.71 → basedpl-0.1.73}/index_files/figure-html/cell-17-output-1.svg +0 -0
  116. {basedpl-0.1.71 → basedpl-0.1.73}/index_files/figure-html/cell-18-output-1.svg +0 -0
  117. {basedpl-0.1.71 → basedpl-0.1.73}/lib/LICENSE-april +0 -0
  118. {basedpl-0.1.71 → basedpl-0.1.73}/lib/README.md +0 -0
  119. {basedpl-0.1.71 → basedpl-0.1.73}/lib/array.bpl +0 -0
  120. {basedpl-0.1.71 → basedpl-0.1.73}/lib/dyalog.bpl +0 -0
  121. {basedpl-0.1.71 → basedpl-0.1.73}/lib/graph.bpl +0 -0
  122. {basedpl-0.1.71 → basedpl-0.1.73}/lib/numeric.bpl +0 -0
  123. {basedpl-0.1.71 → basedpl-0.1.73}/lib/power.bpl +0 -0
  124. {basedpl-0.1.71 → basedpl-0.1.73}/lib/regex.bpl +0 -0
  125. {basedpl-0.1.71 → basedpl-0.1.73}/lib/string.bpl +0 -0
  126. {basedpl-0.1.71 → basedpl-0.1.73}/lib/tree.bpl +0 -0
  127. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/.gitignore +0 -0
  128. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/_quarto.yml +0 -0
  129. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/arrays.ipynb +0 -0
  130. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/assignment.ipynb +0 -0
  131. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/bpl.xml +0 -0
  132. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/bqn.xml +0 -0
  133. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/bracket-types.ipynb +0 -0
  134. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/cli.qmd +0 -0
  135. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/comparison.qmd +0 -0
  136. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/data.ipynb +0 -0
  137. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/dfns.ipynb +0 -0
  138. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/distributions.ipynb +0 -0
  139. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/driver.js +0 -0
  140. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/dyalog.ipynb +0 -0
  141. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/dyalog.xml +0 -0
  142. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/fonts/LICENSE-SAX2 +0 -0
  143. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/fonts/README.md +0 -0
  144. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/fonts/SAX2B.ttf +0 -0
  145. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/fonts/SAX2B.woff2 +0 -0
  146. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/fonts.css +0 -0
  147. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/gallery/attractor.bpl +0 -0
  148. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/gallery/boids.bpl +0 -0
  149. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/gallery/dragon.bpl +0 -0
  150. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/gallery/flow.bpl +0 -0
  151. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/gallery/mandelbrot.bpl +0 -0
  152. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/gallery/mandelbrot32.bpl +0 -0
  153. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/gallery/orbits.bpl +0 -0
  154. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/gallery/phyllotaxis.bpl +0 -0
  155. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/gallery/prefs.bpl +0 -0
  156. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/gallery/reaction.bpl +0 -0
  157. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/gallery.qmd +0 -0
  158. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/getting-started.ipynb +0 -0
  159. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/_metadata.yml +0 -0
  160. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/alpha-underbar.qmd +0 -0
  161. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/alpha.qmd +0 -0
  162. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/at.qmd +0 -0
  163. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/backslash-bar.qmd +0 -0
  164. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/backslash.qmd +0 -0
  165. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/braces.qmd +0 -0
  166. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/bullet.qmd +0 -0
  167. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/circle-backslash.qmd +0 -0
  168. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/circle-bar.qmd +0 -0
  169. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/circle-diaeresis.qmd +0 -0
  170. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/circle-divide.qmd +0 -0
  171. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/circle-slash.qmd +0 -0
  172. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/circle-star.qmd +0 -0
  173. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/circle-stile.qmd +0 -0
  174. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/circle-times.qmd +0 -0
  175. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/circle.qmd +0 -0
  176. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/colon.qmd +0 -0
  177. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/comma-bar.qmd +0 -0
  178. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/comma.qmd +0 -0
  179. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/del-diaeresis.qmd +0 -0
  180. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/del-stile.qmd +0 -0
  181. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/del.qmd +0 -0
  182. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/delta-stile.qmd +0 -0
  183. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/diaeresis.qmd +0 -0
  184. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/diamond-underbar.qmd +0 -0
  185. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/diamond.qmd +0 -0
  186. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/domino.qmd +0 -0
  187. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/dot.qmd +0 -0
  188. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/down-arrow.qmd +0 -0
  189. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/down-shoe.qmd +0 -0
  190. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/down-tack.qmd +0 -0
  191. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/epsilon-underbar.qmd +0 -0
  192. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/epsilon.qmd +0 -0
  193. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/equal-underbar-slash.qmd +0 -0
  194. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/equal-underbar.qmd +0 -0
  195. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/equals.qmd +0 -0
  196. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/error-guard.qmd +0 -0
  197. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/exclamation.qmd +0 -0
  198. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/greater-than-or-equal.qmd +0 -0
  199. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/greater-than.qmd +0 -0
  200. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/hash.qmd +0 -0
  201. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/hydrant.qmd +0 -0
  202. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/infinity.qmd +0 -0
  203. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/inverted-question.qmd +0 -0
  204. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/iota-underbar.qmd +0 -0
  205. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/iota.qmd +0 -0
  206. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/jot-diaeresis.qmd +0 -0
  207. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/jot.qmd +0 -0
  208. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/lamp.qmd +0 -0
  209. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/left-arrow.qmd +0 -0
  210. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/left-shoe-underbar.qmd +0 -0
  211. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/left-shoe.qmd +0 -0
  212. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/left-tack.qmd +0 -0
  213. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/left-tail-arrow.qmd +0 -0
  214. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/less-than-or-equal.qmd +0 -0
  215. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/less-than.qmd +0 -0
  216. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/minus.qmd +0 -0
  217. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/not-equals.qmd +0 -0
  218. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/obelus.qmd +0 -0
  219. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/omega-underbar.qmd +0 -0
  220. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/omega.qmd +0 -0
  221. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/overbar.qmd +0 -0
  222. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/parentheses.qmd +0 -0
  223. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/partial.qmd +0 -0
  224. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/pi.qmd +0 -0
  225. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/plus.qmd +0 -0
  226. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/quad-colon.qmd +0 -0
  227. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/quad-diamond.qmd +0 -0
  228. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/quad-equal.qmd +0 -0
  229. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/quad-jot.qmd +0 -0
  230. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/quad.qmd +0 -0
  231. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/question.qmd +0 -0
  232. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/quote.qmd +0 -0
  233. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/radical.qmd +0 -0
  234. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/rho.qmd +0 -0
  235. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/right-arrow-from-bar.qmd +0 -0
  236. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/right-left-arrows.qmd +0 -0
  237. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/right-shoe.qmd +0 -0
  238. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/right-tack.qmd +0 -0
  239. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/right-tail-arrow.qmd +0 -0
  240. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/slash-bar.qmd +0 -0
  241. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/slash.qmd +0 -0
  242. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/squad.qmd +0 -0
  243. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/star-diaeresis.qmd +0 -0
  244. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/star.qmd +0 -0
  245. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/stile-tilde.qmd +0 -0
  246. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/stile.qmd +0 -0
  247. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/superscript-b.qmd +0 -0
  248. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/thorn.qmd +0 -0
  249. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/tilde-diaeresis.qmd +0 -0
  250. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/tilde.qmd +0 -0
  251. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/times.qmd +0 -0
  252. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/up-arrow.qmd +0 -0
  253. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/up-down-arrow.qmd +0 -0
  254. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/up-shoe.qmd +0 -0
  255. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/up-tack.qmd +0 -0
  256. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/vee-bar.qmd +0 -0
  257. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/vee.qmd +0 -0
  258. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/wedge-bar.qmd +0 -0
  259. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/wedge.qmd +0 -0
  260. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs/zilde.qmd +0 -0
  261. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs-study.qmd +0 -0
  262. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/glyphs.qmd +0 -0
  263. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/hanzi-notation-zh.ipynb +0 -0
  264. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/hanzi-notation.ipynb +0 -0
  265. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/hpl.xml +0 -0
  266. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/index.ipynb +0 -0
  267. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/indexing.ipynb +0 -0
  268. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/introspection.ipynb +0 -0
  269. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/keyboard.qmd +0 -0
  270. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/keyed.ipynb +0 -0
  271. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/magics.ipynb +0 -0
  272. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/modules.qmd +0 -0
  273. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/nbdev.yml +0 -0
  274. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/notebooks.ipynb +0 -0
  275. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/overview.ipynb +0 -0
  276. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/papers/aplwiki-arrays.md +0 -0
  277. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/papers/brickman-depth-1-scalars.md +0 -0
  278. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/papers/mercer-based-system.md +0 -0
  279. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/playground/bpl.js +0 -0
  280. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/playground/gallery.js +0 -0
  281. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/playground/hpl.tmLanguage.json +0 -0
  282. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/playground/monaco-worker.js +0 -0
  283. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/playground/page.js +0 -0
  284. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/playground/worker.js +0 -0
  285. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/playground.qmd +0 -0
  286. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/plot.ipynb +0 -0
  287. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/principles.ipynb +0 -0
  288. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/processes.qmd +0 -0
  289. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/puppy.jpg +0 -0
  290. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/regex.ipynb +0 -0
  291. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/repl.qmd +0 -0
  292. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/sidebar.yml +0 -0
  293. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/strings.ipynb +0 -0
  294. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/study/02_functions.ipynb +0 -0
  295. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/study/03_operators.ipynb +0 -0
  296. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/study/04_nested-arrays.ipynb +0 -0
  297. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/study/05_searching-indexing.ipynb +0 -0
  298. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/study/06_rearranging-arrays.ipynb +0 -0
  299. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/study/07_numerical-tools.ipynb +0 -0
  300. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/style.qmd +0 -0
  301. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/styles.css +0 -0
  302. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/_metadata.yml +0 -0
  303. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/c.qmd +0 -0
  304. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/canvas.qmd +0 -0
  305. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/constants.qmd +0 -0
  306. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/copy.qmd +0 -0
  307. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/csv.qmd +0 -0
  308. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/date.qmd +0 -0
  309. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/decompose.qmd +0 -0
  310. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/deflate.qmd +0 -0
  311. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/delay.qmd +0 -0
  312. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/detach.qmd +0 -0
  313. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/distribution.qmd +0 -0
  314. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/edge.qmd +0 -0
  315. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/element.qmd +0 -0
  316. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/ex.qmd +0 -0
  317. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/fetch.qmd +0 -0
  318. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/float.qmd +0 -0
  319. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/hash.qmd +0 -0
  320. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/host.qmd +0 -0
  321. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/image.qmd +0 -0
  322. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/index.qmd +0 -0
  323. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/js.qmd +0 -0
  324. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/json.qmd +0 -0
  325. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/literal.qmd +0 -0
  326. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/load.qmd +0 -0
  327. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/memory.qmd +0 -0
  328. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/metadata.qmd +0 -0
  329. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/mime.qmd +0 -0
  330. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/mkdir.qmd +0 -0
  331. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/nc.qmd +0 -0
  332. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/nget.qmd +0 -0
  333. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/nl.qmd +0 -0
  334. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/normalize.qmd +0 -0
  335. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/nput.qmd +0 -0
  336. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/path.qmd +0 -0
  337. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/plot.qmd +0 -0
  338. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/r.qmd +0 -0
  339. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/rand.qmd +0 -0
  340. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/readdir.qmd +0 -0
  341. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/remove.qmd +0 -0
  342. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/rename.qmd +0 -0
  343. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/signal.qmd +0 -0
  344. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/src.qmd +0 -0
  345. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/storage.qmd +0 -0
  346. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/svg.qmd +0 -0
  347. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/time.qmd +0 -0
  348. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/ucs.qmd +0 -0
  349. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/uuid.qmd +0 -0
  350. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/vfi.qmd +0 -0
  351. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system/xml.qmd +0 -0
  352. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/system-functions.qmd +0 -0
  353. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/terms.qmd +0 -0
  354. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/web.ipynb +0 -0
  355. {basedpl-0.1.71 → basedpl-0.1.73}/nbs/xml.ipynb +0 -0
  356. {basedpl-0.1.71 → basedpl-0.1.73}/package-lock.json +0 -0
  357. {basedpl-0.1.71 → basedpl-0.1.73}/package.json +0 -0
  358. {basedpl-0.1.71 → basedpl-0.1.73}/provenance/README.md +0 -0
  359. {basedpl-0.1.71 → basedpl-0.1.73}/provenance/aplcart.jsonl +0 -0
  360. {basedpl-0.1.71 → basedpl-0.1.73}/provenance/april.jsonl +0 -0
  361. {basedpl-0.1.71 → basedpl-0.1.73}/provenance/bqn.jsonl +0 -0
  362. {basedpl-0.1.71 → basedpl-0.1.73}/provenance/core.jsonl +0 -0
  363. {basedpl-0.1.71 → basedpl-0.1.73}/provenance/dyalog.jsonl +0 -0
  364. {basedpl-0.1.71 → basedpl-0.1.73}/provenance/ngn.jsonl +0 -0
  365. {basedpl-0.1.71 → basedpl-0.1.73}/py/Cargo.toml +0 -0
  366. {basedpl-0.1.71 → basedpl-0.1.73}/py/build.rs +0 -0
  367. {basedpl-0.1.71 → basedpl-0.1.73}/pyproject.toml +0 -0
  368. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/__init__.py +0 -0
  369. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/_modidx.py +0 -0
  370. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/bpl.tmLanguage.json +0 -0
  371. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/dyalog.py +0 -0
  372. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/editors.py +0 -0
  373. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/font.py +0 -0
  374. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/fonts.css +0 -0
  375. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/hpl.tmLanguage.json +0 -0
  376. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/input.js +0 -0
  377. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/ipython.py +0 -0
  378. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/keyboards.json +0 -0
  379. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/keyboards.py +0 -0
  380. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/layout.json +0 -0
  381. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/lb.js +0 -0
  382. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/notebook_runner.py +0 -0
  383. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/notebooks.py +0 -0
  384. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/reference.py +0 -0
  385. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/syntax.py +0 -0
  386. {basedpl-0.1.71 → basedpl-0.1.73}/python/basedpl/windows_keyboard.py +0 -0
  387. {basedpl-0.1.71 → basedpl-0.1.73}/rustfmt.toml +0 -0
  388. {basedpl-0.1.71 → basedpl-0.1.73}/scripts/install-macos.sh +0 -0
  389. {basedpl-0.1.71 → basedpl-0.1.73}/scripts/prep.py +0 -0
  390. {basedpl-0.1.71 → basedpl-0.1.73}/src/agreement.rs +0 -0
  391. {basedpl-0.1.71 → basedpl-0.1.73}/src/array/text.rs +0 -0
  392. {basedpl-0.1.71 → basedpl-0.1.73}/src/canvas.js +0 -0
  393. {basedpl-0.1.71 → basedpl-0.1.73}/src/canvas.rs +0 -0
  394. {basedpl-0.1.71 → basedpl-0.1.73}/src/csv.rs +0 -0
  395. {basedpl-0.1.71 → basedpl-0.1.73}/src/data.rs +0 -0
  396. {basedpl-0.1.71 → basedpl-0.1.73}/src/date.rs +0 -0
  397. {basedpl-0.1.71 → basedpl-0.1.73}/src/display.rs +0 -0
  398. {basedpl-0.1.71 → basedpl-0.1.73}/src/error.rs +0 -0
  399. {basedpl-0.1.71 → basedpl-0.1.73}/src/eval/bindings.rs +0 -0
  400. {basedpl-0.1.71 → basedpl-0.1.73}/src/eval/dissect.rs +0 -0
  401. {basedpl-0.1.71 → basedpl-0.1.73}/src/execution.rs +0 -0
  402. {basedpl-0.1.71 → basedpl-0.1.73}/src/explain.rs +0 -0
  403. {basedpl-0.1.71 → basedpl-0.1.73}/src/files.rs +0 -0
  404. {basedpl-0.1.71 → basedpl-0.1.73}/src/fusion/blocks.rs +0 -0
  405. {basedpl-0.1.71 → basedpl-0.1.73}/src/host.rs +0 -0
  406. {basedpl-0.1.71 → basedpl-0.1.73}/src/host_web.rs +0 -0
  407. {basedpl-0.1.71 → basedpl-0.1.73}/src/image/codecs.rs +0 -0
  408. {basedpl-0.1.71 → basedpl-0.1.73}/src/image/imageio.rs +0 -0
  409. {basedpl-0.1.71 → basedpl-0.1.73}/src/image.rs +0 -0
  410. {basedpl-0.1.71 → basedpl-0.1.73}/src/inspection.rs +0 -0
  411. {basedpl-0.1.71 → basedpl-0.1.73}/src/js.rs +0 -0
  412. {basedpl-0.1.71 → basedpl-0.1.73}/src/json.rs +0 -0
  413. {basedpl-0.1.71 → basedpl-0.1.73}/src/keyed.rs +0 -0
  414. {basedpl-0.1.71 → basedpl-0.1.73}/src/lib.rs +0 -0
  415. {basedpl-0.1.71 → basedpl-0.1.73}/src/name.rs +0 -0
  416. {basedpl-0.1.71 → basedpl-0.1.73}/src/number_theory.rs +0 -0
  417. {basedpl-0.1.71 → basedpl-0.1.73}/src/optimize.rs +0 -0
  418. {basedpl-0.1.71 → basedpl-0.1.73}/src/plot.rs +0 -0
  419. {basedpl-0.1.71 → basedpl-0.1.73}/src/polynomial.rs +0 -0
  420. {basedpl-0.1.71 → basedpl-0.1.73}/src/protocol.rs +0 -0
  421. {basedpl-0.1.71 → basedpl-0.1.73}/src/reference.rs +0 -0
  422. {basedpl-0.1.71 → basedpl-0.1.73}/src/regex.rs +0 -0
  423. {basedpl-0.1.71 → basedpl-0.1.73}/src/settings.rs +0 -0
  424. {basedpl-0.1.71 → basedpl-0.1.73}/src/symbols.rs +0 -0
  425. {basedpl-0.1.71 → basedpl-0.1.73}/src/system.rs +0 -0
  426. {basedpl-0.1.71 → basedpl-0.1.73}/src/xml.rs +0 -0
  427. {basedpl-0.1.71 → basedpl-0.1.73}/tests/common/mod.rs +0 -0
  428. {basedpl-0.1.71 → basedpl-0.1.73}/tests/conftest.py +0 -0
  429. {basedpl-0.1.71 → basedpl-0.1.73}/tests/core.rs +0 -0
  430. {basedpl-0.1.71 → basedpl-0.1.73}/tests/derivatives.rs +0 -0
  431. {basedpl-0.1.71 → basedpl-0.1.73}/tests/explain.rs +0 -0
  432. {basedpl-0.1.71 → basedpl-0.1.73}/tests/highlighting.mjs +0 -0
  433. {basedpl-0.1.71 → basedpl-0.1.73}/tests/input.mjs +0 -0
  434. {basedpl-0.1.71 → basedpl-0.1.73}/tests/instructions.txt +0 -0
  435. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/LICENSE-aplcart +0 -0
  436. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/LICENSE-april +0 -0
  437. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/LICENSE-bqn +0 -0
  438. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/LICENSE-bqncrate +0 -0
  439. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/LICENSE-dyalog +0 -0
  440. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/LICENSE-ngn +0 -0
  441. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/README.md +0 -0
  442. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/aplcart.bpl +0 -0
  443. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/april.bpl +0 -0
  444. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/bqn.bpl +0 -0
  445. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/dyalog.bpl +0 -0
  446. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/graphics.bpl +0 -0
  447. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/lib.bpl +0 -0
  448. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/ngn.bpl +0 -0
  449. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/regex.bpl +0 -0
  450. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/static-int32.bpl +0 -0
  451. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/static.bpl +0 -0
  452. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/support/april.bpl +0 -0
  453. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/support/avl.bpl +0 -0
  454. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/support/redblack.bpl +0 -0
  455. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/support/sbst.bpl +0 -0
  456. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference/support/splay.bpl +0 -0
  457. {basedpl-0.1.71 → basedpl-0.1.73}/tests/reference.rs +0 -0
  458. {basedpl-0.1.71 → basedpl-0.1.73}/tests/scaling.rs +0 -0
  459. {basedpl-0.1.71 → basedpl-0.1.73}/tests/test_api.py +0 -0
  460. {basedpl-0.1.71 → basedpl-0.1.73}/tests/test_bpltests.py +0 -0
  461. {basedpl-0.1.71 → basedpl-0.1.73}/tests/test_glyphs.py +0 -0
  462. {basedpl-0.1.71 → basedpl-0.1.73}/tests/test_graphics.py +0 -0
  463. {basedpl-0.1.71 → basedpl-0.1.73}/tests/test_instructions.py +0 -0
  464. {basedpl-0.1.71 → basedpl-0.1.73}/tests/test_ipython.py +0 -0
  465. {basedpl-0.1.71 → basedpl-0.1.73}/tests/test_kernel.py +0 -0
  466. {basedpl-0.1.71 → basedpl-0.1.73}/tests/test_keylayout.py +0 -0
  467. {basedpl-0.1.71 → basedpl-0.1.73}/tests/test_notebooks.py +0 -0
  468. {basedpl-0.1.71 → basedpl-0.1.73}/tests/test_reference.py +0 -0
  469. {basedpl-0.1.71 → basedpl-0.1.73}/tests/test_repl.py +0 -0
  470. {basedpl-0.1.71 → basedpl-0.1.73}/tests/test_windows_keyboard.py +0 -0
  471. {basedpl-0.1.71 → basedpl-0.1.73}/tests/test_worker.py +0 -0
  472. {basedpl-0.1.71 → basedpl-0.1.73}/tests/units.rs +0 -0
  473. {basedpl-0.1.71 → basedpl-0.1.73}/tests/wasm-pkg.mjs +0 -0
  474. {basedpl-0.1.71 → basedpl-0.1.73}/tests/wasm-speed.mjs +0 -0
  475. {basedpl-0.1.71 → basedpl-0.1.73}/tests/windows_keyboard.c +0 -0
  476. {basedpl-0.1.71 → basedpl-0.1.73}/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.73"
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.73"
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.73"
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.73"
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.48"
1417
1417
  source = "registry+https://github.com/rust-lang/crates.io-index"
1418
- checksum = "539dbd536cc6c64e9080a2c0bc346b6cf2f5308f0e29f814bfefd244bce87d07"
1418
+ checksum = "3ed381a5dbc0b48b7077c4d510027b240e1067af82bcc5c964ade2c319839499"
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.48"
1438
1438
  source = "registry+https://github.com/rust-lang/crates.io-index"
1439
- checksum = "1b3f549d927a69037ffe1ec3d11a318d89bbb115ac26c071d19150207e62a811"
1439
+ checksum = "8614c8bc25045617899784d0fa952f3137835030bcbb9f77359e1c530fd75c4b"
1440
1440
  dependencies = [
1441
1441
  "pyo3",
1442
1442
  "rustymath",
@@ -1581,9 +1581,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
1581
1581
 
1582
1582
  [[package]]
1583
1583
  name = "smallvec"
1584
- version = "1.16.3"
1584
+ version = "1.16.4"
1585
1585
  source = "registry+https://github.com/rust-lang/crates.io-index"
1586
- checksum = "5b3dc8af474f516a851ff4bd12db780f948b9250ad37211e4eec0bccea54e01b"
1586
+ checksum = "d0d5d4b1981b8bbbb7aed204cae5726d683d5d6ac7e74ec54122ea28f315e7c8"
1587
1587
 
1588
1588
  [[package]]
1589
1589
  name = "socket2"
@@ -1814,9 +1814,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
1814
1814
 
1815
1815
  [[package]]
1816
1816
  name = "uuid"
1817
- version = "1.28.0"
1817
+ version = "1.29.0"
1818
1818
  source = "registry+https://github.com/rust-lang/crates.io-index"
1819
- checksum = "7cc1186384beb7dd8eedea376413fd654937285ea6c9cfbb928dc3043ea4b606"
1819
+ checksum = "4a0e2d11620c50695fe12bbbfde96b3477fe606e7284c22d505c12ce51214514"
1820
1820
  dependencies = [
1821
1821
  "atomic",
1822
1822
  "getrandom",
@@ -2086,7 +2086,7 @@ checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc"
2086
2086
 
2087
2087
  [[package]]
2088
2088
  name = "xtask"
2089
- version = "0.1.71"
2089
+ version = "0.1.73"
2090
2090
  dependencies = [
2091
2091
  "anyhow",
2092
2092
  "rustymath",
@@ -5,14 +5,14 @@ members = ["py"]
5
5
  join_comments = true
6
6
 
7
7
  [workspace.package]
8
- version = "0.1.71"
8
+ version = "0.1.73"
9
9
  edition = "2024"
10
10
  rust-version = "1.98"
11
11
  license = "Apache-2.0"
12
12
 
13
13
  [workspace.dependencies]
14
- rustymath = { version = ">=0.1.44, <1", default-features = false }
15
- rustymath-buffer = ">=0.1.44, <1"
14
+ rustymath = { version = ">=0.1.48, <1", default-features = false }
15
+ rustymath-buffer = ">=0.1.48, <1"
16
16
  pyo3 = ">=0.29.2, <1"
17
17
  pyo3-build-config = ">=0.29.2, <1"
18
18
 
@@ -18,7 +18,7 @@ cargo test
18
18
  pytest -q
19
19
  ```
20
20
 
21
- Use `cargo develop` to rebuild and install the native extension and `bpl` after Rust changes. It uses the `test` profile shared with `cargo test`. Cargo tests compile missing code but don't install it. Run plain `cargo test` while you work; use one test binary for a focused check. Run `pytest -q` at the end of a piece of work. Before you report a `pytest` failure in code you didn't touch, run `cargo develop` and rerun it. Give builds three minutes and test runs one minute; Cargo serializes builds in the same target directory.
21
+ Use `cargo develop` to rebuild and install the native extension and `bpl` after Rust changes. It uses the `test` profile shared with `cargo test`. Cargo tests compile missing code but don't install it. Run plain `cargo test` while you work; use one test binary for a focused check. From a kernel, `fastws.cargo.run_tests(root, *args)` runs `cargo test` and returns the build's compiler messages and each test binary's results. Run `pytest -q` at the end of a piece of work. Before you report a `pytest` failure in code you didn't touch, run `cargo develop` and rerun it. Give builds three minutes and test runs one minute; Cargo serializes builds in the same target directory.
22
22
 
23
23
  Build nothing else without discussion: no scratch crates, alternate target directories, `--release`, `-p` or other-target builds. The documented build diagnostics, browser work and x86-64 inspection below are exceptions. Don't use `maturin develop`; its configuration does not reuse the normal local build.
24
24
 
@@ -26,7 +26,7 @@ When another agent's unfinished edits stop the shared tree compiling, run `cargo
26
26
 
27
27
  An already-running Python process retains its loaded extension. In a kernel, use `from basedpl.worker import fresh; fresh(code)` to check the installed `bpl` in a fresh worker instead of restarting the kernel. A BPL error raises `BplError`. `fresh(code, bpl=PATH)` runs a saved copy of `bpl`, such as the baseline described below. Check one expression and read its result before building on it. `basedpl.bpltests.check_file` and `check_page` check reference files and documentation through the worker without building Rust. With `bpl=PATH`, they check a saved copy without installing it.
28
28
 
29
- Measure with `BASEDPL_COSTS=1 cargo test --test speed` or `basedpl.bpltests.time_cases(cases)`. Both count costs in copies. A copy is the time to write as many floats as the data has items, each negated, into a second buffer. `rustymath::timing::COPIES` stores the copy time of each machine that runs the speed tests, by its CPU, the item's size and the number of items, at the slower end of what that copy normally takes, for copies whose source and destination fit in cache, 64 MiB together (`CACHED_BYTES`). A copy timed beside each case varied more than 3 times on CI's runner, where the functions' own times didn't, so stored times keep that noise out of every cost. A larger copy runs at the speed of memory, which a shared runner varies by up to 2 times between runs, and the cases of that size vary with it. The test measures such a copy once in each run. It also measures a cached size with no entry once, and prints a line to add to `COPIES`. The browser build has entries of its own, for its copy under the JavaScript engine. It can't read the CPU's name, and `tests/wasm-pkg.mjs` passes it the name that Node reads. Each case's line in a log ends with its time for each item, which `logged_costs` keeps in each row, and the log has a copy line for each size of data, which it reads into its result's `copies`. Budgets are single-thread measurements. `thread_scaling()` checks multithreaded speed: it times a large product, a 512×512 SVD and Hermitian eigendecomposition, a stack of QR decompositions and a large elementwise function on one thread and on the machine's cores, and fails when one speeds up less than 1.5 times. Accelerate's GESDD and SYEVD run on one thread whatever its threading setting. On macOS, where Accelerate computes the product, the SVD and the Hermitian eigendecomposition, those three cases need only the speedups in `_ACCELERATED_LEAST`. The manual `Speed` workflow runs it. `speed_costs()` reads the cases in `tests/speed.txt`. `cases=` selects expressions, `wasm=DIR` selects a browser build, `bpl=PATH` selects another native `bpl`, such as a saved copy, and `native=True` times rustymath's own linear algebra, which dev builds compile in. `logged_costs(log)` reads CI output from its text or a file. `cargo_costs(path)` runs either project's Rust speed test, and `pytest_costs(path)` runs rustymath's Python speed test.
29
+ Measure with `BASEDPL_COSTS=1 cargo test --test speed` or `basedpl.bpltests.time_cases(cases)`. Both count costs in copies. A copy is the time to write as many floats as the data has items, each negated, into a second buffer. `rustymath::timing::COPIES` stores the copy time of each machine that runs the speed tests, by its CPU, the item's size and the number of items, at the slower end of what that copy normally takes, for copies whose source and destination fit in cache, 64 MiB together (`CACHED_BYTES`). A copy timed beside each case varied more than 3 times on CI's runner, where the functions' own times didn't, so stored times keep that noise out of every cost. A larger copy runs at the speed of memory, which a shared runner varies by up to 2 times between runs, and the cases of that size vary with it. The test measures such a copy once in each run. It also measures a cached size with no entry once, and prints a line to add to `COPIES`. The browser build has entries of its own, for its copy under the JavaScript engine. It can't read the CPU's name, and `tests/wasm-pkg.mjs` passes it the name that Node reads. Each case's line in a log ends with its time for each item, which `logged_costs` keeps in each row, and the log has a copy line for each size of data, which it reads into its result's `copies`. Budgets are single-thread measurements. `thread_scaling()` checks multithreaded speed: it times a large product, a 512×512 SVD and Hermitian eigendecomposition, a stack of QR decompositions and a large elementwise function on one thread and on the machine's cores, and fails when one speeds up less than 1.5 times. Accelerate's GESDD and SYEVD run on one thread whatever its threading setting. On macOS, where Accelerate computes the product, the SVD and the Hermitian eigendecomposition, those three cases need only the speedups in `_ACCELERATED_LEAST`. The manual `Speed` workflow runs it. `speed_costs()` reads the cases in `tests/speed.txt`. `cases=` selects expressions, `wasm=DIR` selects a browser build, `bpl=PATH` selects another native `bpl`, such as a saved copy, `native=True` times rustymath's own linear algebra, which dev builds compile in, and `prefs=` runs BPL before each section's header, such as `•prefs ["kinds":"static"]`. `logged_costs(log)` reads CI output from its text or a file. `cargo_costs(path)` runs either project's Rust speed test, and `pytest_costs(path)` runs rustymath's Python speed test.
30
30
 
31
31
  Costs in copies can't show a per-call change of a few percent, because code layout alone moves a timing by more than that. `instructions(cases)` counts instructions, which load and layout don't change. Each case is an expression, such as `k(⌈/⊢)⌸a`, run once per step inside `{case ⋄ ⍵}⍣N⊢0`. That dfn's own call adds about 1,900 instructions a step. A case that names `N` makes its own calls instead, such as `{⍵}⍣N⊢0`, which makes one dfn call a step. Such a case must make one call per step: a map such as `f¨N⍴0` calls a dfn once on all its cells, so it gives no per-call cost. It runs fresh single-threaded `bpl` processes at four values of `N`. For each pair of successive values, it divides the difference in instructions retired by the difference in `N`, which cancels startup and `setup=`, and it reports the median of those three slopes. The median drops a one-off cost that starts once `N` passes some size, because such a cost falls between only one pair. `≢•ucs N⍴"ab" "cde"` has one: it retires about 5×10⁶ more instructions from about 131,350 items on. Every value of `N` lies past the warm-up, from a rough count at 1,000 steps, because a case that allocates an array at each step retires extra instructions over its first steps while the allocator settles. Each process pays a different warm-up, up to about 5×10⁶ instructions, so successive values of `N` lie 5×10⁸ instructions apart, where that difference moves a slope by under 1%. `counts=` sets two or more values instead. It reads `/usr/bin/time -l` on macOS and `perf stat` on Linux, and `bpl=PATH` counts a saved copy. A case whose result stays pending, such as large windows or a transpose, counts making the pending copy, not the copy: `3↕v` retires about 12,000 instructions a step. `force=True` computes each step's result in full, through an indexed write, for any result of rank 1 or more: `3↕v` then counts the copy itself, about 9 million instructions a step. A join computes at once and needs no `force`.
32
32
 
@@ -34,7 +34,7 @@ Costs in copies can't show a per-call change of a few percent, because code layo
34
34
 
35
35
  `profile(case)` shows where a case's instructions go, by function, on macOS. It takes a case, and `force=`, as `instructions` does. A fresh process repeats the case on one thread while `sample` counts how often each function is at the top of the main thread's stack. A function's share of those samples, times the build's count from `instructions`, estimates its instructions per step. The estimate assumes every function retires instructions at the same rate. When a count moves, `profile_diff(case, base)` shows which functions moved it, from those estimates for both builds. A function that one build inlines and the other calls out of line appears under one build alone. Run them before reading machine code. `base` is a saved copy, and `bpl=PATH` sets the build to profile, the installed one by default.
36
36
 
37
- `bpl-tests NAME ARGUMENT...` runs one of these functions from the shell and prints its result: `check_file`, `check_page`, `time_cases`, `instructions`, `instruction_budgets`, `profile`, `profile_diff`, `speed_costs`, `thread_scaling`, `cargo_costs`, `pytest_costs`, `compare_costs` or `wasm_test`. Run long checks and timings this way, not in the shared kernel, which runs one cell at a time for every agent. For example, `bpl-tests time_cases '+/v' --threads 4` times `+/v` on four threads. `time_cases`, `instructions` and `speed_costs` take cases as positional arguments. When a case starts with `-`, put the cases last, after `--`, as in `bpl-tests speed_costs -- '-.×m' '+/v'`. `bpl-tests NAME -h` lists a function's arguments.
37
+ `bpl-tests NAME ARGUMENT...` runs one of these functions from the shell and prints its result: `check_file`, `check_page`, `time_cases`, `instructions`, `instruction_budgets`, `profile`, `profile_diff`, `disasm`, `speed_costs`, `thread_scaling`, `cargo_costs`, `pytest_costs`, `compare_costs` or `wasm_test`. For example, `bpl-tests time_cases '+/v' --threads 4` times `+/v` on four threads. `time_cases`, `instructions` and `speed_costs` take cases as positional arguments. When a case starts with `-`, put the cases last, after `--`, as in `bpl-tests speed_costs -- '-.×m' '+/v'`. `bpl-tests NAME -h` lists a function's arguments. Called in a kernel, the same functions return Python objects, such as the rows that `compare_costs` reads.
38
38
 
39
39
  On each push, the `Test` workflow logs every native cost in its `test` job and every wasm cost in its `wasm` job. The speed test that writes them times the test-profile build that the budgets limit. `bpl --costs FILE` times the cases in a file in `speed.txt`'s format as the speed test does, and prints each cost with this machine's budget, without failing on a budget. The manual `Speed` workflow runs it on a `dist` build, the profile releases use, on CI's runner, beside its wasm timing. The `Release` workflow runs it on each binary it builds, on GitHub's runners. Their logs show what releases cost, for comparison with the `Test` workflow's. `logged_costs` reads all three workflows' logs. When you review a run, look for costs over their budgets and for costs that changed by more than 20% since the run before. `compare_costs(before, after)` lists both, from two runs' logs or from the rows that `speed_costs` and the other timing functions give. It measures each change on times per item where both runs give them, so a change to `COPIES` doesn't show as one. Every log names its CPU in its copy lines. Study a slowdown until you know its cause only when it appears in more than one CI run, or when two or more similar cases slow by similar amounts. Treat any other slowdown as normal variation.
40
40
 
@@ -44,23 +44,17 @@ An initial budget is twice what a first-principles analysis says the case should
44
44
 
45
45
  The speed tests and the scaling test time each failing case again after the rest, after each pause in `rustymath::timing::RETRY_PAUSES`, and fail only for a case that fails every time. Each retry prints the case's earlier and new costs, even in a passing run. `logged_costs` keeps a retried case's lowest cost. Study a case that needs a retry in most runs, as you would a slowdown.
46
46
 
47
- For a change meant to make something faster, or a change to code that every call goes through, time the cases it affects before and after the change. Before your first `cargo develop`, copy the installed `bpl` in the kernel with `shutil.copy(basedpl.worker.INSTALLED_BPL, '/tmp/<prefix>_bpl')`. Time that copy with `bpl='/tmp/<prefix>_bpl'`, and your build with the default. Another agent's `cargo develop` can replace the installed `bpl` at any time. The copy keeps your baseline fixed while agents build in parallel. Compare the two builds' times per item, which `time_cases` prints in picoseconds. A build from before a change to `rustymath::timing::COPIES` divides its costs by a different copy. On this Mac, a fused case over a large input can cost up to about 15% more in one process than in another, depending on whether `malloc` starts the input on a 32 KB boundary, where every one of a graph's blocks then ends. Time both builds the same way, each alone in a fresh process or at the same place in one run, and alternate them before you read a lone difference of that size as a regression. The speed test fails a case only past its budget. It misses any smaller slowdown. Other changes need only the speed test. Don't restore old code in the shared tree to get a baseline. On macOS, native timings of matrix products and decompositions mostly measure Accelerate. Rustymath's DEV.md says how to time rustymath's own kernels.
47
+ For a change meant to make something faster, or a change to code that every call goes through, time the cases it affects before and after the change. Before your first `cargo develop`, copy the installed `bpl`. In a kernel, run `shutil.copy(basedpl.worker.INSTALLED_BPL, '/tmp/<prefix>_bpl')`. In the shell, run `cp "$(command -v bpl)" /tmp/<prefix>_bpl`: the installed `bpl` is the one on the venv's `PATH`. Time that copy with `bpl='/tmp/<prefix>_bpl'`, and your build with the default. Another agent's `cargo develop` can replace the installed `bpl` at any time. The copy keeps your baseline fixed while agents build in parallel. Compare the two builds' times per item, which `time_cases` prints in picoseconds. A build from before a change to `rustymath::timing::COPIES` divides its costs by a different copy. On this Mac, a fused case over a large input can cost up to about 15% more in one process than in another, depending on whether `malloc` starts the input on a 32 KB boundary, where every one of a graph's blocks then ends. Time both builds the same way, each alone in a fresh process or at the same place in one run, and alternate them before you read a lone difference of that size as a regression. The speed test fails a case only past its budget. It misses any smaller slowdown. Other changes need only the speed test. Don't restore old code in the shared tree to get a baseline. On macOS, native timings of matrix products and decompositions mostly measure Accelerate. Rustymath's DEV.md says how to time rustymath's own kernels.
48
48
 
49
- Cooperating tools share the machine's timing lock, `/tmp/aai-ws-timing.lock`. Timings take it exclusively. `cargo develop`, `cargo wait`, `cargo wasm`, the reference test, pytest, `check_file`, `check_page`, `bpl-nb` and `wasm_test` without `speed` take it shared. Rust code takes it through `rustymath::timing`. Python code takes it with `fastws.cargo.timing_lock`. Node can't lock a file. `wasm_test` and `speed_costs(wasm=DIR)` hold the lock in Python while Node runs. Other Rust tests and bare Cargo commands do not all take it. After five minutes a timing fails. A build or test run then goes ahead without the lock. After 30 seconds, an exclusive wait prints the processes with the lock file open. The list can include processes that are only waiting for the lock. Never take the lock yourself in the shared kernel process. Never coordinate timings by hand. A hold that outlasts its call blocks the timings that later calls launch. Each such call stalls every other agent's kernel calls while it waits. Native timings run on one thread and request user-interactive macOS QoS, which favours the performance cores. QoS is not CPU affinity.
49
+ Cooperating tools share the machine's timing lock, `/tmp/aai-ws-timing.lock`. Timings take it exclusively. `cargo develop`, `cargo wait`, `cargo wasm`, the reference test, pytest, `check_file`, `check_page`, `bpl-nb` and `wasm_test` without `speed` take it shared. Rust code takes it through `rustymath::timing`. Python code takes it with `fastws.cargo.timing_lock`. Node can't lock a file. `wasm_test` and `speed_costs(wasm=DIR)` hold the lock in Python while Node runs. Other Rust tests and bare Cargo commands do not all take it. After five minutes a timing fails. A build or test run then goes ahead without the lock. After 30 seconds, an exclusive wait prints the processes with the lock file open. The list can include processes that are only waiting for the lock. Never take the lock yourself in a kernel process. Never coordinate timings by hand. A hold that outlasts its call blocks the timings that later calls launch. Native timings run on one thread and request user-interactive macOS QoS, which favours the performance cores. QoS is not CPU affinity.
50
50
 
51
51
  Run `cargo wasm` during development only for browser work. Agents use `cargo wasm --out DIR`, then run the browser tests against that build with `basedpl.bpltests.wasm_test(DIR)` for `tests/wasm.mjs` and `wasm_test(DIR, speed=True)` for `tests/wasm-speed.mjs`. That speed test fails on a wasm budget only on Linux x86-64, CI's platform. On any other host it prints every cost and marks each case still over its budget after the retries, as `bpl --costs` does. This avoids replacing a module another agent is using. For other edits under `cfg(web)` or `host_web.rs`, check compilation with `cargo cs -p basedpl-wasm --target wasm32-unknown-unknown`, which checks the browser wrapper crate together with basedpl's browser code. `cargo cs` alone compiles neither.
52
52
 
53
- ### X86-64 machine code
53
+ ### Machine code
54
54
 
55
- To inspect the x86-64 code that CI and Linux run, build the library for Linux x86-64. In basedpl:
55
+ `bpl-tests disasm PATTERN` shows the machine code of the function whose demangled name matches the regex `PATTERN`, read from the installed `bpl` with `objdump`. `--bpl PATH` reads a saved copy instead. Where several functions match, it lists their names. A function that is always inlined has no code of its own. Read its callers instead.
56
56
 
57
- ```bash
58
- CARGO_INCREMENTAL=0 CC_x86_64_unknown_linux_gnu=clang cargo build --lib --release --target x86_64-unknown-linux-gnu --target-dir /tmp/aai-ws-x86 -p basedpl
59
- ```
60
-
61
- In rustymath, use `-p rustymath`. The target is Linux because macOS builds leave out rustymath's native linear algebra kernels. That target is installed here. `-p` builds only the library, because the Python extension crates can't be built for Linux on this Mac. `CC_x86_64_unknown_linux_gnu=clang` lets Apple's `clang` assemble the x86-64 source in basedpl's `psm` dependency, because this Mac has no `x86_64-linux-gnu-gcc`. Don't move that setting into `.cargo/config.toml`. CI's Linux release builds also read that file, and their manylinux container has no `clang`. The build matches CI's `test` profile in its x86-64 flags and optimization settings. CI turns off the profile's incremental compilation with `CARGO_INCREMENTAL=0`. The command does the same, to split code into compilation units as CI does. Run it only to answer an x86-code question. It doesn't take the timing lock and can disturb timings running alongside it.
62
-
63
- Read the newest `lib<crate>-<hash>.rlib` under `/tmp/aai-ws-x86/x86_64-unknown-linux-gnu/release/deps` with `objdump -d -r --no-show-raw-insn --disassemble-symbols=NAME`. `-r` identifies called functions. `objdump` warns for each archive object without that symbol. `-C` matches demangled names but splits them at commas; for a generic name containing a comma, get its mangled name from `nm` and omit `-C`. Generic code belongs to the crate that instantiates it. Don't use `--emit asm`: the resulting codegen-unit arrangement can inline differently from the build being inspected.
57
+ `--x86` shows the x86-64 code that CI and Linux run. It first builds basedpl's library and the rustymath library it links for Linux x86-64, into `/tmp/aai-ws-x86`, holding the timing lock shared. Where an unfinished edit stops basedpl compiling, it reads rustymath's library alone, and its output says so first. After a change, that build takes minutes. Use it only to answer an x86-code question. The target is Linux because macOS builds leave out rustymath's native linear algebra kernels. Only the libraries build, because the Python extension crates can't be built for Linux on this Mac. Their `release` profile matches CI's `test` profile in its x86-64 flags and optimization settings. The build sets `CC_x86_64_unknown_linux_gnu=clang` for itself. Don't move that setting into `.cargo/config.toml`. CI's Linux release builds also read that file, in a manylinux container that has no `clang`. Don't use `--emit asm`. A build with it splits code into other codegen units and inlines differently.
64
58
 
65
59
  ## Workspace, builds and CI
66
60
 
@@ -184,9 +178,9 @@ Bare numbers, empty literals and NaN use the parsed float width. Top-level `eval
184
178
 
185
179
  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
180
 
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.
181
+ 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
182
 
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.
183
+ 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`. Comparisons, `⌈ ⌊` and bitwise functions compute at their arguments' storage width instead, where their results are the same at every width (`pervasive::first_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
184
 
191
185
  Settings live once for the whole process, in `settings.rs`, and are read from there, not passed through functions, except where a read is slow and on a hot path. Each setting that calls and scalar operations read is an atomic: the numeric settings, the hanzi aliases, the `batch` pref, the fusion report flag and fusion's small sizes. The display settings sit behind one lock. `•prefs` writes them, the lexer writes a source's leading `•prefs` header as it reads it, and `settings::reset` restores the defaults, as `]clear` and the test harnesses do. Nothing copies, captures or restores a setting. A pending array computes under the settings in force when it computes, and a module that `•load` runs changes the settings for the whole process. Rustymath holds the thread count, the one setting that it reads itself, and `•prefs` writes it there. Each call reads the store once where it starts: `pervasive::halves`, which every `pervasive` entry point goes through, `fusion::defers` and `defer`, `Domain::of`, the lexer and `Storage::item`'s complex items. Values derived from the settings within a call stay explicit arguments. `halves` passes 16-bit floats' widened settings to its inner call. The loop structs keep them because their closures run on rustymath's worker threads. A fused graph reads the settings once when it's built at forcing, for the same reason. `Number`'s tolerance methods and `Primitive::number` take them because they run once per item. The parser's leaves take a width marker's width, and `matches_within` takes `⍣∞`'s convergence tolerance. Imports build complex numbers with `Number::complex_in_session`: Python's `_Session.array` and the JSON protocol's `request`. JavaScript values hold no complex numbers.
192
186
 
@@ -222,7 +216,7 @@ Ordinary pervasive kernels also read pending copies through their maps. `fusion:
222
216
 
223
217
  `derivative.rs` implements `∂`. A dual is a tag, a primal and a tangent: a `transform::Carrier`, held in `Value::Carried` for a number and in `Data::Carried` for an array, whose primal and tangent can be pending. A record of linear calls is the other kind of carrier. Routing (`transform::call`) hands a call to the newest level among its arguments, as `Value::newest` finds it. It reads their outer layer, but a newer level inside an argument held in mixed storage wins, as an array of dual atoms beside an older dual shows. A call whose newest level is a `∂` call goes to `derivative::call`, which reads how to run it from the form's facts in `Primitive::info()` (`primitive::Facts`). It applies the partials table to pervasive forms and its own rule to `⌻`, and calls forms whose results carry no tangent on the primals. Structural glyphs, Under and selective assignment need no rules. Their own code moves each part of a carried array through the carrier's moves: `Carrier::view`, `Carrier::at`, `Carrier::copied`, and `transform::written` for writes, which a record answers through its ids. `Gather` copies a dual's primal and tangent together through `derivative::Join`. A glyph that copies its right argument through one plan, and a broadcast, copy a record tangent as one `Op::Copy` of the plan's `Steps` (`primitive::copied`, and `Form::Moves`'s `planned`). Its transpose reads through rustymath's `Steps::transposed`: the inverse map for a copy that reads each item at most once, and a correlation for windows that move by 1. A copy of a copy transposes in one read where the composed copy still transposes by reads (`linear::composed`). The record keeps the chain, because recognising windows needs each copy's own shape. A sum along a window's axis transposes as a sliding sum (`linear::slide`), and a spread axis as a sum along it. Windows that move by more than 1 transpose by rustymath's `signal::overlap_add`, which adds each window back where it read (`linear::strided_back`). Other copies, and copies of several sources, keep ids and scatter. `•explain` lists each scatter as an accumulation. In reverse mode, the rule for a `⌈` or `⌊` fold is a sum of the tangent times a mask of each lane's chosen item. Its transpose reads. Mix of a dual whose primal is nested mixes the primal and the tangent apart. `fold` and scans with `+`, `×`, `⌈` and `⌊`, `+.×` and outer products have rules, and kernels that read numbers directly leave active arguments to their general paths. Folds by primitives, products of primitives, `⌹`, `⊥` and stacks of matrices route through `transform::call` as operations (`primitive::Operation`), so their rules (`derivative::solve`, `decode`, `product_dual`, `determinant` and `fold_dual`) run on a `&Context` and call `Operation::call` for the products, folds and inverses that they need. Rank's routes for whole arguments send stacks that a level carries through `Pairing::Matrices`, so `⌹⍤2`, `+.×⍤2` and `-.×⍤2` take their stacked rules in one call, with the `batch` pref on or off. Attached rules, system functions, and folds and products by functions that aren't primitives route through the same `transform::call`, as `transform::Op`'s other variants. The rules for `⌹` and `-.×` keep the glyph's own result as the primal, so that a function computes the same values with or without `∂`. Their tangents and transposes multiply by `R`, the inverse that `numeric::matrix_inverse` takes from one factorization through rustymath's `Stacked::inverse`, or by exact row reduction for exact matrices. `regular_inverse` gives UNSUPPORTED where rustymath's regularity test finds the matrix singular. With only `B` active, `R` is `⌹A`, a pseudoinverse included. With one number in `x`, `f∂ x` runs `f` once with `x` seeded along it. With more, `linearized` pushes a record level just below its `∂` call's level, then runs `f` once with each part of `x` seeded with a record at that level, from `linear.rs`: a tangent whose items are never computed, which the same rules extend into a graph of linear calls. A call whose newest level is a record level records the linear map that its form's facts name (`linear::call`). `reverse` then reads the Jacobian from the record, by a transpose for each result item or a forward evaluation for each number of `x`, whichever are fewer. A function with a JVP rule that `f∂←g` attached calls the rule with `⍺` a dual of zeros whose tangent is the argument's, so in reverse mode the rule extends the record too (`derivative::attached`). A call of such a function with two arguments gives DOMAIN ERROR wherever `∂` needs a derivative through it (`derivative::two_arguments`). Code that reads a dual array's storage gets its items as dual atoms, which is correct at per-item speed. A rule packs an array that holds its level's duals, at any depth, into one dual before it splits the array (`derivative::packed`). A reader outside a call sees a value through `transform.rs`'s read point. `Value::observed`, which counts, positions, ranks, selectors, `≡` and guards' predicates use, reads a dual's primal. The integer readers of `Items` read carried items through it (`Value::observed_number`), so a count or position that `∂` carries reads its primal. It returns a `Result` whose error, `transform::Stop`, names the level that owns a batched run. A stop is `ErrorKind::Stop`, which no guard catches, even one that names it, and which a handler that catches every error lets pass (`ErrorKind::is_control`). Display reads through `Value::displayed`, because it never runs inside a batched run. `Value::computed`, which kernels use through `primitive::numeric`, gives UNSUPPORTED for a dual atom. Writes to bindings outside a `∂` call are recorded and stripped when it returns.
224
218
 
225
- `batch.rs` makes a map's batched call. `batch::tried`, which `each_pair` calls, begins a batched level for the run (`transform::Kind::Batched`), wraps each argument that has a frame in a `Batch` carrier at that level, calls the operand once, and ends the level. Each map first lays its arguments over its frame through its own agreement, the pairing that its calls on each cell read (`batch::Arguments::laid` and `agreement::laid_cells`). `each_pair` makes no batched call for one cell of atoms, which runs faster without one. Routing hands each call whose newest level is the run's to `batch::call`: a primitive, an operation that primitives name, such as a fold by a primitive or `+.×`, or an operation by a dfn. It leaves `⍕` and random draws to their own code. It runs any other system function once for each cell, on that cell's arguments, as the function runs once for each item of an argument that holds several, and joins the cells' results into one batch (`batch::system`, `batch::each_cell`). `batch::call` runs the call on the whole arguments by Rank's routes: `eval::whole_cells` through `batch::whole_call`, and `eval::folded_cells` for a fold. A primitive therefore batches wherever Rank runs it on whole arguments. A fold or scan that `folded_cells` doesn't cover, such as one by a dfn, runs the fold's own loop over the batch's items. Each stage is then one call, on item `j` of every cell (`Batch::at`). `fold_array` and `primitive_fold` join a result that holds stage batches into one batch (`joined`). Every fold and scan route decides its structural cases, such as a unit, empty lanes and the result's shape, through `FoldPlan`, and ends in `folded`, which alone gives the result its layout, fused folds included. A fold or scan by any function other than a primitive, over more than one lane, also tries a batched run of its own: `operators::by_lanes` moves the fold axis last and runs the derived fold over the lanes through `batch::tried`. `operators::by_triples` does the same for `f.g` where `g` isn't a primitive: one batched call of `g` on a frame of rows by contraction by columns, then the fold by `f` along the contraction, for each chunk of rows whose triples hold at most `batch::CHUNK` items (`operators::by_rows`, which products of primitives share). Each runs its usual loop from the start where its try gives `None`. A fold keeps its stops on its operand's `Definition` (`Function::remembers`). `batch::tries` holds the conditions for any try. A call that no route covers stops the run (`transform::Stop`). A call whose constants with axes, repeated over the frame, would hold more than 4 times the items of its arguments and more than `batch::CHUNK` items, 2²¹, stops the run with the cells of a chunk whose share holds at most `CHUNK` items (`oversized`, `Stop::chunk`). `tried` then runs the operand once on each chunk of that many cells (`batch::chunked`), each as a batched level on a frame of one axis, and joins the chunks' results as the run over cells assembles its cells' results. A chunk that stops for too many items again starts the chunks over with its own smaller chunk. Where one cell's share alone passes `CHUNK`, the map calls its operand once for each cell. Code that must run once for each cell asks the levels first (`Levels::effect`): output, input, `⍕` of a carried value, and the code in a system function that acts (`Effect::Acts`, through `Context::acts`), a guard or a call on prototypes that would catch an error (`Effect::Catches`), and a write to a binding outside the map's frames (`Effect::Writes`, through `Levels::record_write`). A read through `Value::observed`, as a count or a position makes, stops the run too. A guard whose predicate is a batch of the run splits the run instead (`Session::guard` through `operators::guard`). `batch::truths` gives each cell's Boolean, and each side runs once, as a guard case on its own cells (`Levels::case`), through the `Cells` that `⍚` uses. Each batched binding in the frames that the run started is read at the side's cells (`Session::restricted`, through `batch::read_cells` and `operators::cells_at`), and `Cells::assembled` joins the sides' results. During a case, the run's frame is the case's cells, a random draw draws for the case's cells, and a write to an enclosing frame stops the run. A guard of a dfn that already splits the cells in another frame stops the run as a recursive call (`Cause::Recursion`), and sides whose cells differ in layout or kind stop it as a call with no rule. Each stop carries its cause (`transform::Cause`), which says how long a dfn operand remembers it (`Cause::kept`). An effect, a write, an observing read or a recursive call lasts for every later call. A call that no route covers lasts while later calls repeat the arguments' kinds and cell shapes, and the memory guard lasts while they also repeat the frame's shape. A caught error never lasts, because whether an error arises depends on the cells' values. The dfn's `Definition` holds what it remembers (`Definition::remember`): `ALWAYS`, or a signature of the arguments (`batch::signature`), each holding the stop's cause (`batch::holding`). A later try that it covers falls back without calling the operand, with an `"an earlier stop"` event that names the cause. A stop's own `fallbacks` event names its cause (`Cause::reason`), and the glyph of a primitive whose call no rule covers (`Stop::refusing`). Code with no rule for batches that reads a batch's items gets item carriers, item i of every cell, and records an `itemwise` row, route `"batched items"`. `explain::itemwise` is the one helper for routes that handle items one at a time, and the innermost call claims its counts (`Function::reported`), as `forced` does. A kernel that then reads a number meets the stop that `Carrier::computed` gives a batch. A missed reader therefore costs speed or a fallback, never a wrong result. A batched run can also start inside a `∂` call. The run's level is newer than the `∂` tag, so the batch rules take each call first, and their calls on whole arrays reach the derivative rules. A batch's whole can then carry a dual, whose kind batch checks read through `Value::template_dtype`. Stacks of matrices whose wholes carry a dual take the derivative rules through `Pairing::Matrices` (`eval::whole_cells`), because the stacked kernels read compact storage. A `∂` call inside the run differentiates with respect to batches of atoms or of arrays. `derivative::numbers` counts a cell's numbers from the batch's template, every cell shares each direction's seed, and the Jacobian joins into one batch (`batch::joined`). A move with no plan on a dual whose primal is a batch runs on the primal and the tangent apart (`derivative::apart`). Adjoints that a transpose adds into a batch add as one sum on its whole (`batch::scatter_add`). An attached rule runs on the whole batch at its argument's `∂` tag (`batch::call`), and `batch::split_whole` and `batch::dual_of_wholes` keep the newest level outermost. A roll draws once, on its argument laid over the frame (`distribution::drawn_items`), and deals and samples draw for each cell in turn (`distribution::each_cell`), all from one stream in cell order. Where each cell draws once, seeded draws match a run cell by cell, except under a guard that splits the cells, where each side draws for its own cells in turn. A try that falls back puts back the state of each generator it drew from (`distribution::settle`). The map's result must be a batch at its level, a strand of batches whose kinds join (`joined`), or an atom or compact array with no carrier, as every cell's result. Any other result falls back. A pervasive call stops where its result's kind differs from the kind that one route gives every item (`pervasive::expected`). Each cell then keeps the kind that a run cell by cell gives it. `reference::check` runs each reference case with the `batch` pref off, then on, then on under fusion's small sizes (`fusion::Sizes::SMALL`), and compares the storage kinds of the later runs' values with the first's.
219
+ `batch.rs` makes a map's batched call. `batch::tried`, which `each_pair` calls, begins a batched level for the run (`transform::Kind::Batched`), wraps each argument that has a frame in a `Batch` carrier at that level, calls the operand once, and ends the level. Each map first lays its arguments over its frame through its own agreement, the pairing that its calls on each cell read (`batch::Arguments::laid` and `agreement::laid_cells`). `each_pair` makes no batched call for one cell of atoms, which runs faster without one. Routing hands each call whose newest level is the run's to `batch::call`: a primitive, an operation that primitives name, such as a fold by a primitive or `+.×`, or an operation by a dfn. It leaves `⍕` and random draws to their own code. It runs any other system function once for each cell, on that cell's arguments, as the function runs once for each item of an argument that holds several, and joins the cells' results into one batch (`batch::system`, `batch::each_cell`). `batch::call` runs the call on the whole arguments by Rank's routes: `eval::whole_cells` through `batch::whole_call`, and `eval::folded_cells` for a fold. A primitive therefore batches wherever Rank runs it on whole arguments. A fold or scan that `folded_cells` doesn't cover, such as one by a dfn, runs the fold's own loop over the batch's items. Each stage is then one call, on item `j` of every cell (`Batch::at`). `fold_array` and `primitive_fold` join a result that holds stage batches into one batch (`joined`). Every fold and scan route decides its structural cases, such as a unit, empty lanes and the result's shape, through `FoldPlan`, and ends in `folded`, which alone gives the result its layout, fused folds included. A fold or scan by any function other than a primitive, over more than one lane, also tries a batched run of its own: `operators::by_lanes` moves the fold axis last and runs the derived fold over the lanes through `batch::tried`. `operators::by_triples` does the same for `f.g` where `g` isn't a primitive: one batched call of `g` on a frame of rows by contraction by columns, then the fold by `f` along the contraction, for each chunk of rows whose triples hold at most `batch::CHUNK` items (`operators::by_rows`, which products of primitives share). Each runs its usual loop from the start where its try gives `None`. A fold keeps its stops on its operand's `Definition` (`Function::remembers`). `batch::tries` holds the conditions for any try. A call that no route covers stops the run (`transform::Stop`). A call whose constants with axes, repeated over the frame, would hold more than 4 times the items of its arguments and more than `batch::CHUNK` items, 2²¹, stops the run with the cells of a chunk whose share holds at most `CHUNK` items (`oversized`, `Stop::chunk`). `tried` then runs the operand once on each chunk of that many cells (`batch::chunked`), each as a batched level on a frame of one axis, and joins the chunks' results as the run over cells assembles its cells' results. A chunk that stops for too many items again starts the chunks over with its own smaller chunk. Where one cell's share alone passes `CHUNK`, the map calls its operand once for each cell. Code that must run once for each cell asks the levels first (`Levels::effect`): output, input, `⍕` of a carried value, and the code in a system function that acts (`Effect::Acts`, through `Context::acts`), a guard or a call on prototypes that would catch an error (`Effect::Catches`), and a write to a binding outside the map's frames (`Effect::Writes`, through `Levels::record_write`). A read through `Value::observed`, as a count or a position makes, stops the run too. A guard whose predicate is a batch of the run splits the run instead (`Session::guard` through `operators::guard`). `batch::truths` gives each cell's Boolean, and each side runs once, as a guard case on its own cells (`Levels::case`), through the `Cells` that `⍚` uses. Each batched binding in the frames that the run started is read at the side's cells (`Session::restricted`, through `batch::read_cells` and `operators::cells_at`), and `Cells::assembled` joins the sides' results. During a case, the run's frame is the case's cells, a random draw draws for the case's cells, and a write to an enclosing frame stops the run. A map inside the run widens the run instead of beginning another, where the run is the innermost level (`batch::Entry::Widen`). The widening is a case with no definition, whose frame is the run's frame followed by the map's. The run's batches among the map's arguments lay over that frame (`batch::laid_over`), and a binding made before the widening lays over it when code reads it (`Session::read_binding`). A widened run that stops, or an Each whose results are arrays, falls back to calling the map's operand once for each of its cells inside the run. A guard of a dfn that already splits the cells in another frame stops the run as a recursive call (`Cause::Recursion`), and sides whose cells differ in layout or kind stop it as a call with no rule. Each stop carries its cause (`transform::Cause`), which says how long a dfn operand remembers it (`Cause::kept`). An effect, a write, an observing read or a recursive call lasts for every later call. A call that no route covers lasts while later calls repeat the arguments' kinds and cell shapes, and the memory guard lasts while they also repeat the frame's shape. A caught error never lasts, because whether an error arises depends on the cells' values. The dfn's `Definition` holds what it remembers (`Definition::remember`): `ALWAYS`, or a signature of the arguments (`batch::signature`), each holding the stop's cause (`batch::holding`). A later try that it covers falls back without calling the operand, with an `"an earlier stop"` event that names the cause. A stop's own `fallbacks` event names its cause (`Cause::reason`), and the glyph of a primitive whose call no rule covers (`Stop::refusing`). Code with no rule for batches that reads a batch's items gets item carriers, item i of every cell, and records an `itemwise` row, route `"batched items"`. `explain::itemwise` is the one helper for routes that handle items one at a time, and the innermost call claims its counts (`Function::reported`), as `forced` does. A kernel that then reads a number meets the stop that `Carrier::computed` gives a batch. A missed reader therefore costs speed or a fallback, never a wrong result. A batched run can also start inside a `∂` call. The run's level is newer than the `∂` tag, so the batch rules take each call first, and their calls on whole arrays reach the derivative rules. A batch's whole can then carry a dual, whose kind batch checks read through `Value::template_dtype`. Stacks of matrices whose wholes carry a dual take the derivative rules through `Pairing::Matrices` (`eval::whole_cells`), because the stacked kernels read compact storage. A `∂` call inside the run differentiates with respect to batches of atoms or of arrays. `derivative::numbers` counts a cell's numbers from the batch's template, every cell shares each direction's seed, and the Jacobian joins into one batch (`batch::joined`). A move with no plan on a dual whose primal is a batch runs on the primal and the tangent apart (`derivative::apart`). Adjoints that a transpose adds into a batch add as one sum on its whole (`batch::scatter_add`). An attached rule runs on the whole batch at its argument's `∂` tag (`batch::call`), and `batch::split_whole` and `batch::dual_of_wholes` keep the newest level outermost. A roll draws once, on its argument laid over the frame (`distribution::drawn_items`), and deals and samples draw for each cell in turn (`distribution::each_cell`), all from one stream in cell order. Where each cell draws once, seeded draws match a run cell by cell, except under a guard that splits the cells, where each side draws for its own cells in turn. A try that falls back puts back the state of each generator it drew from (`distribution::settle`). The map's result must be a batch at its level, a strand of batches whose kinds join (`joined`), or an atom or compact array with no carrier, as every cell's result. Any other result falls back. A pervasive call stops where its result's kind differs from the kind that one route gives every item (`pervasive::expected`). Each cell then keeps the kind that a run cell by cell gives it. `reference::check` runs each reference case with the `batch` pref off, then on, then on under fusion's small sizes (`fusion::Sizes::SMALL`), and compares the storage kinds of the later runs' values with the first's.
226
220
 
227
221
  Rustymath owns numeric folds, scans, adjacent pairs, grouped reductions and integer bounds. Basedpl selects kernels, tolerance, seeds, storage widths and exact fallbacks. Which reduction folds each primitive comes from rustymath's `facts!` table, through `pervasive::folds` and `truth_fold`, and so do the object by whose rule each takes characters and the comparison objects that `with_comparison!` makes. Folds by algebraic float operations can regroup. Contiguous subtraction/division folds use `Alternating`; quotients fall back to item-by-item folding if their products leave the normal range. Boolean scans compose truth-table maps; comparison scans compute both possible totals in bulk and use `reduce::chosen`. Seeds, axis lanes and scalar fallback preserve the language's accumulation direction. Generic reductions stay right-associated and preserve operand call order/effects. Monadic `f.g` is the exception: it memoizes each minor's expansion, and a cached minor does not repeat operand calls or their effects. Determinant/permanent fast paths use the appropriate rustymath backend.
228
222
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: basedpl
3
- Version: 0.1.71
3
+ Version: 0.1.73
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Requires-Dist: fastcore
@@ -176,6 +176,7 @@ The map calls its operand once for each cell instead where the operand:
176
176
  - writes output, reads input, or formats a cell's value with `⍕`
177
177
  - calls a system function that acts: one that reads or writes files, the network, the clock or the terminal, or that makes something new on each call, such as `•nget`, `•time` or `•uuid`
178
178
  - writes to a name outside the map
179
+ - appends to a value that differs from cell to cell, or writes into one so that it would be held in mixed storage
179
180
  - has a guard that catches an error
180
181
  - gives a result that holds arrays as items
181
182
  - calls a primitive that can't run on all the cells at once
@@ -29,7 +29,7 @@ x←2 4 9
29
29
  ⍴[[1]⋄[2]] ⍝ [2 1]ₓ
30
30
  ```
31
31
 
32
- Around literals, `[…]ₓ` makes every number exact, at any depth. Each number must be whole. After a list that holds anything else, `ₓ` is [`⌊`](downstile.qmd).
32
+ Around literals, `[…]ₓ` makes every number exact, at any depth. Each number must be whole. After a list that holds anything else, `ₓ` floors its numbers to exact integers, as [Superscripts and subscripts](../scripts.ipynb) describes.
33
33
 
34
34
  ```bpl
35
35
  [1 0 1]ₓ≡1ₓ 0ₓ 1ₓ ⍝ $t
@@ -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
  ```
@@ -22,8 +22,8 @@ Each entry below names a difference from Dyalog APL, gives a short example, and
22
22
  - [Brackets](glyphs/brackets.html.md): `[a b]` is a vector, even `[a]`. Inside brackets, spaces separate items. `;` separates items, each read as if parenthesised: `[1 2;3 4]` is `[(1 2) (3 4)]`, two items. `⋄` separates rows: `[1 2⋄3 4]` is a matrix. `"k":v` items make a record: `["a":1 "b":2]`.
23
23
  - [Characters and strings](strings.html.md): `"abc"` is a character vector. `'a'` is one character atom. A single-quoted string such as `'abc'` is an error.
24
24
  - [Indexing](indexing.html.md): `Y[I]` isn't BPL. `I⌷A` takes a cross product, while `A.[I J]` pairs its index arrays as NumPy does: with `i←⍳3`, `m.[i i]` is the diagonal. Positions count from 0. Negative positions count from the end.
25
- - [Numbers](numbers.html.md): bare numbers behave as in Dyalog. BPL adds exact integers, as in `3ₓ`, and exact rationals, as in `1r3`, and arithmetic on exact numbers stays exact.
26
- - [Superscripts and subscripts](scripts.html.md): `x²` is `x*2`, `f⁻¹` is the inverse of `f`, `v₁` is `1⌷v`, and `nₓ` is `⌊n`. Between names, `xⱼy` is `x+y×0ⱼ1`, `xₑy` is `x×10*y` and `xᵣy` is `xₓ÷yₓ`.
25
+ - [Numbers](numbers.html.md): a bare number is a float, as Python's `1.` is, and behaves as in Dyalog. BPL adds exact integers, as in `3ₓ`, which is Python's `3`. It also adds exact rationals, as in `1r3`. Arithmetic on exact numbers stays exact.
26
+ - [Superscripts and subscripts](scripts.html.md): `x²` is `x*2`, `f⁻¹` is the inverse of `f`, `v₁` is `1⌷v`, and `nₓ` is `⌊ₓn`. After a function, `ₓ` floors its results to exact integers: `7÷ₓ2` is `3ₓ`. Between names, `xⱼy` is `x+y×0ⱼ1`, `xₑy` is `x×10*y` and `xᵣy` is the exact quotient of `xₓ` by `yₓ`.
27
27
  - [Keyed arrays](keyed.html.md): axes can have names and keys. `T.a` reads field `a` of a record, and `⊢.a` is `{⍵.a}`. Arithmetic pairs axes by name: with `i←⍳["i":3]` and `j←⍳["j":3]`, `i+j` is a 3×3 table.
28
28
  - [Dfns](dfns.html.md): BPL has only dfns, with no tradfns and no control structures such as `:If`. A dfn returns its last statement. A predicate picks a body, as in BQN: `{⍵<0?-⍵;⍵} ¯3` is `3`. An absent `⍺` drops out of expressions, as BQN's `𝕨` does. A dfn operator's operands are `⍶` and `⍹`, not `⍺⍺` and `⍵⍵`. `⍢` calls the operator recursively. An error guard names its kinds as text, as in `"DOMAIN"::`.
29
29
  - [Assignment](assignment.html.md): `←` is local. Modified and selective updates change the nearest binding. `[a b]←Y` destructures the items of `Y` by position. A space before `←` makes the whole run the target: `[[0 2]]⌷v ←0`.
@@ -19,7 +19,7 @@ BPL has two kinds of number. A bare number such as `0.5` is approximate: a float
19
19
  | `⍬`, `⍬ₓ`, `⍬ₕ`, `⍬ₛ`, `⍬ₚ` | The approximate, the exact, and the 16-bit, 32-bit and 64-bit [empty vector](glyphs/zilde.qmd) |
20
20
  | `[…]ₓ`, `(…)ₓ` | A list, or rows, in which every number is exact |
21
21
  | `[…]ₕ`, `[…]ₛ`, `[…]ₚ` | A list, or rows, in which every real number is a 16-bit, 32-bit or 64-bit float, and every complex number has parts of that width, or 32-bit parts after `ₕ` |
22
- | `xⱼy`, `xₑy`, `xᵣy` | Between two items, such as names: `x+y×0ⱼ1`, `x×10*y` and `xₓ÷yₓ`, as one term |
22
+ | `xⱼy`, `xₑy`, `xᵣy` | Between two items, such as names: `x+y×0ⱼ1`, `x×10*y` and the exact quotient of `xₓ` by `yₓ`, as one term |
23
23
 
24
24
  A plain `e`, `j` or `r` starts a name unless the rest of a number follows it, as in `1e5`, `1r3` and `2j3`. Results display with the subscript forms, as in `1ᵣ3`, `2ⱼ3` and `1ₑ20`. A subscript form that the rest of a number doesn't follow, or one between two other items such as names, joins the items on each side into one term, as a literal is one, with the value the table gives. A literal on the left gives what the all-literal form gives: with `n←3`, `2ₑn` is `2ₑ3`.
25
25
 
@@ -96,7 +96,7 @@ m.[[1]]←1
96
96
  m ⍝ $f 1 $f
97
97
  ```
98
98
 
99
- Around literals, `[…]ₓ` and `(…)ₓ` make every number exact, at any depth. Each number must be whole. After a list or group that holds anything else, as after a name, `ₓ` is [`⌊`](glyphs/downstile.qmd), as [Superscripts and subscripts](scripts.ipynb) describes. A vector of exact integers displays as `[…]ₓ`, and rows of them as `(…)ₓ`. `⍕` writes them the same way:
99
+ Around literals, `[…]ₓ` and `(…)ₓ` make every number exact, at any depth. Each number must be whole. After a list or group that holds anything else, as after a name, `ₓ` floors to exact integers, as [Superscripts and subscripts](scripts.ipynb) describes. A vector of exact integers displays as `[…]ₓ`, and rows of them as `(…)ₓ`. `⍕` writes them the same way:
100
100
 
101
101
  ```bpl
102
102
  [1 0 1]ₓ≡1ₓ 0ₓ 1ₓ ⍝ $t
@@ -199,18 +199,17 @@ 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
 
213
- Some functions choose a result's kind from their arguments' values. `√¯4` is complex because the argument is negative, `1j0` is a float because its imaginary part is zero, and an exact integer that overflows grows. Under [`•prefs`](system/prefs.qmd) `["kinds":"static"]`, a result's kind follows from the function and its arguments' kinds alone. A fused computation needs that, because it decides each result's kind before it runs. Real arguments give real results, with NaN outside a function's domain, and complex results stay complex. `⌊`, `⌈` and monadic `×` of floats give floats, and integer `÷` gives floats:
212
+ Some functions choose a result's kind from their arguments' values. `√¯4` is complex because the argument is negative, `1j0` is a float because its imaginary part is zero, and an exact integer that overflows grows. Under [`•prefs`](system/prefs.qmd) `["kinds":"static"]`, a result's kind follows from the function and its arguments' kinds alone. A fused computation needs that, because it decides each result's kind before it runs. Real arguments give real results, with NaN outside a function's domain, and complex results stay complex. `⌊`, `⌈` and monadic `×` of floats give floats, and integer `÷` gives floats. With `ₓ` after them they give integers, as Rust's `as` converts a float: NaN gives 0, and a value past the `int` width's range gives its largest or smallest integer:
214
213
 
215
214
  ```bpl
216
215
  •prefs ["kinds":"static"]
@@ -218,6 +217,9 @@ Some functions choose a result's kind from their arguments' values. `√¯4` is
218
217
  0j1×0j1 ⍝ ¯1ⱼ0
219
218
  ⌊2.5 ∞ ⍝ 2 ∞
220
219
  7ₓ÷2ₓ ⍝ 3.5
220
+ ⌊ₓ2.5 ¯2.5 ⍝ [2 ¯3]ₓ
221
+ 7ₓ÷ₓ2ₓ ⍝ 3ₓ
222
+ ⌊ₓ $n ∞ ⍝ [0 9223372036854775807]ₓ
221
223
  •prefs ["kinds":"dynamic"]
222
224
  ```
223
225
 
@@ -999,7 +999,7 @@
999
999
  "\n",
1000
1000
  "NumPy float and complex scalars keep their explicit widths, including inside sequences. A list's items combine under BPL's usual joining rules: `[1, 2.5]` gives two floats. A dict's values each keep their own kind, as a record's fields do. In `{\"name\": \"x\", \"age\": 3, \"score\": 2.5}`, `age` stays exact beside the float `score`. Its `name` is the character atom `'x'`.\n",
1001
1001
  "\n",
1002
- "`.np` or `np.asarray(a)` always produces an ndarray. Booleans use `bool`. Integers use the width BPL stores them at: `uint8`, `int16`, `int32` or `int64`. Floats use the width BPL stores them at, `float16`, `float32` or `float64`. A NumPy `float16` or `float32` array keeps its width in BPL. Complex arrays use `complex64` or `complex128`, preserving the stored width. Fractions, large integers, nested arrays and mixed exact and approximate values use `object`. Character arrays use `U1`. The arrays inside a `.py` result, and the columns of a `.df` result, use the same dtypes."
1002
+ "`.np` or `np.asarray(a)` always produces an ndarray. Booleans use `bool`. Integers use the width BPL stores them at, `uint8`, `int16`, `int32` or `int64`, under dynamic kinds. Under static kinds they use the width they compute at, which is at least the `int` pref, so NumPy arithmetic on them wraps where BPL's does. Floats use the width BPL stores them at, `float16`, `float32` or `float64`. A NumPy `float16` or `float32` array keeps its width in BPL. Complex arrays use `complex64` or `complex128`, preserving the stored width. Fractions, large integers, nested arrays and mixed exact and approximate values use `object`. Character arrays use `U1`. The arrays inside a `.py` result, and the columns of a `.df` result, use the same dtypes."
1003
1003
  ]
1004
1004
  },
1005
1005
  {
@@ -962,7 +962,7 @@
962
962
  "id": "a2e00b5b",
963
963
  "metadata": {},
964
964
  "source": [
965
- "The subscript letters `ₓ`, `ⱼ`, `ₑ` and `ᵣ` are parts of numbers, as in `3ₓ` and `1ᵣ3`. [Numbers](numbers.qmd) covers them. Between two other items, such as names, `ⱼ`, `ₑ` and `ᵣ` join the items into one [number](numbers.qmd#writing-numbers): `xⱼy` is `x+y×0ⱼ1`. After a name, or any item but a number or a list of literals, `ₓ` is [`⌊`](glyphs/downstile.qmd):"
965
+ "The subscript letters `ₓ`, `ⱼ`, `ₑ` and `ᵣ` are parts of numbers, as in `3ₓ` and `1ᵣ3`. [Numbers](numbers.qmd) covers them. Between two other items, such as names, `ⱼ`, `ₑ` and `ᵣ` join the items into one [number](numbers.qmd#writing-numbers): `xⱼy` is `x+y×0ⱼ1`, and `xᵣy` is the exact quotient of `xₓ` by `yₓ`, under static kinds too. After a name, or any item but a number or a list of literals, `ₓ` floors the item's numbers to exact integers. `xₓ` is `⌊ₓx`:"
966
966
  ]
967
967
  },
968
968
  {
@@ -986,6 +986,74 @@
986
986
  "xₓ"
987
987
  ]
988
988
  },
989
+ {
990
+ "cell_type": "markdown",
991
+ "id": "f58b3b2a",
992
+ "metadata": {},
993
+ "source": [
994
+ "After a function, `ₓ` floors the function's results to exact integers, under either kinds. Under static kinds, which keep a failed result, it converts as Rust's `as` converts a float, into the `int` width: NaN gives `0`, and a value past the width's range, `∞` included, gives its largest or smallest integer.\n",
995
+ "\n",
996
+ "`⌊ₓ`, `⌈ₓ` and dyadic `÷ₓ`, which divides and floors as Python's `//` does, each compute their integers in one pass:"
997
+ ]
998
+ },
999
+ {
1000
+ "cell_type": "code",
1001
+ "execution_count": null,
1002
+ "id": "fb125557",
1003
+ "metadata": {},
1004
+ "outputs": [
1005
+ {
1006
+ "data": {
1007
+ "text/plain": [
1008
+ "[3 ¯4 3]ₓ"
1009
+ ]
1010
+ },
1011
+ "metadata": {},
1012
+ "output_type": "display_data"
1013
+ }
1014
+ ],
1015
+ "source": [
1016
+ "7 ¯7 7.5÷ₓ2"
1017
+ ]
1018
+ },
1019
+ {
1020
+ "cell_type": "markdown",
1021
+ "id": "255c7890",
1022
+ "metadata": {},
1023
+ "source": [
1024
+ "A float width's marker, `ₕ`, `ₛ` or `ₚ`, works the same way. After a function it makes the function's results floats of that width, and after an array it converts the array, as [`•float`](system/float.qmd) does:"
1025
+ ]
1026
+ },
1027
+ {
1028
+ "cell_type": "code",
1029
+ "execution_count": null,
1030
+ "id": "04c3990d",
1031
+ "metadata": {},
1032
+ "outputs": [
1033
+ {
1034
+ "data": {
1035
+ "text/plain": [
1036
+ "¯3ₛ"
1037
+ ]
1038
+ },
1039
+ "metadata": {},
1040
+ "output_type": "display_data"
1041
+ },
1042
+ {
1043
+ "data": {
1044
+ "text/plain": [
1045
+ "[3.7 ¯2.5]ₛ"
1046
+ ]
1047
+ },
1048
+ "metadata": {},
1049
+ "output_type": "display_data"
1050
+ }
1051
+ ],
1052
+ "source": [
1053
+ "-ₛ 3\n",
1054
+ "xₛ"
1055
+ ]
1056
+ },
989
1057
  {
990
1058
  "cell_type": "markdown",
991
1059
  "id": "0181955a",
@@ -998,7 +1066,7 @@
998
1066
  "- `SYNTAX`: `ⱼ`, `ₑ` or `ᵣ` beside a function or a space, as in `f←- ⋄ fⱼ1`\n",
999
1067
  "- `INDEX`: the position is outside the leading axis\n",
1000
1068
  "- `LENGTH`: the item is a unit, which has no axis to select from\n",
1001
- "- `DOMAIN`: `ₓ` after a function, as in `+ₓ`"
1069
+ "- `DOMAIN`: `ₓ` on a complex number, or under dynamic kinds on an infinity or NaN, as in `1÷ₓ0`"
1002
1070
  ]
1003
1071
  },
1004
1072
  {
@@ -2618,7 +2618,7 @@
2618
2618
  {
2619
2619
  "data": {
2620
2620
  "text/plain": [
2621
- "0 0 2 3 3"
2621
+ "3 4 5 2 4"
2622
2622
  ]
2623
2623
  },
2624
2624
  "metadata": {},
@@ -2638,7 +2638,7 @@
2638
2638
  {
2639
2639
  "data": {
2640
2640
  "text/plain": [
2641
- "0.5811181472 0.9743433567"
2641
+ "0.6628167745 0.8427274246"
2642
2642
  ]
2643
2643
  },
2644
2644
  "metadata": {},
@@ -2674,7 +2674,7 @@
2674
2674
  {
2675
2675
  "data": {
2676
2676
  "text/plain": [
2677
- "8 48 42 32 4 21 37 49 28 19 43 20 25"
2677
+ "3 20 28 11 1 42 4 36 10 15 39 38 7"
2678
2678
  ]
2679
2679
  },
2680
2680
  "metadata": {},