Simple code generation
This tutorial aims at presenting the new Scilab Code Generator:
https://atoms.scilab.org/toolboxes/xcos_code_generator/
More details on:
https://www.scilab.org/software/atoms/scilab-code-generator
Simple example: Gaussian filter
A gaussian filter s a filter whose impulse response is a Gaussian function (Wikipedia)
Let us write a simple script describing the call of a gaussian filter, on a matrix B of size 10x10.
function B=gauss_filter_3_3(A)
x=size(A,2);
y=size(A,1);
B = zeros(y, x);
for j = 2:y-1
for i= 2:x-1
val= 4*A(j,i)+2*(A(j,i-1)+A(j,i+1)+A(j+1,i)+A(j-1,i))+A(j+1,i+1)+A(j-1,i+1)+A(j+1,i-1)+A(j-1,i-1);
B(j,i) = val/16;
end
end
endfunction
A = rand(10, 10) * 256;
B = gauss_filter_3_3(A);
If you represent A & B with the function Matplot, you will clearly understand the impact of the Gaussian filter function:
(A is on the left, and B on the right)
Also, you can have a look at the data in the variable editor:
First important thing to notice is that you need to clarify the calling sequences of the code you aim at generating. You cannot simply generate a function (or a .sci file). The code generator needs to know here that the gauss_filter function will be called by a matrix of double with a size 10x10.
Once the calling sequences is clarified, you can generate the code:
--> emx_codegen('gauss_filter.sce') Generating files in C:\Users\badmo\AppData\Local\Temp\SCI_TMP_11348_18407\build Using Emmtrix CodeGen latest version emmtrix Code Generator (Oct 26 2017 01,14,08) gauss_filter.sce(14,1-2), W00053 Warning, Variable B not used. B = gauss_filter_3_3(A); ~ Value Range Coverage, 147/147 Memory Stats, 8 stack, 0 heap, 0 global Compile time, 160 ms Build succeeded ... 0 error(s), 1 warning(s), 0 note(s) Retrieving file Makefile.gen Retrieving file emx_codegen.h Retrieving file emx_codegen_intern.h Retrieving file emx_codegen_rand.c Retrieving file emx_codegen_rand.h Retrieving file gauss_filter.c Retrieving file gauss_filter.c.map Retrieving file gauss_filter.d Retrieving file gauss_filter.h Retrieving file gauss_filter.h.map Retrieving file gauss_filter.html Retrieving file gauss_filter.sce ans = []
The code generator is quite chatty. You can see that many results are returned in a folder called build by default. This is how the generated code looks like:
Display the output
If you now simply add a call to the variable B at the last line of your Scilab script and regenerate the code, you will end up with this:
// Automatically generated by emmtrix Code Generator (Oct 26 2017 01:14:08)
// Installation: /srv/www/codegen.service.emmtrix.com/install/20180209/Build/x86_64-unknown-linux-gnu-Release/../..
// Command Line Arguments: gauss_filter.sce --makefile=gnumake --report-includefiles=1
// Output Language: C99 (ISO/IEC 9899:1999)
#include
#include
#include
#include
#include "emx_codegen.h"
#include "emx_codegen_rand.h"
#include "gauss_filter.h"
void gauss_filter_3_3(double B_data[10][10], double A_data[10][10]) {
size_t i1, i2, i3, i4;
double val_data;
// gauss_filter.sce(4:4-20): B = zeros(y, x);
#pragma EMX_KILLVAR B_data
for (i2 = 0; i2 < 10; i2++) {
for (i1 = 0; i1 < 10; i1++) {
B_data[i2][i1] = 0;
}
}
// gauss_filter.sce(5-10): for j = 2:y-1
for (i3 = 0; i3 < 8; i3++) {
// gauss_filter.sce(6-9): for i= 2:x-1
for (i4 = 0; i4 < 8; i4++) {
// gauss_filter.sce(7:12-110): val= 4*A(j,i)+2*(A(j,i-1)+A(j,i+1)+A(j+1,i)+A(j-1,i))+A(j+1,i+1)+A(j-1,i+1)+A(j+1,i-1)+A(j-1,i-1);
val_data = 4.0 * A_data[(int32_t )(i4) + 1][(int32_t )(i3) + 1] + 2.0 * (A_data[(int32_t )(i4)][(int32_t )(i3) + 1] + A_data[(int32_t )(i4) + 2][(int32_t )(i3) + 1] + A_data[(int32_t )(i4) + 1][(int32_t )(i3) + 2] + A_data[(int32_t )(i4) + 1][(int32_t )(i3)]) + A_data[(int32_t )(i4) + 2][(int32_t )(i3) + 2] + A_data[(int32_t )(i4) + 2][(int32_t )(i3)] + A_data[(int32_t )(i4)][(int32_t )(i3) + 2] + A_data[(int32_t )(i4)][(int32_t )(i3)];
// gauss_filter.sce(8:12-28): B(j,i) = val/16;
B_data[(int32_t )(i4) + 1][(int32_t )(i3) + 1] = val_data / 16.0;
}
}
}
int main() {
static double A_data[10][10], B_data[10][10];
size_t i1, i2, i3, i4;
// gauss_filter.sce(13:1-24): A = rand(10, 10) * 256;
#pragma EMX_KILLVAR A_data
for (i2 = 0; i2 < 10; i2++) {
for (i1 = 0; i1 < 10; i1++) {
A_data[i2][i1] = EMX_rand_urand() * 256.0;
}
}
// gauss_filter.sce(14:1-25): B = gauss_filter_3_3(A);
gauss_filter_3_3(B_data, A_data);
// gauss_filter.sce(15:1-2): B
puts("B = ");
for (i3 = 0; i3 < 10; i3++) {
for (i4 = 0; i4 < 10; i4++) {
printf(" %11.6g", B_data[i4][i3]);
}
puts("");
}
return 0;
}
Compile your code
You can compile this C code, and verify that it is working well:
(Pay attention: in this example, the random function as been generated as well, and needs to be attached to the program).
You can also create a windows (64bits) executable with this command:
x86_64-w64-mingw32-gcc -o gauss.exe gauss_filter.c emx_codegen_rand.c
Read more here: