newra.texi 110 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057
  1. @c -*-texinfo-*-
  2. @c %**start of header
  3. @setfilename newra.info
  4. @documentencoding UTF-8
  5. @settitle newra — An alternative array library for Guile 3
  6. @c %**end of header
  7. @c last [ma112]
  8. @set VERSION 1
  9. @set UPDATED 2021 October 7
  10. @copying
  11. @code{newra} (version @value{VERSION}, updated @value{UPDATED})
  12. (c) lloda 2017--2021
  13. @smalldisplay
  14. Permission is granted to copy, distribute and/or modify this document
  15. under the terms of the GNU Free Documentation License, Version 1.3 or
  16. any later version published by the Free Software Foundation; with no
  17. Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
  18. @end smalldisplay
  19. @end copying
  20. @dircategory Guile libraries
  21. @direntry
  22. * newra: (newra.info). Array library for Guile meant to replace the built-in array facility.
  23. @end direntry
  24. @include my-bib-macros.texi
  25. @mybibuselist{Sources}
  26. @titlepage
  27. @title newra
  28. @subtitle version @value{VERSION}, updated @value{UPDATED}
  29. @author lloda
  30. @page
  31. @vskip 0pt plus 1filll
  32. @insertcopying
  33. @end titlepage
  34. @ifnottex
  35. @node Top
  36. @top @code{newra}
  37. @insertcopying
  38. @code{newra} is a pure Scheme replacement for the built-in C-based array facility in Guile 3.0.
  39. This document uses ‘array’ to refer both to the old built-in array type and to the new type introduced in @code{newra}. The distinction is made as necessary.
  40. @menu
  41. * Introduction:: Why Guile arrays need replacing.
  42. * Basic use:: Arrays as data structures.
  43. * High level:: Guile as an array language.
  44. * Hazards:: User beware.
  45. * Reference:: Systematic list of types and functions.
  46. * Cheatsheet:: Asking for directions
  47. * @mybibnode{}:: It's been done before.
  48. * Indices:: Or try the search function.
  49. @end menu
  50. @end ifnottex
  51. @iftex
  52. @shortcontents
  53. @end iftex
  54. @c ------------------------------------------------
  55. @node Introduction
  56. @chapter Introduction
  57. @c ------------------------------------------------
  58. @cindex bounds
  59. A multidimensional array is a container (or rather a container view) whose elements can be looked up using a multi-index (i₀, i₁, ...). Each of the indices i₀, i₁, ... has constant bounds [l₀, h₀], [l₁, h₁], ... independent of the values of the other indices, so the array is ‘rectangular’. The number of indices in the multi-index is the @dfn{rank} of the array, and the list ([l₀ h₀] [l₁ h₁] ... [lᵣ₋₁ hᵣ₋₁]) is the @dfn{shape} of the array. We speak of a rank-@math{r} array or of an @math{r}-array.
  60. This is a 2-array with bounds [0, 2] on both axes:
  61. @verbatim
  62. ┌───────┬───────┬───────┐
  63. │A(0, 0)│A(0, 1)│A(0, 2)│
  64. ├───────┼───────┼───────┤
  65. │A(1, 0)│A(1, 1)│A(1, 2)│
  66. ├───────┼───────┼───────┤
  67. │A(2, 0)│A(2, 1)│A(2, 2)│
  68. └───────┴───────┴───────┘
  69. @end verbatim
  70. This is a 3-array with bounds [0, 1] on axis 0, [2, 5] on axis 1, bounds [-2, 0] on axis 2:@footnote{
  71. @verbatim
  72. (import (newra))
  73. (define element (lambda i (format #f "A(~{~a~^, ~})" i)))
  74. (define (ti k) (ra-transpose (ra-iota) k))
  75. (ra-format (ra-map! (make-ra #f 3 3) element (ti 0) (ti 1)) #:prefix? #f)
  76. (ra-format (ra-map! (make-ra #f 2 '(2 5) '(-2 0)) element (ti 0) (ti 1) (ti 2)) #:prefix? #f)
  77. @end verbatim
  78. }
  79. @verbatim
  80. ║───────────┬───────────┬──────────║───────────┬───────────┬──────────║
  81. ║A(0, 2, -2)│A(0, 2, -1)│A(0, 2, 0)║A(1, 2, -2)│A(1, 2, -1)│A(1, 2, 0)║
  82. ║───────────┼───────────┼──────────║───────────┼───────────┼──────────║
  83. ║A(0, 3, -2)│A(0, 3, -1)│A(0, 3, 0)║A(1, 3, -2)│A(1, 3, -1)│A(1, 3, 0)║
  84. ║───────────┼───────────┼──────────║───────────┼───────────┼──────────║
  85. ║A(0, 4, -2)│A(0, 4, -1)│A(0, 4, 0)║A(1, 4, -2)│A(1, 4, -1)│A(1, 4, 0)║
  86. ║───────────┼───────────┼──────────║───────────┼───────────┼──────────║
  87. ║A(0, 5, -2)│A(0, 5, -1)│A(0, 5, 0)║A(1, 5, -2)│A(1, 5, -1)│A(1, 5, 0)║
  88. ║───────────┴───────────┴──────────║───────────┴───────────┴──────────║
  89. @end verbatim
  90. Sometimes we deal with multidimensional @emph{expressions} where the elements aren't stored anywhere, but are computed on demand when the expression is looked up. In this general sense, an ‘array’ is just a function of integers with a rectangular domain. Such an array would be immutable.
  91. Arrays (in the form of @dfn{matrices}, @dfn{vectors}, or @dfn{tensors}) are very common objects in math and programming, and it is very useful to be able to manipulate arrays as individual entities rather than as aggregates — that is one of the main purposes of @code{newra}.
  92. The rest of this section discusses the motivation for @code{newra} in more detail. To start using the library, please jump ahead to @ref{Low level}.
  93. @menu
  94. * Rank polymorphism::
  95. * Rank extension::
  96. * The pieces of an array::
  97. * Built-in Guile arrays::
  98. @end menu
  99. @c ------------------------------------------------
  100. @node Rank polymorphism
  101. @section Rank polymorphism
  102. @c ------------------------------------------------
  103. @cindex rank polymorphism
  104. @dfn{Rank polymorphism} is the ability to treat an array of rank @math{r} as an array of lower rank where the elements are themselves arrays.
  105. @cindex cell
  106. @cindex frame
  107. Think of a matrix A, a 2-array with lengths (l₀, l₁) where the elements A(i₀, i₁) are numbers. If we consider the subarrays (rows) A(0, ...), A(1, ...), ..., A(l₀-1, ...) as individual elements, then we have a new view of A as a 1-array of length l₀ with those rows as elements. We say that the rows A(i₀)≡A(i₀, ...) are the 1-@dfn{cells} of A, and the numbers A(i₀, i₁) are 0-cells of A. For an array of arbitrary rank @math{r} the (@math{r}-1)-cells of A are called its @dfn{items}. The prefix of the shape (l₀, l₁, ... lₙ₋₁₋ₖ) that is not taken up by the k-cell is called the (r-k)-@dfn{frame}.
  108. @multitable @columnfractions .4 .1 .4
  109. @item
  110. @verbatim
  111. ┌───────┬───────┬───────┐
  112. │A(0, 0)│A(0, 1)│A(0, 2)│
  113. ├───────┼───────┼───────┤
  114. │A(1, 0)│A(1, 1)│A(1, 2)│
  115. ├───────┼───────┼───────┤
  116. │A(2, 0)│A(2, 1)│A(2, 2)│
  117. └───────┴───────┴───────┘
  118. @end verbatim
  119. @tab
  120. @tab
  121. @verbatim
  122. ────
  123. A(0)
  124. ────
  125. A(1)
  126. ────
  127. A(2)
  128. ────
  129. @end verbatim
  130. @end multitable
  131. An obvious way to store an array in linearly addressed memory is to place its items one after another. So we would store a 3-array as
  132. @quotation
  133. A: [A(0), A(1), ...]
  134. @end quotation
  135. and the items of A(i₀), etc. are in turn stored in the same way, so
  136. @quotation
  137. A: [A(0): [A(0, 0), A(0, 1) ...], ...]
  138. @end quotation
  139. and the same for the items of A(i₀, i₁), etc.
  140. @quotation
  141. A: [[A(0, 0): [A(0, 0, 0), A(0, 0, 1) ...], A(0, 1): [A(0, 1, 0), A(0, 1, 1) ...]], ...]
  142. @end quotation
  143. @cindex order, row-major
  144. @cindex order, C
  145. This way to lay out an array in memory is called @dfn{row-major order} or @dfn{C-order}, since it's the default order for built-in arrays in C. A row-major array A with lengths (l₀, l₁, ... lᵣ₋₁) can be looked up like this:
  146. @anchor{x-steps}
  147. @quotation
  148. A(i₀, i₁, ...) = (storage-of-A) [(((i₀l₁ + i₁)l₂ + i₂)l₃ + ...)+iᵣ₋₁] = (storage-of-A) [o + s₀·i₀ + s₁·i₁ + ...]
  149. @end quotation
  150. where the numbers (s₀, s₁, ...) are called the @dfn{steps}@footnote{Cf. @url{https://en.wikipedia.org/wiki/Dope_vector, @dfn{dope vector}}}. Note that the ‘linear’ or ‘raveled’ address [o + s₀·i₀ + s₁·i₁ + ...] is an affine function of (i₀, i₁, ...). If we represent an array as a tuple
  151. @quotation
  152. A ≡ ((storage-of-A), o, (s₀, s₁, ...))
  153. @end quotation
  154. then any affine transformation of the indices can be achieved simply by modifying the numbers (o, (s₀, s₁, ...)), with no need to touch the storage. This includes very common operations such as: @ref{x-ra-transpose,transposing} axes, @ref{x-ra-reverse,reversing} the order along an axis, most cases of @ref{Slicing,slicing}, and sometimes even reshaping or tiling the array.
  155. A basic example is obtaining the i₀-th item of A:
  156. @quotation
  157. A(i₀) ≡ ((storage-of-A), o+s₀·i₀, (s₁, ...))
  158. @end quotation
  159. Note that we can iterate over these items by simply bumping the pointer o+s₀·i₀. This means that iterating over (k>0)-cells doesn't have to cost any more than iterating over 0-cells (@ref{x-ra-slice-for-each,@code{ra-slice-for-each}}). Rank polymorphism isn't just a high level property of arrays; it is enabled and supported by the way they are laid out in memory.
  160. @c ------------------------------------------------
  161. @node Rank extension
  162. @section Rank extension
  163. @c ------------------------------------------------
  164. Rank extension is the mechanism that allows @code{R+S} to be defined even when @code{R}, @code{S} may have different ranks. The idea is an interpolation of the following basic cases.
  165. Suppose first that @code{R} and @code{S} have the same rank. We require that the shapes be the same. Then the shape of @code{R+S} will be the same as the shape of either @code{R} or @code{S} and the elements of @code{R+S} will be
  166. @quotation
  167. @code{(R+S)(i₀ i₁ ... i₍ᵣ₋₁₎) = R(i₀ i₁ ... i₍ᵣ₋₁₎) + S(i₀ i₁ ... i₍ᵣ₋₁₎)}
  168. @end quotation
  169. where @code{r} is the rank of @code{R}.
  170. Now suppose that @code{S} has rank 0. The shape of @code{R+S} is the same as the shape of @code{R} and the elements of @code{R+S} will be
  171. @quotation
  172. @code{(R+S)(i₀ i₁ ... i₍ᵣ₋₁₎) = R(i₀ i₁ ... i₍ᵣ₋₁₎) + S()}.
  173. @end quotation
  174. The two rules above are supported by all primitive array languages. But suppose that @code{S} has rank @code{s}, where @code{0<s<r}. Looking at the expressions above, it seems natural to define @code{R+S} by
  175. @quotation
  176. @code{(R+S)(i₀ i₁ ... i₍ₛ₋₁₎ ... i₍ᵣ₋₁₎) = R(i₀ i₁ ... i₍ₛ₋₁₎ ... i₍ᵣ₋₁₎) + S(i₀ i₁ ... i₍ₛ₋₁₎)}.
  177. @end quotation
  178. That is, after we run out of indices in @code{S}, we simply repeat the elements. We have aligned the shapes so:
  179. @quotation
  180. @verbatim
  181. [n₀ n₁ ... n₍ₛ₋₁₎ ... n₍ᵣ₋₁₎]
  182. [n₀ n₁ ... n₍ₛ₋₁₎]
  183. @end verbatim
  184. @end quotation
  185. @cindex shape agreement, prefix
  186. @cindex shape agreement, suffix
  187. @c @cindex J
  188. @cindex Numpy
  189. This rank extension rule is used by the J language @mybibcite{J S} and is known as @dfn{prefix agreement}. The opposite rule of @dfn{suffix agreement} is used, for example, in Numpy @mybibcite{num17}.
  190. As you can verify, the prefix agreement rule is distributive. Therefore it can be applied to nested expressions or to expressions with any number of arguments. It is applied systematically throughout @code{newra}, even in assignments. For example,
  191. @example
  192. @verbatim
  193. (define a (make-ra-root #(3 5 9)))
  194. (define b (make-ra #f 3 2))
  195. (ra-copy! b a) ; copy each aᵢ on each bᵢ
  196. @end verbatim
  197. @result{} @code{#%2:3:2((3 3) (5 5) (9 9))}
  198. @end example
  199. @example
  200. @verbatim
  201. (define a (make-ra 0 3))
  202. (define b (ra-reshape (ra-iota 6 1) 0 3 2))
  203. (ra-map! a + a b) ; sum the rows of b
  204. @end verbatim
  205. @result{} @code{#%1:3(3 7 11)}
  206. @end example
  207. @cindex Numpy
  208. @cindex broadcasting, singleton, newaxis
  209. A weakness of prefix agreement is that the axes you want to match aren't always the prefix axes. Other array systems (e.g. @mybibcite{num17}) offer a feature similar to rank extension called ‘broadcasting’ that is a bit more flexible. For example an array of shape [A B 1 D] will match an array of shape [A B C D] for any value of C. The process of broadcasting consists in inserting so-called ‘singleton dimensions’ (axes with length one) to align the axes that one wishes to match. One may think of rank extension as a particular case of broadcasting where the singleton dimensions are added to the end of the shorter shapes automatically.
  210. A drawback of singleton broadcasting is that it muddles the distinction between a scalar and a vector of length 1. Sometimes, an axis of length 1 is no more than that, and if 2≠3 is a size error, it isn't obvious why 1≠2 shouldn't be. For this reason @code{newra}'s support for explicit broadcasting is based on @ref{x-dead-axes,dead axes}.
  211. @example
  212. @verbatim
  213. (define a (ra-i 5 3))
  214. (define b (make-ra 0 3))
  215. (let ((b1 (ra-transpose b 1))) ; align axis 0 of b with axis 1 of a
  216. (ra-map! b1 + b1 a) ; sum the columns of a
  217. b)
  218. @end verbatim
  219. @result{} b = @code{#%1:5(30 35 40)}
  220. @end example
  221. @c ------------------------------------------------
  222. @node The pieces of an array
  223. @section The pieces of an array
  224. @c ------------------------------------------------
  225. An @code{newra} array is an aggregate of the following pieces:
  226. @cindex rank
  227. @cindex dim vector
  228. @cindex root vector
  229. @itemize
  230. @item A @dfn{root vector}, or root for short.
  231. This can be a Scheme vector, as well as one of several other vector-like types.
  232. @item A @dfn{zero}.
  233. An arbitary integer.
  234. @item A @dfn{dim vector}.
  235. Each dim consists of a length (@dfn{len}), a lower bound (@dfn{lo}), and a @dfn{step}. The length of the dim vector is the @dfn{rank} of the array.
  236. @end itemize
  237. Together, the dim vector and the zero define an affine function of array indices @code{i₀, i₁, ..} that produces an index into the root. Thus, the array is a multidimensional view of the root.
  238. For example, the following pieces
  239. @itemize
  240. @item root: v = @code{#(1 2 3 4 5 6 7)}
  241. @item zero: 1
  242. @item dims: @code{#(#<<dim> len: 2 lo: 0 step: 2> #<<dim> len: 2 lo: 0 step: 1>)}
  243. @end itemize
  244. define an array A(i₀, i₁) = v(1 + 2·i₀ + 1·i₁), 0≤i₀<2, 0≤i₁<2, that is A = [[2 3] [4 5]].
  245. In @code{newra} code,
  246. @example
  247. @verbatim
  248. (make-ra-root (vector 1 2 3 4 5 6 7) 1 (vector (make-dim 2 0 2) (make-dim 2 0 1)))
  249. @end verbatim
  250. @result{} @code{#%2:2:2((2 3) (4 5))}
  251. @end example
  252. The default print style means @code{#%RANK:LEN₀:LEN₁(...)} (@ref{Writing and reading}).
  253. It's unusual to need to specify the dims directly. More commonly, one creates an array of whatever size
  254. @example
  255. @verbatim
  256. > (define a (make-ra #f 3 4))
  257. > a
  258. @end verbatim
  259. @result{} @code{#%2:3:4((#f #f #f #f) (#f #f #f #f) (#f #f #f #f))}
  260. @end example
  261. which automatically creates a root of the required size, so that all the array elements are distinct. Then one operates on the array without making reference to the underlying root,
  262. @example
  263. @verbatim
  264. > (ra-set! a 99 2 2)
  265. @end verbatim
  266. @result{} @code{#%2:3:4((#f #f #f #f) (#f #f 99 #f) (#f #f #f #f))}
  267. @end example
  268. Still, since the array is just a view of the root, any changes on the array are reflected there as well
  269. @example
  270. @verbatim
  271. > (ra-root a)
  272. @end verbatim
  273. @result{} @code{#(#f #f #f #f #f #f #f #f #f #f 99 #f)}
  274. @end example
  275. and the other way around,
  276. @example
  277. @verbatim
  278. > (define b (make-ra-root (vector 'x) 0 (vector (make-dim 3 0 0) (make-dim 2 0 0))))
  279. > b
  280. @end verbatim
  281. @result{} @code{#%2:3:2((x x) (x x) (x x))}
  282. @verbatim
  283. > (vector-set! (ra-root b) 0 'Z)
  284. > b
  285. @end verbatim
  286. @result{} @code{#%2:3:2((Z Z) (Z Z) (Z Z))}
  287. @end example
  288. @cindex shared root
  289. @cindex new array
  290. It is often important to know whether an operation on an array returns a different view of its argument, or instead it allocates a new root which can be modified without affecting the original argument. When we say that a function `creates a new array', we mean that it allocates a new root.
  291. Generally a given function will always do one or the other, e.g. the result of @ref{x-ra-tile, @code{ra-tile}} always shares the root of its argument, while @ref{x-ra-copy, @code{ra-copy}} always creates a new array. Some functions, like @ref{x-ra-ravel, @code{ra-ravel}} or @ref{x-ra-from, @code{ra-from}}, may do either, depending on their arguments. For example, the result of
  292. @example
  293. @verbatim
  294. (ra-ravel (ra-iota 3 4))
  295. @end verbatim
  296. @result{} @code{#%1d:12(0 1 2 3 4 5 6 7 8 9 10 11)}
  297. @end example
  298. shares the root of @code{(ra-iota 3 4)}, but
  299. @example
  300. @verbatim
  301. (ra-ravel (ra-transpose (ra-iota 3 4) 1 0))
  302. @end verbatim
  303. @result{} @code{#%1:12(0 4 8 1 5 9 2 6 10 3 7 11)}
  304. @end example
  305. doesn't.
  306. @c ------------------------------------------------
  307. @node Built-in Guile arrays
  308. @section Built-in Guile arrays
  309. @c ------------------------------------------------
  310. Dense multidimensional arrays work similarly in every language that offers them, and built-in Guile arrays are no different — they also have a root (@code{shared-array-root}), a zero (computable from @code{shared-array-offset} and @code{array-shape}), and a dim vector (@code{array-shape}, @code{shared-array-increments}). Functionally, they are entirely equivalent to the objects offered by @code{newra}. Why replace them?
  311. @cindex libguile
  312. Built-in Guile arrays are implemented in C, as part of libguile. As a Guile type they have their own low-level type tag, and all the basic array operations are C stubs, even the most basic functions such as @code{array-ref} or @code{array-rank}. Obtaining any of the components of the array requires calling into C. There are several problems with this.
  313. First, the built-in library offers a single function to manipulate array dims, @code{make-shared-array}. Although this is a sufficient interface, it is excessively generic, and also very cumbersome and inefficient. The array dims cannot be manipulated directly from Scheme, so any alternative interface written in Scheme is forced to go through @code{make-shared-array}.
  314. Second, the C stubs create a barrier to optimization by the Scheme compiler. The main loop of an operation such as @code{(array-map! c + a b)} has to be implemented in C (for the reasons given above) and then it has to call back to Scheme on each iteration in order to apply @code{+}. Since the Scheme compiler doesn't have any special support for @code{array-map!}, it doesn't know what the types of the arguments are, etc. and those checks and dispatches are repeated over and over. @footnote{Guile (before v1.8) used to offer dedicated operations to sum arrays, etc. but obviously that isn't any kind of solution.}
  315. Third, some of the the larger functions of the array interface, such as @code{array-map!}, etc. are not interruptible. This is especially inconvenient when operating on large arrays.
  316. These problems are solved if the built-in type is replaced with a new type defined in Scheme.
  317. @c ------------------------------------------------
  318. @node Low level
  319. @chapter Low level
  320. @c ------------------------------------------------
  321. @menu
  322. * Creating and accessing arrays::
  323. * Special arrays::
  324. * Writing and reading::
  325. * Iteration::
  326. * Slicing::
  327. * Reshaping::
  328. * Concatenation::
  329. * Transposition::
  330. * Other operations on arrays::
  331. * Automatic result arrays::
  332. * Foreign interface::
  333. * Compatibility with old Guile arrays::
  334. @end menu
  335. @c ------------------------------------------------
  336. @node Creating and accessing arrays
  337. @section Creating and accessing arrays
  338. @c ------------------------------------------------
  339. An array can be created anew (@ref{x-make-ra-new, @code{make-ra-new}}, @ref{x-make-ra, @code{make-ra}}, @ref{x-make-typed-ra, @code{make-typed-ra}}), or over an existing root (@ref{x-make-ra-root, @code{make-ra-root}}).
  340. @ref{x-make-ra, @code{make-ra}} or @ref{x-make-typed-ra, @code{make-typed-ra}} take array lengths and use row-major order by default.
  341. @example
  342. @verbatim
  343. (make-ra 99 2 3)
  344. @end verbatim
  345. @result{} #%2:3:2((9 9) (9 9) (9 9))
  346. @end example
  347. @example
  348. @verbatim
  349. (make-typed-ra 'f64 99 2 3)
  350. @end verbatim
  351. @result{} #%2f64:3:2((9.0 9.0) (9.0 9.0) (9.0 9.0))
  352. @end example
  353. @ref{x-make-ra-new, @code{make-ra-new}} takes an array type, a fill value, and a dim vector. @ref{x-c-dims, @code{c-dims}} can be used to create a row-major dim vector.
  354. @example
  355. @verbatim
  356. (make-ra-new #t 'x (vector (make-dim 3 0 2) (make-dim 2 0 1))) ; more simply
  357. (make-ra-new #t 'x (c-dims 3 2))
  358. @end verbatim
  359. @result{} #%2:3:2((x x) (x x) (x x))
  360. @end example
  361. @example
  362. @verbatim
  363. (make-ra-new 'f32 0.0 (c-dims 3 2))
  364. @end verbatim
  365. @result{} #%2f32:3:2((0.0 0.0) (0.0 0.0) (0.0 0.0))
  366. @end example
  367. @ref{x-make-ra-root, @code{make-ra-root}} takes the type from the root vector.
  368. @example
  369. @verbatim
  370. (make-ra-root (vector 1 2 3 4 5 6) (c-dims 3 2))
  371. @end verbatim
  372. @result{} #%2:3:2((1 2) (3 4) (5 6))
  373. @end example
  374. @code{newra} arrays are applicative; to look up or assign an element of an array, use it as a function of the indices.
  375. @example
  376. @verbatim
  377. (define a (make-ra #f 3 2))
  378. (set! (a 0 0) 9)
  379. (set! (a 1 1) 3)
  380. @end verbatim
  381. @result{} #%2:3:4((9 #f) (#f 3) (#f #f))
  382. @verbatim
  383. (a 0 0)
  384. @end verbatim
  385. @result{} 9
  386. @end example
  387. @cindex prefix slice
  388. If you give fewer indices than the rank, you get a prefix slice. This slice shares the root of the original array.
  389. @example
  390. @verbatim
  391. (a 1)
  392. @end verbatim
  393. @result{} #%1:2(#f 3)
  394. @verbatim
  395. (set! ((a 1) 0) 'b)
  396. @end verbatim
  397. @result{} #%1:2(b 3)
  398. @verbatim
  399. a
  400. @end verbatim
  401. @result{} #%2:3:4((9 #f) (b 3) (#f #f))
  402. @end example
  403. You can also access arrays in the more usual way with the functions @ref{x-ra-ref, @code{ra-ref}} and @ref{x-ra-set!, @code{ra-set!}}. See @ref{Slicing} for additional options.
  404. @c ------------------------------------------------
  405. @node Special arrays
  406. @section Special arrays
  407. @c ------------------------------------------------
  408. Any type that is usable as the root of an old built-in Guile array is also usable as root of a @code{newra} array. These include
  409. @itemize
  410. @item vectors (e.g. @code{(vector 3)})
  411. @item SRFI-4 typed vectors (e.g. @code{(c64vector 1 2+0i)})
  412. @item strings (e.g. @code{"hello"})
  413. @item bitvectors (e.g. @code{(bitvector #f #t #f #t)})
  414. @end itemize
  415. @code{newra} supports an additional root vector type, @code{<aseq>}, representing an unbounded arithmetic sequence.
  416. @cindex @code{make-aseq}
  417. @anchor{x-none}
  418. @deffn @w{Function} make-aseq [org [inc]]
  419. Create an arithmetic sequence [@code{org, org+inc, org+2·inc, ...}]. The default values of @code{org} and @code{inc} are respectively 0 and 1. For example:
  420. @example
  421. @verbatim
  422. (make-ra-root (make-aseq 0 3) (vector (make-dim 10)) 0)
  423. @end verbatim
  424. @result{} #%1d:10(0 3 6 9 12 15 18 21 24 27)
  425. @end example
  426. (The example above can be written @code{(@ref{x-ra-iota, ra-iota} 10 0 3)}).
  427. @end deffn
  428. @cindex @code{d}
  429. @code{aseq} roots are immutable. The type tag of @code{aseq} roots is @code{d}. Arrays with integer-valued @code{aseq} roots have a few special uses; one of them is as arguments in @ref{Slicing, slicing}.
  430. @cindex infinite axes
  431. @cindex unbounded axes
  432. To make @code{<aseq>} even more useful, @code{newra} supports unbounded axes.
  433. @example
  434. @verbatim
  435. (ra-ref (make-ra-root (make-aseq) (vector (make-dim #f)) 0) #e1e12) ; or more simply
  436. (ra-ref (ra-iota) #e1e12)
  437. @end verbatim
  438. @result{} 1000000000000
  439. @end example
  440. These are treated especially when used in iteration, in that they match axes of any finite length (@ref{x-ra-map!, @code{ra-map!}}). Effectively this lets one use @code{(@ref{x-ra-transpose, @code{ra-transpose}} (ra-iota) k)} as a placeholder for the index over axis @code{k}.
  441. @example
  442. @verbatim
  443. (ra-map! (make-ra 0 3) + (ra-iota 3) (ra-iota))
  444. @end verbatim
  445. @result{} #1%3(0 2 4)
  446. @end example
  447. @cindex dead axes
  448. @anchor{x-dead-axes}
  449. @code{newra} also supports `dead axes', which are axes with step 0 and undefined length. These axes can match axes of any length and can exist on arrays of any type, not only on arrays of type @code{d}, because effectively only one position (the lower bound) is ever accessed.
  450. @cindex singleton axis
  451. Dead axes operate essentially as ‘singleton axes’ do in other array languages. The main diference is that the ability to match any finite length is explicit; an axis with length 1 will still fail to match an axis with length 2 (say).
  452. Some functions work by creating axes with step 0, usually with defined lengths.
  453. @example
  454. @verbatim
  455. (define A (make-ra-root #(1 2 3) (c-dims 3)))
  456. (ra-tile A 0 2 2)
  457. @end verbatim
  458. @result{} #%3d:2:2:3(((0 1 2) (0 1 2)) ((0 1 2) (0 1 2)))
  459. @verbatim
  460. (ra-dims (ra-tile A 0 2 2))
  461. @end verbatim
  462. @result{} #(#<<dim> len: 2 lo: 0 step: 0> #<<dim> len: 2 lo: 0 step: 0> #<<dim> len: 3 lo: 0 step: 1>)
  463. @end example
  464. @c ------------------------------------------------
  465. @node Writing and reading
  466. @section Writing and reading
  467. @c ------------------------------------------------
  468. The read syntax for arrays is @url{https://www.gnu.org/software/guile/manual/html_node/Array-Syntax.html,the same} as for built-in Guile arrays, except that @code{#%} is used instead of @code{#}. Full dimensions are printed by default, even when they are not required to read an array.
  469. @example
  470. @verbatim
  471. (call-with-input-string "#%1(2 2 2)" read)
  472. @end verbatim
  473. @result{} @code{#%1:3(2 2 2)}
  474. @end example
  475. @example
  476. @verbatim
  477. (call-with-input-string "#%1:3(2 2 2)" read)
  478. @end verbatim
  479. @result{} @code{#%1:3(2 2 2)}
  480. @end example
  481. Dead axes print as @code{d}, and unbounded (not dead) axes print as @code{f}. These cannot be read back.
  482. @example
  483. @verbatim
  484. (display (ra-transpose (ra-copy (ra-iota 3)) 1))
  485. @end verbatim
  486. @result{} @code{#%2:d:3((0 1 2))}
  487. @end example
  488. Arrays with root of type @code{d} cannot be read back either.
  489. @example
  490. @verbatim
  491. (define s (format #f "~a" (ra-i 2 3)))
  492. s
  493. @end verbatim
  494. @result{} @code{"#%2d:2:3((0 1 2) (3 4 5))"}
  495. @end example
  496. @example
  497. @verbatim
  498. (call-with-input-string s read)
  499. @end verbatim
  500. @result{} error: cannot make array of type d
  501. @end example
  502. Truncated output is not supported yet.
  503. @example
  504. @verbatim
  505. (format #f "~@y" (ra-i 2 3))
  506. @end verbatim
  507. @result{} @code{"#%2d:2:3((0 1 2) (3 4 5))"} ; ok, but we didn't need to truncate
  508. @end example
  509. @example
  510. @verbatim
  511. (format #f "~@y" (ra-i 99 99))
  512. @end verbatim
  513. @result{} @code{"#" ; ouch}
  514. @end example
  515. The function @ref{x-ra-format, @code{ra-format}} can be used to pretty print arrays. This type of output cannot be read back, either.
  516. @example
  517. @verbatim
  518. (ra-format (list->ra 2 '((1 hello) ("try" 2) (never 3.14))) #:fmt "~s")
  519. @end verbatim
  520. @result{}
  521. @verbatim
  522. #%2:3:2─────┐
  523. │ 1│hello│
  524. ├─────┼─────┤
  525. │"try"│ 2│
  526. ├─────┼─────┤
  527. │never│ 3.14│
  528. └─────┴─────┘
  529. @end verbatim
  530. @end example
  531. The writing mode can be configured with the following parameter.
  532. @cindex @code{*ra-print*}
  533. @anchor{x-star-ra-print-star}
  534. @deffn @w{Parameter} *ra-print* (lambda (array port) ...)
  535. Set the default printer for arrays. This parameter is available from @code{(newra print)}.
  536. @cindex @code{box}
  537. @cindex @code{box-compact}
  538. @cindex @code{default}
  539. The parameter can be set to a function @code{(lambda (array port) ...)} or to one of the values @code{#f}, @code{'default}, @code{'box} or @code{'box-compact}.
  540. For example
  541. @example
  542. @verbatim
  543. (import (newra print))
  544. (*ra-print* (lambda (ra o) (ra-print ra o #:dims? #f)))
  545. (ra-i 2 3)
  546. @end verbatim
  547. @result {}
  548. @verbatim
  549. $1 = #%2d((0 1 2) (3 4 5))
  550. @end verbatim
  551. @end example
  552. or
  553. @example
  554. @verbatim
  555. (*ra-print* (lambda (ra o) (newline o) (ra-format ra o)))
  556. ; (*ra-print* 'box) ; same thing
  557. (ra-i 2 3)
  558. @end verbatim
  559. @result {}
  560. @verbatim
  561. $1 =
  562. #%2d:2:3
  563. │0│1│2│
  564. ├─┼─┼─┤
  565. │3│4│5│
  566. └─┴─┴─┘
  567. @end verbatim
  568. @end example
  569. The default printer can be reset with @code{(*ra-print* #f)} or @code{(*ra-print* 'default)}.
  570. @end deffn
  571. @cindex SRFI-163
  572. By default, rank-0 arrays are printed like the built-in Guile arrays, with extra parentheses around the content. In the read syntax specified in @mybibcite{SRFI-163}, those parentheses are not used. The following parameter allows one to choose either behavior for both the printer and the reader.
  573. @cindex @code{*ra-parenthesized-rank-zero*}
  574. @anchor{x-star-ra-parenthesized-rank-zero-star}
  575. @deffn @w{Parameter} *ra-parenthesized-rank-zero* boolean
  576. Control read syntax of rank-0 arrays. This parameter is available from @code{(newra print)} or @code{(newra read)}.
  577. If @code{(*ra-parenthesized-rank-zero*)} is true, the read syntax for rank-0 arrays is
  578. @display
  579. @code{#%0TYPE(item)}
  580. @end display
  581. If it is @code{#f}, it is
  582. @display
  583. @code{#%0TYPE item}
  584. @end display
  585. with @code{TYPE} being optional in either case. Note that these are not compatible:
  586. @example
  587. @verbatim
  588. (ra-ref (parameterize ((*ra-parenthesized-rank-zero* #t))
  589. (call-with-input-string "#%0(a)" read)))
  590. @end verbatim
  591. @result{} @code{a}
  592. @verbatim
  593. (ra-ref (parameterize ((*ra-parenthesized-rank-zero* #f))
  594. (call-with-input-string "#%0(a)" read)))
  595. @end verbatim
  596. @result{} @code{(a)}
  597. @verbatim
  598. (ra-ref (parameterize ((*ra-parenthesized-rank-zero* #f))
  599. (call-with-input-string "#%0 a" read)))
  600. @end verbatim
  601. @result{} @code{a}
  602. @end example
  603. In the last example, the space is necessary (unlike in @mybibcite{SRFI-163}) since the array type tag is optional in Guile.
  604. @example
  605. @verbatim
  606. (parameterize ((*ra-parenthesized-rank-zero* #f))
  607. (call-with-input-string "#%0a" read))
  608. @end verbatim
  609. @result{} Wrong type (expecting character): #<eof>
  610. @end example
  611. The printer always uses a space in this mode:
  612. @example
  613. @verbatim
  614. (parameterize ((*ra-parenthesized-rank-zero* #f))
  615. (display (make-ra '(a))))
  616. @end verbatim
  617. @result{} @code{#%0 (a)}
  618. @end example
  619. Note that setting this parameter to @code{#f} still doesn't make the array read syntax fully compatible with that of @mybibcite{SRFI-163}, since the type tag @code{a} is reserved (in Guile) for character arrays.
  620. The default value of this parameter is @code{#t}.
  621. @end deffn
  622. @c ------------------------------------------------
  623. @node Iteration
  624. @section Iteration
  625. @c ------------------------------------------------
  626. The basic array iteration operations in @code{newra} all operate by effect. This gives you control of how the result is allocated. If one of the arguments is designated as destination, as is the case with @ref{x-ra-map!, @code{ra-map!}}, then that is the result of the whole iteration. For example:
  627. @example
  628. @verbatim
  629. (ra-map! (make-ra #f 3) - (ra-iota 3 1))
  630. @end verbatim
  631. @result{} #%1:3(-1 -2 -3)
  632. @end example
  633. It is common to need the indices of the elements during array iteration. @code{newra} iteration operations do not keep track of those indices@footnote{An exception is @ref{x-ra-index-map!, @code{ra-index-map!}}, where passing the indices is the purpose.} because that has a cost. You need to pass the indices you need as arguments, but it's easy to do so by using an unbounded index vector together with @ref{x-ra-transpose, @code{ra-transpose}}.
  634. @example
  635. @verbatim
  636. (define i0 (ra-iota))
  637. (define i1 (ra-transpose (ra-iota) 1))
  638. (ra-map! (make-ra #f 2 2) list (list->ra 2 '((A B) (C D))) i0 i1)
  639. @end verbatim
  640. @result{} #%2:2:2(((A 0 0) (B 0 1)) ((C 1 0) (D 1 1)))
  641. @end example
  642. One can iterate not only over the whole array, but also over any @code{n}-frame (the first @code{n} axes of an array), using @ref{x-ra-slice-for-each, @code{ra-slice-for-each}}. In this case the operation takes array slices as arguments, even when they are of rank 0; this allows writing to any of the arguments. When there are several arrays involved, all the frames must match.
  643. In the following example, @code{xys} is of rank 2, @code{angle} is of rank 1, and their first axes have the same length.
  644. @example
  645. @verbatim
  646. (ra-slice-for-each 1
  647. (lambda (xy angle)
  648. ; inside the op, xy is rank 1, angle is rank 0
  649. (ra-set! angle (atan (ra-ref xy 1) (ra-ref xy 0))))
  650. xys angles)
  651. @end verbatim
  652. @end example
  653. @cindex prefix matching
  654. The iteration procedures in @code{newra} all perform rank extension of their arguments through prefix matching (see @ref{Rank extension}). In the following example, the shapes of the arguments are (5 5), (5) and (@code{#f} 5), and the common prefixes all match.
  655. @example
  656. @verbatim
  657. (ra-map! (make-ra 5 5) * (ra-iota 5 1) (ra-transpose (ra-iota 5 1) 1))
  658. @end verbatim
  659. @result{} @code{#%2:5:5((1 2 3 4 5) (2 4 6 8 10) (3 6 9 12 15) (4 8 12 16 20) (5 10 15 20 25))}
  660. @end example
  661. Another example using @ref{x-ra-copy!, @code{ra-copy!}},
  662. @example
  663. @verbatim
  664. (ra-copy! (list->ra 2 '((a b) (p q) (x y)))
  665. (list->ra 1 '(1 2 3)))
  666. @end verbatim
  667. @result{} @code{#%2:3:2((1 1) (2 2) (3 3))}
  668. @end example
  669. @c ------------------------------------------------
  670. @node Slicing
  671. @section Slicing
  672. @c ------------------------------------------------
  673. Slicing refers to the operation of taking a partial view of an array (e.g. a row or a column out of a matrix) through modification of the dim vector. This can be done with creative uses of @ref{x-ra-ravel, @code{ra-ravel}}, @ref{x-ra-reshape, @code{ra-reshape}} and @ref{x-ra-transpose, @code{ra-transpose}}, and of course by direct modification of the dim vector, but the facilities described in this section are usually a lot clearer.
  674. @cindex prefix slice
  675. The simplest form of slicing uses @ref{x-ra-slice, ra-slice} to produce ‘prefix slices’.
  676. @example
  677. @verbatim
  678. (define a (list->ra 3 '(((a b) (x y)) ((A B) (X Y)))))
  679. @end verbatim
  680. @result{} @code{#%3:2:2:2(((a b) (x y)) ((A B) (X Y)))}
  681. @verbatim
  682. (ra-slice a 0 1 0)
  683. @end verbatim
  684. @result{} @code{#%0(x)}
  685. @verbatim
  686. (ra-slice a 0 1)
  687. @end verbatim
  688. @result{} @code{#%1:2(x y)}
  689. @verbatim
  690. (ra-slice a 0)
  691. @end verbatim
  692. @result{} @code{#%2:2:2((a b) (x y))}
  693. @verbatim
  694. (ra-slice a)
  695. @end verbatim
  696. @result{} @code{#%3:2:2:2(((a b) (x y)) ((A B) (X Y)))}
  697. @end example
  698. The prefix slice always shares the root of the source array, so it can be used to modify the source array.
  699. @example
  700. @verbatim
  701. (ra-fill! (ra-slice a 1 0) '99)
  702. @end verbatim
  703. @result{} @code{#%1:2(99 99)}
  704. @verbatim
  705. a
  706. @end verbatim
  707. @result{} @code{#%3:2:2:2(((a b) (x y)) ((99 99) (X Y)))}
  708. @end example
  709. The variant @ref{x-ra-cell, @code{ra-cell}} is identical to @code{ra-slice} except that it returns an element (and not a rank 0 array) when the full set of indices is given.
  710. @example
  711. @verbatim
  712. (ra-slice a 0 1 0)
  713. @end verbatim
  714. @result{} @code{x}
  715. @end example
  716. @code{ra-cell} is a @ref{Rank polymorphism, rank-polymorphic} generalization of the basic element lookup function @ref{x-ra-ref, @code{ra-ref}}, which requires the full set of indices.
  717. @example
  718. @verbatim
  719. (ra-ref a 0 1 0) ; same as ra-cell
  720. @end verbatim
  721. @result{} @code{x}
  722. @verbatim
  723. (ra-ref a 0 1)
  724. @end verbatim
  725. @result{} @code{"<unnamed port>":...: Throw to key `bad-number-of-indices' with args `(3 2)'.}
  726. @end example
  727. Both @code{ra-cell} and @code{ra-slice} (and @code{ra-ref}) take scalar indices as arguments. The more powerful function @ref{x-ra-from, @code{ra-from}} is able to handle arrays of indices.
  728. @cindex @code{@{}, from
  729. @quotation
  730. @verbatim
  731. (ra-from a i₀ ...) ⇒ b
  732. @end verbatim
  733. @end quotation
  734. Each of the @code{i₀...} is either 1. an integer; 2. an array of integers; 3. the special value @code{#t}. Integer arguments contain indices into the respective axis of @code{a}. @code{#t} for @code{iₖ} is a shortcut for ‘the whole of axis @code{k}’@footnote{Note that this is not the same as @code{(let ((d (vector-ref (ra-dims a) k))) (ra-iota (dim-len d) (dim-lo d)))}, because the lower bound of @code{(ra-iota ...)} (@emph{not} its content) is 0, not @code{(dim-lo d)}, so the corresponding lower bound on the result array would also be 0, while @code{#t} preserves the lower bound of @code{a}.}. The result @code{b} has rank equal to the sum of all the ranks of the @code{i₀...}, and is defined as
  735. @quotation
  736. @verbatim
  737. (ra-ref b j₀ ...) = (ra-ref a (ra-ref i₀ j₀ ...) ...)
  738. @end verbatim
  739. @end quotation
  740. In other words, @code{ra-from} produces the outer product of the indices @code{i₀...} with operator @code{a} (if one thinks of @code{(a i₀ ...)} as @code{(ra-ref a i₀ ...)}).
  741. If all of the @code{i...} are integers or arrays of type @code{d} (such as those produced by @code{ra-iota} or @code{ra-i}) then the result of @code{ra-from} shares the root of @code{a}. Otherwise @code{newra} cannot tell whether the indices are an arithmetic sequence, so the result has to be copied to a new root. For example:
  742. @example
  743. @verbatim
  744. (define a (list->ra 2 '((a b c) (d e f))))
  745. @end verbatim
  746. @result{} @code{#%2:2:3((a b c) (d e f))}
  747. @verbatim
  748. (ra-from a 0 #t) ; row 0, will share root
  749. @end verbatim
  750. @result{} @code{#%1:3(a b c)}
  751. @verbatim
  752. (ra-from a #t 1) ; column 1, will share root
  753. @end verbatim
  754. @result{} @code{#%1:2(b e)}
  755. @verbatim
  756. (ra-from a #t (make-ra-root #(2 0))) ; cols 2 & 0, won't share root
  757. @end verbatim
  758. @result{} @code{#%2:2:2((c a) (f d))}
  759. @verbatim
  760. (ra-from a #t (ra-iota 2 2 -2)) ; cols 2 & 0, will share root
  761. @end verbatim
  762. @result{} @code{#%2:2:2((c a) (f d))}
  763. @end example
  764. One may give fewer @code{i} than the rank of @code{a}. The missing arguments are taken as @code{#t} (see @ref{Rank polymorphism}).
  765. @example
  766. @verbatim
  767. (ra-from a 0) ; row 0, same as (ra-from a 0 #t)
  768. @end verbatim
  769. @result{} @code{#%1d:3(0 1 2)}
  770. @end example
  771. @cindex @code{ldots}
  772. When used as an argument to @code{ra-from} (or @code{ra-amend!}), the special object @code{(@ref{x-ldots, ldots} n)} stands for @code{n} times @code{#t}. @code{(ldots)} alone will expand to fill the rank of the array argument, so the indices that come after are pushed to the last axes.
  773. @example
  774. @verbatim
  775. (ra-from A 0 (ldots 1) 1) ; same as (ra-from A 0 #t 1)
  776. (ra-from B 0 (ldots 2) 1) ; same as (ra-from B 0 #t #t 1)
  777. (ra-from C 0 (ldots) 1) ; same as (ra-from C 1 (ldots (- (ra-rank C) 2)) 1)
  778. @end verbatim
  779. @end example
  780. For instance:
  781. @example
  782. @verbatim
  783. (ra-i 4 3 2)
  784. @end verbatim
  785. @result{} #%3d:4:3:2(((0 1) (2 3) (4 5)) ((6 7) (8 9) (10 11)) ((12 13) (14 15) (16 17)) ((18 19) (20 21) (22 23)))
  786. @verbatim
  787. (ra-from (ra-i 4 3 2) (ldots) 1) ; select second element on last axis
  788. @end verbatim
  789. @result{} #%2d:4:3((1 3 5) (7 9 11) (13 15 17) (19 21 23))
  790. @end example
  791. When it is known that the result of @code{ra-from} will share the root with its argument, that can be used to modify the original array. For example:
  792. @example
  793. @verbatim
  794. (ra-fill! (ra-from a 1) x)
  795. @end verbatim
  796. @result{} @code{#%2:3((a b c) (x x x)}
  797. @verbatim
  798. a
  799. @end verbatim
  800. @result{} @code{#%2:3((a b c) (x x x))}
  801. @end example
  802. @ref{x-ra-amend!, @code{ra-amend!}} handles the general case:
  803. @example
  804. @verbatim
  805. (define a (list->ra 2 '((a b c) (d e f))))
  806. (ra-amend! a 'Y #t (make-ra-root #(2 0)))
  807. @end verbatim
  808. @result{} @code{#%2:3((Y b Y) (Y e Y))}
  809. @verbatim
  810. a
  811. @end verbatim
  812. @result{} @code{#%2:3((Y b Y) (Y e Y))}
  813. @end example
  814. while on the other hand
  815. @example
  816. @verbatim
  817. (define a (list->ra 2 '((a b c) (d e f))))
  818. (ra-fill! (ra-from a #t (make-ra-root #(2 0))) 'Y)
  819. @end verbatim
  820. @result{} @code{#%2:3((Y Y) (Y Y))}
  821. @verbatim
  822. a
  823. @end verbatim
  824. @result{} @code{#%2:3((a b c) (d e f))}
  825. @end example
  826. @c ------------------------------------------------
  827. @node Reshaping
  828. @section Reshaping
  829. @c ------------------------------------------------
  830. @cindex APL
  831. @cindex @code{,}, ravel
  832. @cindex @code{⍴}, reshape
  833. To match APL ρ, @code{newra} offers three separate functions.
  834. @ref{x-ra-reshape, @code{ra-reshape}} and @ref{x-ra-ravel, @code{ra-ravel}} are in a way the inverse of each other. @code{ra-reshape} folds an axis into (potentially) many, while @code{ra-ravel} makes a block of axes into a single axis. Neither is able to increase the size of the array (although @code{ra-reshape} can @emph{reduce} it). For that purpose @ref{x-ra-tile, @code{ra-tile}} is provided.
  835. @example
  836. @verbatim
  837. (ra-dimensions (ra-i 2 3 4))
  838. @end verbatim
  839. @result{} (2 3 4)
  840. @verbatim
  841. ; insert new axis of size 5 before axis 0
  842. (ra-dimensions (ra-tile (ra-i 2 3 4) 0 5))
  843. @end verbatim
  844. @result{} (5 2 3 4)
  845. @verbatim
  846. ; collapse axes 0 and 1
  847. (ra-dimensions (ra-ravel (ra-tile (ra-i 2 3 4) 0 5) 2))
  848. @end verbatim
  849. @result{} (10 3 4)
  850. @verbatim
  851. ; reshape axis 0 into two axes with shape [3 3]
  852. (ra-dimensions (ra-reshape (ra-ravel (ra-tile (ra-i 2 3 4) 0 5) 2) 0 3 3))
  853. @end verbatim
  854. @result{} (3 3 3 4)
  855. @end example
  856. @code{ra-reshape} and @code{ra-tile} always reuse the root of the argument. On the other hand @code{ra-ravel} may not be able to, depending on the storage order of the array — this is one of the reasons to have three different functions instead of only one. You can check in advance whether @code{ra-ravel} will reuse the root with the function @ref{x-ra-order-c?, @code{ra-order-c?}}.
  857. @c ------------------------------------------------
  858. @node Concatenation
  859. @section Concatenation
  860. @c ------------------------------------------------
  861. @cindex concatenation
  862. @code{newra} offers two concatenation operations: @ref{x-ra-cat, @code{ra-cat}} (prefix cat) and @ref{x-ra-scat, @code{ra-scat}} (suffix cat).
  863. For @code{ra-cat}, the arguments are prefix-matched, and the concatenation axis is counted from the left. E.g. for three arrays @var{r}, @var{s}, @var{t} with shapes
  864. @example
  865. @verbatim
  866. (r₀ r₁ r₂ r₃)
  867. (s₀ s₁ s₂ s₃ s₄ s₅)
  868. (t₀ t₁)
  869. @end verbatim
  870. @end example
  871. Then @code{(define val (ra-cat #t 1 r s t))} will prefix-match these to (it is an error if any of @code{r₀=s₀=t₀}, @code{r₂=s₂}, or @code{r₃=s₃} don't hold)
  872. @example
  873. @verbatim
  874. (s₀ |r₁| s₂ s₃ s₄ s₅)
  875. (s₀ |s₁| s₂ s₃ s₄ s₅)
  876. (s₀ |t₁| s₂ s₃ s₄ s₅)
  877. @end verbatim
  878. @end example
  879. and then concatenate them along axis 1 into an array of shape @code{(s₀ (r₁+s1+t₁) s₂ s₃ s₄ s₅)}.
  880. For @code{ra-scat}, the arguments are suffix-matched, and the concatenation axis is counted from the right. For example
  881. @example
  882. @verbatim
  883. (define r (ra-i 2 3 2))
  884. (define s (list->ra 1 '(a b)))
  885. (ra-scat #t 1 r s)
  886. @end verbatim
  887. @end example
  888. the axes are aligned as
  889. @example
  890. @verbatim
  891. (r₀ r₁ r₂)
  892. (s₀)
  893. @end verbatim
  894. @end example
  895. and suffix-matched (s₀ and r₂ must match)
  896. @example
  897. @verbatim
  898. (r₀ |r₁| r₂)
  899. (r₀ | 1| r₂)
  900. @end verbatim
  901. @end example
  902. for a result
  903. @example
  904. @verbatim
  905. (ra-scat #t 1 r s)
  906. @end verbatim
  907. @result{} @code{#%3(((0 1) (2 3) (4 5) (a b)) ((6 7) (8 9) (10 11) (a b)))}
  908. @end example
  909. Note that the rank extension of @code{s} on the concatenation axis yields a length of 1 (and not @code{r₀}). It can be useful to think of the axis argument of @code{ra-scat} as indicating cell rank, so the code above means `concatenate 1-cells'.
  910. For both @code{ra-cat} and @code{ra-scat}, axes other than the concatenation axis must match across all of the arguments.
  911. @example
  912. @verbatim
  913. (ra-cat #t 0 (ra-i 3 2) (ra-i 2))
  914. @end verbatim
  915. @result{} @code{#%2:4:2((0 1) (2 3) (4 5) (0 0) (1 1))}
  916. @end example
  917. @example
  918. @verbatim
  919. (ra-scat #t 1 (ra-i 3 2) (ra-i 2))
  920. @end verbatim
  921. @result{} @code{#%2:4:2((0 1) (2 3) (4 5) (0 1))}
  922. @end example
  923. In particular, it is not enough for the lengths to be the same; both bounds must match.
  924. @example
  925. @verbatim
  926. (ra-cat #t 0 (make-ra 'a '(1 1) '(1 4))
  927. (make-ra 'b '(2 2) '(1 4)))
  928. @end verbatim
  929. @result{} @code{#%2:2@@1:4((a a a a) (b b b b))} ; axes 1 match, axes 0 don't need to
  930. @end example
  931. @example
  932. @verbatim
  933. (ra-cat #t 1 (make-ra 'a '(1 1) '(1 4))
  934. (make-ra 'b '(2 2) '(1 4)))
  935. @end verbatim
  936. @result{} error ; axes 0 don't match
  937. @end example
  938. Here @ref{x-ra-reshape,@code{ra-reshape}} is used to move axis 0 of the second argument into agreement.@footnote{An example of how using lower bounds other than 0 is generally worthless trouble, not least for the library author.}
  939. @example
  940. @verbatim
  941. (ra-cat #t 1 (make-ra 'a '(1 1) '(1 4))
  942. (ra-reshape (make-ra 'b '(2 2) '(1 4)) 0 '(1 1)))
  943. @end verbatim
  944. @result{} @code{#%2@@1:1:8((a a a a b b b b))}
  945. @end example
  946. On the concatenation axis, only lengths matter; for both @code{ra-cat} and @code{ra-scat}, the lower bound is 0 in the result, and the lower bounds of the arguments are ignored.
  947. @example
  948. @verbatim
  949. (define a (make-ra 'a '(1 2) '(2 3)))
  950. (define b (make-ra 'b '(1 2)))
  951. (define c (make-ra 'c '(1 2) '(-1 0)))
  952. (ra-format (ra-cat #t 1 a b c))
  953. @end verbatim
  954. @result{}
  955. @verbatim
  956. #%2@1:2:5─┐
  957. │a│a│b│c│c│
  958. ├─┼─┼─┼─┼─┤
  959. │a│a│b│c│c│
  960. └─┴─┴─┴─┴─┘
  961. @end verbatim
  962. @end example
  963. Both @code{ra-cat} and @code{ra-scat} accept a negative concatenation axis. That will rank-extend all the arguments to the left (@code{ra-cat}) or to the right (@code{ra-scat}) before concatenating on the leftmost (@code{ra-cat}) or rightmost (@code{ra-scat}) axis. In the same way, one may give a concatenation axis which is beyond the rank of the argument with the highest rank. Consider
  964. @example
  965. @verbatim
  966. (define abc (list->ra 1 #(a b c)))
  967. (ra-cat #t -1 (ra-i 3) abc)
  968. @end verbatim
  969. @result{} @code{#%2:2:3((0 1 2) (a b c))}
  970. @end example
  971. @example
  972. @verbatim
  973. (ra-cat #t 0 (ra-i 3) abc)
  974. @end verbatim
  975. @result{} @code{#%1:6(0 1 2 a b c)}
  976. @end example
  977. @example
  978. @verbatim
  979. (ra-cat #t 1 (ra-i 3) abc)
  980. @end verbatim
  981. @result{} @code{#%2:3:2((0 a) (1 b) (2 c))}
  982. @end example
  983. vs
  984. @example
  985. @verbatim
  986. (ra-scat #t -1 (ra-i 3) abc)
  987. @end verbatim
  988. @result{} @code{#%2:3:2((0 a) (1 b) (2 c))}
  989. @end example
  990. @example
  991. @verbatim
  992. (ra-scat #t 0 (ra-i 3) abc)
  993. @end verbatim
  994. @result{} @code{#%1:6(0 1 2 a b c)}
  995. @end example
  996. @example
  997. @verbatim
  998. (ra-scat #t 1 (ra-i 3) abc)
  999. @end verbatim
  1000. @result{} @code{#%2:2:3((0 1 2) (a b c))}
  1001. @end example
  1002. Cf J append (,) stitch (,.).
  1003. @c ------------------------------------------------
  1004. @node Transposition
  1005. @section Transposition
  1006. @c ------------------------------------------------
  1007. @cindex @code{⍉}, transpose
  1008. @cindex transpose
  1009. @ref{x-ra-transpose, @code{ra-transpose}} takes a source array and one axis argument for each of the dimensions of the source array. The values of the arguments are the corresponding axes of the result array.
  1010. @example
  1011. @verbatim
  1012. (ra-dimensions (ra-transpose (ra-i 10 20 30) 2 0 1))
  1013. @end verbatim
  1014. @result{} @code{'(20 30 10)}
  1015. @end example
  1016. That is, axis 0 in the source array is mapped to axis 2 in the destination array, axis 1 to axis 0, and axis 2 to axis 1. The result array always shares the root of the source array.
  1017. As you'd expect
  1018. @example
  1019. @verbatim
  1020. (ra-transpose (ra-i 2 3) 1 0)
  1021. @end verbatim
  1022. @result{} @code{#%2d:3:2((0 3) (1 4) (2 5))}
  1023. @end example
  1024. One can map more than one axis of the source array to the same axis of the destination array. In that case the step of the destination axis becomes the sum of the steps of all the source axes. The classic example is
  1025. @cindex diagonal
  1026. @example
  1027. @verbatim
  1028. (define A (ra-copy #t (ra-i 3 3)))
  1029. (ra-fill! (ra-transpose A 0 0) 'x)
  1030. A
  1031. @end verbatim
  1032. @result{} @code{#%2:3:3((x 1 2) (3 x 5) (6 7 x))}
  1033. @end example
  1034. If one doesn't give values for all of the source axes, the missing axes are sent beyond the highest one that was given. These are equivalent:
  1035. @example
  1036. @verbatim
  1037. (ra-transpose (ra-i 2 3 4) 1 0 2)
  1038. (ra-transpose (ra-i 2 3 4) 1 0) ; fill with (+ 1 (max 1 0))
  1039. @end verbatim
  1040. @end example
  1041. as are these:
  1042. @example
  1043. @verbatim
  1044. (ra-transpose (ra-i 2 3) 1) ; fill with (+ 1 (max 1))
  1045. (ra-transpose (ra-i 2 3) 1 2)
  1046. @end verbatim
  1047. @end example
  1048. Note that in the last example there is no source axis for destination axis 0. Destination axes not mentioned in the axis argument list become @ref{x-dead-axes,dead axes}. The rank of the result array is always just large enough to fit all the destination axes.
  1049. @example
  1050. @verbatim
  1051. (ra-dimensions (ra-transpose (ra-i 2 3) 1))
  1052. @end verbatim
  1053. @result{} (#f 2 3)
  1054. @end example
  1055. In particular, @code{(ra-transpose A)} is equivalent to @code{(ra-transpose A 0 1 ... (- (ra-rank A) 1))} (which is of course the same array as @code{A}).
  1056. @cindex outer product
  1057. This ability of @code{ra-transpose} can be exploited to compute `outer products'. In the following example the shape @code{[2 2]} of @code{A} matches with the two leading dead axes of @code{(ra-transpose B 2)}:
  1058. @example
  1059. @verbatim
  1060. A : [2 2]
  1061. (ra-transpose B 2) : [f f 2 2]
  1062. @end verbatim
  1063. @end example
  1064. @cindex prefix matching
  1065. The trailing axes then match through @ref{Rank extension,prefix matching}.
  1066. @example
  1067. @verbatim
  1068. (define A (list->ra 2 '((a b) (c d))))
  1069. (define B (ra-i 2 2))
  1070. (ra-format (ra-map! (make-ra #f 2 2 2 2)
  1071. (lambda i (format #f "~{~a~}" i))
  1072. A (ra-transpose B 2)))
  1073. @end verbatim
  1074. @result{}
  1075. @verbatim
  1076. #%4:2:2:2:2═╗
  1077. ║a0│a1║b0│b1║
  1078. ║──┼──║──┼──║
  1079. ║a2│a3║b2│b3║
  1080. ╠═════╬═════╣
  1081. ║c0│c1║d0│d1║
  1082. ║──┼──║──┼──║
  1083. ║c2│c3║d2│d3║
  1084. ╚═════╩═════╝
  1085. @end verbatim
  1086. @end example
  1087. @cindex index placeholder
  1088. Another use is the creation of ‘index placeholders’, e.g.
  1089. @example
  1090. @verbatim
  1091. (define (tensor-index i) (ra-transpose (ra-iota) i))
  1092. (ra-format (ra-map! (make-ra #f 3 4) list (tensor-index 0) (tensor-index 1)))
  1093. @end verbatim
  1094. @result{}
  1095. @verbatim
  1096. #%2:3:4─────┬─────┬─────┐
  1097. │(0 0)│(0 1)│(0 2)│(0 3)│
  1098. ├─────┼─────┼─────┼─────┤
  1099. │(1 0)│(1 1)│(1 2)│(1 3)│
  1100. ├─────┼─────┼─────┼─────┤
  1101. │(2 0)│(2 1)│(2 2)│(2 3)│
  1102. └─────┴─────┴─────┴─────┘
  1103. @end verbatim
  1104. @end example
  1105. @cindex ⍋
  1106. @cindex grade
  1107. The function @ref{x-ra-untranspose, @code{ra-untranspose}} takes its axis arguments the other way from @code{ra-transpose}; the value of each argument is the axis of the original array and the position in the argument list is the axis of the result array. This is less flexible than @code{ra-transpose}, but can be used to reverse an application of @code{ra-transpose} without having to sort (‘grade’) the original axis arguments.
  1108. @example
  1109. @verbatim
  1110. (define a (ra-i 2 3 4))
  1111. (ra-equal? a (ra-untranspose (ra-transpose a 2 0 1) 2 0 1))
  1112. @end verbatim
  1113. @result{} @code{#t}
  1114. @end example
  1115. @c @cindex @code{none}
  1116. @c @anchor{x-none}
  1117. @c @deffn @w{Special objects} {none}
  1118. @c For example...
  1119. @c @example
  1120. @c @verbatim
  1121. @c For example
  1122. @c @end verbatim
  1123. @c @end example
  1124. @c @end deffn
  1125. @c ------------------------------------------------
  1126. @node Other operations on arrays
  1127. @section Other operations on arrays
  1128. @c ------------------------------------------------
  1129. @c ------------------------------------------------
  1130. @node Automatic result arrays
  1131. @section Automatic result arrays
  1132. @c ------------------------------------------------
  1133. Most of the functions of @code{newra} do not create arrays, but instead they expect result arrays to be passed as arguments. This means that they must have been allocated before. However, there are a few functions, such as @ref{x-ra-copy, @code{ra-copy}} or @ref{x-ra-map, @code{ra-map}}, that do create a result array. The type and shape of that result array is deduced from the source arguments, as follows.
  1134. @itemize
  1135. @item The default type of the result array is the type of the first of the source arguments. If that type is @code{'d}, however, the default type of the result array is @code{#t}. Usually, a function will allow this default to be overriden with an explicit argument. If that argument is required, then @code{#f} will select the default.
  1136. @item The rank of the result array will be the rank of the source argument with the largest rank. On each dimension, the lower bound and the length of the result will match those of the source arguments, with the precision that if any of those is finite, then it will be finite in the result as well. (If there is only one source argument, as is the case for @code{ra-copy}, then it follows that that is the shape of the result.)
  1137. @end itemize
  1138. For example:
  1139. @example
  1140. @verbatim
  1141. (ra-map #t *
  1142. ; shape '((0 1))
  1143. (ra-iota 2 1)
  1144. ; shape '((#f #f) (1 3))
  1145. (ra-transpose (make-ra 9 '(1 3)) 1))
  1146. @end verbatim
  1147. @result{}
  1148. @verbatim
  1149. ; shape of result is '((0 1) (1 3))
  1150. #%2:2@1:3((9 9 9) (18 18 18)
  1151. @end verbatim
  1152. @end example
  1153. @c ------------------------------------------------
  1154. @node Foreign interface
  1155. @section Foreign interface
  1156. @c ------------------------------------------------
  1157. One of the major reasons to use arrays instead of other Scheme data structures is that they let one pass a large amount of data through a C interface very efficiently. The data doesn't need to be copied — one only needs to pass a pointer to the data, plus the lengths and the steps in some order. C doesn't have a standard consolidated array type, so the particulars are variable. In any case, the required items can be obtained trivially from a @code{newra} array object.
  1158. For example:
  1159. TODO
  1160. @c ------------------------------------------------
  1161. @node Compatibility with old Guile arrays
  1162. @section Compatibility with old Guile arrays
  1163. @c ------------------------------------------------
  1164. The functions @ref{x-ra->array, @code{ra->array}} and @ref{x-array->ra, @code{array->ra}} are provided to convert to and from @code{newra} arrays and built-in Guile arrays. It is an error to use @code{ra->array} on arrays whose root isn't supported by the built-in arrays, or that have an unbounded axis. Except in those two cases, the conversion is transparent both ways, and the result always shares the root of the argument.
  1165. @example
  1166. @verbatim
  1167. (define a (make-array 'o 2 3))
  1168. (define b (array->ra a))
  1169. (ra-set! b 'x 1 1)
  1170. (array-set! a 'y 0 2)
  1171. a
  1172. @end verbatim
  1173. @result{} @code{#2((o o y) (o x o))}
  1174. @verbatim
  1175. b
  1176. @end verbatim
  1177. @result{} @code{#%2((o o y) (o x o))}
  1178. @end example
  1179. @code{<aseq>}-root arrays must be type converted before using @code{ra->array}.
  1180. @example
  1181. @verbatim
  1182. (ra->array (ra-copy #t (ra-i 2 3)))
  1183. @end verbatim
  1184. @result{} #2((0 1 2) (3 4 5))
  1185. @end example
  1186. On dead axes, lengths can be set to 1 (with @ref{x-ra-singletonize, @code{ra-singletonize}}) to allow conversion with @code{ra->array} or to other array systems that do singleton broadcasting.
  1187. @example
  1188. @verbatim
  1189. (define a (ra-transpose (ra-i 2 3) 1 3))
  1190. a
  1191. @end verbatim
  1192. @result{} @code{#%4d:d:2:d:3((((0 1 2)) ((3 4 5))))}
  1193. @verbatim
  1194. (ra-singletonize a)
  1195. @end verbatim
  1196. @result{} @code{#%4d:1:2:1:3((((0 1 2)) ((3 4 5))))}
  1197. @end example
  1198. One important difference between the built-in array functions and @code{newra} is that bounds matching in @code{newra} is strict: finite bounds must be identical for axes to match, while for @code{array-map!}, @code{array-for-each}, @code{array-copy!}, etc. the iteration range is the intersection of the ranges of the arguments@footnote{I decided against this approach for @code{newra} because in my experience it results in errors going undetected much more often than it saves any work.}. @code{newra} provides @ref{x-ra-clip, @code{ra-clip}} to match ranges easily.
  1199. @example
  1200. @verbatim
  1201. (define a (make-ra-root (vector 'a 'b 'c 'd 'e 'f 'g))) ; range is 0..6
  1202. (define b (ra-reshape (ra-iota 4) 0 '(2 5))) ; range is 2..5
  1203. (ra-copy! a b)
  1204. @end verbatim
  1205. @result{} @code{Throw to key `mismatched-lens' with args `(7 4 at-dim 0)'.}
  1206. @verbatim
  1207. (ra-copy! (ra-clip a b) b)
  1208. a
  1209. @end verbatim
  1210. @result{} @code{#%1:7(a b 0 1 2 3 g)}
  1211. @c Cf. using built-in arrays @c Looks like a Guile bug to me :-/
  1212. @c @verbatim
  1213. @c (define a (vector 'a 'b 'c 'd 'e 'f 'g)))
  1214. @c (define b #1@2:4(0 1 2 3))
  1215. @c (array-copy! b a)
  1216. @c a
  1217. @c @end verbatim
  1218. @c @result{} @code{#(0 1 2 3 e f g)}
  1219. @end example
  1220. @c ------------------------------------------------
  1221. @node High level
  1222. @chapter High level
  1223. @c ------------------------------------------------
  1224. NOTE This section is about a facility that hasn't been implemented yet.
  1225. In array languages such as APL, scalar operations are implicitly extended to work on arrays, so one can just write (the equivalent of) @code{(+ A B)} instead of @code{(ra-map! (make-ra ...) + A B)}. The basic @code{newra} iteration operations such as @code{ra-map!} already perform rank extension of their arguments (so @code{A} or @code{B} can have a different rank from the result, as long as the prefix axes match). We still need ways to:
  1226. @itemize
  1227. @item associate an operation to the ranks of their arguments, so that the right frame of iteration can be chosen.
  1228. @item compute the shape and type of the result (if any).
  1229. @item handle scalar (non-array) arguments.
  1230. @end itemize
  1231. @menu
  1232. * Verbs::
  1233. * Reductions::
  1234. @end menu
  1235. @c ------------------------------------------------
  1236. @node Verbs
  1237. @section Verbs
  1238. @c ------------------------------------------------
  1239. @c ------------------------------------------------
  1240. @node Reductions
  1241. @section Reductions
  1242. @c ------------------------------------------------
  1243. @c ------------------------------------------------
  1244. @node Hazards
  1245. @chapter Hazards
  1246. @c ------------------------------------------------
  1247. @menu
  1248. * Differences with...::
  1249. * Common mistakes::
  1250. * Performance pitfalls::
  1251. @end menu
  1252. @c ------------------------------------------------
  1253. @node Differences with...
  1254. @section Differences with...
  1255. @c ------------------------------------------------
  1256. If you come to @code{newra} from another array language or library, you may want to be aware of some of these differences. See also the @ref{Cheatsheet}.
  1257. Differences with built-in Guile arrays:
  1258. @itemize
  1259. @item @code{newra} map operations are rank-extending but require exact agreement of bounds, unlike operations on built-in arrays, which require exact rank agreement but admit overlapping bounds.
  1260. @end itemize
  1261. @cindex APL
  1262. Differences with APL:
  1263. @itemize
  1264. @item The default lower bound (base index) in @code{newra} is 0, as in @code{⎕io←0}. The lower bound isn't global, but it may be different per axis.
  1265. @item @code{newra} arrays of size 1 are not equivalent to scalars and always retain their rank. For example, @code{(make-ra 99)}, @code{(make-ra 99 1)} and @code{(make-ra 99 1 1)} are all different from each other and from the scalar @code{99}, while in APL @code{99}, @code{(1 ⍴ 99)}, and @code{(1 1 ⍴ 99)} are all the same thing.
  1266. @item When a function takes multiple arguments, the meaning with multiple arguments is an extension of the meaning with a single argument. This contrasts with APL where the monadic and dyadic versions of a verb usually have a related but independent definition. For example @code{(ra-transpose a)}≡@code{(ra-transpose a 0)}≡@code{(ra-transpose a 0 1)}, but (assuming @code{a} is of rank 2) @code{⍉a}≡@code{2 1⍉a}. Please check the documentation for each function.
  1267. @end itemize
  1268. @cindex Fortran
  1269. Differences with Fortran:
  1270. @itemize
  1271. @item The default lower bound (base index) in @code{newra} is 0, not 1. Like in Fortran, the lower bound may be different for each axis of each array.
  1272. @item Unlike Fortran, the default element order in arrays is row-major, or ‘last index changes fastest’. It's possible to define and manipulate arrays in any other order, including Fortran's default. However, some functions (such as @code{ra-ravel}) only support row-major order.
  1273. @item @code{newra} uses prefix matching for rank extension on arguments on any rank, while Fortran only performs rank extension on scalar arguments.
  1274. @end itemize
  1275. @cindex Python
  1276. @cindex NumPy
  1277. Differences with NumPy:
  1278. @itemize
  1279. @item @code{newra} uses prefix matching for rank extension, while Numpy uses suffix matching. For example: FIXME.
  1280. @item @code{newra} doesn't use singleton broadcasting. Axes of length 1 only match axes of length 1. For example, @code{(ra-map! (make-ra 0 2) + (make-ra 90 1) (make-ra 7 2))} is an error because the shapes (2), (1), (2) don't agree.
  1281. @end itemize
  1282. @cindex Octave
  1283. @cindex Matlab
  1284. Differences with Octave:
  1285. @itemize
  1286. @item The default lower bound (base index) in @code{newra} is 0, not 1. Lower bounds may be 1 on a particular array (or particular axes of an array), but not globally.
  1287. @item In Octave, any array of rank ≤ 2 is implicity a matrix (an array of rank 2). This isn't true in @code{newra}, so, for example, an array of rank 1 isn't equivalent to an array of rank 2 with a single row (a ‘row vector’).
  1288. @item Unlike Octave, the default element order in arrays is row-major, or ‘last index changes fastest’. It's possible to define and manipulate arrays in any other order, including Octave's default. However, some functions (such as @code{ra-ravel}) only support row-major order.
  1289. @item @code{newra} uses prefix matching for rank extension on arguments on any rank, while Octave only performs rank extension on scalar arguments.
  1290. @end itemize
  1291. @c ------------------------------------------------
  1292. @node Common mistakes
  1293. @section Common mistakes
  1294. @c ------------------------------------------------
  1295. @c ------------------------------------------------
  1296. @node Performance pitfalls
  1297. @section Performance pitfalls
  1298. @c ------------------------------------------------
  1299. @c ------------------------------------------------
  1300. @node Reference
  1301. @chapter Reference
  1302. @c ------------------------------------------------
  1303. @cindex @code{array->ra}
  1304. @anchor{x-array->ra}
  1305. @deffn @w{Function} array->ra a
  1306. Convert built-in Guile array @var{a} (anything that satisfies @code{array?}) into a (@code{newra)} array.
  1307. This function doesn't create a copy of the array, but reuses the root (@code{shared-array-root}) of @var{a}, that is, @code{(eq? (ra-root (array->ra a)) (shared-array-root a))} is @code{#t}.
  1308. @example
  1309. @verbatim
  1310. (define a (make-array 'x 2 2))
  1311. (define b (array->ra v))
  1312. b
  1313. @end verbatim
  1314. @result{} @code{#%2:2:2((x x) (x x))}
  1315. @verbatim
  1316. (ra-fill! b 'y)
  1317. a
  1318. @end verbatim
  1319. @result{} @code{#2((y y) (y y))}
  1320. @end example
  1321. See also: @ref{x-ra->array,@code{ra->array}}.
  1322. @end deffn
  1323. @cindex @code{c-dims}
  1324. @anchor{x-c-dims}
  1325. @deffn @w{Function} c-dims bounds ...
  1326. @cindex packed array
  1327. Create dims for row-major order array (packed elements, last dimension changing fastest).
  1328. Each of the bounds may be a pair of bounds (@var{lo} @var{hi}) or a single length @var{len}, which implies zero @var{lo}.
  1329. @example
  1330. @verbatim
  1331. (c-dims 2 3)
  1332. @end verbatim
  1333. @result{} @code{#(#<<dim> len: 2 lo: 0 step: 3> #<<dim> len: 3 lo: 0 step: 1>)}
  1334. @end example
  1335. @end deffn
  1336. @cindex @code{ldots}
  1337. @anchor{x-ldots}
  1338. @deffn @w{Function} ldots [n] ...
  1339. Placeholder for @var{n} full axes, used as argument to @code{ra-from} or @code{ra-amend!}. Without @var{n}, expand to fill the rank of the argument @var{a} of @ref{x-ra-from,@code{ra-from}} or @ref{x-ra-amend!,@code{ra-amend!}}.
  1340. @end deffn
  1341. @cindex @code{make-ra}
  1342. @anchor{x-make-ra}
  1343. @deffn @w{Function} make-ra val bounds ... @result{} a
  1344. Create an array of type @code{#t} with the given @var{bounds}, filled with @var{val}.
  1345. @example
  1346. @verbatim
  1347. (make-ra 0 '(2 3) 4)
  1348. @end verbatim
  1349. @result{} @code{#%2@@2:2:4((0 0 0 0) (0 0 0 0))}
  1350. @end example
  1351. See also: @ref{x-make-typed-ra,@code{make-typed-ra}}, @ref{x-make-ra-new,@code{ra-make-ra-new}}, @ref{x-ra-shape,@code{ra-shape}}.
  1352. @end deffn
  1353. @cindex @code{make-ra-new}
  1354. @anchor{x-make-ra-new}
  1355. @deffn @w{Function} make-ra-new type value dims
  1356. Create an array over a new root of the given @var{type} and size (according to @var{dims}), and fill it with @var{value}.
  1357. @example
  1358. @verbatim
  1359. (make-ra-new 'u8 0 (c-dims 3 2))
  1360. @end verbatim
  1361. @result{} #%2u8:3:2((0 0) (0 0) (0 0))
  1362. @end example
  1363. @end deffn
  1364. @cindex @code{make-ra-root}
  1365. @anchor{x-make-ra-root}
  1366. @deffn @w{Function} make-ra-root root [dims [zero]]
  1367. Create an array over the given @var{root}.
  1368. @example
  1369. @verbatim
  1370. (make-ra-root (vector 1 2 3))
  1371. @end verbatim
  1372. @result{} #%1d:3(1 2 3)
  1373. @end example
  1374. @example
  1375. @verbatim
  1376. (make-ra-root (vector 1 2 3) (vector (make-dim 2)))
  1377. @end verbatim
  1378. @result{} #%1d:2(1 2)
  1379. @end example
  1380. @example
  1381. @verbatim
  1382. (make-ra-root (vector 1 2 3) (vector (make-dim 2)) 1)
  1383. @end verbatim
  1384. @result{} #%1d:2(2 3)
  1385. @end example
  1386. @end deffn
  1387. @cindex @code{make-typed-ra}
  1388. @anchor{x-make-typed-ra}
  1389. @deffn @w{Function} make-typed-ra type val bounds ... @result{} a
  1390. Same as @ref{x-make-ra,@code{make-ra}}, except that the result has the specified @var{type}.
  1391. See also: @ref{x-make-ra,@code{make-ra}}, @ref{x-make-ra-root,@code{ra-make-ra-root}}.
  1392. @end deffn
  1393. @cindex intersection
  1394. @cindex @code{ra-clip}
  1395. @anchor{x-ra-clip}
  1396. @deffn @w{Function} ra-clip a b @result{} c
  1397. Slice @var{a} to the intersection of the bounds of @var{a} and @var{b}. If @var{a} and @var{b} have different ranks, only the common prefix of @var{a} is sliced.
  1398. @example
  1399. @verbatim
  1400. (define f (make-ra " " '(-4 4) '(-5 3)))
  1401. (define a (make-ra " A " '(-3 0) '(-4 1)))
  1402. (define b (make-ra " B " '(-1 3) '(-1 2)))
  1403. (ra-fill! (ra-clip a b) " x ")
  1404. (ra-copy! (ra-clip f b) (ra-clip b f))
  1405. (ra-copy! (ra-clip f a) (ra-clip a f))
  1406. (ra-format f)
  1407. @end verbatim
  1408. @result{}
  1409. @verbatim
  1410. #%2@-4:9@-5:9───┬───┬───┬───┬───┬───┐
  1411. │ │ │ │ │ │ │ │ │ │
  1412. ├───┼───┼───┼───┼───┼───┼───┼───┼───┤
  1413. │ │ A │ A │ A │ A │ A │ A │ │ │
  1414. ├───┼───┼───┼───┼───┼───┼───┼───┼───┤
  1415. │ │ A │ A │ A │ A │ A │ A │ │ │
  1416. ├───┼───┼───┼───┼───┼───┼───┼───┼───┤
  1417. │ │ A │ A │ A │ x │ x │ x │ B │ │
  1418. ├───┼───┼───┼───┼───┼───┼───┼───┼───┤
  1419. │ │ A │ A │ A │ x │ x │ x │ B │ │
  1420. ├───┼───┼───┼───┼───┼───┼───┼───┼───┤
  1421. │ │ │ │ │ B │ B │ B │ B │ │
  1422. ├───┼───┼───┼───┼───┼───┼───┼───┼───┤
  1423. │ │ │ │ │ B │ B │ B │ B │ │
  1424. ├───┼───┼───┼───┼───┼───┼───┼───┼───┤
  1425. │ │ │ │ │ B │ B │ B │ B │ │
  1426. ├───┼───┼───┼───┼───┼───┼───┼───┼───┤
  1427. │ │ │ │ │ │ │ │ │ │
  1428. └───┴───┴───┴───┴───┴───┴───┴───┴───┘
  1429. @end verbatim
  1430. @verbatim
  1431. (ra-fill! (ra-clip f (ra-clip a b)) " o ")
  1432. (ra-format f)
  1433. @end verbatim
  1434. @result{}
  1435. @verbatim
  1436. #%2@-4:9@-5:9───┬───┬───┬───┬───┬───┐
  1437. │ │ │ │ │ │ │ │ │ │
  1438. ├───┼───┼───┼───┼───┼───┼───┼───┼───┤
  1439. │ │ A │ A │ A │ A │ A │ A │ │ │
  1440. ├───┼───┼───┼───┼───┼───┼───┼───┼───┤
  1441. │ │ A │ A │ A │ A │ A │ A │ │ │
  1442. ├───┼───┼───┼───┼───┼───┼───┼───┼───┤
  1443. │ │ A │ A │ A │ o │ o │ o │ B │ │
  1444. ├───┼───┼───┼───┼───┼───┼───┼───┼───┤
  1445. │ │ A │ A │ A │ o │ o │ o │ B │ │
  1446. ├───┼───┼───┼───┼───┼───┼───┼───┼───┤
  1447. │ │ │ │ │ B │ B │ B │ B │ │
  1448. ├───┼───┼───┼───┼───┼───┼───┼───┼───┤
  1449. │ │ │ │ │ B │ B │ B │ B │ │
  1450. ├───┼───┼───┼───┼───┼───┼───┼───┼───┤
  1451. │ │ │ │ │ B │ B │ B │ B │ │
  1452. ├───┼───┼───┼───┼───┼───┼───┼───┼───┤
  1453. │ │ │ │ │ │ │ │ │ │
  1454. └───┴───┴───┴───┴───┴───┴───┴───┴───┘
  1455. @end verbatim
  1456. @end example
  1457. The result of @code{ra-clip} always shares the root of its first argument @var{a}.
  1458. See also: @ref{Slicing}, @ref{Compatibility with old Guile arrays}.
  1459. @end deffn
  1460. @cindex @code{ra-dimensions}
  1461. @anchor{x-ra-dimensions}
  1462. @deffn @w{Function} ra-dimensions a
  1463. Return the dimensions of @var{a} as a list, like @ref{x-ra-shape,@code{ra-shape}}, but the dimensions that have lower bound zero are represented by their length alone, instead of a two-element list @code{(lo hi)}. This is a convenience for the common case when lower bounds are zero.
  1464. @example
  1465. @verbatim
  1466. (ra-dimensions (make-ra 0 '(2 3) 4))
  1467. @end verbatim
  1468. @result{} @code{((2 3) 4)}
  1469. @verbatim
  1470. (ra-shape (make-ra 0 '(2 3) 4))
  1471. @end verbatim
  1472. @result{} @code{((2 3) (0 3))}
  1473. @end example
  1474. See also: @ref{x-ra-shape,@code{ra-shape}}, @ref{x-make-ra,@code{make-ra}}.
  1475. @end deffn
  1476. @cindex @code{ra-format}
  1477. @anchor{x-ra-format}
  1478. @deffn @w{Function} ra-format ra port #:fmt #:prefix?
  1479. @deffnx @w{Function} ra-format ra #f #:fmt #:prefix? @result{} sc
  1480. Pretty print array @var{ra}.
  1481. Each element @var{x} of @var{ra} is converted to a string using @code{(fmt x)}, or @code{(format #f fmt x)}@footnote{@url{https://www.gnu.org/software/guile/manual/html_node/Formatted-Output.html,@code{(ice-9 format)}}} if @var{fmt} is a string. @var{fmt} defauts to @code{"~a"}. Elements that are arrays are formatted using @code{ra-format} recursively.
  1482. If @var{port} is @code{#f}, nothing is printed; instead, the function returns a rank-2 character array @var{sc} with the result of the printing. Otherwise the array is printed to @var{port} and the function returns unspecified values. The default for @var{port} is @code{#t}, which works as @code{current-output-port}.
  1483. If @var{prefix?} is true, the array print prefix @ref{x-ra-print-prefix,@code{ra-print-prefix}} is printed over the first line of the printout if the rank of @var{ra} is 2 or greater, else it is printed on a separate line above the printout.
  1484. If @var{compact?} is true, the separators for the rank-0 cells are replaced by spaces and the separators for the rank-1 cells are omitted. This results in a more compact output at the cost of some clarity.
  1485. This function handles arrays of rank up to 8, or up to 10 in compact mode. The even dimensions (counting from the last one) are arranged horizontally, while the odd dimensions are arranged vertically. The dimensions are separated visually using @url{https://unicode.org/charts/nameslist/n_2500.html,box-drawing characters}. This might look better or worse depending on the font.
  1486. A 0-array:
  1487. @example
  1488. @verbatim
  1489. (ra-format (make-ra 'element))
  1490. @end verbatim
  1491. @result{}
  1492. @verbatim
  1493. #%0
  1494. element
  1495. @end verbatim
  1496. @end example
  1497. A 1-array:
  1498. @example
  1499. @verbatim
  1500. (ra-format (ra-i 4))
  1501. @end verbatim
  1502. @result{}
  1503. @verbatim
  1504. #%1d:4
  1505. │0│1│2│3│
  1506. @end verbatim
  1507. @end example
  1508. Compare with the 2-array
  1509. @example
  1510. @verbatim
  1511. (ra-format (ra-i 1 4))
  1512. @end verbatim
  1513. @result{}
  1514. @verbatim
  1515. #%2d:1:4┐
  1516. │0│1│2│3│
  1517. └─┴─┴─┴─┘
  1518. @end verbatim
  1519. @end example
  1520. Another 2-array:
  1521. @example
  1522. @verbatim
  1523. (ra-format (ra-i 3 4) #:prefix? #f)
  1524. @end verbatim
  1525. @result{}
  1526. @verbatim
  1527. ┌─┬─┬──┬──┐
  1528. │0│1│ 2│ 3│
  1529. ├─┼─┼──┼──┤
  1530. │4│5│ 6│ 7│
  1531. ├─┼─┼──┼──┤
  1532. │8│9│10│11│
  1533. └─┴─┴──┴──┘
  1534. @end verbatim
  1535. @end example
  1536. A 5-array:
  1537. @example
  1538. @verbatim
  1539. (ra-format (ra-i 2 2 3 2 4) #:prefix? #f)
  1540. @end verbatim
  1541. @result{}
  1542. @verbatim
  1543. ┃═══════════╦═══════════╦═══════════┃═══════════╦═══════════╦═══════════┃
  1544. ┃ 0│ 1│ 2│ 3║ 8│ 9│10│11║16│17│18│19┃48│49│50│51║56│57│58│59║64│65│66│67┃
  1545. ┃──┼──┼──┼──║──┼──┼──┼──║──┼──┼──┼──┃──┼──┼──┼──║──┼──┼──┼──║──┼──┼──┼──┃
  1546. ┃ 4│ 5│ 6│ 7║12│13│14│15║20│21│22│23┃52│53│54│55║60│61│62│63║68│69│70│71┃
  1547. ┃═══════════╬═══════════╬═══════════┃═══════════╬═══════════╬═══════════┃
  1548. ┃24│25│26│27║32│33│34│35║40│41│42│43┃72│73│74│75║80│81│82│83║88│89│90│91┃
  1549. ┃──┼──┼──┼──║──┼──┼──┼──║──┼──┼──┼──┃──┼──┼──┼──║──┼──┼──┼──║──┼──┼──┼──┃
  1550. ┃28│29│30│31║36│37│38│39║44│45│46│47┃76│77│78│79║84│85│86│87║92│93│94│95┃
  1551. ┃═══════════╩═══════════╩═══════════┃═══════════╩═══════════╩═══════════┃
  1552. @end verbatim
  1553. @end example
  1554. The same 5-array in compact mode:
  1555. @example
  1556. @verbatim
  1557. (ra-format (ra-i 2 2 3 2 4) #:prefix? #f #:compact? #t)
  1558. @end verbatim
  1559. @result{}
  1560. @verbatim
  1561. ║───────────┬───────────┬───────────║───────────┬───────────┬───────────║
  1562. ║ 0 1 2 3│ 8 9 10 11│16 17 18 19║48 49 50 51│56 57 58 59│64 65 66 67║
  1563. ║ 4 5 6 7│12 13 14 15│20 21 22 23║52 53 54 55│60 61 62 63│68 69 70 71║
  1564. ║───────────┼───────────┼───────────║───────────┼───────────┼───────────║
  1565. ║24 25 26 27│32 33 34 35│40 41 42 43║72 73 74 75│80 81 82 83│88 89 90 91║
  1566. ║28 29 30 31│36 37 38 39│44 45 46 47║76 77 78 79│84 85 86 87│92 93 94 95║
  1567. ║───────────┴───────────┴───────────║───────────┴───────────┴───────────║
  1568. @end verbatim
  1569. @end example
  1570. @cindex SRFI-163
  1571. A nested array (example from @mybibcite{SRFI-163}):
  1572. @example
  1573. @verbatim
  1574. (ra-format (call-with-input-string "#%2@1:2@1:3((#%2((1 2) (3 4)) 9 #%2((3 4) (5 6)))
  1575. (#%(42 43) #%2((8 7 6)) #%2((90 91) (100 101))))))"
  1576. read))
  1577. @end verbatim
  1578. @result{}
  1579. @verbatim
  1580. #%2@1:2@1:3─────┬─────────┐
  1581. │#%2:2:2│ 9│ #%2:2:2│
  1582. ││1│2│ │ │ │3│4│ │
  1583. │├─┼─┤ │ │ ├─┼─┤ │
  1584. ││3│4│ │ │ │5│6│ │
  1585. │└─┴─┘ │ │ └─┴─┘ │
  1586. ├───────┼───────┼─────────┤
  1587. │#%1:2 │#%2:1:3│#%2:2:2─┐│
  1588. ││42│43│││8│7│6│││ 90│ 91││
  1589. │ │└─┴─┴─┘│├───┼───┤│
  1590. │ │ ││100│101││
  1591. │ │ │└───┴───┘│
  1592. └───────┴───────┴─────────┘
  1593. @end verbatim
  1594. @end example
  1595. Looking at the return value when @var{port} is @code{#f}:
  1596. @example
  1597. @verbatim
  1598. (ra-format (ra-format (ra-i 2 3) #f #:prefix? #f) #:prefix? #f)
  1599. @end verbatim
  1600. @result{}
  1601. @verbatim
  1602. ┌─┬─┬─┬─┬─┬─┬─┐
  1603. │┌│─│┬│─│┬│─│┐│
  1604. ├─┼─┼─┼─┼─┼─┼─┤
  1605. │││0│││1│││2│││
  1606. ├─┼─┼─┼─┼─┼─┼─┤
  1607. │├│─│┼│─│┼│─│┤│
  1608. ├─┼─┼─┼─┼─┼─┼─┤
  1609. │││3│││4│││5│││
  1610. ├─┼─┼─┼─┼─┼─┼─┤
  1611. │└│─│┴│─│┴│─│┘│
  1612. └─┴─┴─┴─┴─┴─┴─┘
  1613. @end verbatim
  1614. @end example
  1615. Using a custom element formatter:
  1616. @example
  1617. @verbatim
  1618. (ra-format (ra-map! (make-ra #f 4 4) sqrt (ra-reshape (ra-iota 20 -10) 0 4 4))
  1619. #:fmt (lambda (x) (format #f (cond ((real? x) "~4,2f")
  1620. ((complex? x) "~4,2i")
  1621. (else "~a"))
  1622. x)))
  1623. @end verbatim
  1624. @result{}
  1625. @verbatim
  1626. #%2:4:4────┬──────────┬──────────┬──────────┐
  1627. │0.00+3.16i│0.00+3.00i│0.00+2.83i│0.00+2.65i│
  1628. ├──────────┼──────────┼──────────┼──────────┤
  1629. │0.00+2.45i│0.00+2.24i│0.00+2.00i│0.00+1.73i│
  1630. ├──────────┼──────────┼──────────┼──────────┤
  1631. │0.00+1.41i│0.00+1.00i│ 0.00│ 1.00│
  1632. ├──────────┼──────────┼──────────┼──────────┤
  1633. │ 1.41│ 1.73│ 2.00│ 2.24│
  1634. └──────────┴──────────┴──────────┴──────────┘
  1635. @end verbatim
  1636. @end example
  1637. If any of the lengths of @var{ra} is 0, only the prefix is printed.
  1638. This function doesn't handle large arrays in any particular way. User beware!
  1639. See also: @ref{x-ra-print,@code{ra-print}}, @ref{x-star-ra-print-star, @code{*ra-print*}}.
  1640. @end deffn
  1641. @cindex @code{ra-i}
  1642. @anchor{x-ra-i}
  1643. @deffn @w{Function} ra-i bounds ...
  1644. Create multidimensional index array with the given bounds.
  1645. The root is of type @code{d}. The first upper bound that isn't @code{#f} may be @code{#t}; this creates an unbounded axis.
  1646. @example
  1647. @verbatim
  1648. (ra-i 2 3 4)
  1649. @end verbatim
  1650. @result{} #%3d:2:3:4(((0 1 2 3) (4 5 6 7) (8 9 10 11)) ((12 13 14 15) (16 17 18 19) (20 21 22 23)))
  1651. @end example
  1652. See also: @ref{x-ra-iota,@code{ra-iota}}, @ref{x-ra-index-map!,@code{ra-index-map!}}. @footnote{Cf. @code{array-index} from @mybibcite{SRFI-164}.}
  1653. @end deffn
  1654. @cindex @code{ra-iota}
  1655. @anchor{x-ra-iota}
  1656. @deffn @w{Function} ra-iota len [lo [step]]
  1657. @deffnx @w{Function} ra-iota
  1658. Create rank-1 index array. The root is of type @code{d}. @var{lo} defaults to 0 and @var{step} to 1.
  1659. @example
  1660. @verbatim
  1661. (ra-iota 4 3 -1)
  1662. @end verbatim
  1663. @result{} #%1d:4(3 2 1 0)
  1664. @end example
  1665. @code{(ra-iota)} is unbounded both ways, e.g.
  1666. @example
  1667. @verbatim
  1668. (ra-shape (ra-iota))
  1669. @end verbatim
  1670. @result{} @code{((#f #f))}
  1671. @verbatim
  1672. ((ra-iota) -100000000000)
  1673. @end verbatim
  1674. @result{} -100000000000
  1675. @end example
  1676. See also: @ref{x-ra-i,@code{ra-i}}.
  1677. @end deffn
  1678. @cindex @code{ra-cat}
  1679. @anchor{x-ra-cat}
  1680. @deffn @w{Function} ra-cat type i a ... @result{} b
  1681. Concatenate arrays @var{a} ... along axis @var{i}. The arguments are prefix-matched and rank extended before concatenation. All axes must match, other than the concatenation axis.
  1682. This function always produces a new array, of the type given. If @var{type} is @code{#f} then the type of the first @var{a} is used, unless that is @code{d}, in which case @code{#t} is used. The lower bound in the concatenation axis of the result is 0; the lower bounds of the arguments in the concatenation axis are ignored.
  1683. @example
  1684. @verbatim
  1685. (ra-cat #f 1 #%1(a b) #%2((0 1) (2 3)))
  1686. @end verbatim
  1687. @result{} #%2((a 0 1) (b 2 3))
  1688. @end example
  1689. See also: @ref{x-ra-scat,@code{ra-scat}}, @ref{x-ra-tile,@code{ra-tile}}, @ref{Concatenation}.
  1690. @end deffn
  1691. @cindex @code{ra-print}
  1692. @anchor{x-ra-print}
  1693. @deffn @w{Function} ra-print ra [port]
  1694. Print an array to @var{port}. @var{port} defaults to @code{(current-output-port)}.
  1695. This is the default array printer. The result is meant to be back-readable, although some special arrays are not supported yet.
  1696. See also: @ref{x-ra-format,@code{ra-format}}, @ref{x-star-ra-print-star,@code{*ra-print*}}, @ref{x-star-ra-parenthesized-rank-zero-star, @code{*ra-parenthesized-rank-zero*}}.
  1697. @end deffn
  1698. @cindex @code{print prefix}
  1699. @cindex @code{ra-print-prefix}
  1700. @anchor{x-ra-print-prefix}
  1701. @deffn @w{Function} ra-print-prefix ra port #:dims?
  1702. Return the print prefix for array @var{ra}. This is a string that details the type, rank, and (optionally) the dimensions of @var{ra}, and is part of the default read syntax for arrays. This is the same syntax as that of the @url{https://www.gnu.org/software/guile/manual/html_node/Array-Syntax.html,the built in Guile arrays}, except that @var{dims?} defaults to true and @code{#%} is used instead of @code{#}.
  1703. This function is provided by the module @code{(newra print)}.
  1704. @example
  1705. @verbatim
  1706. (call-with-output-string (cut ra-print-prefix (make-ra 4 '(3 4) '(2 3)) <>))
  1707. @end verbatim
  1708. @result{} @code{"#%2@@3:2@@2:2"}
  1709. @end example
  1710. @example
  1711. @verbatim
  1712. (call-with-output-string (cut ra-print-prefix (make-ra 4 '(3 4) '(2 3)) <> #:dims? #t))
  1713. @end verbatim
  1714. @result{} @code{"#%2@@3@@2"}
  1715. @end example
  1716. See also: @ref{x-ra-format,@code{ra-format}}, @ref{Writing and reading}.
  1717. @end deffn
  1718. @cindex @code{ra-ravel}
  1719. @anchor{x-ra-ravel}
  1720. @deffn @w{Function} ra-ravel a [n [org]] @result{} b
  1721. Ravel axes [@var{org} ... @var{org}+@var{n}) of array @var{a} in row-major order. @var{n} defaults to the rank of @var{a} and @var{org} defaults to 0.
  1722. For example:
  1723. @example
  1724. @verbatim
  1725. (ra-ravel (ra-i 2 3))
  1726. @end verbatim
  1727. @result{} #%1d:6(0 1 2 3 4 5)
  1728. @end example
  1729. Consider this 3-array:
  1730. @example
  1731. @verbatim
  1732. (ra-format (ra-i 2 3 4))
  1733. @end verbatim
  1734. @result{}
  1735. @verbatim
  1736. #%3d:2:3:4║──┬──┬──┬──║
  1737. ║0│1│ 2│ 3║12│13│14│15║
  1738. ║─┼─┼──┼──║──┼──┼──┼──║
  1739. ║4│5│ 6│ 7║16│17│18│19║
  1740. ║─┼─┼──┼──║──┼──┼──┼──║
  1741. ║8│9│10│11║20│21│22│23║
  1742. ║─┴─┴──┴──║──┴──┴──┴──║
  1743. @end verbatim
  1744. @end example
  1745. Ravel axes 0..1:
  1746. @example
  1747. @verbatim
  1748. (ra-format (ra-ravel (ra-i 2 3 4) 2)) ; or (ra-ravel ... 2 0)
  1749. @end verbatim
  1750. @result{}
  1751. @verbatim
  1752. #%2d:6:4─┬──┐
  1753. │ 0│ 1│ 2│ 3│
  1754. ├──┼──┼──┼──┤
  1755. │ 4│ 5│ 6│ 7│
  1756. ├──┼──┼──┼──┤
  1757. │ 8│ 9│10│11│
  1758. ├──┼──┼──┼──┤
  1759. │12│13│14│15│
  1760. ├──┼──┼──┼──┤
  1761. │16│17│18│19│
  1762. ├──┼──┼──┼──┤
  1763. │20│21│22│23│
  1764. └──┴──┴──┴──┘
  1765. @end verbatim
  1766. @end example
  1767. Ravel axes 1..2:
  1768. @example
  1769. @verbatim
  1770. (ra-format (ra-ravel (ra-i 2 3 4) 2 1))
  1771. @end verbatim
  1772. @result{}
  1773. @verbatim
  1774. @end verbatim
  1775. #%2d:2:12┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
  1776. │ 0│ 1│ 2│ 3│ 4│ 5│ 6│ 7│ 8│ 9│10│11│
  1777. ├──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┤
  1778. │12│13│14│15│16│17│18│19│20│21│22│23│
  1779. └──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┘
  1780. @end example
  1781. To ravel other combinations of axes, use @ref{Transposition}.
  1782. @cindex packed array
  1783. The full ravel of an array doesn't necessarily result in a rank-1 `packed' array, that is, one where the step is 1. If that is required, one can use @code{(ra-ravel (ra-copy ra))}. @footnote{This works because @ref{x-ra-order-c?, @code{ra-order-c?}} is always true for the result of @code{ra-copy}. Note that the ravel operation in @code{(ra-ravel (ra-copy ra))} is free, while it might not be in @code{(ra-copy (ra-ravel ra))}, so it is preferable, in principle, to copy first.}.
  1784. See also: @ref{x-ra-reshape,@code{ra-reshape}}, @ref{x-ra-tile,@code{ra-tile}}, @ref{Reshaping}.
  1785. @end deffn
  1786. @cindex @code{ra-reshape}
  1787. @anchor{x-ra-reshape}
  1788. @deffn @w{Function} ra-reshape a k bounds ... @result{} b
  1789. Reshape axis @var{k} of array @var{a} to @var{bounds}.
  1790. Each of the bounds may be an integer (a length) or a pair of integers (lower and upper bounds).
  1791. @example
  1792. @verbatim
  1793. (define a (ra-i 4 3))
  1794. (ra-format a)
  1795. @end verbatim
  1796. @result{}
  1797. @verbatim
  1798. #%2d:4:3┐
  1799. │0│ 1│ 2│
  1800. ├─┼──┼──┤
  1801. │3│ 4│ 5│
  1802. ├─┼──┼──┤
  1803. │6│ 7│ 8│
  1804. ├─┼──┼──┤
  1805. │9│10│11│
  1806. └─┴──┴──┘
  1807. @end verbatim
  1808. @verbatim
  1809. (ra-format (ra-reshape a 0 2 2))
  1810. @end verbatim
  1811. @result{}
  1812. @verbatim
  1813. #%3d:2:2:3─┬──║
  1814. ║0│1│2║6│ 7│ 8║
  1815. ║─┼─┼─║─┼──┼──║
  1816. ║3│4│5║9│10│11║
  1817. ║─┴─┴─║─┴──┴──║
  1818. @end verbatim
  1819. @end example
  1820. The result of @code{ra-reshape} always shares the root of @var{a}.
  1821. It is an error if the product of the lengths in @var{bounds} exceeds the length of axis @var{k} of @var{a}. For example
  1822. @example
  1823. @verbatim
  1824. (ra-reshape (ra-i 8 2) 0 2 3)
  1825. @end verbatim
  1826. @result{} @code{#%3d:2:3:2(((0 1) (2 3) (4 5)) ((6 7) (8 9) (10 11))} ; ok, 8 can be reshaped into 2·3
  1827. @verbatim
  1828. (ra-reshape (ra-i 8 2) 0 4 3)
  1829. @end verbatim
  1830. @result{} error ; 8 cannot be reshaped into 4·3
  1831. @end example
  1832. @cindex bounds
  1833. @code{ra-reshape} may be used to change either of the bounds of an axis, not only its length. For example
  1834. @example
  1835. @verbatim
  1836. (ra-format (ra-i 2 3))
  1837. @end verbatim
  1838. @result {}
  1839. @verbatim
  1840. #%2d:2:3
  1841. │0│1│2│
  1842. ├─┼─┼─┤
  1843. │3│4│5│
  1844. └─┴─┴─┘
  1845. @end verbatim
  1846. @end example
  1847. @example
  1848. @verbatim
  1849. (ra-format (ra-reshape (ra-i 2 3) 0 '(1 2)))
  1850. @end verbatim
  1851. @result {}
  1852. @verbatim
  1853. #%2d@1:2:3
  1854. │0│1│2│
  1855. ├─┼─┼─┤
  1856. │3│4│5│
  1857. └─┴─┴─┘
  1858. @end verbatim
  1859. @end example
  1860. See also: @ref{x-ra-ravel,@code{ra-ravel}}, @ref{x-ra-tile,@code{ra-tile}}, @ref{Reshaping}.
  1861. @end deffn
  1862. @cindex @code{⌽}, reverse
  1863. @cindex @code{ra-reverse}
  1864. @anchor{x-ra-reverse}
  1865. @deffn @w{Function} ra-reverse a axes ... @result{} b
  1866. Reverse the given @var{axes} of @var{a}.
  1867. @example
  1868. @verbatim
  1869. (ra-reverse (ra-i 2 3) 0 1)
  1870. @end verbatim
  1871. @result{} #%1d:2:3((5 4 3) (2 1 0))
  1872. @end example
  1873. The reversed array shares the root of @var{a}.
  1874. See also: @ref{x-ra-rotate,@code{ra-rotate}}, @ref{x-ra-rotate,@code{ra-rotate!}}.
  1875. @end deffn
  1876. @cindex @code{⌽}, rotate
  1877. @cindex @code{⊖}, rowel
  1878. @cindex @code{ra-rotate}
  1879. @anchor{x-ra-rotate}
  1880. @deffn @w{Function} ra-rotate n a @result{} b
  1881. (FIXME: not implemented) Rotate the first axis of @var{a} toward the lower indices (‘to the left’) @var{n} times. @var{n} may be any integer. The result has the type of @var{a}, unless that type is @code{d}, in which case the result is of type @code{#t}.
  1882. This function always returns a new array.
  1883. Example:
  1884. @example
  1885. @verbatim
  1886. (ra-rotate 1 (ra-i 3 2))
  1887. @end verbatim
  1888. @result{} #%1:3:2((2 3) (4 5) (0 1))
  1889. @end example
  1890. See also: @ref{x-ra-rotate!,@code{ra-rotate!}}, @ref{x-ra-reverse,@code{ra-reverse}}.
  1891. @end deffn
  1892. @cindex rotate!
  1893. @cindex @code{ra-rotate!}
  1894. @anchor{x-ra-rotate!}
  1895. @deffn @w{Function} ra-rotate! n a @result{} a
  1896. Rotate in place the first axis of @var{a} to the left @var{n} times. @var{n} may be any integer. @var{a} must be writable. This function returns @var{a}.
  1897. Example:
  1898. @example
  1899. @verbatim
  1900. (define a (ra-copy #t (ra-i 3 2)))
  1901. (ra-rotate! 1 a)
  1902. a
  1903. @end verbatim
  1904. @result{} #%1:3:2((2 3) (4 5) (0 1))
  1905. @end example
  1906. See also: @ref{x-ra-rotate,@code{ra-rotate}}, @ref{x-ra-reverse,@code{ra-reverse}}.
  1907. @end deffn
  1908. @cindex @code{ra-scat}
  1909. @anchor{x-ra-scat}
  1910. @deffn @w{Function} ra-scat type i a ... @result{} b
  1911. Concatenate @var{i}-items of arrays @var{a} ... . The arguments are suffix-matched and rank extended before concatenation. All axes must match, other than the concatenation axis.
  1912. This function always produces a new array, of the type given. If @var{type} is @code{#f} then the type of the first @var{a} is used, unless that is @code{d}, in which case @code{#t} is used. The lower bound in the concatenation axis of the result is 0; the lower bounds of the arguments in the concatenation axis are ignored.
  1913. @example
  1914. @verbatim
  1915. (ra-scat #t 1 #%2((0 1) (2 3)) #%(a b))
  1916. @end verbatim
  1917. @result{} #%2((0 1) (2 3) (a b))
  1918. @end example
  1919. See also: @ref{x-ra-cat,@code{ra-cat}}, @ref{x-ra-tile,@code{ra-tile}}, @ref{Concatenation}.
  1920. @end deffn
  1921. @cindex @code{ra-shape}
  1922. @anchor{x-ra-shape}
  1923. @deffn @w{Function} ra-shape a @result{} s
  1924. Return the shape (a list of two-element lists, each containing the lower and upper bound of each axis) of array @var{a}.
  1925. @example
  1926. @verbatim
  1927. (ra-shape (make-ra 0 '(2 3) 4))
  1928. @end verbatim
  1929. @result{} @code{((2 3) (0 3))}
  1930. @end example
  1931. See also: @ref{x-ra-dimensions,@code{ra-dimensions}}, @ref{x-make-ra,@code{make-ra}}.
  1932. @end deffn
  1933. @cindex @code{ra-tile}
  1934. @anchor{x-ra-tile}
  1935. @deffn @w{Function} ra-tile a k bounds ... @result{} b
  1936. Replicate array @var{a} by inserting axes of @var{bounds} ... before axis @var{k}. If @var{t} is the shape of @var{a}, the shape of the result will be
  1937. @example
  1938. @verbatim
  1939. [t₀ ... tₖ₋₁ s₀ ... tₖ ...]
  1940. @end verbatim
  1941. @end example
  1942. Each of the bounds may be an integer (a length) or a pair of integers (lower and upper bounds).
  1943. @example
  1944. @verbatim
  1945. (define a (ra-i 3 4))
  1946. (ra-format a)
  1947. @end verbatim
  1948. @result{}
  1949. @verbatim
  1950. #%2d:3:4──┐
  1951. │0│1│ 2│ 3│
  1952. ├─┼─┼──┼──┤
  1953. │4│5│ 6│ 7│
  1954. ├─┼─┼──┼──┤
  1955. │8│9│10│11│
  1956. └─┴─┴──┴──┘
  1957. @end verbatim
  1958. @end example
  1959. @example
  1960. @verbatim
  1961. (ra-format (ra-tile a 0 2))
  1962. @end verbatim
  1963. @result{}
  1964. @verbatim
  1965. #%3d:2:3:4║─┬─┬──┬──║
  1966. ║0│1│ 2│ 3║0│1│ 2│ 3║
  1967. ║─┼─┼──┼──║─┼─┼──┼──║
  1968. ║4│5│ 6│ 7║4│5│ 6│ 7║
  1969. ║─┼─┼──┼──║─┼─┼──┼──║
  1970. ║8│9│10│11║8│9│10│11║
  1971. ║─┴─┴──┴──║─┴─┴──┴──║
  1972. @end verbatim
  1973. @end example
  1974. @example
  1975. @verbatim
  1976. (ra-format (ra-tile a 1 2))
  1977. @end verbatim
  1978. @result{}
  1979. @verbatim
  1980. #%3d:3:2:4┬─┬─┬─║─┬─┬──┬──║
  1981. ║0│1│2│3║4│5│6│7║8│9│10│11║
  1982. ║─┼─┼─┼─║─┼─┼─┼─║─┼─┼──┼──║
  1983. ║0│1│2│3║4│5│6│7║8│9│10│11║
  1984. ║─┴─┴─┴─║─┴─┴─┴─║─┴─┴──┴──║
  1985. @end verbatim
  1986. @end example
  1987. @example
  1988. @verbatim
  1989. (ra-format (ra-tile a 2 2))
  1990. @end verbatim
  1991. @result{}
  1992. @verbatim
  1993. #%3d:3:4:2─┬──║
  1994. ║0│0║4│4║ 8│ 8║
  1995. ║─┼─║─┼─║──┼──║
  1996. ║1│1║5│5║ 9│ 9║
  1997. ║─┼─║─┼─║──┼──║
  1998. ║2│2║6│6║10│10║
  1999. ║─┼─║─┼─║──┼──║
  2000. ║3│3║7│7║11│11║
  2001. ║─┴─║─┴─║──┴──║
  2002. @end verbatim
  2003. @end example
  2004. Either @var{len} or @var{hi} being @code{#f} creates @ref{x-dead-axes,dead axes}.
  2005. @example
  2006. @verbatim
  2007. (define a (ra-tile (ra-i 2 2) 0 #f #f))
  2008. (define b (ra-transpose (ra-i 2 2) 2)) ; same thing
  2009. @end verbatim
  2010. @result{} @code{#%4d:d:d:2:2((((0 1) (2 3))))}
  2011. @end example
  2012. The tiled array shares the root of @var{a}.
  2013. See also: @ref{x-ra-ravel,@code{ra-ravel}}, @ref{x-ra-reshape,@code{ra-reshape}}, @ref{Reshaping}.
  2014. @end deffn
  2015. @cindex @code{ra-transpose}
  2016. @anchor{x-ra-transpose}
  2017. @deffn @w{Function} ra-transpose a axes ... @result{} b
  2018. Transpose each axis 0, 1, ... of @var{a} to matching destination @var{axes}.
  2019. @example
  2020. @verbatim
  2021. (ra-transpose (ra-i 2 3) 1 0)
  2022. @end verbatim
  2023. @result{} #%1d:3:2((0 3) (1 4) (2 5))
  2024. @end example
  2025. The transposed array shares the root of @var{a}.
  2026. See also: @ref{x-ra-untranspose,@code{ra-untranspose}}, @ref{Transposition}.
  2027. @end deffn
  2028. @cindex @code{ra-untranspose}
  2029. @anchor{x-ra-untranspose}
  2030. @deffn @w{Function} ra-untranspose a axes ... @result{} b
  2031. Transpose @var{axes} of @var{a} to matching destination axes 0, 1, ...
  2032. @example
  2033. @verbatim
  2034. (ra-untranspose (ra-transpose (ra-i 2 3 4) 2 1 0) 2 1 0)
  2035. @end verbatim
  2036. @result{} @code{#%3d:2:3:4(((0 1 2 3) (4 5 6 7) (8 9 10 11)) ((12 13 14 15) (16 17 18 19) (20 21 22 23)))}
  2037. @end example
  2038. but
  2039. @example
  2040. @verbatim
  2041. (ra-transpose (ra-transpose (ra-i 2 3 4) 2 1 0) 2 1 0)
  2042. @end verbatim
  2043. @result{} @code{#%3d:4:2:3(((0 4 8) (12 16 20)) ((1 5 9) (13 17 21)) ((2 6 10) (14 18 22)) ((3 7 11) (15 19 23)))}
  2044. @end example
  2045. The transposed array shares the root of @var{a}.
  2046. See also: @ref{x-ra-transpose,@code{ra-transpose}}, @ref{Transposition}.
  2047. @end deffn
  2048. @cindex @code{ra-index-map!}
  2049. @anchor{x-ra-index-map!}
  2050. @deffn @w{Function} ra-index-map! a op @result{} a
  2051. Iterate over array @var{a} in unspecified order, assigning to each element the result of @code{(op i₀ ...)}, where @code{i₀ ...} are the indices of that element.
  2052. For example:
  2053. @example
  2054. @verbatim
  2055. (ra-index-map! (make-ra #t 3 4) -)
  2056. (ra-map! (make-ra #t 3 4) - (ra-iota) (ra-transpose (ra-iota) 1)) ; same thing
  2057. @end verbatim
  2058. @result{} @code{#%2:3:4((0 -1 -2 -3) (1 0 -1 -2) (2 1 0 -1))}
  2059. @end example
  2060. See also: @ref{x-ra-map!,@code{ra-map!}}, @ref{Iteration}.
  2061. @end deffn
  2062. @cindex @code{ra-slice-for-each}
  2063. @anchor{x-ra-slice-for-each}
  2064. @deffn @w{Function} ra-slice-for-each k op a ...
  2065. Iterate over the @var{k}-frames of arrays @var{a} ..., applying @var{op} to the respective slices. The arguments @var{a} ... must have matching shapes over their @var{k}-frames.
  2066. Note that it isn't necessary for arguments @var{a} to have rank ≥ @var{k}. Arguments with rank < @var{k} are rank-extended and the corresponding arguments are 0-cells. For example:
  2067. @example
  2068. @verbatim
  2069. (ra-slice-for-each 1
  2070. (lambda (a b) (display (list (a) (b))))
  2071. (make-ra-root #(a b))
  2072. (ra-i 2 3))
  2073. @end verbatim
  2074. @result{} @code{(a #%1d:3(0 1 2))(b #%1d:3(3 4 5))}
  2075. @end example
  2076. @example
  2077. @verbatim
  2078. (ra-slice-for-each 2
  2079. (lambda (a b) (display (list (a) (b))))
  2080. (make-ra-root #(a b))
  2081. (ra-i 2 3))
  2082. @end verbatim
  2083. @result{} @code{(a 0)(a 1)(a 2)(b 3)(b 4)(b 5)}
  2084. @end example
  2085. See also: @ref{x-ra-map!,@code{ra-map!}}, @ref{x-ra-for-each,@code{ra-for-each}}, @ref{Iteration}.
  2086. @end deffn
  2087. @cindex @code{ra-map!}
  2088. @anchor{x-ra-map!}
  2089. @deffn @w{Function} ra-map! dst op a ... @result{} dst
  2090. Iterate over arrays @var{dst} @var{a} ... applying @var{op} to the respective elements in @var{a}, and storing the result in the respective element of @var{dst}. The arguments must have matching shapes and the type of @var{dst} must be compatible with the results of @var{op}.
  2091. This is equivalent to
  2092. @verbatim
  2093. (apply ra-slice-for-each
  2094. (rank dst)
  2095. (lambda (dst . a)
  2096. (ra-set! dst (apply op (map ra-ref a))))
  2097. dst a)
  2098. @end verbatim
  2099. See also: @ref{x-ra-map,@code{ra-map}}, @ref{x-ra-for-each,@code{ra-for-each}}, @ref{x-ra-slice-for-each,@code{ra-slice-for-each}}, @ref{Iteration}.
  2100. @end deffn
  2101. @cindex @code{ra-map}
  2102. @anchor{x-ra-map}
  2103. @deffn @w{Function} ra-map type op a0 a ... @result{} dst
  2104. Same as @ref{x-ra-map!,@code{ra-map!}}, but create the result array from the arguments. Unlike @code{ra-map!}, this function requires at least one source argument.
  2105. The type of @var{dst} is @var{type} unless that is @code{#f}, in which case the type of @var{a0} is used, unless that is @code{'d}, in which case the @code{#f} is used. For the computation of the shape of @var{dst} see @ref{Automatic result arrays}.
  2106. @example
  2107. @verbatim
  2108. (ra-format (ra-map 'f64 + (ra-iota 3 1) (ra-i 3 4)))
  2109. @end verbatim
  2110. @result{}
  2111. @verbatim
  2112. #%2f64:3:4┬────┬────┐
  2113. │ 1.0│ 2.0│ 3.0│ 4.0│
  2114. ├────┼────┼────┼────┤
  2115. │ 6.0│ 7.0│ 8.0│ 9.0│
  2116. ├────┼────┼────┼────┤
  2117. │11.0│12.0│13.0│14.0│
  2118. └────┴────┴────┴────┘
  2119. @end verbatim
  2120. @end example
  2121. See also: @ref{x-ra-map!,@code{ra-map!}}, @ref{x-ra-copy,@code{ra-copy}}.
  2122. @end deffn
  2123. @cindex @code{ra-copy!}
  2124. @anchor{x-ra-copy!}
  2125. @deffn @w{Function} ra-copy! dst src @result{} dst
  2126. Copy @var{src} to @var{dst}. The arguments must have matching shapes and be of compatible types.
  2127. For valid arguments, this is equivalent to any one of
  2128. @verbatim
  2129. (ra-map! dst identity src)
  2130. (ra-amend! dst src)
  2131. @end verbatim
  2132. See also @ref{x-ra-copy,@code{ra-copy}} @ref{x-ra-amend!,@code{ra-amend!}} @ref{x-ra-set!,@code{ra-set!}} @ref{x-ra-map!,@code{ra-map!}}.
  2133. @end deffn
  2134. @cindex @code{ra-copy}
  2135. @anchor{x-ra-copy}
  2136. @deffn @w{Function} ra-copy src @result{} dst
  2137. @deffnx @w{Function} ra-copy type src @result{} dst
  2138. Create a new array of type @var{type} and copy @var{src} into it. If @var{type} is @code{#f} or isn't given, use the type of @var{src}, unless that type is @code{d}, in which case the result is of type @code{#t}.
  2139. See also @ref{x-ra-copy!,@code{ra-copy!}} @ref{x-ra-amend!,@code{ra-amend!}} @ref{x-ra-set!,@code{ra-set!}}.
  2140. @end deffn
  2141. @cindex @code{ra-swap!}
  2142. @anchor{x-ra-swap!}
  2143. @deffn @w{Function} ra-swap! a b @result{} a
  2144. Swap the contents of @var{a} and @var{b}. The swap is executed in unspecified order, so the effect on @var{a} and @var{b} is undefined if @var{a} and @var{b} share storage.
  2145. @example
  2146. @verbatim
  2147. (ra-swap! (make-ra 2 3) (make-typed-ra 'f64 -1 3))
  2148. @end verbatim
  2149. @result{}
  2150. @verbatim
  2151. #%1:3(-1.0 -1.0 -1.0)
  2152. @end verbatim
  2153. @end example
  2154. See also @ref{x-ra-swap-in-order!,@code{ra-swap-in-order!}} @ref{x-ra-copy!,@code{ra-copy!}}.
  2155. @end deffn
  2156. @cindex @code{ra-swap-in-order!}
  2157. @anchor{x-ra-swap-in-order!}
  2158. @deffn @w{Function} ra-swap-in-order! a b @result{} a
  2159. Swap the contents of @var{a} and @var{b}. The swap is executed in row-major order.
  2160. @end deffn
  2161. @cindex @code{ra-fill!}
  2162. @anchor{x-ra-fill!}
  2163. @deffn @w{Function} ra-fill! dst value @result{} dst
  2164. Assign @var{value} to each element of @var{dst}. The arguments must be of compatible types.
  2165. This is equivalent to any one of
  2166. @example
  2167. @verbatim
  2168. (ra-map! dst (const value))
  2169. (ra-copy! dst (make-ra value))
  2170. (ra-amend! dst (make-ra value))
  2171. (ra-amend! dst value) ; as long as value isn't an array
  2172. @end verbatim
  2173. @end example
  2174. Compare
  2175. @example
  2176. @verbatim
  2177. (ra-fill! (make-ra #f 2 2) (make-ra 'x))
  2178. @end verbatim
  2179. @result{} #%2:2:2((#%0(x) #%0(x)) (#%0(x) #%0(x)))
  2180. @verbatim
  2181. (ra-amend! (make-ra #f 2 2) 'x)
  2182. @end verbatim
  2183. @result{} #%2:2:2((x x) (x x))
  2184. @verbatim
  2185. (ra-amend! (make-ra #f 2 2) (make-ra 'x))
  2186. @end verbatim
  2187. @result{} #%2:2:2((x x) (x x))
  2188. @verbatim
  2189. (ra-amend! (make-ra #f 2 2) (make-ra (make-ra 'x)))
  2190. @end verbatim
  2191. @result{} #%2:2:2((#%0(x) #%0(x)) (#%0(x) #%0(x)))
  2192. @end example
  2193. See also: @ref{x-ra-set!,@code{ra-set!}}, @ref{x-ra-copy!,@code{ra-copy!}}, @ref{x-ra-amend!,@code{ra-amend!}}.
  2194. @end deffn
  2195. @cindex packed array
  2196. @cindex @code{ra-order-c?}
  2197. @anchor{x-ra-order-c?}
  2198. @deffn @w{Function} ra-order-c? a [n [org]]
  2199. Check whether axes [@var{org} ... @var{org}+@var{n}) of @var{a} are in row-major order. By default, check that the whole array is in row-major order, and additionally that the step on the last axis is 1 (i.e. the array is ‘packed’).
  2200. @code{(ra-order-c? a n org)} implies @code{(eq? (ra-root a) (ra-root (@ref{x-ra-ravel, @code{ra-ravel}} a n org)))}. Note that the stronger condition @code{(ra-order-c? a)} is not necessary for @code{(eq? (ra-root a) (ra-root (ra-ravel a)))} to hold.
  2201. @end deffn
  2202. @cindex @code{ra-ref}
  2203. @anchor{x-ra-ref}
  2204. @deffn @w{Function} ra-ref a i ...
  2205. Look up array element. It is an error if the number of @var{i ...} doesn't match the rank of @var{a}.
  2206. See also: @ref{x-ra-cell,@code{ra-cell}}, @ref{x-ra-slice,@code{ra-slice}}, @ref{x-ra-from,@code{ra-from}}, @ref{x-ra-set!,@code{ra-set!}}.
  2207. @end deffn
  2208. @cindex @code{ra-set!}
  2209. @anchor{x-ra-set!}
  2210. @deffn @w{Function} ra-set! a o i ...
  2211. Assign array element. It is an error if the number of @var{i ...} doesn't match the rank of @var{a}.
  2212. See also: @ref{x-ra-amend!,@code{ra-amend!}}, @ref{x-ra-ref,@code{ra-ref}}.
  2213. @end deffn
  2214. @cindex @code{ra-slice}
  2215. @anchor{x-ra-slice}
  2216. @deffn @w{Function} ra-slice a i ...
  2217. Look up array cell.
  2218. This function returns a view of @var{a} with rank @var{k} equal to the rank of @var{a} minus the number of @var{i ...}, even if that is 0.
  2219. It is an error if the number of @var{i ...} exceeds the rank of @var{a}.
  2220. See also: @ref{x-ra-cell,@code{ra-cell}}, @ref{x-ra-ref,@code{ra-ref}}, @ref{x-ra-from,@code{ra-from}}, @ref{Slicing}.
  2221. @end deffn
  2222. @cindex @code{ra-cell}
  2223. @anchor{x-ra-cell}
  2224. @deffn @w{Function} ra-cell a i ...
  2225. Look up array cell.
  2226. Let @var{k} be the rank of @var{a} minus the number of @var{i ...}. If @var{k} is zero, return the array element at @var{i ...}, like @ref{x-ra-ref,@code{ra-ref}}; else return a @var{k}-view of @var{a}, like @ref{x-ra-slice,@code{ra-slice}}.
  2227. It is an error if the number of @var{i ...} exceeds the rank of @var{a}.
  2228. @example
  2229. @verbatim
  2230. (define a (ra-copy (ra-i 3 2)))
  2231. (ra-cell a 0)
  2232. (ra-slice a 0) ; same thing
  2233. @end verbatim
  2234. @result{} @code{#%1(0 1 2)}
  2235. @verbatim
  2236. (ra-slice a 0 1)
  2237. @end verbatim
  2238. @result{} @code{#%0(4)}
  2239. @verbatim
  2240. (ra-cell a 0 1)
  2241. (ra-ref a 0 1) ; same thing
  2242. @end verbatim
  2243. @result{} @code{4}
  2244. @end example
  2245. See also: @ref{x-ra-slice,@code{ra-slice}}, @ref{x-ra-ref,@code{ra-ref}}, @ref{x-ra-from,@code{ra-from}}, @ref{Slicing}.
  2246. @end deffn
  2247. @cindex @code{ra-equal?}
  2248. @anchor{x-ra-equal?}
  2249. @deffn @w{Function} ra-equal? a ... → boolean
  2250. Return @code{#t} if the arrays @var{a} ... have the same shapes and types and their
  2251. corresponding elements are all @code{equal?} to each other, or @code{#f} otherwise.
  2252. Note that this function isn't rank extending; the shapes of the arguments must be the same, not just match. Here's a rank-extending version:
  2253. @example
  2254. @verbatim
  2255. (import (ice-9 control))
  2256. (define (ra-equal?* . a) (let/ec exit (apply ra-for-each (lambda a (unless (apply equal? a) (exit #f))) a) #t))
  2257. @end verbatim
  2258. @end example
  2259. See also: @ref{x-ra-for-each,@code{ra-for-each}}, @ref{x-ra-fold,@code{ra-fold}}, @ref{x-ra-every,@code{ra-every}}, @ref{x-ra-any,@code{ra-any}}.
  2260. @end deffn
  2261. @cindex @code{ra-for-each}
  2262. @anchor{x-ra-for-each}
  2263. @deffn @w{Function} ra-for-each op a ...
  2264. See also: @ref{x-ra-slice-for-each, @code{ra-slice-for-each}}, @ref{x-ra-map!,@code{ra-map}}, @ref{Iteration}.
  2265. @end deffn
  2266. @cindex @code{ra-fold}
  2267. @anchor{x-ra-fold}
  2268. @deffn @w{Function} ra-fold op knil a ...
  2269. See also: @ref{x-ra-every,@code{ra-every}}, @ref{x-ra-any,@code{ra-any}}, @ref{Iteration}.
  2270. @end deffn
  2271. @cindex @code{ra-every}
  2272. @anchor{x-ra-every}
  2273. @deffn @w{Function} ra-every pred? a ...
  2274. See also: @ref{x-ra-fold,@code{ra-fold}}, @ref{x-ra-any,@code{ra-any}}.
  2275. @end deffn
  2276. @cindex @code{ra-any}
  2277. @anchor{x-ra-any}
  2278. @deffn @w{Function} ra-any pred? a ...
  2279. See also: @ref{x-ra-fold,@code{ra-fold}}, @ref{x-ra-every,@code{ra-every}}.
  2280. @end deffn
  2281. @cindex @code{ra-from}
  2282. @anchor{x-ra-from}
  2283. @deffn @w{Function} ra-from a i ... → b
  2284. Outer product slice of @var{a} by indices @var{i} ...
  2285. The shape of @var{b} is the concatenation of the shapes of @var{i}... and the
  2286. contents are obtained by looking up in each dimension of @var{a} by the indices @var{i},
  2287. that is
  2288. @example
  2289. @verbatim
  2290. b(j₀₀ j₀₁ ... j₁₀ j₁₁ ...) = a(i₀(j₀₀ j₀₁ ...) i₁(j₁₀ j₁₁ ...) ...)
  2291. @end verbatim
  2292. @end example
  2293. where @var{i} : @var{i₀} @var{i₁} ... The special value @code{#t} is understood as the full range of @var{a} on that axis.
  2294. Additionally, if each of the @var{i} ... is one of
  2295. @itemize
  2296. @item @code{#t}
  2297. @item an array of type @code{d}
  2298. @item an array of rank 0
  2299. @item an integer
  2300. @end itemize
  2301. then the result @var{b} shares the root of @var{a}. In all other cases a new root is allocated for the result. For example
  2302. @example
  2303. @verbatim
  2304. (define a (list->ra 2 '((1 2 3) (a b c))))
  2305. (define b (ra-from a #t (ra-iota 3 2 -1))) ; same as (ra-reverse a 1)
  2306. b
  2307. @end verbatim
  2308. @result {} @code{#%2:2:3((3 2 1) (c b a))}
  2309. @verbatim
  2310. (eq? (ra-root a) (ra-root b))
  2311. @end verbatim
  2312. @result {} @code{#t}
  2313. @verbatim
  2314. (define c (ra-from a #t (list->ra 1 '(2 1 0))))
  2315. b
  2316. @end verbatim
  2317. @result {} @code{#%2:2:3((3 2 1) (c b a))}
  2318. @verbatim
  2319. (eq? (ra-root a) (ra-root c))
  2320. @end verbatim
  2321. @result {} @code{#f}
  2322. @end example
  2323. Unbounded indices aren't treated especially, so they are only valid if the relevant axis of @var{ra} is itself unbounded.
  2324. @example
  2325. @verbatim
  2326. (ra-i #t 4)
  2327. @end verbatim
  2328. @result {}
  2329. @verbatim
  2330. #%2d:f:4──┐
  2331. │0│1│ 2│ 3│
  2332. ├─┼─┼──┼──┤
  2333. │4│5│ 6│ 7│
  2334. ├─┼─┼──┼──┤
  2335. │8│9│10│11│
  2336. ...........
  2337. @end verbatim
  2338. @verbatim
  2339. (ra-from (ra-i #t 4) (ra-iota #f 0 2))
  2340. @end verbatim
  2341. @result {}
  2342. @verbatim
  2343. #%2d:f:4─┬──┐
  2344. │ 0│ 1│ 2│ 3│
  2345. ├──┼──┼──┼──┤
  2346. │ 8│ 9│10│11│
  2347. ├──┼──┼──┼──┤
  2348. │16│17│18│19│
  2349. .............
  2350. @end verbatim
  2351. @end example
  2352. @i{If the result would have rank 0, then an array element is returned, and not a 0-rank view of @var{a}. Use @ref{x-ra-amend!,@code{ra-amend!}} to assign to cells of an array regardless of whether they are of 0-rank or higher.}
  2353. The type of @var{b} is the same as that of @var{a}, with the only exception that if the type of @var{a} is @code{d} and the root of @var{b} cannot be shared with the root of @var{a}, then the type of @var{b} is @code{#t}.
  2354. See also: @ref{x-ra-cell,@code{ra-cell}}, @ref{x-ra-ref,@code{ra-ref}}, @ref{x-ra-slice,@code{ra-slice}}, @ref{x-ra-amend!,@code{ra-amend!}}, @ref{Slicing}.@footnote{Cf. @code{array-index-ref} from @mybibcite{SRFI-164}.}
  2355. @end deffn
  2356. @cindex @code{ra-from-copy}
  2357. @anchor{x-ra-from-copy}
  2358. @deffn @w{Function} ra-from-copy a i ... @result{} b
  2359. Like @code{ra-from}, but always return a newly allocated array. This is equivalent to @code{(ra-copy (ra-from a i ...))}, but it doesn't incur a second copy in case @code{ra-from} already allocates a new array.
  2360. See also: @ref{x-ra-from,@code{ra-from}}.
  2361. @end deffn
  2362. @cindex @code{ra-amend!}
  2363. @anchor{x-ra-amend!}
  2364. @deffn @w{Function} ra-amend! a c i ... → a
  2365. Copy @var{c} to the outer product slice of @var{a} by indices @var{i} ...
  2366. @example
  2367. @verbatim
  2368. a(i₀(j₀₀ j₀₁ ...) i₁(j₁₀ j₁₁ ...) ...) ← c(j₀₀ j₀₁ ... j₁₀ j₁₁ ...)
  2369. @end verbatim
  2370. @end example
  2371. where @var{i} : @var{i₀} @var{i₁} ...
  2372. This is equivalent to @code{(ra-copy! (ra-from a i ...) c)} if @code{(ra-from a i ...)} would
  2373. return a shared ra of @var{a}, but it also works in other cases, as long as @var{a} is
  2374. writable. @var{i} may take any of the special values accepted by @code{ra-from}.
  2375. @example
  2376. @verbatim
  2377. (define a (list->ra 1 '(1 2 3)))
  2378. (define x 1)
  2379. (define y (array->ra #(1)))
  2380. (ra-amend! a 9 x) ; modifies a
  2381. (ra-amend! a (array->ra #0(9)) x) ; same thing
  2382. (ra-copy! (ra-from a x) (array->ra #0(9))) ; modifies a
  2383. (ra-amend! a 9 y) ; modifies a
  2384. (ra-copy! (ra-from a y) (array->ra #0(9))) ; (ra-from a y) is a new array, so a is NOT modified
  2385. (ra-amend! (array->ra #(2 3 4)) 9 1) ; error, (array->ra #(2 3 4)) is not mutable
  2386. @end verbatim
  2387. @end example
  2388. If @var{i} contains repeated indices or the steps of @var{a} make it so that the same elements of @var{a}
  2389. are referenced more than once, then the value that ends up in @var{a} may correspond to any of the
  2390. indices that match those elements. @code{newra} will @emph{not} check that each element of @var{a} is represented uniquely in its root vector.
  2391. @example
  2392. @verbatim
  2393. (ra-amend! a (array->ra #(6 7 8)) (ra-tile (array->ra #0(1)) 0 3))
  2394. @end verbatim
  2395. @result{} #%1:3(1 8 3) ; do not rely on 8 ending up there
  2396. @end example
  2397. This function returns the modified array @var{a}.
  2398. See also: @ref{x-ra-from,@code{ra-from}}, @ref{x-ra-copy!,@code{ra-copy!}} @ref{x-ra-cell,@code{ra-cell}} @ref{x-ra-ref,@code{ra-ref}} @ref{x-ra-slice,@code{ra-slice}} @ref{x-ra-set!,@code{ra-set!}}.
  2399. @end deffn
  2400. @cindex @code{ra->array}
  2401. @anchor{x-ra->array}
  2402. @deffn @w{Function} ra->array a
  2403. Convert (@code{newra}) array @var{a} into built-in Guile array.
  2404. This function does not create a copy of the array, but reuses the root (@code{ra-root}) of @var{a}, that is, @code{(eq? (ra-root a) (shared-array-root (ra->array a)))} is @code{#t}.
  2405. Not all arrays can be converted into built-in Guile arrays. For example, type @code{d} arrays, or arrays with unbounded axes, are not convertible.
  2406. @example
  2407. @verbatim
  2408. (ra->array (ra-i 3)) ; error, type d not convertible
  2409. (ra->array (ra-copy (ra-i 3))) ; ok, (ra-copy (ra-i 3)) has type #t
  2410. (ra->array (ra-transpose (ra-i 2 3) 1)) ; error, not convertible
  2411. (ra->array (ra-singletonize (ra-transpose (ra-i 2 3) 1))) ; ok
  2412. @end verbatim
  2413. @end example
  2414. See also: @ref{x-array->ra,@code{array->ra}}, @ref{x-ra-singletonize,@code{ra-singletonize}}, @ref{x-ra-copy!,@code{ra-copy!}}.
  2415. @end deffn
  2416. @cindex @code{ra-singletonize}
  2417. @anchor{x-ra-singletonize}
  2418. @deffn @w{Function} ra-singletonize a
  2419. Return an array with the same root and dimensions as @var{a}, except that dead axes (axes with step 0 and undefined length) have their length set to 1.
  2420. @example
  2421. @verbatim
  2422. (ra-dimensions (ra-transpose (ra-i 2 3) 1))
  2423. @end verbatim
  2424. @result{} (#f 2 3)
  2425. @verbatim
  2426. (ra-dimensions (ra-singletonize (ra-transpose (ra-i 2 3) 1)))
  2427. @end verbatim
  2428. @result{} (1 2 3)
  2429. @verbatim
  2430. (ra-dimensions (ra-singletonize (ra-tile (ra-i 2 3) 0 4)))
  2431. @end verbatim
  2432. @result{} (4 2 3) ; no change
  2433. @end example
  2434. @end deffn
  2435. @c ------------------------------------------------
  2436. @node Cheatsheet
  2437. @chapter Cheatsheet
  2438. @c ------------------------------------------------
  2439. @c ------------------------------------------------
  2440. @node @mybibnode{}
  2441. @chapter Sources
  2442. @c ------------------------------------------------
  2443. @multitable @columnfractions .1 .9
  2444. @item @mybibitem{Abr70} @tab Philip S. Abrams. An APL machine. Technical report SLAC-114 UC-32 (MISC), Stanford Linear Accelerator Center, Stanford University, Stanford, CA, USA, February 1970.
  2445. @item @mybibitem{Ber87} @tab Robert Bernecky. An introduction to function rank. ACM SIGAPL APL Quote Quad, 18(2):39–43, December 1987.
  2446. @item @mybibitem{bli17} @tab The Blitz++ meta-template library. @url{http://blitz.sourceforge.net}, November 2017.
  2447. @item @mybibitem{Cha86} @tab Gregory J. Chaitin. Physics in APL2, June 1986.
  2448. @item @mybibitem{FI68} @tab Adin D. Falkoff and Kenneth Eugene Iverson. APL\360 User’s manual. IBM Thomas J. Watson Research Center, August 1968.
  2449. @item @mybibitem{FI73} @tab Adin D. Falkoff and Kenneth Eugene Iverson. The design of APL. IBM Journal of Research and Development, 17(4):5–14, July 1973.
  2450. @item @mybibitem{FI78} @tab Adin D. Falkoff and Kenneth Eugene Iverson. The evolution of APL. ACM SIGAPL APL, 9(1):30– 44, 1978.
  2451. @item @mybibitem{J S} @tab J Primer. J Software, @url{https://www.jsoftware.com/help/primer/contents.htm}, November 2017.
  2452. @item @mybibitem{Mat} @tab MathWorks. MATLAB documentation, @url{https://www.mathworks.com/help/matlab/}, November 2017.
  2453. @item @mybibitem{num17} @tab NumPy. @url{http://www.numpy.org}, November 2017.
  2454. @item @mybibitem{Ric08} @tab Henry Rich. J for C programmers, February 2008.
  2455. @item @mybibitem{SSM14} @tab Justin Slepak, Olin Shivers, and Panagiotis Manolios. An array-oriented language with static rank polymorphism. In Z. Shao, editor, ESOP 2014, LNCS 8410, pages 27–46, 2014.
  2456. @item @mybibitem{Vel01} @tab Todd Veldhuizen. Blitz++ user’s guide, February 2001.
  2457. @item @mybibitem{Wad90} @tab Philip Wadler. Deforestation: transforming programs to eliminate trees. Theoretical Computer Science, 73(2): 231--248, June 1990. @url{https://doi.org/10.1016/0304-3975%2890%2990147-A}
  2458. @item @mybibitem{SRFI-4} @tab Marc Feeley. SRFI-4: Homogeneous numeric vector datatypes, May 1999. @url{https://srfi.schemers.org/srfi-4/srfi-4.html}
  2459. @item @mybibitem{SRFI-25} @tab Jussi Piitulainen. SRFI-25: Multi-dimensional array primitives, May 2002. @url{https://srfi.schemers.org/srfi-25/srfi-25.html}
  2460. @item @mybibitem{SRFI-122} @tab Bradley J. Lucier. SRFI-122: Nonempty intervals and generalized arrays, December 2016. @url{https://srfi.schemers.org/srfi-122/srfi-122.html}
  2461. @item @mybibitem{SRFI-160} @tab John Cowan and Shiro Kawai. SRFI-160: Homogeneous numeric vector libraries, November 2020. @url{https://srfi.schemers.org/srfi-160/srfi-160.html}
  2462. @item @mybibitem{SRFI-163} @tab Per Bothner. SRFI-163: Enhanced array literals, January 2019. @url{https://srfi.schemers.org/srfi-163/srfi-163.html}
  2463. @item @mybibitem{SRFI-164} @tab Per Bothner. SRFI-164: Enhanced multi-dimensional arrays, August 2019. @url{https://srfi.schemers.org/srfi-164/srfi-164.html}
  2464. @end multitable
  2465. @c ------------------------------------------------
  2466. @node Indices
  2467. @unnumbered Indices
  2468. @c ------------------------------------------------
  2469. @c @node Concept Index
  2470. @c @unnumbered Concept Index
  2471. @printindex cp
  2472. @c @node Function Index
  2473. @c @unnumbered Function Index
  2474. @c @printindex fn
  2475. @c \nocite{JLangReference,FalkoffIverson1968,Abrams1970,FalkoffIverson1973,FalkoffIverson1978,APLexamples1,ArraysCowan,KonaTheLanguage,blitz++2001}
  2476. @bye