# How do I return an mcomplex NAN from C++ to Mathematica using LibraryLink?

I need to deliberately return a 'NAN' from a LibraryLink function, which is expected to return mcomplex so it appears as Indeterminate in Mathematica.

MArgument_setComplex(Res, ???);
return LIBRARY_NO_ERROR;


What do I put in ????

• Do you mean something like 0./0.? Jun 20, 2017 at 1:28
• @MichaelE2 Yes something like that. I could define an exception constant double myNaN = 0./0., but I don't know how to turn it into an mcomplex. Jun 20, 2017 at 1:30
• My thought it to divide two complex zeros. If necessary define a variable zero, mcomplex z = {0.,0.}. Or maybe mcomplex zNaN = {0./0., 0./0.}? Jun 20, 2017 at 1:37
• Ok, that works; I didn't realize you could simply define an mcomplex like that. I wonder if that's the "official" way of making it return Indeterminate. Jun 20, 2017 at 1:48

It is not clear to me how well IEEE 754 NaNs or infinities are supported in Mathematica. I have seen values come out as an unusable expression (instead of Indeterminate) when sending them through MathLink. I do not understand when and why this happens, but it's good to keep in mind that NaNs have multiple representations, and there's multiple kinds of them.

You can create a NaN using the nan() function from the math.h header, and insert it into an mcomplex:

double dnan = nan("");
mcomplex cnan = {dnan, dnan};


With LTemplate, this is a bit simpler, as it uses std::complex<double> as the complex type. Thus std::nan("") can automatically be converted to the complex version.

Below is an LTemplate program that tests sending multiple kinds of NaNs in multiple ways (as a simple double, as part of an array, with or without MathLink). I tested it in 10.0.2 and 11.2.0 on OS X, and the result was always Indeterminate instead of an unusable value. Thus, at least on this platform, this seems to be a safe way to pass back an Indeterminate. Perhaps someone can test on other platforms.

SetDirectory@CreateDirectory[];
Needs["LTemplate"]

tem = LClass["NaNDemo",
{
LFun["NaN", {}, Complex],
LFun["quietNaN", {}, Real],
LFun["signalingNaN", {}, Real],
LFun["arrayQuietNaN", {}, {Real, 1}],
LFun["arraySignalingNaN", {}, {Real, 1}],
}
];

code = "
#include <mlstream.h>
#include <cmath>
#include <limits>

struct NaNDemo {
mma::complex_t NaN() { return std::nan(\"\"); }

double quietNaN() { return std::numeric_limits<double>::quiet_NaN(); }
double signalingNaN() { return std::numeric_limits<double>::signaling_NaN(); }

ml >> mlCheckArgs(0);
ml.newPacket();
ml << quietNaN();
}

ml >> mlCheckArgs(0);
ml.newPacket();
ml << signalingNaN();
}

mma::RealTensorRef arrayQuietNaN() {
auto vec = mma::makeVector<double>(1);
vec[0] = quietNaN();
return vec;
}

mma::RealTensorRef arraySignalingNaN() {
auto vec = mma::makeVector<double>(1);
vec[0] = signalingNaN();
return vec;
}

ml >> mlCheckArgs(0);
ml.newPacket();
ml << std::vector<double>({quietNaN()});
}

ml >> mlCheckArgs(0);
ml.newPacket();
ml << std::vector<double>({signalingNaN()});
}
};";
Export["NaNDemo.h", code, "String"]

CompileTemplate[tem,
"CompileOptions" -> {"-mmacosx-version-min=10.9"}]

obj = Make[NaNDemo];

obj@"NaN"[]
(* Indeterminate *)

obj@"quietNaN"[]
(* Indeterminate *)

obj@"signalingNaN"[]
(* Indeterminate *)

obj@"quietNaNML"[]
(* Indeterminate *)

obj@"signalingNaNML"[]
(* Indeterminate *)

obj@"arrayQuietNaN"[]
(* {Indeterminate} *)

obj@"arraySignalingNaN"[]
(* {Indeterminate} *)

obj@"arrayQuietNaNML"[]
(* {Indeterminate} *)

obj@"arraySignalingNaNML"[]
(* {Indeterminate} *)
`