ra-ra.texi 69 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707
  1. @c -*-texinfo-*-
  2. @c %**start of header
  3. @setfilename ra-ra.info
  4. @documentencoding UTF-8
  5. @settitle @code{ra::} —An array library for C++1z
  6. @c %**end of header
  7. @set VERSION 0.3
  8. @set UPDATED 2017 April 11
  9. @copying
  10. @code{ra::} (version @value{VERSION}, updated @value{UPDATED})
  11. (c) Daniel Llorens 2016--2017
  12. @smalldisplay
  13. Permission is granted to copy, distribute and/or modify this document
  14. under the terms of the GNU Free Documentation License, Version 1.3 or
  15. any later version published by the Free Software Foundation; with no
  16. Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
  17. @end smalldisplay
  18. @end copying
  19. @dircategory C++ libraries
  20. @direntry
  21. * ra-ra: (ra-ra.info). Expression template and multidimensional array library for C++.
  22. @end direntry
  23. @titlepage
  24. @title ra::
  25. @subtitle version @value{VERSION}, updated @value{UPDATED}
  26. @author Daniel Llorens
  27. @page
  28. @vskip 0pt plus 1filll
  29. @insertcopying
  30. @end titlepage
  31. @ifnottex
  32. @node Top
  33. @top @code{ra::}
  34. @insertcopying
  35. @code{ra::} is a general purpose multidimensional array and expression template library for C++14/C++17. Please keep in mind that this manual is a work in progress. There are many errors and whole sections unwritten.
  36. @menu
  37. * Overview:: Array programming and C++.
  38. * Usage:: Everything you can do with @code{ra::}.
  39. * Hazards:: User beware.
  40. * Internals:: For all the world to see.
  41. * The future:: Could be even better.
  42. * Reference:: Systematic list of types and functions.
  43. * Sources:: It's been done before.
  44. @end menu
  45. @end ifnottex
  46. @iftex
  47. @shortcontents
  48. @end iftex
  49. @c ------------------------------------------------
  50. @node Overview
  51. @chapter Overview
  52. @c ------------------------------------------------
  53. A multidimensional array is a container whose elements can be looked up using a multi-index (i₀, i₁, ...). Each of the indices i₀, i₁, ... has a fixed range [0, n₀), [0, n₁), ... so the array is `rectangular'. The number of indices in the multi-index is the @dfn{rank} of the array, and the list (n₀, n₁, ... nᵣ₋₁) is the @dfn{shape} of the array. We speak of a rank-@math{r} array or of an @math{r}-array.
  54. Often 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.
  55. Arrays (also called @dfn{matrices}, @dfn{vectors}, or @dfn{tensors}) are everywhere in math and many other fields, and it is enormously useful to be able to manipulate arrays as individual entities rather than as aggregates. Not only is
  56. @verbatim
  57. A = B+C;
  58. @end verbatim
  59. much more compact and easier to read than
  60. @verbatim
  61. for (int i=0; i!=m; ++i)
  62. for (int j=0; j!=n; ++j)
  63. for (int k=0; k!=p; ++k)
  64. A(i, j, k) = B(i, j, k)+C(i, j, k);
  65. @end verbatim
  66. but it's also safer and less redundant. For example, the order of the loops may be something you don't really care about.
  67. However, if array operations are implemented naively, a piece of code such as @code{A=B+C} may result in the creation of a temporary to hold @code{B+C} which is then assigned to @code{A}. Needless to say this is very wasteful if the arrays involved are large.
  68. @cindex Blitz++
  69. Fortunately the problem is almost as old as aggregate data types, and other programming languages have addressed it with optimizations such as `loop fusion' REF, `drag along' REF, or `deforestation' REF. In the C++ context the technique of `expression templates' was pioneered in the late 90s by libraries such as Blitz++ REF. It works by making @code{B+C} into an `expression object' which holds references to its arguments and performs the sum only when its elements are looked up. The compiler removes the temporary expression objects during optimization, so that @code{A=B+C} results (in principle) in the same generated code as the complicated loop nest above.
  70. @menu
  71. * Rank polymorphism:: What makes arrays special.
  72. * Drag along and beating:: The basic array optimizations.
  73. * Why C++:: High level, low level.
  74. * Guidelines:: How @code{ra::} tries to do things.
  75. * Other libraries:: Inspiration and desperation.
  76. @end menu
  77. @c ------------------------------------------------
  78. @node Rank polymorphism
  79. @section Rank polymorphism
  80. @c ------------------------------------------------
  81. @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.
  82. @cindex cell
  83. @cindex frame
  84. For example, think of a matrix A, a 2-array with sizes (n₀, n₁) where the elements A(i₀, i₁) are numbers. If we consider the subarrays (rows) A(0, ...), A(1, ...), ..., A(n₀-1, ...) as individual elements, then we have a new view of A as a 1-array of size n₀ 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 (n₀, n₁, ... nₙ₋₁₋ₖ) that is not taken up by the k-cell is called the k-@dfn{frame}.
  85. 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
  86. @quotation
  87. A: [A(0), A(1), ...]
  88. @end quotation
  89. and the items of A(i₀), etc. are in turn stored in the same way, so
  90. @quotation
  91. A: [A(0): [A(0, 0), A(0, 1) ...], ...]
  92. @end quotation
  93. and the same for the items of A(i₀, i₁), etc.
  94. @quotation
  95. A: [[A(0, 0): [A(0, 0, 0), A(0, 0, 1) ...], A(0, 1): [A(0, 1, 0), A(0, 1, 1) ...]], ...]
  96. @end quotation
  97. @cindex order, row-major
  98. 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 (@pxref{Other libraries}). A row-major array A with sizes (n₀, n₁, ... nᵣ₋₁) can be looked up like this:
  99. @quotation
  100. A(i₀, i₁, ...) = (storage-of-A) [(((i₀n₁ + i₁)n₂ + i₂)n₃ + ...)+iᵣ₋₁] = (storage-of-A) [o + s₀i₀ + s₁i₁ + ...]
  101. @end quotation
  102. where the numbers (s₀, s₁, ...) are called the @dfn{strides} or the @dfn{dope vector} REF. 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
  103. @quotation
  104. A ≡ ((storage-of-A), o, (s₀, s₁, ...))
  105. @end quotation
  106. 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-transpose,transposing} axes, @ref{x-reverse,reversing} the order along an axis, most cases of @ref{Slicing,slicing}, and sometimes even reshaping or tiling the array.
  107. A basic example is obtaining the i₀-th item of A:
  108. @quotation
  109. A(i₀) ≡ ((storage-of-A), o+s₀i₀, (s₁, ...))
  110. @end quotation
  111. 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 cost any more than iterating over 0-cells (@pxref{Cell iteration}).
  112. @c ------------------------------------------------
  113. @node Drag along and beating
  114. @section Drag along and beating
  115. @c ------------------------------------------------
  116. @c ------------------------------------------------
  117. @node Why C++
  118. @section Why C++
  119. @c ------------------------------------------------
  120. Of course the main reason is that (this being a personal project) I'm more familiar with C++ than with other languages to which the following applies.
  121. C++ supports the low level control that is necessary for interoperation with external libraries and languages, but still has the abstraction power to create the features we want even though the language has no native support for most of them.
  122. @cindex APL
  123. @cindex J
  124. The classic array languages, APL and J, have array support baked in. The same is true for other languages with array facilities such as Fortran or Octave/Matlab. Array libraries for general purpose languages usually depend heavily on C extensions. In Numpy's case this is both for reasons of flexibility (e.g. to obtain predictable memory layout and machine types) and of performance.
  125. On the other extreme, an array library for C would be hampered by the limited means of abstraction in the language (no polymorphism, no metaprogramming, etc.) so the natural choice of C programmers is to resort to code generators, which eventually turn into new languages.
  126. In C++, a library is enough.
  127. @c ------------------------------------------------
  128. @node Guidelines
  129. @section Guidelines
  130. @c ------------------------------------------------
  131. @code{ra::} attempts to be general, consistent, and transparent.
  132. @c @cindex J # TODO makeinfo can't handle an entry appearing more than once (it creates multiple entries in the index).
  133. Generality is achieved by removing arbitrary restrictions and by adopting the rank extension mechanism of J. @code{ra::} supports array operations with an arbitrary number of arguments. Any of the arguments in an array expression can be read from or written to. Arrays or array expressions can be of any rank. Slicing operations work for subscripts of any rank, as in APL. You can use your own types as array elements.
  134. Consistency is achieved by having a clear set of concepts and having the realizations of those concepts adhere to the concept as closely as possible. @code{ra::} offers a few different types of views and containers, but it should be possible to use them interchangeably whenever the properties that justify their existence are not involved. When this isn't possible, it's a bug. For example, you can currently create a higher rank iterator on a @code{View} but not a @code{SmallView}; this is a bug.
  135. Sometimes consistency requires a choice. For example, given array views A and B, @code{A=B} copies the contents of view B into view A. To change view A instead (to treat A as a pointer) would be the default meaning of A=B for C++ types, and result in better consistency with the rest of the language, but I have decided that having consistency between views and containers (which `are' their contents in a sense that views aren't) is more important.
  136. Transparency is achieved by avoiding opaque types. An array view consists of a pointer and a list of strides and I see no point in hiding that. Manipulating the strides directly is often useful. A container consists of storage and a view and that isn't hidden either. Some of the types have an obscure implementation but I consider that a defect. Ideally you should be able to rewrite expressions on the fly, or plug in your own traversal methods or storage handling.
  137. That isn't to mean that you need to be in command of a lot of internal detail to be able to use the library. I hope to have provided a high level interface to most operations and a reasonably sweet syntax. However, transparency is critical to achieve interoperation with external libraries and languages. When you need to, you'll be able to guarantee that an array is stored by compact columns or that the real parts are interleaved with the imaginary parts.
  138. @c ------------------------------------------------
  139. @node Other libraries
  140. @section Other array libraries
  141. @c ------------------------------------------------
  142. Here I try to list the C++ array libraries that I know of, or libraries that I think deserve a mention for the way they deal with arrays. It is not an extensive review, since I have only used a few of these libraries myself. Please follow the links if you want to be properly informed.
  143. Since the C++ standard library doesn't offer a standard multidimensional array type, some libraries for specific tasks (linear algebra operations, finite elements, optimization) offer an accessory array library, which may be more or less general. Other libraries have generic array interfaces without needing to provide an array type. FFTW is a good example, maybe because it isn't C++!
  144. C++ offers multidimensional arrays as a legacy feature from C, e.g. @code{int a[3][4]}. These decay to pointers when you do nearly anything with them, don't know their own sizes or rank, and are generally too limited.
  145. The C++ standard library also offers a number of containers that can be used as 1-arrays, of which the most important are @code{<array>}, @code{<vector>} and @code{<valarray>}. Neither supports higher ranks out of the box, but @code{<valarray>} offers array operations for 1-arrays. @code{ra::} makes use of @code{<array>} and @code{<vector>} for storage and bootstrapping so we'll mention these containers from time to time.
  146. @cindex Blitz++
  147. Blitz++ (REF) pioneered the use of expression templates in C++. It supported higher rank arrays, as high as it was practical in C++98, but not dynamic rank. It also supported small arrays with compile time sizes, and convenience features such as Fortran-order constructors and arbitrary lower bounds for the array indices (both of which @code{ra::} chooses not to support). Storage for large arrays was reference-counted, while in @code{ra::} that is optional but not the default. It placed a strong emphasis on performance, with array traversal methods such as blocking, space filling curves, etc. To date it remains, I believe, one of the most general array libraries for C++. However, the implementation had to fight the limitations of C++98, and it offered no general rank extension mechanism.
  148. TODO More libraries.
  149. TODO Maybe review other languages, at least the important ones (Fortran/APL/J/Matlab/Numpy).
  150. @c ------------------------------------------------
  151. @node Usage
  152. @chapter Usage
  153. @c ------------------------------------------------
  154. This is an extended exposition of the features of @code{ra::} and is probably best read in order. For details on specific functions or types, please @pxref{Reference}.
  155. @menu
  156. * Using @code{ra@asis{::}}:: @code{ra::} is a header-only library.
  157. * Containers and views:: Data objects.
  158. * Array operations:: Building and traversing expressions.
  159. * Rank extension:: How array operands are matched.
  160. * Cell iteration:: At any rank.
  161. * Slicing:: Subscripting is a special operation.
  162. * Special objects:: Not arrays, yet arrays.
  163. * The rank conjunction:: J comes to C++.
  164. * Compatibility:: With the STL and others.
  165. * Extension:: Using your own types and more.
  166. * Functions:: Ready to go.
  167. @end menu
  168. @c ------------------------------------------------
  169. @node Using @code{ra@asis{::}}
  170. @section Using @code{ra::}
  171. @c ------------------------------------------------
  172. @code{ra::} is a header only library with no dependencies, so you just need to place the @samp{ra/} folder somewhere in your include path and add @code{#include "ra/operators.H"} and @code{"ra/io.H"} at the top of your sources.
  173. A C++14 compiler with partial C++17 support is required. At the time of writing this means gcc 6.3 with @option{-std=c++1z}. Most tests pass under clang 4.0 with a couple of extra flags (@code{-Wno-missing-braces}, @option{-DRA_OPTIMIZE_SMALLVECTOR=0}).
  174. Here is a minimal program:
  175. @example @c readme.C [ma101]
  176. @verbatim
  177. #include "ra/operators.H"
  178. #include "ra/io.H"
  179. #include <iostream>
  180. int main()
  181. {
  182. ra::Big<char, 2> A({2, 5}, "helloworld");
  183. std::cout << format_array(transpose<1, 0>(A), false, "|") << std::endl;
  184. }
  185. @end verbatim
  186. @print{} h|w
  187. e|o
  188. l|r
  189. l|l
  190. d|d
  191. @end example
  192. You may want to @code{#include "ra/real.H"} and @code{"ra/complex.H"}. These put some functions in the global namespace that make it easier to work on built-in scalar types or array expressions indistinctly. They are not required for the rest of the library to function.
  193. @c ------------------------------------------------
  194. @node Containers and views
  195. @section Containers and views
  196. @c ------------------------------------------------
  197. @code{ra::} offers two kinds of data objects. The first kind, the @dfn{container}, owns its data. Creating a container requires memory and destroying it causes that memory to be freed.
  198. There are three kinds of containers: fixed size, fixed rank/dynamic size, and dynamic rank. Here fixed means `compile time constant' while dynamic is normally a run time constant. (Some dynamic size arrays can be resized but dynamic rank arrays cannot normally have their rank changed. Instead, you create a new container or view with the rank you want.)
  199. For example:
  200. @example
  201. @verbatim
  202. {
  203. ra::Small<double, 2, 3> a(0.); // a fixed size 2x3 array
  204. ra::Big<double, 2> b({2, 3}, 0.); // a dynamic size 2x3 array
  205. ra::Big<double> c({2, 3}, 0.); // a dynamic rank 2x3 array
  206. // a, b, c destroyed at end of scope
  207. }
  208. @end verbatim
  209. @end example
  210. The main reason to have all these different types is performance; the compiler can do a better job when it knows the size or the rank of the array. Also, the sizes of a fixed size array do not need to be stored in memory, so when you have thousands of small arrays it pays off to use the fixed size types. Fixed size or fixed rank arrays are also safer to use; sometimes @code{ra::} will be able to detect errors in the sizes or ranks of array operands at compile time, if the appropriate types are used.
  211. Container constructors come in two main forms. The first takes a single argument which is copied into the new container. This argument provides shape information if the container type requires it.
  212. @example
  213. @verbatim
  214. ra::Small<double, 2, 3> a = 0.; // 0. is copied into a
  215. ra::Small<double, 2, 3> b = a; // the contents of a are copied into b
  216. ra::Big<double> c = a; // c takes the size of a and a is copied into c
  217. ra::Big<double> d = 0.; // d is a 0-array with one element d()==0.
  218. @end verbatim
  219. @end example
  220. The second form takes two arguments, one giving the shape, the second the contents.
  221. @example
  222. @verbatim
  223. ra::Big<double, 2> a({2, 3}, 1.); // a has size 2x3 and be filled with 1.
  224. ra::Big<double> b({2, 3}, a); // b has size 2x3 and a is copied into b
  225. @end verbatim
  226. @end example
  227. The last example may result in an error if the shape of @code{a} and @{2,@w{ }3@} don't match. Here the shape () of @code{1.} matches (2,@w{ }3) by a mechanism of rank extension (@pxref{Rank extension}).
  228. Finally, there are special constructors where the content argument is either a pointer or an @code{std::initializer_list}. This argument isn't used for shape @footnote{You can still use pointer or @code{std::initializer_list} for shape by using the functions @code{ptr} or @code{vector}.}, but only as the (row-major) ravel of the content. The pointer constructor is unsafe —use at your own risk! Nested @code{std::initializer_list} isn't supported yet, but may be supported in the future.
  229. @cindex order, column-major
  230. @example
  231. @verbatim
  232. ra::Big<double, 2> a({2, 3}, {1, 2, 3, 4, 5, 6}); // {{1, 2, 3}, {4, 5, 6}}
  233. double bx[6] = {1, 2, 3, 4, 5, 6}
  234. ra::Big<double, 2> b({3, 2}, bx); // {{1, 2}, {3, 4}, {5, 6}}
  235. double cx[4] = {1, 2, 3, 4}
  236. ra::Big<double, 2> c({3, 2}, cx); // *** WHO NOSE ***
  237. using sizes = mp::int_list<2, 3>;
  238. using strides = mp::int_list<1, 2>;
  239. ra::SmallArray<real, sizes, strides> a { 1, 2, 3, 4, 5, 6 }; // {{1, 2, 3}, {4, 5, 6}} stored column-major
  240. @end verbatim
  241. @end example
  242. @anchor{x-scalar-char-star}
  243. Sometimes the pointer constructor gets in the way (see @ref{x-scalar,@code{scalar}}): @c [ma102]
  244. @example
  245. @verbatim
  246. ra::Big<char const *, 1> A({3}, "hello"); // error: try to convert char to char const *
  247. ra::Big<char const *, 1> A({3}, ra::scalar("hello")); // ok, "hello" is a single item
  248. std::cout << format_array(A, false, "|") << std::endl;
  249. @end verbatim
  250. @print{} hello|hello|hello
  251. @end example
  252. A @dfn{view} is similar to a container in that it points to actual data in memory. However, the view doesn't own that data and destroying the view won't affect it. For example:
  253. @example
  254. @verbatim
  255. ra::Big<double> c({2, 3}, 0.); // a dynamic rank 2x3 array
  256. {
  257. auto c1 = c(1); // the first row of array c
  258. // c1 is destroyed here
  259. }
  260. // can still use c here
  261. @end verbatim
  262. @end example
  263. The data accessed through a view is the data of the `root' container, so modifying the first will be reflected in the latter.
  264. @example
  265. @verbatim
  266. ra::Big<double> c({2, 3}, 0.);
  267. auto c1 = c(1);
  268. c1(2) = 9.; // c(1, 2) = 9.
  269. @end verbatim
  270. @end example
  271. Just as for containers, there are separate types of views depending on whether the size is known at compile time, the rank is known at compile time but the size is not, or neither the size nor the rank are known at compile time. @code{ra::} has functions to create the most common kinds of views:
  272. @example
  273. @verbatim
  274. ra::Big<double> c({2, 3}, {1, 2, 3, 4, 5, 6});
  275. auto ct = transpose<1, 0>(c); // {{1, 4}, {2, 5}, {3, 6}}
  276. auto cr = reverse(c, 0); // {{4, 5, 6}, {1, 2, 3}}
  277. @end verbatim
  278. @end example
  279. However, views can point to anywhere in memory and that memory doesn't have to belong to a @code{ra::} container. For example:
  280. @example
  281. @verbatim
  282. int raw[6] = {1, 2, 3, 4, 5, 6};
  283. ra::View<int> v1({{2, 3}, {3, 1}}, raw); // view with sizes {2, 3} strides {3, 1}
  284. ra::View<int> v2({2, 3}, raw); // same, default C (row-major) strides
  285. @end verbatim
  286. @end example
  287. Containers can be treated as views and the container types convert implicitly to view types of the same `fixedness'. If you declare a function
  288. @example
  289. @verbatim
  290. void f(ra::View<int, 3> & v);
  291. @end verbatim
  292. @end example
  293. you may pass it an object of type @code{ra::Big<int, 3>}.
  294. @c ------------------------------------------------
  295. @node Array operations
  296. @section Array operations
  297. @c ------------------------------------------------
  298. To apply an operation to each element of an array, use the function @code{for_each}. The array is traversed in an order that is decided by the library.
  299. @example
  300. @verbatim
  301. ra::Small<double, 2, 3> a = {1, 2, 3, 4, 5, 6};
  302. real s = 0.;
  303. for_each([&s](auto && a) { s+=a; }, a);
  304. @end verbatim
  305. @result{} s = 21.
  306. @end example
  307. To construct an array expression but stop short of traversing it, use the function @code{map}. The expression will be traversed when it is assigned to a view, printed out, etc.
  308. @example
  309. @verbatim
  310. using T = ra::Small<double, 2, 2>;
  311. T a = {1, 2, 3, 4};
  312. T b = {10, 20, 30, 40};
  313. T c = map([](auto && a, auto && b) { return a+b; }, a, b); // (1)
  314. @end verbatim
  315. @result{} c = @{ 11, 22, 33, 44 @}
  316. @end example
  317. Expressions may take any number of arguments and be nested arbitrarily.
  318. @example
  319. @verbatim
  320. T d = 0;
  321. for_each([](auto && a, auto && b, auto && d) { d = a+b; },
  322. a, b, d); // same as (1)
  323. for_each([](auto && ab, auto && d) { d = ab; },
  324. map([](auto && a, auto && b) { return a+b; },
  325. a, b),
  326. d); // same as (1)
  327. @end verbatim
  328. @end example
  329. The operator of an expression may return a reference and you may assign to an expression in that case. @code{ra::} will complain if the expression is somehow not assignable.
  330. @example
  331. @verbatim
  332. T d = 0;
  333. map([](auto & d) -> decltype(auto) { return d; }, d) // just pass d along
  334. = map([](auto && a, auto && b) { return a+b; }, a, b); // same as (1)
  335. @end verbatim
  336. @end example
  337. @code{ra::} defines many shortcuts for common array operations. You can of course just do:
  338. @example
  339. @verbatim
  340. T c = a+b; // same as (1)
  341. @end verbatim
  342. @end example
  343. @c ------------------------------------------------
  344. @node Rank extension
  345. @section Rank extension
  346. @c ------------------------------------------------
  347. 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.
  348. 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
  349. @quotation
  350. @code{(R+S)(i₀ i₁ ... i₍ᵣ₋₁₎) = R(i₀ i₁ ... i₍ᵣ₋₁₎) + S(i₀ i₁ ... i₍ᵣ₋₁₎)}
  351. @end quotation
  352. where @code{r} is the rank of @code{R}.
  353. 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
  354. @quotation
  355. @code{(R+S)(i₀ i₁ ... i₍ᵣ₋₁₎) = R(i₀ i₁ ... i₍ᵣ₋₁₎) + S()}.
  356. @end quotation
  357. The two rules above are supported by all primitive array languages, e.g. Matlab REF. 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
  358. @quotation
  359. @code{(R+S)(i₀ i₁ ... i₍ₛ₋₁₎ ... i₍ᵣ₋₁₎) = R(i₀ i₁ ... i₍ₛ₋₁₎ ... i₍ᵣ₋₁₎) + S(i₀ i₁ ... i₍ₛ₋₁₎)}.
  360. @end quotation
  361. That is, after we run out of indices in @code{S}, we simply repeat the elements. We have aligned the shapes so:
  362. @quotation
  363. @verbatim
  364. [n₀ n₁ ... n₍ₛ₋₁₎ ... n₍ᵣ₋₁₎]
  365. [n₀ n₁ ... n₍ₛ₋₁₎]
  366. @end verbatim
  367. @end quotation
  368. @cindex shape agreement, prefix
  369. @cindex shape agreement, suffix
  370. @c @cindex J
  371. @cindex Numpy
  372. This rank extension rule is used by J REF and is known as @dfn{prefix agreement}. (The opposite rule of @dfn{suffix agreement} is used, for example, in Numpy REF.)
  373. 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{ra::}, even in assignments. For example,
  374. @example
  375. @verbatim
  376. ra::Small<int, 3> x {3, 5, 9};
  377. ra::Small<int, 3, 2> a = x; // assign x(i) to each a(i, j)
  378. @end verbatim
  379. @result{} a = @{@{3, 3@}, @{5, 5@}, @{9, 9@}@}
  380. @end example
  381. @example
  382. @verbatim
  383. ra::Small<int, 3> x(0.);
  384. ra::Small<int, 3, 2> a = {1, 2, 3, 4, 5, 6};
  385. x += a; // sum the rows of a
  386. @end verbatim
  387. @result{} x = @{3, 7, 11@}
  388. @end example
  389. @example
  390. @verbatim
  391. ra::Big<double, 3> a({5, 3, 3}, ra::_0);
  392. ra::Big<double, 2> b({5}, 0.);
  393. b += transpose<0, 1, 1>(a); // b(i) = ∑ⱼ a(i, j, j)
  394. @end verbatim
  395. @result{} b = @{0, 3, 6, 9, 12@}
  396. @end example
  397. An obvious weakness of prefix agreement is that sometimes the axes you want to match are not the prefix axes. Obviously @ref{x-transpose,transposing} the axes before extension is a workaround. For a more general form of rank extension, @pxref{The rank conjunction}.
  398. @cindex Numpy
  399. @cindex broadcasting, singleton
  400. Other languages have a feature similar to rank extension called `broadcasting'. For example, in the way it's implemented in Numpy, an array of shape [A B 1 D] will match an array of shape [A B C D]. The process of broadcasting consists in inserting so-called `singleton dimensions' (axes with size one) to align the axes that one wishes to match. This is more general than prefix agreement, because any axes can be matched. You can think of prefix agreement as the case where all the singleton dimensions are added to the end of the shape.
  401. Singleton broadcasting still isn't entirely general, since it doesn't handle transposition. Another drawback is that it muddles the distinction between a scalar and a vector of size 1. Sometimes, an axis of size 1 is no more than that, and if 2!=3 is a size error, it isn't obvious why 1!=2 shouldn't be.
  402. @c ------------------------------------------------
  403. @node Cell iteration
  404. @section Cell iteration
  405. @c ------------------------------------------------
  406. @code{map} and @code{for_each} apply their operators to each element of their arguments; in other words, to the 0-cells of the arguments. But it is possible to specify directly the rank of the cells that one iterates over:
  407. @example
  408. @verbatim
  409. ra::Big<double, 3> a({5, 4, 3}, ra::_0);
  410. for_each([](auto && b) { /* b has shape (5 4 3) */ }, iter<3>(a));
  411. for_each([](auto && b) { /* b has shape (4 3) */ }, iter<2>(a));
  412. for_each([](auto && b) { /* b has shape (3) */ }, iter<1>(a));
  413. for_each([](auto && b) { /* b has shape () */ }, iter<0>(a)); // elements
  414. for_each([](auto && b) { /* b has shape () */ }, a); // same as iter<0>(a); default
  415. @end verbatim
  416. @end example
  417. One may specify the @emph{frame} rank instead:
  418. @example
  419. @verbatim
  420. for_each([](auto && b) { /* b has shape () */ }, iter<-3>(a)); // same as iter<0>(a)
  421. for_each([](auto && b) { /* b has shape (3) */ }, iter<-2>(a)); // same as iter<1>(a)
  422. for_each([](auto && b) { /* b has shape (4 3) */ }, iter<-1>(a)); // same as iter<2>(a)
  423. @end verbatim
  424. @end example
  425. In this way it is possible to match shapes in various ways. Compare
  426. @example
  427. @verbatim
  428. ra::Big<double, 2> a({2, 3}, {1, 2, 3, 4, 5, 6});
  429. ra::Big<double, 2> b({2}, {10, 20});
  430. ra::Big<double, 2> c = a * b; // multiply (each item of a) by (each item of b)
  431. @end verbatim
  432. @result{} a = @{@{10, 20, 30@}, @{80, 100, 120@}@}
  433. @end example
  434. with
  435. @example @c [ma105]
  436. @verbatim
  437. ra::Big<double, 2> a({2, 3}, {1, 2, 3, 4, 5, 6});
  438. ra::Big<double, 2> b({3}, {10, 20, 30});
  439. ra::Big<double, 2> c({2, 3}, 0.);
  440. iter<1>(c) = iter<1>(a) * iter<1>(b); // multiply (each item of a) by (b)
  441. @end verbatim
  442. @result{} a = @{@{10, 40, 90@}, @{40, 100, 180@}@}
  443. @end example
  444. Note that in this case we cannot construct @code{c} directly from @code{iter<1>(a) * iter<1>(b)}, since the constructor for @code{ra::Big} matches its argument using (the equivalent of) @code{iter<0>(*this)}. See @ref{x-iter,@code{iter}} for more examples.
  445. Cell iteration is best used when the operations take naturally operands of rank > 0; for instance, the operation `determinant of a matrix' is naturally of rank 2. When the operation is of rank 0, such as @code{*} above, there may be faster ways to rearrange shapes for matching (@pxref{The rank conjunction}).
  446. FIXME More examples.
  447. @c ------------------------------------------------
  448. @node Slicing
  449. @section Slicing
  450. @c ------------------------------------------------
  451. Slicing is an array extension of the subscripting operation. However, tradition and convenience have given it a special status in most array languages, together with some peculiar semantics that @code{ra::} supports.
  452. The form of the scripting operator @code{A(i₀, i₁, ...)} makes it plain that @code{A} is a function of @code{rank(A)} integer arguments. An array extension is immediately available through @code{map}. For example:
  453. @example
  454. @verbatim
  455. ra::Big<double, 1> a = {1., 2., 3., 4.};
  456. ra::Big<int, 1> i = {1, 3};
  457. map(a, i) = 77.;
  458. @end verbatim
  459. @result{} a = @{1., 77., 3, 77.@}
  460. @end example
  461. Just as with any use of @code{map}, array arguments are subject to the prefix agreement rule.
  462. @example
  463. @verbatim
  464. ra::Big<double, 2> a({2, 2}, {1., 2., 3., 4.});
  465. ra::Big<int, 1> i = {1, 0};
  466. ra::Big<double, 1> b = map(a, i, 0);
  467. @end verbatim
  468. @result{} b = @{3., 1.@} // @{a(1, 0), a(0, 0)@}
  469. @end example
  470. @example
  471. @verbatim
  472. ra::Big<int, 1> j = {0, 1};
  473. b = map(a, i, j);
  474. @end verbatim
  475. @result{} b = @{3., 2.@} // @{a(1, 0), a(0, 1)@}
  476. @end example
  477. The latter is a form of sparse subscripting.
  478. Most array operations (e.g. @code{+}) are defined through @code{map} in this way. For example, @code{A+B+C} is defined as @code{map(+, A, B, C)} (or the equivalent @code{map(+, map(+, A, B), C)}). Not so for the subscripting operation:
  479. @example
  480. @verbatim
  481. ra::Big<double, 2> A({2, 2}, {1., 2., 3., 4.});
  482. ra::Big<int, 1> i = {1, 0};
  483. ra::Big<int, 1> j = {0, 1};
  484. // {{A(i₀, j₀), A(i₀, j₁)}, {A(i₁, j₀), A(i₁, j₁)}}
  485. ra::Big<double, 2> b = A(i, j);
  486. @end verbatim
  487. @result{} b = @{@{3., 4.@}, @{1., 2.@}@}
  488. @end example
  489. @code{A(i, j, ...)} is the @emph{outer product} of the indices @code{(i, j, ...)} with operator @code{A}.
  490. This operation sees much more use in practice than @code{map(A, i, j ...)}. Besides, when the subscripts @code{i, j, ...} are scalars or @dfn{linear ranges} (integer sequences of the form @code{(o, o+s, ..., o+s*(n-1))}, the subscripting can be performed inmediately at constant cost and without needing to construct an expression object. This optimization is called @ref{Drag along and beating,@dfn{beating}}.
  491. @code{ra::} isn't smart enough to know when an arbitrary expression might be a linear range, so the following special objects are provided:
  492. @deffn @w{Special object} iota count [start:0 [step:1]]
  493. Create a linear range @code{start, start+step, ... start+step*(count-1)}.
  494. @end deffn
  495. This can used anywhere an array expression is expected.
  496. @example
  497. @verbatim
  498. ra::Big<int, 1> a = ra::iota(4, 3 -2);
  499. @end verbatim
  500. @result{} a = @{3, 1, -1, -3@}
  501. @end example
  502. Here, @code{b} and @code{c} are @code{View}s (@pxref{Containers and views}).
  503. @example
  504. @verbatim
  505. ra::Big<int, 1> a = {1, 2, 3, 4, 5, 6};
  506. auto b = a(iota(3));
  507. auto c = a(iota(3, 3));
  508. @end verbatim
  509. @result{} a = @{1, 2, 3@}
  510. @result{} a = @{4, 5, 6@}
  511. @end example
  512. @deffn @w{Special object} all
  513. Create a linear range @code{0, 1, ... (nᵢ-1)} when used as a subscript for the @code{i}-th argument of a subscripting expression.
  514. @end deffn
  515. This object cannot stand alone as an array expression. All the examples below result in @code{View} objects:
  516. @example
  517. @verbatim
  518. ra::Big<int, 2> a({3, 2}, {1, 2, 3, 4, 5, 6});
  519. auto b = a(ra::all, ra::all); // (1) a view of the whole of a
  520. auto c = a(iota(3), iota(2)); // same as (1)
  521. auto d = a(iota(3), ra::all); // same as (1)
  522. auto e = a(ra:all, iota(2)); // same as (1)
  523. auto f = a(0, ra::all); // first row of a
  524. auto g = a(ra::all, 1); // second column of a
  525. @end verbatim
  526. @end example
  527. @code{all} is a special case (@code{dots<1>}) of the more general object @code{dots}.
  528. @deffn @w{Special object} dots<n>
  529. Equivalent to as many instances of @code{ra::all} as indicated by @code{n}, which must not be negative. Each instance takes the place of one argument to the subscripting operation.
  530. @end deffn
  531. This object cannot stand alone as an array expression. All the examples below result in @code{View} objects:
  532. @example
  533. @verbatim
  534. auto h = a(ra::all, ra::all); // same as (1)
  535. auto i = a(ra::all, ra::dots<1>); // same as (1)
  536. auto j = a(ra::dots<2>); // same as (1)
  537. auto k = a(ra::dots<0>, ra::dots<2>); // same as (1)
  538. auto l = a(0, ra::dots<1>); // first row of a
  539. auto m = a(ra::dots<1>, 1); // second column of a
  540. @end verbatim
  541. @end example
  542. This is useful when writing rank-generic code, see @code{examples/maxwell.C} in the distribution for an example.
  543. @deffn @w{Special object} newaxis<n>
  544. Inserts @code{n} new axes at the subscript position. @code{n} must not be negative. The new axes have size 1 and stride 0.
  545. @end deffn
  546. This object cannot stand alone as an array expression. All the examples below result in @code{View} objects:
  547. @example
  548. @verbatim
  549. auto h = a(newaxis<0>); // same as (1)
  550. auto i = a(newaxis<1>); // same contents as ra::Big<int, 2> a({1, 3, 2}, {1, 2, 3, 4, 5, 6})
  551. @end verbatim
  552. @end example
  553. @cindex broadcasting, singleton
  554. @code{newaxis<n>} main use is to prepare arguments for broadcasting. However, since argument agreement in @code{ra::} requires exact size match on all dimensions, this isn't currently as useful as in e.g. Numpy where dimensions of size 1 match dimensions of any other size. A more flexible syntax @code{newaxis(n0, n1...)} to insert axes of arbitrary sizes may be implemented in the future.
  555. In addition to the special objects listed above, you can also omit any trailing @code{ra::all} subscripts. For example:
  556. @example
  557. @verbatim
  558. ra::Big<int, 3> a({2, 2, 2}, {1, 2, 3, 4, 5, 6, 7, 8});
  559. auto a0 = a(0); // same as a(0, ra::all, ra::all)
  560. auto a10 = a(1, 0); // same as a(1, 0, ra::all)
  561. @end verbatim
  562. @result{} a0 = @{@{1, 2@}, @{3, 4@}@}
  563. @result{} a10 = @{5, 6@}
  564. @end example
  565. This supports the notion (@pxref{Rank polymorphism}) that a 3-array is also an 2-array where the elements are 1-arrays themselves, or a 1-array where the elements are 2-arrays. This important property is directly related to the mechanism of rank extension (@pxref{Rank extension}).
  566. @c ------------------------------------------------
  567. @node Special objects
  568. @section Special objects
  569. @c ------------------------------------------------
  570. @deffn @w{Special object} TensorIndex<n, integer_type=ra::dim_t>
  571. @code{TensorIndex<n>} represents the @code{n}-th index of an array expression. @code{TensorIndex<n>} is itself an array expression of rank @code{n}-1 and size undefined. It must be used with other terms whose dimensions are defined, so that the overall shape of the array expression can be determined.
  572. @code{ra::} offers the shortcut @code{ra::_0} for @code{ra::TensorIndex<0>@{@}}, etc.
  573. @end deffn
  574. @example
  575. @verbatim
  576. ra::Big<int, 1> v = {1, 2, 3};
  577. cout << (v - ra::_0) << endl; // { 1-0, 2-1, 3-2 }
  578. // cout << (ra::_0) << endl; // error: TensorIndex cannot drive array expression
  579. // cout << (v - ra::_1) << endl; // error: TensorIndex cannot drive array expression
  580. ra::Big<int, 2> a({3, 2}, 0);
  581. cout << (a + ra::_0 - ra::_1) << endl; // {{0, -1, -2}, {1, 0, -1}, {2, 1, 0}}
  582. @end verbatim
  583. @end example
  584. Note that array expressions using @code{TensorIndex} will generally be slower than array expressions not using @code{TensorIndex}, especially if they have rank > 1, because the presence of @code{TensorIndex} prevents nested loops from being flattened (@pxref{Internals}). @c FIXME Have an implementation section to discuss these issues
  585. @c FIXME the rest
  586. @c ------------------------------------------------
  587. @node The rank conjunction
  588. @section The rank conjunction
  589. @c ------------------------------------------------
  590. We have seen in @ref{Cell iteration} that it is possible to treat an r-array as an array of lower rank with subarrays as its elements. With the @ref{x-iter,@code{iter<cell rank>}} construction, this `exploding' is performed (notionally) on the argument; the operation of the array expression is applied blindly to these cells, whatever they turn out to be.
  591. @example
  592. @verbatim
  593. for_each(sort, A.iter<1>()); // (in ra::) sort is a regular function, cell rank must be given
  594. for_each(sort, A.iter<0>()); // (in ra::) error, bad cell rank
  595. @end verbatim
  596. @end example
  597. @c @cindex J
  598. The array language J has instead the concept of @dfn{verb rank}. Every function (or @dfn{verb}) has an associated cell rank for each of its arguments. Therefore @code{iter<cell rank>} is not needed.
  599. @example
  600. @verbatim
  601. for_each(sort_rows, A); // (not in ra::) will iterate over 1-cells of A, sort_rows knows
  602. @end verbatim
  603. @end example
  604. @c @cindex J
  605. @code{ra::} doesn't have `verb ranks' yet. In practice one can think of @code{ra::}'s operations as having a verb rank of 0. However, @code{ra::} supports a limited form of J's @dfn{rank conjunction} with the function @ref{x-wrank,@code{wrank}}.
  606. @c @cindex J
  607. This is an operator that takes one verb (such operators are known as @dfn{adverbs} in J) and produces another verb with different ranks. These ranks are used for rank extension through prefix agreement, but then the original verb is used on the cells that result. The rank conjunction can be nested, and this allows repeated rank extension before the innermost operation is applied.
  608. A standard example is `outer product'.
  609. @example
  610. @verbatim
  611. ra::Big<int, 1> a = {1, 2, 3};
  612. ra::Big<int, 1> b = {40, 50};
  613. ra::Big<int, 2> axb = map(ra::wrank<0, 1>([](auto && a, auto && b) { return a*b; }),
  614. a, b)
  615. @end verbatim
  616. @result{} axb = @{@{40, 80, 120@}, @{50, 100, 150@}@}
  617. @end example
  618. It works like this. The verb @code{ra::wrank<0, 1>([](auto && a, auto && b) @{ return a*b; @})} has verb ranks (0, 1), so the 0-cells of @code{a} are paired with the 1-cells of @code{b}. In this case @code{b} has a single 1-cell. The frames and the cell shapes of each operand are:
  619. @example
  620. @verbatim
  621. a: 3 |
  622. b: | 2
  623. @end verbatim
  624. @end example
  625. Now the frames are rank-extended through prefix agreement.
  626. @example
  627. @verbatim
  628. a: 3 |
  629. b: 3 | 2
  630. @end verbatim
  631. @end example
  632. Now we need to perform the operation on each cell. The verb @code{[](auto && a, auto && b) @{ return a*b; @}} has verb ranks (0, 0). This results in the 0-cells of @code{a} (which have shape ()) being rank-extended to the shape of the 1-cells of @code{b} (which is (2)).
  633. @example
  634. @verbatim
  635. a: 3 | 2
  636. b: 3 | 2
  637. @end verbatim
  638. @end example
  639. This use of the rank conjunction is packaged in @code{ra::} as the @ref{x-from,@code{from}} operator. It supports any number of arguments, not only two.
  640. @example
  641. @verbatim
  642. ra::Big<int, 1> a = {1, 2, 3};
  643. ra::Big<int, 1> b = {40, 50};
  644. ra::Big<int, 2> axb = from([](auto && a, auto && b) { return a*b; }), a, b)
  645. @end verbatim
  646. @result{} axb = @{@{40, 80, 120@}, @{50, 100, 150@}@}
  647. @end example
  648. Another example is matrix multiplication. For 2-array arguments C, A and B with shapes C: (m, n) A: (m, p) and B: (p, n), we want to perform the operation C(i, j) += A(i, k)*B(k, j). The axis alignment gives us the ranks we need to use.
  649. @example
  650. @verbatim
  651. C: m | | n
  652. A: m | p |
  653. B: | p | n
  654. @end verbatim
  655. @end example
  656. First we'll align the first axes of C and A using the cell ranks (1, 1, 2). The cell shapes are:
  657. @example
  658. @verbatim
  659. C: m | n
  660. A: m | p
  661. B: | p n
  662. @end verbatim
  663. @end example
  664. Then we'll use the ranks (1, 0, 1) on the cells:
  665. @example
  666. @verbatim
  667. C: m | | n
  668. A: m | p |
  669. B: | p | n
  670. @end verbatim
  671. @end example
  672. The final operation is a standard operation on arrays of scalars. In actual @code{ra::} syntax:
  673. @example @c [ma103]
  674. @verbatim
  675. ra::Big A({3, 2}, {1, 2, 3, 4, 5, 6});
  676. ra::Big B({2, 3}, {7, 8, 9, 10, 11, 12});
  677. ra::Big C({3, 3}, 0.);
  678. for_each(ra::wrank<1, 1, 2>(ra::wrank<1, 0, 1>([](auto && c, auto && a, auto && b) { c += a*b; })), C, A, B);
  679. @end verbatim
  680. @result{} C = @{@{27, 30, 33@}, @{61, 68, 75@}, @{95, 106, 117@}@}
  681. @end example
  682. Note that @code{wrank} cannot be used to transpose axes in general.
  683. I hope that in the future something like @code{C(i, j) += A(i, k)*B(k, j)}, where @code{i, j, k} are special objects, can be automatically translated to the requisite combination of @code{wrank} and perhaps also @ref{x-transpose,@code{transpose}}. For the time being, you have to align or transpose the axes yourself.
  684. @c ------------------------------------------------
  685. @node Compatibility
  686. @section Compatibility
  687. @c ------------------------------------------------
  688. @subsection Using other C and C++ types with @code{ra::}
  689. @cindex foreign type
  690. @code{ra::} is able to accept certain types from outside @code{ra::} (@dfn{foreign types}) as array expressions. Generally it is enough to mix the foreign type with a type from @code{ra::} and let deduction work its magic.
  691. @example
  692. @verbatim
  693. std::vector<int> x = {1, 2, 3};
  694. ra::Small<int, 3> y = {6, 5, 4};
  695. cout << (x-y) << endl;
  696. @end verbatim
  697. @print{} -5 -3 -1
  698. @end example
  699. @cindex @code{start}
  700. Foreign types can be brought into @code{ra::} explicitly with the function @ref{x-start,@code{start}}.
  701. @example
  702. @verbatim
  703. std::vector<int> x = {1, 2, 3};
  704. cout << sum(ra::start(x)) << endl;
  705. cout << ra::sum(x) << endl;
  706. @end verbatim
  707. @print{} 6
  708. 6
  709. @end example
  710. The following types are accepted as foreign types:
  711. @itemize
  712. @item @code{std::vector}
  713. produces an expression of rank 1 and dynamic size.
  714. @item @code{std::array}
  715. produces an expression of rank 1 and fixed size.
  716. @item Builtin arrays
  717. produce an expression of positive rank and fixed size.
  718. @item Raw pointers
  719. produce an expression of rank 1 and @emph{undefined} size. Raw pointers must always be brought into @code{ra::} explicitly with the function @ref{x-ptr,@code{ptr}}.
  720. @end itemize
  721. Compare:
  722. @example @c [ma106]
  723. @verbatim
  724. int p[] = {1, 2, 3};
  725. int * z = p;
  726. ra::Big<int, 1> q {1, 2, 3};
  727. q += p; // ok, q is ra::, p is foreign object with size info
  728. ra::start(p) += q; // can't redefine operator+=(int[]), foreign needs ra::start()
  729. // z += q; // error: raw pointer needs ra::ptr()
  730. ra::ptr(z) += p; // ok, size is determined by foreign object p
  731. @end verbatim
  732. @end example
  733. @anchor{x-is-scalar}
  734. Some types are accepted automatically as scalars. These include:
  735. @itemize
  736. @item
  737. Any type @code{T} for which @code{std::is_scalar<T>::value} is true, @emph{except} pointers. These include @code{char}, @code{int}, @code{double}, etc.
  738. @item
  739. @code{std::complex<T>}, if you import @code{ra/complex.H}.
  740. @end itemize
  741. You can add your own types as scalar types with the following declaration (see @code{ra/complex.H}):
  742. @verbatim
  743. namespace ra { template <> constexpr bool is_scalar_def<MYTYPE> = true; }
  744. @end verbatim
  745. Otherwise, you can bring a scalar object into @code{ra::} on the spot, with the function @ref{x-scalar,@code{scalar}}.
  746. @subsection Using @code{ra::} types with the STL
  747. General @code{ra::} @ref{Containers and views,views} provide STL compatible @code{ForwardIterator}s with the members @code{begin()} and @code{end()}. These iterators traverse the elements of the array (0-cells) in row major order.
  748. For @ref{Containers and views,containers} @code{begin()} provides @code{RandomAccessIterator}s, which is handy for certain functions such as @code{sort}. There's no reason why all views couldn't provide @code{RandomAccessIterator}, but these wouldn't be efficient in general for ranks above 1 and I haven't implemented them ---those @code{RandomAccessIterator} are in fact raw pointers.
  749. @example @c [ma106]
  750. @verbatim
  751. ra::Big<int> x {3, 2, 1}; // x is a Container
  752. auto y = x(); // y is a View on x
  753. // std::sort(y.begin(), y.end()); // error: y.begin() is not RandomAccessIterator
  754. std::sort(x.begin(), x.end());
  755. @result{} x = @{1, 2, 3@}
  756. @end verbatim
  757. @end example
  758. @subsection Using @code{ra::} types with other libraries
  759. When you have to pass arrays back and forth between your program and an external library, perhaps even another language, it is necessary for both sides to agree on a memory layout. @code{ra::} gives you access to its own memory layout and allows you to obtain a @code{ra::} view on any type of memory.
  760. FIXME lapack example
  761. FIXME fftw example
  762. FIXME Guile example
  763. @c ------------------------------------------------
  764. @node Extension
  765. @section Extension
  766. @c ------------------------------------------------
  767. @subsection New scalar types
  768. @code{ra::} will let you construct arrays of arbitrary types out of the box. This is the same functionality you get with e.g. @code{std::vector}.
  769. @example
  770. @verbatim
  771. struct W { int x; }
  772. ra::Big<W, 2> w({2, 2}, { {4}, {2}, {1}, {3} });
  773. cout << W(1, 1).x << endl;
  774. cout << amin(map([](auto && x) { return w.x; }, w)) << endl;
  775. @end verbatim
  776. @print{} 3
  777. 1
  778. @end example
  779. However, if you want to mix arbitrary types in array operations, you'll need to tell @code{ra::} that that is actually what you want ---this is to avoid conflicts with other libraries.
  780. @example
  781. @verbatim
  782. namespace ra { template <> constexpr bool is_scalar_def<W> = true; }
  783. ...
  784. W ww {11};
  785. for_each([](auto && x, auto && y) { cout << x.x + y.y << " "; }, w, ww); // ok
  786. @end verbatim
  787. @print{} 15 13 12 14
  788. @end example
  789. but
  790. @example
  791. @verbatim
  792. struct U { int x; }
  793. U uu {11};
  794. for_each([](auto && x, auto && y) { cout << x.x + y.y << " "; }, w, uu); // error: can't find ra::start(U)
  795. @end verbatim
  796. @end example
  797. @anchor{x-new-array-operations}
  798. @subsection New array operations
  799. @code{ra::} provides array extensions for standard operations such as @code{+}, @code{*}, @code{cos} @ref{x-scalar-ops,and so on}. You can add array extensions for your own operations in the obvious way, with @ref{x-map,@code{map}} (but note the namespace qualifiers):
  800. @example
  801. @verbatim
  802. return_type my_fun(...) { };
  803. ...
  804. namespace ra {
  805. template <class ... A> inline auto
  806. my_fun(A && ... a)
  807. {
  808. return map(::my_fun, std::forward<A>(a) ...);
  809. }
  810. } // namespace ra
  811. @end verbatim
  812. @end example
  813. @cindex Blitz++
  814. If you compare this with what Blitz++ had to do, modern C++ sure has made our lives easier.
  815. If @code{my_fun} is an overload set, you can use
  816. @example
  817. @verbatim
  818. namespace ra {
  819. template <class ... A> inline auto
  820. my_fun(A && ... a)
  821. {
  822. return map([](auto && ... a) { return ::my_fun(a ...); }, std::forward<A>(a) ...);
  823. }
  824. } // namespace ra
  825. @end verbatim
  826. @end example
  827. @c ------------------------------------------------
  828. @node Functions
  829. @section Functions
  830. @c ------------------------------------------------
  831. You don't need to use @ref{Array operations,@code{map}} every time you want to do something with arrays in @code{ra::}. A number of array functions are already defined.
  832. @anchor{x-scalar-ops}
  833. @subsection Standard scalar operations
  834. @code{ra::} defines array extensions for @code{+}, @code{-} (both unary and binary), @code{*}, @code{/}, @code{!}, @code{&&}, @code{||}@footnote{@code{&&}, @code{||} do not short-circuit; this is a bug.}, @code{>}, @code{<}, @code{>=}, @code{<=}, @code{==}, @code{!=}, @code{pow}, @code{sqr}, @code{sqrm}, @code{abs}, @code{cos}, @code{sin}, @code{exp}, @code{expm1}, @code{sqrt}, @code{log}, @code{log1p}, @code{log10}, @code{isfinite}, @code{isnan}, @code{isinf}, @code{max}, @code{min}, @code{odd}, @code{asin}, @code{acos}, @code{atan}, @code{atan2}, @code{cosh}, @code{sinh}, @code{tanh}. Extending other scalar operations is straightforward; see @ref{x-new-array-operations,New array operations}. @code{ra::} also defines (and extends) the non-standard functions @ref{x-conj,@code{conj}}, @ref{x-rel-error,@code{rel_error}}, and @ref{x-xI,@code{xI}}.
  835. @subsection Conditional operations
  836. @ref{x-map,@code{map}} evaluates all of its arguments before passing them along to its operator. This isn't always what you want. The simplest example is @code{where(condition, iftrue, iffalse)}, which returns an expression that will evaluate @code{iftrue} when @code{condition} is true and @code{iffalse} otherwise.
  837. @example
  838. @verbatim
  839. ra::Big<double> x ...
  840. ra::Big<double> y = where(x>0, expensive_expr_1(x), expensive_expr_2(x));
  841. @end verbatim
  842. @end example
  843. Here @code{expensive_expr_1} and @code{expensive_expr_2} are array expressions. So the computation of the other arm would be wasted if one where to do instead
  844. @example
  845. @verbatim
  846. ra::Big<double> y = map([](auto && w, auto && t, auto && f) -> decltype(auto) { return w ? t : f; }
  847. x>0, expensive_expr_1(x), expensive_function_2(x));
  848. @end verbatim
  849. @end example
  850. If the expressions have side effects, then @code{map} won't even give the right result.
  851. @c [ma109]
  852. @example
  853. @verbatim
  854. ra::Big<int, 1> o = {};
  855. ra::Big<int, 1> e = {};
  856. ra::Big<int, 1> n = {1, 2, 7, 9, 12};
  857. ply(where(odd(n), map([&o](auto && x) { o.push_back(x); }, n), map([&e](auto && x) { e.push_back(x); }, n)));
  858. cout << "o: " << format_array(o, false) << ", e: " << format_array(e, false) << endl;
  859. @end verbatim
  860. @print{} o: 1 7 9, e: 2 12
  861. @end example
  862. FIXME Very artificial example.
  863. FIXME Do we want to expose ply(); this is the only example in the manual that uses it.
  864. When the choice is between more than two expressions, there's @ref{x-pick,@code{pick}}, which operates similarly.
  865. @subsection Special operations
  866. Some operations are essentially scalar operations, but require special syntax and would need a lambda wrapper to be used with @code{map}. @code{ra::} comes with a few of these already defined.
  867. FIXME
  868. @subsection Elementwise reductions
  869. @code{ra::} defines the following common reductions.
  870. FIXME
  871. Note that @code{max} and @code{min} are two-argument scalar operations with array extensions, while @code{amax} and @code{amin} are reductions.
  872. You can define similar reductions in the same way that @code{ra::} does it:
  873. FIXME
  874. Often enough you need to reduce over particular axes. This is possible by combining assignment operators with the @ref{Rank extension,rank extension} mechanism, or using the @ref{The rank conjunction,rank conjunction}.
  875. FIXME example with assignment op
  876. A few common operations of this type are already packaged in @code{ra::}.
  877. @subsection Special reductions
  878. @code{ra::} defines the following special reductions.
  879. FIXME
  880. @subsection Shortcut reductions
  881. Some reductions do not need to traverse the whole array if a certain condition is encountered early. The most obvious ones are the reductions of @code{&&} and @code{||}, which @code{ra::} defines as @code{every} and @code{any}.
  882. FIXME
  883. These operations are defined on top of another function @code{early}.
  884. FIXME early
  885. The following is often useful.
  886. FIXME lexicographical compare etc.
  887. @c ------------------------------------------------
  888. @node Hazards
  889. @chapter Hazards
  890. @c ------------------------------------------------
  891. Some of these issues arise because @code{ra::} applies its principles systematically, which can have surprising results. Still others are the result of unfortunate compromises. And a few are just bugs.
  892. @section Understand rank extension
  893. Assignment of an expression onto another expression of lower rank may not do what you expect. This example matches @code{a} and 3 [both of shape ()] with a vector of shape (3). This is equivalent to @code{@{a=3+4; a=3+5; a=3+6;@}}. You may get a different result depending on the order of traversal.
  894. @example @c [ma107]
  895. @verbatim
  896. int a = 0;
  897. ra::scalar(a) = 3 + ra::Small<int, 3> {4, 5, 6};
  898. @end verbatim
  899. @result{} a = 9
  900. @end example
  901. @section Chained assignment
  902. FIXME
  903. When @code{a=b=c} works, it operates as @code{b=c; a=b;} and not as an array expression.
  904. @section Unregistered scalar types
  905. FIXME
  906. @code{View<T, N> x; x = T()} fails if @code{T} isn't registered as @code{is_scalar}.
  907. @section Assignment to views
  908. FIXME
  909. With large containers (e.g. @code{Big}), @code{operator=} replaces the lhs instead of writing over its contents. This behavior is inconsistent with @code{View::operator=} and is there only so that istream >> container may work; do not rely on it.
  910. @section Array iterators and temporaries
  911. FIXME
  912. @section Size of brace initializers isn't checked until run time
  913. FIXME
  914. @enumerate
  915. @item
  916. Item 0
  917. @item
  918. Item 1
  919. @item
  920. Item 2
  921. @end enumerate
  922. @c ------------------------------------------------
  923. @node Internals
  924. @chapter Internals
  925. @c ------------------------------------------------
  926. @menu
  927. * Type hierarchy:: From Containers to FlatIterators.
  928. * Driving expressions:: The term in charge.
  929. * Loop types:: Chosen for performance.
  930. * Compiling and running:: Practical matters.
  931. @end menu
  932. @c ------------------------------------------------
  933. @node Type hierarchy
  934. @section Type hierarchy
  935. @c ------------------------------------------------
  936. @c ------------------------------------------------
  937. @node Driving expressions
  938. @section Driving expressions
  939. @c ------------------------------------------------
  940. @c ------------------------------------------------
  941. @node Loop types
  942. @section Loop types
  943. @c ------------------------------------------------
  944. @c ------------------------------------------------
  945. @node Compiling and running
  946. @section Compiling and running
  947. @c ------------------------------------------------
  948. The following boolean @code{#define}s affect the behavior of @code{ra::}.
  949. @itemize
  950. @item @code{RA_CHECK_BOUNDS} (default 1) Check bounds on random array accesses (e.g. @code{int i = 10; a[i] = 0;}). Bounds are never checked on regular array traversal, since in that case the library can guarantee that out of bounds accesses don't happen.
  951. @item @code{RA_USE_BLAS} (default 0) Try to use BLAS for certain rank 1 and rank 2 operations. Currently this is only used by some of the benchmarks and not by the library itself.
  952. @item @code{RA_OPTIMIZE} (default 1) Replace certain expressions by others that are expected to perform better. This acts as a global mask on other @code{RA_OPTIMIZE_xxx} flags.
  953. @item @code{RA_OPTIMIZE_IOTA} (default 1) Perform immediately (beat) certain operations on @code{ra::Iota} objects. For example, @code{ra::Iota(3, 0) + 1} becomes @code{ra::Iota(3, 1)} instead of a two-operand expression template.
  954. @item @code{RA_OPTIMIZE_SMALLVECTOR} (default 0) Perform immediately certain operations on @code{ra::Small} objects, using small vector intrinsics. Currently this only works on gcc and doesn't necessarily result in improved performance.
  955. @end itemize
  956. @code{ra::} comes with three kinds of tests: examples, proper tests, and benchmarks. Simply run @code{scons} from the top directory of the distribution to run them all. @code{ra::} uses its own crude test and benchmark suites.
  957. @c ------------------------------------------------
  958. @node The future
  959. @chapter The future
  960. @c ------------------------------------------------
  961. Wishlist and acknowledged bugs.
  962. @c ------------------------------------------------
  963. @node Reference
  964. @chapter Reference
  965. @c ------------------------------------------------
  966. @anchor{x-map} @defun map op expr ...
  967. Create an array expression that applies @var{op} to @var{expr} ...
  968. @end defun
  969. For example:
  970. @example
  971. @verbatim
  972. ra::Big<double, 1> x = map(cos, ra::Small<double, 1> {0.});
  973. @end verbatim
  974. @result{} x = @{ 1. @}
  975. @end example
  976. @var{op} can return a reference. A typical use is subscripting. For example (TODO better example, e.g. using STL types):
  977. @example
  978. @verbatim
  979. ra::Big<int, 2> x = {{3, 3}, 0.};
  980. map([](auto && i, auto && j) -> int & { return x(i, j); },
  981. ra::Big<int, 1> {0, 1, 1, 2}, ra::Big<int, 1> {1, 0, 2, 1})
  982. = 1;
  983. @end verbatim
  984. @result{} x = @{@{0, 1, 0@}, @{1, 0, 1@}, @{0, 1, 0@}@}
  985. @end example
  986. Here the anonymous function can be replaced by simply @code{x}. Remember that unspecified return type defaults to (value) @code{auto}, so either a explicit type or @code{decltype(auto)} should be used if you want to return a reference.
  987. @anchor{x-for_each} @defun for_each op expr ...
  988. Create an array expression that applies @var{op} to @var{expr} ..., and traverse it.
  989. @end defun
  990. @var{op} should normally return @code{void}. For example:
  991. @example
  992. @verbatim
  993. double s = 0.;
  994. for_each([&s](auto && a) { s+=a; }, ra::Small<double, 1> {1., 2., 3})
  995. @end verbatim
  996. @result{} s = 6.
  997. @end example
  998. @defun ply expr
  999. Traverse @var{expr}. @code{ply} returns @code{void} so @var{expr} should be run for effect.
  1000. @end defun
  1001. It is rarely necessary to use @code{ply}. Expressions are traversed automatically when they are assigned to views, for example, or printed out. @ref{x-for_each,@code{for_each}}@code{(...)} (which is actually @code{ply(map(...))} should cover most other uses.
  1002. @example
  1003. @verbatim
  1004. double s = 0.;
  1005. ply(map([&s](auto && a) { s+=a; }, ra::Small<double, 1> {1., 2., 3})) // same as for_each
  1006. @end verbatim
  1007. @result{} s = 6.
  1008. @end example
  1009. @defun pack <type> expr ...
  1010. Create an array expression that brace-constructs @var{type} from @var{expr} ...
  1011. @end defun
  1012. @defun cast <type> expr
  1013. Create an array expression that casts @var{expr} into @var{type}.
  1014. @end defun
  1015. @anchor{x-pick}
  1016. @defun pick select_expr expr ...
  1017. Create an array expression that selects the first of @var{expr} ... if @var{select_expr} is 0, the second if @var{select_expr} is 1, and so on. The expressions that are not selected are not looked up.
  1018. @end defun
  1019. This function cannot be defined using @ref{x-map,@code{map}}, because @code{map} looks up each one of its argument expressions before calling @var{op}.
  1020. For example:
  1021. @example @c cf examples/readme.C [ma100].
  1022. @verbatim
  1023. ra::Small<int, 3> s {2, 1, 0};
  1024. ra::Small<char const *, 3> z = pick(s, s*s, s+s, sqrt(s));
  1025. @end verbatim
  1026. @result{} z = @{1.41421, 2, 0@}
  1027. @end example
  1028. @defun where pred_expr true_expr false_expr
  1029. Create an array expression that selects @var{true_expr} if @var{pred_expr} is @code{true}, and @var{false_expr} if @var{pred_expr} is @code{false}. The expression that is not selected is not looked up.
  1030. @end defun
  1031. For example:
  1032. @example
  1033. @verbatim
  1034. ra::Big<double, 1> s {1, -1, 3, 2};
  1035. s = where(s>=2, 2, s); // saturate s
  1036. @end verbatim
  1037. @result{} s = @{1, -1, 2, 2@}
  1038. @end example
  1039. @anchor{x-from}
  1040. @defun from op ... expr
  1041. Create outer product expression. This is defined as @math{E(i00, i01 ..., i10, i11, ..., ...) = op(expr0(i01, i01, ...), expr1(i10, i11, ...), ...)}.
  1042. @end defun
  1043. For example:
  1044. @example
  1045. @verbatim
  1046. ra::Big<double, 1> a {1, 2, 3};
  1047. ra::Big<double, 1> b {10, 20, 30};
  1048. ra::Big<double, 2> axb = from([](auto && a, auto && b) { return a*b; }, a, b)
  1049. @end verbatim
  1050. @result{} axb = @{@{10, 20, 30@}, @{20, 40, 60@}, @{30, 60, 90@}@}
  1051. @end example
  1052. @example
  1053. @verbatim
  1054. ra::Big<int, 1> i {2, 1};
  1055. ra::Big<int, 1> j {0, 1};
  1056. ra::Big<double, 2> A({3, 2}, {1, 2, 3, 4, 5, 6});
  1057. ra::Big<double, 2> Aij = from(A, i, j)
  1058. @end verbatim
  1059. @result{} Aij = @{@{6, 5@}, @{4, 3@}@}
  1060. @end example
  1061. The last example is more or less how @code{A(i, j)} is actually implemented (@pxref{The rank conjunction}).
  1062. @defun at expr indices
  1063. Look up @var{expr} at each element of @var{indices}, which shall be a multi-index into @var{expr}.
  1064. @end defun
  1065. This can be used for sparse subscripting. For example:
  1066. @example @c [ra30]
  1067. @verbatim
  1068. ra::Big<int, 2> A({3, 2}, {100, 101, 110, 111, 120, 121});
  1069. ra::Big<ra::Small<int, 2>, 2> i({2, 2}, {{0, 1}, {2, 0}, {1, 0}, {2, 1}});
  1070. ra::Big<int, 2> B = at(A, i);
  1071. @end verbatim
  1072. @result{} B = @{@{101, 120@}, @{110, 121@}@}
  1073. @end example
  1074. @anchor{x-wrank}
  1075. @defun wrank <input_rank ...> op
  1076. Wrap op using a rank conjunction (@pxref{The rank conjunction}).
  1077. @end defun
  1078. For example: TODO
  1079. @example
  1080. @verbatim
  1081. @end verbatim
  1082. @result{} x = 0
  1083. @end example
  1084. @anchor{x-transpose}
  1085. @defun transpose <axes ...> view
  1086. Create a new view by transposing the axes of @var{view}.
  1087. @end defun
  1088. This operation does not work on arbitrary array expressions yet. TODO FILL
  1089. @defun diag view
  1090. Equivalent to @code{transpose<0, 0>(view)}.
  1091. @end defun
  1092. @anchor{x-reverse}
  1093. @defun reverse view axis
  1094. Create a new view by reversing axis @var{k} of @var{view}.
  1095. @end defun
  1096. This is equivalent to @code{view(ra::dots<k>, ra::iota(view.size(k), view.size(k)-1, -1))}.
  1097. This operation does not work on arbitrary array expressions yet. TODO FILL
  1098. @c @anchor{x-reshape}
  1099. @c @defun reshape view shape
  1100. @c Create a new view with shape @var{shape} from the row-major ravel of @var{view}.
  1101. @c @end defun
  1102. @c FIXME fill when the implementation is more mature...
  1103. @c @anchor{x-ravel}
  1104. @c @defun ravel view
  1105. @c Return the ravel of @var{view} as a view on @var{view}.
  1106. @c @end defun
  1107. @c FIXME fill when the implementation is more mature...
  1108. @defun stencil view lo hi
  1109. Create a stencil on @var{view} with lower bounds @var{lo} and higher bounds @var{hi}.
  1110. @end defun
  1111. @var{lo} and @var{hi} are expressions of rank 1 indicating the extent of the stencil on each dimension. Scalars are rank extended, that is, @var{lo}=0 is equivalent to @var{lo}=(0, 0, ..., 0) with length equal to the rank @code{r} of @var{view}. The stencil view has twice as many axes as @var{view}. The first @code{r} dimensions are the same as those of @var{view} except that they have their sizes reduced by @var{lo}+@var{hi}. The last @code{r} dimensions correspond to the stencil around each element of @var{view}; the center element is at @code{s(i0, i1, ..., lo(0), lo(1), ...)}.
  1112. This operation does not work on arbitrary array expressions yet. TODO FILL
  1113. @defun collapse
  1114. TODO
  1115. @end defun
  1116. @defun explode
  1117. TODO
  1118. @end defun
  1119. @defun format_array expr [print_shape? [first_axis_separator [second_axis_separator ...]]]
  1120. TODO
  1121. @end defun
  1122. @anchor{x-start}
  1123. @defun start foreign_object
  1124. Create a array expression from @var{foreign_object}.
  1125. @end defun
  1126. @var{foreign_object} can be of type @code{std::vector} or @code{std::array}, a built-in array (int[3], etc.) or an initializer list, or any object that @code{ra::} accepts as scalar (see @ref{x-is-scalar,@code{here}}). The resulting expresion has rank and size according to the original object. Compare this with @ref{x-scalar,@code{scalar}}, which will always produce an expression of rank 0.
  1127. Generally one can mix these types with @code{ra::} expressions without needing @code{ra::start}, but sometimes this isn't possible, for example for operators that must be class members.
  1128. @example
  1129. @verbatim
  1130. std::vector<int> x = {1, 2, 3};
  1131. ra::Big<int, 1> y = {10, 20, 30};
  1132. cout << (x+y) << endl; // same as ra::start(x)+y
  1133. // x += y; // error: no mach for operator+=
  1134. ra::start(x) += y; // ok
  1135. @end verbatim
  1136. @print{} 3
  1137. 11 22 33
  1138. @result{} x = @{ 11, 22, 33 @}
  1139. @end example
  1140. @anchor{x-ptr}
  1141. @defun ptr pointer
  1142. Create vector expression from raw @var{pointer}.
  1143. @end defun
  1144. The resulting expression has rank 1 and undefined size. To traverse it, it must be matched with other expressions whose size is defined. @code{ra::} cannot check accesses made through this object, so be careful. For instance:
  1145. @example
  1146. @verbatim
  1147. int p[] = {1, 2, 3};
  1148. ra::Big<int, 1> v3 {1, 2, 3};
  1149. ra::Big<int, 1> v4 {1, 2, 3, 4};
  1150. v3 += ra::ptr(p); // ok, shape (3): v3 = {2, 4, 6}
  1151. v4 += ra::ptr(p); // error, shape (4): bad access to p[3]
  1152. // cout << (ra::ptr(p)+ra::TensorIndex<0>{}) << endl; // ct error, expression has undefined shape
  1153. @end verbatim
  1154. @end example
  1155. @anchor{x-scalar}
  1156. @defun scalar expr
  1157. Create scalar expression from @var{expr}.
  1158. @end defun
  1159. The primary use of this function is to bring a scalar object into the @code{ra::} namespace. A somewhat artificial example:
  1160. @example
  1161. @verbatim
  1162. struct W { int x; }
  1163. ra::Big<W, 1> w { {1}, {2}, {3} };
  1164. // error: no matching function for call to start(W)
  1165. // for_each([](auto && a, auto && b) { cout << (a.x + b.x) << endl; }, w, W {7});
  1166. // bring W into ra:: with ra::scalar
  1167. for_each([](auto && a, auto && b) { cout << (a.x + b.x) << endl; }, w, ra::scalar(W {7}));
  1168. @end verbatim
  1169. @print{} 8
  1170. 9
  1171. 10
  1172. @end example
  1173. See also @ref{x-scalar-char-star,@code{this example}}.
  1174. Since @code{scalar} produces an object with rank 0, it's also useful when dealing with nested arrays, even for objects that are already in @code{ra::}. Consider:
  1175. @example
  1176. @verbatim
  1177. using Vec2 = ra::Small<double, 2>;
  1178. Vec2 x {-1, 1};
  1179. ra::Big<Vec2, 1> c { {1, 2}, {2, 3}, {3, 4} };
  1180. // c += x // error: x has shape (2) and c has shape (3)
  1181. c += ra::scalar(x); // ok: scalar(x) has shape () and matches c.
  1182. @end verbatim
  1183. @result{} c = @{ @{0, 3@}, @{1, 4@}, @{2, 5@} @}
  1184. @end example
  1185. The result is @{c(0)+x, c(1)+x, c(2)+x@}. Compare this with
  1186. @example
  1187. @verbatim
  1188. c(ra::iota(2)) += x; // c(ra::iota(2)) with shape (2) matches x with shape (2)
  1189. @end verbatim
  1190. @result{} c = @{ @{-1, 2@}, @{2, 5@} @}
  1191. @end example
  1192. where the result is @{c(0)+x(0), c(1)+x(1)@}.
  1193. @anchor{x-iter}
  1194. @defun iter <k> (view)
  1195. Create iterator over the @var{k}-cells of @var{view}. If @var{k} is negative, it is interpreted as the negative of the frame rank. In the current version of @code{ra::}, @var{view} must be a dynamic size @code{View}. (This is a defect.)
  1196. @end defun
  1197. @example
  1198. @verbatim
  1199. ra::Big<int, 2> c {{1, 3, 2}, {7, 1, 3}};
  1200. cout << "max of each row: " << map([](auto && a) { return amax(a); }, iter<1>(c)) << endl;
  1201. ra::Big<int, 1> m({3}, 0);
  1202. scalar(m) = max(scalar(m), iter<1>(c));
  1203. cout << "max of each column: " << m << endl;
  1204. m = 0;
  1205. for_each([&m](auto && a) { m = max(m, a); }, iter<1>(c));
  1206. cout << "max of each column again: " << m << endl;
  1207. @end verbatim
  1208. @print{} max of each row: 2
  1209. 3 7
  1210. max of each column: 3
  1211. 7 3 3
  1212. max of each column again: 3
  1213. 7 3 3
  1214. @end example
  1215. In the following example, @code{iter} emulates @code{scalar}. Note that the shape () of @code{iter<1>(m)} matches the shape (3) of @code{iter<1>(c)}. Thus, each of the 1-cells of @code{c} matches against the single 1-cell of @code{m}.
  1216. @example
  1217. @verbatim
  1218. m = 0;
  1219. iter<1>(m) = max(iter<1>(m), iter<1>(c));
  1220. cout << "max of each yet again: " << m << endl;
  1221. @end verbatim
  1222. @print{} max of each column again: 3
  1223. 7 3 3
  1224. @end example
  1225. The following example computes the trace of each of the items [(-1)-cells] of @code{c}. @c [ma104]
  1226. @example
  1227. @verbatim
  1228. ra::Big<int, 2> c = ra::_0 - ra::_1 - 2*ra::_2;
  1229. cout << "c: " << c << endl;
  1230. cout << "s: " << map([](auto && a) { return sum(diag(a)); }, iter<-1>(c)) << endl;
  1231. @end verbatim
  1232. @print{} c: 3 2 2
  1233. 0 -2
  1234. -1 -3
  1235. 1 -1
  1236. 0 -2
  1237. 2 0
  1238. 1 -1
  1239. s: 3
  1240. -3 -1 -1
  1241. @end example
  1242. @defun sum expr
  1243. Return the sum (+) of the elements of @var{expr}, or 0 if expr is empty. This sum is performed in unspecified order.
  1244. @end defun
  1245. @defun prod expr
  1246. Return the product (*) of the elements of @var{expr}, or 1 if expr is empty. This product is performed in unspecified order.
  1247. @end defun
  1248. @defun amax expr
  1249. Return the maximum of the elements of @var{expr}. If @var{expr} is empty, return @code{-std::numeric_limits<T>::infinity()} if the type supports it, otherwise @code{std::numeric_limits<T>::lowest()}, where @code{T} is the value type of the elements of @var{expr}.
  1250. @end defun
  1251. @defun amin expr
  1252. Return the minimum of the elements of @var{expr}. If @var{expr} is empty, If @var{expr} is empty, return @code{+std::numeric_limits<T>::infinity()} if the type supports it, otherwise @code{std::numeric_limits<T>::max()}, where @code{T} is the value type of the elements of @var{expr}.
  1253. @end defun
  1254. @defun early expr default
  1255. @var{expr} shall be an array expression that returns @code{std::tuple<bool, T>}. @var{expr} is traversed as by @code{for_each}; if the expression ever returns @code{true} in the first element of the tuple, traversal stops and the second element is returned. If this never happens, @var{default} is returned instead.
  1256. @end defun
  1257. The following definition of elementwise @code{lexicographical_compare} relies on @code{early}.
  1258. @example @c [ma108]
  1259. @verbatim
  1260. template <class A, class B>
  1261. inline bool lexicographical_compare(A && a, B && b)
  1262. {
  1263. return early(map([](auto && a, auto && b)
  1264. { return a==b ? std::make_tuple(false, true) : std::make_tuple(true, a<b); },
  1265. a, b),
  1266. false);
  1267. }
  1268. @end verbatim
  1269. @end example
  1270. @defun any expr
  1271. Return @code{true} if any element of @var{expr} is true, @code{false} otherwise. The traversal of the array expression will stop as soon as possible, but the traversal order is not specified.
  1272. @end defun
  1273. @defun every expr
  1274. Return @code{true} if every element of @var{expr} is true, @code{false} otherwise. The traversal of the array expression will stop as soon as possible, but the traversal order is not specified.
  1275. @end defun
  1276. @anchor{x-conj}
  1277. @defun conj expr
  1278. Compute the complex conjugate of @var{expr}.
  1279. @end defun
  1280. @anchor{x-xI}
  1281. @defun xI expr
  1282. Compute @code{(0+1j)} times @var{expr}.
  1283. @end defun
  1284. @anchor{x-rel-error}
  1285. @defun rel_error a b
  1286. @var{a} and @var{b} are arbitrary array expressions. Compute the error of @var{a} relative to @var{b} as
  1287. @code{(a==0. && b==0.) ? 0. : 2.*abs(a, b)/(abs(a)+abs(b))}
  1288. @end defun
  1289. @c ------------------------------------------------
  1290. @node Sources
  1291. @chapter Sources
  1292. @c ------------------------------------------------
  1293. @c ------------------------------------------------
  1294. @c Indices
  1295. @c ------------------------------------------------
  1296. @c @node Concept Index
  1297. @c @unnumbered Concept Index
  1298. @printindex cp
  1299. @c @node Function Index
  1300. @c @unnumbered Function Index
  1301. @c @printindex fn
  1302. @c \nocite{JLangReference}
  1303. @c \nocite{FalkoffIverson1968}
  1304. @c \nocite{Abrams1970}
  1305. @c \nocite{FalkoffIverson1973}
  1306. @c \nocite{FalkoffIverson1978}
  1307. @c \nocite{APLexamples1}
  1308. @c \nocite{ArraysCowan}
  1309. @c \nocite{KonaTheLanguage}
  1310. @c \nocite{blitz++2001}
  1311. @bye