-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathcontainers_manual.tex
700 lines (535 loc) · 30.3 KB
/
containers_manual.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
\documentclass[11pt,a4paper,oneside,openright]{report}
\usepackage[bindingoffset=5mm,left=20mm,right=20mm,top=20mm,bottom=20mm,footskip=10mm]{geometry}
\usepackage[utf8x]{inputenc}
\usepackage{hyperref}
\usepackage[english]{babel}
\usepackage{listings}
\usepackage{subfiles}
\usepackage{longtable}
\usepackage{multirow}
\usepackage{ragged2e}
\usepackage{cmap} % avoid fi ligatures in pdf file
\usepackage{amsthm} % example numbering
\usepackage{color}
%\usepackage{bold-extra} % for bold tt font. Remember to include bold-extra.sty file
\usepackage{graphicx}
\usepackage[yyyymmdd]{datetime}
\usepackage{float}
% style for code listing
\renewcommand{\familydefault}{\sfdefault}
\renewcommand{\ttdefault}{pcr} % selects Courier font
\newtheorem{example}{Example}[chapter] % example numbering
\lstset{language=C} % formatting for code listing
\lstset{basicstyle=\ttfamily,breaklines=true}
\definecolor{darkGreen}{rgb}{0,0.4,0}
\definecolor{mybrown}{rgb}{0.40,0.10,0.05}
\lstset{commentstyle=\color{darkGreen}} % comments color
\lstset{keywordstyle=\color{blue}} % keyword color
\lstset{stringstyle=\color{mybrown}} % string color
\lstset{showstringspaces=false} % don't mark spaces in strings
\renewcommand{\dateseparator}{-}
% command for turning indent back on after \flushleft
\newcommand{\indenton}{\RaggedRight\parindent=15pt}
% command for vertical space
\newcommand{\vspacesmall}{\vspace{3mm}}
\newcommand{\vspacebig}{\vspace{6mm}}
% style for code inlined in text:
\newcommand{\codei}[1]{\bfseries \ttfamily{#1}\normalfont}
\begin{document}
\begin{titlepage}
\centering
\null %empty box needed for vfill to work
\vfill
{\bfseries\Huge
Container class templates
\vspacesmall
extension for C++ vector class library
\vspacebig
}
\vspacebig
{\Large
Agner Fog
\vspacebig
\copyright\ \today. Apache license 2.0
}
\vfill
\includegraphics[width=306pt]{freesoftwarelogo.jpg}
\vfill
\end{titlepage}
\RaggedRight
\chapter{Introduction}\label{chap:Introduction}
A container class template is a piece of C++ code that is useful for allocating memory space for a list of objects. It is similar to an array but with additional functionality and security.
\vspacesmall
C++ programmers routinely use the C++ standard containers (previously known as the standard template library) for this purpose. Unfortunately, the standard
C++ container templates can be quite inefficient. They are optimized for generality and flexibility, while efficiency has been sacrificed. Many of the standard C++ containers are implemented as linked lists that allocate memory in a lot of separate small pieces. This is inefficient because of a lot of heap management overhead, memory fragmentation, and poor caching. Many C++ programmers are routinely implementing a matrix as a nested container (vector of vectors) which is even more inefficient.
\vspacesmall
The container class templates provided here are intended to fill the need for more efficient containers with contiguous memory storage. Some of these containers are tailor-made to fit the classes defined in the vector classes library (VCL). Containers for other types of objects are also included.
\vspacesmall
Overview of container class templates:
\begin {table}[H]
\caption{Container class templates}
\label{table:containerClassTemplates}
\begin{tabular}{|p{44mm}|p{70mm}|p{35mm}|}
\hline
\bfseries Template & \bfseries Description & \bfseries Header file \\ \hline
ContainerG<type> & Linear array of any type of objects, \newline dynamic size & general\_containers.h \\ \hline
ContainerV<vector\_type, size> & Linear array of vectors, fixed size or \newline dynamic size & vector\_containers.h \\ \hline
MatrixV<vector\_type, rows, columns> & Matrix. Rows are stored as VCL vectors & matrixv.h \\ \hline
\end{tabular}
\end{table}
\vspacebig
\chapter{Description of container templates}\label{chap:DescriptionTemplates}
\section{ContainerG} \label{ContainerG}
{\bfseries Declaration}\\
\codei{template <typename T> class ContainerG};
\vspacebig
This container class template makes a linear array with dynamic size. \codei{ContainerG} is independent of the vector class library and can be used for most kinds of objects.
\vspacesmall
The type \codei{T} can be a simple type such as \codei{int} or \codei{float}, or a composite type such as a \codei{struct}, \codei{class}, or \codei{union}. The container will likely not work if the type \codei{T} has a non-default constructor, destructor, copy constructor, or move constructor. The type \codei{T} cannot be another container, but it can be a \codei{struct} containing a fixed-size array.
\vspacesmall
\begin{lstlisting}[frame=none]
// Example:
#include <stdio.h>
#include "general_containers.h"
// Function for error reporting
void error_reporter() {
fprintf(stderr, "\nError: index out of range\n");
}
int main () {
// Declare a container for float elements
ContainerG<float> my_array;
// Register error_reporter function to report any errors
my_array.set_error_handler(error_reporter);
// Set the size of the array
my_array.set_size(10);
// Put data into a C-style array
const int listsize = 8;
float list[listsize];
for (int i = 0; i < listsize; i++) list[i] = float(i);
// Load 8 elements into my_array
my_array.load(listsize, list);
// Print contents of my_array
for (int i = 0; i < my_array.size(); i++) {
printf(" %.2f", my_array[i]);
}
// Increase the size of the array
my_array.set_size(12);
// Change last element (index goes from 0 to size()-1 )
my_array[my_array.size()-1] = 88;
// Print contents again
printf("\n\n");
for (int i = 0; i < my_array.size(); i++) {
printf(" %.2f", my_array[i]);
}
}
/* Output:
0.00 1.00 2.00 3.00 4.00 5.00 6.00 7.00 0.00 0.00
0.00 1.00 2.00 3.00 4.00 5.00 6.00 7.00 0.00 0.00 0.00 88.00
*/
\end{lstlisting}
\vspacebig
{\bfseries Member functions:}\\
\vspacebig
{\bfseries void set\_size(int size)}\\
Sets the size of the container, i.e. the number of elements it can contain.\\
The size can be changed at any time. Increasing the size will make the code allocate a new internal memory buffer if the current memory buffer is not big enough. All contents will be copied to the new memory buffer and the old buffer will be deleted.\\
The code may allocate a bigger memory block than requested in order to avoid frequent re-allocations if the size is increased in small amounts.
The code does not re-allocate memory if the size is decreased to a non-zero value.\\
Calling \codei{set\_size} with a size of zero will delete the allocated memory and set everything to the initial condition. This may free memory for other purposes, but it is not needed because the container has a destructor that will free the allocated memory anyway.
\vspacebig
{\bfseries int size()}\\
Returns the current size of the container, i.e. the number of elements it can contain.
\vspacebig
{\bfseries int allocated\_size()}\\
Gives the size of the internal buffer, which may be bigger than specified by the last call to \codei{set\_size}. \codei{allocated\_size()} is the maximum size that can be set without reallocation of the internal memory.
\vspacebig
{\bfseries T \& operator [] (int index)}\\
The operator \codei{[]} works like an array index. This makes it possible to read or write a single element in the array. The code checks that the index is within the range $0 \leq$ \codei{index} $<$ \codei{size()}.
\vspacebig
{\bfseries void load(int n, T const {*} p)}\\
Loads \codei{n} objects from an array \codei{p}.\\
\codei{n} is the size of the array \codei{p} or the maximum number of elements to load. If \codei{n} is bigger than the size of the \codei{ContainerG} then it is reduced to the size of the container.
\vspacebig
{\bfseries void store(int n, T {*} p)}\\
Stores \codei{n} objects to an array \codei{p}.\\
\codei{n} is the size of the array \codei{p} or the maximum number of elements to store. If \codei{n} is bigger than the size of the \codei{ContainerG} then it is reduced to the size of the container.
\vspacebig
{\bfseries set\_error\_handler(void ({*}err)(void))}\\
Saves a pointer to an error handling function. This function will be called in case an index is out of range. The error handling function should issue an error message in a way that is appropriate for the actual user interface. The program will crash in case of an index out of range if no error handler is set.
\vspacebig
{\bfseries T {*} get\_buf()}\\
Returns a pointer to the internal buffer. It is important to remember that any pointer or reference to elements in the container will be invalid after the size has been increased.
\vspacebig
\subsection{Recycling of memory} \label{RecyclingOfMemory}
It may be more efficient to reuse a container for a new purpose during the course of the program than to delete each container when it is no longer needed and create a new one. This will improve memory caching.
\vspacesmall
The container may be resized for every new use. It can be useful to specify an estimated maximum size before first use of the container, and then reduce and increase the size as required during the course of the program.
\vspacesmall
The memory is zeroed at the first call to \codei{set\_size}, but it is not necessarily cleared when the container is later resized.
\vspacebig
\section{ContainerV} \label{ContainerV}
{\bfseries Declaration}\\
\codei{template <typename V, int n> class ContainerV};
\vspacebig
This container is designed for VCL vectors only. Vectors of all integer and floating point types are allowed, but not boolean types. Access is provided to each vector as well as to individual vector elements.
\vspacesmall
\begin{lstlisting}[frame=none]
// Example:
#include <stdio.h>
#include <vectorclass.h>
#include <vector_containers.h>
// Make container of four vectors of 8 float values each
ContainerV<Vec8f, 4> c;
// Array of floats
float list[32] = {0,1,2,3,4,5,6};
// Load array into container
c.load(32, list);
// Change one vector in container
c.set_vector(Vec8f(16,17,18,19,20,21,22,23), 2);
// Change one vector element in container
c.set_element(-99, 5);
// Loop through vectors:
for (int i = 0; i < c.n_vectors(); i++) {
// Loop through elements of each vector:
for (int j = 0; j < c.get_vector(0).size(); j++) {
// Print value:
printf(" %6.2f", c.get_vector(i)[j]);
}
// Next vector on new line:
printf("\n");
}
/* Output:
0.00 1.00 2.00 3.00 4.00 -99.00 6.00 0.00
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
16.00 17.00 18.00 19.00 20.00 21.00 22.00 23.00
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
*/
\end{lstlisting}
\vspacebig
{\bfseries Defined type \codei{etype} }\\
The template defines \codei{etype} as the type of the vector elements. For example, if the container is based on vectors of type \codei{Vec8f}, then \codei{etype} is the type \codei{float}.
\vspacebig
{\bfseries Member functions:}\\
\vspacebig
{\bfseries int n\_vectors()}\\
Returns the number of vectors.
\vspacebig
{\bfseries int n\_elements()}\\
Returns the number of vector elements.
\vspacebig
{\bfseries int elementtype()}\\
Returns the \codei{elementtype()} of the underlying vector class + 0x1000.
\vspacebig
{\bfseries vector\_type get\_vector(int index)}\\
Returns one vector from the position indicated by index. (The first vector has index 0).
\vspacebig
{\bfseries set\_vector(vector\_type x, int index)}\\
Replaces one vector at the position indicated by index.
\vspacebig
{\bfseries etype get\_element(int index)}\\
Returns a single vector element. The index runs consecutively through all vectors in the container, from 0 to (number of vectors) * (elements per vector) - 1.
\vspacebig
{\bfseries set\_element(etype x, int index)}\\
Replaces a single vector element. The index runs consecutively through all vectors in the container, from 0 to (number of vectors) * (elements per vector) - 1.
\vspacebig
{\bfseries load(int n, void const {*} p)}\\
Loads values from an array into the container. p points to an array of type
\codei{etype}. n is the array size or the maximum number of vector elements to load. If n is not a multiple of the vector size then the last vector will be partially filled. If n is bigger than the container size, then it is limited to the container size. If n is smaller than the container size, then the remaining full vectors are unchanged.
\vspacebig
{\bfseries store(int n, void * p)}\\
Stores values from the container into an array. p points to an array of type
\codei{etype}.
n is the array size or the maximum number of vector elements to store. n does not have to be a multiple of the vector size. If n is bigger than the container size, then it is limited to the container size.
\vspacebig
{\bfseries vector\_type get\_buf()}\\
Returns a pointer to the internal buffer. Note that this pointer will be invalid if the size of the container is later increased (see below).
\vspacebig
{\bfseries zero()}\\
Sets all vectors and all vector elements in the container to zero. Does not change the size of the container.
\vspacebig
{\bfseries set\_error\_handler(void ({*}err)(void))}\\
Saves a pointer to an error handling function. This function will be called in case an index is out of range. The error handling function should issue an error message in a way that is appropriate for the actual user interface. The program will crash in case of an index out of range if no error handler is set.
\begin{lstlisting}[frame=none]
// Example:
#include <stdio.h>
#include <vectorclass.h>
#include <vector_containers.h>
void error_reporter() {
fprintf(stderr, "\nError: index out of range\n");
}
// Make container of four vectors of 8 float values each
ContainerV<Vec8f, 4> c;
// Set the error handler
c.set_error_handler(error_reporter);
\end{lstlisting}
\vspacebig
\subsection{Dynamic size} \label{ContainerVDynamicSize}
The \codei{ContainerV} template has a dynamic size if, and only if, the initial size is 0.
\vspacesmall
\begin{lstlisting}[frame=none]
// Example:
#include <stdio.h>
#include <vectorclass.h>
#include <vector_containers.h>
// Make dynamic container of a variable number of vectors
ContainerV<Vec8f, 0> c;
// Set the size
c.set_nvectors(6);
// Change one vector in container
c.set_vector(Vec8f(16,17,18,19,20,21,22,23), 2);
// Loop through vectors:
for (int i = 0; i < c.n_vectors(); i++) {
// Loop through elements of each vector:
for (int j = 0; j < c.get_vector(0).size(); j++) {
// Print value:
printf(" %6.2f", c.get_vector(i)[j]);
}
// Next vector on new line:
printf("\n");
}
/* Output:
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
16.00 17.00 18.00 19.00 20.00 21.00 22.00 23.00
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
*/
\end{lstlisting}
\vspacebig
{\bfseries Additional member functions for dynamic size}\\
The following member functions are only available for ContainerV if the initial size is 0:
\vspacebig
{\bfseries set\_nvectors(int size)}\\
Changes the size of the container. On the first call to this function, the code allocates a memory block big enough to contain the specified number of vectors. If a later call to \codei{set\_nvectors} increases the size, then it will allocate a new bigger memory block if necessary, copy all data to the new memory block, and delete the old memory block. The code may allocate a bigger memory block than requested in order to avoid frequent re-allocations if the size is increased in small amounts.
The code does not re-allocate memory if the size is decreased to a non-zero value.
Calling \codei{set\_nvectors} with a size of zero will delete the allocated memory and set everything to the initial condition. This may free memory for other purposes, but it is not needed because the container has a destructor that frees the allocated memory anyway.
\vspacebig
{\bfseries set\_nelements(int n)}\\
This function is similar to \codei{set\_nvectors}, but makes it possible to set a size that is not a multiple of the vector size. The size is rounded up to a multiple of the vector size in order to determine the amount of memory to allocate, while the last vector will be only partially used.
\codei{n\_vectors()} will report the number of vectors used, including any partially used vector, while \codei{n\_elements()} will return the value set by \codei{set\_nelements(n)}.
\vspacebig
{\bfseries int allocated\_size()}\\
This function returns the actual amount of memory allocated, including any unused memory. The unit is the vector size, similar to \codei{set\_nvectors}.
\vspacebig
\subsection{Recycling of memory} \label{RecyclingOfMemory}
It may be more efficient to reuse a container for a new purpose during the course of the program than to delete each container when it is no longer needed and create a new one. This will improve memory caching.
\vspacesmall
The container may be resized for every new use. It can be useful to specify an estimated maximum size before first use of the container, and then reduce and increase the size as required during the course of the program.
\vspacesmall
The memory is zeroed at the first call to \codei{set\_nvectors}, but it is not necessarily cleared when the container is later resized. A container with fixed size contains random data initially.
\vspacebig
\section{MatrixV} \label{ContainerV}
MatrixV is a container for representing numerical data as a matrix. Each row in the matrix is stored as one or more VCL vectors. This is useful for representing numerical data as a matrix. MatrixV can also be used for storing a list of vectors where each vector is represented as a row, and the number of columns corresponds to the number of elements in each vector.
\vspacesmall
MatrixV is optimized for accessing the matrix as rows rather than columns.
\vspacesmall
{\bfseries Declaration}\\
\codei{template <typename V, int rows, int columns>
class MatrixV;}
\vspacebig
The vector type \codei{V} can be any floating point or integer vector class. Boolean vectors are not supported. (It is more efficient to pack boolean vectors into integer bitfields).
\vspacesmall
If the number of columns is larger than the number of elements in the vector class \codei{V} then the template will use multiple vectors for each row. If the number of columns is less than the number of elements in the vector class \codei{V} then the template will use the smallest possible vector class that fits the number of columns. Any extra elements in \codei{V} will be unused. The template will not store multiple rows in one vector, but start each row with a new vector. It is possible to specify \codei{V} as the largest possible vector with the desired element type and leave it to the template to find the smallest vector of the same element type that fits the number of columns. The MatrixV template will not use vectors larger than \codei{V}.
\vspacesmall
{\bfseries Defined type \codei{row\_vector\_type} }\\
The template defines \codei{row\_vector\_type} as the vector class used for storing rows. This may be the specified vector class \codei{V} or a smaller vector class with the same element type.
\vspacesmall
{\bfseries Defined type \codei{etype} }\\
The template defines \codei{etype} as the type of the vector elements. For example, if the container is based on vectors of type \codei{Vec8f}, then \codei{etype} is the type \codei{float}.
\vspacebig
{\bfseries Member functions:}\\
\vspacebig
{\bfseries int nrows()}\\
Returns the number of rows in the matrix.
\vspacebig
{\bfseries int ncolumns()}\\
Returns the number of columns in the matrix.
\vspacebig
{\bfseries int vectors\_per\_row()}\\
Returns the number of vectors of class \codei{row\_vector\_type} that are used for each row. Any partially used vector is included.
\vspacebig
{\bfseries int full\_vectors\_per\_row()}\\
Returns the number of fully-used vectors of class \codei{row\_vector\_type} that are used for each row. Any partially used vector is not included.
\vspacebig
{\bfseries int partial\_vector\_elements()}\\
If the number of columns is not divisible by the number of elements in vector class \codei{row\_vector\_type} then the last vector in each row will be partially used. This function returns the number of used elements in a partially-used vector. The function returns 0 if there are no partially used vectors.
\vspacebig
{\bfseries set\_error\_handler(void ({*}err)(void))}\\
This function is used for registering a function for reporting errors such as an index out of range. \codei{err} should be a function that reports the error in a way that is appropriate for the actual user interface. The program will crash in case a row or column index is out of range if no error-handling function is registered.
\vspacebig
{\bfseries void ({*}get\_error\_handler())(void)}\\
Returns a pointer to the function set by \codei{set\_error\_handler}.
\vspacebig
{\bfseries row\_vector\_type get\_row(int r, int i = 0)}\\
Returns row number \codei{r} as a vector of class \codei{row\_vector\_type}. \\
Row numbers go from 0 to \codei{nrows()-1}.\\
If each row contains more than one vector then call \codei{get\_row} multiple times with \codei{i} going from 0 to \codei{vectors\_per\_row() - 1}.
\vspacebig
{\bfseries set\_row(row\_vector\_type x, int r, int i = 0)}\\
Sets row number \codei{r} to a vector of class \codei{row\_vector\_type}. \\
Row numbers go from 0 to \codei{nrows()-1}.\\
If each row contains more than one vector then call \codei{set\_row} multiple times with \codei{i} going from 0 to \codei{vectors\_per\_row() - 1}.
\vspacebig
{\bfseries etype get\_element(int row, int column)}\\
Returns a single element from the matrix.\\
The row number goes from 0 to \codei{nrows()-1}.\\
The column number goes from 0 to \codei{ncolumns()-1}.
\vspacebig
{\bfseries set\_element(etype x, int row, int column)}\\
Changes a single element in the matrix.\\
The row number goes from 0 to \codei{nrows()-1}.\\
The column number goes from 0 to \codei{ncolumns()-1}.
\vspacebig
{\bfseries load(void const {*} p)}\\
Fills the entire matrix with data from a C-style matrix or linear array pointed to by \codei{p}. The matrix or array must contain (rows * columns) elements.\\
The elements are retrieved in row-major order in accordance with the C standard.
\vspacebig
{\bfseries store(void {*} p)}\\
A C-style matrix or array pointed to by \codei{p} is filled with all data from the entire matrix. The number of elements stored at \codei{ {*}p} is (rows * columns).\\
The elements are stored in row-major order in accordance with the C standard.
\vspacebig
{\bfseries zero()}\\
Sets all elements in the matrix to zero.
\vspacebig
\subsection{Initializing a MatrixV} \label{InitializingMatrixV}
A \codei{MatrixV} is not initialized when it is first constructed. The contents of unitialized matrix elements is unpredictable.
The matrix can be initialized by the \codei{load} member function or by multiple calls to \codei{set\_row}. It is less efficient to set all elements individually with \codei{set\_element}.
\vspacesmall
The internal vectors contain unused vector elements if the number of columns is not divisible by the vector size.
It is recommended to call the \codei{zero} member function first if the matrix elements are initialized with \codei{set\_element} only, in order to clear any unused vector elements. Otherwise, the unused elements may occur as random values in unused vector elements retrieved by \codei{get\_row} or by the pack functions described below.
\vspacebig
\subsection{Pack and unpack functions} \label{PackAndUnpack}
Several functions are defined for packing multiple matrix rows into one big vector and for unpacking such a vector into multiple matrix rows. These functions cannot be used if the number of columns is too big for multiple rows to fit into a single large vector.
\vspacesmall
The pack and unpack functions are useful in cases where matrix elements are accessed in other patterns than rowwise and when permutations are needed, such as matrix transposition and matrix-by-matrix products. The pack and unpack functions support all floating point vector classes and integer vector classes with integer types of at least 16 bits. 8-bit integers are not supported.
\vspacebig
{\bfseries Pack functions}\\
\codei{template <typename M> auto pack2rows(M \& matrix, int first\_row)}\\
\codei{template <typename M> auto pack3rows(M \& matrix, int first\_row)}\\
\codei{template <typename M> auto pack4rows(M \& matrix, int first\_row)}\\
\codei{template <typename M> auto pack5rows(M \& matrix, int first\_row)}
\vspacebig
These functions will pack n consecutive rows of a \codei{MatrixV} matrix into a single vector, provided that a vector class with sufficient size exists.
\vspacesmall
For example, a matrix with 5 rows and 3 columns with elements of type \codei{float} can be packed in the following ways.
\codei{pack2rows} will pack two consecutive rows into a vector of type \codei{Vec8f} with the elements of two rows in the first 6 vector positions, while the last two vector positions are unused. \codei{pack3rows} will pack three rows into a \codei{Vec16f} with the first 9 elements used and the last 7 elements unused. \codei{pack4rows} will use 12 elements, and \codei{pack5rows} can pack the entire matrix into 15 elements of a \codei{Vec16f} with the last element unused. \codei{first\_row} indicates the start row, where row numbers start at 0.
\vspacesmall
The pack functions are automatically finding a vector size that fits the number of data elements packed. You will get a compilation error if no sufficiently big vector class exists. It is not possible to pack the rows into multiple vectors with a single call to a pack function.
\vspacesmall
The error handling function set by \codei{set\_error\_handler} for the matrix will be called in case any of the row indexes is out of range. For example, calling \codei{pack3rows} with \codei{first\_row} set to 3 on a matrix with 5 rows will give an error because the last row is out of range. The program will crash if there is no error handling function and a row index is out of range.
\vspacebig
{\bfseries Unpack functions}\\
\codei{template <typename V, typename M> unpack2rows(V rr, M \& matrix, int first\_row))}\\
\codei{template <typename V, typename M> unpack3rows(V rr, M \& matrix, int first\_row))}\\
\codei{template <typename V, typename M> unpack4rows(V rr, M \& matrix, int first\_row))}\\
\codei{template <typename V, typename M> unpack5rows(V rr, M \& matrix, int first\_row))}\\
\vspacebig
These functions are doing the opposite of the pack functions. The large vector \codei{rr} is unpacked to fill n consecutive rows of the matrix \codei{M}. The unpack functions can be used for initializing or modifying a matrix.
\vspacesmall
A row index out of range will be indicated by a call to the error handling function in the same way as for the pack functions.
\vspacebig
\subsection{Examples} \label{MatrixExamples}
The following examples illustrate how to use the \codei{MatrixV} container, its member functions, and the pack and unpack functions.
\vspacebig
\begin{lstlisting}[frame=none]
#include <stdio.h>
#include <vectorclass.h>
#include <matrixv.h>
// Function for reporting an error message
void error_reporter() {
fprintf(stderr, "\nError: index out of range\n");
}
// Function for printing a whole matrix
template <typename M>
void print_matrix(M & matrix) {
// row loop
for (int r = 0; r < matrix.nrows(); r++) {
// column loop
for (int c = 0; c < matrix.ncolumns(); c++) {
// print one element
printf(" %6.2f", matrix.get_element(r, c));
}
printf("\n"); // new line for next row
}
}
int main() {
// C-style matrix with 3 rows and 4 columns
float Amatrix[3][4];
// Put data into this matrix
for (int r = 0; r < 3; r++) {
for (int c = 0; c < 4; c++) {
Amatrix[r][c] = float(r + 0.1 * c);
}
}
// Vector-based matrix with 3 rows and 4 columns
MatrixV<Vec8f, 3, 4> A;
// Set an error handler
A.set_error_handler(error_reporter);
// Load data from C-style matrix Amatrix into vector-based matrix A
A.load(Amatrix);
// Print matrix A
printf("\n A:\n");
print_matrix(A);
// Pack matrix A into one big vector (A has 3 rows)
Vec16f Apack = pack3rows(A, 0);
// Transpose matrix A
const int d = V_DC; // d means don't care
Vec16f Atransposed = permute16<
0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11, d, d, d, d>(Apack);
// Vector-based matrix for A transposed. Has 4 rows and 3 columns
MatrixV<Vec8f, 4, 3> B;
// Set an error handler
B.set_error_handler(error_reporter);
// Unpack Atransposed vector into matrix B (B has 4 rows)
unpack4rows(Atransposed, B, 0);
// Row operations
// Subtract 2 * row2 from row1 in matrix B
auto row1 = B.get_row(1); // row 1 as Vec4f
auto row2 = B.get_row(2); // row 2 as Vec4f
auto new_row1 = row1 - 2.0f * row2; // calculate new row 1
B.set_row(new_row1, 1); // insert new row 1
// Print matrix B
printf("\n B:\n");
print_matrix(B);
// Matrix multiplication
// Pack matrix B into one big vector
Vec16f Bpack = pack4rows(B, 0);
// Calculate matrix product A * B
Vec16f AxBpack =
permute16<0, 0, 0, 4, 4, 4, 8, 8, 8, d, d, d, d, d, d, d>(Apack)
* permute16<0, 1, 2, 0, 1, 2, 0, 1, 2, d, d, d, d, d, d, d>(Bpack)
+ permute16<1, 1, 1, 5, 5, 5, 9, 9, 9, d, d, d, d, d, d, d>(Apack)
* permute16<3, 4, 5, 3, 4, 5, 3, 4, 5, d, d, d, d, d, d, d>(Bpack)
+ permute16<2, 2, 2, 6, 6, 6,10,10,10, d, d, d, d, d, d, d>(Apack)
* permute16<6, 7, 8, 6, 7, 8, 6, 7, 8, d, d, d, d, d, d, d>(Bpack)
+ permute16<3, 3, 3, 7, 7, 7,11,11,11, d, d, d, d, d, d, d>(Apack)
* permute16<9,10,11, 9,10,11, 9,10,11, d, d, d, d, d, d, d>(Bpack);
// Product matrix has 3 rows and 3 columns
MatrixV<Vec8f, 3, 3> AxB;
// Set an error handler
AxB.set_error_handler(error_reporter);
// Unpack product vector into matrix AxB
unpack3rows(AxBpack, AxB, 0);
// Print product matrix AxB
printf("\n AxB:\n");
print_matrix(AxB);
}
/* Output:
A:
0.00 0.10 0.20 0.30
1.00 1.10 1.20 1.30
2.00 2.10 2.20 2.30
B:
0.00 1.00 2.00
-0.30 -1.30 -2.30
0.20 1.20 2.20
0.30 1.30 2.30
AxB:
0.10 0.50 0.90
0.30 2.70 5.10
0.50 4.90 9.30
*/
\end{lstlisting}
\vspacebig
\end{document}