diff --git a/main/dsppp_building.html b/main/dsppp_building.html index 75fb5bb66..f2ab34947 100644 --- a/main/dsppp_building.html +++ b/main/dsppp_building.html @@ -132,14 +132,14 @@
First time:
Other times:
If you want to select another test, edit the file example.cproject.yml
and uncomment the test.
If the tools have been installed with vcpkg
:
If you want to compute the dot product:
@@ -157,7 +157,7 @@
With this new C++ template library, you can write:
The code generated by this line computes the dot product in one pass with all the operators (+
, *
) included in the loop. There is no more any temporary buffers.
Let's look at another example:
diff --git a/main/dsppp_main.js b/main/dsppp_main.js index 11764d987..c1c7c3eec 100644 --- a/main/dsppp_main.js +++ b/main/dsppp_main.js @@ -2,47 +2,47 @@ var dsppp_main = [ [ "Introduction", "dsppp_intro.html", null ], [ "What you need to know about C++ templates", "dsppp_template.html", [ - [ "What is a template useful for ?", "dsppp_template.html#autotoc_md7", null ], - [ "Templates for datatypes", "dsppp_template.html#autotoc_md8", null ], - [ "Implicit parameters", "dsppp_template.html#autotoc_md9", null ], - [ "How to use templates ?", "dsppp_template.html#autotoc_md10", null ], - [ "Example", "dsppp_template.html#autotoc_md11", null ] + [ "What is a template useful for ?", "dsppp_template.html#autotoc_md8", null ], + [ "Templates for datatypes", "dsppp_template.html#autotoc_md9", null ], + [ "Implicit parameters", "dsppp_template.html#autotoc_md10", null ], + [ "How to use templates ?", "dsppp_template.html#autotoc_md11", null ], + [ "Example", "dsppp_template.html#autotoc_md12", null ] ] ], [ "Vector operation example", "dsppp_vector_example.html", [ - [ "Include the headers", "dsppp_vector_example.html#autotoc_md12", null ], - [ "Creation of the vectors", "dsppp_vector_example.html#autotoc_md13", null ], - [ "Initialization of the vectors", "dsppp_vector_example.html#autotoc_md14", null ], - [ "Computation", "dsppp_vector_example.html#autotoc_md15", null ], - [ "Displaying the result", "dsppp_vector_example.html#autotoc_md16", null ] + [ "Include the headers", "dsppp_vector_example.html#autotoc_md13", null ], + [ "Creation of the vectors", "dsppp_vector_example.html#autotoc_md14", null ], + [ "Initialization of the vectors", "dsppp_vector_example.html#autotoc_md15", null ], + [ "Computation", "dsppp_vector_example.html#autotoc_md16", null ], + [ "Displaying the result", "dsppp_vector_example.html#autotoc_md17", null ] ] ], [ "Memory allocation", "dsppp_memory_allocator.html", null ], [ "Static / dynamic", "dsppp_memory_static_dynamic.html", [ - [ "Static objects", "dsppp_memory_static_dynamic.html#autotoc_md17", null ], - [ "Dynamic objects", "dsppp_memory_static_dynamic.html#autotoc_md18", null ] + [ "Static objects", "dsppp_memory_static_dynamic.html#autotoc_md18", null ], + [ "Dynamic objects", "dsppp_memory_static_dynamic.html#autotoc_md19", null ] ] ], [ "Code size", "dsppp_code_size.html", null ], [ "Fusion", "dsppp_fusion.html", null ], [ "Vector", "dsppp_vector.html", [ - [ "Q15 example", "dsppp_vector.html#autotoc_md19", null ], - [ "VectorView", "dsppp_vector.html#autotoc_md20", null ] + [ "Q15 example", "dsppp_vector.html#autotoc_md20", null ], + [ "VectorView", "dsppp_vector.html#autotoc_md21", null ] ] ], [ "Matrix", "dsppp_matrix.html", [ - [ "VectorView", "dsppp_matrix.html#autotoc_md21", [ - [ "Row vector", "dsppp_matrix.html#autotoc_md22", null ], - [ "Column vector", "dsppp_matrix.html#autotoc_md23", null ] + [ "VectorView", "dsppp_matrix.html#autotoc_md22", [ + [ "Row vector", "dsppp_matrix.html#autotoc_md23", null ], + [ "Column vector", "dsppp_matrix.html#autotoc_md24", null ] ] ], - [ "MatrixView", "dsppp_matrix.html#autotoc_md24", null ], - [ "Matrix operations", "dsppp_matrix.html#autotoc_md25", [ - [ "dot", "dsppp_matrix.html#autotoc_md26", null ], - [ "diagonal", "dsppp_matrix.html#autotoc_md27", null ], - [ "identity", "dsppp_matrix.html#autotoc_md28", null ], - [ "transpose", "dsppp_matrix.html#autotoc_md29", null ], - [ "outer product", "dsppp_matrix.html#autotoc_md30", null ] + [ "MatrixView", "dsppp_matrix.html#autotoc_md25", null ], + [ "Matrix operations", "dsppp_matrix.html#autotoc_md26", [ + [ "dot", "dsppp_matrix.html#autotoc_md27", null ], + [ "diagonal", "dsppp_matrix.html#autotoc_md28", null ], + [ "identity", "dsppp_matrix.html#autotoc_md29", null ], + [ "transpose", "dsppp_matrix.html#autotoc_md30", null ], + [ "outer product", "dsppp_matrix.html#autotoc_md31", null ] ] ] ] ], [ "Building and running examples", "dsppp_building.html", [ - [ "To build", "dsppp_building.html#autotoc_md31", null ], - [ "To run", "dsppp_building.html#autotoc_md32", null ] + [ "To build", "dsppp_building.html#autotoc_md32", null ], + [ "To run", "dsppp_building.html#autotoc_md33", null ] ] ], [ "Guidelines", "dsppp_guidelines.html", null ] ]; \ No newline at end of file diff --git a/main/dsppp_matrix.html b/main/dsppp_matrix.html index 0c3059a38..20d9b71dc 100644 --- a/main/dsppp_matrix.html +++ b/main/dsppp_matrix.html @@ -154,10 +154,10 @@
The operators +
and *
are merged into the loop. *
is the element-wise multiply. For the vector / matrix products you should use the operator dot
.
Note that fusion of operators will not work with dot(Matrix, Matrix
). It is only supported with vectors : dot(Vector,Vector)
or dot(Matrix,Vector)
.
We can create virtual vectors which are view of some slices of the matrix.
-To set the second row to 0.0f
, you can do:
stop
is the index of the first element after the end of the view.
i
is the row index
There is a similar API for columns.
Let's set the odd elements of columns 3 to 5.0f
:
It is also possible to create a virtual matrix : a view onto a subset of the matrix.
Let's add the bottom right corner of the matrix to itself:
@@ -189,7 +189,7 @@You specify the row start and row end, then column start and column end.
Note that the end is the first index after the end of your rows or columns.
No stride is supported for matrix view in this version of the library.
-In addition to the vector operations +
,-
and *
, matrixes are supporting more operations:
tranpose
to create the transposed matrixouter
for the outer product of two vectorsThe compiler may use the move semantic to copy the temporary result of the dot
function to result
.
In this case, no copy would occur and result
after the assignment would be a vector allocated by dot
so using the TMP_ALLOC
.
or
This naming "static" / "dynamic" is referring to the dimension. With "dynamic" vectors the same code can, at runtime, create vectors of different length based on a runtime length.
With "static" vectors : the length is fixed at build time and will never change at runtime.
Note that the library also have "static" / "dynamic" matrixes. So, we are going to use the name "object" to cover both cases in the below explanations.
-The advantage of static objects is that the dimension is known at build time. The compiler can thus generate an algorithm that is specialized for those dimensions and thus more efficient.
With static objects it is also possible to use different memory allocator with better performances and determinism.
But, with static objects, objects of different dimension are considered as different types. The compiler will generate different implementation so it will have an impact on the code size.
If you need lots of objects of different dimensions, or if the dimensions are not known at build time, then you need to use dynamic object
-With dynamic objects, the dimension is know at runtime. So object of different dimensions have the same datatype and the compiler is generating only one implementation for all those objects. It cannot generate specialized implementations based on the dimension. It is better for code size, but the implementations will be less efficient.
Also when dimension is not know at build time, some instruction selection made by the C++ library at build time is no more possible. It has an effect on performance since at runtime one must decides what's possible or not. It is mostly impacting matrixes where stride information is needed.
diff --git a/main/dsppp_template.html b/main/dsppp_template.html index e4d712a9e..2b1875980 100644 --- a/main/dsppp_template.html +++ b/main/dsppp_template.html @@ -132,7 +132,7 @@In CMSIS-DSP, you have functions like:
The generic arm_add
source code is a template used to generate different implementations. It is like a code generator.
And if the compiler is unable to generate an implementation because the type variable T
is replaced by a type with no addition operator, then it would be detected by the compiler.
Note that in C++, you can also use overloading of functions. They'll use the same name (but different arguments) but they won't share the same source code.
-C++ templates also apply to structs and classes.
For instance, we could have a template Vector<T>
and thus different types Vector<float32_t>
, Vector<Q15>
...
For instance, one could have a type Vector<float32_t,10>
for a vector of float
and of length 10
. The length being known at build time.
The types Vector<float32_t,10>
and Vector<float32_t,5>
should be considered as different types because they have different lengths. The length is part of the type.
What we said above for code generation applies. For a template algorithm using any kind of vector, the compiler would generate different code for different vector types. The code for a template algorithm using Vector<float32_t,10>
would be different from the code for Vector<float32_t,5>
because those two types are different.
A template can also have implicit parameters.
For instance one could use Vector<float32_t>
or Vector<float32_t,10>
.
In the first case, the length is an implicit parameter with a default value and it is equivalent to writing Vector<float32_t,DYNAMIC>
where DYNAMIC
could be a special value (negative for instance) used to tell the compiler that the length of the vector is not known at build time but only at runtime.
Both variants may use totally different implementations. The DYNAMIC
variant may contain a length
field in the struct
definition whereas other variants do not need this field since the length is known at build time.
A template is just a C++ header. You only need to include this header to start using the template. There is nothing to build.
-Now you can look at an example with vector operations showing how to use the library
Allocator
is the memory allocator. By default it is TMP_ALLOC
that you can redefine since it is a macroVector_Base<P>
is providing the storage. A vector owns its storage buffer.Example with Q15
is very similar:
The vectors are defined:
@@ -160,7 +160,7 @@The result is displayed:
A vector view is a virtual vector : a view of a vector.
One can define a VectorView
with:
The headers are not yet part of the CMSIS-DSP packs since they are experimental. You can get them from the CMSIS-DSP github
If fixed point datatypes are required, #include <dsppp/fixed_point>
should be used before <dsppp/matrix>
Fixed point requires the use of CMSIS-DSP.
-To create a vector a
you would write:
If you don't know the dimension at build time, you can use a different type of vector with:
For the trade-off between vector with build time dimension or runtime dimension please see the section Static / dynamic .
-You can index the vectors as normal C arrays.
The computation can be written normally as :
The operators +
, *
are computed in one pass with one loop : we have loop fusion and instead of having a loop per operator we have a loop for the whole computation.
To understand fusion and how to extend it with new operators, see section Fusion .
For an overview of vector operators, see section Vector . For an overview of matrix operators, see section Matrix .
-The vectors can be displayed on stdout
for debug purpose.
Functions | |
float16_t | arm_weighted_sum_f16 (const float16_t *in, const float16_t *weigths, uint32_t blockSize) |
Weighted sum. | |
float32_t | arm_weighted_sum_f32 (const float32_t *in, const float32_t *weigths, uint32_t blockSize) |
Weighted sum. | |
float16_t | arm_weighted_average_f16 (const float16_t *in, const float16_t *weigths, uint32_t blockSize) |
Weighted average. | |
float32_t | arm_weighted_average_f32 (const float32_t *in, const float32_t *weigths, uint32_t blockSize) |
Weighted average. | |
Weighted sum of values
+Weighted average of values