Lapack

@peter.ludemann
Next interesting observation (probably a feature, not a bug). The C++ PREDICATE(name, arity) macros only catch Prolog exceptions. I have to catch the c++ exceptions myself:

Here, I catch the exception from libarmadillo in the code:

?- matrix(2, 2, A), eye(A), matrix(3, 3, B), ones(B), mult(A, B, M).
ERROR: Domain error: `matrix multiplication: incompatible matrix dimensions: 2x2 and 3x3' expected, found `Matrix(rows=2 cols=2)*Matrix(rows=3 cols=3)'
ERROR: In:
ERROR:   [11] mult(Matrix(rows=2 cols=2),Matrix(rows=3 cols=3),_1990)
ERROR:   [10] '<meta-call>'('<garbage_collected>') <foreign>
ERROR:    [9] toplevel_call('<garbage_collected>') at /usr/lib/swi-prolog/boot/toplevel.pl:1173
?- halt.

Note that control is back at top level.

Here, I don’t catch the exception:

?- matrix(2, 2, A), eye(A), column(3, B), ones(B), mult(A, B, M).
terminate called after throwing an instance of 'std::logic_error'
  what():  matrix multiplication: incompatible matrix dimensions: 2x2 and 3x1
Aborted
$ 

Note that swipl terminated, and I am back at the command prompt.

That is the C++ code:

PREDICATE(mult, 3)
{ PL_blob_t *t1, *t2 ;
  if(A1.is_blob(&t1) && t1 == &matrix && A2.is_blob(&t2) && t2 == &matrix)
  { auto m1 = PlBlobV<Matrix>::cast_ex(A1, matrix) ;
    auto m2 = PlBlobV<Matrix>::cast_ex(A2, matrix) ;

    try
    { mat m = m1->m * m2->m ;
      auto ref = std::unique_ptr<PlBlob>(new Matrix(m)) ;
      return A3.unify_blob(&ref) ;
    }

    catch(std::exception& e)
    { throw PlDomainError(e.what(), PlCompound("*", PlTermv(A1, A2))) ;
    }
  }

  if(A1.is_blob(&t1) && t1 == &matrix && A2.is_blob(&t2) && t2 == &column)
  { auto m1 = PlBlobV<Matrix>::cast_ex(A1, matrix) ;
    auto m2 = PlBlobV<Column>::cast_ex(A2, column) ;
    mat m = m1->m * m2->v ;
    auto ref = std::unique_ptr<PlBlob>(new Matrix(m)) ;
    return A3.unify_blob(&ref) ;
  }

  etc.

About your code for plblas_portray/1:

  • It’s usually considered bad style to use C-style casts, e.g., (PlTerm)a1, because they’re ambiguous as to whether they’re a static_cast or reinterpret_cast (the former only if there exists a conversion operator for the type) – better to use either static_cast<PlTerm>(a1) or the equivalent PlTerm(a1).
  • If you use the macro PREDICATE(plblas_portray, 1), you don’t need to use PlRegister. Also, no need to do PlTerm(a1)A1 is already a PlTerm.
  • You can get the current_output stream by: PlStream s(Scurrent_output);

Yes, that’s a “feature”.
If you want to specifically catch (or ignore) the SWI-Prolog-specific exceptions, there’s the macro PREDICATE_CATCH(error_action), where error_action is a statement; and the class PlExceptionBase, which matches all the SWI-Prolog-specific exceptions.