Changeset 266732e
- Timestamp:
- Mar 9, 2024, 5:40:09 PM (8 weeks ago)
- Branches:
- master
- Children:
- b64d0f4
- Parents:
- 03606ce
- Location:
- doc/theses/mike_brooks_MMath
- Files:
-
- 1 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/mike_brooks_MMath/array.tex
r03606ce r266732e 6 6 7 7 \begin{lstlisting} 8 9 10 11 12 13 14 15 16 17 18 8 array(float, 99) x; // x contains 99 floats 9 10 void f( array(float, 42) & a ) {} 11 f(x); // statically rejected: types are different 12 13 forall( T, [N] ) 14 void g( array(T, N) & a, int i ) { 15 T elem = a[i]; // dynamically checked: requires 0 <= i < N 16 } 17 g(x, 0); // T is float, N is 99, succeeds 18 g(x, 1000); // T is float, N is 99, dynamic check fails 19 19 \end{lstlisting} 20 20 … … 31 31 32 32 \begin{lstlisting} 33 34 35 36 37 33 forall( [N] ) 34 void declDemo() { 35 float a1[N]; // built-in type ("C array") 36 array(float, N) a2; // type from library 37 } 38 38 \end{lstlisting} 39 39 … … 54 54 My contributions are 55 55 \begin{itemize} 56 57 \item [TODO: general parking...] 58 59 56 \item a type system enhancement that lets polymorphic functions and generic types be parameterized by a numeric value: @forall( [N] )@ 57 \item TODO: general parking... 58 \item identify specific abilities brought by @array@ 59 \item Where there is a gap concerning this feature's readiness for prime-time, identification of specific workable improvements that are likely to close the gap 60 60 \end{itemize} 61 61 62 62 63 64 63 \section{Definitions and design considerations} 65 64 65 66 66 \subsection{Dependent typing} 67 67 68 68 69 70 71 69 \section{Features Added} 72 70 73 71 The present work adds a type @array@ to the \CFA standard library~\cite{Cforall}. 74 72 75 This array's length is statically managed and dynamically valued. This static management achieves argument safety and suggests a path to subscript safety as future work (TODO: cross reference). 73 This array's length is statically managed and dynamically valued. 74 This static management achieves argument safety and suggests a path to subscript safety as future work (TODO: cross reference). 76 75 77 76 This section presents motivating examples of the new array type's usage and follows up with definitions of the notations that appear. 78 77 79 The core of the new array management is tracking all array lengths in the type system. Dynamically valued lengths are represented using type variables. The stratification of type variables preceding object declarations makes a length referenceable everywhere that it is needed. For example, a declaration can share one length, @N@, among a pair of parameters and the return. 78 The core of the new array management is tracking all array lengths in the type system. 79 Dynamically valued lengths are represented using type variables. 80 The stratification of type variables preceding object declarations makes a length referenceable everywhere that it is needed. 81 For example, a declaration can share one length, @N@, among a pair of parameters and the return. 80 82 \lstinputlisting[language=CFA, firstline=10, lastline=17]{hello-array.cfa} 81 83 Here, the function @f@ does a pointwise comparison, checking if each pair of numbers is within half a percent of each other, returning the answers in a newly allocated @bool@ array. 82 84 83 The array type uses the parameterized length information in its @sizeof@ determination, illustrated in the example's call to @alloc@. That call requests an allocation of type @array(bool, N)@, which the type system deduces from the left-hand side of the initialization, into the return type of the @alloc@ call. Preexisting \CFA behaviour is leveraged here, both in the return-type-only polymorphism, and the @sized(T)@-aware standard-library @alloc@ routine. The new @array@ type plugs into this behaviour by implementing the @sized@/@sizeof@ assertion to have the intuitive meaning. As a result, this design avoids an opportunity for programmer error by making the size/length communication to a called routine implicit, compared with C's @calloc@ (or the low-level \CFA analog @aalloc@), which take an explicit length parameter not managed by the type system. 85 The array type uses the parameterized length information in its @sizeof@ determination, illustrated in the example's call to @alloc@. 86 That call requests an allocation of type @array(bool, N)@, which the type system deduces from the left-hand side of the initialization, into the return type of the @alloc@ call. 87 Preexisting \CFA behaviour is leveraged here, both in the return-type-only polymorphism, and the @sized(T)@-aware standard-library @alloc@ routine. 88 The new @array@ type plugs into this behaviour by implementing the @sized@/@sizeof@ assertion to have the intuitive meaning. 89 As a result, this design avoids an opportunity for programmer error by making the size/length communication to a called routine implicit, compared with C's @calloc@ (or the low-level \CFA analog @aalloc@), which take an explicit length parameter not managed by the type system. 84 90 85 91 \VRef[Figure]{f:fHarness} shows the harness to use the @f@ function illustrating how dynamic values are fed into the system. 86 Here, the @a@ array is loaded with decreasing values, and the @b@ array with amounts off by a constant, giving relative differences within tolerance at first and out of tolerance later. The program main is run with two different inputs of sequence length. 92 Here, the @a@ array is loaded with decreasing values, and the @b@ array with amounts off by a constant, giving relative differences within tolerance at first and out of tolerance later. 93 The program main is run with two different inputs of sequence length. 87 94 88 95 \begin{figure} … … 92 99 \end{figure} 93 100 94 The loops in the program main follow the more familiar pattern of using the ordinary variable @n@ to convey the length. The type system implicitly captures this value at the call site (@main@ calling @f@) and makes it available within the callee (@f@'s loop bound). 101 The loops in the program main follow the more familiar pattern of using the ordinary variable @n@ to convey the length. 102 The type system implicitly captures this value at the call site (@main@ calling @f@) and makes it available within the callee (@f@'s loop bound). 95 103 96 104 The two parts of the example show @n@ adapting a variable into a type-system managed length (at @main@'s declarations of @a@, @b@, and @result@), @N@ adapting in the opposite direction (at @f@'s loop bound), and a pass-thru use of a managed length (at @f@'s declaration of @ret@). 97 105 98 The @forall( ...[N] )@ participates in the user-relevant declaration of the name @N@, which becomes usable in parameter/return declarations and in the function @b@. The present form is chosen to parallel the existing @forall@ forms: 106 The @forall( ...[N] )@ participates in the user-relevant declaration of the name @N@, which becomes usable in parameter/return declarations and in the function @b@. 107 The present form is chosen to parallel the existing @forall@ forms: 99 108 \begin{cfa} 100 109 forall( @[N]@ ) ... // array kind … … 115 124 @array( thing, N0, N1, ... )@ -- a type wrapping $\prod_i N_i$ adjacent occurrences of @thing@ objects 116 125 \end{itemize} 117 Unsigned integers have a special status in this type system. Unlike how C++ allows @template< size_t N, char * msg, typename T >...@ declarations, \CFA does not accommodate values of any user-provided type. TODO: discuss connection with dependent types. 118 119 An example of a type error demonstrates argument safety. The running example has @f@ expecting two arrays of the same length. A compile-time error occurs when attempting to call @f@ with arrays whose lengths may differ. 120 \lstinputlisting[language=CFA, firstline=60, lastline=65]{hello-array.cfa} 126 Unsigned integers have a special status in this type system. 127 Unlike how C++ allows 128 \begin{lstlisting}[language=c++] 129 template< size_t N, char * msg, typename T >... // declarations 130 \end{lstlisting} 131 \CFA does not accommodate values of any user-provided type. 132 TODO: discuss connection with dependent types. 133 An example of a type error demonstrates argument safety. 134 The running example has @f@ expecting two arrays of the same length. 135 A compile-time error occurs when attempting to call @f@ with arrays whose lengths may differ. 136 \begin{cfa} 137 forall( [M], [N] ) 138 void bad( array(float, M) &a, array(float, N) &b ) { 139 f( a, a ); // ok 140 f( b, b ); // ok 141 f( a, b ); // error 142 } 143 \end{cfa} 144 %\lstinputlisting[language=CFA, firstline=60, lastline=65]{hello-array.cfa} 121 145 As is common practice in C, the programmer is free to cast, to assert knowledge not shared with the type system. 122 \lstinputlisting[language=CFA, firstline=70, lastline=75]{hello-array.cfa} 146 \begin{cfa} 147 forall( [M], [N] ) 148 void bad_fixed( array(float, M) & a, array(float, N) & b ) { 149 if ( M == N ) { 150 f( a, (array(float, M) &)b ); // cast b to matching type 151 } 152 } 153 \end{cfa} 154 %\lstinputlisting[language=CFA, firstline=70, lastline=75]{hello-array.cfa} 123 155 124 156 Argument safety and the associated implicit communication of array length work with \CFA's generic types too. … … 126 158 Doing so gives a refinement of C's ``flexible array member'' pattern, that allows nesting structures with array members anywhere within other structures. 127 159 \lstinputlisting[language=CFA, firstline=10, lastline=16]{hello-accordion.cfa} 128 This structure's layout has the starting offset of @cost_contribs@ varying in @Nclients@, and the offset of @total_cost@ varying in both generic parameters. For a function that operates on a @request@ structure, the type system handles this variation transparently. 160 This structure's layout has the starting offset of @cost_contribs@ varying in @Nclients@, and the offset of @total_cost@ varying in both generic parameters. 161 For a function that operates on a @request@ structure, the type system handles this variation transparently. 129 162 \lstinputlisting[language=CFA, firstline=40, lastline=47]{hello-accordion.cfa} 130 163 In the example, different runs of the program result in different offset values being used. 131 164 \lstinputlisting[language=CFA, firstline=60, lastline=76]{hello-accordion.cfa} 132 The output values show that @summarize@ and its caller agree on both the offsets (where the callee starts reading @cost_contribs@ and where the callee writes @total_cost@). Yet the call site still says just, ``pass the request.'' 165 The output values show that @summarize@ and its caller agree on both the offsets (where the callee starts reading @cost_contribs@ and where the callee writes @total_cost@). 166 Yet the call site still says just, ``pass the request.'' 133 167 134 168 … … 136 170 \label{toc:mdimpl} 137 171 138 139 172 TODO: introduce multidimensional array feature and approaches 140 173 141 The new \CFA standard library @array@ datatype supports multidimensional uses more richly than the C array. The new array's multidimensional interface and implementation, follows an array-of-arrays setup, meaning, like C's @float[n][m]@ type, one contiguous object, with coarsely-strided dimensions directly wrapping finely-strided dimensions. This setup is in contrast with the pattern of array of pointers to other allocations representing a sub-array. Beyond what C's type offers, the new array brings direct support for working with a noncontiguous array slice, allowing a program to work with dimension subscripts given in a non-physical order. C and C++ require a programmer with such a need to manage pointer/offset arithmetic manually. 174 The new \CFA standard library @array@ datatype supports multidimensional uses more richly than the C array. 175 The new array's multidimensional interface and implementation, follows an array-of-arrays setup, meaning, like C's @float[n][m]@ type, one contiguous object, with coarsely-strided dimensions directly wrapping finely-strided dimensions. 176 This setup is in contrast with the pattern of array of pointers to other allocations representing a sub-array. 177 Beyond what C's type offers, the new array brings direct support for working with a noncontiguous array slice, allowing a program to work with dimension subscripts given in a non-physical order. 178 C and C++ require a programmer with such a need to manage pointer/offset arithmetic manually. 142 179 143 180 Examples are shown using a $5 \times 7$ float array, @a@, loaded with increments of $0.1$ when stepping across the length-7 finely-strided dimension shown on columns, and with increments of $1.0$ when stepping across the length-5 coarsely-strided dimension shown on rows. 144 \lstinputlisting[language=CFA, firstline=120, lastline=126]{hello-md.cfa}181 %\lstinputlisting[language=CFA, firstline=120, lastline=126]{hello-md.cfa} 145 182 The memory layout of @a@ has strictly increasing numbers along its 35 contiguous positions. 146 183 147 A trivial form of slicing extracts a contiguous inner array, within an array-of-arrays. Like with the C array, a lesser-dimensional array reference can be bound to the result of subscripting a greater-dimensional array, by a prefix of its dimensions. This action first subscripts away the most coarsely strided dimensions, leaving a result that expects to be be subscripted by the more finely strided dimensions. 184 A trivial form of slicing extracts a contiguous inner array, within an array-of-arrays. 185 Like with the C array, a lesser-dimensional array reference can be bound to the result of subscripting a greater-dimensional array, by a prefix of its dimensions. 186 This action first subscripts away the most coarsely strided dimensions, leaving a result that expects to be be subscripted by the more finely strided dimensions. 148 187 \lstinputlisting[language=CFA, firstline=60, lastline=66]{hello-md.cfa} 149 188 \lstinputlisting[aboveskip=0pt, language=CFA, firstline=140, lastline=140]{hello-md.cfa} 150 189 151 This function declaration is asserting too much knowledge about its parameter @c@, for it to be usable for printing either a row slice or a column slice. Specifically, declaring the parameter @c@ with type @array@ means that @c@ is contiguous. However, the function does not use this fact. For the function to do its job, @c@ need only be of a container type that offers a subscript operator (of type @ptrdiff_t@ $\rightarrow$ @float@), with managed length @N@. The new-array library provides the trait @ix@, so-defined. With it, the original declaration can be generalized, while still implemented with the same body, to the latter declaration: 190 This function declaration is asserting too much knowledge about its parameter @c@, for it to be usable for printing either a row slice or a column slice. 191 Specifically, declaring the parameter @c@ with type @array@ means that @c@ is contiguous. 192 However, the function does not use this fact. 193 For the function to do its job, @c@ need only be of a container type that offers a subscript operator (of type @ptrdiff_t@ $\rightarrow$ @float@), with managed length @N@. 194 The new-array library provides the trait @ix@, so-defined. 195 With it, the original declaration can be generalized, while still implemented with the same body, to the latter declaration: 152 196 \lstinputlisting[language=CFA, firstline=40, lastline=44]{hello-md.cfa} 153 197 \lstinputlisting[aboveskip=0pt, language=CFA, firstline=145, lastline=145]{hello-md.cfa} 154 198 155 Nontrivial slicing, in this example, means passing a noncontiguous slice to @print1d@. The new-array library provides a ``subscript by all'' operation for this purpose. In a multi-dimensional subscript operation, any dimension given as @all@ is left ``not yet subscripted by a value,'' implementing the @ix@ trait, waiting for such a value. 199 Nontrivial slicing, in this example, means passing a noncontiguous slice to @print1d@. 200 The new-array library provides a ``subscript by all'' operation for this purpose. 201 In a multi-dimensional subscript operation, any dimension given as @all@ is left ``not yet subscripted by a value,'' implementing the @ix@ trait, waiting for such a value. 156 202 \lstinputlisting[language=CFA, firstline=150, lastline=151]{hello-md.cfa} 157 203 158 The example has shown that @a[2]@ and @a[[2, all]]@ both refer to the same, ``2.*'' slice. Indeed, the various @print1d@ calls under discussion access the entry with value 2.3 as @a[2][3]@, @a[[2,all]][3]@, and @a[[all,3]][2]@. This design preserves (and extends) C array semantics by defining @a[[i,j]]@ to be @a[i][j]@ for numeric subscripts, but also for ``subscripting by all''. That is: 204 The example has shown that @a[2]@ and @a[[2, all]]@ both refer to the same, ``2.*'' slice. 205 Indeed, the various @print1d@ calls under discussion access the entry with value 2.3 as @a[2][3]@, @a[[2,all]][3]@, and @a[[all,3]][2]@. 206 This design preserves (and extends) C array semantics by defining @a[[i,j]]@ to be @a[i][j]@ for numeric subscripts, but also for ``subscripting by all''. 207 That is: 159 208 160 209 \begin{tabular}{cccccl} 161 162 210 @a[[2,all]][3]@ & $=$ & @a[2][all][3]@ & $=$ & @a[2][3]@ & (here, @all@ is redundant) \\ 211 @a[[all,3]][2]@ & $=$ & @a[all][3][2]@ & $=$ & @a[2][3]@ & (here, @all@ is effective) 163 212 \end{tabular} 164 213 … … 168 217 169 218 \begin{tabular}{ll} 170 171 172 173 219 @a@ & 2-dimensional, want subscripts for coarse then fine \\ 220 @a[2]@ & 1-dimensional, want subscript for fine; lock coarse = 2 \\ 221 @a[2][all]@ & 1-dimensional, want subscript for fine \\ 222 @a[2][all][3]@ & 0-dimensional; lock fine = 3 174 223 \end{tabular} 175 224 … … 177 226 178 227 \begin{tabular}{ll} 179 180 181 182 228 @a@ & 2-dimensional, want subscripts for coarse then fine \\ 229 @a[all]@ & 2-dimensional, want subscripts for fine then coarse \\ 230 @a[all][3]@ & 1-dimensional, want subscript for coarse; lock fine = 3 \\ 231 @a[all][3][2]@ & 0-dimensional; lock coarse = 2 183 232 \end{tabular} 184 233 185 The semantics of @-[all]@ is to dequeue from the front of the ``want subscripts'' list and re-enqueue at its back. The semantics of @-[i]@ is to dequeue from the front of the ``want subscripts'' list and lock its value to be @i@. 186 187 Contiguous arrays, and slices of them, are all realized by the same underlying parameterized type. It includes stride information in its metatdata. The @-[all]@ operation is a conversion from a reference to one instantiation, to a reference to another instantiation. The running example's @all@-effective step, stated more concretely, is: 234 The semantics of @-[all]@ is to dequeue from the front of the ``want subscripts'' list and re-enqueue at its back. 235 The semantics of @-[i]@ is to dequeue from the front of the ``want subscripts'' list and lock its value to be @i@. 236 237 Contiguous arrays, and slices of them, are all realized by the same underlying parameterized type. 238 It includes stride information in its metatdata. 239 The @-[all]@ operation is a conversion from a reference to one instantiation, to a reference to another instantiation. 240 The running example's @all@-effective step, stated more concretely, is: 188 241 189 242 \begin{tabular}{ll} 190 191 243 @a@ & : 5 of ( 7 of float each spaced 1 float apart ) each spaced 7 floats apart \\ 244 @a[all]@ & : 7 of ( 5 of float each spaced 7 floats apart ) each spaced 1 float apart 192 245 \end{tabular} 193 246 194 247 \begin{figure} 195 \includegraphics{measuring-like-layout} 196 \caption{Visualization of subscripting by value and by \lstinline[language=CFA,basicstyle=\ttfamily]{all}, for \lstinline[language=CFA,basicstyle=\ttfamily]{a} of type \lstinline[language=CFA,basicstyle=\ttfamily]{array( float, 5, 7 )}. The horizontal dimension represents memory addresses while vertical layout is conceptual.} 197 \label{fig:subscr-all} 248 \includegraphics{measuring-like-layout} 249 \caption{Visualization of subscripting by value and by \lstinline[language=CFA,basicstyle=\ttfamily]{all}, for \lstinline[language=CFA,basicstyle=\ttfamily]{a} of type \lstinline[language=CFA,basicstyle=\ttfamily]{array( float, 5, 7 )}. 250 The horizontal dimension represents memory addresses while vertical layout is conceptual.} 251 \label{fig:subscr-all} 198 252 \end{figure} 199 253 200 \noindent While the latter description implies overlapping elements, Figure \ref{fig:subscr-all} shows that the overlaps only occur with unused spaces between elements. Its depictions of @a[all][...]@ show the navigation of a memory layout with nontrivial strides, that is, with ``spaced \_ floats apart'' values that are greater or smaller than the true count of valid indices times the size of a logically indexed element. Reading from the bottom up, the expression @a[all][3][2]@ shows a float, that is masquerading as a @float[7]@, for the purpose of being arranged among its peers; five such occurrences form @a[all][3]@. The tail of flatter boxes extending to the right of a proper element represents this stretching. At the next level of containment, the structure @a[all][3]@ masquerades as a @float[1]@, for the purpose of being arranged among its peers; seven such occurrences form @a[all]@. The vertical staircase arrangement represents this compression, and resulting overlapping. 201 202 The new-array library defines types and operations that ensure proper elements are accessed soundly in spite of the overlapping. The private @arpk@ structure (array with explicit packing) is generic over these two types (and more): the contained element, what it is masquerading as. This structure's public interface is the @array(...)@ construction macro and the two subscript operators. Construction by @array@ initializes the masquerading-as type information to be equal to the contained-element information. Subscripting by @all@ rearranges the order of masquerading-as types to achieve, in general, nontrivial striding. Subscripting by a number consumes the masquerading-as size of the contained element type, does normal array stepping according to that size, and returns there element found there, in unmasked form. 254 \noindent While the latter description implies overlapping elements, Figure \ref{fig:subscr-all} shows that the overlaps only occur with unused spaces between elements. 255 Its depictions of @a[all][...]@ show the navigation of a memory layout with nontrivial strides, that is, with ``spaced \_ floats apart'' values that are greater or smaller than the true count of valid indices times the size of a logically indexed element. 256 Reading from the bottom up, the expression @a[all][3][2]@ shows a float, that is masquerading as a @float[7]@, for the purpose of being arranged among its peers; five such occurrences form @a[all][3]@. 257 The tail of flatter boxes extending to the right of a proper element represents this stretching. 258 At the next level of containment, the structure @a[all][3]@ masquerades as a @float[1]@, for the purpose of being arranged among its peers; seven such occurrences form @a[all]@. 259 The vertical staircase arrangement represents this compression, and resulting overlapping. 260 261 The new-array library defines types and operations that ensure proper elements are accessed soundly in spite of the overlapping. 262 The private @arpk@ structure (array with explicit packing) is generic over these two types (and more): the contained element, what it is masquerading as. 263 This structure's public interface is the @array(...)@ construction macro and the two subscript operators. 264 Construction by @array@ initializes the masquerading-as type information to be equal to the contained-element information. 265 Subscripting by @all@ rearranges the order of masquerading-as types to achieve, in general, nontrivial striding. 266 Subscripting by a number consumes the masquerading-as size of the contained element type, does normal array stepping according to that size, and returns there element found there, in unmasked form. 203 267 204 268 The @arpk@ structure and its @-[i]@ operator are thus defined as: 205 269 \begin{lstlisting} 206 270 forall( ztype(N), // length of current dimension 207 dtype(S) | sized(S), // masquerading-as 208 dtype E_im, // immediate element, often another array 209 dtype E_base // base element, e.g. float, never array 210 ) { 211 struct arpk { 212 S strides[N]; // so that sizeof(this) is N of S 213 }; 214 215 // expose E_im, stride by S 216 E_im & ?[?]( arpk(N, S, E_im, E_base) & a, ptrdiff_t i ) { 217 return (E_im &) a.strides[i]; 218 } 219 } 220 \end{lstlisting} 221 222 An instantiation of the @arpk@ generic is given by the @array(E_base, N0, N1, ...)@ expansion, which is @arpk( N0, Rec, Rec, E_base )@, where @Rec@ is @array(E_base, N1, ...)@. In the base case, @array(E_base)@ is just @E_base@. Because this construction uses the same value for the generic parameters @S@ and @E_im@, the resulting layout has trivial strides. 223 224 Subscripting by @all@, to operate on nontrivial strides, is a dequeue-enqueue operation on the @E_im@ chain, which carries @S@ instantiations, intact, to new positions. Expressed as an operation on types, this rotation is: 271 dtype(S) | sized(S), // masquerading-as 272 dtype E_im, // immediate element, often another array 273 dtype E_base // base element, e.g. float, never array 274 ) { 275 struct arpk { 276 S strides[N]; // so that sizeof(this) is N of S 277 }; 278 279 // expose E_im, stride by S 280 E_im & ?[?]( arpk(N, S, E_im, E_base) & a, ptrdiff_t i ) { 281 return (E_im &) a.strides[i]; 282 } 283 } 284 \end{lstlisting} 285 286 An instantiation of the @arpk@ generic is given by the @array(E_base, N0, N1, ...)@ expansion, which is @arpk( N0, Rec, Rec, E_base )@, where @Rec@ is @array(E_base, N1, ...)@. 287 In the base case, @array(E_base)@ is just @E_base@. 288 Because this construction uses the same value for the generic parameters @S@ and @E_im@, the resulting layout has trivial strides. 289 290 Subscripting by @all@, to operate on nontrivial strides, is a dequeue-enqueue operation on the @E_im@ chain, which carries @S@ instantiations, intact, to new positions. 291 Expressed as an operation on types, this rotation is: 225 292 \begin{eqnarray*} 226 293 suball( arpk(N, S, E_i, E_b) ) & = & enq( N, S, E_i, E_b ) \\ … … 232 299 \section{Bound checks, added and removed} 233 300 234 \CFA array subscripting is protected with runtime bound checks. Having dependent typing causes the optimizer to remove more of these bound checks than it would without them. This section provides a demonstration of the effect. 235 236 The experiment compares the \CFA array system with the padded-room system [TODO:xref] most typically exemplified by Java arrays, but also reflected in the C++ pattern where restricted vector usage models a checked array. The essential feature of this padded-room system is the one-to-one correspondence between array instances and the symbolic bounds on which dynamic checks are based. The experiment compares with the C++ version to keep access to generated assembly code simple. 237 238 As a control case, a simple loop (with no reused dimension sizes) is seen to get the same optimization treatment in both the \CFA and C++ versions. When the programmer treats the array's bound correctly (making the subscript ``obviously fine''), no dynamic bound check is observed in the program's optimized assembly code. But when the bounds are adjusted, such that the subscript is possibly invalid, the bound check appears in the optimized assembly, ready to catch an occurrence the mistake. 301 \CFA array subscripting is protected with runtime bound checks. 302 Having dependent typing causes the optimizer to remove more of these bound checks than it would without them. 303 This section provides a demonstration of the effect. 304 305 The experiment compares the \CFA array system with the padded-room system [TODO:xref] most typically exemplified by Java arrays, but also reflected in the C++ pattern where restricted vector usage models a checked array. 306 The essential feature of this padded-room system is the one-to-one correspondence between array instances and the symbolic bounds on which dynamic checks are based. 307 The experiment compares with the C++ version to keep access to generated assembly code simple. 308 309 As a control case, a simple loop (with no reused dimension sizes) is seen to get the same optimization treatment in both the \CFA and C++ versions. 310 When the programmer treats the array's bound correctly (making the subscript ``obviously fine''), no dynamic bound check is observed in the program's optimized assembly code. 311 But when the bounds are adjusted, such that the subscript is possibly invalid, the bound check appears in the optimized assembly, ready to catch an occurrence the mistake. 239 312 240 313 TODO: paste source and assembly codes 241 314 242 Incorporating reuse among dimension sizes is seen to give \CFA an advantage at being optimized. The case is naive matrix multiplication over a row-major encoding. 315 Incorporating reuse among dimension sizes is seen to give \CFA an advantage at being optimized. 316 The case is naive matrix multiplication over a row-major encoding. 243 317 244 318 TODO: paste source codes … … 250 324 \section{Comparison with other arrays} 251 325 252 \CFA's array is the first lightweight application of dependently-typed bound tracking to an extension of C. Other extensions of C that apply dependently-typed bound tracking are heavyweight, in that the bound tracking is part of a linearly typed ownership system that further helps guarantee statically the validity of every pointer deference. These systems, therefore, ask the programmer to convince the type checker that every pointer dereference is valid. \CFA imposes the lighter-weight obligation, with the more limited guarantee, that initially-declared bounds are respected thereafter. 253 254 \CFA's array is also the first extension of C to use its tracked bounds to generate the pointer arithmetic implied by advanced allocation patterns. Other bound-tracked extensions of C either forbid certain C patterns entirely, or address the problem of \emph{verifying} that the user's provided pointer arithmetic is self-consistent. The \CFA array, applied to accordion structures [TOD: cross-reference] \emph{implies} the necessary pointer arithmetic, generated automatically, and not appearing at all in a user's program. 326 \CFA's array is the first lightweight application of dependently-typed bound tracking to an extension of C. 327 Other extensions of C that apply dependently-typed bound tracking are heavyweight, in that the bound tracking is part of a linearly typed ownership system that further helps guarantee statically the validity of every pointer deference. 328 These systems, therefore, ask the programmer to convince the type checker that every pointer dereference is valid. 329 \CFA imposes the lighter-weight obligation, with the more limited guarantee, that initially-declared bounds are respected thereafter. 330 331 \CFA's array is also the first extension of C to use its tracked bounds to generate the pointer arithmetic implied by advanced allocation patterns. 332 Other bound-tracked extensions of C either forbid certain C patterns entirely, or address the problem of \emph{verifying} that the user's provided pointer arithmetic is self-consistent. 333 The \CFA array, applied to accordion structures [TOD: cross-reference] \emph{implies} the necessary pointer arithmetic, generated automatically, and not appearing at all in a user's program. 255 334 256 335 \subsection{Safety in a padded room} 257 336 258 Java's array [TODO:cite] is a straightforward example of assuring safety against undefined behaviour, at a cost of expressiveness for more applied properties. Consider the array parameter declarations in: 337 Java's array [TODO:cite] is a straightforward example of assuring safety against undefined behaviour, at a cost of expressiveness for more applied properties. 338 Consider the array parameter declarations in: 259 339 260 340 \begin{tabular}{rl} 261 262 341 C & @void f( size_t n, size_t m, float a[n][m] );@ \\ 342 Java & @void f( float[][] a );@ 263 343 \end{tabular} 264 344 265 Java's safety against undefined behaviour assures the callee that, if @a@ is non-null, then @a.length@ is a valid access (say, evaluating to the number $\ell$) and if @i@ is in $[0, \ell)$ then @a[i]@ is a valid access. If a value of @i@ outside this range is used, a runtime error is guaranteed. In these respects, C offers no guarantees at all. Notably, the suggestion that @n@ is the intended size of the first dimension of @a@ is documentation only. Indeed, many might prefer the technically equivalent declarations @float a[][m]@ or @float (*a)[m]@ as emphasizing the ``no guarantees'' nature of an infrequently used language feature, over using the opportunity to explain a programmer intention. Moreover, even if @a[0][0]@ is valid for the purpose intended, C's basic infamous feature is the possibility of an @i@, such that @a[i][0]@ is not valid for the same purpose, and yet, its evaluation does not produce an error. 345 Java's safety against undefined behaviour assures the callee that, if @a@ is non-null, then @a.length@ is a valid access (say, evaluating to the number $\ell$) and if @i@ is in $[0, \ell)$ then @a[i]@ is a valid access. 346 If a value of @i@ outside this range is used, a runtime error is guaranteed. 347 In these respects, C offers no guarantees at all. 348 Notably, the suggestion that @n@ is the intended size of the first dimension of @a@ is documentation only. 349 Indeed, many might prefer the technically equivalent declarations @float a[][m]@ or @float (*a)[m]@ as emphasizing the ``no guarantees'' nature of an infrequently used language feature, over using the opportunity to explain a programmer intention. 350 Moreover, even if @a[0][0]@ is valid for the purpose intended, C's basic infamous feature is the possibility of an @i@, such that @a[i][0]@ is not valid for the same purpose, and yet, its evaluation does not produce an error. 266 351 267 352 Java's lack of expressiveness for more applied properties means these outcomes are possible: 268 353 \begin{itemize} 269 270 271 354 \item @a[0][17]@ and @a[2][17]@ are valid accesses, yet @a[1][17]@ is a runtime error, because @a[1]@ is a null pointer 355 \item the same observation, now because @a[1]@ refers to an array of length 5 356 \item execution times vary, because the @float@ values within @a@ are sometimes stored nearly contiguously, and other times, not at all 272 357 \end{itemize} 273 358 C's array has none of these limitations, nor do any of the ``array language'' comparators discussed in this section. 274 359 275 This Java level of safety and expressiveness is also exemplified in the C family, with the commonly given advice [TODO:cite example], for C++ programmers to use @std::vector@ in place of the C++ language's array, which is essentially the C array. The advice is that, while a vector is also more powerful (and quirky) than an array, its capabilities include options to preallocate with an upfront size, to use an available bound-checked accessor (@a.at(i)@ in place of @a[i]@), to avoid using @push_back@, and to use a vector of vectors. Used with these restrictions, out-of-bound accesses are stopped, and in-bound accesses never exercise the vector's ability to grow, which is to say, they never make the program slow to reallocate and copy, and they never invalidate the program's other references to the contained values. Allowing this scheme the same referential integrity assumption that \CFA enjoys [TODO:xref], this scheme matches Java's safety and expressiveness exactly. [TODO: decide about going deeper; some of the Java expressiveness concerns have mitigations, up to even more tradeoffs.] 360 This Java level of safety and expressiveness is also exemplified in the C family, with the commonly given advice [TODO:cite example], for C++ programmers to use @std::vector@ in place of the C++ language's array, which is essentially the C array. 361 The advice is that, while a vector is also more powerful (and quirky) than an array, its capabilities include options to preallocate with an upfront size, to use an available bound-checked accessor (@a.at(i)@ in place of @a[i]@), to avoid using @push_back@, and to use a vector of vectors. 362 Used with these restrictions, out-of-bound accesses are stopped, and in-bound accesses never exercise the vector's ability to grow, which is to say, they never make the program slow to reallocate and copy, and they never invalidate the program's other references to the contained values. 363 Allowing this scheme the same referential integrity assumption that \CFA enjoys [TODO:xref], this scheme matches Java's safety and expressiveness exactly. 364 [TODO: decide about going deeper; some of the Java expressiveness concerns have mitigations, up to even more tradeoffs.] 276 365 277 366 \subsection{Levels of dependently typed arrays} … … 279 368 The \CFA array and the field of ``array language'' comparators all leverage dependent types to improve on the expressiveness over C and Java, accommodating examples such as: 280 369 \begin{itemize} 281 282 283 370 \item a \emph{zip}-style operation that consumes two arrays of equal length 371 \item a \emph{map}-style operation whose produced length matches the consumed length 372 \item a formulation of matrix multiplication, where the two operands must agree on a middle dimension, and where the result dimensions match the operands' outer dimensions 284 373 \end{itemize} 285 Across this field, this expressiveness is not just an available place to document such assumption, but these requirements are strongly guaranteed by default, with varying levels of statically/dynamically checked and ability to opt out. Along the way, the \CFA array also closes the safety gap (with respect to bounds) that Java has over C. 286 287 Dependent type systems, considered for the purpose of bound-tracking, can be full-strength or restricted. In a full-strength dependent type system, a type can encode an arbitrarily complex predicate, with bound-tracking being an easy example. The tradeoff of this expressiveness is complexity in the checker, even typically, a potential for its nontermination. In a restricted dependent type system (purposed for bound tracking), the goal is to check helpful properties, while keeping the checker well-behaved; the other restricted checkers surveyed here, including \CFA's, always terminate. [TODO: clarify how even Idris type checking terminates] 288 289 Idris is a current, general-purpose dependently typed programming language. Length checking is a common benchmark for full dependent type systems. Here, the capability being considered is to track lengths that adjust during the execution of a program, such as when an \emph{add} operation produces a collection one element longer than the one on which it started. [TODO: finish explaining what Data.Vect is and then the essence of the comparison] 374 Across this field, this expressiveness is not just an available place to document such assumption, but these requirements are strongly guaranteed by default, with varying levels of statically/dynamically checked and ability to opt out. 375 Along the way, the \CFA array also closes the safety gap (with respect to bounds) that Java has over C. 376 377 Dependent type systems, considered for the purpose of bound-tracking, can be full-strength or restricted. 378 In a full-strength dependent type system, a type can encode an arbitrarily complex predicate, with bound-tracking being an easy example. 379 The tradeoff of this expressiveness is complexity in the checker, even typically, a potential for its nontermination. 380 In a restricted dependent type system (purposed for bound tracking), the goal is to check helpful properties, while keeping the checker well-behaved; the other restricted checkers surveyed here, including \CFA's, always terminate. 381 [TODO: clarify how even Idris type checking terminates] 382 383 Idris is a current, general-purpose dependently typed programming language. 384 Length checking is a common benchmark for full dependent type systems. 385 Here, the capability being considered is to track lengths that adjust during the execution of a program, such as when an \emph{add} operation produces a collection one element longer than the one on which it started. 386 [TODO: finish explaining what Data.Vect is and then the essence of the comparison] 290 387 291 388 POINTS: … … 293 390 it can also do these other cool checks, but watch how I can mess with its conservativeness and termination 294 391 295 Two current, state-of-the-art array languages, Dex\cite{arr:dex:long} and Futhark\cite{arr:futhark:tytheory}, offer offer novel contributions concerning similar, restricted dependent types for tracking array length. Unlike \CFA, both are garbage-collected functional languages. Because they are garbage-collected, referential integrity is built-in, meaning that the heavyweight analysis, that \CFA aims to avoid, is unnecessary. So, like \CFA, the checking in question is a lightweight bounds-only analysis. Like \CFA, their checks that are conservatively limited by forbidding arithmetic in the depended-upon expression. 296 297 298 299 The Futhark work discusses the working language's connection to a lambda calculus, with typing rules and a safety theorem proven in reference to an operational semantics. There is a particular emphasis on an existential type, enabling callee-determined return shapes. 392 Two current, state-of-the-art array languages, Dex\cite{arr:dex:long} and Futhark\cite{arr:futhark:tytheory}, offer offer novel contributions concerning similar, restricted dependent types for tracking array length. 393 Unlike \CFA, both are garbage-collected functional languages. 394 Because they are garbage-collected, referential integrity is built-in, meaning that the heavyweight analysis, that \CFA aims to avoid, is unnecessary. 395 So, like \CFA, the checking in question is a lightweight bounds-only analysis. 396 Like \CFA, their checks that are conservatively limited by forbidding arithmetic in the depended-upon expression. 397 398 399 400 The Futhark work discusses the working language's connection to a lambda calculus, with typing rules and a safety theorem proven in reference to an operational semantics. 401 There is a particular emphasis on an existential type, enabling callee-determined return shapes. 402 300 403 301 404 Dex uses a novel conception of size, embedding its quantitative information completely into an ordinary type. 302 405 303 Futhark and full-strength dependently typed languages treat array sizes are ordinary values. Futhark restricts these expressions syntactically to variables and constants, while a full-strength dependent system does not. 304 305 CFA's hybrid presentation, @forall( [N] )@, has @N@ belonging to the type system, yet has no instances. Belonging to the type system means it is inferred at a call site and communicated implicitly, like in Dex and unlike in Futhark. Having no instances means there is no type for a variable @i@ that constrains @i@ to be in the range for @N@, unlike Dex, [TODO: verify], but like Futhark. 406 Futhark and full-strength dependently typed languages treat array sizes are ordinary values. 407 Futhark restricts these expressions syntactically to variables and constants, while a full-strength dependent system does not. 408 409 CFA's hybrid presentation, @forall( [N] )@, has @N@ belonging to the type system, yet has no instances. 410 Belonging to the type system means it is inferred at a call site and communicated implicitly, like in Dex and unlike in Futhark. 411 Having no instances means there is no type for a variable @i@ that constrains @i@ to be in the range for @N@, unlike Dex, [TODO: verify], but like Futhark. 306 412 307 413 \subsection{Static safety in C extensions} … … 318 424 \subsection{With described enumerations} 319 425 320 A project in \CFA's current portfolio will improve enumerations. In the incumbent state, \CFA has C's enumerations, unmodified. I will not discuss the core of this project, which has a tall mission already, to improve type safety, maintain appropriate C compatibility and offer more flexibility about storage use. It also has a candidate stretch goal, to adapt \CFA's @forall@ generic system to communicate generalized enumerations: 321 \begin{lstlisting} 322 forall( T | is_enum(T) ) 323 void show_in_context( T val ) { 324 for( T i ) { 325 string decorator = ""; 326 if ( i == val-1 ) decorator = "< ready"; 327 if ( i == val ) decorator = "< go" ; 328 sout | i | decorator; 329 } 330 } 331 enum weekday { mon, tue, wed = 500, thu, fri }; 332 show_in_context( wed ); 426 A project in \CFA's current portfolio will improve enumerations. 427 In the incumbent state, \CFA has C's enumerations, unmodified. 428 I will not discuss the core of this project, which has a tall mission already, to improve type safety, maintain appropriate C compatibility and offer more flexibility about storage use. 429 It also has a candidate stretch goal, to adapt \CFA's @forall@ generic system to communicate generalized enumerations: 430 \begin{lstlisting} 431 forall( T | is_enum(T) ) 432 void show_in_context( T val ) { 433 for( T i ) { 434 string decorator = ""; 435 if ( i == val-1 ) decorator = "< ready"; 436 if ( i == val ) decorator = "< go" ; 437 sout | i | decorator; 438 } 439 } 440 enum weekday { mon, tue, wed = 500, thu, fri }; 441 show_in_context( wed ); 333 442 \end{lstlisting} 334 443 with output 335 444 \begin{lstlisting} 336 mon 337 tue < ready 338 wed < go 339 thu 340 fri 341 \end{lstlisting} 342 The details in this presentation aren't meant to be taken too precisely as suggestions for how it should look in \CFA. But the example shows these abilities: 445 mon 446 tue < ready 447 wed < go 448 thu 449 fri 450 \end{lstlisting} 451 The details in this presentation aren't meant to be taken too precisely as suggestions for how it should look in \CFA. 452 But the example shows these abilities: 343 453 \begin{itemize} 344 345 346 347 454 \item a built-in way (the @is_enum@ trait) for a generic routine to require enumeration-like information about its instantiating type 455 \item an implicit implementation of the trait whenever a user-written enum occurs (@weekday@'s declaration implies @is_enum@) 456 \item a total order over the enumeration constants, with predecessor/successor (@val-1@) available, and valid across gaps in values (@tue == 1 && wed == 500 && tue == wed - 1@) 457 \item a provision for looping (the @for@ form used) over the values of the type. 348 458 \end{itemize} 349 459 … … 352 462 [TODO: introduce Ada in the comparators] 353 463 354 In Ada and Dex, an array is conceived as a function whose domain must satisfy only certain structural assumptions, while in C, C++, Java, Futhark and \CFA today, the domain is a prefix of the natural numbers. The generality has obvious aesthetic benefits for programmers working on scheduling resources to weekdays, and for programmers who prefer to count from an initial number of their own choosing. 355 356 This change of perspective also lets us remove ubiquitous dynamic bound checks. [TODO: xref] discusses how automatically inserted bound checks can often be optimized away. But this approach is unsatisfying to a programmer who believes she has written code in which dynamic checks are unnecessary, but now seeks confirmation. To remove the ubiquitous dynamic checking is to say that an ordinary subscript operation is only valid when it can be statically verified to be in-bound (and so the ordinary subscript is not dynamically checked), and an explicit dynamic check is available when the static criterion is impractical to meet. 464 In Ada and Dex, an array is conceived as a function whose domain must satisfy only certain structural assumptions, while in C, C++, Java, Futhark and \CFA today, the domain is a prefix of the natural numbers. 465 The generality has obvious aesthetic benefits for programmers working on scheduling resources to weekdays, and for programmers who prefer to count from an initial number of their own choosing. 466 467 This change of perspective also lets us remove ubiquitous dynamic bound checks. 468 [TODO: xref] discusses how automatically inserted bound checks can often be optimized away. 469 But this approach is unsatisfying to a programmer who believes she has written code in which dynamic checks are unnecessary, but now seeks confirmation. 470 To remove the ubiquitous dynamic checking is to say that an ordinary subscript operation is only valid when it can be statically verified to be in-bound (and so the ordinary subscript is not dynamically checked), and an explicit dynamic check is available when the static criterion is impractical to meet. 357 471 358 472 [TODO, fix confusion: Idris has this arrangement of checks, but still the natural numbers as the domain.] 359 473 360 The structural assumptions required for the domain of an array in Dex are given by the trait (there, ``interface'') @Ix@, which says that the parameter @n@ is a type (which could take an argument like @weekday@) that provides two-way conversion with the integers and a report on the number of values. Dex's @Ix@ is analogous the @is_enum@ proposed for \CFA above. 474 The structural assumptions required for the domain of an array in Dex are given by the trait (there, ``interface'') @Ix@, which says that the parameter @n@ is a type (which could take an argument like @weekday@) that provides two-way conversion with the integers and a report on the number of values. 475 Dex's @Ix@ is analogous the @is_enum@ proposed for \CFA above. 361 476 \begin{lstlisting} 362 477 interface Ix n 363 get_size n : Unit -> Int 364 ordinal : n -> Int 365 unsafe_from_ordinal n : Int -> n 366 \end{lstlisting} 367 368 Dex uses this foundation of a trait (as an array type's domain) to achieve polymorphism over shapes. This flavour of polymorphism lets a function be generic over how many (and the order of) dimensions a caller uses when interacting with arrays communicated with this function. Dex's example is a routine that calculates pointwise differences between two samples. Done with shape polymorphism, one function body is equally applicable to a pair of single-dimensional audio clips (giving a single-dimensional result) and a pair of two-dimensional photographs (giving a two-dimensional result). In both cases, but with respectively dimensioned interpretations of ``size,'' this function requires the argument sizes to match, and it produces a result of the that size. 369 370 The polymorphism plays out with the pointwise-difference routine advertising a single-dimensional interface whose domain type is generic. In the audio instantiation, the duration-of-clip type argument is used for the domain. In the photograph instantiation, it's the tuple-type of $ \langle \mathrm{img\_wd}, \mathrm{img\_ht} \rangle $. This use of a tuple-as-index is made possible by the built-in rule for implementing @Ix@ on a pair, given @Ix@ implementations for its elements 478 get_size n : Unit -> Int 479 ordinal : n -> Int 480 unsafe_from_ordinal n : Int -> n 481 \end{lstlisting} 482 483 Dex uses this foundation of a trait (as an array type's domain) to achieve polymorphism over shapes. 484 This flavour of polymorphism lets a function be generic over how many (and the order of) dimensions a caller uses when interacting with arrays communicated with this function. 485 Dex's example is a routine that calculates pointwise differences between two samples. 486 Done with shape polymorphism, one function body is equally applicable to a pair of single-dimensional audio clips (giving a single-dimensional result) and a pair of two-dimensional photographs (giving a two-dimensional result). 487 In both cases, but with respectively dimensioned interpretations of ``size,'' this function requires the argument sizes to match, and it produces a result of the that size. 488 489 The polymorphism plays out with the pointwise-difference routine advertising a single-dimensional interface whose domain type is generic. 490 In the audio instantiation, the duration-of-clip type argument is used for the domain. 491 In the photograph instantiation, it's the tuple-type of $ \langle \mathrm{img\_wd}, \mathrm{img\_ht} \rangle $. 492 This use of a tuple-as-index is made possible by the built-in rule for implementing @Ix@ on a pair, given @Ix@ implementations for its elements 371 493 \begin{lstlisting} 372 494 instance {a b} [Ix a, Ix b] Ix (a & b) 373 374 375 376 377 495 get_size = \(). size a * size b 496 ordinal = \(i, j). (ordinal i * size b) + ordinal j 497 unsafe_from_ordinal = \o. 498 bs = size b 499 (unsafe_from_ordinal a (idiv o bs), unsafe_from_ordinal b (rem o bs)) 378 500 \end{lstlisting} 379 501 and by a user-provided adapter expression at the call site that shows how to indexing with a tuple is backed by indexing each dimension at a time 380 502 \begin{lstlisting} 381 382 383 503 img_trans :: (img_wd,img_ht)=>Real 504 img_trans.(i,j) = img.i.j 505 result = pairwise img_trans 384 506 \end{lstlisting} 385 507 [TODO: cite as simplification of example from https://openreview.net/pdf?id=rJxd7vsWPS section 4] -
doc/theses/mike_brooks_MMath/background.tex
r03606ce r266732e 21 21 This behaviour is typically one of 22 22 \begin{itemize} 23 24 25 23 \item my statement that the compiler accepts or rejects the program 24 \item the program's printed output, which I show 25 \item my implied assurance that its assertions do not fail when run 26 26 \end{itemize} 27 27 28 28 The compiler whose program semantics is shown is 29 \begin{ lstlisting}29 \begin{cfa} 30 30 $ gcc --version 31 31 gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0 32 \end{ lstlisting}32 \end{cfa} 33 33 running on Architecture @x86_64@, with the same environment targeted. 34 34 … … 39 39 \subsection{C reports many ill-typed expressions as warnings} 40 40 41 TODO: typeset 42 \lstinputlisting[language=C, firstline=13, lastline=56]{bkgd-c-tyerr.c} 41 These attempts to assign @y@ to @x@ and vice-versa are obviously ill-typed. 42 \lstinput{12-15}{bkgd-c-tyerr.c} 43 with warnings: 44 \begin{cfa} 45 warning: assignment to 'float *' from incompatible pointer type 'void (*)(void)' 46 warning: assignment to 'void (*)(void)' from incompatible pointer type 'float *' 47 \end{cfa} 48 Similarly, 49 \lstinput{17-19}{bkgd-c-tyerr.c} 50 with warning: 51 \begin{cfa} 52 warning: passing argument 1 of 'f' from incompatible pointer type 53 note: expected 'void (*)(void)' but argument is of type 'float *' 54 \end{cfa} 55 with a segmentation fault at runtime. 56 57 That @f@'s attempt to call @g@ fails is not due to 3.14 being a particularly unlucky choice of value to put in the variable @pi@. 58 Rather, it is because obtaining a program that includes this essential fragment, yet exhibits a behaviour other than "doomed to crash," is a matter for an obfuscated coding competition. 59 60 A "tractable syntactic method for proving the absence of certain program behaviours by classifying phrases according to the kinds of values they compute"*1 rejected the program. 61 The behaviour (whose absence is unprovable) is neither minor nor unlikely. 62 The rejection shows that the program is ill-typed. 63 64 Yet, the rejection presents as a GCC warning. 65 66 In the discussion following, ``ill-typed'' means giving a nonzero @gcc -Werror@ exit condition with a message that discusses typing. 67 68 *1 TAPL-pg1 definition of a type system 43 69 44 70 … … 47 73 \subsection{C has an array type (!)} 48 74 49 TODO: typeset 50 \lstinputlisting[language=C, firstline=35, lastline=116]{bkgd-carray-arrty.c} 75 When a programmer works with an array, C semantics provide access to a type that is different in every way from ``pointer to its first element.'' 76 Its qualities become apparent by inspecting the declaration 77 \lstinput{34-34}{bkgd-carray-arrty.c} 78 The inspection begins by using @sizeof@ to provide definite program semantics for the intuition of an expression's type. 79 Assuming a target platform keeps things concrete: 80 \lstinput{35-36}{bkgd-carray-arrty.c} 81 Consider the sizes of expressions derived from @a@, modified by adding ``pointer to'' and ``first element'' (and including unnecessary parentheses to avoid confusion about precedence). 82 \lstinput{37-40}{bkgd-carray-arrty.c} 83 That @a@ takes up 40 bytes is common reasoning for C programmers. 84 Set aside for a moment the claim that this first assertion is giving information about a type. 85 For now, note that an array and a pointer to its first element are, sometimes, different things. 86 87 The idea that there is such a thing as a pointer to an array may be surprising. 88 It is not the same thing as a pointer to the first element: 89 \lstinput{42-45}{bkgd-carray-arrty.c} 90 The first gets 91 \begin{cfa} 92 warning: assignment to `float (*)[10]' from incompatible pointer type `float *' 93 \end{cfa} 94 and the second gets the opposite. 95 96 We now refute a concern that @sizeof(a)@ is reporting on special knowledge from @a@ being an local variable, 97 say that it is informing about an allocation, rather than simply a type. 98 99 First, recognizing that @sizeof@ has two forms, one operating on an expression, the other on a type, we observe that the original answers are unaffected by using the type-parameterized form: 100 \lstinput{46-50}{bkgd-carray-arrty.c} 101 Finally, the same sizing is reported when there is no allocation at all, and we launch the analysis instead from the pointer-to-array type. 102 \lstinput{51-57}{bkgd-carray-arrty.c} 103 So, in spite of considerable programmer success enabled by an understanding that an array just a pointer to its first element (revisited TODO pointer decay), this understanding is simplistic. 104 105 A shortened form for declaring local variables exists, provided that length information is given in the initializer: 106 \lstinput{59-63}{bkgd-carray-arrty.c} 107 In these declarations, the resulting types are both arrays, but their lengths are inferred. 108 109 \begin{tabular}{lllllll} 110 @float x;@ & $\rightarrow$ & (base element) & @float@ & @float x;@ & @[ float ]@ & @[ float ]@ \\ 111 @float * x;@ & $\rightarrow$ & pointer & @float *@ & @float * x;@ & @[ * float ]@ & @[ * float ]@ \\ 112 @float x[10];@ & $\rightarrow$ & array & @float[10]@ & @float x[10];@ & @[ [10] float ]@ & @[ array(float, 10) ]@ \\ 113 @float *x[10];@ & $\rightarrow$ & array of pointers & @(float*)[10]@ & @float *x[10];@ & @[ [10] * float ]@ & @[ array(*float, 10) ]@ \\ 114 @float (*x)[10];@ & $\rightarrow$ & pointer to array & @float(*)[10]@ & @float (*x)[10];@ & @[ * [10] float ]@ & @[ * array(float, 10) ]@ \\ 115 @float *(*x5)[10];@ & $\rightarrow$ & pointer to array & @(float*)(*)[10]@ & @float *(*x)[10];@ & @[ * [10] * float ]@ & @[ * array(*float, 10) ]@ 116 \end{tabular} 117 \begin{cfa} 118 x5 = (float*(*)[10]) x4; 119 // x5 = (float(*)[10]) x4; // wrong target type; meta test suggesting above cast uses correct type 120 121 // [here] 122 // const 123 124 // [later] 125 // static 126 // star as dimension 127 // under pointer decay: int p1[const 3] being int const *p1 128 129 const float * y1; 130 float const * y2; 131 float * const y3; 132 133 y1 = 0; 134 y2 = 0; 135 // y3 = 0; // bad 136 137 // *y1 = 3.14; // bad 138 // *y2 = 3.14; // bad 139 *y3 = 3.14; 140 141 const float z1 = 1.414; 142 float const z2 = 1.414; 143 144 // z1 = 3.14; // bad 145 // z2 = 3.14; // bad 146 147 148 } 149 150 #define T float 151 void stx2() { const T x[10]; 152 // x[5] = 3.14; // bad 153 } 154 void stx3() { T const x[10]; 155 // x[5] = 3.14; // bad 156 } 157 \end{cfa} 51 158 52 159 My contribution is enabled by recognizing 53 160 \begin{itemize} 54 55 56 57 161 \item There is value in using a type that knows how big the whole thing is. 162 \item The type pointer to (first) element does not. 163 \item C \emph{has} a type that knows the whole picture: array, e.g. @T[10]@. 164 \item This type has all the usual derived forms, which also know the whole picture. A usefully noteworthy example is pointer to array, e.g. @T(*)[10]@. 58 165 \end{itemize} 59 166 … … 75 182 a declaration is always the type followed by the declared identifier name; 76 183 for the example of letting @x@ be a \emph{pointer to array}, the declaration is spelled: 77 \begin{ lstlisting}184 \begin{cfa} 78 185 [ * [10] T ] x; 79 \end{ lstlisting}186 \end{cfa} 80 187 The \CFA-Full column gives the spelling of a different type, introduced in TODO, which has all of my contributed improvements for safety and ergonomics. 81 188 … … 83 190 \textbf{Unfortunate Syntactic Reference} 84 191 85 \noindent 192 \begin{figure} 193 \centering 194 \setlength{\tabcolsep}{3pt} 86 195 \begin{tabular}{llllll} 87 88 89 90 91 92 93 94 95 96 97 98 99 \\\hline100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 \\\hline118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 \\\hline148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 196 & Description & Type & Declaration & \CFA-C & \CFA-Full \\ \hline 197 $\triangleright$ & val. 198 & @T@ 199 & @T x;@ 200 & @[ T ]@ 201 & 202 \\ \hline 203 & \pbox{20cm}{ \vspace{2pt} val.\\ \footnotesize{no writing the val.\ in \lstinline{x}} }\vspace{2pt} 204 & \pbox{20cm}{ \vspace{2pt} \lstinline{const T} \\ \lstinline{T const} } 205 & \pbox{20cm}{ \vspace{2pt} \lstinline{const T x;} \\ \lstinline{T const x;} } 206 & @[ const T ]@ 207 & 208 \\ \hline \hline 209 $\triangleright$ & ptr.\ to val. 210 & @T *@ 211 & @T * x;@ 212 & @[ * T ]@ 213 & 214 \\ \hline 215 & \pbox{20cm}{ \vspace{2pt} ptr.\ to val.\\ \footnotesize{no writing the ptr.\ in \lstinline{x}} }\vspace{2pt} 216 & @T * const@ 217 & @T * const x;@ 218 & @[ const * T ]@ 219 & 220 \\ \hline 221 & \pbox{20cm}{ \vspace{2pt} ptr.\ to val.\\ \footnotesize{no writing the val.\ in \lstinline{*x}} }\vspace{2pt} 222 & \pbox{20cm}{ \vspace{2pt} \lstinline{const T *} \\ \lstinline{T const *} } 223 & \pbox{20cm}{ \vspace{2pt} \lstinline{const T * x;} \\ \lstinline{T const * x;} } 224 & @[ * const T ]@ 225 & 226 \\ \hline \hline 227 $\triangleright$ & ar.\ of val. 228 & @T[10]@ 229 & @T x[10];@ 230 & @[ [10] T ]@ 231 & @[ array(T, 10) ]@ 232 \\ \hline 233 & \pbox{20cm}{ \vspace{2pt} ar.\ of val.\\ \footnotesize{no writing the val.\ in \lstinline{x[5]}} }\vspace{2pt} 234 & \pbox{20cm}{ \vspace{2pt} \lstinline{const T[10]} \\ \lstinline{T const[10]} } 235 & \pbox{20cm}{ \vspace{2pt} \lstinline{const T x[10];} \\ \lstinline{T const x[10];} } 236 & @[ [10] const T ]@ 237 & @[ const array(T, 10) ]@ 238 \\ \hline 239 & ar.\ of ptr.\ to val. 240 & @T*[10]@ 241 & @T *x[10];@ 242 & @[ [10] * T ]@ 243 & @[ array(* T, 10) ]@ 244 \\ \hline 245 & \pbox{20cm}{ \vspace{2pt} ar.\ of ptr.\ to val.\\ \footnotesize{no writing the ptr.\ in \lstinline{x[5]}} }\vspace{2pt} 246 & @T * const [10]@ 247 & @T * const x[10];@ 248 & @[ [10] const * T ]@ 249 & @[ array(const * T, 10) ]@ 250 \\ \hline 251 & \pbox{20cm}{ \vspace{2pt} ar.\ of ptr.\ to val.\\ \footnotesize{no writing the val.\ in \lstinline{*(x[5])}} }\vspace{2pt} 252 & \pbox{20cm}{ \vspace{2pt} \lstinline{const T * [10]} \\ \lstinline{T const * [10]} } 253 & \pbox{20cm}{ \vspace{2pt} \lstinline{const T * x[10];} \\ \lstinline{T const * x[10];} } 254 & @[ [10] * const T ]@ 255 & @[ array(* const T, 10) ]@ 256 \\ \hline \hline 257 $\triangleright$ & ptr.\ to ar.\ of val. 258 & @T(*)[10]@ 259 & @T (*x)[10];@ 260 & @[ * [10] T ]@ 261 & @[ * array(T, 10) ]@ 262 \\ \hline 263 & \pbox{20cm}{ \vspace{2pt} ptr.\ to ar.\ of val.\\ \footnotesize{no writing the ptr.\ in \lstinline{x}} }\vspace{2pt} 264 & @T(* const)[10]@ 265 & @T (* const x)[10];@ 266 & @[ const * [10] T ]@ 267 & @[ const * array(T, 10) ]@ 268 \\ \hline 269 & \pbox{20cm}{ \vspace{2pt} ptr.\ to ar.\ of val.\\ \footnotesize{no writing the val.\ in \lstinline{(*x)[5]}} }\vspace{2pt} 270 & \pbox{20cm}{ \vspace{2pt} \lstinline{const T(*)[10]} \\ \lstinline{T const (*) [10]} } 271 & \pbox{20cm}{ \vspace{2pt} \lstinline{const T (*x)[10];} \\ \lstinline{T const (*x)[10];} } 272 & @[ * [10] const T ]@ 273 & @[ * const array(T, 10) ]@ 274 \\ \hline 275 & ptr.\ to ar.\ of ptr.\ to val. 276 & @T*(*)[10]@ 277 & @T *(*x)[10];@ 278 & @[ * [10] * T ]@ 279 & @[ * array(* T, 10) ]@ 280 \\ \hline 172 281 \end{tabular} 282 \caption{Figure} 283 \end{figure} 173 284 174 285 175 286 \subsection{Arrays decay and pointers diffract} 176 287 177 TODO: typeset 178 \lstinputlisting[language=C, firstline=4, lastline=26]{bkgd-carray-decay.c} 179 288 The last section established the difference between these four types: 289 \lstinput{3-6}{bkgd-carray-decay.c} 290 But the expression used for obtaining the pointer to the first element is pedantic. 291 The root of all C programmer experience with arrays is the shortcut 292 \lstinput{8-8}{bkgd-carray-decay.c} 293 which reproduces @pa0@, in type and value: 294 \lstinput{9-9}{bkgd-carray-decay.c} 295 The validity of this initialization is unsettling, in the context of the facts established in the last section. 296 Notably, it initializes name @pa0x@ from expression @a@, when they are not of the same type: 297 \lstinput{10-10}{bkgd-carray-decay.c} 180 298 181 299 So, C provides an implicit conversion from @float[10]@ to @float*@, as described in ARM-6.3.2.1.3: 182 183 300 \begin{quote} 184 185 186 187 188 301 Except when it is the operand of the @sizeof@ operator, or the unary @&@ operator, or is a 302 string literal used to initialize an array 303 an expression that has type ``array of type'' is 304 converted to an expression with type ``pointer to type'' that points to the initial element of 305 the array object 189 306 \end{quote} 190 307 … … 206 323 leads to an expectation that the runtime handling is uniform across legal and illegal accesses. 207 324 Moreover, consider the common pattern of subscripting on a malloc result: 208 \begin{ lstlisting}209 210 211 \end{ lstlisting}325 \begin{cfa} 326 float * fs = malloc( 10 * sizeof(float) ); 327 fs[5] = 3.14; 328 \end{cfa} 212 329 The @malloc@ behaviour is specified as returning a pointer to ``space for an object whose size is'' as requested (ARM-7.22.3.4.2). 213 330 But program says \emph{nothing} more about this pointer value, that might cause its referent to \emph{be} an array, before doing the subscript. … … 229 346 the parameter's type becomes a type that I summarize as being the array-decayed type. 230 347 The respective handlings of the following two parameter spellings shows that the array-spelled one is really, like the other, a pointer. 231 \lstinput listing[language=C, firstline=40, lastline=44]{bkgd-carray-decay.c}348 \lstinput{12-16}{bkgd-carray-decay.c} 232 349 As the @sizeof(x)@ meaning changed, compared with when run on a similarly-spelled local variariable declaration, 233 350 GCC also gives this code the warning: ```sizeof' on array function parameter `x' will return size of `float *'.'' 234 351 235 352 The caller of such a function is left with the reality that a pointer parameter is a pointer, no matter how it's spelled: 236 \lstinput listing[language=C, firstline=60, lastline=63]{bkgd-carray-decay.c}353 \lstinput{18-21}{bkgd-carray-decay.c} 237 354 This fragment gives no warnings. 238 355 … … 240 357 Note the opposite meaning of this spelling now, compared with its use in local variable declarations. 241 358 This point of confusion is illustrated in: 242 \lstinput listing[language=C, firstline=80, lastline=87]{bkgd-carray-decay.c}359 \lstinput{23-30}{bkgd-carray-decay.c} 243 360 The basic two meanings, with a syntactic difference helping to distinguish, 244 361 are illustrated in the declarations of @ca@ vs.\ @cp@, … … 252 369 In sumary, when a funciton is written with an array-typed parameter, 253 370 \begin{itemize} 254 255 256 371 \item an appearance of passing an array by value is always an incorrect understanding 372 \item a dimension value, if any is present, is ignorred 373 \item pointer decay is forced at the call site and the callee sees the parameter having the decayed type 257 374 \end{itemize} 258 375 259 376 Pointer decay does not affect pointer-to-array types, because these are already pointers, not arrays. 260 377 As a result, a function with a pointer-to-array parameter sees the parameter exactly as the caller does: 261 \lstinputlisting[language=C, firstline=100, lastline=110]{bkgd-carray-decay.c} 262 378 \lstinput{32-42}{bkgd-carray-decay.c} 263 379 264 380 \noindent … … 268 384 (Parameter declaration; ``no writing'' refers to the callee's ability) 269 385 270 \noindent 386 \begin{figure} 387 \centering 271 388 \begin{tabular}{llllll} 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 \\\hline288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 389 & Description & Type & Param. Decl & \CFA-C \\ \hline 390 $\triangleright$ & ptr.\ to val. 391 & @T *@ 392 & \pbox{20cm}{ \vspace{2pt} \lstinline{T * x,} \\ \lstinline{T x[10],} \\ \lstinline{T x[],} }\vspace{2pt} 393 & \pbox{20cm}{ \vspace{2pt} \lstinline{[ * T ]} \\ \lstinline{[ [10] T ]} \\ \lstinline{[ [] T ]} } 394 \\ \hline 395 & \pbox{20cm}{ \vspace{2pt} ptr.\ to val.\\ \footnotesize{no writing the ptr.\ in \lstinline{x}} }\vspace{2pt} 396 & @T * const@ 397 & \pbox{20cm}{ \vspace{2pt} \lstinline{T * const x,} \\ \lstinline{T x[const 10],} \\ \lstinline{T x[const],} }\vspace{2pt} 398 & \pbox{20cm}{ \vspace{2pt} \lstinline{[ const * T ]} \\ \lstinline{[ [const 10] T ]} \\ \lstinline{[ [const] T ]} } 399 \\ \hline 400 & \pbox{20cm}{ \vspace{2pt} ptr.\ to val.\\ \footnotesize{no writing the val.\ in \lstinline{*x}} }\vspace{2pt} 401 & \pbox{20cm}{ \vspace{2pt} \lstinline{const T *} \\ \lstinline{T const *} } 402 & \pbox{20cm}{ \vspace{2pt} \lstinline{const T * x,} \\ \lstinline{T const * x,} \\ \lstinline{const T x[10],} \\ \lstinline{T const x[10],} \\ \lstinline{const T x[],} \\ \lstinline{T const x[],} }\vspace{2pt} 403 & \pbox{20cm}{ \vspace{2pt} \lstinline{[* const T]} \\ \lstinline{[ [10] const T ]} \\ \lstinline{[ [] const T ]} } 404 \\ \hline \hline 405 $\triangleright$ & ptr.\ to ar.\ of val. 406 & @T(*)[10]@ 407 & \pbox{20cm}{ \vspace{2pt} \lstinline{T (*x)[10],} \\ \lstinline{T x[3][10],} \\ \lstinline{T x[][10],} }\vspace{2pt} 408 & \pbox{20cm}{ \vspace{2pt} \lstinline{[* [10] T]} \\ \lstinline{[ [3] [10] T ]} \\ \lstinline{[ [] [10] T ]} } 409 \\ \hline 410 & ptr.\ to ptr.\ to val. 411 & @T **@ 412 & \pbox{20cm}{ \vspace{2pt} \lstinline{T ** x,} \\ \lstinline{T *x[10],} \\ \lstinline{T *x[],} }\vspace{2pt} 413 & \pbox{20cm}{ \vspace{2pt} \lstinline{[ * * T ]} \\ \lstinline{[ [10] * T ]} \\ \lstinline{[ [] * T ]} } 414 \\ \hline 415 & \pbox{20cm}{ \vspace{2pt} ptr.\ to ptr.\ to val.\\ \footnotesize{no writing the val.\ in \lstinline{**argv}} }\vspace{2pt} 416 & @const char **@ 417 & \pbox{20cm}{ \vspace{2pt} \lstinline{const char *argv[],} \\ \footnotesize{(others elided)} }\vspace{2pt} 418 & \pbox{20cm}{ \vspace{2pt} \lstinline{[ [] * const char ]} \\ \footnotesize{(others elided)} } 419 \\ \hline 303 420 \end{tabular} 304 421 \caption{Figure} 422 \end{figure} 305 423 306 424 … … 309 427 When the desired number of elements is unknown at compile time, 310 428 a variable-length array is a solution: 311 \begin{lstlisting} 312 int main( int argc, const char *argv[] ) { 313 314 assert( argc == 2 ); 315 size_t n = atol( argv[1] ); 316 assert( 0 < n && n < 1000 ); 317 318 float a[n]; 319 float b[10]; 320 321 // ... discussion continues here 322 } 323 \end{lstlisting} 324 This arrangement allocates @n@ elements on the @main@ stack frame for @a@, 325 just as it puts 10 elements on the @main@ stack frame for @b@. 429 \begin{cfa} 430 int main( int argc, const char *argv[] ) { 431 assert( argc == 2 ); 432 size_t n = atol( argv[1] ); 433 assert( 0 < n && n < 1000 ); 434 435 float a[n]; 436 float b[10]; 437 438 // ... discussion continues here 439 } 440 \end{cfa} 441 This arrangement allocates @n@ elements on the @main@ stack frame for @a@, just as it puts 10 elements on the @main@ stack frame for @b@. 326 442 The variable-sized allocation of @a@ is provided by @alloca@. 327 443 328 In a situation where the array sizes are not known to be small enough 329 for stack allocation to be sensible, 330 corresponding heap allocations are achievable as: 331 \begin{lstlisting} 332 float *ax1 = malloc( sizeof( float[n] ) ); 333 float *ax2 = malloc( n * sizeof( float ) ); 334 float *bx1 = malloc( sizeof( float[1000000] ) ); 335 float *bx2 = malloc( 1000000 * sizeof( float ) ); 336 \end{lstlisting} 444 In a situation where the array sizes are not known to be small enough for stack allocation to be sensible, corresponding heap allocations are achievable as: 445 \begin{cfa} 446 float *ax1 = malloc( sizeof( float[n] ) ); 447 float *ax2 = malloc( n * sizeof( float ) ); 448 float *bx1 = malloc( sizeof( float[1000000] ) ); 449 float *bx2 = malloc( 1000000 * sizeof( float ) ); 450 \end{cfa} 337 451 338 452 … … 353 467 Just as an array's element type can be @float@, so can it be @float[10]@. 354 468 355 While any of @float*@, @float[10]@ and @float(*)[10]@ are easy to tell apart from @float@, 356 telling them apart from each other may need occasional reference back to TODO intro section. 469 While any of @float*@, @float[10]@ and @float(*)[10]@ are easy to tell apart from @float@, telling them apart from each other may need occasional reference back to TODO intro section. 357 470 The sentence derived by wrapping each type in @-[3]@ follows. 358 471 … … 360 473 telling them apart from each other is what it takes to know what ``array of arrays'' really means. 361 474 362 363 475 Pointer decay affects the outermost array only 364 476 365 366 477 TODO: unfortunate syntactic reference with these cases: 367 478 368 479 \begin{itemize} 369 370 480 \item ar. of ar. of val (be sure about ordering of dimensions when the declaration is dropped) 481 \item ptr. to ar. of ar. of val 371 482 \end{itemize} 372 483 373 484 374 375 376 377 485 \subsection{Arrays are (but) almost values} 378 486 … … 391 499 392 500 \subsection{Returning an array is (but) almost possible} 393 394 395 501 396 502 … … 414 520 which type information associated with a polymorphic return type 415 521 replaces @malloc@'s use of programmer-supplied size information. 416 \begin{ lstlisting}417 418 419 420 421 422 423 424 425 426 427 428 \end{ lstlisting}522 \begin{cfa} 523 // C, library 524 void * malloc( size_t ); 525 // C, user 526 struct tm * el1 = malloc( sizeof(struct tm) ); 527 struct tm * ar1 = malloc( 10 * sizeof(struct tm) ); 528 529 // CFA, library 530 forall( T * ) T * alloc(); 531 // CFA, user 532 tm * el2 = alloc(); 533 tm (*ar2)[10] = alloc(); 534 \end{cfa} 429 535 The alloc polymorphic return compiles into a hidden parameter, which receives a compiler-generated argument. 430 536 This compiler's argument generation uses type information from the left-hand side of the initialization to obtain the intended type. … … 436 542 In the last example, the choice of ``pointer to array'' @ar2@ breaks a parallel with @ar1@. 437 543 They are not subscripted in the same way. 438 \begin{ lstlisting}439 440 441 \end{ lstlisting}544 \begin{cfa} 545 ar1[5]; 546 (*ar2)[5]; 547 \end{cfa} 442 548 Using ``reference to array'' works at resolving this issue. TODO: discuss connection with Doug-Lea \CC proposal. 443 \begin{ lstlisting}444 445 446 \end{ lstlisting}549 \begin{cfa} 550 tm (&ar3)[10] = *alloc(); 551 ar3[5]; 552 \end{cfa} 447 553 The implicit size communication to @alloc@ still works in the same ways as for @ar2@. 448 554 … … 453 559 where the type requested is an array, making the result, much more obviously, an array object. 454 560 455 The ``reference to array'' type has its sore spots too. TODO see also @dimexpr-match-c/REFPARAM_CALL (under TRY_BUG_1)@ 456 457 561 The ``reference to array'' type has its sore spots too. 562 TODO see also @dimexpr-match-c/REFPARAM_CALL@ (under @TRY_BUG_1@) 458 563 459 564 TODO: I fixed a bug associated with using an array as a T. I think. Did I really? What was the bug? -
doc/theses/mike_brooks_MMath/programs/bkgd-c-tyerr.c
r03606ce r266732e 10 10 11 11 int main() { 12 float * x; $\C{// x points at a floating-point number}$ 13 void (*y)(void); $\C{// y points at a function}$ 14 @x = y;@ $\C{// wrong}$ 15 @y = x;@ $\C{// wrong}$ 12 16 13 /* 14 These attempts to assign @y@ to @x@ and vice-versa are obviously ill-typed. 15 */ 16 float * x; // x points at a floating-point number 17 void (*y)(void); // y points at a function 18 ERR( 19 x = y; // wrong 20 y = x; // wrong 21 ) 17 float pi = 3.14; 18 void f( void (*g)(void) ) { g(); } 19 @f( &pi );@ $\C{// wrong}$ 20 } 22 21 23 /* 24 The first gets 25 warning: assignment to `float *' from incompatible pointer type `void (*)(void)' 26 and the second gets the opposite. 27 28 Similarly, 29 */ 30 31 float pi = 3.14; 32 void f( void (*g)(void) ) { 33 g(); 34 } 35 ERR( 36 f( & pi ); // wrong 37 ) 38 /* 39 gets 40 warning: passing argument 1 of `f' from incompatible pointer type 41 with a segmentation fault at runtime. 42 43 That @f@'s attempt to call @g@ fails is not due to 3.14 being a particularly unlucky choice of value to put in the variable @pi@. 44 Rather, it is because obtaining a program that includes this essential fragment, yet exhibits a behaviour other than "doomed to crash," is a matter for an obfuscated coding competition. 45 46 A "tractable syntactic method for proving the absence of certain program behaviours 47 by classifying phrases according to the kinds of values they compute"*1 48 rejected the program. The behaviour (whose absence is unprovable) is neither minor nor unlikely. 49 The rejection shows that the program is ill-typed. 50 51 Yet, the rejection presents as a GCC warning. 52 53 In the discussion following, ``ill-typed'' means giving a nonzero @gcc -Werror@ exit condition with a message that discusses typing. 54 55 *1 TAPL-pg1 definition of a type system 56 */ 57 58 } 22 // Local Variables: // 23 // compile-command: "sed -f sedcmd bkgd-c-tyerr.c > tmp.c; gcc tmp.c" // 24 // End: // -
doc/theses/mike_brooks_MMath/programs/bkgd-carray-arrty.c
r03606ce r266732e 24 24 25 25 26 27 28 29 26 // SHOW(sizeof( a ), "%zd"); 27 // SHOW(sizeof(&a ), "%zd"); 28 // SHOW(sizeof( a[0]), "%zd"); 29 // SHOW(sizeof(&a[0]), "%zd"); 30 30 31 31 32 32 33 33 int main() { 34 float a[10]; 35 static_assert(sizeof(float) == 4); $\C{// floats (array elements) are 4 bytes}$ 36 static_assert(sizeof(void*) == 8); $\C{// pointers are 8 bytes}$ 37 static_assert(sizeof(a) == 40); $\C{// array}$ 38 static_assert(sizeof(&a) == 8 ); $\C{// pointer to array}$ 39 static_assert(sizeof(a[0]) == 4 ); $\C{// first element}$ 40 static_assert(sizeof(&(a[0])) == 8 ); $\C{// pointer to first element}$ 34 41 35 /* 36 When a programmer works with an array, C semantics provide access to a type that is different in every way from ``pointer to its first element.'' 42 typeof(&a) x; $\C{// x is pointer to array}$ 43 typeof(&(a[0])) y; $\C{// y is pointer to first element}$ 44 @x = y;@ $\C{// ill-typed}$ 45 @y = x;@ $\C{// ill-typed}$ 46 static_assert(sizeof(typeof(a)) == 40); 47 static_assert(sizeof(typeof(&a)) == 8 ); 48 static_assert(sizeof(typeof(a[0])) == 4 ); 49 static_assert(sizeof(typeof(&(a[0]))) == 8 ); 37 50 38 Its qualities become apparent by inspecting the declaration 39 */ 40 float a[10]; 41 /* 51 void f( float (*pa)[10] ) { 52 static_assert(sizeof( *pa ) == 40); $\C{// array}$ 53 static_assert(sizeof( pa ) == 8 ); $\C{// pointer to array}$ 54 static_assert(sizeof( (*pa)[0] ) == 4 ); $\C{// first element}$ 55 static_assert(sizeof(&((*pa)[0])) == 8 ); $\C{// pointer to first element}$ 56 } 57 f( & a ); 42 58 43 The inspection begins by using @sizeof@ to provide definite program semantics for the intuition of an expression's type. 59 float fs[] = {3.14, 1.707}; 60 char cs[] = "hello"; 44 61 45 Assuming a target platform keeps things concrete: 46 */ 47 static_assert(sizeof(float)==4); // floats (array elements) are 4 bytes 48 static_assert(sizeof(void*)==8); // pointers are 8 bytes 49 /* 50 51 Consider the sizes of expressions derived from @a@, modified by adding ``pointer to'' and ``first element'' (and including unnecessary parentheses to avoid confusion about precedence). 52 */ 53 static_assert(sizeof( a ) == 40); // array 54 static_assert(sizeof(& a ) == 8 ); // pointer to array 55 static_assert(sizeof( a[0] ) == 4 ); // first element 56 static_assert(sizeof(&(a[0])) == 8 ); // pointer to first element 57 /* 58 That @a@ takes up 40 bytes is common reasoning for C programmers. 59 Set aside for a moment the claim that this first assertion is giving information about a type. 60 For now, note that an array and a pointer to its first element are, sometimes, different things. 61 62 The idea that there is such a thing as a pointer to an array may be surprising. 63 It is not the same thing as a pointer to the first element: 64 */ 65 typeof(& a ) x; // x is pointer to array 66 typeof(&(a[0])) y; // y is pointer to first element 67 ERR( 68 x = y; // ill-typed 69 y = x; // ill-typed 70 ) 71 /* 72 The first gets 73 warning: warning: assignment to `float (*)[10]' from incompatible pointer type `float *' 74 and the second gets the opposite. 75 */ 76 77 /* 78 We now refute a concern that @sizeof(a)@ is reporting on special knowledge from @a@ being an local variable, 79 say that it is informing about an allocation, rather than simply a type. 80 81 First, recognizing that @sizeof@ has two forms, one operating on an expression, the other on a type, we observe that the original answers are unaffected by using the type-parameterized form: 82 */ 83 static_assert(sizeof(typeof( a )) == 40); 84 static_assert(sizeof(typeof(& a )) == 8 ); 85 static_assert(sizeof(typeof( a[0] )) == 4 ); 86 static_assert(sizeof(typeof(&(a[0]))) == 8 ); 87 88 /* 89 Finally, the same sizing is reported when there is no allocation at all, and we launch the analysis instead from the pointer-to-array type. 90 */ 91 void f( float (*pa)[10] ) { 92 static_assert(sizeof( *pa ) == 40); // array 93 static_assert(sizeof( pa ) == 8 ); // pointer to array 94 static_assert(sizeof( (*pa)[0] ) == 4 ); // first element 95 static_assert(sizeof(&((*pa)[0])) == 8 ); // pointer to first element 96 } 97 f( & a ); 98 99 /* 100 So, in spite of considerable programmer success enabled by an understanding that 101 an array just a pointer to its first element (revisited TODO pointer decay), 102 this understanding is simplistic. 103 */ 104 105 /* 106 A shortened form for declaring local variables exists, provided that length information is given in the initializer: 107 */ 108 float fs[] = {3.14, 1.707}; 109 char cs[] = "hello"; 110 111 static_assert( sizeof(fs) == 2 * sizeof(float) ); 112 static_assert( sizeof(cs) == 6 * sizeof(char) ); // 5 letters + 1 null terminator 113 114 /* 115 In these declarations, the resulting types are both arrays, but their lengths are inferred. 116 */ 117 62 static_assert( sizeof(fs) == 2 * sizeof(float) ); 63 static_assert( sizeof(cs) == 6 * sizeof(char) ); $\C{// 5 letters + 1 null terminator}$ 118 64 } 119 65 66 void syntaxReferenceCheck(void) { 67 // $\rightarrow$ & (base element) 68 // & @float@ 69 // & @float x;@ 70 // & @[ float ]@ 71 // & @[ float ]@ 72 float x0; 120 73 121 void syntaxReferenceCheck(void) { 122 // $\rightarrow$ & (base element) 123 // & @float@ 124 // & @float x;@ 125 // & @[ float ]@ 126 // & @[ float ]@ 127 float x0; 74 // $\rightarrow$ & pointer 75 // & @float *@ 76 // & @float * x;@ 77 // & @[ * float ]@ 78 // & @[ * float ]@ 79 float * x1; 128 80 129 // $\rightarrow$ & pointer 130 // & @float *@131 // & @float * x;@132 // & @[ *float ]@133 // & @[ * float]@134 float * x1;81 // $\rightarrow$ & array 82 // & @float[10]@ 83 // & @float x[10];@ 84 // & @[ [10] float ]@ 85 // & @[ array(float, 10) ]@ 86 float x2[10]; 135 87 136 // $\rightarrow$ & array 137 // & @float[10]@ 138 // & @float x[10];@ 139 // & @[ [10] float ]@ 140 // & @[ array(float, 10) ]@ 141 float x2[10]; 88 typeof(float[10]) x2b; 142 89 143 typeof(float[10]) x2b; 144 145 // & array of pointers 146 // & @(float*)[10]@ 147 // & @float *x[10];@ 148 // & @[ [10] * float ]@ 149 // & @[ array(*float, 10) ]@ 150 float *x3[10]; 90 // & array of pointers 91 // & @(float*)[10]@ 92 // & @float *x[10];@ 93 // & @[ [10] * float ]@ 94 // & @[ array(*float, 10) ]@ 95 float *x3[10]; 151 96 // (float *)x3a[10]; NO 152 97 153 154 155 156 157 158 98 // $\rightarrow$ & pointer to array 99 // & @float(*)[10]@ 100 // & @float (*x)[10];@ 101 // & @[ * [10] float ]@ 102 // & @[ * array(float, 10) ]@ 103 float (*x4)[10]; 159 104 160 161 162 163 164 165 166 105 // & pointer to array 106 // & @(float*)(*)[10]@ 107 // & @float *(*x)[10];@ 108 // & @[ * [10] * float ]@ 109 // & @[ * array(*float, 10) ]@ 110 float *(*x5)[10]; 111 x5 = (float*(*)[10]) x4; 167 112 // x5 = (float(*)[10]) x4; // wrong target type; meta test suggesting above cast uses correct type 168 113 169 170 114 // [here] 115 // const 171 116 172 173 174 175 117 // [later] 118 // static 119 // star as dimension 120 // under pointer decay: int p1[const 3] being int const *p1 176 121 177 178 179 122 const float * y1; 123 float const * y2; 124 float * const y3; 180 125 181 182 183 126 y1 = 0; 127 y2 = 0; 128 // y3 = 0; // bad 184 129 185 186 187 130 // *y1 = 3.14; // bad 131 // *y2 = 3.14; // bad 132 *y3 = 3.14; 188 133 189 190 134 const float z1 = 1.414; 135 float const z2 = 1.414; 191 136 192 193 137 // z1 = 3.14; // bad 138 // z2 = 3.14; // bad 194 139 195 140 … … 199 144 void stx2() { const T x[10]; 200 145 // x[5] = 3.14; // bad 201 146 } 202 147 void stx3() { T const x[10]; 203 148 // x[5] = 3.14; // bad 204 } 149 } 150 151 // Local Variables: // 152 // compile-command: "sed -f sedcmd bkgd-carray-arrty.c > tmp.c; gcc tmp.c" // 153 // End: // -
doc/theses/mike_brooks_MMath/programs/bkgd-carray-decay.c
r03606ce r266732e 1 1 #include <assert.h> 2 2 int main() { 3 float a[10]; $\C{// array}$ 4 float (*pa)[10] = &a; $\C{// pointer to array}$ 5 float a0 = a[0]; $\C{// element}$ 6 float *pa0 = &(a[0]); $\C{// pointer to element}$ 3 7 4 /* 5 The last section established the difference between these four types: 6 */ 8 float *pa0x = a; $\C{// (ok)}$ 9 assert( pa0 == pa0x ); 10 assert( sizeof(pa0x) != sizeof(a) ); 7 11 8 float a [10] ; // array 9 float (*pa )[10] = & a ; // pointer to array 10 float a0 = a[0] ; // element 11 float *pa0 = &(a[0]); // pointer to element 12 void f( float x[10], float *y ) { 13 static_assert( sizeof(x) == sizeof(void*) ); 14 static_assert( sizeof(y) == sizeof(void*) ); 15 } 16 f(0,0); 12 17 13 /* 14 But the expression used for obtaining the pointer to the first element is pedantic. 15 The root of all C programmer experience with arrays is the shortcut 16 */ 17 float *pa0x = a ; // (ok) 18 /* 19 which reproduces @pa0@, in type and value: 20 */ 21 assert( pa0 == pa0x ); 22 /* 23 The validity of this initialization is unsettling, in the context of the facts established in the last section. 24 Notably, it initializes name @pa0x@ from expression @a@, when they are not of the same type: 25 */ 26 assert( sizeof(pa0x) != sizeof(a) ); 18 // reusing local var `float a[10];`} 19 float v; 20 f( a, a ); $\C{// ok: two decays, one into an array spelling}$ 21 f( &v, &v ); $\C{// ok: no decays; a non-array passes to an array spelling}$ 27 22 23 char ca[] = "hello"; $\C{// array on stack, initialized from read-only data}$ 24 char *cp = "hello"; $\C{// pointer to read-only data [decay here]}$ 25 void edit(char c[]) { $\C{// param is pointer}$ 26 c[3] = 'p'; 27 } 28 edit(ca); $\C{// ok [decay here]}$ 29 edit(cp); $\C{// Segmentation fault}$ 30 edit("hello"); $\C{// Segmentation fault [decay here]}$ 28 31 32 void decay( float x[10] ) { 33 static_assert( sizeof(x) == sizeof(void*) ); 34 } 35 static_assert( sizeof(a) == 10 * sizeof(float) ); 36 decay(a); 29 37 38 void no_decay( float (*px)[10] ) { 39 static_assert( sizeof(*px) == 10 * sizeof(float) ); 40 } 41 static_assert( sizeof(*pa) == 10 * sizeof(float) ); 42 no_decay(pa); 43 } 30 44 31 32 33 34 35 36 37 38 39 40 void f( float x[10], float *y ) { 41 static_assert( sizeof(x) == sizeof(void*) ); 42 static_assert( sizeof(y) == sizeof(void*) ); 43 } 44 f(0,0); 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 // reusing local var `float a[10];` 61 float v; 62 f( a, a ); // ok: two decays, one into an array spelling 63 f( &v, &v ); // ok: no decays; a non-array passes to an array spelling 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 char ca[] = "hello"; // array on stack, initialized from read-only data 81 char *cp = "hello"; // pointer to read-only data [decay here] 82 void edit(char c[]) { // param is pointer 83 c[3] = 'p'; 84 } 85 edit(ca); // ok [decay here] 86 edit(cp); // Segmentation fault 87 edit("hello"); // Segmentation fault [decay here] 88 89 90 91 92 93 94 95 96 97 98 99 100 void decay( float x[10] ) { 101 static_assert( sizeof(x) == sizeof(void*) ); 102 } 103 static_assert( sizeof(a) == 10 * sizeof(float) ); 104 decay(a); 105 106 void no_decay( float (*px)[10] ) { 107 static_assert( sizeof(*px) == 10 * sizeof(float) ); 108 } 109 static_assert( sizeof(*pa) == 10 * sizeof(float) ); 110 no_decay(pa); 111 } 45 // Local Variables: // 46 // compile-command: "sed -f sedcmd bkgd-carray-decay.c > tmp.c; gcc tmp.c" // 47 // End: // -
doc/theses/mike_brooks_MMath/string.tex
r03606ce r266732e 6 6 7 7 \input{sharing-demo.tex} 8 9 Consider two strings @s1@ and @s1a@ that are in an aliasing relationship, and a third, @s2@, made by a simple copy from @s1@. 10 \par\noindent 11 \begin{tabular}{llll} 12 & @s1@ & @s1a@ & @s2@ \\ 13 %\input{sharing-demo1.tex} 14 \end{tabular} 15 \par\noindent 16 8 17 9 18 \subsection{RAII limitations} … … 225 234 } 226 235 \end{lstlisting} 236 237 \section{String I/O} -
doc/theses/mike_brooks_MMath/uw-ethesis.tex
r03606ce r266732e 1 1 %====================================================================== 2 % University of Waterloo Thesis Template for LaTeX 3 % Last Updated November, 20204 % by Stephen Carr, IST Client Services,2 % University of Waterloo Thesis Template for LaTeX 3 % Last Updated August 2022 4 % by IST Client Services, 5 5 % University of Waterloo, 200 University Ave. W., Waterloo, Ontario, Canada 6 % FOR ASSISTANCE, please send mail to request@uwaterloo.ca6 % FOR ASSISTANCE, please send mail to helpdesk@uwaterloo.ca 7 7 8 8 % DISCLAIMER … … 21 21 22 22 % DON'T FORGET TO ADD YOUR OWN NAME AND TITLE in the "hyperref" package configuration below. 23 % THIS INFORMATION GETS EMBEDDED IN THE PDF FINAL PDF DOCUMENT. 23 % Search for: PDFTITLE, PDFAUTHOR, PDFSUBJECT, and PDFKEYWORDS. 24 % THIS INFORMATION GETS EMBEDDED IN THE FINAL PDF DOCUMENT. 24 25 % You can view the information if you view properties of the PDF document. 25 26 26 % Many faculties/departments also require one or more printed copies. 27 % This template attempts to satisfy both types of output. 27 % Many faculties/departments also require one or more printed copies. 28 % This template attempts to satisfy both types of output. 28 29 % See additional notes below. 29 30 % It is based on the standard "book" document class which provides all necessary sectioning structures and allows multi-part theses. … … 32 33 33 34 % For people who prefer to install their own LaTeX distributions on their own computers, and process the source files manually, the following notes provide the sequence of tasks: 34 35 35 36 % E.g. to process a thesis called "mythesis.tex" based on this template, run: 36 37 … … 51 52 % Tip: Photographs should be cropped and compressed so as not to be too large. 52 53 53 % To create a PDF output that is optimized for double-sided printing: 54 % To create a PDF output that is optimized for double-sided printing: 54 55 % 1) comment-out the \documentclass statement in the preamble below, and un-comment the second \documentclass line. 55 56 % 2) change the value assigned below to the boolean variable "PrintVersion" from " false" to "true". … … 60 61 % For hyperlinked PDF, suitable for viewing on a computer, use this: 61 62 \documentclass[letterpaper,12pt,titlepage,oneside,final]{book} 62 \usepackage{times}63 63 \usepackage[T1]{fontenc} % Latin-1 => 256-bit characters, => | not dash, <> not Spanish question marks 64 64 65 65 % For PDF, suitable for double-sided printing, change the PrintVersion variable below to "true" and use this \documentclass line instead of the one above: 66 66 %\documentclass[letterpaper,12pt,titlepage,openright,twoside,final]{book} … … 69 69 % If you have to, it's easier to make changes to nomenclature once here than in a million places throughout your thesis! 70 70 \newcommand{\package}[1]{\textbf{#1}} % package names in bold text 71 \newcommand{\cmmd}[1]{\textbackslash\texttt{#1}} % command name in tt font 71 \newcommand{\cmmd}[1]{\textbackslash\texttt{#1}} % command name in tt font 72 72 \newcommand{\href}[1]{#1} % does nothing, but defines the command so the print-optimized version will ignore \href tags (redefined by hyperref pkg). 73 73 %\newcommand{\texorpdfstring}[2]{#1} % does nothing, but defines the command … … 82 82 %\usepackage{nomencl} % For a nomenclature (optional; available from ctan.org) 83 83 \usepackage{amsmath,amssymb,amstext} % Lots of math symbols and environments 84 \usepackage{fullpage,times,comment} 84 85 \usepackage{xcolor} 85 86 \usepackage{epic,eepic} 86 87 \usepackage{graphicx} 87 \graphicspath{{pictures/}} % picture directory88 \usepackage{comment} % Removes large sections of the document.89 88 \usepackage{tabularx} 90 89 \usepackage[labelformat=simple,aboveskip=0pt,farskip=0pt,font=normalsize]{subfig} 91 90 \renewcommand\thesubfigure{(\alph{subfigure})} 92 91 93 \ usepackage{algorithm}94 \usepackage{algpseudocode}95 92 \graphicspath{{pictures/}} % picture directory 93 %\usepackage{algorithm} 94 %\usepackage{algpseudocode} 96 95 \usepackage{pbox} 96 97 \makeatletter 98 \newcommand{\lstinput}[2]{\lstinputlisting[linerange={#1},xleftmargin=4pt,escapechar={\$},moredelim={**[is][\color{red}]{@}{@}}]{#2}} 99 \makeatother 100 % cfa macros used in the document 101 \input{common} 102 %\usepackage{common} 103 \CFAStyle % CFA code-style 104 \lstset{language=cfa,belowskip=-1pt} % set default language to CFA 105 \lstset{inputpath={programs}} 106 107 \newcommand{\uCpp}{$\mu$\CC} 108 \newcommand{\PAB}[1]{{\color{red}PAB: #1}} 97 109 98 110 % Hyperlinks make it very easy to navigate an electronic document. 99 111 % In addition, this is where you should specify the thesis title and author as they appear in the properties of the PDF document. 100 % Use the "hyperref" package 112 % Use the "hyperref" package 101 113 % N.B. HYPERREF MUST BE THE LAST PACKAGE LOADED; ADD ADDITIONAL PKGS ABOVE 114 \usepackage{url} 102 115 \usepackage[pagebackref=true]{hyperref} % with basic options 103 116 %\usepackage[pdftex,pagebackref=true]{hyperref} … … 110 123 pdffitwindow=false, % window fit to page when opened 111 124 pdfstartview={FitH}, % fits the width of the page to the window 112 pdftitle={ Cforall Memory Allocation}, % title: CHANGE THIS TEXT!113 pdfauthor={M ubeen Zulfiqar}, % author: CHANGE THIS TEXT! and uncomment this line125 pdftitle={\CFA Container Library}, % title: CHANGE THIS TEXT! 126 pdfauthor={Mike Brooks}, % author: CHANGE THIS TEXT! and uncomment this line 114 127 pdfsubject={Cforall}, % subject: CHANGE THIS TEXT! and uncomment this line 115 pdfkeywords={Cforall} { storage allocation} {C language}, % optional list of keywords128 pdfkeywords={Cforall} {container library} {C language}, % optional list of keywords 116 129 pdfnewwindow=true, % links in new window 117 130 colorlinks=true, % false: boxed links; true: colored links 118 131 linkcolor=blue, % color of internal links 119 citecolor=blue, % color of links to bibliography132 citecolor=blue, % color of links to bibliography 120 133 filecolor=magenta, % color of file links 121 urlcolor=blue, 134 urlcolor=blue, % color of external links 122 135 breaklinks=true 123 136 } 124 137 \ifthenelse{\boolean{PrintVersion}}{ % for improved print quality, change some hyperref options 125 138 \hypersetup{ % override some previously defined hyperref options 139 % colorlinks,% 126 140 citecolor=black,% 127 141 filecolor=black,% 128 142 linkcolor=black,% 129 urlcolor=black 130 }}{} % end of ifthenelse (no else) 143 urlcolor=black} 144 }{} % end of ifthenelse (no else) 145 146 \usepackage{breakurl} 131 147 \urlstyle{sf} 132 148 133 149 %\usepackage[automake,toc,abbreviations]{glossaries-extra} % Exception to the rule of hyperref being the last add-on package 134 % If glossaries-extra is not in your LaTeX distribution, get it from CTAN (http://ctan.org/pkg/glossaries-extra), 135 % although it's supposed to be in both the TeX Live and MikTeX distributions. There are also documentation and 150 % If glossaries-extra is not in your LaTeX distribution, get it from CTAN (http://ctan.org/pkg/glossaries-extra), 151 % although it's supposed to be in both the TeX Live and MikTeX distributions. There are also documentation and 136 152 % installation instructions there. 137 153 … … 140 156 141 157 % Setting up the page margins... 142 \setlength{\textheight}{9in}143 \setlength{\topmargin}{-0.45in}144 \setlength{\headsep}{0.25in}158 %\setlength{\textheight}{9in} 159 %\setlength{\topmargin}{-0.45in} 160 %\setlength{\headsep}{0.25in} 145 161 % uWaterloo thesis requirements specify a minimum of 1 inch (72pt) margin at the 146 % top, bottom, and outside page edges and a 1.125 in. (81pt) gutter margin (on binding side). 162 % top, bottom, and outside page edges and a 1.125 in. (81pt) gutter margin (on binding side). 147 163 % While this is not an issue for electronic viewing, a PDF may be printed, and so we have the same page layout for both printed and electronic versions, we leave the gutter margin in. 148 164 % Set margins to minimum permitted by uWaterloo thesis regulations: … … 152 168 % edge is less than 15 mm (0.6 in.) 153 169 \setlength{\marginparsep}{0pt} % width of space between body text and margin notes 154 \setlength{\evensidemargin}{0.125in} % Adds 1/8 in. to binding side of all 170 \setlength{\evensidemargin}{0.125in} % Adds 1/8 in. to binding side of all 155 171 % even-numbered pages when the "twoside" printing option is selected 156 172 \setlength{\oddsidemargin}{0.125in} % Adds 1/8 in. to the left of all pages when "oneside" printing is selected, and to the left of all odd-numbered pages when "twoside" printing is selected … … 161 177 \setlength{\parskip}{\medskipamount} 162 178 163 % The following statement controls the line spacing. 179 % The following statement controls the line spacing. 164 180 % The default spacing corresponds to good typographic conventions and only slight changes (e.g., perhaps "1.2"), if any, should be made. 165 181 \renewcommand{\baselinestretch}{1} % this is the default line space setting … … 174 190 \let\cleardoublepage\clearemptydoublepage 175 191 176 % Define Glossary terms (This is properly done here, in the preamble and 177 % could also be \input{} from a separate file...) 192 % Define Glossary terms (This is properly done here, in the preamble and could also be \input{} from a separate file...) 178 193 %\input{glossaries} 179 194 %\makeglossaries 180 181 % cfa macros used in the document182 \input{common}183 %\usepackageinput{common}184 \CFAStyle % CFA code-style185 \lstset{language=CFA} % default language186 \lstset{basicstyle=\linespread{0.9}\sf} % CFA typewriter font187 \lstset{inputpath={programs}}188 \newcommand{\PAB}[1]{{\color{red}PAB: #1}}189 190 \newcommand{\uCpp}{$\mu$\CC}191 195 192 196 %====================================================================== … … 202 206 % dedication, table of contents, list of tables, list of figures, nomenclature, etc. 203 207 %---------------------------------------------------------------------- 204 \input{uw-ethesis-frontpgs} 208 \input{uw-ethesis-frontpgs} 205 209 206 210 %---------------------------------------------------------------------- … … 211 215 % Tip: Putting each sentence on a new line is a way to simplify later editing. 212 216 %---------------------------------------------------------------------- 213 \begin{sloppypar} 217 214 218 \input{intro} 215 219 \input{background} … … 219 223 \input{conclusion} 220 224 221 \end{sloppypar}222 223 225 %---------------------------------------------------------------------- 224 226 % END MATERIAL … … 228 230 % Bibliography 229 231 230 % The following statement selects the style to use for references. 232 % The following statement selects the style to use for references. 231 233 % It controls the sort order of the entries in the bibliography and also the formatting for the in-text labels. 232 234 \bibliographystyle{plain} 233 % This specifies the location of the file containing the bibliographic information. 235 % This specifies the location of the file containing the bibliographic information. 234 236 % It assumes you're using BibTeX to manage your references (if not, why not?). 235 237 \cleardoublepage % This is needed if the "book" document class is used, to place the anchor in the correct page, because the bibliography will start on its own page. 236 238 % Use \clearpage instead if the document class uses the "oneside" argument 237 \phantomsection % With hyperref package, enables hyperlinking from the table of contents to bibliography 239 \phantomsection % With hyperref package, enables hyperlinking from the table of contents to bibliography 238 240 % The following statement causes the title "References" to be used for the bibliography section: 239 241 \renewcommand*{\bibname}{References} … … 243 245 244 246 \bibliography{pl,uw-ethesis} 245 % Tip: You can create multiple .bib files to organize your references. 247 % Tip: You can create multiple .bib files to organize your references. 246 248 % Just list them all in the \bibliogaphy command, separated by commas (no spaces). 247 249 248 % The following statement causes the specified references to be added to the bibliography even if they were not cited in the text. 250 % The following statement causes the specified references to be added to the bibliography even if they were not cited in the text. 249 251 % The asterisk is a wildcard that causes all entries in the bibliographic database to be included (optional). 250 252 % \nocite{*} … … 261 263 % \input{appendix-matlab_plots.tex} 262 264 263 % GLOSSARIES (Lists of definitions, abbreviations, symbols, etc. 264 % provided by the glossaries-extra package) 265 % GLOSSARIES (Lists of definitions, abbreviations, symbols, etc. provided by the glossaries-extra package) 265 266 % ----------------------------- 266 267 %\printglossaries
Note: See TracChangeset
for help on using the changeset viewer.