@@ -572,6 +572,71 @@ \section{Array Operations}
572572functional languages, they have implicitly parallel semantics, and
573573some restrictions to preserve those semantics.
574574
575+ In addition to the array combinators, there are constructs for
576+ \textit {constructing } arrays. We already demonstrated literal arrays.
577+ Additionally, there is \texttt {iota }, which creates an array of a
578+ range of integers starting from zero:
579+
580+ \ begin{lstlisting}
581+ iota 10 == [0,1,2,3,4,5,6,7,8,9]
582+ \end {lstlisting }
583+
584+ The name \texttt {iota } comes from APL, one of the earliest array
585+ programming languages, and is supposed to be mnemonic for creating
586+ \textit {index spaces } of arrays. Put another way, \texttt {iota n }
587+ produces an array of valid indices into an array of size \texttt {n }.
588+
589+ The \texttt {replicate } construct is used to create an array of some
590+ size, with all elements having the same given value:
591+
592+ \ begin{lstlisting}
593+ replicate 3 42 == [42,42,42]
594+ \end {lstlisting }
595+
596+ We can use \texttt {concat } to combine several arrays:
597+
598+ \ begin{lstlisting}
599+ concat (iota 2) ([1,2,3]) (replicate 4 1) ==
600+ [0,1,1,2,3,1,1,1,1i32]
601+ \end {lstlisting }
602+
603+ Note that the parentheses around the literal array are necessary - if
604+ they were not present, this expression would be parsed as an attempt
605+ to index the expression \texttt {iota 2 } using \texttt {[1,2,3] } as the
606+ indices. This would of course result in a type error.
607+
608+ We can use \texttt {zip } to transform $ n$ arrays to a single array of
609+ $ n$ -tuples:
610+
611+ \ begin{lstlisting}
612+ zip [1,2,3] [true,false,true] [7.0,8.0,9.0] ==
613+ [(1,true,7.0),(2,false,8.0),(3,true,9.0)]
614+ \end {lstlisting }
615+
616+ That the input arrays may have different types. We can use
617+ \texttt {unzip } to perform the inverse transformation:
618+
619+ \ begin{lstlisting}
620+ unzip [(1,true,7.0),(2,false,8.0),(3,true,9.0)] ==
621+ ([1,2,3], [true,false,true], [7.0,8.0,9.0])
622+ \end {lstlisting }
623+
624+ Be aware that \texttt {zip } requires all of the input arrays to have
625+ the same size. Transforming between arrays of tuples and tuples of
626+ arrays is common in Futhark programs, as many array operations accept
627+ only one array as input. Due to a clever implementation technique,
628+ \texttt {zip } and \texttt {unzip } also have no runtime cost (no copying
629+ or allocation whatsoever), so you should not shy away from using them
630+ out of efficiency concerns.\footnote {This is enabled via storing all
631+ arrays in `` unzipped'' form. That is, at runtime, arrays of tuples
632+ do not exist, but have always been decomposed into multiple arrays.
633+ This is a common practice for high-performance computing, usually
634+ called `` structs of arrays'' versus `` arrays of structs'' , and
635+ serves to permit memory access patterns more friendly to vectorised
636+ operations.}
637+
638+ \subsection {Map }
639+
575640The simplest SOAC is probably \texttt {map }. It takes two arguments: a
576641function and an array. The function argument can be a function name,
577642or an anonymous function using \texttt {fn } syntax. The function is
@@ -613,6 +678,33 @@ \section{Array Operations}
613678map (+) [1,2,3] [4,5,6] == [5,7,9]
614679\end {lstlisting }
615680
681+ Be careful when writing \texttt {map } expressions where the function
682+ returns an array. Futhark requires regular arrays, so a map with
683+ \texttt {iota } is unlikely to go well:
684+
685+ \ begin{lstlisting}
686+ map (fn n => iota n) ns
687+ \end {lstlisting }
688+
689+ Unless the array \texttt {ns } consisted of identical values, the
690+ program would fail at runtime.
691+
692+ We can use \texttt {map } and \texttt {iota } to duplicate many other
693+ language constructs. For example, if we have two arrays
694+ \texttt {xs:[n]int } and \texttt {ys:[m]int }---that is, two integer
695+ arrays of sizes \texttt {n } and \texttt {m }---we can concatenate them
696+ using:
697+
698+ \lstinputlisting [firstline=2]{src/concat_with_map.fut}
699+
700+ However, it is not a good idea to write code like this, as it hinders
701+ the compiler from using high-level properties to do optimisation.
702+ Using \texttt {map }s over \texttt {iota }s with explicit indexing is
703+ usually only necessary when solving complicated irregular problems
704+ that cannot be represented directly.
705+
706+ \subsection {Scan and Reduce }
707+
616708While \texttt {map } is an array transformer, the \texttt {reduce } SOAC
617709is an array aggregator: it uses some function of type \texttt {t -> t
618710 -> t } to combine the elements of an array of type \texttt {[]t } to a
@@ -678,6 +770,37 @@ \section{Array Operations}
678770Several examples are discussed in
679771Chapter~\ref {chap:parallel-algorithms }.
680772
773+ \subsection {Filtering }
774+
775+ We have seen \texttt {map }, which permits us to change all the elements
776+ of an array. We have seen \texttt {reduce }, which lets us collapse all
777+ the elements of an array. But we still need something that lets us
778+ remove some, but not all, of the elements of an array. This SOAC is
779+ \texttt {filter }, which behaves much like a filter in any other
780+ functional language:
781+
782+ \ begin{lstlisting}
783+ filter (<3) [1,5,2,3,4] == [1,2]
784+ \end {lstlisting }
785+
786+ The use of \texttt {filter } is mostly straightforward, but there are
787+ some patterns that may appear subtle at first glance. For example,
788+ how do we find the \textit {indices } of all nonzero entries in an array
789+ of integers? Finding the values is simple enough:
790+
791+ \ begin{lstlisting}
792+ filter (fn x => x != 0) [0,5,2,0,1] ==
793+ [5,2,1]
794+ \end {lstlisting }
795+
796+ But what are the corresponding indices? We can solve this using a
797+ combination of \texttt {zip }, \texttt {filter }, and \texttt {unzip }:
798+
799+ \lstinputlisting [firstline=2]{src/indices_of_nonzero.fut}
800+
801+ Be aware that \texttt {filter } is a somewhat expensive SOAC,
802+ corresponding roughly to a \texttt {scan } plus a \texttt {map }.
803+
681804\section {Sequential Loops }
682805\label {sec:sequential-loops }
683806
0 commit comments