# Lapack

**URL:** <https://swi-prolog.discourse.group/t/lapack/7070>\
**Category:** General\
**Created:** [December 15, 2023, 8:17am UTC](https://swi-prolog.discourse.group/t/lapack/7070 "2023-12-15T08:17:42Z")\
**Posts on this page:** 2\
**Page:** 3

<div class="post-metadata">

**Author:** ![mgondan1](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/mgondan1/32/803_2.png) [@mgondan1](https://swi-prolog.discourse.group/u/mgondan1)\
**Post date:** [January 8, 2024, 11:54am UTC](https://swi-prolog.discourse.group/t/lapack/7070/42 "2024-01-08T11:54:02Z")

</div>

@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:

```prolog
?- 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:

```prolog
?- 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:

```prolog
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.

```

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [January 10, 2024, 11:38pm UTC](https://swi-prolog.discourse.group/t/lapack/7070/43 "2024-01-10T23:38:40Z")

</div>

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);`

> [@mgondan1](#):
>
> C++ PREDICATE(name, arity) macros only catch Prolog exceptions. I have to catch the c++ exceptions myself

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.

[Previous page](https://swi-prolog.discourse.group/t/lapack/7070.md?page=2)
