5
$\begingroup$

Suppose I have a big integer from some library such as GMP. I need to return this from a LibraryLink function. What is the most efficient way to do it?

The simplest way is to convert it to a string stringRepr then use MathLink to send ToExpression[stringRepr]. Is there a more direct way, using the binary representation? Is there a way that avoids the need to send an explicit ToExpression?

$\endgroup$
  • 2
    $\begingroup$ How are bigints sent the other way? $\endgroup$ – Roman Jun 4 at 11:41
  • $\begingroup$ @Roman That's a reasonable thought, but it seems that different functions return the result in different formats. However, if MLGetData returns it in a textual form, that would hint that MLPutData must send it in the same form. $\endgroup$ – Szabolcs Jun 4 at 12:03
4
$\begingroup$

The following sequence of calls appears to work:

const char *stringRepr = "123456";

MLPutNext(link, MLTKINT); /* put an integer */
MLPutSize(link, strlen(stringRepr));
MLPutData(link, stringRepr, strlen(stringRepr));

It was not originally clear to me that MLPutData must send a string representation of the integer. This is mentioned in the J/Link documentation, but I was unable to find it in the documentation of the C MathLink API.

It is still not clear to me why an MLPutSize is necessary if we need to specify the size in MLPutData as well. Perhaps this is because the data can be sent in multiple chunks with multiple MLPutData calls?


Finally, a question is if this is indeed the most efficient way. It seems like a clean way because it avoids ToExpression. But simply returning a string with LibraryLink (not through MathLink), then applying ToExpression afterwards seems to be about 2x faster than sending the textual representation of a large integer through MathLink.

Do[returnBigintML[], {1000}] // RepeatedTiming
(* {0.0073, Null} *)

Do[ToExpression[returnStringLL[]]], {1000}] // RepeatedTiming
(* {0.0037, Null} *)

Related:


Update based on the comment of @ihojnicki. This also works:

MLPutType(link, MLTKINT);
MLPutString(link, stringRepr);
$\endgroup$
  • 3
    $\begingroup$ It is easier to use MLPutType() followed by MLPutString() and friends. $\endgroup$ – ihojnicki Jun 4 at 12:18
  • 1
    $\begingroup$ @ihojnicki Thank you, this works. I am struggling with MathLink because I am missing the conceptual foundations. It would be useful to explain these in the documentation. In this case, I assumed that MLPutString can only put the String datatype. It seems this is not true. It can put a string representation of anything. The actual type is indicated with MLPutType. $\endgroup$ – Szabolcs Jun 4 at 12:38
  • $\begingroup$ @ihojnicki But now I do not understand what the difference is between MLPutType and MLPutNext. It's also not clear what are the valid sequences of calls in cases when multiple functions need to be used together. $\endgroup$ – Szabolcs Jun 4 at 12:40
  • 1
    $\begingroup$ I believe MLPutNext is the precursor to MLPutType, but I'd have to glance through the code. That is probably not going to happen today though. $\endgroup$ – ihojnicki Jun 4 at 18:07
  • $\begingroup$ @ihojnicki In this context, they both appear to work. If you do figure out the difference, here's the question: mathematica.stackexchange.com/q/199714/12 $\endgroup$ – Szabolcs Jun 4 at 18:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.