Last active
January 6, 2019 22:49
-
-
Save charcode78/e2214522cbe709adaa56546b430c2bc2 to your computer and use it in GitHub Desktop.
How-to build: emscripten + gsl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <gsl/gsl_blas.h> | |
int | |
main (void) | |
{ | |
double a[] = { 0.11, 0.12, 0.13, | |
0.21, 0.22, 0.23 }; | |
double b[] = { 1011, 1012, | |
1021, 1022, | |
1031, 1032 }; | |
double c[] = { 0.00, 0.00, | |
0.00, 0.00 }; | |
gsl_matrix_view A = gsl_matrix_view_array(a, 2, 3); | |
gsl_matrix_view B = gsl_matrix_view_array(b, 3, 2); | |
gsl_matrix_view C = gsl_matrix_view_array(c, 2, 2); | |
/* Compute C = A B */ | |
gsl_blas_dgemm (CblasNoTrans, CblasNoTrans, | |
1.0, &A.matrix, &B.matrix, | |
0.0, &C.matrix); | |
printf ("[ %g, %g\n", c[0], c[1]); | |
printf (" %g, %g ]\n", c[2], c[3]); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# This gisted shell script presents linking details when converting C programs into wasm | |
# through kripken's emscripten. In this language convertion, emcc is the tool that will | |
# replace gcc. emconfigure and emmake will replace ./configure and make. It is straight | |
# forward for C language advanced programmers, but it may not # be the case for HTML+CSS+ | |
# Javascript developers. | |
# | |
# The prior readings: | |
# - https://developers.google.com/web/updates/2018/03/emscripting-a-c-library | |
# - https://kripken.github.io/emscripten-site/docs/compiling/Building-Projects.html | |
# Dependencies: | |
# -git, wget,tar | |
# -nodejs | |
INITIAL_DIR=$(pwd) | |
GSL_LATEST_URL="ftp://ftp.gnu.org/gnu/gsl/gsl-latest.tar.gz" | |
GSL_LATEST_FILE="gsl-latest.tar.gz" | |
EMSDK_GIT_URL="https://github.com/juj/emsdk.git" | |
# Download emscripten | |
git clone "$EMSDK_GIT_URL" | |
cd emsdk | |
git pull | |
./emsdk install latest | |
./emsdk activate latest | |
EMMAKE_RUNNABLE=$(find $(pwd) -name 'emmake' | head -n 1) | |
EMCONF_RUNNABLE=$(find $(pwd) -name 'emconfigure' | head -n 1) | |
EMCC___RUNNABLE=$(find $(pwd) -name 'emcc' | head -n 1) | |
# Download gsl | |
cd "$INITIAL_DIR" | |
wget "$GSL_LATEST_URL" --output-document "$GSL_LATEST_FILE" | |
tar xf "$GSL_LATEST_FILE" | |
cd $(find . -maxdepth 1 -type d | grep gsl) | |
$EMCONF_RUNNABLE ./configure | |
$EMMAKE_RUNNABLE make | |
# Compiles any 'main.c' program that depends on gsl like this: | |
# | |
# $ emcc main.c .libs/libgsl.so.23 cblas/*.o -I . -lm | |
# | |
# '.libs/libgsl.so.23' | |
# path to the gsl llvm compiled library | |
# 'cblas/*.o' | |
# pattern that refers to the remaining compiled objs | |
# '-I .' | |
# CFLAGS to include necessary headers from main.c | |
# '-lm' | |
# CFLAGS to include math.h | |
# | |
# PS: it also works fine with gcc like this: | |
# | |
# $ gcc main.c .libs/libgsl.so.23 cblas/*.o -I . -lm | |
# | |
# Runnning llvm-nm on libgsl.so.23 should reveal cblas_x | |
# objects are just referenced but undefined by the library | |
# | |
# $ llvm-nm .libs/libgsl.so.23 | |
# (...) | |
# u atanh | |
# U calloc | |
# U cblas_caxpy # <- NOTE THOSE | |
# U cblas_ccopy # ... and later ones | |
# (...) | |
LIBGSLSO_PATH=$(find . -name 'libgsl.so.23' ) | |
CBLAS_BC_PATH=$(find . -name 'CBLAS' -type d) | |
cp "$INITIAL_DIR/blas-sample.c" . # NOTE: have the c files on the initial directory | |
cp "$INITIAL_DIR/mult-sample.c" . # otherwise move it manualy | |
gcc "$LIBGSLSO_PATH" "$CBLAS_BC_PATH/*.o" blas-sample.c -I . -lm -o blas-sample.js | |
gcc "$LIBGSLSO_PATH" "$CBLAS_BC_PATH/*.o" mult-sample.c -I . -lm -o mult-sample.js | |
node.js blas-sample.js | |
node.js mult-sample.js | |
# Check if the output from node is as expected | |
# Loading the js and wasm on Chrome should also be working fine: | |
# - move the blas-sample.js and blas-sample.wasm to the apache dir | |
# - on the html load blas-sample.js file with <script src='path'> tag | |
# - output should be printed on the console ('ctrl+shift+i') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <gsl/gsl_multimin.h> | |
/* Paraboloid centered on (p[0],p[1]), with | |
scale factors (p[2],p[3]) and minimum p[4] */ | |
double my_f (const gsl_vector *v, void *params) | |
{ | |
double x, y; | |
double *p = (double *)params; | |
x = gsl_vector_get(v, 0); | |
y = gsl_vector_get(v, 1); | |
return p[2] * (x - p[0]) * (x - p[0]) + | |
p[3] * (y - p[1]) * (y - p[1]) + p[4]; | |
} | |
/* The gradient of f, df = (df/dx, df/dy). */ | |
void my_df (const gsl_vector *v, void *params, | |
gsl_vector *df) | |
{ | |
double x, y; | |
double *p = (double *)params; | |
x = gsl_vector_get(v, 0); | |
y = gsl_vector_get(v, 1); | |
gsl_vector_set(df, 0, 2.0 * p[2] * (x - p[0])); | |
gsl_vector_set(df, 1, 2.0 * p[3] * (y - p[1])); | |
} | |
/* Compute both f and df together. */ | |
void my_fdf (const gsl_vector *x, void *params, | |
double *f, gsl_vector *df) | |
{ | |
*f = my_f(x, params); | |
my_df(x, params, df); | |
} | |
int main (void) { | |
size_t iter = 0; | |
int status; | |
const gsl_multimin_fdfminimizer_type *T; | |
gsl_multimin_fdfminimizer *s; | |
/* Position of the minimum (1,2), scale factors | |
10,20, height 30. */ | |
double par[5] = { 1.0, 2.0, 10.0, 20.0, 30.0 }; | |
gsl_vector *x; | |
gsl_multimin_function_fdf my_func; | |
my_func.n = 2; | |
my_func.f = my_f; | |
my_func.df = my_df; | |
my_func.fdf = my_fdf; | |
my_func.params = par; | |
/* Starting point, x = (5,7) */ | |
x = gsl_vector_alloc (2); | |
gsl_vector_set (x, 0, 35.0); | |
gsl_vector_set (x, 1, 27.0); | |
T = gsl_multimin_fdfminimizer_conjugate_fr; | |
s = gsl_multimin_fdfminimizer_alloc (T, 2); | |
gsl_multimin_fdfminimizer_set (s, &my_func, x, 0.01, 1e-14); | |
do | |
{ | |
iter++; | |
status = gsl_multimin_fdfminimizer_iterate (s); | |
if (status) | |
break; | |
status = gsl_multimin_test_gradient (s->gradient, 1e-3); | |
if (status == GSL_SUCCESS) | |
printf ("Minimum found at:\n"); | |
printf ("%5d %.5f %.5f %10.5f\n", iter, | |
gsl_vector_get (s->x, 0), | |
gsl_vector_get (s->x, 1), | |
s->f); | |
} | |
while (status == GSL_CONTINUE && iter < 100); | |
gsl_multimin_fdfminimizer_free (s); | |
gsl_vector_free (x); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment