// build:
// g++ -std=c++11 -g -L</path/to/libjulia-debug.so> julia_example.cpp
// -ljulia-debug -o julia_example
// run:
// JULIA_ENV_PATH=</path/to/julia/environment> \
// LD_LIBRARY_PATH=</path/to/julia/lib>:$LD_LIBRARY_PATH \
// julia_example </path/to/julia/source.jl>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <cstring>
#include <cerrno>
#include <cstdio>
#include <boost/spirit/include/karma.hpp>
// -----------------------------------------------------------------
// Provide external definitions of the functions we are using from
// the libjulia.so
struct jl_value_t;
extern "C" {
void jl_init(char *julia_home_dir);
void *jl_eval_string(char *str);
void *jl_unbox_voidpointer(jl_value_t *v);
}
// ------------------------------------------------------------------
// Print a vector<double> as an (m x n) matrix assuming it is stored
// in the vector in column major order.
void printMatrix(std::vector<double> &A, size_t m, size_t n)
{
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
if (j == n - 1)
std::printf("% .5f\n", A[i + (m * j)]);
else
std::printf("% .5f ", A[i + (m * j)]);
}
// ------------------------------------------------------------------
// Read the entire contents of a file into a character vector.
void fileToString(char *filename, std::vector<char> &buf)
{
std::streampos fileLength;
std::ifstream file(filename);
if (not file) {
std::cerr << "Error opening file: "
<< std::strerror(errno) << std::endl;
exit (1);
}
file.seekg(0, std::ios::end);
fileLength = file.tellg();
file.seekg(0, std::ios::beg);
buf.resize(fileLength);
file.read(&buf[0], fileLength);
}
int main(int argc, char **argv)
{
namespace karma = boost::spirit::karma;
void *ans;
void *svdPtr;
char *juliaEnvPath;
std::vector<char> juliaCodeBuf;
// ----------------------------------------------------------------
// get the julia enviroment path from env variables
juliaEnvPath = getenv("JULIA_ENV_PATH");
if (NULL == juliaEnvPath) {
std::cerr << "JULIA_ENV_PATH not found in Env Vars" << std::endl;
exit (1);
}
// ----------------------------------------------------------------
// read in Julia source from file passed as arg 1
fileToString(argv[1], juliaCodeBuf);
// ----------------------------------------------------------------
// instanciate the Julia environment and evaluate source
jl_init(juliaEnvPath);
ans = jl_eval_string(&juliaCodeBuf[0]);
if (NULL == ans) {
std::cerr << "Error parsing julia source file" << std::endl;
exit (1);
}
// ----------------------------------------------------------------
// unbox the pointer to the function and cast with appropriate sig
// int svd(double *A, size_t *m, size_t *n,
// double *U, double *S, double *V);
svdPtr = jl_unbox_voidpointer((jl_value_t*)ans);
auto svd = (int (*)(double*, size_t*, size_t*,
double*, double*, double*)) svdPtr;
// ----------------------------------------------------------------
// test that svd is working.
size_t m = 3, n = 2;
std::vector<double> A = {1.0, 1.0, sqrt(3.0), -1.0, -1.0, 0.0};
std::vector<double> U(m*n);
std::vector<double> S(1*n);
std::vector<double> V(n*n);
svd(&A[0], &m, &n, &U[0], &S[0], &V[0]);
std::cout << "A:" << std::endl;
printMatrix(A, m, n);
std::cout << "U:" << std::endl;
printMatrix(U, n, n);
std::cout << "S:" << std::endl;
printMatrix(S, 1, n);
std::cout << "V:" << std::endl;
printMatrix(V, n, n);
return (0);
}