Support type placeholders that translate to C++ template functions

Issue #5 new
Szabolcs Horvát repo owner created an issue

Right now, arbitrary dimensional tensors are supported, but not arbitrary type tensors.

Both {Integer, 2} and {Integer, _} are valid tensor types. {_, 2} and {_, _} are not valid in LTemplate (they are valid in plain LibraryLink).

There should be a way to allow generic base types for tensors, images and raw arrays. These would translate to C++ templates. Need to find a good API for this.

Idea 1

LFun["fun", {{AnyType[], 2}}, Integer]

would expect this on the C++ side:

template<typename T>
mint fun(mma::TensorRef<T> arg1);

Separate top level LibraryLink functions will be generated for the Integer, Real and Complex cases:

extern "C" DLLEXPORT int MyClass_fun_Integer(WolframLibraryData libData, mint Argc, MArgument * Args, MArgument Res) {
    ...
    ... = (MyClass_collection[id])->fun<mint>(var1);
    ...
}

extern "C" DLLEXPORT int MyClass_fun_Real(WolframLibraryData libData, mint Argc, MArgument * Args, MArgument Res) {
    ...
    ... = (MyClass_collection[id])->fun<double>(var1);
    ...
}

extern "C" DLLEXPORT int MyClass_fun_Complex(WolframLibraryData libData, mint Argc, MArgument * Args, MArgument Res) {
    ...
    ... = (MyClass_collection[id])->fun<mma::complex_t>(var1);
    ...
}

To avoid forcing template instantiations that would cause errors, it should be possible to restrict the types that are allowed on the Mathematica side, e.g. AnyType[{Real, Integer}] would only allow Real and Integer, but not Complex.

It should work similarly for e.g. LibraryDataType[Image, AnyType[]], but this time AnyType represents types allowed in images, such as "Bit", "Byte", "Bit16", etc.

Similar again for LibraryDataType[RawArray, AnyType[]].

To handle all these cases consistently, it may be good to internally translate the old tensor notation {type, rank} to the new standard LibraryDataType[List, type, rank] form.

This feature might lead to an explosive number of library functions being generated, so may become important to implement lazy loading: #4

The most prominent use case of generic types is images. There is already a LibraryLink demo which handles different image types through templates. Need to check about other special properties of images (such as interleaving) to see if anything else ought to be templated.

Comments (5)

  1. Szabolcs Horvát reporter

    Idea 2

    Idea 1 won't work because we need to be able to create templates where the types of different arguments match each other. The function template specification should be analogous to what one would use in C++, with type placeholders.

    Proposed syntax:

    {t1 : Integer|Real, t2 : Real } :> LFun["myfun", {{t1, 1, "Constant"}, t2}, {t1, 2}]
    

    This effectively translates to

    {
     LFun["myfun_Integer_Real", {{Integer, 1, "Constant"}, Real}, {Integer, 2}], 
     LFun["myfun_Real_Real", {{Real, 1, "Constant"}, Real}, {Real, 2}]
    }
    

    On the C++ side we write

    template<typename T1, typename T2>
    mma::MatrixRef<T1> myfun(mma::TensorRef<T1> var1, T2 var2) {
        ...
    }
    

    An advantage of this notation is that syntax highlighting will mark t1 and t2 on the RHS of :>. These symbols are also held unevaluated, at least when :> is used instead of ->.

    Later this syntax can potentially be expanded to LClass instead of restricting it to LFun.

    Validation should be done in two steps: validate as is, then validate after expanding to multiple LFun.

  2. Log in to comment