Added LTemplate files.
This commit is contained in:
parent
d55ac90d9e
commit
732ab6f600
13
LTemplate.m
Normal file
13
LTemplate.m
Normal file
@ -0,0 +1,13 @@
|
||||
(* ::Package:: *)
|
||||
|
||||
(* This is a traditional package that uses BeginPackage instead of Package.
|
||||
It loads LTemplate into the correct context. *)
|
||||
|
||||
BeginPackage["TestPackage`"]
|
||||
|
||||
Print[$InputFileName]
|
||||
|
||||
Get["`LTemplate`LTemplatePrivate`"];
|
||||
ConfigureLTemplate["MessageSymbol" -> TestPackageSym, "LazyLoading" -> False]
|
||||
|
||||
EndPackage[]
|
116
LTemplate/Documentation/Examples/Armadillo/Arma.h
Normal file
116
LTemplate/Documentation/Examples/Armadillo/Arma.h
Normal file
@ -0,0 +1,116 @@
|
||||
#include <LTemplate.h>
|
||||
|
||||
// Let Armadillo print to Mathematica notebooks by default
|
||||
#define ARMA_COUT_STREAM mma::mout
|
||||
#define ARMA_CERR_STREAM mma::mout
|
||||
#include <armadillo>
|
||||
|
||||
// We start by defining conversion functions to/from Armadillo's basic datatypes:
|
||||
// matrices, column vectors and sparse matrices.
|
||||
|
||||
// Armadillo stores matrices in column major order, while Mathematica uses row-major order.
|
||||
// It is thus fastest to convert an MTensor to/from its transposed Armadillo equivalent.
|
||||
|
||||
// Convert from Mathematica matrix to the transposed Armadillo equivalent without copying any data.
|
||||
template<typename T>
|
||||
arma::Mat<T> toArmaTransposed(mma::MatrixRef<T> m) {
|
||||
// wrap MTensor with arma::mat without copying
|
||||
// See the "Advanced Constructors" documentation http://arma.sourceforge.net/docs.html#Mat
|
||||
return arma::Mat<T>(m.data(), m.cols(), m.rows(), false /* do not copy */, false /* until resized */);
|
||||
}
|
||||
|
||||
// Convert from Armadillo matrix to transposed Mathematica matrix.
|
||||
// This time the data must be copied.
|
||||
template<typename T>
|
||||
mma::TensorRef<T> fromArmaTransposed(const arma::Mat<T> &m) {
|
||||
return mma::makeMatrix<T>(m.n_cols, m.n_rows, m.memptr());
|
||||
}
|
||||
|
||||
// Convert from Mathematica vector to Armadillo column vector without copying.
|
||||
template<typename T>
|
||||
arma::Col<T> toArmaVec(mma::TensorRef<T> v) {
|
||||
return arma::Col<T>(v.data(), v.size(), false /* do not copy */, false /* until resized */);
|
||||
}
|
||||
|
||||
// Convert from Armadillo column vector to Mathematica vector with copying.
|
||||
template<typename T>
|
||||
mma::TensorRef<T> fromArmaVec(const arma::Col<T> &v) {
|
||||
return mma::makeVector<T>(v.size(), v.memptr());
|
||||
}
|
||||
|
||||
// Convert from Mathematica sparse matrix to Armadillo sparse matrix.
|
||||
template<typename T>
|
||||
arma::SpMat<T> toArmaSparseTransposed(mma::SparseMatrixRef<T> sm) {
|
||||
return arma::SpMat<T>(
|
||||
// Column indices and row pointers must be explicitly converted
|
||||
// because Armadillo uses unsigned integers while Mathematica uses signed ones.
|
||||
arma::conv_to<arma::uvec>::from(toArmaVec(sm.columnIndices())) - 1, // convert to 0-based indices; Mathematica uses 1-based ones.
|
||||
arma::conv_to<arma::uvec>::from(toArmaVec(sm.rowPointers())),
|
||||
toArmaVec(sm.explicitValues()),
|
||||
sm.cols(), sm.rows()
|
||||
);
|
||||
}
|
||||
|
||||
// Convert from Armadillo sparse matrix to Mathematica SparseArray.
|
||||
template<typename T>
|
||||
mma::SparseMatrixRef<T> fromArmaSparse(const arma::SpMat<T> &am) {
|
||||
// there are am.n_nonzero explicitly stored elements in am
|
||||
auto pos = mma::makeMatrix<mint>(am.n_nonzero, 2); // positions array
|
||||
auto vals = mma::makeVector<double>(am.n_nonzero); // values array
|
||||
|
||||
// iterate through all explicitly stored elements in the Armadillo sparse matrix and
|
||||
// fill out the positions and values arrays to be used in the creation of a Mathematica SparseArray
|
||||
mint i = 0;
|
||||
for (typename arma::SpMat<T>::const_iterator it = am.begin();
|
||||
it != am.end();
|
||||
++it, ++i)
|
||||
{
|
||||
vals[i] = *it;
|
||||
pos(i,0) = it.row() + 1; // convert 0-based index to 1-based
|
||||
pos(i,1) = it.col() + 1;
|
||||
}
|
||||
|
||||
auto mm = mma::makeSparseMatrix(pos, vals, am.n_rows, am.n_cols);
|
||||
|
||||
pos.free();
|
||||
vals.free();
|
||||
|
||||
return mm;
|
||||
}
|
||||
|
||||
class Arma {
|
||||
public:
|
||||
// Matrix inverse
|
||||
mma::RealMatrixRef inv(mma::RealMatrixRef mat) {
|
||||
arma::mat m = toArmaTransposed(mat);
|
||||
return fromArmaTransposed<double>(arma::inv(m));
|
||||
}
|
||||
|
||||
// The first k complex eigenvalues of a sparse matrix
|
||||
mma::ComplexTensorRef eigs(mma::SparseMatrixRef<double> sm, mint k) {
|
||||
return fromArmaVec<mma::complex_t>(arma::eigs_gen(toArmaSparseTransposed(sm), k));
|
||||
}
|
||||
|
||||
// Random sparse matrix
|
||||
mma::SparseMatrixRef<double> sprandu(mint i, mint j, double dens) {
|
||||
return fromArmaSparse(arma::sprandu<arma::sp_mat>(i, j, dens));
|
||||
}
|
||||
|
||||
// Solve a linear equation
|
||||
mma::RealTensorRef solve(mma::RealMatrixRef mat, mma::RealTensorRef vec) {
|
||||
return fromArmaVec<double>(
|
||||
arma::solve(toArmaTransposed(mat).t(), // transpose back to match mat
|
||||
toArmaVec(vec))
|
||||
);
|
||||
}
|
||||
|
||||
// Print an Armadillo matrix
|
||||
void print(mma::RealMatrixRef mat) {
|
||||
mma::mout << toArmaTransposed(mat).t();
|
||||
}
|
||||
|
||||
// Print an Armadillo sparse matrix
|
||||
void printSparse(mma::SparseMatrixRef<double> sm) {
|
||||
mma::mout << toArmaSparseTransposed(sm);
|
||||
}
|
||||
};
|
1137
LTemplate/Documentation/Examples/Armadillo/Armadillo.nb
Normal file
1137
LTemplate/Documentation/Examples/Armadillo/Armadillo.nb
Normal file
File diff suppressed because it is too large
Load Diff
82
LTemplate/Documentation/Examples/BGraph/BGraph.h
Normal file
82
LTemplate/Documentation/Examples/BGraph/BGraph.h
Normal file
@ -0,0 +1,82 @@
|
||||
|
||||
#include <LTemplate.h>
|
||||
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/isomorphism.hpp>
|
||||
#include <boost/graph/boyer_myrvold_planar_test.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
// Graph class based on the Boost Graph Library
|
||||
class BGraph {
|
||||
using graph = boost::adjacency_list<
|
||||
boost::vecS, boost::vecS, boost::undirectedS,
|
||||
boost::property<boost::vertex_index_t, mint>,
|
||||
boost::property<boost::edge_index_t, mint>
|
||||
>;
|
||||
|
||||
using edge_iterator = boost::graph_traits<graph>::edge_iterator;
|
||||
using edge_descriptor = boost::graph_traits<graph>::edge_descriptor;
|
||||
|
||||
graph g; // for simplicity, initialize with an empty graph
|
||||
|
||||
public:
|
||||
|
||||
// Set vertices and edges.
|
||||
// Expected input: edge list with 0-based vertex indices.
|
||||
void set(mint vcount, mma::IntMatrixRef elist) {
|
||||
if (elist.cols() != 2)
|
||||
throw mma::LibraryError("The edge list must be an n-by-2 matrix.");
|
||||
|
||||
g = graph(vcount); // create graph with appropriate number of edges
|
||||
|
||||
auto e_index = get(boost::edge_index, g);
|
||||
for (int i=0; i < elist.rows(); ++i) {
|
||||
auto aer = boost::add_edge(elist(i,0), elist(i,1), g); // add edge
|
||||
put(e_index, aer.first, i); // initialize the interior edge index
|
||||
}
|
||||
}
|
||||
|
||||
// Vertex count.
|
||||
mint vcount() const { return boost::num_vertices(g); }
|
||||
|
||||
// Edge count.
|
||||
mint ecount() const { return boost::num_edges(g); }
|
||||
|
||||
// Retrive edge list.
|
||||
// Output: edge list with 0-based vertex indices.
|
||||
mma::IntMatrixRef edgeList() const {
|
||||
auto elist = mma::makeMatrix<mint>(ecount(), 2);
|
||||
edge_iterator ei, ei_end;
|
||||
for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) {
|
||||
const auto i = get(boost::edge_index, g, *ei);
|
||||
elist(i,0) = source(*ei, g);
|
||||
elist(i,1) = target(*ei, g);
|
||||
}
|
||||
return elist;
|
||||
}
|
||||
|
||||
// Isomorphism test
|
||||
bool isomorphicQ(const BGraph &bg) const { return boost::isomorphism(g, bg.g); }
|
||||
|
||||
// Compute Kuratowski subdivison of non-planar graph
|
||||
mma::IntTensorRef kuratowskiSubdivision() const {
|
||||
|
||||
std::vector<edge_descriptor> kuratowski_edges;
|
||||
|
||||
boost::boyer_myrvold_planarity_test(
|
||||
boost::boyer_myrvold_params::graph = g,
|
||||
boost::boyer_myrvold_params::kuratowski_subgraph = std::back_inserter(kuratowski_edges)
|
||||
);
|
||||
|
||||
auto edge_indices = mma::makeVector<mint>(kuratowski_edges.size());
|
||||
std::transform(
|
||||
kuratowski_edges.begin(), kuratowski_edges.end(),
|
||||
edge_indices.begin(),
|
||||
[this] (edge_descriptor ed) { return get(boost::edge_index, g, ed); }
|
||||
);
|
||||
return edge_indices;
|
||||
}
|
||||
};
|
985
LTemplate/Documentation/Examples/BGraph/BGraph.nb
Normal file
985
LTemplate/Documentation/Examples/BGraph/BGraph.nb
Normal file
@ -0,0 +1,985 @@
|
||||
Notebook[{
|
||||
|
||||
Cell[CellGroupData[{
|
||||
Cell["Interfacing with the Boost Graph Library", "Section",
|
||||
ExpressionUUID -> "aa884a08-8724-4a0b-bbe5-6894c36af936"],
|
||||
|
||||
Cell["\<\
|
||||
This example shows how to create a class that represents a graph, and run \
|
||||
various algorithms on it using the Boost Graph Library.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "0ef29b79-5af8-4918-8a14-11a8a85e43d4"],
|
||||
|
||||
Cell[BoxData[{
|
||||
RowBox[{"Needs", "[", "\"\<LTemplate`\>\"", "]"}], "\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"SetDirectory", "@",
|
||||
RowBox[{"NotebookDirectory", "[", "]"}]}], ";"}]}], "Input",
|
||||
ExpressionUUID -> "978a9ae9-dee6-4995-ac77-77a4bd3103c3"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"template", "=", "\[IndentingNewLine]",
|
||||
RowBox[{"LClass", "[",
|
||||
RowBox[{"\"\<BGraph\>\"", ",", "\[IndentingNewLine]",
|
||||
RowBox[{"{", "\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<set\>\"", ",", "\[IndentingNewLine]",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Integer", " ",
|
||||
RowBox[{"(*", " ",
|
||||
RowBox[{"vertex", " ", "count"}], " ", "*)"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Integer", ",", "2", ",", "\"\<Constant\>\""}], "}"}]}],
|
||||
" ",
|
||||
RowBox[{"(*", " ",
|
||||
RowBox[{"0", "-",
|
||||
RowBox[{"based", " ", "indexed", " ", "edge", " ", "list"}]}],
|
||||
" ", "*)"}], "}"}], ",", "\[IndentingNewLine]", "\"\<Void\>\""}],
|
||||
"\[IndentingNewLine]", "]"}], ",", "\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<vcount\>\"", ",",
|
||||
RowBox[{"{", "}"}], ",", "Integer"}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<ecount\>\"", ",",
|
||||
RowBox[{"{", "}"}], ",", "Integer"}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<edgeList\>\"", ",",
|
||||
RowBox[{"{", "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Integer", ",", "2"}], "}"}]}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<isomorphicQ\>\"", ",", "\[IndentingNewLine]",
|
||||
RowBox[{"{",
|
||||
RowBox[{"LExpressionID", "[", "\"\<BGraph\>\"", "]"}], " ",
|
||||
RowBox[{"(*", " ",
|
||||
RowBox[{"the", " ", "other", " ", "graph"}], " ", "*)"}], "}"}],
|
||||
",", "\[IndentingNewLine]",
|
||||
RowBox[{"True", "|", "False"}]}], "\[IndentingNewLine]", "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<kuratowskiSubdivision\>\"", ",",
|
||||
RowBox[{"{", "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Integer", ",", "1"}], "}"}]}], " ",
|
||||
RowBox[{"(*", " ",
|
||||
RowBox[{"edge", " ", "indices"}], " ", "*)"}], "]"}]}],
|
||||
"\[IndentingNewLine]", "}"}]}], "\[IndentingNewLine]", "]"}]}],
|
||||
";"}]], "Input",
|
||||
ExpressionUUID -> "72378522-fb62-4f9c-8d3f-92fbc6288650"],
|
||||
|
||||
Cell["\<\
|
||||
To compile this example, it is necessary to indicate the location of the \
|
||||
Boost headers. Adjust this according to your system.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "d6d6fe8c-81d4-4580-9546-8cc36aaa6eda"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"CompileTemplate", "[",
|
||||
RowBox[{"template", ",", "\[IndentingNewLine]",
|
||||
RowBox[{"\"\<IncludeDirectories\>\"", "\[Rule]",
|
||||
RowBox[{"{", "\"\</opt/local/include\>\"", "}"}]}]}], " ",
|
||||
RowBox[{"(*", " ",
|
||||
RowBox[{"Boost", " ", "location"}], " ", "*)"}], "\[IndentingNewLine]",
|
||||
"]"}]], "Input",
|
||||
ExpressionUUID -> "a8045402-4022-4ecb-8598-fadac4343f5b"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
InterpretationBox[
|
||||
RowBox[{
|
||||
StyleBox["\<\"Current directory is: \"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\"/Users/szhorvat/Repos/LTemplate/LTemplate/Documentation/\
|
||||
Examples/BGraph\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]}],
|
||||
SequenceForm[
|
||||
Style["Current directory is: ",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style["/Users/szhorvat/Repos/LTemplate/LTemplate/Documentation/Examples/\
|
||||
BGraph",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]]],
|
||||
Editable->False]], "Print",
|
||||
ExpressionUUID -> "26b4ea99-649a-4493-8698-93dea00ec109"],
|
||||
|
||||
Cell[BoxData[
|
||||
InterpretationBox[
|
||||
RowBox[{
|
||||
StyleBox["\<\"Unloading library \"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\"BGraph\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\" ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]}],
|
||||
SequenceForm[
|
||||
Style["Unloading library ",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style["BGraph",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style[" ...",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]]],
|
||||
Editable->False]], "Print",
|
||||
ExpressionUUID -> "26b4ea99-649a-4493-8698-93dea00ec109"],
|
||||
|
||||
Cell[BoxData[
|
||||
StyleBox["\<\"Generating library code ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]], "Print",
|
||||
ExpressionUUID -> "26b4ea99-649a-4493-8698-93dea00ec109"],
|
||||
|
||||
Cell[BoxData[
|
||||
StyleBox["\<\"Compiling library code ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]], "Print",
|
||||
ExpressionUUID -> "26b4ea99-649a-4493-8698-93dea00ec109"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[BoxData["\<\"/Users/szhorvat/Library/Mathematica/SystemFiles/\
|
||||
LibraryResources/MacOSX-x86-64/BGraph.dylib\"\>"], "Output",
|
||||
ExpressionUUID -> "840d4b10-2e8f-4954-8708-8fc124ee6fa1"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LoadTemplate", "[", "template", "]"}]], "Input",
|
||||
ExpressionUUID -> "b54a2e2b-71f0-4352-8b31-66e687bf008f"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell["Create graphs", "Subsubsection",
|
||||
ExpressionUUID -> "d5c63930-33b8-4220-9037-dab8375a7462"],
|
||||
|
||||
Cell["\<\
|
||||
Since LTemplate does not currently support passing arguments to constructors, \
|
||||
the BGraph object is created in two steps:\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "0f5ba9c6-8c9c-4b01-a9df-1db10ffa1d04"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell["Create an empty graph", "Item",
|
||||
ExpressionUUID -> "15fefd58-434d-4b4d-98a1-284f858116e0"],
|
||||
|
||||
Cell["Set edges and vertices", "Item",
|
||||
ExpressionUUID -> "5dbaf41d-e438-46c3-bde4-3ab1a12605fe"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["\<\
|
||||
The following function handles all of this. We will use only this function to \
|
||||
create BGraphs to ensure that they have been correctly initialized.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "443e6f8a-3657-4581-a2fe-f79b14b13a8c"],
|
||||
|
||||
Cell["\<\
|
||||
IndexGraph is not particularly fast, but we shall use it for the sake of \
|
||||
simplicity. The set function expects zero-based indices, therefore we must \
|
||||
subtract 1.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "863c26ce-b730-467b-aa20-a4496c915d92"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"makeBGraph", "[",
|
||||
RowBox[{"g_", "?", "UndirectedGraphQ"}], "]"}], ":=",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"Block", "[",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"bg", "=",
|
||||
RowBox[{"Make", "[", "BGraph", "]"}]}], "}"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"bg", "@",
|
||||
RowBox[{"\"\<set\>\"", "[",
|
||||
RowBox[{
|
||||
RowBox[{"VertexCount", "[", "g", "]"}], ",",
|
||||
RowBox[{
|
||||
RowBox[{"List", "@@@",
|
||||
RowBox[{"EdgeList", "@",
|
||||
RowBox[{"IndexGraph", "[", "g", "]"}]}]}], "-", "1"}]}], "]"}]}],
|
||||
";", "\[IndentingNewLine]", "bg"}]}], "\[IndentingNewLine]",
|
||||
"]"}]}]], "Input",
|
||||
ExpressionUUID -> "a97ac584-7bf7-4cb1-aa00-ee13e8d901c1"],
|
||||
|
||||
Cell["Let\[CloseCurlyQuote]s convert the following graph to a BGraph:", "Text",
|
||||
ExpressionUUID -> "a3d5cb7d-ea6c-4e07-8c71-0841fe32fed4"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"pg", "=",
|
||||
RowBox[{"PetersenGraph", "[", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "34e4f8f6-0463-4722-8961-331d8f3e32d9"],
|
||||
|
||||
Cell[BoxData[
|
||||
GraphicsBox[
|
||||
NamespaceBox["NetworkGraphics",
|
||||
DynamicModuleBox[{Typeset`graph = HoldComplete[
|
||||
Graph[{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {
|
||||
Null, {{1, 3}, {1, 4}, {1, 6}, {2, 4}, {2, 5}, {2, 7}, {3, 5}, {3, 8}, {
|
||||
4, 9}, {5, 10}, {6, 7}, {6, 10}, {7, 8}, {8, 9}, {9, 10}}}, {
|
||||
VertexCoordinates -> {{0.9510565162951535, 0.30901699437494745`}, {
|
||||
0.5877852522924732, -0.8090169943749473}, {-0.587785252292473, \
|
||||
-0.8090169943749476}, {-0.9510565162951536,
|
||||
0.30901699437494723`}, {-2.4492935982947064`*^-16, 1.}, {
|
||||
1.902113032590307, 0.6180339887498949}, {
|
||||
1.1755705045849465`, -1.6180339887498947`}, {-1.175570504584946, \
|
||||
-1.6180339887498951`}, {-1.9021130325903073`,
|
||||
0.6180339887498945}, {-4.898587196589413*^-16, 2.}}}]]},
|
||||
TagBox[
|
||||
GraphicsGroupBox[
|
||||
GraphicsComplexBox[{{0.9510565162951535, 0.30901699437494745`}, {
|
||||
0.5877852522924732, -0.8090169943749473}, {-0.587785252292473, \
|
||||
-0.8090169943749476}, {-0.9510565162951536,
|
||||
0.30901699437494723`}, {-2.4492935982947064`*^-16, 1.}, {
|
||||
1.902113032590307, 0.6180339887498949}, {
|
||||
1.1755705045849465`, -1.6180339887498947`}, {-1.175570504584946, \
|
||||
-1.6180339887498951`}, {-1.9021130325903073`,
|
||||
0.6180339887498945}, {-4.898587196589413*^-16, 2.}}, {
|
||||
{Hue[0.6, 0.7, 0.5], Opacity[0.7],
|
||||
{Arrowheads[0.], ArrowBox[{1, 3}, 0.03574187784409402]},
|
||||
{Arrowheads[0.], ArrowBox[{1, 4}, 0.03574187784409402]},
|
||||
{Arrowheads[0.], ArrowBox[{1, 6}, 0.03574187784409402]},
|
||||
{Arrowheads[0.], ArrowBox[{2, 4}, 0.03574187784409402]},
|
||||
{Arrowheads[0.], ArrowBox[{2, 5}, 0.03574187784409402]},
|
||||
{Arrowheads[0.], ArrowBox[{2, 7}, 0.03574187784409402]},
|
||||
{Arrowheads[0.], ArrowBox[{3, 5}, 0.03574187784409402]},
|
||||
{Arrowheads[0.], ArrowBox[{3, 8}, 0.03574187784409402]},
|
||||
{Arrowheads[0.], ArrowBox[{4, 9}, 0.03574187784409402]},
|
||||
{Arrowheads[0.], ArrowBox[{5, 10}, 0.03574187784409402]},
|
||||
{Arrowheads[0.], ArrowBox[{6, 7}, 0.03574187784409402]},
|
||||
{Arrowheads[0.], ArrowBox[{6, 10}, 0.03574187784409402]},
|
||||
{Arrowheads[0.], ArrowBox[{7, 8}, 0.03574187784409402]},
|
||||
{Arrowheads[0.], ArrowBox[{8, 9}, 0.03574187784409402]},
|
||||
{Arrowheads[0.], ArrowBox[{9, 10}, 0.03574187784409402]}},
|
||||
{Hue[0.6, 0.2, 0.8], EdgeForm[{GrayLevel[0], Opacity[0.7]}],
|
||||
DiskBox[1, 0.03574187784409402], DiskBox[2, 0.03574187784409402],
|
||||
DiskBox[3, 0.03574187784409402], DiskBox[4, 0.03574187784409402],
|
||||
DiskBox[5, 0.03574187784409402], DiskBox[6, 0.03574187784409402],
|
||||
DiskBox[7, 0.03574187784409402], DiskBox[8, 0.03574187784409402],
|
||||
DiskBox[9, 0.03574187784409402], DiskBox[10, 0.03574187784409402]}}]],
|
||||
MouseAppearanceTag["NetworkGraphics"]],
|
||||
AllowKernelInitialization->False]],
|
||||
DefaultBaseStyle->{
|
||||
"NetworkGraphics", FrontEnd`GraphicsHighlightColor -> Hue[0.8, 1., 0.6]},
|
||||
FrameTicks->None,
|
||||
GridLinesStyle->Directive[
|
||||
GrayLevel[0.5, 0.4]]]], "Output",
|
||||
ExpressionUUID -> "2728ee8c-fc48-4a9d-9129-9d80455b0b70"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"bg", "=",
|
||||
RowBox[{"makeBGraph", "[", "pg", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "82e12ead-05f1-41e9-8ae1-4523e471cf24"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"BGraph", "[", "1", "]"}]], "Output",
|
||||
ExpressionUUID -> "8d1730d3-d6fb-4f22-8435-71fc4923c556"]
|
||||
}, Open ]]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell["Retrieve basic properties", "Subsubsection",
|
||||
ExpressionUUID -> "ea7843fc-c17b-4122-b1bb-45dc2250980f"],
|
||||
|
||||
Cell["How many vertices does it have?", "Text",
|
||||
ExpressionUUID -> "1a73c6c9-f664-476f-9973-ff8a64c0d1b4"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"bg", "@",
|
||||
RowBox[{"\"\<vcount\>\"", "[", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "20a28eb0-555f-40c7-8308-e0773b60bb58"],
|
||||
|
||||
Cell[BoxData["10"], "Output",
|
||||
ExpressionUUID -> "fa8d3a82-3793-43d0-845a-8114d20da8ab"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["How many edges does it have?", "Text",
|
||||
ExpressionUUID -> "cca07f74-dd9d-40c6-80d7-dafddcd8a719"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"bg", "@",
|
||||
RowBox[{"\"\<ecount\>\"", "[", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "742a3af0-a9dc-4fa9-a297-e7d4f89885c6"],
|
||||
|
||||
Cell[BoxData["15"], "Output",
|
||||
ExpressionUUID -> "2ba271ae-d759-45eb-97ab-c93ad3fd0c55"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Retrieve the edge list.", "Text",
|
||||
ExpressionUUID -> "77d0c741-8d01-4279-b7d4-cbcb6c98a16c"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"bg", "@",
|
||||
RowBox[{"\"\<edgeList\>\"", "[", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "077bae0c-1dbb-4829-902a-86b4d8068303"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"0", ",", "2"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"0", ",", "3"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"0", ",", "5"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1", ",", "3"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1", ",", "4"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1", ",", "6"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"2", ",", "4"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"2", ",", "7"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"3", ",", "8"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"4", ",", "9"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"5", ",", "6"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"5", ",", "9"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"6", ",", "7"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"7", ",", "8"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"8", ",", "9"}], "}"}]}], "}"}]], "Output",
|
||||
ExpressionUUID -> "7fab54c6-d92f-43ad-a525-a0d1e3db563d"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["\<\
|
||||
Convert to a Mathematica Graph with vertices labelled from 1 (instead of 0).\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "bb99f19b-3ddb-47d7-b9e8-e647810ef431"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"fromBGraph", "[", "bg_BGraph", "]"}], ":=", "\[IndentingNewLine]",
|
||||
|
||||
RowBox[{"Graph", "[",
|
||||
RowBox[{
|
||||
RowBox[{"Range", "[",
|
||||
RowBox[{"bg", "@",
|
||||
RowBox[{"\"\<vcount\>\"", "[", "]"}]}], "]"}], ",",
|
||||
RowBox[{"1", "+",
|
||||
RowBox[{"bg", "@",
|
||||
RowBox[{"\"\<edgeList\>\"", "[", "]"}]}]}], ",",
|
||||
RowBox[{"DirectedEdges", "\[Rule]", "False"}]}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "d48948ea-3ba1-4e1b-af8c-70946e65dca9"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"fromBGraph", "[", "bg", "]"}]], "Input",
|
||||
ExpressionUUID -> "d20d883e-2eae-4153-a2fa-3ac7cd828056"],
|
||||
|
||||
Cell[BoxData[
|
||||
GraphicsBox[
|
||||
NamespaceBox["NetworkGraphics",
|
||||
DynamicModuleBox[{Typeset`graph = HoldComplete[
|
||||
Graph[{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {
|
||||
Null, {{1, 3}, {1, 4}, {1, 6}, {2, 4}, {2, 5}, {2, 7}, {3, 5}, {3, 8}, {
|
||||
4, 9}, {5, 10}, {6, 7}, {6, 10}, {7, 8}, {8, 9}, {9, 10}}}]]},
|
||||
TagBox[
|
||||
GraphicsGroupBox[
|
||||
GraphicsComplexBox[{{1.8750105837989297`, 0.733244241062911}, {
|
||||
1.8415650123658316`, 1.3620813936125686`}, {1.1749364294125422`,
|
||||
0.39951830930753657`}, {0.9014384102184719, 0.9286633426597406}, {
|
||||
1.8190275035455308`, 0.09019481978361599}, {1.2929028389366695`,
|
||||
1.1785381450163794`}, {1.0513121542102433`, 1.9864048777087877`}, {
|
||||
0.27259657017746486`, 1.2771371290432734`}, {0.,
|
||||
0.48128666421627553`}, {0.8106136635018724, 0.}}, {
|
||||
{Hue[0.6, 0.7, 0.5], Opacity[0.7],
|
||||
{Arrowheads[0.], ArrowBox[{1, 3}, 0.02250105963782012]},
|
||||
{Arrowheads[0.], ArrowBox[{1, 4}, 0.02250105963782012]},
|
||||
{Arrowheads[0.], ArrowBox[{1, 6}, 0.02250105963782012]},
|
||||
{Arrowheads[0.], ArrowBox[{2, 4}, 0.02250105963782012]},
|
||||
{Arrowheads[0.], ArrowBox[{2, 5}, 0.02250105963782012]},
|
||||
{Arrowheads[0.], ArrowBox[{2, 7}, 0.02250105963782012]},
|
||||
{Arrowheads[0.], ArrowBox[{3, 5}, 0.02250105963782012]},
|
||||
{Arrowheads[0.], ArrowBox[{3, 8}, 0.02250105963782012]},
|
||||
{Arrowheads[0.], ArrowBox[{4, 9}, 0.02250105963782012]},
|
||||
{Arrowheads[0.], ArrowBox[{5, 10}, 0.02250105963782012]},
|
||||
{Arrowheads[0.], ArrowBox[{6, 7}, 0.02250105963782012]},
|
||||
{Arrowheads[0.], ArrowBox[{6, 10}, 0.02250105963782012]},
|
||||
{Arrowheads[0.], ArrowBox[{7, 8}, 0.02250105963782012]},
|
||||
{Arrowheads[0.], ArrowBox[{8, 9}, 0.02250105963782012]},
|
||||
{Arrowheads[0.], ArrowBox[{9, 10}, 0.02250105963782012]}},
|
||||
{Hue[0.6, 0.2, 0.8], EdgeForm[{GrayLevel[0], Opacity[0.7]}],
|
||||
DiskBox[1, 0.02250105963782012], DiskBox[2, 0.02250105963782012],
|
||||
DiskBox[3, 0.02250105963782012], DiskBox[4, 0.02250105963782012],
|
||||
DiskBox[5, 0.02250105963782012], DiskBox[6, 0.02250105963782012],
|
||||
DiskBox[7, 0.02250105963782012], DiskBox[8, 0.02250105963782012],
|
||||
DiskBox[9, 0.02250105963782012], DiskBox[10, 0.02250105963782012]}}]],
|
||||
MouseAppearanceTag["NetworkGraphics"]],
|
||||
AllowKernelInitialization->False]],
|
||||
DefaultBaseStyle->{
|
||||
"NetworkGraphics", FrontEnd`GraphicsHighlightColor -> Hue[0.8, 1., 0.6]},
|
||||
FrameTicks->None,
|
||||
GridLinesStyle->Directive[
|
||||
GrayLevel[0.5, 0.4]]]], "Output",
|
||||
ExpressionUUID -> "d2a5a57b-d954-4d4d-823c-a3e6f55586e9"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["\<\
|
||||
Verify that it is indeed the same graph, with the same edge ordering:\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "44e63c1f-4e60-443b-9f21-179f10cc5a1b"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"EdgeList", "[",
|
||||
RowBox[{"fromBGraph", "[", "bg", "]"}], "]"}], "===",
|
||||
RowBox[{"EdgeList", "@",
|
||||
RowBox[{"IndexGraph", "[", "pg", "]"}]}]}]], "Input",
|
||||
ExpressionUUID -> "b78cf826-1a21-49e5-af94-3bc3bfc6491a"],
|
||||
|
||||
Cell[BoxData["True"], "Output",
|
||||
ExpressionUUID -> "353d8e39-9b8d-42f9-8651-4b8448051f4a"]
|
||||
}, Open ]]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell["Run graph algorithms", "Subsubsection",
|
||||
ExpressionUUID -> "006201b5-7775-4b41-b5cb-e0a1aa4a1371"],
|
||||
|
||||
Cell["Run the isomorphism algorithm.", "Text",
|
||||
ExpressionUUID -> "7128c8bd-c750-4132-b4f7-c9c7a25bd5e5"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"bg2", "=",
|
||||
RowBox[{"makeBGraph", "[",
|
||||
RowBox[{"GraphData", "[", "\"\<PetersenGraph\>\"", "]"}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "5ada7d10-ff87-4af2-99f5-da05449dc9e1"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"BGraph", "[", "2", "]"}]], "Output",
|
||||
ExpressionUUID -> "5393bb6b-e8ad-4ddb-90b9-b991bc601566"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"bg", "@",
|
||||
RowBox[{"\"\<isomorphicQ\>\"", "[",
|
||||
RowBox[{"ManagedLibraryExpressionID", "[", "bg2", "]"}], "]"}]}]], "Input",
|
||||
|
||||
ExpressionUUID -> "ccda914c-ccd5-4de5-93a5-32f6976820b9"],
|
||||
|
||||
Cell[BoxData["True"], "Output",
|
||||
ExpressionUUID -> "5fadbaa2-c984-4a51-b088-b1bdb4a7d663"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["\<\
|
||||
Wrap the function for convenient isomorphism checking of Mathematica Graphs.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "3f76d1e0-bb97-48ba-935a-037e49f98985"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"isomorphicQ", "[",
|
||||
RowBox[{
|
||||
RowBox[{"g1_", "?", "UndirectedGraphQ"}], ",",
|
||||
RowBox[{"g2_", "?", "UndirectedGraphQ"}]}], "]"}], ":=",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"Block", "[",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"bg1", "=",
|
||||
RowBox[{"makeBGraph", "[", "g1", "]"}]}], ",",
|
||||
RowBox[{"bg2", "=",
|
||||
RowBox[{"makeBGraph", "[", "g2", "]"}]}]}], "}"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"bg1", "@",
|
||||
RowBox[{"\"\<isomorphicQ\>\"", "[",
|
||||
RowBox[{"ManagedLibraryExpressionID", "[", "bg2", "]"}], "]"}]}]}],
|
||||
"\[IndentingNewLine]", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "f1de92a5-ee30-47b7-9e51-06430b8ab0e3"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"isomorphicQ", "[",
|
||||
RowBox[{
|
||||
RowBox[{"Graph", "[",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"1", "\[UndirectedEdge]", "2"}], ",",
|
||||
RowBox[{"2", "\[UndirectedEdge]", "3"}]}], "}"}], "]"}], ",",
|
||||
RowBox[{"Graph", "[",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"1", "\[UndirectedEdge]", "3"}], ",",
|
||||
RowBox[{"2", "\[UndirectedEdge]", "3"}]}], "}"}], "]"}]}],
|
||||
"]"}]], "Input",
|
||||
ExpressionUUID -> "4499c911-4c58-4bbb-abb7-0237457b0473"],
|
||||
|
||||
Cell[BoxData["True"], "Output",
|
||||
ExpressionUUID -> "a02d2212-e6fe-4e70-b330-f78e3a203c0f"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["\<\
|
||||
Let us compute a Kuratowski subdivision of a non-planar graph.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "4c3bc4d3-c457-46c1-a5c0-e8d2d0e63fb9"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"kuratowskiSubdivision", "[",
|
||||
RowBox[{"g_", "?", "UndirectedGraphQ"}], "]"}], ":=",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"Block", "[",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"bg", "=",
|
||||
RowBox[{"makeBGraph", "[", "g", "]"}]}], "}"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"Part", "[",
|
||||
RowBox[{
|
||||
RowBox[{"EdgeList", "[", "g", "]"}], ",",
|
||||
RowBox[{"1", "+",
|
||||
RowBox[{"bg", "@",
|
||||
RowBox[{"\"\<kuratowskiSubdivision\>\"", "[", "]"}]}]}]}], "]"}]}],
|
||||
"\[IndentingNewLine]", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "296d406b-a5ec-4462-b98f-104ed144c9f5"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"npg", "=",
|
||||
RowBox[{"GraphData", "[",
|
||||
RowBox[{"{",
|
||||
RowBox[{"\"\<Cone\>\"", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"4", ",", "7"}], "}"}]}], "}"}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "c263174f-c3e5-4bf3-997e-29138e40b539"],
|
||||
|
||||
Cell[BoxData[
|
||||
GraphicsBox[
|
||||
NamespaceBox["NetworkGraphics",
|
||||
DynamicModuleBox[{Typeset`graph = HoldComplete[
|
||||
Graph[{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, {Null,
|
||||
SparseArray[
|
||||
Automatic, {11, 11}, 0, {
|
||||
1, {{0, 9, 18, 27, 36, 40, 44, 48, 52, 56, 60, 64}, {{2}, {4}, {5}, {
|
||||
6}, {7}, {8}, {9}, {10}, {11}, {1}, {3}, {5}, {6}, {7}, {8}, {9}, {
|
||||
10}, {11}, {2}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {1}, {
|
||||
3}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {1}, {2}, {3}, {4}, {1}, {
|
||||
2}, {3}, {4}, {1}, {2}, {3}, {4}, {1}, {2}, {3}, {4}, {1}, {2}, {
|
||||
3}, {4}, {1}, {2}, {3}, {4}, {1}, {2}, {3}, {4}}}, Pattern}]}]]},
|
||||
TagBox[
|
||||
GraphicsGroupBox[
|
||||
GraphicsComplexBox[{{0.780774697805059, 1.199409711066857}, {
|
||||
1.1999525032799427`, 0.8319430146461535}, {0.8200678462633789,
|
||||
0.7964395160694195}, {1.1631489624818339`, 1.2336554432233262`}, {
|
||||
1.436385194178687, 1.9305572632126569`}, {0., 1.2362392592240465`}, {
|
||||
1.9812731165155193`, 1.2361258172872176`}, {0.9886961315621108, 0.}, {
|
||||
1.7894534978737644`, 0.3840372833294744}, {0.5527059960246021,
|
||||
1.932547584373542}, {0.18951736097760385`, 0.3902718952492563}}, {
|
||||
{Hue[0.6, 0.7, 0.5], Opacity[0.7],
|
||||
{Arrowheads[0.], ArrowBox[{1, 2}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{1, 4}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{1, 5}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{1, 6}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{1, 7}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{1, 8}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{1, 9}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{1, 10}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{1, 11}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{2, 3}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{2, 5}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{2, 6}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{2, 7}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{2, 8}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{2, 9}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{2, 10}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{2, 11}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{3, 4}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{3, 5}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{3, 6}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{3, 7}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{3, 8}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{3, 9}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{3, 10}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{3, 11}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{4, 5}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{4, 6}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{4, 7}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{4, 8}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{4, 9}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{4, 10}, 0.02245933508462397]},
|
||||
{Arrowheads[0.], ArrowBox[{4, 11}, 0.02245933508462397]}},
|
||||
{Hue[0.6, 0.2, 0.8], EdgeForm[{GrayLevel[0], Opacity[0.7]}],
|
||||
DiskBox[1, 0.02245933508462397], DiskBox[2, 0.02245933508462397],
|
||||
DiskBox[3, 0.02245933508462397], DiskBox[4, 0.02245933508462397],
|
||||
DiskBox[5, 0.02245933508462397], DiskBox[6, 0.02245933508462397],
|
||||
DiskBox[7, 0.02245933508462397], DiskBox[8, 0.02245933508462397],
|
||||
DiskBox[9, 0.02245933508462397], DiskBox[10, 0.02245933508462397],
|
||||
DiskBox[11, 0.02245933508462397]}}]],
|
||||
MouseAppearanceTag["NetworkGraphics"]],
|
||||
AllowKernelInitialization->False]],
|
||||
DefaultBaseStyle->{
|
||||
"NetworkGraphics", FrontEnd`GraphicsHighlightColor -> Hue[0.8, 1., 0.6]},
|
||||
FrameTicks->None,
|
||||
GridLinesStyle->Directive[
|
||||
GrayLevel[0.5, 0.4]]]], "Output",
|
||||
ExpressionUUID -> "21ac32cf-65f2-4897-aa63-dbc1bfa803be"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"kuratowskiSubdivision", "[", "npg", "]"}]], "Input",
|
||||
ExpressionUUID -> "505b1e60-9260-43b2-98e3-382c63076f42"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"1", "\[UndirectedEdge]", "2"}], ",",
|
||||
RowBox[{"2", "\[UndirectedEdge]", "5"}], ",",
|
||||
RowBox[{"2", "\[UndirectedEdge]", "6"}], ",",
|
||||
RowBox[{"2", "\[UndirectedEdge]", "7"}], ",",
|
||||
RowBox[{"3", "\[UndirectedEdge]", "5"}], ",",
|
||||
RowBox[{"3", "\[UndirectedEdge]", "6"}], ",",
|
||||
RowBox[{"3", "\[UndirectedEdge]", "7"}], ",",
|
||||
RowBox[{"4", "\[UndirectedEdge]", "5"}], ",",
|
||||
RowBox[{"4", "\[UndirectedEdge]", "6"}], ",",
|
||||
RowBox[{"4", "\[UndirectedEdge]", "7"}]}], "}"}]], "Output",
|
||||
ExpressionUUID -> "f85fa7a7-747b-471e-8058-d86250add82f"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["\<\
|
||||
The function returns it as a list of edge indices, which we transform to an \
|
||||
edge list in Mathematica. Let us visualize it.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "187c2fe1-68a5-4036-bcfc-6616ddc9bfc9"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"HighlightGraph", "[",
|
||||
RowBox[{"npg", ",",
|
||||
RowBox[{"Subgraph", "[",
|
||||
RowBox[{"npg", ",",
|
||||
RowBox[{"kuratowskiSubdivision", "[", "npg", "]"}]}], "]"}]}],
|
||||
"]"}]], "Input",
|
||||
ExpressionUUID -> "6c3bf6da-8056-4946-94f3-93d61584acbf"],
|
||||
|
||||
Cell[BoxData[
|
||||
GraphicsBox[
|
||||
NamespaceBox["NetworkGraphics",
|
||||
DynamicModuleBox[{Typeset`graph = HoldComplete[
|
||||
Graph[{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, {Null,
|
||||
SparseArray[
|
||||
Automatic, {11, 11}, 0, {
|
||||
1, {{0, 9, 18, 27, 36, 40, 44, 48, 52, 56, 60, 64}, {{2}, {4}, {5}, {
|
||||
6}, {7}, {8}, {9}, {10}, {11}, {1}, {3}, {5}, {6}, {7}, {8}, {9}, {
|
||||
10}, {11}, {2}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {1}, {
|
||||
3}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {1}, {2}, {3}, {4}, {1}, {
|
||||
2}, {3}, {4}, {1}, {2}, {3}, {4}, {1}, {2}, {3}, {4}, {1}, {2}, {
|
||||
3}, {4}, {1}, {2}, {3}, {4}, {1}, {2}, {3}, {4}}}, Pattern}]}, {
|
||||
GraphHighlight -> {
|
||||
UndirectedEdge[5, 4],
|
||||
UndirectedEdge[2, 3],
|
||||
UndirectedEdge[7, 4],
|
||||
UndirectedEdge[1, 5],
|
||||
UndirectedEdge[5, 3],
|
||||
UndirectedEdge[7, 3], 1,
|
||||
UndirectedEdge[2, 6], 6, 5,
|
||||
UndirectedEdge[2, 7],
|
||||
UndirectedEdge[1, 7],
|
||||
UndirectedEdge[1, 4],
|
||||
UndirectedEdge[6, 4],
|
||||
UndirectedEdge[1, 2],
|
||||
UndirectedEdge[1, 6], 7, 2,
|
||||
UndirectedEdge[6, 3],
|
||||
UndirectedEdge[3, 4],
|
||||
UndirectedEdge[2, 5], 4, 3}}]]},
|
||||
TagBox[
|
||||
GraphicsGroupBox[
|
||||
GraphicsComplexBox[{{0.780774697805059, 1.199409711066857}, {
|
||||
1.1999525032799427`, 0.8319430146461535}, {0.8200678462633789,
|
||||
0.7964395160694195}, {1.1631489624818339`, 1.2336554432233262`}, {
|
||||
1.436385194178687, 1.9305572632126569`}, {0., 1.2362392592240465`}, {
|
||||
1.9812731165155193`, 1.2361258172872176`}, {0.9886961315621108, 0.}, {
|
||||
1.7894534978737644`, 0.3840372833294744}, {0.5527059960246021,
|
||||
1.932547584373542}, {0.18951736097760385`, 0.3902718952492563}}, {
|
||||
{Hue[0.6, 0.7, 0.5], Opacity[0.7],
|
||||
{Hue[1, 1, 0.7], Opacity[1],
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{0.780774697805059, 1.199409711066857}, {
|
||||
1.1999525032799427`, 0.8319430146461535}}, 0.02245933508462397]}},
|
||||
{Hue[1, 1, 0.7], Opacity[1],
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{0.780774697805059, 1.199409711066857}, {
|
||||
1.1631489624818339`, 1.2336554432233262`}},
|
||||
0.02245933508462397]}},
|
||||
{Hue[1, 1, 0.7], Opacity[1],
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{0.780774697805059, 1.199409711066857}, {
|
||||
1.436385194178687, 1.9305572632126569`}},
|
||||
0.02245933508462397]}},
|
||||
{Hue[1, 1, 0.7], Opacity[1],
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{0.780774697805059, 1.199409711066857}, {0.,
|
||||
1.2362392592240465`}}, 0.02245933508462397]}},
|
||||
{Hue[1, 1, 0.7], Opacity[1],
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{0.780774697805059, 1.199409711066857}, {
|
||||
1.9812731165155193`, 1.2361258172872176`}},
|
||||
0.02245933508462397]}},
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{0.780774697805059, 1.199409711066857}, {
|
||||
0.9886961315621108, 0.}}, 0.02245933508462397]},
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{0.780774697805059, 1.199409711066857}, {
|
||||
1.7894534978737644`, 0.3840372833294744}}, 0.02245933508462397]},
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{0.780774697805059, 1.199409711066857}, {
|
||||
0.5527059960246021, 1.932547584373542}}, 0.02245933508462397]},
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{0.780774697805059, 1.199409711066857}, {
|
||||
0.18951736097760385`, 0.3902718952492563}},
|
||||
0.02245933508462397]},
|
||||
{Hue[1, 1, 0.7], Opacity[1],
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{1.1999525032799427`, 0.8319430146461535}, {
|
||||
0.8200678462633789, 0.7964395160694195}},
|
||||
0.02245933508462397]}},
|
||||
{Hue[1, 1, 0.7], Opacity[1],
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{1.1999525032799427`, 0.8319430146461535}, {
|
||||
1.436385194178687, 1.9305572632126569`}},
|
||||
0.02245933508462397]}},
|
||||
{Hue[1, 1, 0.7], Opacity[1],
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{1.1999525032799427`, 0.8319430146461535}, {0.,
|
||||
1.2362392592240465`}}, 0.02245933508462397]}},
|
||||
{Hue[1, 1, 0.7], Opacity[1],
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{1.1999525032799427`, 0.8319430146461535}, {
|
||||
1.9812731165155193`, 1.2361258172872176`}},
|
||||
0.02245933508462397]}},
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{1.1999525032799427`, 0.8319430146461535}, {
|
||||
0.9886961315621108, 0.}}, 0.02245933508462397]},
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{1.1999525032799427`, 0.8319430146461535}, {
|
||||
1.7894534978737644`, 0.3840372833294744}}, 0.02245933508462397]},
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{1.1999525032799427`, 0.8319430146461535}, {
|
||||
0.5527059960246021, 1.932547584373542}}, 0.02245933508462397]},
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{1.1999525032799427`, 0.8319430146461535}, {
|
||||
0.18951736097760385`, 0.3902718952492563}},
|
||||
0.02245933508462397]},
|
||||
{Hue[1, 1, 0.7], Opacity[1],
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{0.8200678462633789, 0.7964395160694195}, {
|
||||
1.1631489624818339`, 1.2336554432233262`}},
|
||||
0.02245933508462397]}},
|
||||
{Hue[1, 1, 0.7], Opacity[1],
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{0.8200678462633789, 0.7964395160694195}, {
|
||||
1.436385194178687, 1.9305572632126569`}},
|
||||
0.02245933508462397]}},
|
||||
{Hue[1, 1, 0.7], Opacity[1],
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{0.8200678462633789, 0.7964395160694195}, {0.,
|
||||
1.2362392592240465`}}, 0.02245933508462397]}},
|
||||
{Hue[1, 1, 0.7], Opacity[1],
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{0.8200678462633789, 0.7964395160694195}, {
|
||||
1.9812731165155193`, 1.2361258172872176`}},
|
||||
0.02245933508462397]}},
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{0.8200678462633789, 0.7964395160694195}, {
|
||||
0.9886961315621108, 0.}}, 0.02245933508462397]},
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{0.8200678462633789, 0.7964395160694195}, {
|
||||
1.7894534978737644`, 0.3840372833294744}}, 0.02245933508462397]},
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{0.8200678462633789, 0.7964395160694195}, {
|
||||
0.5527059960246021, 1.932547584373542}}, 0.02245933508462397]},
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{0.8200678462633789, 0.7964395160694195}, {
|
||||
0.18951736097760385`, 0.3902718952492563}},
|
||||
0.02245933508462397]},
|
||||
{Hue[1, 1, 0.7], Opacity[1],
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{1.1631489624818339`, 1.2336554432233262`}, {
|
||||
1.436385194178687, 1.9305572632126569`}},
|
||||
0.02245933508462397]}},
|
||||
{Hue[1, 1, 0.7], Opacity[1],
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{1.1631489624818339`, 1.2336554432233262`}, {0.,
|
||||
1.2362392592240465`}}, 0.02245933508462397]}},
|
||||
{Hue[1, 1, 0.7], Opacity[1],
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{1.1631489624818339`, 1.2336554432233262`}, {
|
||||
1.9812731165155193`, 1.2361258172872176`}},
|
||||
0.02245933508462397]}},
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{1.1631489624818339`, 1.2336554432233262`}, {
|
||||
0.9886961315621108, 0.}}, 0.02245933508462397]},
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{1.1631489624818339`, 1.2336554432233262`}, {
|
||||
1.7894534978737644`, 0.3840372833294744}}, 0.02245933508462397]},
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{1.1631489624818339`, 1.2336554432233262`}, {
|
||||
0.5527059960246021, 1.932547584373542}}, 0.02245933508462397]},
|
||||
{Arrowheads[0.],
|
||||
ArrowBox[{{1.1631489624818339`, 1.2336554432233262`}, {
|
||||
0.18951736097760385`, 0.3902718952492563}}, 0.02245933508462397]}},
|
||||
{Hue[0.6, 0.2, 0.8], EdgeForm[{GrayLevel[0], Opacity[0.7]}],
|
||||
{Hue[1, 1, 0.7], EdgeForm[{Hue[1, 1, 0.7], Opacity[1]}],
|
||||
DiskBox[1, 0.02245933508462397]},
|
||||
{Hue[1, 1, 0.7], EdgeForm[{Hue[1, 1, 0.7], Opacity[1]}],
|
||||
DiskBox[2, 0.02245933508462397]},
|
||||
{Hue[1, 1, 0.7], EdgeForm[{Hue[1, 1, 0.7], Opacity[1]}],
|
||||
DiskBox[3, 0.02245933508462397]},
|
||||
{Hue[1, 1, 0.7], EdgeForm[{Hue[1, 1, 0.7], Opacity[1]}],
|
||||
DiskBox[4, 0.02245933508462397]},
|
||||
{Hue[1, 1, 0.7], EdgeForm[{Hue[1, 1, 0.7], Opacity[1]}],
|
||||
DiskBox[5, 0.02245933508462397]},
|
||||
{Hue[1, 1, 0.7], EdgeForm[{Hue[1, 1, 0.7], Opacity[1]}],
|
||||
DiskBox[6, 0.02245933508462397]},
|
||||
{Hue[1, 1, 0.7], EdgeForm[{Hue[1, 1, 0.7], Opacity[1]}],
|
||||
DiskBox[7, 0.02245933508462397]}, DiskBox[8, 0.02245933508462397],
|
||||
DiskBox[9, 0.02245933508462397], DiskBox[10, 0.02245933508462397],
|
||||
DiskBox[11, 0.02245933508462397]}}]],
|
||||
MouseAppearanceTag["NetworkGraphics"]],
|
||||
AllowKernelInitialization->False]],
|
||||
DefaultBaseStyle->{
|
||||
"NetworkGraphics", FrontEnd`GraphicsHighlightColor -> Hue[0.8, 1., 0.6]},
|
||||
FrameTicks->None,
|
||||
GridLinesStyle->Directive[
|
||||
GrayLevel[0.5, 0.4]]]], "Output",
|
||||
ExpressionUUID -> "4581a286-c75f-4757-8653-4b6d4378c180"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["For planar graphs, the function returns the empty list.", "Text",
|
||||
ExpressionUUID -> "cf1d13e4-9d78-4d46-92cf-0ee99f6206d2"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"kuratowskiSubdivision", "[",
|
||||
RowBox[{"CycleGraph", "[", "5", "]"}], "]"}]], "Input",
|
||||
ExpressionUUID -> "2647bdf5-f0b8-4a77-a554-893f75eea34e"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{", "}"}]], "Output",
|
||||
ExpressionUUID -> "6b676bec-d857-4cfb-a509-467344ec6278"]
|
||||
}, Open ]]
|
||||
}, Open ]]
|
||||
}, Open ]]
|
||||
},
|
||||
WindowSize->{808, 755},
|
||||
WindowMargins->{{302, Automatic}, {Automatic, 40}},
|
||||
PrivateNotebookOptions->{"FileOutlineCache"->False},
|
||||
TrackCellChangeTimes->False,
|
||||
FrontEndVersion->"10.3 for Mac OS X x86 (32-bit, 64-bit Kernel) (December 10, \
|
||||
2015)",
|
||||
StyleDefinitions->"Default.nb"
|
||||
]
|
||||
|
21
LTemplate/Documentation/Examples/Basics/Basics.h
Normal file
21
LTemplate/Documentation/Examples/Basics/Basics.h
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
#include <LTemplate.h>
|
||||
#include <complex>
|
||||
|
||||
struct Basics {
|
||||
// Add two real numbers.
|
||||
double add(double x, double y) {
|
||||
return x+y;
|
||||
}
|
||||
|
||||
// How many times does z -> z^2 + c need to be iterated before abs(z) > 2?
|
||||
mint mandel(mma::complex_t c, mint max_iter) {
|
||||
mint iter = 0;
|
||||
mma::complex_t z = 0;
|
||||
while (std::abs(z) < 2 && iter < max_iter) {
|
||||
z = z*z + c;
|
||||
iter++;
|
||||
}
|
||||
return iter;
|
||||
}
|
||||
};
|
723
LTemplate/Documentation/Examples/Basics/Basics.nb
Normal file
723
LTemplate/Documentation/Examples/Basics/Basics.nb
Normal file
@ -0,0 +1,723 @@
|
||||
Notebook[{
|
||||
|
||||
Cell[CellGroupData[{
|
||||
Cell["Basic LTemplate usage", "Section"],
|
||||
|
||||
Cell[TextData[{
|
||||
"This notebook demonstrates basic LTemplate usage with ",
|
||||
Cell[BoxData["Integer"]],
|
||||
", ",
|
||||
Cell[BoxData["Real"]],
|
||||
" and ",
|
||||
Cell[BoxData["Complex"]],
|
||||
" numerical arguments."
|
||||
}], "Text"],
|
||||
|
||||
Cell[BoxData[{
|
||||
RowBox[{"Needs", "[", "\"\<LTemplate`\>\"", "]"}], "\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"SetDirectory", "@",
|
||||
RowBox[{"NotebookDirectory", "[", "]"}]}], ";"}]}], "Input"],
|
||||
|
||||
Cell["Start by creating a template specification:", "Text"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"template", "=", "\[IndentingNewLine]",
|
||||
RowBox[{"LClass", "[",
|
||||
RowBox[{"\"\<Basics\>\"", ",", "\[IndentingNewLine]",
|
||||
RowBox[{"{", "\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<add\>\"", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Real", ",", "Real"}], "}"}], ",", "Real"}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<mandel\>\"", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Complex", " ",
|
||||
RowBox[{"(*", " ", "c", " ", "*)"}], ",", "Integer"}], " ",
|
||||
RowBox[{"(*", " ", "max_iter", " ", "*)"}], "}"}], ",", "Integer"}],
|
||||
"]"}]}], "\[IndentingNewLine]", "}"}]}], "\[IndentingNewLine]",
|
||||
"]"}]}], ";"}]], "Input"],
|
||||
|
||||
Cell["\<\
|
||||
The corresponding C++ code is in Basics.h, in the same directory.\
|
||||
\>", "Text"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"SystemOpen", "@",
|
||||
RowBox[{"NotebookDirectory", "[", "]"}]}]], "Input"],
|
||||
|
||||
Cell["Compile the library:", "Text"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"CompileTemplate", "[", "template", "]"}]], "Input"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
InterpretationBox[
|
||||
RowBox[{
|
||||
StyleBox["\<\"Current directory is: \"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\"/Users/szhorvat/Repos/LTemplate/LTemplate/Documentation/\
|
||||
Examples/Basics\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]}],
|
||||
SequenceForm[
|
||||
Style["Current directory is: ",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style["/Users/szhorvat/Repos/LTemplate/LTemplate/Documentation/Examples/\
|
||||
Basics",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]]],
|
||||
Editable->False]], "Print"],
|
||||
|
||||
Cell[BoxData[
|
||||
InterpretationBox[
|
||||
RowBox[{
|
||||
StyleBox["\<\"Unloading library \"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\"Basics\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\" ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]}],
|
||||
SequenceForm[
|
||||
Style["Unloading library ",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style["Basics",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style[" ...",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]]],
|
||||
Editable->False]], "Print"],
|
||||
|
||||
Cell[BoxData[
|
||||
StyleBox["\<\"Generating library code ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]], "Print"],
|
||||
|
||||
Cell[BoxData[
|
||||
StyleBox["\<\"Compiling library code ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]], "Print"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[BoxData["\<\"/Users/szhorvat/Library/Mathematica/SystemFiles/\
|
||||
LibraryResources/MacOSX-x86-64/Basics.dylib\"\>"], "Output"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Load the template:", "Text"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LoadTemplate", "[", "template", "]"}]], "Input"],
|
||||
|
||||
Cell["Create a class instance on which to call member functions:", "Text"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "=",
|
||||
RowBox[{"Make", "[", "Basics", "]"}]}]], "Input"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"Basics", "[", "1", "]"}]], "Output"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Add two real numbers, obtaining a real result:", "Text"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<add\>\"", "[",
|
||||
RowBox[{"42", ",", "137.2"}], "]"}]}]], "Input"],
|
||||
|
||||
Cell[BoxData["179.2`"], "Output"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Passing in the wrong type of argument results in an error:", "Text"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<add\>\"", "[",
|
||||
RowBox[{"I", ",", "1"}], "]"}]}]], "Input"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
StyleBox[
|
||||
RowBox[{"LibraryFunction", "::", "cfsa"}], "MessageName"],
|
||||
RowBox[{
|
||||
":", " "}], "\<\"Argument \[NoBreak]\\!\\(\[ImaginaryI]\\)\[NoBreak] at \
|
||||
position \[NoBreak]\\!\\(2\\)\[NoBreak] should be a \
|
||||
\[NoBreak]\\!\\(\\\"machine-size real number\\\"\\)\[NoBreak]. \
|
||||
\\!\\(\\*ButtonBox[\\\"\[RightSkeleton]\\\", ButtonStyle->\\\"Link\\\", \
|
||||
ButtonFrame->None, ButtonData:>\\\"paclet:ref/LibraryFunction\\\", ButtonNote \
|
||||
-> \\\"LibraryFunction::cfsa\\\"]\\)\"\>"}]], "Message", "MSG"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
InterpretationBox[
|
||||
RowBox[{
|
||||
TagBox["LibraryFunction",
|
||||
"SummaryHead"], "[",
|
||||
DynamicModuleBox[{Typeset`open$$ = False},
|
||||
PanelBox[
|
||||
PaneSelectorBox[{False->GridBox[{
|
||||
{
|
||||
PaneBox[
|
||||
ButtonBox[
|
||||
|
||||
DynamicBox[FEPrivate`FrontEndResource[
|
||||
"FEBitmaps", "SquarePlusIconMedium"],
|
||||
ImageSizeCache->{12., {0., 12.}}],
|
||||
Appearance->None,
|
||||
ButtonFunction:>(Typeset`open$$ = True),
|
||||
Evaluator->Automatic,
|
||||
Method->"Preemptive"],
|
||||
Alignment->{Center, Center},
|
||||
|
||||
ImageSize->
|
||||
Dynamic[{
|
||||
Automatic, 3.5 CurrentValue["FontCapHeight"]/
|
||||
AbsoluteCurrentValue[Magnification]}]],
|
||||
GraphicsBox[
|
||||
{Thickness[0.038461538461538464`],
|
||||
{FaceForm[{GrayLevel[0.93], Opacity[1.]}],
|
||||
FilledCurveBox[{{{1, 4, 3}, {0, 1, 0}, {1, 3, 3}, {0, 1, 0}, {1,
|
||||
3, 3}, {0, 1, 0}, {1, 3, 3}, {0, 1, 0}}}, {{{
|
||||
25.499999999999996`, 2.5}, {25.499999999999996`,
|
||||
1.3953100000000003`}, {24.604699999999998`,
|
||||
0.49999999999999994`}, {23.5, 0.49999999999999994`}, {2.5,
|
||||
0.49999999999999994`}, {1.3953100000000003`,
|
||||
0.49999999999999994`}, {0.49999999999999994`,
|
||||
1.3953100000000003`}, {0.49999999999999994`, 2.5}, {
|
||||
0.49999999999999994`, 23.5}, {0.49999999999999994`,
|
||||
24.604699999999998`}, {1.3953100000000003`,
|
||||
25.499999999999996`}, {2.5, 25.499999999999996`}, {23.5,
|
||||
25.499999999999996`}, {24.604699999999998`,
|
||||
25.499999999999996`}, {25.499999999999996`,
|
||||
24.604699999999998`}, {25.499999999999996`, 23.5}, {
|
||||
25.499999999999996`, 2.5}}}]},
|
||||
{FaceForm[{RGBColor[0.5, 0.5, 0.5], Opacity[1.]}],
|
||||
FilledCurveBox[{{{0, 2, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0,
|
||||
1, 0}, {0, 1, 0}, {0, 1, 0}}}, {{{20.5426,
|
||||
19.116799999999998`}, {16.3832, 21.876199999999997`}, {16.3832,
|
||||
20.021499999999996`}, {6.930469999999999,
|
||||
20.021499999999996`}, {6.930469999999999,
|
||||
18.212100000000003`}, {16.3832, 18.212100000000003`}, {16.3832,
|
||||
16.357399999999995`}, {20.5426, 19.116799999999998`}}}],
|
||||
FilledCurveBox[{{{0, 2, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0,
|
||||
1, 0}, {0, 1, 0}, {0, 1, 0}}}, {{{5.30508, 13.8391}, {9.46445,
|
||||
11.079700000000003`}, {9.46445, 12.933999999999997`}, {
|
||||
18.917199999999998`, 12.933999999999997`}, {18.917199999999998`,
|
||||
14.7438}, {9.46445, 14.7438}, {9.46445, 16.598}, {5.30508,
|
||||
13.8391}}}],
|
||||
FilledCurveBox[{{{1, 4, 3}, {1, 3, 3}, {1, 3, 3}, {1, 3, 3}, {0,
|
||||
1, 0}, {1, 3, 3}, {1, 3, 3}, {1, 3, 3}, {1, 3, 3}, {1, 3, 3}, {
|
||||
1, 3, 3}, {1, 3, 3}, {1, 3, 3}, {0, 1, 0}, {1, 3, 3}, {1, 3,
|
||||
3}, {1, 3, 3}, {1, 3, 3}}}, CompressedData["
|
||||
1:eJxTTMoPSmVmYGBgBGJjIGYCYq4u+eR3VWoOxhkv5j+Qk3SA8fu/r5rKOVHM
|
||||
Yd2vmNyjZ9Qcrt9QXbW9S8RBg59767IidQcPMYPGaHFhB+Nn61SfiGo4xBwp
|
||||
T7o2V9Dh0Iolfg6/NBxEHv/x1Xgi4FB1XNNqkqQWnP+axUTQjFkbzn+oO2HB
|
||||
j/3aDg/Xn5T6WiDoYLs3aJpiqI7DrHN+bO6tQg4zfUR7vF7pQOyfIQyRd9d1
|
||||
WLL0U1kLoyjEPdm6DpoTXfQX7xBzKPjQejLkhDacL5J4+LL2Gm2HtNnSl4Vf
|
||||
iELM69J2qPZM3tLnJerQX1oozZugDfHPUxGI/4W1HQ5p3TthoyDi4D7lG1v8
|
||||
Mi2HgqL9zoEHhB1inOxe3BRG8MH62zXhfIbN1Z82CGhC/GMg4nCm3mN/7TYN
|
||||
iHlCUPdGakDc/1kUEr46GhD/eYnD+d9iBf/kC0vC+TuCrSL+X5Vy2HGR4R5T
|
||||
uAbEfxYykPBYp+HQqsCuesZAFhL+rJoQ/2rIQdxTpwkJ7yVycPfD+GDzVqLx
|
||||
xbUd5HYt2JfqBdWfpA2Jj9mykPDpgYaXtaxDy7yzq86vg8qvlIHE5ylY/Eo7
|
||||
XAt7o787TxfOB5ufqesQ9PbyxxkPZSDhZ6nrMAGU3u7LQtLLEx2HN2253UbX
|
||||
ofZ76jis/Pay4oynAsT8QG0HKZMv/gW7FCDyTFpwPsz/MD44/Mw1HFjb1uR9
|
||||
TVVwWKy880/7FHWIexrkIfLX1RzOMDZZVjHIOaDkh3vSDuj5AwCF11Vc
|
||||
"]]}},
|
||||
AspectRatio->1,
|
||||
Axes->False,
|
||||
Background->GrayLevel[0.93],
|
||||
Frame->True,
|
||||
FrameStyle->Directive[
|
||||
Thickness[Tiny],
|
||||
GrayLevel[0.7]],
|
||||
FrameTicks->None,
|
||||
ImageSize->{Automatic,
|
||||
Dynamic[
|
||||
3.5 (CurrentValue["FontCapHeight"]/AbsoluteCurrentValue[
|
||||
Magnification]), ImageSizeCache -> {45., {0., 9.}}]}], GridBox[{
|
||||
{
|
||||
RowBox[{
|
||||
TagBox["\<\"Function name: \"\>",
|
||||
"SummaryItemAnnotation"], "\[InvisibleSpace]",
|
||||
TagBox["\<\"Basics_add\"\>",
|
||||
"SummaryItem"]}]},
|
||||
{
|
||||
RowBox[{
|
||||
TagBox["\<\"Argument count: \"\>",
|
||||
"SummaryItemAnnotation"], "\[InvisibleSpace]",
|
||||
TagBox["3",
|
||||
"SummaryItem"]}]}
|
||||
},
|
||||
AutoDelete->False,
|
||||
|
||||
BaseStyle->{
|
||||
ShowStringCharacters -> False, NumberMarks -> False,
|
||||
PrintPrecision -> 3, ShowSyntaxStyles -> False},
|
||||
GridBoxAlignment->{"Columns" -> {{Left}}, "Rows" -> {{Automatic}}},
|
||||
|
||||
|
||||
GridBoxItemSize->{
|
||||
"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}},
|
||||
GridBoxSpacings->{"Columns" -> {{2}}, "Rows" -> {{Automatic}}}]}
|
||||
},
|
||||
AutoDelete->False,
|
||||
BaselinePosition->{1, 1},
|
||||
GridBoxAlignment->{"Rows" -> {{Top}}},
|
||||
GridBoxItemSize->{
|
||||
"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}], True->GridBox[{
|
||||
{
|
||||
PaneBox[
|
||||
ButtonBox[
|
||||
|
||||
DynamicBox[FEPrivate`FrontEndResource[
|
||||
"FEBitmaps", "SquareMinusIconMedium"]],
|
||||
Appearance->None,
|
||||
ButtonFunction:>(Typeset`open$$ = False),
|
||||
Evaluator->Automatic,
|
||||
Method->"Preemptive"],
|
||||
Alignment->{Center, Center},
|
||||
|
||||
ImageSize->
|
||||
Dynamic[{
|
||||
Automatic, 3.5 CurrentValue["FontCapHeight"]/
|
||||
AbsoluteCurrentValue[Magnification]}]],
|
||||
GraphicsBox[
|
||||
{Thickness[0.038461538461538464`],
|
||||
{FaceForm[{GrayLevel[0.93], Opacity[1.]}],
|
||||
FilledCurveBox[{{{1, 4, 3}, {0, 1, 0}, {1, 3, 3}, {0, 1, 0}, {1,
|
||||
3, 3}, {0, 1, 0}, {1, 3, 3}, {0, 1, 0}}}, {{{
|
||||
25.499999999999996`, 2.5}, {25.499999999999996`,
|
||||
1.3953100000000003`}, {24.604699999999998`,
|
||||
0.49999999999999994`}, {23.5, 0.49999999999999994`}, {2.5,
|
||||
0.49999999999999994`}, {1.3953100000000003`,
|
||||
0.49999999999999994`}, {0.49999999999999994`,
|
||||
1.3953100000000003`}, {0.49999999999999994`, 2.5}, {
|
||||
0.49999999999999994`, 23.5}, {0.49999999999999994`,
|
||||
24.604699999999998`}, {1.3953100000000003`,
|
||||
25.499999999999996`}, {2.5, 25.499999999999996`}, {23.5,
|
||||
25.499999999999996`}, {24.604699999999998`,
|
||||
25.499999999999996`}, {25.499999999999996`,
|
||||
24.604699999999998`}, {25.499999999999996`, 23.5}, {
|
||||
25.499999999999996`, 2.5}}}]},
|
||||
{FaceForm[{RGBColor[0.5, 0.5, 0.5], Opacity[1.]}],
|
||||
FilledCurveBox[{{{0, 2, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0,
|
||||
1, 0}, {0, 1, 0}, {0, 1, 0}}}, {{{20.5426,
|
||||
19.116799999999998`}, {16.3832, 21.876199999999997`}, {16.3832,
|
||||
20.021499999999996`}, {6.930469999999999,
|
||||
20.021499999999996`}, {6.930469999999999,
|
||||
18.212100000000003`}, {16.3832, 18.212100000000003`}, {16.3832,
|
||||
16.357399999999995`}, {20.5426, 19.116799999999998`}}}],
|
||||
FilledCurveBox[{{{0, 2, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0,
|
||||
1, 0}, {0, 1, 0}, {0, 1, 0}}}, {{{5.30508, 13.8391}, {9.46445,
|
||||
11.079700000000003`}, {9.46445, 12.933999999999997`}, {
|
||||
18.917199999999998`, 12.933999999999997`}, {18.917199999999998`,
|
||||
14.7438}, {9.46445, 14.7438}, {9.46445, 16.598}, {5.30508,
|
||||
13.8391}}}],
|
||||
FilledCurveBox[{{{1, 4, 3}, {1, 3, 3}, {1, 3, 3}, {1, 3, 3}, {0,
|
||||
1, 0}, {1, 3, 3}, {1, 3, 3}, {1, 3, 3}, {1, 3, 3}, {1, 3, 3}, {
|
||||
1, 3, 3}, {1, 3, 3}, {1, 3, 3}, {0, 1, 0}, {1, 3, 3}, {1, 3,
|
||||
3}, {1, 3, 3}, {1, 3, 3}}}, CompressedData["
|
||||
1:eJxTTMoPSmVmYGBgBGJjIGYCYq4u+eR3VWoOxhkv5j+Qk3SA8fu/r5rKOVHM
|
||||
Yd2vmNyjZ9Qcrt9QXbW9S8RBg59767IidQcPMYPGaHFhB+Nn61SfiGo4xBwp
|
||||
T7o2V9Dh0Iolfg6/NBxEHv/x1Xgi4FB1XNNqkqQWnP+axUTQjFkbzn+oO2HB
|
||||
j/3aDg/Xn5T6WiDoYLs3aJpiqI7DrHN+bO6tQg4zfUR7vF7pQOyfIQyRd9d1
|
||||
WLL0U1kLoyjEPdm6DpoTXfQX7xBzKPjQejLkhDacL5J4+LL2Gm2HtNnSl4Vf
|
||||
iELM69J2qPZM3tLnJerQX1oozZugDfHPUxGI/4W1HQ5p3TthoyDi4D7lG1v8
|
||||
Mi2HgqL9zoEHhB1inOxe3BRG8MH62zXhfIbN1Z82CGhC/GMg4nCm3mN/7TYN
|
||||
iHlCUPdGakDc/1kUEr46GhD/eYnD+d9iBf/kC0vC+TuCrSL+X5Vy2HGR4R5T
|
||||
uAbEfxYykPBYp+HQqsCuesZAFhL+rJoQ/2rIQdxTpwkJ7yVycPfD+GDzVqLx
|
||||
xbUd5HYt2JfqBdWfpA2Jj9mykPDpgYaXtaxDy7yzq86vg8qvlIHE5ylY/Eo7
|
||||
XAt7o787TxfOB5ufqesQ9PbyxxkPZSDhZ6nrMAGU3u7LQtLLEx2HN2253UbX
|
||||
ofZ76jis/Pay4oynAsT8QG0HKZMv/gW7FCDyTFpwPsz/MD44/Mw1HFjb1uR9
|
||||
TVVwWKy880/7FHWIexrkIfLX1RzOMDZZVjHIOaDkh3vSDuj5AwCF11Vc
|
||||
"]]}},
|
||||
AspectRatio->1,
|
||||
Axes->False,
|
||||
Background->GrayLevel[0.93],
|
||||
Frame->True,
|
||||
FrameStyle->Directive[
|
||||
Thickness[Tiny],
|
||||
GrayLevel[0.7]],
|
||||
FrameTicks->None,
|
||||
ImageSize->{Automatic,
|
||||
Dynamic[
|
||||
3.5 (CurrentValue["FontCapHeight"]/AbsoluteCurrentValue[
|
||||
Magnification]), ImageSizeCache -> {45., {0., 9.}}]}], GridBox[{
|
||||
{
|
||||
RowBox[{
|
||||
TagBox["\<\"Function name: \"\>",
|
||||
"SummaryItemAnnotation"], "\[InvisibleSpace]",
|
||||
TagBox["\<\"Basics_add\"\>",
|
||||
"SummaryItem"]}]},
|
||||
{
|
||||
RowBox[{
|
||||
TagBox["\<\"Argument count: \"\>",
|
||||
"SummaryItemAnnotation"], "\[InvisibleSpace]",
|
||||
TagBox["3",
|
||||
"SummaryItem"]}]},
|
||||
{
|
||||
RowBox[{
|
||||
TagBox["\<\"Argument types: \"\>",
|
||||
"SummaryItemAnnotation"], "\[InvisibleSpace]",
|
||||
TagBox[
|
||||
PaneBox[
|
||||
RowBox[{"{",
|
||||
RowBox[{"Integer", ",", "Real", ",", "Real"}], "}"}],
|
||||
BaselinePosition->Baseline,
|
||||
ContentPadding->False,
|
||||
FrameMargins->0,
|
||||
ImageSize->{{1, 500}, Automatic},
|
||||
StripOnInput->True],
|
||||
"SummaryItem"]}]},
|
||||
{
|
||||
RowBox[{
|
||||
TagBox["\<\"Return type: \"\>",
|
||||
"SummaryItemAnnotation"], "\[InvisibleSpace]",
|
||||
TagBox[
|
||||
PaneBox["Real",
|
||||
BaselinePosition->Baseline,
|
||||
ContentPadding->False,
|
||||
FrameMargins->0,
|
||||
ImageSize->{{1, 500}, Automatic},
|
||||
StripOnInput->True],
|
||||
"SummaryItem"]}]},
|
||||
{
|
||||
RowBox[{
|
||||
TagBox["\<\"Library: \"\>",
|
||||
"SummaryItemAnnotation"], "\[InvisibleSpace]",
|
||||
TagBox["\<\"Basics.dylib\"\>",
|
||||
"SummaryItem"]}]}
|
||||
},
|
||||
AutoDelete->False,
|
||||
|
||||
BaseStyle->{
|
||||
ShowStringCharacters -> False, NumberMarks -> False,
|
||||
PrintPrecision -> 3, ShowSyntaxStyles -> False},
|
||||
GridBoxAlignment->{"Columns" -> {{Left}}, "Rows" -> {{Automatic}}},
|
||||
|
||||
|
||||
GridBoxItemSize->{
|
||||
"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}},
|
||||
GridBoxSpacings->{"Columns" -> {{2}}, "Rows" -> {{Automatic}}}]}
|
||||
},
|
||||
AutoDelete->False,
|
||||
BaselinePosition->{1, 1},
|
||||
GridBoxAlignment->{"Rows" -> {{Top}}},
|
||||
GridBoxItemSize->{
|
||||
"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}]}, Dynamic[
|
||||
Typeset`open$$],
|
||||
ImageSize->Automatic],
|
||||
BaselinePosition->Baseline],
|
||||
DynamicModuleValues:>{}], "]"}],
|
||||
LibraryFunction[
|
||||
"/Users/szhorvat/Library/Mathematica/SystemFiles/LibraryResources/MacOSX-\
|
||||
x86-64/Basics.dylib", "Basics_add", {Integer, Real, Real}, Real],
|
||||
Editable->False,
|
||||
SelectWithContents->True,
|
||||
Selectable->False], "[",
|
||||
RowBox[{"1", ",", "\[ImaginaryI]", ",", "1"}], "]"}]], "Output"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[TextData[{
|
||||
Cell[BoxData["mandel"]],
|
||||
" is a helper function for implementing the escape time algorithm for \
|
||||
visualizing the Mandelbrot set. It counts how many iterations of ",
|
||||
Cell[BoxData[
|
||||
RowBox[{"z", "\[Function]",
|
||||
RowBox[{
|
||||
SuperscriptBox["z", "2"], "+", "c"}]}]]],
|
||||
" are necessary before ",
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"Abs", "[", "z", "]"}], ">", "2"}]]],
|
||||
". The first argument is ",
|
||||
Cell[BoxData["c"]],
|
||||
", the second the maximum number of iterations."
|
||||
}], "Text"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"Table", "[", "\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<mandel\>\"", "[",
|
||||
RowBox[{
|
||||
RowBox[{"a", "+",
|
||||
RowBox[{"I", " ", "b"}]}], ",", "50"}], "]"}]}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"{",
|
||||
RowBox[{"a", ",",
|
||||
RowBox[{"-", "2"}], ",", "1", ",", "0.01"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"b", ",",
|
||||
RowBox[{"-", "1"}], ",", "1", ",", "0.01"}], "}"}]}],
|
||||
"\[IndentingNewLine]", "]"}], "//", "ArrayPlot"}]], "Input"],
|
||||
|
||||
Cell[BoxData[
|
||||
GraphicsBox[RasterBox[CompressedData["
|
||||
1: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
|
||||
"], {{0, 0}, {201, 301}}, {0, 50}],
|
||||
Frame->Automatic,
|
||||
FrameLabel->{None, None},
|
||||
FrameTicks->{{None, None}, {None, None}},
|
||||
GridLinesStyle->Directive[
|
||||
GrayLevel[0.5, 0.4]],
|
||||
Method->{
|
||||
"AxisPadding" -> Scaled[0.02], "DefaultBoundaryStyle" -> Automatic,
|
||||
"DefaultPlotStyle" -> Automatic, "DomainPadding" -> Scaled[0.02],
|
||||
"RangePadding" -> Scaled[0.05]}]], "Output"]
|
||||
}, Open ]]
|
||||
}, Open ]]
|
||||
},
|
||||
WindowSize->{808, 751},
|
||||
WindowMargins->{{92, Automatic}, {-4, Automatic}},
|
||||
PrivateNotebookOptions->{"FileOutlineCache"->False},
|
||||
CommonDefaultFormatTypes->{"TextInline"->StandardForm},
|
||||
TrackCellChangeTimes->False,
|
||||
FrontEndVersion->"10.0 for Mac OS X x86 (32-bit, 64-bit Kernel) (December 4, \
|
||||
2014)",
|
||||
StyleDefinitions->"Default.nb"
|
||||
]
|
||||
|
41194
LTemplate/Documentation/Examples/Images/Images.nb
Normal file
41194
LTemplate/Documentation/Examples/Images/Images.nb
Normal file
File diff suppressed because it is too large
Load Diff
155
LTemplate/Documentation/Examples/Images/Img.h
Normal file
155
LTemplate/Documentation/Examples/Images/Img.h
Normal file
@ -0,0 +1,155 @@
|
||||
|
||||
#include <LTemplate.h>
|
||||
#include <complex>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
struct Img {
|
||||
|
||||
/* Invert an Image like ColorNegate
|
||||
*
|
||||
* Demonstrated features:
|
||||
*
|
||||
* - Iterating through all channels except the alpha channel (nonAlphaChannels)
|
||||
* - Iterating through all pixels of a single channel linearly (pixelBegin)
|
||||
*
|
||||
*/
|
||||
mma::GenericImageRef invert(mma::ImageRef<double> im) {
|
||||
// loop through all channels except the alpha channel
|
||||
for (int ch=0; ch < im.nonAlphaChannels(); ++ch)
|
||||
// loop through the pixels of the given channel
|
||||
// instead of auto it, we could use ImageRef<double>::pixel_iterator it
|
||||
for (auto it = im.pixelBegin(ch); it != im.pixelEnd(ch); ++it)
|
||||
*it = 1 - *it; // invert pixel value
|
||||
return im;
|
||||
}
|
||||
|
||||
/* Blur an image up to radius 1 by averaging it with its four direct neighbours.
|
||||
* For simplicity, this implementation does not handle boundary pixels.
|
||||
*
|
||||
* Demonstrated features:
|
||||
*
|
||||
* - Iterating through all channels except the alpha channel (if one exists)
|
||||
* - Indexing into an image by pixel position
|
||||
*
|
||||
*/
|
||||
mma::GenericImageRef blur1(mma::ImageRef<double> im) {
|
||||
// loop through all channels except the alpha channel
|
||||
for (int ch=0; ch < im.nonAlphaChannels(); ++ch)
|
||||
// loop through all non-boundary pixels using 2D indexing
|
||||
for (int i=1; i < im.rows()-1; ++i)
|
||||
for (int j=1; j < im.cols()-1; ++j)
|
||||
// average each pixel with its four neighbours
|
||||
im(i,j,ch) = (im(i-1, j, ch) + im(i+1, j, ch) + im(i, j-1, ch) + im(i, j+1, ch) + im(i, j, ch)) / 5.0;
|
||||
return im;
|
||||
}
|
||||
|
||||
/* Retrieve image dimensions.
|
||||
*
|
||||
* Demonstrated features:
|
||||
*
|
||||
* - GenericImageRef can refer an image with any pixel type, but it cannot index into them.
|
||||
* Using it allows us to prevent copying the image.
|
||||
*
|
||||
*/
|
||||
mma::IntTensorRef imageDimensions(mma::GenericImageRef im) {
|
||||
return mma::makeVector<mint>({im.cols(), im.rows()});
|
||||
}
|
||||
|
||||
/* Creates a gradient image.
|
||||
*
|
||||
* Demonstrated features:
|
||||
*
|
||||
* - Creating new images
|
||||
* - Indexing into an image by pixel position
|
||||
*
|
||||
*/
|
||||
mma::GenericImageRef gradient(mint cols, mint rows) {
|
||||
auto im = mma::makeImage<mma::im_byte_t>(cols, rows);
|
||||
for (int i=0; i < rows; ++i)
|
||||
for (int j=0; j < cols; ++j)
|
||||
im(i,j) = 255.0*j/cols;
|
||||
return im;
|
||||
}
|
||||
|
||||
/* Creates a Mandelbrot set image.
|
||||
*
|
||||
* Demonstrated features:
|
||||
*
|
||||
* - Creating new images
|
||||
* - Indexing into an image by pixel position
|
||||
*
|
||||
*/
|
||||
mma::GenericImageRef mandelbrot(mma::complex_t lower, mma::complex_t upper, mint width, mint iter) {
|
||||
if (! (upper.real() > lower.real() && upper.imag() > lower.imag()) )
|
||||
throw mma::LibraryError("Real and imaginary parts of 'upper' must be greater than that of 'lower'.");
|
||||
if (iter > 255) {
|
||||
iter = 255;
|
||||
mma::message("The maximum number of iterations is 255. No more than this will be tried.");
|
||||
}
|
||||
double rat = (upper.real() - lower.real()) / width;
|
||||
mint height = (upper.imag() - lower.imag()) / rat;
|
||||
auto im = mma::makeImage<mma::im_byte_t>(width, height);
|
||||
|
||||
for (int i=0; i < height; ++i)
|
||||
for (int j=0; j < width; ++j) {
|
||||
mma::complex_t z = 0, c = lower + mma::complex_t(j,i)*rat;
|
||||
int k=0;
|
||||
while (std::abs(z) < 2 && k < iter) {
|
||||
z = z*z+c;
|
||||
k++;
|
||||
}
|
||||
im(height - i - 1, j) = k == iter ? 0 : k+1;
|
||||
}
|
||||
|
||||
return im;
|
||||
}
|
||||
|
||||
/* Adjusts each channel of an image so that the values span the whole available range (defined through top()).
|
||||
*
|
||||
* Demonstrated features:
|
||||
*
|
||||
* - Dispatching to the correct function based on the type of the image
|
||||
* - Casting GenericImageRef to a type-specialized ImageRef
|
||||
* - Finding the clipping values of different images types using mma::imageMax()
|
||||
* - Iterating through each pixel and each non-alpha channel
|
||||
*
|
||||
*/
|
||||
mma::GenericImageRef adjust(mma::GenericImageRef im) {
|
||||
// Dispatch to the correct function based on the type of the image
|
||||
switch (im.type()) {
|
||||
case MImage_Type_Bit:
|
||||
break;
|
||||
case MImage_Type_Bit8:
|
||||
iadjust(mma::ImageRef<mma::im_byte_t>(im));
|
||||
break;
|
||||
case MImage_Type_Bit16:
|
||||
iadjust(mma::ImageRef<mma::im_bit16_t>(im));
|
||||
break;
|
||||
case MImage_Type_Real32:
|
||||
iadjust(mma::ImageRef<mma::im_real32_t>(im));
|
||||
break;
|
||||
case MImage_Type_Real:
|
||||
iadjust(mma::ImageRef<mma::im_real_t>(im));
|
||||
break;
|
||||
case MImage_Type_Undef:
|
||||
throw mma::LibraryError("Invalid image.");
|
||||
}
|
||||
return im;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Specialized version of adjust() for each image type
|
||||
template<typename T> void iadjust(mma::ImageRef<T> im) {
|
||||
for (int ch=0; ch < im.nonAlphaChannels(); ++ch) {
|
||||
auto minmax = std::minmax_element(im.pixelBegin(ch), im.pixelEnd(ch));
|
||||
T lo = *minmax.first, hi = *minmax.second;
|
||||
T diff = hi - lo;
|
||||
if (diff == 0)
|
||||
diff = 1;
|
||||
for (auto it = im.pixelBegin(ch); it != im.pixelEnd(ch); ++it)
|
||||
*it = mma::imageMax<T>() * double(*it - lo) / diff;
|
||||
}
|
||||
}
|
||||
};
|
133
LTemplate/Documentation/Examples/Ising/Ising.h
Normal file
133
LTemplate/Documentation/Examples/Ising/Ising.h
Normal file
@ -0,0 +1,133 @@
|
||||
|
||||
#include <LTemplate.h>
|
||||
|
||||
#include <random>
|
||||
#include <cmath>
|
||||
|
||||
// Auxiliary class for holding the spin state.
|
||||
template<typename T>
|
||||
class Matrix {
|
||||
int nrows, ncols;
|
||||
T *data;
|
||||
|
||||
public:
|
||||
Matrix(int r, int c) : nrows(r), ncols(c) {
|
||||
data = new T[nrows*ncols];
|
||||
}
|
||||
|
||||
~Matrix() { delete [] data; }
|
||||
|
||||
T & operator () (int i, int j) { return data[i*ncols + j]; }
|
||||
const T & operator () (int i, int j) const { return data[i*ncols + j]; }
|
||||
|
||||
T & operator [] (int i) { return data[i]; }
|
||||
const T & operator [] (int i) const { return data[i]; }
|
||||
|
||||
int rows() const { return nrows; }
|
||||
int cols() const { return ncols; }
|
||||
int size() const { return nrows*ncols; }
|
||||
|
||||
T *begin() { return data; }
|
||||
T *end() { return data + size(); }
|
||||
};
|
||||
|
||||
typedef Matrix<bool> StateMatrix;
|
||||
|
||||
// Convert bool value to -1 or +1.
|
||||
inline int spin(bool b) { return 2*b-1; }
|
||||
|
||||
|
||||
// LTemplate class for the Ising model simulation.
|
||||
class Ising {
|
||||
std::mt19937 engine;
|
||||
|
||||
/* LTemplate does not currently support constructor arguments, thus Ising
|
||||
* objects must be created with an "empty" state. We indicate this using nullptr,
|
||||
* which is safe to delete in the destructor.
|
||||
*
|
||||
* There is a separate function, setState(), for assigning an actual state.
|
||||
*/
|
||||
StateMatrix *state;
|
||||
|
||||
public:
|
||||
Ising() : engine{ std::random_device()() }, state(nullptr) { }
|
||||
~Ising() { delete state; }
|
||||
|
||||
// Seed the random number generator.
|
||||
void seed(mint s) { engine.seed(s); }
|
||||
|
||||
// Set the Ising state.
|
||||
void setState(mma::IntMatrixRef mat) {
|
||||
if (mat.rows() < 2 || mat.cols() < 2)
|
||||
throw mma::LibraryError("State matrix must be at least of size 2 by 2.");
|
||||
delete state;
|
||||
state = new StateMatrix(mat.rows(), mat.cols());
|
||||
std::copy(mat.begin(), mat.end(), state->begin());
|
||||
}
|
||||
|
||||
// Retrieve the Ising state.
|
||||
mma::IntMatrixRef getState() const {
|
||||
if (! state)
|
||||
throw mma::LibraryError("State not set.");
|
||||
return mma::makeMatrix<mint>(state->rows(), state->cols(), state->begin());
|
||||
}
|
||||
|
||||
// Compute the magnetization value.
|
||||
mint magnetization() const {
|
||||
if (! state)
|
||||
throw mma::LibraryError("State not set.");
|
||||
int total = 0;
|
||||
for (const auto &el : *state)
|
||||
total += el;
|
||||
return 2*total - state->size();
|
||||
}
|
||||
|
||||
// Compute the energy value.
|
||||
mint energy() const {
|
||||
if (! state)
|
||||
throw mma::LibraryError("State not set.");
|
||||
int E = 0;
|
||||
for (int i=1; i < state->rows(); ++i)
|
||||
for (int j=0; j < state->cols(); ++j)
|
||||
E += spin((*state)(i,j)) * spin((*state)(i-1,j));
|
||||
for (int i=0; i < state->rows(); ++i)
|
||||
for (int j=1; j < state->cols(); ++j)
|
||||
E += spin((*state)(i,j)) * spin((*state)(i,j-1));
|
||||
return -E;
|
||||
}
|
||||
|
||||
// Simulate the Ising system for the given number of steps and the given temperature.
|
||||
void simulate(mint steps, double temp) {
|
||||
if (! state)
|
||||
throw mma::LibraryError("State not set.");
|
||||
if (temp <= 0)
|
||||
throw mma::LibraryError("Temperature must be strictly positive.");
|
||||
|
||||
std::uniform_int_distribution<> randrow(0, state->rows()-1);
|
||||
std::uniform_int_distribution<> randcol(0, state->cols()-1);
|
||||
std::uniform_real_distribution<> rrand;
|
||||
|
||||
for (mint i=0; i < steps; ++i) {
|
||||
// Allow for aborting the simulation every 1000 steps.
|
||||
if (i % 1000 == 0)
|
||||
mma::check_abort();
|
||||
|
||||
int ri = randrow(engine);
|
||||
int rj = randcol(engine);
|
||||
|
||||
int s = 0;
|
||||
if (ri > 0) s += spin((*state)(ri-1, rj));
|
||||
if (ri < state->rows()-1) s += spin((*state)(ri+1, rj));
|
||||
if (rj > 0) s += spin((*state)(ri, rj-1));
|
||||
if (rj < state->cols()-1) s += spin((*state)(ri, rj+1));
|
||||
|
||||
int x = spin((*state)(ri,rj));
|
||||
|
||||
int deltaE = 2*s*x;
|
||||
|
||||
if (rrand(engine) < std::exp( -deltaE/temp )) {
|
||||
(*state)(ri,rj) = ! (*state)(ri,rj); // do flip
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
198
LTemplate/Documentation/Examples/Ising/Ising.nb
Normal file
198
LTemplate/Documentation/Examples/Ising/Ising.nb
Normal file
@ -0,0 +1,198 @@
|
||||
Notebook[{
|
||||
|
||||
Cell[CellGroupData[{
|
||||
Cell["Two-dimensional Ising model", "Section",
|
||||
ExpressionUUID -> "10c6cfd6-9e82-43f5-a390-f895753bc07f"],
|
||||
|
||||
Cell[TextData[{
|
||||
"This example shows how to simulate a two-dimensional ",
|
||||
ButtonBox["Ising model",
|
||||
BaseStyle->"Hyperlink",
|
||||
ButtonData->{
|
||||
URL["https://en.wikipedia.org/wiki/Ising_model"], None},
|
||||
ButtonNote->"https://en.wikipedia.org/wiki/Ising_model"],
|
||||
" in C++ and visualize it in real time in Mathematica."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "76cdc71d-e64b-4770-8661-fd72ae6b7780"],
|
||||
|
||||
Cell[BoxData[{
|
||||
RowBox[{"Needs", "[", "\"\<LTemplate`\>\"", "]"}], "\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"SetDirectory", "@",
|
||||
RowBox[{"NotebookDirectory", "[", "]"}]}], ";"}]}], "Input",
|
||||
ExpressionUUID -> "742d9654-8e42-415c-8976-dcce157c587c"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"template", "=", "\[IndentingNewLine]",
|
||||
RowBox[{"LClass", "[",
|
||||
RowBox[{"\"\<Ising\>\"", ",", "\[IndentingNewLine]",
|
||||
RowBox[{"{", "\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<seed\>\"", ",",
|
||||
RowBox[{"{", "Integer", "}"}], ",", "\"\<Void\>\""}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<getState\>\"", ",",
|
||||
RowBox[{"{", "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Integer", ",", "2"}], "}"}]}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<setState\>\"", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Integer", ",", "2", ",", "\"\<Constant\>\""}], "}"}],
|
||||
"}"}], ",", "\"\<Void\>\""}], "]"}], ",", "\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<energy\>\"", ",",
|
||||
RowBox[{"{", "}"}], ",", "Integer"}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<magnetization\>\"", ",",
|
||||
RowBox[{"{", "}"}], ",", "Integer"}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<simulate\>\"", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Integer", ",", "Real"}], "}"}], ",", "\"\<Void\>\""}],
|
||||
"]"}]}], "\[IndentingNewLine]", "}"}]}], "\[IndentingNewLine]",
|
||||
"]"}]}], ";"}]], "Input",
|
||||
ExpressionUUID -> "74ae851f-272f-4653-9816-f1c3194402de"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"CompileTemplate", "[", "template", "]"}]], "Input",
|
||||
ExpressionUUID -> "ffbc1822-22e9-47c4-be40-57db4f4eb58d"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LoadTemplate", "[", "template", "]"}]], "Input",
|
||||
ExpressionUUID -> "add3ebe9-db11-4e9c-932e-6825b7a1836c"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"ising", "=",
|
||||
RowBox[{"Make", "[", "Ising", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "238aa2cf-9058-40f5-8230-9c9f71652ca1"],
|
||||
|
||||
Cell[TextData[{
|
||||
"The state must be set before the ",
|
||||
Cell[BoxData["ising"],
|
||||
ExpressionUUID -> "1082ab58-96d7-4dc4-a21c-1971dfaa4685"],
|
||||
" object can be used:"
|
||||
}], "Text",
|
||||
ExpressionUUID -> "cf0f3dce-51aa-4efa-87b2-61fc61b49c09"],
|
||||
|
||||
Cell[BoxData[{
|
||||
RowBox[{
|
||||
RowBox[{"ising", "@",
|
||||
RowBox[{"\"\<setState\>\"", "[",
|
||||
RowBox[{"RandomInteger", "[",
|
||||
RowBox[{"1", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"40", ",", "40"}], "}"}]}], "]"}], "]"}]}], ";"}], "\n",
|
||||
RowBox[{
|
||||
RowBox[{"state", "=",
|
||||
RowBox[{"ising", "@",
|
||||
RowBox[{"\"\<getState\>\"", "[", "]"}]}]}], ";"}]}], "Input",
|
||||
ExpressionUUID -> "732764c4-9e22-41c5-8271-53a1ecaf3c95"],
|
||||
|
||||
Cell["\<\
|
||||
Control sliders for the temperature and simulation speed. Try using them \
|
||||
while the simulation is running.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "bb8b1248-3180-4132-bfc9-664523f0b223"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{"\"\<temp\>\"", ",",
|
||||
RowBox[{"Control", "[",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"temp", ",", "2"}], "}"}], ",", "0.01", ",", "20"}], "}"}],
|
||||
"]"}], ",",
|
||||
RowBox[{"Dynamic", "[", "temp", "]"}]}], "}"}]], "Input",
|
||||
ExpressionUUID -> "60f3866b-788c-4462-91dc-70b167cb8f84"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{"\"\<speed\>\"", ",",
|
||||
RowBox[{"Control", "[",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"step", ",", "300"}], "}"}], ",", "1", ",", "10000", ",",
|
||||
"1"}], "}"}], "]"}], ",",
|
||||
RowBox[{"Dynamic", "[", "step", "]"}]}], "}"}]], "Input",
|
||||
ExpressionUUID -> "82de69c3-d667-4447-874f-e58320aa4df3"],
|
||||
|
||||
Cell["Set up dynamic visualizations.", "Text",
|
||||
ExpressionUUID -> "37962e41-50d0-4648-9fa0-5fda053fa3e2"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"Dynamic", "@",
|
||||
RowBox[{"Row", "[",
|
||||
RowBox[{"{", "\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"ArrayPlot", "[",
|
||||
RowBox[{"state", ",",
|
||||
RowBox[{"ImageSize", "\[Rule]", "Medium"}]}], "]"}], ",",
|
||||
RowBox[{"VerticalGauge", "[",
|
||||
RowBox[{
|
||||
RowBox[{"ising", "@",
|
||||
RowBox[{"\"\<energy\>\"", "[", "]"}]}], ",",
|
||||
RowBox[{"2", " ",
|
||||
RowBox[{"40", "^", "2"}],
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"-", "1"}], ",", "1"}], "}"}]}], ",",
|
||||
RowBox[{"GaugeLabels", "\[Rule]", "\"\<energy\>\""}]}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"VerticalGauge", "[",
|
||||
RowBox[{
|
||||
RowBox[{"ising", "@",
|
||||
RowBox[{"\"\<magnetization\>\"", "[", "]"}]}], ",",
|
||||
RowBox[{
|
||||
RowBox[{"40", "^", "2"}],
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"-", "1"}], ",", "1"}], "}"}]}], ",",
|
||||
RowBox[{"GaugeLabels", "\[Rule]", "\"\<magnetization\>\""}]}], "]"}]}],
|
||||
"}"}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "73fd3f39-b896-4ae1-a4cc-115272b9e9af"],
|
||||
|
||||
Cell["Start the simulation.", "Text",
|
||||
ExpressionUUID -> "8f9ec8ef-ea0b-4024-ba82-1f22cae42506"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"While", "[",
|
||||
RowBox[{"True", ",", "\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"ising", "@",
|
||||
RowBox[{"\"\<simulate\>\"", "[",
|
||||
RowBox[{"step", ",", "temp"}], "]"}]}], ";", "\[IndentingNewLine]",
|
||||
RowBox[{"state", "=",
|
||||
RowBox[{"ising", "@",
|
||||
RowBox[{"\"\<getState\>\"", "[", "]"}]}]}], ";", "\[IndentingNewLine]",
|
||||
|
||||
RowBox[{"Pause", "[", "0.05", "]"}]}]}], "\[IndentingNewLine]",
|
||||
"]"}]], "Input",
|
||||
ExpressionUUID -> "c7758668-cab3-47ee-a816-125c948085c4"],
|
||||
|
||||
Cell["\<\
|
||||
Simply abort the calculation (Evaluation menu, Abort Evaluation) to stop the \
|
||||
simulation.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "897d8457-ad83-4800-a4b2-33c18a32e805"]
|
||||
}, Open ]]
|
||||
},
|
||||
WindowSize->{808, 824},
|
||||
WindowMargins->{{Automatic, 169}, {Automatic, 10}},
|
||||
PrivateNotebookOptions->{"FileOutlineCache"->False},
|
||||
CommonDefaultFormatTypes->{"TextInline"->StandardForm},
|
||||
TrackCellChangeTimes->False,
|
||||
FrontEndVersion->"10.0 for Mac OS X x86 (32-bit, 64-bit Kernel) (December 4, \
|
||||
2014)",
|
||||
StyleDefinitions->"Default.nb"
|
||||
]
|
||||
|
@ -0,0 +1,704 @@
|
||||
Notebook[{
|
||||
|
||||
Cell[CellGroupData[{
|
||||
Cell["Managed Library Expressions", "Section",
|
||||
ExpressionUUID -> "cd2d3f18-e46f-4d9c-adac-d36ea52104dd"],
|
||||
|
||||
Cell[TextData[{
|
||||
"This example demonstrates various operations on ",
|
||||
ButtonBox["managed library expressions",
|
||||
BaseStyle->"Link",
|
||||
ButtonData->
|
||||
"paclet:paclet:LibraryLink/tutorial/InteractionWithMathematica#353220453"],\
|
||||
|
||||
". It shows the implementation of a real-valued vector class, ",
|
||||
Cell[BoxData[
|
||||
FormBox["VecExpr", TraditionalForm]],
|
||||
ExpressionUUID -> "54d425c9-3fb5-4ffc-87c3-e4a57edcb78c"],
|
||||
"."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "63587299-0a81-4c30-a2c3-d05440e19b72"],
|
||||
|
||||
Cell["\<\
|
||||
LTemplate was originally created to simplify working with managed library \
|
||||
expressions. All LTemplate classes correspond to library expressions with the \
|
||||
same manager name.\
|
||||
\>", "Text"],
|
||||
|
||||
Cell[BoxData[{
|
||||
RowBox[{
|
||||
RowBox[{"SetDirectory", "@",
|
||||
RowBox[{"NotebookDirectory", "[", "]"}]}], ";"}], "\[IndentingNewLine]",
|
||||
RowBox[{"Needs", "[", "\"\<LTemplate`\>\"", "]"}]}], "Input",
|
||||
ExpressionUUID -> "3c1bcca1-fd1e-487c-a227-5eebf7de8e12"],
|
||||
|
||||
Cell["\<\
|
||||
This library has two classes, each having its own header file.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "b611e1bd-c606-4faa-b805-87bd28e021a6"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"template", "=",
|
||||
RowBox[{"LTemplate", "[",
|
||||
RowBox[{"\"\<LibraryExpressions\>\"", ",", "\[IndentingNewLine]",
|
||||
RowBox[{"{", "\[IndentingNewLine]",
|
||||
RowBox[{"(*", " ",
|
||||
RowBox[{
|
||||
"Functions", " ", "that", " ", "are", " ", "not", " ", "attached", " ",
|
||||
"to", " ", "any", " ", "VecExpr", " ",
|
||||
RowBox[{"(",
|
||||
RowBox[{
|
||||
RowBox[{"i", ".", "e", ".", " ", "could"}], " ", "also", " ", "be",
|
||||
" ", "free"}], ")"}], " ", "will", " ", "be", " ", "members", " ",
|
||||
"of", " ", "this", " ",
|
||||
RowBox[{"class", ".", " ", "There"}], " ", "will", " ", "be", " ",
|
||||
"only", " ", "once", " ", "instance", " ", "of", " ", "this", " ",
|
||||
RowBox[{"class", "."}]}], " ", "*)"}], "\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"LClass", "[",
|
||||
RowBox[{"\"\<Manager\>\"", ",", "\[IndentingNewLine]",
|
||||
RowBox[{"{", "\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<releaseVecExpr\>\"", ",",
|
||||
RowBox[{"{", "Integer", "}"}], ",", "\"\<Void\>\""}], "]"}],
|
||||
"\[IndentingNewLine]", "}"}]}], "\[IndentingNewLine]", "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"(*", " ",
|
||||
RowBox[{"The", " ", "vector", " ",
|
||||
RowBox[{"class", "."}]}], " ", "*)"}], "\[IndentingNewLine]",
|
||||
RowBox[{"LClass", "[",
|
||||
RowBox[{"\"\<VecExpr\>\"", ",", "\[IndentingNewLine]",
|
||||
RowBox[{"{", "\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<set\>\"", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Real", ",", "1"}], "}"}], "}"}], ",",
|
||||
"\"\<Void\>\""}], "]"}], ",", "\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<value\>\"", ",",
|
||||
RowBox[{"{", "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Real", ",", "1"}], "}"}]}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<inner\>\"", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"LExpressionID", "[", "\"\<VecExpr\>\"", "]"}], "}"}],
|
||||
",", "Real"}], "]"}], ",", "\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<setToSum\>\"", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Integer", ",", "1"}], "}"}], "}"}], ",",
|
||||
"\"\<Void\>\""}], "]"}]}], "\[IndentingNewLine]", "}"}]}],
|
||||
"\[IndentingNewLine]", "]"}]}], "\[IndentingNewLine]", "}"}]}],
|
||||
"\[IndentingNewLine]", "]"}]}], ";"}]], "Input",
|
||||
ExpressionUUID -> "5dd1cf3f-d485-4693-8d58-975a44fa935e"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"CompileTemplate", "[", "template", "]"}]], "Input",
|
||||
ExpressionUUID -> "0991b970-8180-4faa-af96-aa4996111648"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
InterpretationBox[
|
||||
RowBox[{
|
||||
StyleBox["\<\"Current directory is: \"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\"/Users/szhorvat/Repos/LTemplate/LTemplate/Documentation/\
|
||||
Examples/LibraryExpressions\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]}],
|
||||
SequenceForm[
|
||||
Style["Current directory is: ",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style["/Users/szhorvat/Repos/LTemplate/LTemplate/Documentation/Examples/\
|
||||
LibraryExpressions",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]]],
|
||||
Editable->False]], "Print",
|
||||
ExpressionUUID -> "d9d4032f-0322-40d3-9f57-d95e3b99b3a5"],
|
||||
|
||||
Cell[BoxData[
|
||||
InterpretationBox[
|
||||
RowBox[{
|
||||
StyleBox["\<\"Unloading library \"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\"LibraryExpressions\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\" ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]}],
|
||||
SequenceForm[
|
||||
Style["Unloading library ",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style["LibraryExpressions",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style[" ...",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]]],
|
||||
Editable->False]], "Print",
|
||||
ExpressionUUID -> "d9d4032f-0322-40d3-9f57-d95e3b99b3a5"],
|
||||
|
||||
Cell[BoxData[
|
||||
StyleBox["\<\"Generating library code ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]], "Print",
|
||||
ExpressionUUID -> "d9d4032f-0322-40d3-9f57-d95e3b99b3a5"],
|
||||
|
||||
Cell[BoxData[
|
||||
StyleBox["\<\"Compiling library code ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]], "Print",
|
||||
ExpressionUUID -> "d9d4032f-0322-40d3-9f57-d95e3b99b3a5"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[BoxData["\<\"/Users/szhorvat/Library/Mathematica/SystemFiles/\
|
||||
LibraryResources/MacOSX-x86-64/LibraryExpressions.dylib\"\>"], "Output",
|
||||
ExpressionUUID -> "ec9a1924-6a42-40af-b5df-ea4965aa360a"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LoadTemplate", "[", "template", "]"}]], "Input",
|
||||
ExpressionUUID -> "86a63d4d-0b65-4d65-87ff-14e55df6b2bb"],
|
||||
|
||||
Cell["\<\
|
||||
We start by turning off history tracking, to be able to demonstrate automatic \
|
||||
freeing of managed library expressions later.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "603fbe90-66bf-43bf-be7b-9110da8bc154"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"$HistoryLength", "=", "0"}], ";"}]], "Input",
|
||||
ExpressionUUID -> "117a414b-6cad-44aa-bbf5-f226c089520d"],
|
||||
|
||||
Cell[TextData[{
|
||||
Cell[BoxData[
|
||||
FormBox[
|
||||
RowBox[{"toVecExpr", "[", "]"}], TraditionalForm]],
|
||||
ExpressionUUID -> "7f181341-43b8-4312-b5e2-8fc05fa57338"],
|
||||
" converts to a ",
|
||||
StyleBox["Mathematica",
|
||||
FontSlant->"Italic"],
|
||||
" list to a ",
|
||||
Cell[BoxData[
|
||||
FormBox["VecExpr", TraditionalForm]],
|
||||
ExpressionUUID -> "b66620f0-ec83-49aa-95f2-855e7c1cd587"],
|
||||
" vector. We define ",
|
||||
Cell[BoxData[
|
||||
FormBox[
|
||||
RowBox[{"toVecExpr", "[", "]"}], TraditionalForm]],
|
||||
ExpressionUUID -> "c432be49-3b6a-4455-8461-7c215d3ad655"],
|
||||
" in such a way that it will not accept any symbolic arguments, and use ",
|
||||
Cell[BoxData[
|
||||
FormBox["Block", TraditionalForm]],
|
||||
ExpressionUUID -> "d2cf1e57-06de-4cb4-926a-d34e2562e95c"],
|
||||
" for localization. This is slightly faster than ",
|
||||
Cell[BoxData[
|
||||
FormBox["Module", TraditionalForm]],
|
||||
ExpressionUUID -> "e3a3e20f-ac1f-42fd-8d03-412a92876bdd"],
|
||||
". While this performance difference is not normally noticeable in ",
|
||||
StyleBox["Mathematica",
|
||||
FontSlant->"Italic"],
|
||||
", library functions are so fast that it is measurable in this case."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "09264c44-3a23-4454-b579-e768a6a14f46"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"toVecExpr", "[",
|
||||
RowBox[{"v_", "?",
|
||||
RowBox[{"(",
|
||||
RowBox[{
|
||||
RowBox[{"VectorQ", "[",
|
||||
RowBox[{"#", ",", "NumericQ"}], "]"}], "&"}], ")"}]}], "]"}], ":=",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"Block", "[",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"vec", "=",
|
||||
RowBox[{"Make", "[", "VecExpr", "]"}]}], "}"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"vec", "@",
|
||||
RowBox[{"\"\<set\>\"", "[", "v", "]"}]}], ";", "\[IndentingNewLine]",
|
||||
"vec"}]}], "\[IndentingNewLine]", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "7f5298e4-7c8f-4c34-acc3-ecaacdec40dc"],
|
||||
|
||||
Cell["Let us create two vectors:", "Text",
|
||||
ExpressionUUID -> "c0748e4f-e445-435a-9d80-a008a9e867b1"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"v1", "=",
|
||||
RowBox[{"toVecExpr", "[",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.6", ",", "2", ",", "3", ",", "4"}], "}"}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "3305886a-0a00-4b43-adf5-f3d3fc544331"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"VecExpr", "[", "1", "]"}]], "Output",
|
||||
ExpressionUUID -> "e306bbdf-65d1-4a4a-8a55-020b9625051d"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"v2", "=",
|
||||
RowBox[{"toVecExpr", "[",
|
||||
RowBox[{"{",
|
||||
RowBox[{"4", ",", "3", ",", "2", ",", "1"}], "}"}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "aea78f2a-ffdb-4519-9afb-a9cf8794a14c"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"VecExpr", "[", "2", "]"}]], "Output",
|
||||
ExpressionUUID -> "023dda62-c25a-461d-9815-b7915b4f68a9"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Retrieve their value:", "Text",
|
||||
ExpressionUUID -> "83f0efc4-afba-4130-93b8-ab20869e3cdb"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"v1", "@",
|
||||
RowBox[{"\"\<value\>\"", "[", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "336a42a3-538d-4694-a496-73874b0e9eed"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.6`", ",", "2.`", ",", "3.`", ",", "4.`"}], "}"}]], "Output",
|
||||
ExpressionUUID -> "f9a27d1e-e6e5-4737-b63c-124ae123eee0"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[TextData[{
|
||||
"Compute their inner product. Notice that we must pass the managed library \
|
||||
expression ID (i.e. an integer) of a VecExpr. While LTemplate could in \
|
||||
principle detect when ",
|
||||
ButtonBox["ManagedLibraryExpressionID",
|
||||
BaseStyle->"Link",
|
||||
ButtonData->"paclet:ref/ManagedLibraryExpressionID"],
|
||||
" needs to be applied, this is left to the user so that better performance \
|
||||
can be achieved."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "8b4aa657-1a23-417a-9231-9bffbc50de16"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"v1", "@",
|
||||
RowBox[{"\"\<inner\>\"", "[",
|
||||
RowBox[{"ManagedLibraryExpressionID", "[", "v2", "]"}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "22cca200-8d33-4b30-a1c9-5cb06dd6bef4"],
|
||||
|
||||
Cell[BoxData["22.4`"], "Output",
|
||||
ExpressionUUID -> "ad417a0b-38c6-476c-bdd1-5b96bc6e7926"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Verify the result:", "Text",
|
||||
ExpressionUUID -> "56fcadd6-a1a0-4e58-9cfe-282ba5d072e2"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"v1", "@",
|
||||
RowBox[{"\"\<value\>\"", "[", "]"}]}], ".",
|
||||
RowBox[{"v2", "@",
|
||||
RowBox[{"\"\<value\>\"", "[", "]"}]}]}]], "Input",
|
||||
ExpressionUUID -> "4a458cca-6c38-47ca-a63b-986694f0a950"],
|
||||
|
||||
Cell[BoxData["22.4`"], "Output",
|
||||
ExpressionUUID -> "938f5fab-15f5-4195-8281-1b90b5fa2071"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[TextData[{
|
||||
"The following function creates a new ",
|
||||
Cell[BoxData[
|
||||
FormBox["VecExpr", TraditionalForm]],
|
||||
ExpressionUUID -> "4cfc5c43-dd6c-4bba-8f0f-ead68ebccca6"],
|
||||
" from the sum of multiple other vectors:"
|
||||
}], "Text",
|
||||
ExpressionUUID -> "37e823c2-302b-4dac-a693-5310f70edd0f"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"vecSum", "[", "vecs__VecExpr", "]"}], ":=", "\[IndentingNewLine]",
|
||||
|
||||
RowBox[{"Block", "[",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"vec", "=",
|
||||
RowBox[{"Make", "[", "VecExpr", "]"}]}], "}"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"vec", "@",
|
||||
RowBox[{"\"\<setToSum\>\"", "[",
|
||||
RowBox[{"ManagedLibraryExpressionID", "/@",
|
||||
RowBox[{"{", "vecs", "}"}]}], "]"}]}], ";", "\[IndentingNewLine]",
|
||||
"vec"}]}], "\[IndentingNewLine]", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "5b07c542-8f3a-450a-9156-ff190821a399"],
|
||||
|
||||
Cell["Let\[CloseCurlyQuote]s try it:", "Text",
|
||||
ExpressionUUID -> "0a2cd7a7-82a9-4352-9e06-d3f2ab108119"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"v3", "=",
|
||||
RowBox[{"vecSum", "[",
|
||||
RowBox[{"v1", ",", "v2"}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "a431b93b-fafd-468f-89fd-cbb590eda6c8"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"VecExpr", "[", "3", "]"}]], "Output",
|
||||
ExpressionUUID -> "4e38e6ef-a73e-4f5c-b007-963974729189"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"v3", "@",
|
||||
RowBox[{"\"\<value\>\"", "[", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "2bc5057f-aadc-4c0f-aee0-057f922410ae"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{"5.6`", ",", "5.`", ",", "5.`", ",", "5.`"}], "}"}]], "Output",
|
||||
ExpressionUUID -> "3e36e89b-5ed2-47a1-82c5-7a544e8fc7f2"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["At this point, we have three managed library expressions", "Text",
|
||||
ExpressionUUID -> "ae1326ce-2cbf-4e37-8780-c9340fc6fa10"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LExpressionList", "[", "VecExpr", "]"}]], "Input",
|
||||
ExpressionUUID -> "b26ae979-7b2f-4398-870f-bc6de7d63a4c"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"VecExpr", "[", "1", "]"}], ",",
|
||||
RowBox[{"VecExpr", "[", "2", "]"}], ",",
|
||||
RowBox[{"VecExpr", "[", "3", "]"}]}], "}"}]], "Output",
|
||||
ExpressionUUID -> "67ec54a6-67c2-4213-b7a5-358ac73d97b5"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Let us now sum three vectors:", "Text",
|
||||
ExpressionUUID -> "2f4da39c-222c-4f38-bd63-1fb09cd9782d"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"v3", "=",
|
||||
RowBox[{"vecSum", "[",
|
||||
RowBox[{"v1", ",", "v2", ",", "v1"}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "ca0daf5a-201b-4edd-a667-dd4d1de7efe5"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"VecExpr", "[", "4", "]"}]], "Output",
|
||||
ExpressionUUID -> "582d2dec-c63f-44de-9e6b-a54104bc1f48"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"v3", "@",
|
||||
RowBox[{"\"\<value\>\"", "[", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "2d90fd89-59c8-4b99-94e3-d21a769593fe"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{"7.199999999999999`", ",", "7.`", ",", "8.`", ",", "9.`"}],
|
||||
"}"}]], "Output",
|
||||
ExpressionUUID -> "bebf8d06-f688-4185-b32a-d834e1cd51bd"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[TextData[{
|
||||
"When we gave the symbol ",
|
||||
Cell[BoxData[
|
||||
FormBox["v3", TraditionalForm]]],
|
||||
" a new value, its old value (a ",
|
||||
Cell[BoxData[
|
||||
FormBox["VecExpr", TraditionalForm]]],
|
||||
") no longer had any references to it. Thus ",
|
||||
StyleBox["Mathematica",
|
||||
FontSlant->"Italic"],
|
||||
" has automatically released the corresponding managed library expression. \
|
||||
Notice that ",
|
||||
Cell[BoxData[
|
||||
FormBox[
|
||||
RowBox[{"VecExpr", "[", "3", "]"}], TraditionalForm]],
|
||||
ExpressionUUID -> "ceca620d-5ac9-4ca9-a9bc-a9a3d5d22da7"],
|
||||
" no longer exists."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "80718511-b739-4bdb-9356-f2e06507efcb"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LExpressionList", "[", "VecExpr", "]"}]], "Input",
|
||||
ExpressionUUID -> "ecc5986c-7ad5-4149-bd6d-4336b1616946"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"VecExpr", "[", "1", "]"}], ",",
|
||||
RowBox[{"VecExpr", "[", "2", "]"}], ",",
|
||||
RowBox[{"VecExpr", "[", "4", "]"}]}], "}"}]], "Output",
|
||||
ExpressionUUID -> "f92b408f-6f24-469d-a10c-f2c66e363fdc"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[TextData[{
|
||||
"However, if ",
|
||||
ButtonBox["$HistoryLength",
|
||||
BaseStyle->"Link",
|
||||
ButtonData->"paclet:ref/$HistoryLength"],
|
||||
" had not been set to 0, Out would have been keeping a reference to ",
|
||||
Cell[BoxData[
|
||||
FormBox[
|
||||
RowBox[{"VecExpr", "[", "3", "]"}], TraditionalForm]],
|
||||
ExpressionUUID -> "8c83c4ed-4a84-4699-bb05-3e80f48bbdf3"],
|
||||
", preventing its release."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "38285429-55e5-4415-bb9a-5999782a86ec"],
|
||||
|
||||
Cell[TextData[{
|
||||
"Since library expressions are automatically managed by ",
|
||||
StyleBox["Mathematica",
|
||||
FontSlant->"Italic"],
|
||||
", there is normally no need to release them manually. Thus LTemplate (or ",
|
||||
StyleBox["Mathematica",
|
||||
FontSlant->"Italic"],
|
||||
" itself) does not currently provide a function to do this. Should you want \
|
||||
to do this anyway for some reason, you can use the LibraryLink C API function \
|
||||
",
|
||||
ButtonBox["releaseManagedLibraryExpression",
|
||||
BaseStyle->"Link",
|
||||
ButtonData->
|
||||
"paclet:LibraryLink/ref/callback/releaseManagedLibraryExpression"],
|
||||
", and expose it to ",
|
||||
StyleBox["Mathematica",
|
||||
FontSlant->"Italic"],
|
||||
". This is how e.g. the ",
|
||||
ButtonBox["TriangleDelete",
|
||||
BaseStyle->"Link",
|
||||
ButtonData->"paclet:TriangleLink/ref/TriangleDelete"],
|
||||
" function of ",
|
||||
ButtonBox["TriangleLink",
|
||||
BaseStyle->"Link",
|
||||
ButtonData->"paclet:TriangleLink/guide/TriangleLink"],
|
||||
" works. An example is shown below."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "67beb8c0-7739-42a0-ae14-5d9690809294"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"ManagedLibraryExpressionQ", "[", "v3", "]"}]], "Input",
|
||||
ExpressionUUID -> "489039f5-2f2d-418c-9776-8b3adc53afd5"],
|
||||
|
||||
Cell[BoxData["True"], "Output",
|
||||
ExpressionUUID -> "f7039d15-cdb0-4d95-9622-147c5f3c38a3"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"manager", "=",
|
||||
RowBox[{"Make", "[", "Manager", "]"}]}], ";"}]], "Input",
|
||||
ExpressionUUID -> "6e71477f-6c3b-4768-bc8e-ee292fc77262"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"manager", "@",
|
||||
RowBox[{"\"\<releaseVecExpr\>\"", "[",
|
||||
RowBox[{"ManagedLibraryExpressionID", "[", "v3", "]"}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "22bfe2c8-8279-4e30-8d3b-2f8152cecda3"],
|
||||
|
||||
Cell["\<\
|
||||
The problem with allowing explicit deletions is that it makes it easy to \
|
||||
create expressions which look like they are pointing to a library expression, \
|
||||
but in fact they aren\[CloseCurlyQuote]t (as the library expression was \
|
||||
already released).\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "7bba95eb-45d5-432b-8599-c96392d83558"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData["v3"], "Input",
|
||||
ExpressionUUID -> "3da604e0-ba9f-47b4-b203-36895cc93536"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"VecExpr", "[", "4", "]"}]], "Output",
|
||||
ExpressionUUID -> "fb71ea5a-a9d5-4449-8f4e-233ea6c12c03"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"v3", "@",
|
||||
RowBox[{"\"\<value\>\"", "[", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "89a9dd05-4d44-405b-b1ac-acaee0720f68"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
StyleBox[
|
||||
RowBox[{"LibraryFunction", "::", "noinst"}], "MessageName"], ":",
|
||||
" ", "\<\"Managed library expression instance does not exist. \
|
||||
\\!\\(\\*ButtonBox[\\\"\[RightSkeleton]\\\", ButtonStyle->\\\"Link\\\", \
|
||||
ButtonFrame->None, ButtonData:>\\\"paclet:ref/LibraryFunction\\\", ButtonNote \
|
||||
-> \\\"LibraryFunction::noinst\\\"]\\)\"\>"}]], "Message", "MSG",
|
||||
ExpressionUUID -> "60e15e21-1284-4ec8-a7d0-024e642d2f55"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LibraryFunctionError", "[",
|
||||
RowBox[{"\<\"LIBRARY_FUNCTION_ERROR\"\>", ",", "6"}], "]"}]], "Output",
|
||||
ExpressionUUID -> "6abe0f62-8086-427e-961b-8a1290bb3790"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"ManagedLibraryExpressionQ", "[", "v3", "]"}]], "Input",
|
||||
ExpressionUUID -> "a8d02726-8b03-4c2e-a76b-3384c0da588a"],
|
||||
|
||||
Cell[BoxData["False"], "Output",
|
||||
ExpressionUUID -> "b38befe8-49ab-424f-9870-1781db4ec5ce"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Now there are only two VecExpr left:", "Text",
|
||||
ExpressionUUID -> "eae3d927-cae9-4c84-8ba3-fdea45f77701"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LExpressionList", "[", "VecExpr", "]"}]], "Input",
|
||||
ExpressionUUID -> "799d2977-f1f8-44b8-9d6f-41984193daa7"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"VecExpr", "[", "1", "]"}], ",",
|
||||
RowBox[{"VecExpr", "[", "2", "]"}]}], "}"}]], "Output",
|
||||
ExpressionUUID -> "80c4584b-6ba6-4031-9c3a-423379551aca"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Let us release those too:", "Text",
|
||||
ExpressionUUID -> "7a1bb01e-1cb6-4845-bf28-8f93e2f1b7a6"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{
|
||||
RowBox[{"manager", "@",
|
||||
RowBox[{"\"\<releaseVecExpr\>\"", "[", "#", "]"}]}], "&"}], "/@",
|
||||
RowBox[{"ManagedLibraryExpressionID", "/@",
|
||||
RowBox[{"LExpressionList", "[", "VecExpr", "]"}]}]}]], "Input",
|
||||
ExpressionUUID -> "2c77a682-236c-40fe-9ddf-c4968958628c"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{"Null", ",", "Null"}], "}"}]], "Output",
|
||||
ExpressionUUID -> "e2adcb84-213d-4cac-9e68-b30e25dd99d3"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LExpressionList", "[", "VecExpr", "]"}]], "Input",
|
||||
ExpressionUUID -> "9edfb5c5-1e4c-4e40-b263-6ebab0206733"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{", "}"}]], "Output",
|
||||
ExpressionUUID -> "cfcac460-d9f2-4c84-a1bf-00a65dac3867"]
|
||||
}, Open ]]
|
||||
}, Open ]]
|
||||
},
|
||||
WindowSize->{808, 751},
|
||||
WindowMargins->{{12, Automatic}, {Automatic, 24}},
|
||||
PrivateNotebookOptions->{"FileOutlineCache"->False},
|
||||
TrackCellChangeTimes->False,
|
||||
FrontEndVersion->"10.0 for Mac OS X x86 (32-bit, 64-bit Kernel) (December 4, \
|
||||
2014)",
|
||||
StyleDefinitions->"Default.nb"
|
||||
]
|
||||
|
@ -0,0 +1,13 @@
|
||||
|
||||
#include <LTemplate.h>
|
||||
|
||||
// Dummy class for "free" functions
|
||||
struct Manager {
|
||||
|
||||
// Release a VecExpr
|
||||
void releaseVecExpr(mint id) {
|
||||
int err = mma::libData->releaseManagedLibraryExpression("VecExpr", id);
|
||||
if (err)
|
||||
throw mma::LibraryError("Managed library expression does not exist.");
|
||||
}
|
||||
};
|
@ -0,0 +1,56 @@
|
||||
|
||||
#include <LTemplate.h>
|
||||
#include <vector>
|
||||
#include <numeric>
|
||||
#include <algorithm>
|
||||
|
||||
// A class for arbitrary length real vectors
|
||||
class VecExpr {
|
||||
std::vector<double> vec;
|
||||
|
||||
public:
|
||||
// Set the value of the vector
|
||||
void set(mma::RealTensorRef values) {
|
||||
vec.assign(values.begin(), values.end());
|
||||
}
|
||||
|
||||
// Retrieve the value of the vector
|
||||
mma::RealTensorRef value() const {
|
||||
return mma::makeVector<double>(vec.size(), vec.data());
|
||||
}
|
||||
|
||||
// Inner product with another vector
|
||||
// The integer library expression ID passed to the function is
|
||||
// automatically translated to an object reference (VecExpr &)
|
||||
double inner(const VecExpr &v) const {
|
||||
if (vec.size() != v.vec.size())
|
||||
throw mma::LibraryError("VecExprs are of inconsistent sizes.");
|
||||
return std::inner_product(vec.begin(), vec.end(), v.vec.begin(), 0.0);
|
||||
}
|
||||
|
||||
// Set this vector to the sum of an arbitrary number of other vectors
|
||||
// Currently there is no feature in LTemplate to expose multiple IDs as object references.
|
||||
// Instead, IDs can be translated manually using mma::getInstance().
|
||||
void setToSum(mma::IntTensorRef ids) {
|
||||
if (ids.size() == 0)
|
||||
throw mma::LibraryError("There must be at least one VecExpr to sum.");
|
||||
|
||||
// Get the size of the first vector, and resize this vector
|
||||
const size_t len = mma::getInstance<VecExpr>(ids[0]).vec.size();
|
||||
vec.clear();
|
||||
vec.resize(len, 0.0);
|
||||
|
||||
// Iterate through all library expression IDs
|
||||
for (const auto &id : ids) {
|
||||
VecExpr &ve = mma::getInstance<VecExpr>(id);
|
||||
if (ve.vec.size() != len)
|
||||
throw mma::LibraryError("Mismatch between VecExpr sizes");
|
||||
for (auto it1 = vec.begin(), it2 = ve.vec.begin();
|
||||
it1 != vec.end();
|
||||
++it1, ++it2)
|
||||
{
|
||||
*it1 += *it2;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
@ -0,0 +1,5 @@
|
||||
|
||||
#include "Tensor.h"
|
||||
|
||||
// The IntegerTensor class
|
||||
typedef Tensor<mint> IntegerTensor;
|
120
LTemplate/Documentation/Examples/LinkObject/LinkDemo.h
Normal file
120
LTemplate/Documentation/Examples/LinkObject/LinkDemo.h
Normal file
@ -0,0 +1,120 @@
|
||||
|
||||
#include <LTemplate.h>
|
||||
|
||||
// The mlstream.h header makes it easier to handle argument passing through MathLink
|
||||
#include <mlstream.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
struct LinkDemo {
|
||||
/* When using LinkObject based passing, the function must follow the same conventions
|
||||
* which are described in the LibraryLink tutorial:
|
||||
*
|
||||
* - a single MLINK argument
|
||||
* - void return type
|
||||
*
|
||||
* The arguments are passed in a list, which must be explicitly read off the link.
|
||||
* The usual MathLink functions (mathlink.h) may be used to do this.
|
||||
*/
|
||||
void reverse(MLINK link) {
|
||||
int args = 1;
|
||||
if (!MLTestHeadWithArgCount(link, "List", &args))
|
||||
throw mma::LibraryError("reverse: one argument expected.");
|
||||
const char *str;
|
||||
if (!MLGetString(link, &str))
|
||||
throw mma::LibraryError("reverse: string expected.");
|
||||
std::string s = str;
|
||||
MLReleaseString(link, str);
|
||||
std::reverse(s.begin(), s.end());
|
||||
|
||||
MLNewPacket(link);
|
||||
MLPutString(link, s.c_str());
|
||||
}
|
||||
|
||||
/* LTemplate comes with the mlstream.h auxiliary header, which makes it easier
|
||||
* to read the arguments, check for errors, and return a result.
|
||||
* It uses a streams-like interface.
|
||||
*/
|
||||
void reverse2(MLINK link) {
|
||||
// A "context string" may optionally be passed to mlStream ("reverse2").
|
||||
// This will be prepended to any automatically generated error messages.
|
||||
mlStream ml(link, "reverse2");
|
||||
ml >> mlCheckArgs(1); // expecting a single argument
|
||||
|
||||
std::string str;
|
||||
ml >> str; // read a string
|
||||
std::reverse(str.begin(), str.end()); // reverse it
|
||||
|
||||
ml.newPacket(); // must call newPacket() before returning results; same as MLNewPacket()
|
||||
ml << str; // resturn a single result
|
||||
}
|
||||
|
||||
void addTwo(MLINK link) {
|
||||
mlStream ml(link); // the context string may be omitted
|
||||
ml >> mlCheckArgs(2); // two arguments expected
|
||||
|
||||
mint a, b;
|
||||
ml >> a >> b; // read two integers
|
||||
|
||||
ml.newPacket();
|
||||
ml << a+b; // return their sum
|
||||
}
|
||||
|
||||
// Compute the product and sum of the elements of a list
|
||||
void prodSum(MLINK link) {
|
||||
mlStream ml(link, "prodSum");
|
||||
ml >> mlCheckArgs(1);
|
||||
|
||||
// vectors can be read directly form mlStream
|
||||
std::vector<double> vec;
|
||||
ml >> vec;
|
||||
|
||||
double prod = 1.0;
|
||||
double sum = 0.0;
|
||||
for (const auto &el : vec) {
|
||||
prod *= el;
|
||||
sum += el;
|
||||
}
|
||||
|
||||
ml.newPacket();
|
||||
|
||||
// To return multiple results, they must be explicitly placed into a List
|
||||
ml << mlHead("List", 2) // a list of two elements
|
||||
<< prod << sum; // now put the correct number of list elements
|
||||
}
|
||||
|
||||
// Compute the square root of the elements of a list.
|
||||
void sqrtList(MLINK link) {
|
||||
mlStream ml(link, "sqrtList");
|
||||
ml >> mlCheckArgs(1);
|
||||
|
||||
std::vector<double> vec;
|
||||
ml >> vec;
|
||||
|
||||
for (auto &el : vec)
|
||||
el = std::sqrt(el);
|
||||
|
||||
ml.newPacket();
|
||||
ml << vec; // vectors can be returned directly
|
||||
}
|
||||
|
||||
// Concatenate an arbitrary number of strings
|
||||
void strcat(MLINK link) {
|
||||
mlStream ml(link, "strcat");
|
||||
|
||||
// We do not check for the number of arguments;
|
||||
// instead, we read all arguments into a string vector
|
||||
std::vector<std::string> vec;
|
||||
ml >> vec;
|
||||
|
||||
// Concatenate the strings
|
||||
std::string result;
|
||||
for (const auto &el : vec)
|
||||
result += el;
|
||||
|
||||
ml.newPacket();
|
||||
ml << result;
|
||||
}
|
||||
};
|
632
LTemplate/Documentation/Examples/LinkObject/LinkDemo.nb
Normal file
632
LTemplate/Documentation/Examples/LinkObject/LinkDemo.nb
Normal file
@ -0,0 +1,632 @@
|
||||
Notebook[{
|
||||
|
||||
Cell[CellGroupData[{
|
||||
Cell["LinkObject based passing", "Section",
|
||||
ExpressionUUID -> "5f730c1c-3f28-44e9-a51b-8c18457a0324"],
|
||||
|
||||
Cell["\<\
|
||||
This example demonstrates passing arguments and returning results through a \
|
||||
MathLink connection.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "4931aba6-de17-4b05-9fa9-774e9e7c77b4"],
|
||||
|
||||
Cell[TextData[{
|
||||
ButtonBox["LinkObject-based passing",
|
||||
BaseStyle->"Link",
|
||||
ButtonData->
|
||||
"paclet:paclet:LibraryLink/tutorial/InteractionWithMathematica#306127487"],\
|
||||
|
||||
" provides much more flexibility than using the standard LibraryLink type. \
|
||||
However, it is also much slower. See a benchmark here:"
|
||||
}], "Text",
|
||||
ExpressionUUID -> "2a159845-6072-4bfb-9bec-57f3c1c411bb"],
|
||||
|
||||
Cell[TextData[ButtonBox["https://mathematica.stackexchange.com/questions/\
|
||||
91887/mathlink-wstp-vs-librarylink-performance",
|
||||
BaseStyle->"Hyperlink",
|
||||
ButtonData->{
|
||||
URL["https://mathematica.stackexchange.com/questions/91887/mathlink-wstp-\
|
||||
vs-librarylink-performance/12"], None},
|
||||
ButtonNote->
|
||||
"https://mathematica.stackexchange.com/questions/91887/mathlink-wstp-vs-\
|
||||
librarylink-performance/12"]], "Item",
|
||||
ExpressionUUID -> "16e90e3f-c037-4f85-97cb-622e2139b86d"],
|
||||
|
||||
Cell[BoxData[{
|
||||
RowBox[{
|
||||
RowBox[{"SetDirectory", "@",
|
||||
RowBox[{"NotebookDirectory", "[", "]"}]}], ";"}], "\[IndentingNewLine]",
|
||||
RowBox[{"Needs", "[", "\"\<LTemplate`\>\"", "]"}]}], "Input",
|
||||
ExpressionUUID -> "7e1f28de-1661-4af5-b312-b65eee18d48b"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{
|
||||
RowBox[{"tensorClass", "[", "type_", "]"}], ":=", "\[IndentingNewLine]",
|
||||
RowBox[{"LClass", "[",
|
||||
RowBox[{
|
||||
RowBox[{
|
||||
RowBox[{"ToString", "[", "type", "]"}], "<>", "\"\<Tensor\>\""}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"{", "\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<set\>\"", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"{",
|
||||
RowBox[{"type", ",", "_", ",", "\"\<Manual\>\""}], "}"}], "}"}],
|
||||
",", "\"\<Void\>\""}], "]"}], ",", "\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<value\>\"", ",", "LinkObject"}], "]"}]}],
|
||||
"\[IndentingNewLine]", "}"}]}], "\[IndentingNewLine]", "]"}]}],
|
||||
";"}]], "Input",
|
||||
ExpressionUUID -> "7fda221d-b883-438b-8492-91ba45272041"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"template", "=", "\[IndentingNewLine]",
|
||||
RowBox[{"LTemplate", "[",
|
||||
RowBox[{"\"\<LinkDemo\>\"", ",", "\[IndentingNewLine]",
|
||||
RowBox[{"{", "\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"LClass", "[", "\[IndentingNewLine]",
|
||||
RowBox[{"\"\<LinkDemo\>\"", ",", "\[IndentingNewLine]",
|
||||
RowBox[{"{", "\[IndentingNewLine]",
|
||||
RowBox[{"(*", " ",
|
||||
RowBox[{
|
||||
"LinkObject", " ", "based", " ", "passing", " ", "can", " ", "be",
|
||||
" ", "specified", " ", "in", " ", "the", " ", "same", " ", "was",
|
||||
" ", "as", " ", "in", " ",
|
||||
RowBox[{"LibraryFunctionLoad", ":"}]}], " ", "*)"}],
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<reverse\>\"", ",", "LinkObject", ",", "LinkObject"}],
|
||||
"]"}], ",", "\[IndentingNewLine]", "\[IndentingNewLine]",
|
||||
RowBox[{"(*", " ",
|
||||
RowBox[{
|
||||
RowBox[{"when", " ", "using", " ", "LinkObject"}], "-",
|
||||
RowBox[{
|
||||
"based", " ", "passing", " ", "the", " ", "\"\<return type\>\"",
|
||||
" ", "may", " ", "be", " ",
|
||||
RowBox[{"omitted", ":"}]}]}], " ", "*)"}],
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<reverse2\>\"", ",", "LinkObject"}], "]"}], ",",
|
||||
"\[IndentingNewLine]", "\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<addTwo\>\"", ",", "LinkObject"}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<prodSum\>\"", ",", "LinkObject"}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<sqrtList\>\"", ",", "LinkObject"}], "]"}], ",",
|
||||
"\[IndentingNewLine]", "\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<strcat\>\"", ",", "LinkObject"}], "]"}]}],
|
||||
"\[IndentingNewLine]", "}"}]}], "\[IndentingNewLine]", "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"tensorClass", "[", "Real", "]"}], ",", "\[IndentingNewLine]",
|
||||
|
||||
RowBox[{"tensorClass", "[", "Integer", "]"}]}], "\[IndentingNewLine]",
|
||||
"}"}]}], "\[IndentingNewLine]", "]"}]}], ";"}]], "Input",
|
||||
ExpressionUUID -> "6ed6ee35-ca79-4bb0-a779-b5016009a32b"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"CompileTemplate", "[", "template", "]"}]], "Input",
|
||||
ExpressionUUID -> "8d0172da-dc4a-4a66-b09c-e337af11bcd8"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
InterpretationBox[
|
||||
RowBox[{
|
||||
StyleBox["\<\"Current directory is: \"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\"/Users/szhorvat/Repos/LTemplate/LTemplate/Documentation/\
|
||||
Examples/LinkObject\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]}],
|
||||
SequenceForm[
|
||||
Style["Current directory is: ",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style["/Users/szhorvat/Repos/LTemplate/LTemplate/Documentation/Examples/\
|
||||
LinkObject",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]]],
|
||||
Editable->False]], "Print",
|
||||
ExpressionUUID -> "e76d9baf-6d2d-4e59-9cb8-baa17660b303"],
|
||||
|
||||
Cell[BoxData[
|
||||
InterpretationBox[
|
||||
RowBox[{
|
||||
StyleBox["\<\"Unloading library \"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\"LinkDemo\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\" ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]}],
|
||||
SequenceForm[
|
||||
Style["Unloading library ",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style["LinkDemo",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style[" ...",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]]],
|
||||
Editable->False]], "Print",
|
||||
ExpressionUUID -> "e76d9baf-6d2d-4e59-9cb8-baa17660b303"],
|
||||
|
||||
Cell[BoxData[
|
||||
StyleBox["\<\"Generating library code ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]], "Print",
|
||||
ExpressionUUID -> "e76d9baf-6d2d-4e59-9cb8-baa17660b303"],
|
||||
|
||||
Cell[BoxData[
|
||||
StyleBox["\<\"Compiling library code ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]], "Print",
|
||||
ExpressionUUID -> "e76d9baf-6d2d-4e59-9cb8-baa17660b303"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[BoxData["\<\"/Users/szhorvat/Library/Mathematica/SystemFiles/\
|
||||
LibraryResources/MacOSX-x86-64/LinkDemo.dylib\"\>"], "Output",
|
||||
ExpressionUUID -> "d37d7b4d-0a60-4c6d-8488-1f8db5b9cd9c"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LoadTemplate", "[", "template", "]"}]], "Input",
|
||||
ExpressionUUID -> "59006634-acdc-465c-b23b-3388f0d02058"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell["Basics", "Subsubsection",
|
||||
ExpressionUUID -> "08e1f854-767a-473e-8e37-517fdd8ddebd"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "=",
|
||||
RowBox[{"Make", "[", "LinkDemo", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "1e7436af-1b46-4b2c-8438-da9f2d814fc6"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LinkDemo", "[", "1", "]"}]], "Output",
|
||||
ExpressionUUID -> "2fd1917c-d3a5-4176-bf57-64c85cf81023"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Reverse a string.", "Text",
|
||||
ExpressionUUID -> "bd40472f-b3f6-49b9-b999-b23b80b8d65c"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<reverse\>\"", "[", "\"\<Dennis sinned.\>\"", "]"}]}]], "Input",
|
||||
|
||||
ExpressionUUID -> "a98933ac-d478-4d94-b8a5-017add059ddf"],
|
||||
|
||||
Cell[BoxData["\<\".dennis sinneD\"\>"], "Output",
|
||||
ExpressionUUID -> "5b6b0ce7-bf9e-4a0a-beb0-bf18e6f04d74"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[TextData[{
|
||||
Cell[BoxData[
|
||||
FormBox[
|
||||
RowBox[{"reverse2", "[", "]"}], TraditionalForm]],
|
||||
ExpressionUUID -> "a39e405b-bd6b-4ffd-88ae-d8630e0b50c5"],
|
||||
" is a simpler implementation of the same using mlstream.h."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "bb67809e-d820-4b43-82ac-184e311a9412"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<reverse2\>\"", "[", "\"\<Dennis sinned.\>\"", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "f6aa51a4-2dd7-423f-bce3-4513fd0125a8"],
|
||||
|
||||
Cell[BoxData["\<\".dennis sinneD\"\>"], "Output",
|
||||
ExpressionUUID -> "d37f147a-0ac4-46e7-98d7-c4cc7aba007d"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Error checking is included.", "Text",
|
||||
ExpressionUUID -> "a7d2e878-5009-49f2-a72e-ef03395e781e"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<reverse2\>\"", "[",
|
||||
RowBox[{"\"\<foo\>\"", ",", "\"\<bar\>\""}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "bcd06e5b-36da-4c50-b2aa-2d44abbd9988"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
StyleBox[
|
||||
RowBox[{"LTemplate", "::", "error"}], "MessageName"], ":",
|
||||
" ", "\<\"\[NoBreak]\\!\\(\\\"reverse2: 1 argument expected, 2 \
|
||||
received.\\\"\\)\[NoBreak]\"\>"}]], "Message", "MSG",
|
||||
ExpressionUUID -> "b555dda9-2a07-4886-b6da-17876773c66b"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LibraryFunctionError", "[",
|
||||
RowBox[{"\<\"LIBRARY_FUNCTION_ERROR\"\>", ",", "6"}], "]"}]], "Output",
|
||||
ExpressionUUID -> "f9b75ce4-5529-4e24-b633-712187be51c9"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["\<\
|
||||
Note that any type that can be converted to a string can be read off the link \
|
||||
as a string. Passing a number of a symbol to the function won\
|
||||
\[CloseCurlyQuote]t result in an error.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "a33d738a-83e5-4bb3-9305-a0df47aeca31"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<reverse2\>\"", "[", "123", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "2c12bcb8-71bc-490b-8623-281fcf54be92"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LibraryFunctionError", "[",
|
||||
RowBox[{"\<\"LIBRARY_FUNCTION_ERROR\"\>", ",", "6"}], "]"}]], "Output",
|
||||
ExpressionUUID -> "391dec1a-5613-404c-a85f-a2748b02099a"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<reverse2\>\"", "[", "symbol", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "ce6d7519-b297-46db-a4cb-b9f4eadc92bd"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LibraryFunctionError", "[",
|
||||
RowBox[{"\<\"LIBRARY_FUNCTION_ERROR\"\>", ",", "6"}], "]"}]], "Output",
|
||||
ExpressionUUID -> "8b8513d6-caf5-42be-9b2c-d9120ea125d9"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Add two numbers.", "Text",
|
||||
ExpressionUUID -> "c860b0f5-793b-4044-b233-68f8ed268664"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<addTwo\>\"", "[",
|
||||
RowBox[{"4", ",", "5"}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "21fee05f-283c-47d5-8e33-67738d4056ff"],
|
||||
|
||||
Cell[BoxData["9"], "Output",
|
||||
ExpressionUUID -> "1087ed51-42a8-4123-9ede-2e01f1570227"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["\<\
|
||||
This function tried to read integers from the link. Strings are not \
|
||||
convertible to integers, thus with string arguments an error occurs.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "4036c2fe-bb2b-478d-a988-cd0f1293ce8d"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<addTwo\>\"", "[",
|
||||
RowBox[{"\"\<a\>\"", ",", "\"\<b\>\""}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "91cc4482-9505-4651-8154-a95ad14c6a0c"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
StyleBox[
|
||||
RowBox[{"LTemplate", "::", "error"}], "MessageName"], ":",
|
||||
" ", "\<\"\[NoBreak]\\!\\(\\\"Integer64 expected.\\\"\\)\[NoBreak]\"\>"}]], \
|
||||
"Message", "MSG",
|
||||
ExpressionUUID -> "304bb7e1-9adc-4e7f-942f-01f0825f3dbc"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LibraryFunctionError", "[",
|
||||
RowBox[{"\<\"LIBRARY_FUNCTION_ERROR\"\>", ",", "6"}], "]"}]], "Output",
|
||||
ExpressionUUID -> "afffa030-4085-4308-aab6-6ec8e9c32ec1"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["\<\
|
||||
Compute both the produce and sum of an arbitrary-length real list:\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "e849ad0c-2ecf-48e8-983c-81f1386ae91b"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<prodSum\>\"", "[",
|
||||
RowBox[{"Range", "[", "5", "]"}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "2f44c694-4ca8-433b-94f2-27abc3141a04"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{"120.`", ",", "15.`"}], "}"}]], "Output",
|
||||
ExpressionUUID -> "1094a56a-a80b-462b-840f-58cee58e6773"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Error checking is always available.", "Text",
|
||||
ExpressionUUID -> "2cf21cf2-59b7-4c24-b199-4af38484f52b"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<prodSum\>\"", "[", "12", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "5b320d7a-5956-46da-a48d-f4f574ebadaa"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
StyleBox[
|
||||
RowBox[{"LTemplate", "::", "error"}], "MessageName"], ":",
|
||||
" ", "\<\"\[NoBreak]\\!\\(\\\"prodSum: Real64 list expected.\\\"\\)\
|
||||
\[NoBreak]\"\>"}]], "Message", "MSG",
|
||||
ExpressionUUID -> "a41bf603-f9d2-45a8-8d8b-4022c4c70f8b"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LibraryFunctionError", "[",
|
||||
RowBox[{"\<\"LIBRARY_FUNCTION_ERROR\"\>", ",", "6"}], "]"}]], "Output",
|
||||
ExpressionUUID -> "113724dd-0d3d-4801-9fa9-5f2060057e6b"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Compute the square root of each element in a list.", "Text",
|
||||
ExpressionUUID -> "8552624d-d3e3-4eba-8f30-6e851b28f019"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<sqrtList\>\"", "[",
|
||||
RowBox[{"Range", "[", "5", "]"}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "7f1ab8a6-56b6-41f8-bf9a-3af150053cbc"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
"1.`", ",", "1.4142135623730951`", ",", "1.7320508075688772`", ",", "2.`",
|
||||
",", "2.23606797749979`"}], "}"}]], "Output",
|
||||
ExpressionUUID -> "ce544aaa-ab16-4957-a9a5-7f51c821ed19"]
|
||||
}, Open ]]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell["Variable number of arguments", "Subsubsection",
|
||||
ExpressionUUID -> "5c32a900-84ca-4881-a485-00251fe436d5"],
|
||||
|
||||
Cell["Concatenate an arbitrary number of string arguments.", "Text",
|
||||
ExpressionUUID -> "edcf9a77-da24-4df1-87ab-ce9030a26ea5"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<strcat\>\"", "[",
|
||||
RowBox[{"\"\<foo\>\"", ",", "\"\<bar\>\""}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "1afd7a38-c3ee-41a3-8de9-ee8450f60dcb"],
|
||||
|
||||
Cell[BoxData["\<\"foobar\"\>"], "Output",
|
||||
ExpressionUUID -> "3724c723-f575-4b87-8e55-ae6cc8127c56"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<strcat\>\"", "[",
|
||||
RowBox[{"\"\<foo\>\"", ",", "\"\<bar\>\"", ",", "\"\<baz\>\""}],
|
||||
"]"}]}]], "Input",
|
||||
ExpressionUUID -> "406b2ff3-f017-4177-aeb1-29b0d905032b"],
|
||||
|
||||
Cell[BoxData["\<\"foobarbaz\"\>"], "Output",
|
||||
ExpressionUUID -> "4670280e-25f6-493f-a02b-4bd42d8a2f11"]
|
||||
}, Open ]]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell["Returning MTensors", "Subsubsection",
|
||||
ExpressionUUID -> "06a99056-bbd9-43a7-8dfc-beac65d7c439"],
|
||||
|
||||
Cell["\<\
|
||||
mlstream.h supports directly returning Real and Integer Tensors.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "09498a36-b2a2-41c3-b8f6-2e4e19ad55df"],
|
||||
|
||||
Cell[TextData[{
|
||||
"The following function creates a new instance of the RealTensor or \
|
||||
IntegerTensor class. These two were included in the template specification \
|
||||
using the helper function ",
|
||||
Cell[BoxData[
|
||||
FormBox[
|
||||
RowBox[{"tensorClass", "[", "]"}], TraditionalForm]],
|
||||
ExpressionUUID -> "b452462b-1341-47f3-b457-0b918f8ee2b1"],
|
||||
". In C++, they share code using the template mechanism."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "621670d4-eb5a-4acc-a241-825977492d90"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"makeTensor", "[",
|
||||
RowBox[{"array_", ",", "type_"}], "]"}], ":=", "\[IndentingNewLine]",
|
||||
RowBox[{"Module", "[",
|
||||
RowBox[{
|
||||
RowBox[{"{", "ten", "}"}], ",", "\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"ten", "=",
|
||||
RowBox[{"Make", "[",
|
||||
RowBox[{
|
||||
RowBox[{"<|",
|
||||
RowBox[{
|
||||
RowBox[{"Real", "\[Rule]", "RealTensor"}], ",",
|
||||
RowBox[{"Integer", "\[Rule]", "IntegerTensor"}]}], "|>"}], "[",
|
||||
"type", "]"}], "]"}]}], ";", "\[IndentingNewLine]",
|
||||
RowBox[{"If", "[",
|
||||
RowBox[{
|
||||
RowBox[{
|
||||
RowBox[{"ten", "@",
|
||||
RowBox[{"\"\<set\>\"", "[", "array", "]"}]}], "=!=", "Null"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"Return", "[", "$Failed", "]"}]}], "\[IndentingNewLine]",
|
||||
"]"}], ";", "\[IndentingNewLine]", "ten"}]}], "\[IndentingNewLine]",
|
||||
"]"}]}]], "Input",
|
||||
ExpressionUUID -> "913bdc3f-0cfd-4271-af0a-348be33d0e6e"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"ten1", "=",
|
||||
RowBox[{"makeTensor", "[",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"1", ",", "2", ",", "3"}], "}"}], ",", "Integer"}],
|
||||
"]"}]}]], "Input",
|
||||
ExpressionUUID -> "71f268f0-674f-4793-b78a-55e022318aa1"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"IntegerTensor", "[", "1", "]"}]], "Output",
|
||||
ExpressionUUID -> "944b9e6b-97b7-4a5e-be9b-de773cf27c89"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"ten1", "@",
|
||||
RowBox[{"\"\<value\>\"", "[", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "c72d872c-9871-42f9-8d67-d6c0e0a85a7d"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{"1", ",", "2", ",", "3"}], "}"}]], "Output",
|
||||
ExpressionUUID -> "2f9afaf1-d14d-4b7b-8fe7-1d09d69e6862"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"ten2", "=",
|
||||
RowBox[{"makeTensor", "[",
|
||||
RowBox[{
|
||||
RowBox[{"RandomReal", "[",
|
||||
RowBox[{"1", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"2", ",", "3"}], "}"}]}], "]"}], ",", "Real"}],
|
||||
"]"}]}]], "Input",
|
||||
ExpressionUUID -> "cc26659c-f597-40ac-8287-a597920b2766"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"RealTensor", "[", "1", "]"}]], "Output",
|
||||
ExpressionUUID -> "a6b494e9-c508-4cc9-b787-097e8f29232d"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"ten2", "@",
|
||||
RowBox[{"\"\<value\>\"", "[", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "1717bae0-cbf6-4060-9d05-1af1d6084804"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
"0.4400929447288291`", ",", "0.35580944983968976`", ",",
|
||||
"0.6226563927874686`"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
"0.07763187725628051`", ",", "0.3081456393842128`", ",",
|
||||
"0.19111291592768676`"}], "}"}]}], "}"}]], "Output",
|
||||
ExpressionUUID -> "db5c0e01-d1c0-42a1-80bf-6f83a0d5f478"]
|
||||
}, Open ]]
|
||||
}, Open ]]
|
||||
}, Open ]]
|
||||
},
|
||||
WindowSize->{808, 751},
|
||||
WindowMargins->{{4, Automatic}, {Automatic, 4}},
|
||||
PrivateNotebookOptions->{"FileOutlineCache"->False},
|
||||
TrackCellChangeTimes->False,
|
||||
FrontEndVersion->"10.0 for Mac OS X x86 (32-bit, 64-bit Kernel) (December 4, \
|
||||
2014)",
|
||||
StyleDefinitions->"Default.nb"
|
||||
]
|
||||
|
5
LTemplate/Documentation/Examples/LinkObject/RealTensor.h
Normal file
5
LTemplate/Documentation/Examples/LinkObject/RealTensor.h
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
#include "Tensor.h"
|
||||
|
||||
// The RealTensor class.
|
||||
typedef Tensor<double> RealTensor;
|
42
LTemplate/Documentation/Examples/LinkObject/Tensor.h
Normal file
42
LTemplate/Documentation/Examples/LinkObject/Tensor.h
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
#ifndef TENSOR_H
|
||||
#define TENSOR_H
|
||||
|
||||
#include <LTemplate.h>
|
||||
#include <mlstream.h>
|
||||
|
||||
// Class representing a Tensor.
|
||||
// It is specialized for Real and Integer tensors in RealTensor.h and IntegerTensor.h.
|
||||
// This is because LTemplate requires a separate header file for each class.
|
||||
template<typename T>
|
||||
class Tensor {
|
||||
mma::TensorRef<T> *rt = nullptr;
|
||||
|
||||
void free() {
|
||||
if (rt) {
|
||||
rt->free();
|
||||
delete rt;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
~Tensor() { free(); }
|
||||
|
||||
// Set Tensor value; meant to be used in conjunction with Make[]
|
||||
void set(mma::TensorRef<T> t) {
|
||||
free();
|
||||
rt = new mma::TensorRef<T>(t);
|
||||
}
|
||||
|
||||
// Retrieve Tensor value using MathLink
|
||||
void value(MLINK ml) {
|
||||
if (! rt)
|
||||
throw mma::LibraryError("No tensor set.");
|
||||
mlStream link(ml);
|
||||
link >> mlCheckArgs(0);
|
||||
link.newPacket();
|
||||
link << *rt;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // TENSOR_H
|
51
LTemplate/Documentation/Examples/NumericArray/NA.h
Normal file
51
LTemplate/Documentation/Examples/NumericArray/NA.h
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
#include <LTemplate.h>
|
||||
|
||||
class NA {
|
||||
public:
|
||||
// Store the data from a Real Tensor in a Byte NumericArray and shuffle the byte storage order
|
||||
mma::NumericArrayRef<uint8_t> shuffle(mma::RealTensorRef t) {
|
||||
const uint8_t *data = reinterpret_cast<uint8_t *>(t.data());
|
||||
auto na = mma::makeNumericVector<uint8_t>(t.size() * sizeof(double));
|
||||
for (int i=0; i < sizeof(double); ++i)
|
||||
for (int j=0; j < t.size(); ++j)
|
||||
na[i*t.size() + j] = data[j*sizeof(double) + i];
|
||||
return na;
|
||||
}
|
||||
|
||||
// Reverse the transformation done by shuffle()
|
||||
mma::RealTensorRef deshuffle(mma::NumericArrayRef<uint8_t> na) {
|
||||
if (na.size() % sizeof(double) != 0)
|
||||
throw mma::LibraryError("Input size must be a multiple of 8.");
|
||||
auto t = mma::makeVector<double>(na.size() / sizeof(double));
|
||||
uint8_t *data = reinterpret_cast<uint8_t *>(t.data());
|
||||
for (int i=0; i < sizeof(double); ++i)
|
||||
for (int j=0; j < t.size(); ++j)
|
||||
data[j*sizeof(double) + i] = na[i*t.size() + j];
|
||||
return t;
|
||||
}
|
||||
|
||||
// Convert an arbitrary NumericArray into a Byte NumericArray. Use the default conversion method,
|
||||
// which is to clip and round values not representable as the target type.
|
||||
mma::NumericArrayRef<uint8_t> clipToBytes(mma::GenericNumericArrayRef na) {
|
||||
return na.convertTo<uint8_t>();
|
||||
}
|
||||
|
||||
// Convert an arbitrary type NumericArray into a Byte NumericArray. Use the Check conversion method,
|
||||
// which will verify that all values fit in the target type, and throw a LibraryError exception if they don't.
|
||||
mma::NumericArrayRef<uint8_t> safeConvertToBytes(mma::GenericNumericArrayRef na) {
|
||||
return na.convertTo<uint8_t>(mma::GenericNumericArrayRef::Check);
|
||||
}
|
||||
|
||||
// Convert an arbitrary type NumericArray into a Real32 NumericArray
|
||||
// using the chosen conversion method and tolerance.
|
||||
mma::NumericArrayRef<float> convertToFloat(mma::GenericNumericArrayRef na, mint method, double tolerance) {
|
||||
return na.convertTo<float>(mma::GenericNumericArrayRef::ConversionMethod(method), tolerance);
|
||||
}
|
||||
|
||||
// Convert an arbitrary type NumericArray into a Integer16 NumericArray
|
||||
// using the chosen conversion method and tolerance.
|
||||
mma::NumericArrayRef<int16_t> convertToInteger16(mma::GenericNumericArrayRef na, mint method, double tolerance) {
|
||||
return na.convertTo<int16_t>(mma::GenericNumericArrayRef::ConversionMethod(method), tolerance);
|
||||
}
|
||||
};
|
94515
LTemplate/Documentation/Examples/NumericArray/NA.nb
Normal file
94515
LTemplate/Documentation/Examples/NumericArray/NA.nb
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,75 @@
|
||||
|
||||
#include <LTemplate.h>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
class Printing {
|
||||
mint positiveValue = 1;
|
||||
|
||||
public:
|
||||
/* Throw an mma::LibraryError exception in case of errors.
|
||||
* The associated message will be printed directly in the notebook.
|
||||
*/
|
||||
void set(mint x) {
|
||||
if (x <= 0)
|
||||
throw mma::LibraryError("The value must be positive.");
|
||||
positiveValue = x;
|
||||
}
|
||||
|
||||
// Print a C string or an std::string
|
||||
void hello() const {
|
||||
mma::print("Hello world!");
|
||||
}
|
||||
|
||||
/* The most convenient way to show a complex message is to use the
|
||||
* stream interface mma::out.
|
||||
*
|
||||
* Note that the output is only printed to the notebook when the
|
||||
* mma::mout buffer is flushed. This is most easily accomplished
|
||||
* by inserting an std::endl into the stream. Flushing effectively
|
||||
* starts a new notebook cell.
|
||||
*
|
||||
* Due to how Mathematica's Print[] works, a newline is always
|
||||
* inserted at the end of the output, whether or not it was explicitly
|
||||
* sent to mma::mout.
|
||||
*
|
||||
* The buffer is always flushed when the library function exits,
|
||||
* thus the std::endl below is not strictly required.
|
||||
*/
|
||||
void printValue() const {
|
||||
mma::mout << "My value is " << positiveValue << "!" << std::endl;
|
||||
}
|
||||
|
||||
// Issue a message in Mathematica as LTemplate::info
|
||||
void message(const char *msg) const {
|
||||
mma::message(msg);
|
||||
mma::disownString(msg); // release the string sent by the kernel
|
||||
}
|
||||
|
||||
// Issue an error message in Mathematica as LTemplate::error
|
||||
void errorMessage(const char *msg) const {
|
||||
mma::message(msg, mma::M_ERROR);
|
||||
mma::disownString(msg); // release the string sent by the kernel
|
||||
}
|
||||
|
||||
// Use std::ostringstream to build a more complex message
|
||||
void messageValue() const {
|
||||
std::ostringstream msg;
|
||||
msg << "The value is " << positiveValue << ".";
|
||||
mma::message(msg.str());
|
||||
}
|
||||
|
||||
/* The massert macro can be used in place of the standard C assert macro.
|
||||
* Instead of aborting the entire kernel process, it will simply return
|
||||
* from the library, and print the assertion failure message in the notebook.
|
||||
*/
|
||||
void assertDemo() const {
|
||||
massert(42 == 137);
|
||||
}
|
||||
|
||||
// This function demonstrates catching arbitrary exceptions
|
||||
void exception() const {
|
||||
std::vector<int> vec = {1,2,3};
|
||||
vec.at(4); // out-of-bounds error, throws std::out_of_range exception
|
||||
}
|
||||
};
|
449
LTemplate/Documentation/Examples/PrintingAndMessages/Printing.nb
Normal file
449
LTemplate/Documentation/Examples/PrintingAndMessages/Printing.nb
Normal file
@ -0,0 +1,449 @@
|
||||
Notebook[{
|
||||
|
||||
Cell[CellGroupData[{
|
||||
Cell["Printing messages from an LTemplate library", "Section",
|
||||
ExpressionUUID -> "1afcf7ff-2148-49b1-bca3-c1d27cb68e11"],
|
||||
|
||||
Cell[TextData[{
|
||||
"This example illustrates how to print from a library into a notebook (as in \
|
||||
",
|
||||
ButtonBox["Print",
|
||||
BaseStyle->"Link",
|
||||
ButtonData->"paclet:ref/Print"],
|
||||
"), and how to issue messages (as in ",
|
||||
ButtonBox["Message",
|
||||
BaseStyle->"Link",
|
||||
ButtonData->"paclet:ref/Print"],
|
||||
"), as well as other features useful for error reporting or debugging."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "5e0c3751-73d6-48b8-a521-a495e915b9b5"],
|
||||
|
||||
Cell[BoxData[{
|
||||
RowBox[{"Needs", "[", "\"\<LTemplate`\>\"", "]"}], "\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"SetDirectory", "@",
|
||||
RowBox[{"NotebookDirectory", "[", "]"}]}], ";"}]}], "Input",
|
||||
ExpressionUUID -> "04ef3909-ebdf-4f84-88f6-fe52710284f9"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"template", "=", "\[IndentingNewLine]",
|
||||
RowBox[{"LClass", "[",
|
||||
RowBox[{"\"\<Printing\>\"", ",", "\[IndentingNewLine]",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<set\>\"", ",",
|
||||
RowBox[{"{", "Integer", "}"}], ",", "\"\<Void\>\""}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<hello\>\"", ",",
|
||||
RowBox[{"{", "}"}], ",", "\"\<Void\>\""}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<printValue\>\"", ",",
|
||||
RowBox[{"{", "}"}], ",", "\"\<Void\>\""}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<message\>\"", ",",
|
||||
RowBox[{"{", "\"\<UTF8String\>\"", "}"}], ",", "\"\<Void\>\""}],
|
||||
"]"}], ",", "\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<errorMessage\>\"", ",",
|
||||
RowBox[{"{", "\"\<UTF8String\>\"", "}"}], ",", "\"\<Void\>\""}],
|
||||
"]"}], ",", "\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<messageValue\>\"", ",",
|
||||
RowBox[{"{", "}"}], ",", "\"\<Void\>\""}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<assertDemo\>\"", ",",
|
||||
RowBox[{"{", "}"}], ",", "\"\<Void\>\""}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<exception\>\"", ",",
|
||||
RowBox[{"{", "}"}], ",", "\"\<Void\>\""}], "]"}]}],
|
||||
"\[IndentingNewLine]", "}"}]}], "\[IndentingNewLine]", "]"}]}],
|
||||
";"}]], "Input",
|
||||
ExpressionUUID -> "5992e7b7-1044-4d77-8909-7c0400320a42"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"CompileTemplate", "[", "template", "]"}]], "Input",
|
||||
ExpressionUUID -> "030e9f79-2e4b-4b44-8c70-062e521e3c35"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
InterpretationBox[
|
||||
RowBox[{
|
||||
StyleBox["\<\"Current directory is: \"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\"/Users/szhorvat/Repos/LTemplate/LTemplate/Documentation/\
|
||||
Examples/PrintingAndMessages\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]}],
|
||||
SequenceForm[
|
||||
Style["Current directory is: ",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style["/Users/szhorvat/Repos/LTemplate/LTemplate/Documentation/Examples/\
|
||||
PrintingAndMessages",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]]],
|
||||
Editable->False]], "Print",
|
||||
ExpressionUUID -> "35331c6b-de6a-4b9f-844e-603973de16b9"],
|
||||
|
||||
Cell[BoxData[
|
||||
InterpretationBox[
|
||||
RowBox[{
|
||||
StyleBox["\<\"Unloading library \"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\"Printing\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\" ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]}],
|
||||
SequenceForm[
|
||||
Style["Unloading library ",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style["Printing",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style[" ...",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]]],
|
||||
Editable->False]], "Print",
|
||||
ExpressionUUID -> "35331c6b-de6a-4b9f-844e-603973de16b9"],
|
||||
|
||||
Cell[BoxData[
|
||||
StyleBox["\<\"Generating library code ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]], "Print",
|
||||
ExpressionUUID -> "35331c6b-de6a-4b9f-844e-603973de16b9"],
|
||||
|
||||
Cell[BoxData[
|
||||
StyleBox["\<\"Compiling library code ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]], "Print",
|
||||
ExpressionUUID -> "35331c6b-de6a-4b9f-844e-603973de16b9"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[BoxData["\<\"/Users/szhorvat/Library/Mathematica/SystemFiles/\
|
||||
LibraryResources/MacOSX-x86-64/Printing.dylib\"\>"], "Output",
|
||||
ExpressionUUID -> "8a7e178c-7e8d-4096-b074-63b7ee78f393"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LoadTemplate", "[", "template", "]"}]], "Input",
|
||||
ExpressionUUID -> "f2c79f41-1ae4-4b80-9037-7ef180f26b82"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"expr", "=",
|
||||
RowBox[{"Make", "[", "Printing", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "6e6482a9-786c-4c70-9e9f-f997dd8d8fb6"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"Printing", "[", "1", "]"}]], "Output",
|
||||
ExpressionUUID -> "fc669461-212f-400d-a861-6265724e6d55"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[TextData[{
|
||||
"Throwing a mma::LibraryError object causes the associated error message to \
|
||||
be shown as an ",
|
||||
Cell[BoxData[
|
||||
FormBox[
|
||||
RowBox[{"LTemplate", "::", "error"}], TraditionalForm]],
|
||||
ExpressionUUID -> "ac3ead2e-094d-4bd9-a11a-2ad688c223d0"],
|
||||
" message in the notebook."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "ce4ad3db-ccbc-427b-8167-f14db2a6dd07"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"expr", "@",
|
||||
RowBox[{"\"\<set\>\"", "[",
|
||||
RowBox[{"-", "1"}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "4576c374-6ce1-44cb-ab66-317041a79b37"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
StyleBox[
|
||||
RowBox[{"LTemplate", "::", "error"}], "MessageName"], ":",
|
||||
" ", "\<\"\[NoBreak]\\!\\(\\\"The value must be \
|
||||
positive.\\\"\\)\[NoBreak]\"\>"}]], "Message", "MSG",
|
||||
ExpressionUUID -> "655db173-eb2d-4167-808e-f1d194644760"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LibraryFunctionError", "[",
|
||||
RowBox[{"\<\"LIBRARY_FUNCTION_ERROR\"\>", ",", "6"}], "]"}]], "Output",
|
||||
ExpressionUUID -> "07f2da4a-e2b3-46fc-a5ee-83a14302b2a3"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"expr", "@",
|
||||
RowBox[{"\"\<set\>\"", "[", "42", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "67abd17d-c6c3-42a0-857a-83db6147921e"],
|
||||
|
||||
Cell[TextData[{
|
||||
"Printing directly into the notebook, as with ",
|
||||
Cell[BoxData[
|
||||
FormBox["Print", TraditionalForm]],
|
||||
FormatType->"TraditionalForm"],
|
||||
":"
|
||||
}], "Text",
|
||||
ExpressionUUID -> "7ca22b0f-a792-43c9-b519-d35e6babb132"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"expr", "@",
|
||||
RowBox[{"\"\<hello\>\"", "[", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "9e5da1b1-e270-43a7-9d4d-8a567bff464a"],
|
||||
|
||||
Cell[BoxData["\<\"Hello world!\"\>"], "Print",
|
||||
ExpressionUUID -> "b4ef3684-611a-4813-b24e-061f50960a34"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"expr", "@",
|
||||
RowBox[{"\"\<printValue\>\"", "[", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "18e2ac87-f132-4ee9-8370-63689269e88e"],
|
||||
|
||||
Cell[BoxData["\<\"My value is 42!\"\>"], "Print",
|
||||
ExpressionUUID -> "3a93b2df-2159-4424-9afd-35b017268e1b"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Issuing messages directly from the library:", "Text",
|
||||
ExpressionUUID -> "51d2ae64-0a11-4939-8ab7-7fd41d857685"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"expr", "@",
|
||||
RowBox[{
|
||||
"\"\<message\>\"", "[", "\"\<Hello from Message!\>\"", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "058c1324-2d04-478c-aa00-f0fc62d1ea60"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
StyleBox[
|
||||
RowBox[{"LTemplate", "::", "info"}], "MessageName"], ":",
|
||||
" ", "\<\"\[NoBreak]\\!\\(\\\"Hello from Message!\\\"\\)\[NoBreak]\"\>"}]], \
|
||||
"Message", "MSG",
|
||||
ExpressionUUID -> "424eee77-650c-42ae-a335-e550cf345d42"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"expr", "@",
|
||||
RowBox[{
|
||||
"\"\<errorMessage\>\"", "[", "\"\<Error encountered.\>\"",
|
||||
"]"}]}]], "Input"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
StyleBox[
|
||||
RowBox[{"LTemplate", "::", "error"}], "MessageName"], ":",
|
||||
" ", "\<\"\[NoBreak]\\!\\(\\\"Error encountered.\\\"\\)\[NoBreak]\"\>"}]], \
|
||||
"Message", "MSG"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"expr", "@",
|
||||
RowBox[{"\"\<messageValue\>\"", "[", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "85bf86be-5305-4ee7-8ed8-38ab0e81753e"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
StyleBox[
|
||||
RowBox[{"LTemplate", "::", "info"}], "MessageName"], ":",
|
||||
" ", "\<\"\[NoBreak]\\!\\(\\\"The value is 42.\\\"\\)\[NoBreak]\"\>"}]], \
|
||||
"Message", "MSG",
|
||||
ExpressionUUID -> "e2b1d362-349e-499f-bd0f-70e0e1d3d89a"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[TextData[{
|
||||
"There are three basic types of messages to choose from ",
|
||||
Cell[BoxData[
|
||||
FormBox[
|
||||
RowBox[{"LTemplate", "::", "info"}], TraditionalForm]],
|
||||
ExpressionUUID -> "0334245a-ecf7-45ac-a4ef-ee0eb08eff26"],
|
||||
", ",
|
||||
Cell[BoxData[
|
||||
FormBox[
|
||||
RowBox[{"LTemplate", "::", "warning"}], TraditionalForm]],
|
||||
ExpressionUUID -> "d41a1c79-ca68-4078-9fb4-70d5f993ef7b"],
|
||||
" ",
|
||||
Cell[BoxData[
|
||||
FormBox[
|
||||
RowBox[{"LTemplate", "::", "error"}], TraditionalForm]],
|
||||
ExpressionUUID -> "cfb885ab-e547-4d18-98e5-69659ca41971"],
|
||||
". Additionally, ",
|
||||
Cell[BoxData[
|
||||
FormBox[
|
||||
RowBox[{"LTemplate", "::", "assert"}], TraditionalForm]],
|
||||
ExpressionUUID -> "a192dfa9-f3ee-4892-bf5f-44a9af66177d"],
|
||||
" is used by the massert() macro. When embedding LTemplate into another \
|
||||
package, the symbol with which message are associated can be changed to \
|
||||
something else than ",
|
||||
Cell[BoxData[
|
||||
FormBox["LTemplate", TraditionalForm]],
|
||||
ExpressionUUID -> "1ede47f2-1366-4123-b323-006b08763669"],
|
||||
". See the skeleton project included in the LTemplate distribution to see \
|
||||
how this is accomplished."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "2ec5a785-d7e5-4ef2-af22-5d6194dce795"],
|
||||
|
||||
Cell["\<\
|
||||
LTemplate.h provides the massert() macro as a replacement for the standard C \
|
||||
assert() macro. Unlike assert(), massert() will not terminate the kernel \
|
||||
process. Instead, it prints the assertion failure message directly into the \
|
||||
notebook and returns from the library function.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "fdcf12aa-5d3d-4cb6-a0fb-f0d4f438e6a8"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"expr", "@",
|
||||
RowBox[{"\"\<assertDemo\>\"", "[", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "ee1c42ba-786d-4ccc-9aa2-2c8f5fc998fb"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
StyleBox[
|
||||
RowBox[{"LTemplate", "::", "assert"}], "MessageName"], ":",
|
||||
" ", "\<\"Assertion failed: \[NoBreak]\\!\\(\\\"42 == 137, file \
|
||||
/Users/szhorvat/Repos/LTemplate/LTemplate/Documentation/Examples/\
|
||||
PrintingAndMessages/Printing.h, line 67\\\"\\)\[NoBreak].\"\>"}]], "Message", \
|
||||
"MSG",
|
||||
ExpressionUUID -> "dcf44bc0-82df-49b6-8b39-f851369c95ce"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LibraryFunctionError", "[",
|
||||
RowBox[{"\<\"LIBRARY_FUNCTION_ERROR\"\>", ",", "6"}], "]"}]], "Output",
|
||||
ExpressionUUID -> "3f981706-4bd3-4bfd-bed2-3d21b962aefd"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[TextData[{
|
||||
"LTemplate functions will catch ",
|
||||
StyleBox["all",
|
||||
FontSlant->"Italic"],
|
||||
" C++ exceptions to avoid killing the kernel. For exceptions different from \
|
||||
mma::LibraryError a warning message is shown: uncaught exceptions can \
|
||||
indicate a serious error in the library, possibly even memory corruption, \
|
||||
thus it is best to restart the kernel session. If the exception derives from \
|
||||
std::exception, the what() description is also included."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "827ac7f3-b8b5-4e93-8e59-2f84568a1ddd"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"expr", "@",
|
||||
RowBox[{"\"\<exception\>\"", "[", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "d3dca0fe-04a0-42f9-a548-4394ac2e1aff"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
StyleBox[
|
||||
RowBox[{"LTemplate", "::", "error"}], "MessageName"], ":",
|
||||
" ", "\<\"\[NoBreak]\\!\\(\\\"Unknown exception caught in \
|
||||
Printing::exception(). The library may be in an inconsistent state. It is \
|
||||
recommended that you restart the kernel now to avoid \
|
||||
instability.\\\\nvector\\\"\\)\[NoBreak]\"\>"}]], "Message", "MSG",
|
||||
ExpressionUUID -> "4b958576-2c0e-4050-aa31-432503d82f65"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LibraryFunctionError", "[",
|
||||
RowBox[{"\<\"LIBRARY_FUNCTION_ERROR\"\>", ",", "6"}], "]"}]], "Output",
|
||||
ExpressionUUID -> "d3ca1829-0e10-4ecc-906c-71fed771766f"]
|
||||
}, Open ]]
|
||||
}, Open ]]
|
||||
},
|
||||
WindowSize->{808, 751},
|
||||
WindowMargins->{{124, Automatic}, {36, Automatic}},
|
||||
PrivateNotebookOptions->{"FileOutlineCache"->False},
|
||||
TrackCellChangeTimes->False,
|
||||
FrontEndVersion->"10.0 for Mac OS X x86 (32-bit, 64-bit Kernel) (December 4, \
|
||||
2014)",
|
||||
StyleDefinitions->"Default.nb"
|
||||
]
|
||||
|
27
LTemplate/Documentation/Examples/RawArray/RA.h
Normal file
27
LTemplate/Documentation/Examples/RawArray/RA.h
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
#include <LTemplate.h>
|
||||
|
||||
class RA {
|
||||
public:
|
||||
// Store the data from a Real Tensor in a Byte RawArray and shuffle the byte storage order
|
||||
mma::RawArrayRef<uint8_t> shuffle(mma::RealTensorRef t) {
|
||||
const uint8_t *data = reinterpret_cast<uint8_t *>(t.data());
|
||||
auto ra = mma::makeRawVector<uint8_t>(t.size() * sizeof(double));
|
||||
for (int i=0; i < sizeof(double); ++i)
|
||||
for (int j=0; j < t.size(); ++j)
|
||||
ra[i*t.size() + j] = data[j*sizeof(double) + i];
|
||||
return ra;
|
||||
}
|
||||
|
||||
// Reverse the transformation done by shuffle()
|
||||
mma::RealTensorRef deshuffle(mma::RawArrayRef<uint8_t> ra) {
|
||||
if (ra.size() % sizeof(double) != 0)
|
||||
throw mma::LibraryError("Input size must be a multiple of 8.");
|
||||
auto t = mma::makeVector<double>(ra.size() / sizeof(double));
|
||||
uint8_t *data = reinterpret_cast<uint8_t *>(t.data());
|
||||
for (int i=0; i < sizeof(double); ++i)
|
||||
for (int j=0; j < t.size(); ++j)
|
||||
data[j*sizeof(double) + i] = ra[i*t.size() + j];
|
||||
return t;
|
||||
}
|
||||
};
|
764
LTemplate/Documentation/Examples/RawArray/RA.nb
Normal file
764
LTemplate/Documentation/Examples/RawArray/RA.nb
Normal file
@ -0,0 +1,764 @@
|
||||
Notebook[{
|
||||
|
||||
Cell[CellGroupData[{
|
||||
Cell["Working with RawArrays", \
|
||||
"Section",ExpressionUUID->"fff5ad90-c711-4958-b676-be343cf900c3"],
|
||||
|
||||
Cell[TextData[{
|
||||
StyleBox["Note: ",
|
||||
FontWeight->"Bold"],
|
||||
StyleBox["RawArrays, available in Mathematica 10.4 and later, are not \
|
||||
documented and not supported by Wolfram Research. Mathematica 12.0 replaces ",
|
||||
|
||||
FontSlant->"Italic"],
|
||||
Cell[BoxData["RawArray"],
|
||||
FontSlant->"Italic",ExpressionUUID->
|
||||
"bf9ba4bf-9bb2-4cef-83a4-b640dc36c5ce"],
|
||||
StyleBox[" with the documented ",
|
||||
FontSlant->"Italic"],
|
||||
Cell[BoxData["NumericArray"],
|
||||
FontSlant->"Italic",ExpressionUUID->
|
||||
"04d40a53-9fd8-4e65-8f09-48aa2b32248b"],
|
||||
StyleBox[". Consider using ",
|
||||
FontSlant->"Italic"],
|
||||
Cell[BoxData["NumericArray"],
|
||||
FontSlant->"Italic",ExpressionUUID->
|
||||
"29aa7d1e-4bb6-4b28-ad40-c144b2ed6ad6"],
|
||||
StyleBox[" instead.",
|
||||
FontSlant->"Italic"]
|
||||
}], "Text",ExpressionUUID->"0f7c0727-0d43-4ea5-a912-e7713cf8a6a0"],
|
||||
|
||||
Cell[TextData[{
|
||||
"This example demonstrates working with RawArrays. It requires ",
|
||||
StyleBox["Mathematica",
|
||||
FontSlant->"Italic"],
|
||||
" 11.1 or later because it uses the ",
|
||||
Cell[BoxData[
|
||||
ButtonBox["BinarySerialize",
|
||||
BaseStyle->"Hyperlink",
|
||||
ButtonData->{
|
||||
URL["http://reference.wolfram.com/language/ref/BinarySerialize.html"],
|
||||
None},
|
||||
ButtonNote->
|
||||
"http://reference.wolfram.com/language/ref/BinarySerialize.html"]],
|
||||
ExpressionUUID->"b73d0c21-921c-40e5-a0f1-bf9368919810"],
|
||||
" function."
|
||||
}], "Text",ExpressionUUID->"71315409-8bf1-4733-aabb-377f9feb2a01"],
|
||||
|
||||
Cell["\<\
|
||||
RawArray support in LTemplate requires Mathematica 10.4 or later.\
|
||||
\>", "Text",ExpressionUUID->"725aaf69-f8c0-4b97-a381-bde120d8bfc4"],
|
||||
|
||||
Cell[BoxData[{
|
||||
RowBox[{"Needs", "[", "\"\<LTemplate`\>\"", "]"}], "\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"SetDirectory", "@",
|
||||
RowBox[{"NotebookDirectory", "[", "]"}]}],
|
||||
";"}]}], "Input",ExpressionUUID->"35c0416d-df3e-4655-8910-ffa15d860a2f"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"template", "=", "\[IndentingNewLine]",
|
||||
RowBox[{"LClass", "[",
|
||||
RowBox[{"\"\<RA\>\"", ",", "\[IndentingNewLine]",
|
||||
RowBox[{"{", "\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<shuffle\>\"", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"LType", "[",
|
||||
RowBox[{"List", ",", "Real", ",", "1"}], "]"}], ",",
|
||||
"\"\<Constant\>\""}], "}"}], "}"}], ",",
|
||||
RowBox[{"LType", "[",
|
||||
RowBox[{"RawArray", ",", "\"\<Byte\>\""}], "]"}]}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<deshuffle\>\"", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"LType", "[",
|
||||
RowBox[{"RawArray", ",", "\"\<Byte\>\""}], "]"}], ",",
|
||||
"\"\<Constant\>\""}], "}"}], "}"}], ",",
|
||||
RowBox[{"LType", "[",
|
||||
RowBox[{"List", ",", "Real", ",", "1"}], "]"}]}], "]"}]}],
|
||||
"\[IndentingNewLine]", "}"}]}], "\[IndentingNewLine]", "]"}]}],
|
||||
";"}]], "Input",ExpressionUUID->"28b12d00-2a3a-4117-b361-71794c21c60d"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"CompileTemplate", "[", "template",
|
||||
"]"}]], "Input",ExpressionUUID->"e003c53b-e132-4175-b40c-de5aa3ebdfbc"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
InterpretationBox[
|
||||
RowBox[{
|
||||
StyleBox["\<\"Current directory is: \"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\"/Users/szhorvat/Repos/LTemplate/LTemplate/Documentation/\
|
||||
Examples/RawArray\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]}],
|
||||
SequenceForm[
|
||||
Style["Current directory is: ",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style["/Users/szhorvat/Repos/LTemplate/LTemplate/Documentation/Examples/\
|
||||
RawArray",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]]],
|
||||
Editable->
|
||||
False]], "Print",ExpressionUUID->"89147b84-e437-4a32-a63e-5afd96e2a69b"],
|
||||
|
||||
Cell[BoxData[
|
||||
InterpretationBox[
|
||||
RowBox[{
|
||||
StyleBox["\<\"Unloading library \"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\"RA\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\" ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]}],
|
||||
SequenceForm[
|
||||
Style["Unloading library ",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style["RA",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style[" ...",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]]],
|
||||
Editable->
|
||||
False]], "Print",ExpressionUUID->"25d27c05-18c8-42c1-b98c-fd1e585088f3"],
|
||||
|
||||
Cell[BoxData[
|
||||
StyleBox["\<\"Generating library code ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[
|
||||
2, 3]]]], "Print",ExpressionUUID->"8dc2deb6-488a-41ab-b3a5-29a3557814fb"],
|
||||
|
||||
Cell[BoxData[
|
||||
StyleBox["\<\"Compiling library code ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[
|
||||
2, 3]]]], "Print",ExpressionUUID->"ee0a54d5-cb48-461e-885c-8b333d578b51"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[BoxData["\<\"/Users/szhorvat/Library/Mathematica/SystemFiles/\
|
||||
LibraryResources/MacOSX-x86-64/RA.dylib\"\>"], \
|
||||
"Output",ExpressionUUID->"3b14953d-7b42-4935-96c3-6ac1db941b01"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LoadTemplate", "[", "template",
|
||||
"]"}]], "Input",ExpressionUUID->"1b175dcc-89b6-4482-a163-55b5a6a2fb58"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"obj", "=",
|
||||
RowBox[{"Make", "[", "RA", "]"}]}],
|
||||
";"}]], "Input",ExpressionUUID->"2655c6b0-63c0-4a66-a8bb-984c3949c8d5"],
|
||||
|
||||
Cell["This table of real numbers takes up 800 kB of storage.", \
|
||||
"Text",ExpressionUUID->"62ca9139-cee5-45a1-aa49-013a1cf6684f"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"data", "=",
|
||||
RowBox[{"Table", "[",
|
||||
RowBox[{
|
||||
RowBox[{"Sin", "[", "x", "]"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"x", ",", "0", ",", "100", ",", "0.001"}], "}"}]}], "]"}]}],
|
||||
";"}]], "Input",ExpressionUUID->"6302ce63-b63d-4279-b1cf-2d1993c1ac84"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"ByteCount", "[", "data",
|
||||
"]"}]], "Input",ExpressionUUID->"e637b750-883d-4865-8906-73261219ee9c"],
|
||||
|
||||
Cell[BoxData["800152"], \
|
||||
"Output",ExpressionUUID->"4863b78b-d31e-478d-9472-f01fb4fa7fec"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["\<\
|
||||
However, there is a lot of redundancy in the numbers as they represent a \
|
||||
continuous function.\
|
||||
\>", "Text",ExpressionUUID->"2752208d-da2d-421e-9d0f-5d1bfd91e42a"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"ListLinePlot", "[",
|
||||
RowBox[{"data", ",",
|
||||
RowBox[{"MaxPlotPoints", "\[Rule]", "500"}]}],
|
||||
"]"}]], "Input",ExpressionUUID->"3ddb6a0d-c908-4c7f-a14a-5d9f90c71b9b"],
|
||||
|
||||
Cell[BoxData[
|
||||
GraphicsBox[{{}, {{}, {},
|
||||
{RGBColor[0.368417, 0.506779, 0.709798], PointSize[0.002777777777777778],
|
||||
AbsoluteThickness[1.6], LineBox[CompressedData["
|
||||
1:eJxN2XlcjPv7P/DKlj05RMhkiRNRkuUgL8pSpFSyFaOIhEqW0NGQXYgQEoMs
|
||||
IY0oRDWhhaR9ozLt0z5bU1H5+n2u93k8fv3T49V9d890P7uu93W/R9fZw3aL
|
||||
moqKikJVReX/facvyXyV///LZg9qlI9jenJz6eePjuDJrrjz00eUUeadwske
|
||||
aaLoS9WURedxpsnspsmLOso3L2FDiE7+tOhGyoIr2J21NbDHvmbK767hd+2r
|
||||
Tb6/WU4NwXjBqnV7bFn25WOAYKlbzYF6yvl3cHSlyoVBpmLK5veg2TfwikPv
|
||||
Svb693HSqMK1zC+PsuFDBDYeqOs1N5ny0XBYuIVlD1qYkPC/vPkx1ukGHkv5
|
||||
lk552FO81D2W+EK9mPKXCBQUfhyuJ66g7BiJGQ/NTmT4iikfE2B36kGXJKsG
|
||||
ynbP0TTtjuuNj02UdaLw4EH7vLfiZso1Udhp1jB5bwLLwS9QenHfl+nn2fnL
|
||||
XuKHyqhbEx3Z9bpH47tavPEivVrKydF4pHlyantxJeWdMQjL9nf9+4yIst4r
|
||||
aI43cMjxyKec/woTOzRyRIYplPu8gcfRec05A4V0Pw6/QVuew7JPD75SXhcL
|
||||
cyg8Fx8rpjztLbwU0sKxg9j9bXuL027XenQFsfv/8R1qr27btHRWA+VTcVhd
|
||||
5PZG/1YTZYt4NGpKOz3ymGfvBPhdTErPLWU5PgEXSrycfuXS+bw5Qiz3inAp
|
||||
j6Xr8W4I0VG0sXD6uVrKXUK03pkyv+/MKvp9+0Tk/X5gapIrouNRibjSpVb6
|
||||
PTefjvd7D/+Yw2dDw1Lo+KP3uJZkhKB5QrofFe+RX9TTcJ386/8yb+UHaNQ4
|
||||
15vEMP+4D+iovRrsy2H3m/MRy7XTrG/wmb//R4iLozQd9cmLV/4RqxRmpW6n
|
||||
yZOHJGwb7bxy7Sfy5oUmIWnOaK/n9Sy3J+FWitnBpW3s/NXJ+HF2r8u8eub/
|
||||
Ohku5T4dgxOZ/6gU7KwY5nXGvYrO906Bn6v6vX5qZXQ8JwUWT39e0BpRQHlK
|
||||
KhIRmVtVwPy/pOKGv+9eG3fy5/X8hEcyjZNanAzKez8hxk/Pz7OI/HmiT3C3
|
||||
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
|
||||
tuB3zcOPlt3IV7CqBWUx9n7JfuSr4dyCFC2PNONktp+3swUdvZacGM8nX42j
|
||||
LRB3/bA4nsTm+dMtiHoiGJX5inw9g1tw4lcPxzQD8hWEtWDpm+D5uxaQr0jQ
|
||||
gr8vBJxVY75414Krdrb6cjnr5yktCBk1fNXN+eQrKG7BjoP+7aeZr1DcgrGR
|
||||
vTenOLD+3dICt5vnk4IOsv6tqsQlSYy9vSvr3wOUmLq/+kZmT/Z5obYSg8y7
|
||||
leX7ky9XT4lj//ztPjODfDnTlEh0Tp7QL4jN74uV6BOj7W4exfZvrJQQOjd6
|
||||
xn8k38z1Siz9pZL31ph8NdyUCJyZf7Abm9+xV4mv+2WeY9j8HshTYvfVKwVX
|
||||
pKx/n/1zvHrCzp6mbH6/o8QLk8LPV5mvRoQSA+7rrH2/mvXvN0r4rovr2OdL
|
||||
vpIkJQq5ra5em8mXk6OEber99M3dyZdbqoS4h3FB3yPkK6xToiWzm0uPT2y/
|
||||
RqkE1674mOw426/p04rbB6KNeQnka6jZipl1R7WanpMvh9MKrdB1l7Qmsf5t
|
||||
0ArHHPdG8WzWv2e3wmuqPTf7PvlmmrfiTdduxcx68hVatyL5tfjsgJmsfre0
|
||||
ovrIMb0y5ivwbEW59KX6hu2sn/u24vLwiMsb3rD92VOtSAvn5o+qJl+NK624
|
||||
dPn1lMAq8g3ktyL3xqHWs+7l9H4jWnHdt7ud14MiOv6mFZHVZf8WaafR/4Pw
|
||||
z98zQFYVMe0dvX7mn/ejN3GKe+sHuv/fWvHiXaudx8ocul8NrbBuuFUdMLKc
|
||||
vFTa0Px0QFLGKvZ5iWYbXF2Wdg0pJB/DCW04vUzwahHbf7WZ2wb7Sal1dYeZ
|
||||
95I2NDltDI5wpf08Dds2+B/wWuPnSNfjO7VhQ/LjiakONH9pbG/Da6uAV+On
|
||||
ixL+D5h7iDQ=
|
||||
"]]}}, {}, {}, {{}, {}}, {{}, {}}},
|
||||
AspectRatio->NCache[GoldenRatio^(-1), 0.6180339887498948],
|
||||
Axes->{True, True},
|
||||
AxesLabel->{None, None},
|
||||
AxesOrigin->{0., 0},
|
||||
DisplayFunction->Identity,
|
||||
Frame->{{False, False}, {False, False}},
|
||||
FrameLabel->{{None, None}, {None, None}},
|
||||
FrameTicks->{{Automatic, Automatic}, {Automatic, Automatic}},
|
||||
GridLines->{None, None},
|
||||
GridLinesStyle->Directive[
|
||||
GrayLevel[0.5, 0.4]],
|
||||
ImagePadding->All,
|
||||
Method->{"CoordinatesToolOptions" -> {"DisplayFunction" -> ({
|
||||
(Identity[#]& )[
|
||||
Part[#, 1]],
|
||||
(Identity[#]& )[
|
||||
Part[#, 2]]}& ), "CopiedValueFunction" -> ({
|
||||
(Identity[#]& )[
|
||||
Part[#, 1]],
|
||||
(Identity[#]& )[
|
||||
Part[#, 2]]}& )}},
|
||||
PlotRange->{{0., 100001.}, {-0.9999999998602358, 0.9999999998313446}},
|
||||
PlotRangeClipping->True,
|
||||
PlotRangePadding->{{
|
||||
Scaled[0.02],
|
||||
Scaled[0.02]}, {
|
||||
Scaled[0.05],
|
||||
Scaled[0.05]}},
|
||||
Ticks->{
|
||||
Automatic,
|
||||
Automatic}]], \
|
||||
"Output",ExpressionUUID->"305faab1-e6ad-424b-941d-1a13d0f9e389"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["\<\
|
||||
It is reasonable to expect this data to compress well, but BinarySerialize \
|
||||
does not do very well on it. The result is 750 kB, only a 6% reduction from \
|
||||
the original size.\
|
||||
\>", "Text",ExpressionUUID->"db7d2b25-4b5a-4a66-99d3-c1c901095d98"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"BinarySerialize", "[",
|
||||
RowBox[{"data", ",",
|
||||
RowBox[{"PerformanceGoal", "\[Rule]", "\"\<Size\>\""}]}],
|
||||
"]"}]], "Input",ExpressionUUID->"12e321f1-7759-4537-a82b-c85df2754486"],
|
||||
|
||||
Cell[BoxData[
|
||||
TagBox[
|
||||
TemplateBox[{RowBox[{
|
||||
StyleBox[
|
||||
TagBox["ByteArray", "SummaryHead"], "NonInterpretableSummary"],
|
||||
StyleBox["[", "NonInterpretableSummary"],
|
||||
DynamicModuleBox[{Typeset`open$$ = False},
|
||||
PanelBox[
|
||||
PaneSelectorBox[{False -> GridBox[{{
|
||||
GridBox[{{
|
||||
TagBox["\"750.4 kB\"", "SummaryItem"]}},
|
||||
GridBoxAlignment -> {
|
||||
"Columns" -> {{Left}}, "Rows" -> {{Automatic}}}, AutoDelete ->
|
||||
False, GridBoxItemSize -> {
|
||||
"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}},
|
||||
GridBoxSpacings -> {
|
||||
"Columns" -> {{2}}, "Rows" -> {{Automatic}}},
|
||||
BaseStyle -> {
|
||||
ShowStringCharacters -> False, NumberMarks -> False,
|
||||
PrintPrecision -> 3, ShowSyntaxStyles -> False}]}},
|
||||
GridBoxAlignment -> {"Rows" -> {{Top}}}, AutoDelete -> False,
|
||||
GridBoxItemSize -> {
|
||||
"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}},
|
||||
BaselinePosition -> {1, 1}], True -> GridBox[{{
|
||||
GridBox[{{
|
||||
TagBox["\"750.4 kB\"", "SummaryItem"]}},
|
||||
GridBoxAlignment -> {
|
||||
"Columns" -> {{Left}}, "Rows" -> {{Automatic}}}, AutoDelete ->
|
||||
False, GridBoxItemSize -> {
|
||||
"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}},
|
||||
GridBoxSpacings -> {
|
||||
"Columns" -> {{2}}, "Rows" -> {{Automatic}}},
|
||||
BaseStyle -> {
|
||||
ShowStringCharacters -> False, NumberMarks -> False,
|
||||
PrintPrecision -> 3, ShowSyntaxStyles -> False}]}},
|
||||
GridBoxAlignment -> {"Rows" -> {{Top}}}, AutoDelete -> False,
|
||||
GridBoxItemSize -> {
|
||||
"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}},
|
||||
BaselinePosition -> {1, 1}]},
|
||||
Dynamic[Typeset`open$$], ImageSize -> Automatic], BaselinePosition ->
|
||||
Baseline], DynamicModuleValues :> {}],
|
||||
StyleBox["]", "NonInterpretableSummary"]}]},
|
||||
"CopyTag",
|
||||
DisplayFunction->(#& ),
|
||||
InterpretationFunction->("ByteArray[<750447>]"& )],
|
||||
False,
|
||||
Editable->False,
|
||||
SelectWithContents->True,
|
||||
Selectable->
|
||||
False]], "Output",ExpressionUUID->"6306f9e4-ca35-4ce4-8eb3-302884341323"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{
|
||||
RowBox[{"ByteCount", "[", "%", "]"}], "/",
|
||||
RowBox[{"ByteCount", "[", "data", "]"}]}], "//",
|
||||
"N"}]], "Input",ExpressionUUID->"f3df6018-424d-4b85-8ba2-773367817370"],
|
||||
|
||||
Cell[BoxData["0.9380005298993191`"], \
|
||||
"Output",ExpressionUUID->"1f42d380-bb2d-48da-8b54-8114334c6891"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[TextData[{
|
||||
"The compressibility can be improved considerably by rearranging the \
|
||||
underlying bytes of the data so that the first byte of each floating point \
|
||||
number are stored contiguously, followed by the second bytes, and so on. This \
|
||||
exposes the redundancy in the data. The ",
|
||||
Cell[BoxData[
|
||||
"shuffle"],ExpressionUUID->"96674cd3-b1e8-47ba-876b-a021153d76d7"],
|
||||
" function performs this rearranging."
|
||||
}], "Text",ExpressionUUID->"633ef7d1-1ab3-4811-9c14-0a0b865c68bd"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{
|
||||
"\"\<shuffle\>\"", "[", "data",
|
||||
"]"}]}]], "Input",ExpressionUUID->"f199ac5e-96fc-44c8-8cc1-bce892c26b87"],
|
||||
|
||||
Cell[BoxData[
|
||||
TagBox[
|
||||
RowBox[{"RawArray", "[",
|
||||
RowBox[{"\<\"UnsignedInteger8\"\>", ",",
|
||||
RowBox[{
|
||||
StyleBox["\<\"<\"\>",
|
||||
ShowStringCharacters->False], "\[InvisibleSpace]", "800008",
|
||||
"\[InvisibleSpace]",
|
||||
StyleBox["\<\">\"\>",
|
||||
ShowStringCharacters->False]}]}], "]"}],
|
||||
False,
|
||||
Editable->False,
|
||||
SelectWithContents->
|
||||
True]], "Output",ExpressionUUID->"4271f9f0-fd75-469f-a37c-b8901eb6b06c"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"BinarySerialize", "[",
|
||||
RowBox[{
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<shuffle\>\"", "[", "data", "]"}]}], ",",
|
||||
RowBox[{"PerformanceGoal", "\[Rule]", "\"\<Size\>\""}]}],
|
||||
"]"}]], "Input",ExpressionUUID->"21501e88-0b6a-432b-8cac-f349f7ff1351"],
|
||||
|
||||
Cell[BoxData[
|
||||
TagBox[
|
||||
TemplateBox[{RowBox[{
|
||||
StyleBox[
|
||||
TagBox["ByteArray", "SummaryHead"], "NonInterpretableSummary"],
|
||||
StyleBox["[", "NonInterpretableSummary"],
|
||||
DynamicModuleBox[{Typeset`open$$ = False},
|
||||
PanelBox[
|
||||
PaneSelectorBox[{False -> GridBox[{{
|
||||
GridBox[{{
|
||||
TagBox["\"548.0 kB\"", "SummaryItem"]}},
|
||||
GridBoxAlignment -> {
|
||||
"Columns" -> {{Left}}, "Rows" -> {{Automatic}}}, AutoDelete ->
|
||||
False, GridBoxItemSize -> {
|
||||
"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}},
|
||||
GridBoxSpacings -> {
|
||||
"Columns" -> {{2}}, "Rows" -> {{Automatic}}},
|
||||
BaseStyle -> {
|
||||
ShowStringCharacters -> False, NumberMarks -> False,
|
||||
PrintPrecision -> 3, ShowSyntaxStyles -> False}]}},
|
||||
GridBoxAlignment -> {"Rows" -> {{Top}}}, AutoDelete -> False,
|
||||
GridBoxItemSize -> {
|
||||
"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}},
|
||||
BaselinePosition -> {1, 1}], True -> GridBox[{{
|
||||
GridBox[{{
|
||||
TagBox["\"548.0 kB\"", "SummaryItem"]}},
|
||||
GridBoxAlignment -> {
|
||||
"Columns" -> {{Left}}, "Rows" -> {{Automatic}}}, AutoDelete ->
|
||||
False, GridBoxItemSize -> {
|
||||
"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}},
|
||||
GridBoxSpacings -> {
|
||||
"Columns" -> {{2}}, "Rows" -> {{Automatic}}},
|
||||
BaseStyle -> {
|
||||
ShowStringCharacters -> False, NumberMarks -> False,
|
||||
PrintPrecision -> 3, ShowSyntaxStyles -> False}]}},
|
||||
GridBoxAlignment -> {"Rows" -> {{Top}}}, AutoDelete -> False,
|
||||
GridBoxItemSize -> {
|
||||
"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}},
|
||||
BaselinePosition -> {1, 1}]},
|
||||
Dynamic[Typeset`open$$], ImageSize -> Automatic], BaselinePosition ->
|
||||
Baseline], DynamicModuleValues :> {}],
|
||||
StyleBox["]", "NonInterpretableSummary"]}]},
|
||||
"CopyTag",
|
||||
DisplayFunction->(#& ),
|
||||
InterpretationFunction->("ByteArray[<548033>]"& )],
|
||||
False,
|
||||
Editable->False,
|
||||
SelectWithContents->True,
|
||||
Selectable->
|
||||
False]], "Output",ExpressionUUID->"fbbe7a2c-a7f1-43cb-8523-9dd456a0bb84"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Now we have a 31% reduction.", \
|
||||
"Text",ExpressionUUID->"cd8235af-dbda-4a42-bf58-47bae7556ca8"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{
|
||||
RowBox[{"ByteCount", "[", "%", "]"}], "/",
|
||||
RowBox[{"ByteCount", "[", "data", "]"}]}], "//",
|
||||
"N"}]], "Input",ExpressionUUID->"b4bc966b-6080-432b-a863-e8ae8ca6de33"],
|
||||
|
||||
Cell[BoxData["0.6850310940921225`"], \
|
||||
"Output",ExpressionUUID->"282ba1b8-236a-477b-9925-33df390fe4d1"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["\<\
|
||||
The compressibility could be improved further (at the cost of some numerical \
|
||||
accuracy) by storing only the differences between the consecutive numbers. \
|
||||
The following functions implement this:\
|
||||
\>", "Text",ExpressionUUID->"6132506c-9377-459f-ac60-98e95b1cea24"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"compress", "[",
|
||||
RowBox[{"data_", "?",
|
||||
RowBox[{"(",
|
||||
RowBox[{
|
||||
RowBox[{"VectorQ", "[",
|
||||
RowBox[{"#", ",", "Developer`MachineRealQ"}], "]"}], "&"}], ")"}]}],
|
||||
"]"}], ":=", "\[IndentingNewLine]",
|
||||
RowBox[{"BinarySerialize", "[", "\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<shuffle\>\"", "[",
|
||||
RowBox[{"Prepend", "[",
|
||||
RowBox[{
|
||||
RowBox[{"Differences", "[", "data", "]"}], ",",
|
||||
RowBox[{"First", "[", "data", "]"}]}], "]"}], "]"}]}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"PerformanceGoal", "\[Rule]", "\"\<Size\>\""}]}],
|
||||
"\[IndentingNewLine]",
|
||||
"]"}]}]], "Input",ExpressionUUID->"a0b56d69-1359-4221-b791-0450443bfabf"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"decompress", "[", "bytes_", "]"}], ":=",
|
||||
RowBox[{"Accumulate", "[",
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<deshuffle\>\"", "[",
|
||||
RowBox[{"BinaryDeserialize", "[", "bytes", "]"}], "]"}]}],
|
||||
"]"}]}]], "Input",ExpressionUUID->"afbcff7b-0c29-4e83-92fd-f422abb5822f"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"compress", "[", "data",
|
||||
"]"}]], "Input",ExpressionUUID->"33d3fee4-c860-468b-82f8-b8701a6fbabf"],
|
||||
|
||||
Cell[BoxData[
|
||||
TagBox[
|
||||
TemplateBox[{RowBox[{
|
||||
StyleBox[
|
||||
TagBox["ByteArray", "SummaryHead"], "NonInterpretableSummary"],
|
||||
StyleBox["[", "NonInterpretableSummary"],
|
||||
DynamicModuleBox[{Typeset`open$$ = False},
|
||||
PanelBox[
|
||||
PaneSelectorBox[{False -> GridBox[{{
|
||||
GridBox[{{
|
||||
TagBox["\"440.0 kB\"", "SummaryItem"]}},
|
||||
GridBoxAlignment -> {
|
||||
"Columns" -> {{Left}}, "Rows" -> {{Automatic}}}, AutoDelete ->
|
||||
False, GridBoxItemSize -> {
|
||||
"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}},
|
||||
GridBoxSpacings -> {
|
||||
"Columns" -> {{2}}, "Rows" -> {{Automatic}}},
|
||||
BaseStyle -> {
|
||||
ShowStringCharacters -> False, NumberMarks -> False,
|
||||
PrintPrecision -> 3, ShowSyntaxStyles -> False}]}},
|
||||
GridBoxAlignment -> {"Rows" -> {{Top}}}, AutoDelete -> False,
|
||||
GridBoxItemSize -> {
|
||||
"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}},
|
||||
BaselinePosition -> {1, 1}], True -> GridBox[{{
|
||||
GridBox[{{
|
||||
TagBox["\"440.0 kB\"", "SummaryItem"]}},
|
||||
GridBoxAlignment -> {
|
||||
"Columns" -> {{Left}}, "Rows" -> {{Automatic}}}, AutoDelete ->
|
||||
False, GridBoxItemSize -> {
|
||||
"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}},
|
||||
GridBoxSpacings -> {
|
||||
"Columns" -> {{2}}, "Rows" -> {{Automatic}}},
|
||||
BaseStyle -> {
|
||||
ShowStringCharacters -> False, NumberMarks -> False,
|
||||
PrintPrecision -> 3, ShowSyntaxStyles -> False}]}},
|
||||
GridBoxAlignment -> {"Rows" -> {{Top}}}, AutoDelete -> False,
|
||||
GridBoxItemSize -> {
|
||||
"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}},
|
||||
BaselinePosition -> {1, 1}]},
|
||||
Dynamic[Typeset`open$$], ImageSize -> Automatic], BaselinePosition ->
|
||||
Baseline], DynamicModuleValues :> {}],
|
||||
StyleBox["]", "NonInterpretableSummary"]}]},
|
||||
"CopyTag",
|
||||
DisplayFunction->(#& ),
|
||||
InterpretationFunction->("ByteArray[<440021>]"& )],
|
||||
False,
|
||||
Editable->False,
|
||||
SelectWithContents->True,
|
||||
Selectable->
|
||||
False]], "Output",ExpressionUUID->"566d3dab-b4a6-474d-be7f-231c09ff246b"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["This way we could achieve a 45% reduction in size.", \
|
||||
"Text",ExpressionUUID->"5600a668-09b5-4540-b2f7-de4764c469ba"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{
|
||||
RowBox[{"ByteCount", "@",
|
||||
RowBox[{"compress", "[", "data", "]"}]}], "/",
|
||||
RowBox[{"ByteCount", "[", "data", "]"}]}], "//",
|
||||
"N"}]], "Input",ExpressionUUID->"4ec69f1b-8cbf-43f0-8e02-2bbcd4742ce3"],
|
||||
|
||||
Cell[BoxData["0.5500417420690069`"], \
|
||||
"Output",ExpressionUUID->"af90dac3-cbe9-44aa-a801-f16370f0bbe6"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["For practical purposes, the accuracy loss is negligible.", \
|
||||
"Text",ExpressionUUID->"e33c89ed-85d7-4c78-9419-0a1facb233b7"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"Abs", "[",
|
||||
RowBox[{
|
||||
RowBox[{"decompress", "@",
|
||||
RowBox[{"compress", "[", "data", "]"}]}], "-", "data"}], "]"}], "//",
|
||||
"Max"}]], "Input",ExpressionUUID->"cf050699-40c0-45f3-9161-65ed31ce042a"],
|
||||
|
||||
Cell[BoxData["4.336808689942018`*^-19"], \
|
||||
"Output",ExpressionUUID->"48e262ee-e1e1-4111-9858-f20411638ad6"]
|
||||
}, Open ]]
|
||||
}, Open ]]
|
||||
},
|
||||
WindowSize->{878, 722},
|
||||
WindowMargins->{{42, Automatic}, {Automatic, 55}},
|
||||
PrivateNotebookOptions->{"FileOutlineCache"->False},
|
||||
CommonDefaultFormatTypes->{"TextInline"->StandardForm},
|
||||
TrackCellChangeTimes->False,
|
||||
FrontEndVersion->"11.1 for Mac OS X x86 (32-bit, 64-bit Kernel) (April 18, \
|
||||
2017)",
|
||||
StyleDefinitions->"Default.nb"
|
||||
]
|
||||
|
167
LTemplate/Documentation/Examples/SparseArray/Sparse.h
Normal file
167
LTemplate/Documentation/Examples/SparseArray/Sparse.h
Normal file
@ -0,0 +1,167 @@
|
||||
|
||||
#include <LTemplate.h>
|
||||
#include <iomanip>
|
||||
|
||||
class Sparse {
|
||||
public:
|
||||
// ACCESSING PROPERTIES
|
||||
|
||||
mma::RealTensorRef explicitValues(mma::SparseArrayRef<double> sa) {
|
||||
// The Tensor returned by .explicitValues() is part of the SparseArray data structure,
|
||||
// and should not be modified. Therefore we .clone() it before returning it to Mathematica.
|
||||
return sa.explicitValues().clone();
|
||||
}
|
||||
|
||||
mma::IntTensorRef explicitPositions(mma::SparseArrayRef<double> sa) {
|
||||
// Unlike .explicitValues(), the .explicitPositions() member function creates a new Tensor.
|
||||
// We are responsible for freeing this Tensor when we are done using it.
|
||||
// In this case we simply return it to the kernel without cloning.
|
||||
return sa.explicitPositions();
|
||||
}
|
||||
|
||||
mma::IntTensorRef rowPointers(mma::SparseArrayRef<double> sa) {
|
||||
return sa.rowPointers().clone();
|
||||
}
|
||||
|
||||
mma::IntTensorRef columnIndices(mma::SparseArrayRef<double> sa) {
|
||||
return sa.columnIndices().clone();
|
||||
}
|
||||
|
||||
// Find the rank of a sparse array.
|
||||
mint depth(mma::SparseArrayRef<double> sa) {
|
||||
return sa.rank();
|
||||
}
|
||||
|
||||
// Find the dimensions of a sparse array.
|
||||
mma::IntTensorRef dimensions(mma::SparseArrayRef<double> sa) {
|
||||
return mma::makeVector<mint>(sa.rank(), sa.dimensions());
|
||||
}
|
||||
|
||||
// The implicit value of a sparse array is the value assumed for the
|
||||
// elements that were not explicitly stored.
|
||||
double implicitValue(mma::SparseArrayRef<double> sa) {
|
||||
return sa.implicitValue();
|
||||
}
|
||||
|
||||
|
||||
// DENSE <-> SPARSE CONVERSIONS
|
||||
|
||||
// Convert sparse arrays to dense ones.
|
||||
mma::RealTensorRef toDense(mma::SparseArrayRef<double> sa) {
|
||||
return sa.toTensor();
|
||||
}
|
||||
|
||||
// Convert dense arrays to sparse ones.
|
||||
mma::SparseArrayRef<double> toSparse(mma::RealTensorRef t) {
|
||||
return t.toSparseArray();
|
||||
}
|
||||
|
||||
|
||||
// ELEMENT ACCESS
|
||||
|
||||
// Iterate through all index-pairs of a matrix and print the corresponding element.
|
||||
void printMatrix(mma::SparseMatrixRef<double> sm) {
|
||||
mma::mout << "Rows: " << sm.rows() << ", Cols: " << sm.cols() << std::endl;
|
||||
for (int i=0; i < sm.rows(); ++i) {
|
||||
for (int j=0; j < sm.cols(); ++j)
|
||||
mma::mout << std::setw(9) << sm(i,j);
|
||||
mma::mout << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate through all explicitly stored elements of a sparse matrix.
|
||||
void printExplicit(mma::SparseMatrixRef<double> sm) {
|
||||
mma::mout << "Rows: " << sm.rows() << ", Cols: " << sm.cols() << std::endl;
|
||||
for (auto it = sm.begin(); it != sm.end(); ++it)
|
||||
mma::mout << "(" << it.row() << ", " << it.col() << ") " << *it << '\n';
|
||||
}
|
||||
|
||||
// Find the smallest and largest elements of a sparse array.
|
||||
mma::RealTensorRef minmax(mma::SparseArrayRef<double> sa) {
|
||||
auto mm = std::minmax_element(sa.explicitValues().begin(), sa.explicitValues().end());
|
||||
auto res = std::minmax({*mm.first, *mm.second, sa.implicitValue()});
|
||||
return mma::makeVector<double>({res.first, res.second});
|
||||
}
|
||||
|
||||
|
||||
// CREATING SPARSE ARRAYS FROM SCRATCH
|
||||
|
||||
// Create a 5-by-6 sparse array by explicitly specifying the stored elements.
|
||||
mma::SparseMatrixRef<double> createMatrixDemo() {
|
||||
// The positions matrix must me n-by-2 in size.
|
||||
// Positions indices start at 1, as in Mathematica, not in 0, as in C++.
|
||||
auto pos = mma::makeMatrix<mint>({{1,1}, {3,4}, {2,3}});
|
||||
|
||||
// The explicit value array.
|
||||
auto vals = mma::makeVector<double>({1.0, 2.5, 3.6});
|
||||
|
||||
auto sm = mma::makeSparseMatrix(pos, vals, 5, 6);
|
||||
|
||||
// The Tensors we used for constructing the sparse matrix must be explicitly freed.
|
||||
pos.free();
|
||||
vals.free();
|
||||
|
||||
return sm;
|
||||
}
|
||||
|
||||
// Create a 3D sparse array, analogously to createMatrixDemo() above.
|
||||
mma::SparseArrayRef<double> createCubeDemo() {
|
||||
auto pos = mma::makeMatrix<mint>({{1,2,1}, {3,2,1}});
|
||||
auto vals = mma::makeVector<double>({1.5,3.2});
|
||||
auto dims = mma::makeVector<mint>({3,3,3});
|
||||
|
||||
auto sa = mma::makeSparseArray(pos, vals, dims);
|
||||
|
||||
pos.free();
|
||||
vals.free();
|
||||
dims.free();
|
||||
|
||||
return sa;
|
||||
}
|
||||
|
||||
// Create a 3-by-4 all-zero SparseArray.
|
||||
mma::SparseMatrixRef<double> createZeroMatrixDemo() {
|
||||
auto pos = mma::makeMatrix<mint>(0,2);
|
||||
auto vals = mma::makeVector<double>(0);
|
||||
|
||||
auto sa = mma::makeSparseMatrix(pos, vals, 3, 4);
|
||||
|
||||
pos.free();
|
||||
vals.free();
|
||||
|
||||
return sa;
|
||||
}
|
||||
|
||||
|
||||
// RECOMPUTE STRUCTURE
|
||||
|
||||
// Recompute the sparse structure to eliminate unnecessary explicit values.
|
||||
mma::SparseArrayRef<double> resetImplicitValue(mma::SparseArrayRef<double> sa) {
|
||||
return sa.resetImplicitValue();
|
||||
}
|
||||
|
||||
// Recompute the sparse structure based on a user-specified implicit value.
|
||||
mma::SparseArrayRef<double> newImplicitValue(mma::SparseArrayRef<double> sa, double iv) {
|
||||
return sa.resetImplicitValue(iv);
|
||||
}
|
||||
|
||||
|
||||
// MODIFY SPARSE ARRAY
|
||||
|
||||
mma::SparseArrayRef<double> modify(mma::SparseArrayRef<double> sa) {
|
||||
auto fun = [] (double x) { return x*x + 1; }; // x -> x*x+1
|
||||
for (auto &el : sa.explicitValues())
|
||||
el = fun(el);
|
||||
sa.implicitValue() = fun(sa.implicitValue());
|
||||
|
||||
/* Optionally, use
|
||||
*
|
||||
* return sa.resetImplicitValue();
|
||||
*
|
||||
* to eliminate any redundant explicit values. This is unnecessary with the
|
||||
* transformation x -> x*x+1 as it leaves no real value unchanged.
|
||||
*/
|
||||
|
||||
return sa;
|
||||
}
|
||||
};
|
4261
LTemplate/Documentation/Examples/SparseArray/Sparse.nb
Normal file
4261
LTemplate/Documentation/Examples/SparseArray/Sparse.nb
Normal file
File diff suppressed because it is too large
Load Diff
105
LTemplate/Documentation/Examples/Tensor/Tensor.h
Normal file
105
LTemplate/Documentation/Examples/Tensor/Tensor.h
Normal file
@ -0,0 +1,105 @@
|
||||
|
||||
#include <LTemplate.h>
|
||||
#include <random>
|
||||
#include <numeric>
|
||||
#include <iomanip>
|
||||
|
||||
class Tensor {
|
||||
public:
|
||||
// A trivial function that returns a real array as-is.
|
||||
mma::RealTensorRef identity(mma::RealTensorRef t) { return t; }
|
||||
|
||||
// Return the depth of a real array.
|
||||
mint depth(mma::RealTensorRef t) {
|
||||
return t.rank();
|
||||
}
|
||||
|
||||
// Return the dimensions of a real array. Demonstrates creating new arrays.
|
||||
mma::IntTensorRef dimensions(mma::RealTensorRef t) {
|
||||
return mma::makeVector<mint>(t.rank(), t.dimensions());
|
||||
}
|
||||
|
||||
// Return the total number of elements in a real array.
|
||||
mint length(mma::RealTensorRef t) {
|
||||
return t.length();
|
||||
}
|
||||
|
||||
// Sum the elements of an arbitrary dimensional real array.
|
||||
// Demonstrates linear iteration through array elements.
|
||||
double sum(mma::RealTensorRef t) {
|
||||
double s = 0.0;
|
||||
for (const auto &el : t)
|
||||
s += el;
|
||||
return s;
|
||||
}
|
||||
|
||||
// Print the elements of a vector along with their indices.
|
||||
// Demonstrates direct indexing.
|
||||
void printVector(mma::RealTensorRef v) {
|
||||
for (int i=0; i < v.size(); ++i)
|
||||
mma::mout << std::setw(4) << i+1 << ": " << std::setw(9) << v[i] << '\n';
|
||||
}
|
||||
|
||||
// Print the elements of a matrix.
|
||||
// Demonstrates matrix indexing.
|
||||
void printMatrix(mma::RealMatrixRef m) {
|
||||
for (int i=0; i < m.rows(); ++i) {
|
||||
for (int j=0; j < m.cols(); ++j)
|
||||
mma::mout << std::setw(9) << m(i,j);
|
||||
mma::mout << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
// Directly create a complex vector using initializer list.
|
||||
mma::ComplexTensorRef createVector() {
|
||||
return mma::makeVector<mma::complex_t>({mma::complex_t(2,-1), 2.5, 6});
|
||||
}
|
||||
|
||||
// Directly create a real matrix using initializer list.
|
||||
mma::RealMatrixRef createMatrix() {
|
||||
return mma::makeMatrix<double>({{1.5, 0.7}, {3.9, 4}});
|
||||
}
|
||||
|
||||
// Directly create an integer cube (rank-3 Tensor) using initializer list.
|
||||
mma::IntTensorRef createCube() {
|
||||
return mma::makeCube<mint>({ {{1,2},{3,4}}, {{5,6},{7,8}} });
|
||||
}
|
||||
|
||||
// Create a high-dimensional Tensor, specifying its dimensions directly.
|
||||
mma::RealTensorRef ones2345() {
|
||||
auto t = mma::makeTensor<double>({2,3,4,5});
|
||||
std::fill(t.begin(), t.end(), 1);
|
||||
return t;
|
||||
}
|
||||
|
||||
// Create an arbitrary dimensional array of zeros.
|
||||
mma::RealTensorRef zeros(mma::IntTensorRef dims) {
|
||||
auto t = mma::makeTensor<double>(dims.length(), dims.data());
|
||||
std::fill(t.begin(), t.end(), 0);
|
||||
return t;
|
||||
}
|
||||
|
||||
// Create an integer range.
|
||||
mma::IntTensorRef range(mint i, mint j) {
|
||||
if (j < i)
|
||||
return mma::makeVector<mint>(0);
|
||||
else {
|
||||
auto vec = mma::makeVector<mint>(j-i+1);
|
||||
std::iota(vec.begin(), vec.end(), i);
|
||||
return vec;
|
||||
}
|
||||
}
|
||||
|
||||
// Create n random numbers between lower and upper.
|
||||
mma::RealTensorRef randomReal(mint n, double lower, double upper) {
|
||||
std::random_device r;
|
||||
std::default_random_engine eng(r());
|
||||
std::uniform_real_distribution<double> dist(lower, upper);
|
||||
|
||||
auto vec = mma::makeVector<double>(n);
|
||||
for (auto &el : vec)
|
||||
el = dist(eng);
|
||||
|
||||
return vec;
|
||||
}
|
||||
};
|
963
LTemplate/Documentation/Examples/Tensor/Tensor.nb
Normal file
963
LTemplate/Documentation/Examples/Tensor/Tensor.nb
Normal file
@ -0,0 +1,963 @@
|
||||
Notebook[{
|
||||
|
||||
Cell[CellGroupData[{
|
||||
Cell["Working with arrays", "Section",
|
||||
ExpressionUUID -> "89046541-ecb9-4571-a6e2-02bc16e11ecd"],
|
||||
|
||||
Cell["\<\
|
||||
These examples demonstrate the basics of working with multidimensional \
|
||||
arrays, the meat-and-potatoes of LibraryLink programming.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "9c75b65d-6319-43d0-add4-e5a2f62865ec"],
|
||||
|
||||
Cell[BoxData[{
|
||||
RowBox[{
|
||||
RowBox[{"SetDirectory", "@",
|
||||
RowBox[{"NotebookDirectory", "[", "]"}]}], ";"}], "\[IndentingNewLine]",
|
||||
RowBox[{"Needs", "[", "\"\<LTemplate`\>\"", "]"}]}], "Input",
|
||||
ExpressionUUID -> "ebe6207a-a36c-43fc-81c0-301563a98729"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"template", "=", "\[IndentingNewLine]",
|
||||
RowBox[{"LClass", "[",
|
||||
RowBox[{"\"\<Tensor\>\"", ",", "\[IndentingNewLine]",
|
||||
RowBox[{"{", "\[IndentingNewLine]",
|
||||
RowBox[{"(*", " ",
|
||||
RowBox[{
|
||||
"properties", " ", "and", " ", "basic", " ", "argument", " ",
|
||||
"passing"}], " ", "*)"}], "\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<identity\>\"", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Real", ",", "_"}], "}"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Real", ",", "_"}], "}"}]}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<depth\>\"", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Real", ",", "_"}], "}"}], "}"}], ",", "Integer"}], "]"}],
|
||||
",", "\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<dimensions\>\"", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Real", ",", "_"}], "}"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Integer", ",", "1"}], "}"}]}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<length\>\"", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Real", ",", "_"}], "}"}], "}"}], ",", "Integer"}], "]"}],
|
||||
",", "\[IndentingNewLine]", "\[IndentingNewLine]",
|
||||
RowBox[{"(*", " ",
|
||||
RowBox[{"iteration", " ", "and", " ", "element", " ", "access"}], " ",
|
||||
"*)"}], "\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<sum\>\"", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Real", ",", "_"}], "}"}], "}"}], ",", "Real"}], "]"}],
|
||||
",", "\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<printVector\>\"", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Real", ",", "1"}], "}"}], "}"}], ",", "\"\<Void\>\""}],
|
||||
"]"}], ",", "\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<printMatrix\>\"", ",", " ",
|
||||
RowBox[{"{",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Real", ",", "2"}], "}"}], "}"}], ",", "\"\<Void\>\""}],
|
||||
"]"}], ",", "\[IndentingNewLine]", "\[IndentingNewLine]",
|
||||
RowBox[{"(*", " ",
|
||||
RowBox[{
|
||||
"creating", " ", "Tensors", " ", "of", " ", "various", " ",
|
||||
"dimensions"}], " ", "*)"}], "\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<createVector\>\"", ",",
|
||||
RowBox[{"{", "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Complex", ",", "1"}], "}"}]}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<createMatrix\>\"", ",",
|
||||
RowBox[{"{", "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Real", ",", "2"}], "}"}]}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<createCube\>\"", ",",
|
||||
RowBox[{"{", "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Integer", ",", "3"}], "}"}]}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<ones2345\>\"", ",",
|
||||
RowBox[{"{", "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Real", ",", "4"}], "}"}]}], "]"}], ",",
|
||||
"\[IndentingNewLine]", "\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<zeros\>\"", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Integer", ",", "1"}], "}"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Real", ",", "_"}], "}"}]}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<range\>\"", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Integer", ",", "Integer"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Integer", ",", "1"}], "}"}]}], "]"}], ",",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"LFun", "[",
|
||||
RowBox[{"\"\<randomReal\>\"", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Integer",
|
||||
RowBox[{"(*", " ", "n", " ", "*)"}], ",", "Real", " ",
|
||||
RowBox[{"(*", " ",
|
||||
RowBox[{"lower", " ", "bound"}], " ", "*)"}], ",", " ", "Real"}],
|
||||
" ",
|
||||
RowBox[{"(*", " ",
|
||||
RowBox[{"upper", " ", "bound"}], " ", "*)"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"Real", ",", "1"}], "}"}]}], "]"}]}], "\[IndentingNewLine]",
|
||||
"}"}]}], "\[IndentingNewLine]", "]"}]}], ";"}]], "Input",
|
||||
ExpressionUUID -> "76f0bd2a-001c-4b12-8ada-339aada23a1d"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"CompileTemplate", "[", "template", "]"}]], "Input",
|
||||
ExpressionUUID -> "84627654-cf87-45b8-b889-a53a94794b73"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
InterpretationBox[
|
||||
RowBox[{
|
||||
StyleBox["\<\"Current directory is: \"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\"/Users/szhorvat/Repos/LTemplate/LTemplate/Documentation/\
|
||||
Examples/Tensor\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]}],
|
||||
SequenceForm[
|
||||
Style["Current directory is: ",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style["/Users/szhorvat/Repos/LTemplate/LTemplate/Documentation/Examples/\
|
||||
Tensor",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]]],
|
||||
Editable->False]], "Print",
|
||||
ExpressionUUID -> "ffd01111-03d8-4e49-b831-cfea5b37552d"],
|
||||
|
||||
Cell[BoxData[
|
||||
InterpretationBox[
|
||||
RowBox[{
|
||||
StyleBox["\<\"Unloading library \"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\"Tensor\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]], "\[InvisibleSpace]",
|
||||
StyleBox["\<\" ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]}],
|
||||
SequenceForm[
|
||||
Style["Unloading library ",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style["Tensor",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]],
|
||||
Style[" ...",
|
||||
RGBColor[0, 0,
|
||||
Rational[2, 3]]]],
|
||||
Editable->False]], "Print",
|
||||
ExpressionUUID -> "ffd01111-03d8-4e49-b831-cfea5b37552d"],
|
||||
|
||||
Cell[BoxData[
|
||||
StyleBox["\<\"Generating library code ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]], "Print",
|
||||
ExpressionUUID -> "ffd01111-03d8-4e49-b831-cfea5b37552d"],
|
||||
|
||||
Cell[BoxData[
|
||||
StyleBox["\<\"Compiling library code ...\"\>",
|
||||
StripOnInput->False,
|
||||
LineColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FrontFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
BackFaceColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
GraphicsColor->RGBColor[0, 0,
|
||||
Rational[2, 3]],
|
||||
FontColor->RGBColor[0, 0,
|
||||
Rational[2, 3]]]], "Print",
|
||||
ExpressionUUID -> "ffd01111-03d8-4e49-b831-cfea5b37552d"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[BoxData["\<\"/Users/szhorvat/Library/Mathematica/SystemFiles/\
|
||||
LibraryResources/MacOSX-x86-64/Tensor.dylib\"\>"], "Output",
|
||||
ExpressionUUID -> "4839bed5-e820-4d57-aabf-7e39d7d71cf1"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"LoadTemplate", "[", "template", "]"}]], "Input",
|
||||
ExpressionUUID -> "22e04a97-b178-46db-b9c6-393d8485b3ad"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "=",
|
||||
RowBox[{"Make", "[", "Tensor", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "e8609779-55a3-4886-ab0a-3b1298e9938a"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"Tensor", "[", "1", "]"}]], "Output",
|
||||
ExpressionUUID -> "15ca9e05-e17b-4bc9-b925-1c62fd666605"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["We will use this random matrix for testing:", "Text",
|
||||
ExpressionUUID -> "6be0909a-caa7-4fa1-9ca0-a7d71004caf5"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"arr", "=",
|
||||
RowBox[{"RandomReal", "[",
|
||||
RowBox[{"1", ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"2", ",", "3"}], "}"}]}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "b0dba48f-7746-4b27-a93a-045ed7352c17"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
"0.10382876133700258`", ",", "0.2392867379885466`", ",",
|
||||
"0.3888547597436942`"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
"0.05883891620681547`", ",", "0.1635506346922937`", ",",
|
||||
"0.24925601323394098`"}], "}"}]}], "}"}]], "Output",
|
||||
ExpressionUUID -> "f205a1d3-46ed-47ee-b7be-8697ded518f2"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Get the depth of the array:", "Text",
|
||||
ExpressionUUID -> "da12df11-3248-4919-ade3-7eddea2ac6dd"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<depth\>\"", "[", "arr", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "5acca3fc-f44d-4bb4-9d72-b76bde62a457"],
|
||||
|
||||
Cell[BoxData["2"], "Output",
|
||||
ExpressionUUID -> "ff9fdb6e-becf-4ceb-ae1c-c2e6a38f64f0"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Get its dimensions:", "Text",
|
||||
ExpressionUUID -> "6469be75-7e43-410e-a6ec-1f1d537a8956"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<dimensions\>\"", "[", "arr", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "6ebb3959-c0d2-4c5c-a960-59195955cb2c"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{"2", ",", "3"}], "}"}]], "Output",
|
||||
ExpressionUUID -> "c5ecd901-afbc-4f33-9010-597035936bf4"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Get the total number of elements:", "Text"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<length\>\"", "[", "arr", "]"}]}]], "Input"],
|
||||
|
||||
Cell[BoxData["6"], "Output"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["\<\
|
||||
A trivial function that returns a real-valued arbitrary dimensional array \
|
||||
as-is:\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "ed64c68b-1c78-4d8a-9777-a1059cc09345"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<identity\>\"", "[", "arr", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "41d120e5-5fcf-4b0d-82ce-6d95c2c6242c"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
"0.10382876133700258`", ",", "0.2392867379885466`", ",",
|
||||
"0.3888547597436942`"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
"0.05883891620681547`", ",", "0.1635506346922937`", ",",
|
||||
"0.24925601323394098`"}], "}"}]}], "}"}]], "Output",
|
||||
ExpressionUUID -> "48408d7c-01f2-4fab-a51c-5bfd29ef1b39"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Sum the elements of an array:", "Text",
|
||||
ExpressionUUID -> "02b45b96-3bbe-43d3-84e1-a1c3ca9a7848"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<sum\>\"", "[", "arr", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "641e3ed1-74b6-44a3-9737-c530fb156673"],
|
||||
|
||||
Cell[BoxData["1.2036158232022935`"], "Output",
|
||||
ExpressionUUID -> "df28ec17-9f54-4832-826c-bb397e31a9bc"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"Total", "[",
|
||||
RowBox[{"arr", ",", "Infinity"}], "]"}]], "Input",
|
||||
ExpressionUUID -> "628e794d-7f15-4689-8403-900a0c71664e"],
|
||||
|
||||
Cell[BoxData["1.2036158232022935`"], "Output",
|
||||
ExpressionUUID -> "f10bf4c9-76a6-4787-93eb-ed2634520e02"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["\<\
|
||||
This function demonstrates iterating through the elements of a matrix, and \
|
||||
printing them to the notebook:\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "78452fda-9dd0-47a4-a0a3-35ba17a928f2"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<printMatrix\>\"", "[", "arr", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "b743607a-3b07-4620-b727-8eaf04f652c8"],
|
||||
|
||||
Cell[BoxData["\<\" 0.103829 0.239287 0.388855\\n0.0588389 0.163551 0.249256\"\
|
||||
\>"], "Print",
|
||||
ExpressionUUID -> "8ecfd94f-7d7d-4c33-9778-368a6c87f256"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"MatrixForm", "[", "arr", "]"}]], "Input",
|
||||
ExpressionUUID -> "f0be799a-5da5-4440-8d0a-7a5fd80798bb"],
|
||||
|
||||
Cell[BoxData[
|
||||
TagBox[
|
||||
RowBox[{"(", "\[NoBreak]", GridBox[{
|
||||
{"0.10382876133700258`", "0.2392867379885466`", "0.3888547597436942`"},
|
||||
{"0.05883891620681547`", "0.1635506346922937`", "0.24925601323394098`"}
|
||||
},
|
||||
GridBoxAlignment->{
|
||||
"Columns" -> {{Center}}, "ColumnsIndexed" -> {}, "Rows" -> {{Baseline}},
|
||||
"RowsIndexed" -> {}},
|
||||
GridBoxSpacings->{"Columns" -> {
|
||||
Offset[0.27999999999999997`], {
|
||||
Offset[0.7]},
|
||||
Offset[0.27999999999999997`]}, "ColumnsIndexed" -> {}, "Rows" -> {
|
||||
Offset[0.2], {
|
||||
Offset[0.4]},
|
||||
Offset[0.2]}, "RowsIndexed" -> {}}], "\[NoBreak]", ")"}],
|
||||
Function[BoxForm`e$,
|
||||
MatrixForm[BoxForm`e$]]]], "Output",
|
||||
ExpressionUUID -> "03272424-4977-45d9-8e77-6a9c369c770c"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<printVector\>\"", "[",
|
||||
RowBox[{"{",
|
||||
RowBox[{"E", ",", "Pi", ",", "EulerGamma"}], "}"}], "]"}]}]], "Input"],
|
||||
|
||||
Cell[BoxData["\<\" 1: 2.71828\\n 2: 3.14159\\n 3: 0.577216\"\>"], \
|
||||
"Print"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["\<\
|
||||
Create vectors, matrices or cubes (3D arrays) directly. Also demonstrates \
|
||||
Complex, Real and Integer tensors.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "248f6a25-7cb6-411e-8131-0c6d0e1fc4ad"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<createVector\>\"", "[", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "9d335f32-8d83-40aa-993e-63eb86d0d3ab"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"2.`", "\[VeryThinSpace]", "-",
|
||||
RowBox[{"1.`", " ", "\[ImaginaryI]"}]}], ",",
|
||||
RowBox[{"2.5`", "\[VeryThinSpace]", "+",
|
||||
RowBox[{"0.`", " ", "\[ImaginaryI]"}]}], ",",
|
||||
RowBox[{"6.`", "\[VeryThinSpace]", "+",
|
||||
RowBox[{"0.`", " ", "\[ImaginaryI]"}]}]}], "}"}]], "Output",
|
||||
ExpressionUUID -> "f08f788f-54f0-4360-b650-f70491393107"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<createMatrix\>\"", "[", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "6c796ef8-0b4a-4e18-91c9-c3b28d930e1d"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.5`", ",", "0.7`"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"3.9`", ",", "4.`"}], "}"}]}], "}"}]], "Output",
|
||||
ExpressionUUID -> "c594d8aa-541c-4887-b52a-cecbe9c837c7"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<createCube\>\"", "[", "]"}]}]], "Input",
|
||||
ExpressionUUID -> "80811547-218b-4994-9296-a52bd69d5a18"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"1", ",", "2"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"3", ",", "4"}], "}"}]}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"5", ",", "6"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"7", ",", "8"}], "}"}]}], "}"}]}], "}"}]], "Output",
|
||||
ExpressionUUID -> "2195c631-51c7-4985-ae01-1f5fc2927435"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[TextData[{
|
||||
"Directly create an array of ones of dimensions ",
|
||||
Cell[BoxData[
|
||||
FormBox[
|
||||
RowBox[{"{",
|
||||
RowBox[{"2", ",", "3", ",", "4", ",", "5"}], "}"}], TraditionalForm]]],
|
||||
"."
|
||||
}], "Text"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<ones2345\>\"", "[", "]"}]}]], "Input"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}]}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}]}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}]}], "}"}]}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}]}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}]}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"1.`", ",", "1.`", ",", "1.`", ",", "1.`", ",", "1.`"}],
|
||||
"}"}]}], "}"}]}], "}"}]}], "}"}]], "Output"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"Dimensions", "[", "%", "]"}]], "Input"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{", "1", "}"}]], "Output"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<zeros\>\"", "[",
|
||||
RowBox[{"{",
|
||||
RowBox[{"3", ",", "2", ",", "2"}], "}"}], "]"}]}]], "Input"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"0.`", ",", "0.`"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"0.`", ",", "0.`"}], "}"}]}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"0.`", ",", "0.`"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"0.`", ",", "0.`"}], "}"}]}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"0.`", ",", "0.`"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"0.`", ",", "0.`"}], "}"}]}], "}"}]}], "}"}]], "Output"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"Dimensions", "[", "%", "]"}]], "Input"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{", "1", "}"}]], "Output"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Create an array of arbitrary dimensions, filled with zeros:", "Text"],
|
||||
|
||||
Cell["Create integer ranges:", "Text",
|
||||
ExpressionUUID -> "2cb9e4db-6866-4601-8588-697007e22adc"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<range\>\"", "[",
|
||||
RowBox[{"3", ",", "7"}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "8394e275-4553-426b-82b5-d2402e369267"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{"3", ",", "4", ",", "5", ",", "6", ",", "7"}], "}"}]], "Output",
|
||||
ExpressionUUID -> "8da9db06-6a75-46e1-b723-289393a60607"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<range\>\"", "[",
|
||||
RowBox[{"1", ",", "0"}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "9fdf257a-00fc-4a15-beb0-496056e630fb"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{", "}"}]], "Output",
|
||||
ExpressionUUID -> "1aa7edbb-b61f-4158-96ae-9b00990af0a4"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<range\>\"", "[",
|
||||
RowBox[{"1", ",", "1"}], "]"}]}]], "Input",
|
||||
ExpressionUUID -> "de1d9044-84ee-49c2-91a8-e2213ece219e"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{", "1", "}"}]], "Output",
|
||||
ExpressionUUID -> "feecdea2-f8a2-4f82-9f35-66fe7046dc3c"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["Generate 1000 random numbers between 0 and 10:", "Text",
|
||||
ExpressionUUID -> "d80ae80b-b1db-4137-89d7-59d272a5ab77"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"obj", "@",
|
||||
RowBox[{"\"\<randomReal\>\"", "[",
|
||||
RowBox[{"1000", ",", "0", ",", "10"}], "]"}]}], "//",
|
||||
"Histogram"}]], "Input",
|
||||
ExpressionUUID -> "dc1549e3-4320-4f36-ab93-954603f5a072"],
|
||||
|
||||
Cell[BoxData[
|
||||
GraphicsBox[{
|
||||
{RGBColor[0.987148, 0.8073604000000001, 0.49470040000000004`], EdgeForm[{
|
||||
Opacity[0.63], Thickness[Small]}], {},
|
||||
{RGBColor[0.987148, 0.8073604000000001, 0.49470040000000004`], EdgeForm[{
|
||||
Opacity[0.63], Thickness[Small]}],
|
||||
TagBox[
|
||||
TooltipBox[
|
||||
TagBox[
|
||||
DynamicBox[{
|
||||
FEPrivate`If[
|
||||
CurrentValue["MouseOver"],
|
||||
EdgeForm[{
|
||||
GrayLevel[0.5],
|
||||
AbsoluteThickness[1.5],
|
||||
Opacity[0.66]}], {}, {}],
|
||||
RectangleBox[{0., 0}, {1., 81}, "RoundingRadius" -> 0]},
|
||||
ImageSizeCache->{{26.254403522818258`,
|
||||
59.27642113690954}, {-48.1405962925824, 91.93456273819318}}],
|
||||
StatusArea[#, 81]& ,
|
||||
TagBoxNote->"81"],
|
||||
StyleBox["81", {}, StripOnInput -> False]],
|
||||
Annotation[#,
|
||||
Style[81, {}], "Tooltip"]& ],
|
||||
TagBox[
|
||||
TooltipBox[
|
||||
TagBox[
|
||||
DynamicBox[{
|
||||
FEPrivate`If[
|
||||
CurrentValue["MouseOver"],
|
||||
EdgeForm[{
|
||||
GrayLevel[0.5],
|
||||
AbsoluteThickness[1.5],
|
||||
Opacity[0.66]}], {}, {}],
|
||||
RectangleBox[{1., 0}, {2., 98}, "RoundingRadius" -> 0]},
|
||||
ImageSizeCache->{{58.77642113690954,
|
||||
91.79843875100082}, {-77.43414818793038, 91.93456273819318}}],
|
||||
StatusArea[#, 98]& ,
|
||||
TagBoxNote->"98"],
|
||||
StyleBox["98", {}, StripOnInput -> False]],
|
||||
Annotation[#,
|
||||
Style[98, {}], "Tooltip"]& ],
|
||||
TagBox[
|
||||
TooltipBox[
|
||||
TagBox[
|
||||
DynamicBox[{
|
||||
FEPrivate`If[
|
||||
CurrentValue["MouseOver"],
|
||||
EdgeForm[{
|
||||
GrayLevel[0.5],
|
||||
AbsoluteThickness[1.5],
|
||||
Opacity[0.66]}], {}, {}],
|
||||
RectangleBox[{2., 0}, {3., 105}, "RoundingRadius" -> 0]},
|
||||
ImageSizeCache->{{91.29843875100082,
|
||||
124.3204563650921}, {-89.49619896836775, 91.93456273819318}}],
|
||||
StatusArea[#, 105]& ,
|
||||
TagBoxNote->"105"],
|
||||
StyleBox["105", {}, StripOnInput -> False]],
|
||||
Annotation[#,
|
||||
Style[105, {}], "Tooltip"]& ],
|
||||
TagBox[
|
||||
TooltipBox[
|
||||
TagBox[
|
||||
DynamicBox[{
|
||||
FEPrivate`If[
|
||||
CurrentValue["MouseOver"],
|
||||
EdgeForm[{
|
||||
GrayLevel[0.5],
|
||||
AbsoluteThickness[1.5],
|
||||
Opacity[0.66]}], {}, {}],
|
||||
RectangleBox[{3., 0}, {4., 93}, "RoundingRadius" -> 0]},
|
||||
ImageSizeCache->{{123.8204563650921,
|
||||
156.84247397918338`}, {-68.81839763047508, 91.93456273819318}}],
|
||||
StatusArea[#, 93]& ,
|
||||
TagBoxNote->"93"],
|
||||
StyleBox["93", {}, StripOnInput -> False]],
|
||||
Annotation[#,
|
||||
Style[93, {}], "Tooltip"]& ],
|
||||
TagBox[
|
||||
TooltipBox[
|
||||
TagBox[
|
||||
DynamicBox[{
|
||||
FEPrivate`If[
|
||||
CurrentValue["MouseOver"],
|
||||
EdgeForm[{
|
||||
GrayLevel[0.5],
|
||||
AbsoluteThickness[1.5],
|
||||
Opacity[0.66]}], {}, {}],
|
||||
RectangleBox[{4., 0}, {5., 105}, "RoundingRadius" -> 0]},
|
||||
ImageSizeCache->{{156.34247397918338`,
|
||||
189.36449159327466`}, {-89.49619896836775, 91.93456273819318}}],
|
||||
StatusArea[#, 105]& ,
|
||||
TagBoxNote->"105"],
|
||||
StyleBox["105", {}, StripOnInput -> False]],
|
||||
Annotation[#,
|
||||
Style[105, {}], "Tooltip"]& ],
|
||||
TagBox[
|
||||
TooltipBox[
|
||||
TagBox[
|
||||
DynamicBox[{
|
||||
FEPrivate`If[
|
||||
CurrentValue["MouseOver"],
|
||||
EdgeForm[{
|
||||
GrayLevel[0.5],
|
||||
AbsoluteThickness[1.5],
|
||||
Opacity[0.66]}], {}, {}],
|
||||
RectangleBox[{5., 0}, {6., 110}, "RoundingRadius" -> 0]},
|
||||
ImageSizeCache->{{188.86449159327466`,
|
||||
221.88650920736595`}, {-98.11194952582305, 91.93456273819318}}],
|
||||
StatusArea[#, 110]& ,
|
||||
TagBoxNote->"110"],
|
||||
StyleBox["110", {}, StripOnInput -> False]],
|
||||
Annotation[#,
|
||||
Style[110, {}], "Tooltip"]& ],
|
||||
TagBox[
|
||||
TooltipBox[
|
||||
TagBox[
|
||||
DynamicBox[{
|
||||
FEPrivate`If[
|
||||
CurrentValue["MouseOver"],
|
||||
EdgeForm[{
|
||||
GrayLevel[0.5],
|
||||
AbsoluteThickness[1.5],
|
||||
Opacity[0.66]}], {}, {}],
|
||||
RectangleBox[{6., 0}, {7., 91}, "RoundingRadius" -> 0]},
|
||||
ImageSizeCache->{{221.38650920736595`,
|
||||
254.40852682145723`}, {-65.37209740749297, 91.93456273819318}}],
|
||||
StatusArea[#, 91]& ,
|
||||
TagBoxNote->"91"],
|
||||
StyleBox["91", {}, StripOnInput -> False]],
|
||||
Annotation[#,
|
||||
Style[91, {}], "Tooltip"]& ],
|
||||
TagBox[
|
||||
TooltipBox[
|
||||
TagBox[
|
||||
DynamicBox[{
|
||||
FEPrivate`If[
|
||||
CurrentValue["MouseOver"],
|
||||
EdgeForm[{
|
||||
GrayLevel[0.5],
|
||||
AbsoluteThickness[1.5],
|
||||
Opacity[0.66]}], {}, {}],
|
||||
RectangleBox[{7., 0}, {8., 100}, "RoundingRadius" -> 0]},
|
||||
ImageSizeCache->{{253.90852682145723`,
|
||||
286.93054443554854`}, {-80.88044841091248, 91.93456273819318}}],
|
||||
StatusArea[#, 100]& ,
|
||||
TagBoxNote->"100"],
|
||||
StyleBox["100", {}, StripOnInput -> False]],
|
||||
Annotation[#,
|
||||
Style[100, {}], "Tooltip"]& ],
|
||||
TagBox[
|
||||
TooltipBox[
|
||||
TagBox[
|
||||
DynamicBox[{
|
||||
FEPrivate`If[
|
||||
CurrentValue["MouseOver"],
|
||||
EdgeForm[{
|
||||
GrayLevel[0.5],
|
||||
AbsoluteThickness[1.5],
|
||||
Opacity[0.66]}], {}, {}],
|
||||
RectangleBox[{8., 0}, {9., 104}, "RoundingRadius" -> 0]},
|
||||
ImageSizeCache->{{286.43054443554854`,
|
||||
319.4525620496398}, {-87.77304885687671, 91.93456273819318}}],
|
||||
StatusArea[#, 104]& ,
|
||||
TagBoxNote->"104"],
|
||||
StyleBox["104", {}, StripOnInput -> False]],
|
||||
Annotation[#,
|
||||
Style[104, {}], "Tooltip"]& ],
|
||||
TagBox[
|
||||
TooltipBox[
|
||||
TagBox[
|
||||
DynamicBox[{
|
||||
FEPrivate`If[
|
||||
CurrentValue["MouseOver"],
|
||||
EdgeForm[{
|
||||
GrayLevel[0.5],
|
||||
AbsoluteThickness[1.5],
|
||||
Opacity[0.66]}], {}, {}],
|
||||
RectangleBox[{9., 0}, {10., 113}, "RoundingRadius" -> 0]},
|
||||
ImageSizeCache->{{318.9525620496398,
|
||||
351.9745796637311}, {-103.28139986029622`, 91.93456273819318}}],
|
||||
StatusArea[#, 113]& ,
|
||||
TagBoxNote->"113"],
|
||||
StyleBox["113", {}, StripOnInput -> False]],
|
||||
Annotation[#,
|
||||
Style[113, {}],
|
||||
"Tooltip"]& ]}, {}, {}}, {{}, {}, {}, {}, {}, {}, {}, {}, {}, {}}},
|
||||
AspectRatio->NCache[GoldenRatio^(-1), 0.6180339887498948],
|
||||
Axes->{True, True},
|
||||
AxesLabel->{None, None},
|
||||
AxesOrigin->{-0.2, 0},
|
||||
FrameLabel->{{None, None}, {None, None}},
|
||||
FrameTicks->{{Automatic, Automatic}, {Automatic, Automatic}},
|
||||
GridLines->{None, None},
|
||||
GridLinesStyle->Directive[
|
||||
GrayLevel[0.5, 0.4]],
|
||||
PlotRange->{{0., 10.}, {All, All}},
|
||||
PlotRangePadding->{{
|
||||
Scaled[0.02],
|
||||
Scaled[0.02]}, {
|
||||
Scaled[0.02],
|
||||
Scaled[0.05]}},
|
||||
Ticks->{Automatic, Automatic}]], "Output",
|
||||
ExpressionUUID -> "00030c6d-66e9-4869-b5ac-1f17488c7fd2"]
|
||||
}, Open ]]
|
||||
}, Open ]]
|
||||
},
|
||||
WindowSize->{808, 751},
|
||||
WindowMargins->{{68, Automatic}, {Automatic, 44}},
|
||||
PrivateNotebookOptions->{"FileOutlineCache"->False},
|
||||
TrackCellChangeTimes->False,
|
||||
FrontEndVersion->"10.0 for Mac OS X x86 (32-bit, 64-bit Kernel) (December 4, \
|
||||
2014)",
|
||||
StyleDefinitions->"Default.nb"
|
||||
]
|
||||
|
323
LTemplate/Documentation/FAQ.nb
Normal file
323
LTemplate/Documentation/FAQ.nb
Normal file
@ -0,0 +1,323 @@
|
||||
Notebook[{
|
||||
|
||||
Cell[CellGroupData[{
|
||||
Cell["LTemplate FAQ", "Title",
|
||||
ExpressionUUID -> "a5b9798d-8acb-4713-b51f-9f5a4097104d"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell["What is LTemplate?", "Subsection",
|
||||
ExpressionUUID -> "e800e0bf-3d74-4a5b-be42-25cbbd33f0a3"],
|
||||
|
||||
Cell[TextData[{
|
||||
"LTemplate is a system that makes ",
|
||||
ButtonBox["LibraryLink",
|
||||
BaseStyle->"Link",
|
||||
ButtonData->"paclet:LibraryLink/tutorial/Overview"],
|
||||
" development fast and convenient."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "84bc5199-cfac-4299-bbcf-7a325adebdda"],
|
||||
|
||||
Cell[TextData[{
|
||||
"LTemplate is a ",
|
||||
StyleBox["Mathematica",
|
||||
FontSlant->"Italic"],
|
||||
" package that simplifies writing LibraryLink code by automatically \
|
||||
generating repetitive code based on \[OpenCurlyDoubleQuote]templates\
|
||||
\[CloseCurlyDoubleQuote] describing a C++ class interface. These are inspired \
|
||||
by ",
|
||||
StyleBox["MathLink",
|
||||
FontSlant->"Italic"],
|
||||
"\[CloseCurlyQuote]s ",
|
||||
StyleBox[".tm", "Program"],
|
||||
" files. It also provides easy to use C++ wrapper classes for the usual \
|
||||
LibraryLink types, as well as a number of convenience functions for faster \
|
||||
development and debugging."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "5c9c4883-d28c-4484-a0dd-dbdec923af1b"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell["What is the best way to learn LTemplate?", "Subsection",
|
||||
ExpressionUUID -> "10ef8230-2810-479d-a49e-81c66d950569"],
|
||||
|
||||
Cell[TextData[{
|
||||
"It is recommended to understand the basics of the LibraryLink C API before \
|
||||
starting to use LTemplate. ",
|
||||
ButtonBox["There is an excellent set of tutorials at Wolfram Community",
|
||||
BaseStyle->"Hyperlink",
|
||||
ButtonData->{
|
||||
URL["http://community.wolfram.com/groups/-/m/t/189735/"], None},
|
||||
ButtonNote->"http://community.wolfram.com/groups/-/m/t/189735/"],
|
||||
", written by Arnoud Buzing. These are much easier to follow than the User \
|
||||
Guide. Read them concurrently with ",
|
||||
ButtonBox["the LibraryLink User Guide",
|
||||
BaseStyle->"Link",
|
||||
ButtonData->"paclet:LibraryLink/tutorial/Overview"],
|
||||
" and learn at least about passing numerical arguments, returning results, \
|
||||
and basic handling of arrays."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "c89e8e65-ef9d-4631-8615-3f48fa4c6a24"],
|
||||
|
||||
Cell[TextData[{
|
||||
"Once you have a grasp of the basics, start reading ",
|
||||
ButtonBox["LTemplateTutorial",
|
||||
BaseStyle->"Hyperlink",
|
||||
ButtonData->{"LTemplateTutorial.nb", None}],
|
||||
" while concurrently looking at the example programs in the \
|
||||
Documentation/Examples directory. Start with these two sets of examples: \
|
||||
Basics, Tensor."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "48223301-4631-4c9d-8eba-22f3997bbeda"],
|
||||
|
||||
Cell[TextData[{
|
||||
"When working with array-like types, such as Tensors, SparseArray, Images \
|
||||
and RawArrays, it is important to understand memory management in \
|
||||
LibraryLink. This is discussed in the ",
|
||||
ButtonBox["Memory Management of MTensors",
|
||||
BaseStyle->"Link",
|
||||
ButtonData->
|
||||
"paclet:LibraryLink/tutorial/InteractionWithMathematica#97446640"],
|
||||
" section of the User Guide."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "200e6859-1313-406b-bc6e-7a01099ac1c7"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell["\<\
|
||||
Do I need to learn LibraryLink before starting to use LTemplate?\
|
||||
\>", "Subsection",
|
||||
ExpressionUUID -> "fe2694c6-98bb-4b52-9fee-1ff1b8bc7609"],
|
||||
|
||||
Cell[TextData[{
|
||||
"Yes, it is strongly recommended to learn at least the basics. Please take a \
|
||||
look at ",
|
||||
ButtonBox["the LibraryLink user guide",
|
||||
BaseStyle->"Link",
|
||||
ButtonData->"paclet:LibraryLink/tutorial/Overview"],
|
||||
" and understand the basic LibraryLink examples."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "7be581f2-80bf-479c-8e6e-b52c26c90176"],
|
||||
|
||||
Cell["\<\
|
||||
While LTemplate makes it much easier and faster to set up a library, it is \
|
||||
necessary to understand certain concepts, such as the memory management of \
|
||||
MTensors, to be able to write correct code.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "227313e7-b579-4141-b2de-fdec7ba242c8"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell["What are the minimum system requirements?", "Subsection",
|
||||
ExpressionUUID -> "51910736-00c4-49b0-a96a-8f49ce40bc9b"],
|
||||
|
||||
Cell[TextData[{
|
||||
StyleBox["Mathematica",
|
||||
FontSlant->"Italic"],
|
||||
" 10.0 or later and a C++11 capable compiler."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "9fe30d23-5ab4-4554-8cf8-8c2bdfd839b0"],
|
||||
|
||||
Cell["\<\
|
||||
If using the default compiler on OS X, then OS X 10.9 or later is needed for \
|
||||
C++11 support.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "21a75098-23b8-4b98-a52d-c5bf149c206b"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell["\<\
|
||||
Can I use LTemplate to generate an interface to an existing class?\
|
||||
\>", "Subsection",
|
||||
ExpressionUUID -> "1e1f3d74-d37e-4ca9-9add-9bd3b2dc3f03"],
|
||||
|
||||
Cell["\<\
|
||||
No. Just like LibraryLink\[CloseCurlyQuote]s library functions, LTemplate \
|
||||
classes must follow certain conventions.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "6149f3af-6968-4612-821d-e0bb36832284"],
|
||||
|
||||
Cell["\<\
|
||||
To interface with another library, one would normally create conversion \
|
||||
functions to/from that library\[CloseCurlyQuote]s data types. See \
|
||||
Examples/Armadillo for an example.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "d359e04d-37aa-4085-a1a0-9debfc2116ff"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell["Can I use C instead of C++?", "Subsection",
|
||||
ExpressionUUID -> "450cc096-5703-43bd-99bc-43067ca00ffc"],
|
||||
|
||||
Cell["\<\
|
||||
LTemplate requires the use of C++. It is the features that C++ provides over \
|
||||
C that made it possible to construct an easier-to-use interface than the C \
|
||||
LibraryLink API. However, LTemplate only requires the use of relatively basic \
|
||||
C++ features.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "648cfb8b-abac-4831-a302-3630b1347094"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell["\<\
|
||||
Why do I need to create a class? I only need a few functions.\
|
||||
\>", "Subsection",
|
||||
ExpressionUUID -> "199aeea2-6a9e-4d87-96b8-83f5fb006faa"],
|
||||
|
||||
Cell["\<\
|
||||
Future versions of LTemplate may add support for free functions.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "e81f5fe4-c895-4058-8ce6-e841fe1da761"],
|
||||
|
||||
Cell["\<\
|
||||
Originally, LTemplate was created to make it easy to set up managed library \
|
||||
expressions, which map very well to classes. If you only need free \
|
||||
functions, you can always create a single instance of a class, and keep \
|
||||
calling functions on it.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "cf515e75-a8f9-48e7-b670-3165f0b60d1e"],
|
||||
|
||||
Cell["\<\
|
||||
However, non-trivial libraries that manage a global state, such as physics \
|
||||
simulations, typically benefit from encapsulating that state into a class. \
|
||||
Then it becomes easy to create multiple simulation states and manage them \
|
||||
simultaneously.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "a9232ad7-1bf9-4d2f-961d-48ddfa5cdf2c"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell["How do I write library initialization and cleanup code?", "Subsection",
|
||||
ExpressionUUID -> "7156cafb-6789-46cc-861c-dde52523c241"],
|
||||
|
||||
Cell[TextData[{
|
||||
"Currently LTemplate doesn\[CloseCurlyQuote]t support injecting code into ",
|
||||
StyleBox["WolframLibrary_initialize", "Program"],
|
||||
" and ",
|
||||
StyleBox["WolframLibrary_uninitialize", "Program"],
|
||||
". Add the initialization and cleanup code to the constructor and destructor \
|
||||
of a special class. Then create a single instance of this class. The \
|
||||
destructor will be called when the library is unloaded."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "c0e101f7-fb15-475d-86d2-91512f7e6871"],
|
||||
|
||||
Cell["\<\
|
||||
A drawback of this method is that it cannot be controlled which classes and \
|
||||
which objects will be destroyed last. This will be remedied in a future \
|
||||
version of LTemplate.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "8fdffd20-a2eb-4df5-903f-b07a1baec6b7"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell["Can I use the LibraryLink C API with LTemplate?", "Subsection",
|
||||
ExpressionUUID -> "3869333c-c237-439b-9bda-cb8b0d1121c5"],
|
||||
|
||||
Cell[TextData[{
|
||||
"Yes, the C functions from ",
|
||||
StyleBox["WolframLibrary.h", "Program"],
|
||||
" can be used in a library built with LTemplate."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "e578081d-e797-43a6-8e7c-e0a6ececb829"],
|
||||
|
||||
Cell[TextData[{
|
||||
"Wrapper classes, such as ",
|
||||
StyleBox["mma::TensorRef", "Program"],
|
||||
", always provide access to the underlying data structure, such as ",
|
||||
StyleBox["MTensor", "Program"],
|
||||
". See e.g. ",
|
||||
StyleBox["mma::TensorRef::tensor()", "Program"],
|
||||
"."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "42722a35-6258-4c92-9f37-cf435e4cc308"],
|
||||
|
||||
Cell[TextData[{
|
||||
StyleBox["mma::libData", "Program"],
|
||||
" provides access to the LibraryLink callback functions."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "c9873b5b-4323-4c9b-bf4f-c57dbb5cfbdb"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell["Can I use LTemplate in another package?", "Subsection",
|
||||
ExpressionUUID -> "909417d4-a800-483c-87ab-9ea4ce1c1c17"],
|
||||
|
||||
Cell["\<\
|
||||
Yes, LTemplate is designed to be embeddable into other packages.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "a96a30e4-40f1-4dd6-9276-ee30fd5a3a7e"],
|
||||
|
||||
Cell["\<\
|
||||
Mathematica packages that rely on LTemplate should embed it instead of \
|
||||
requiring users to install LTemplate. This is to avoid compatibility problems.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "b4c08f9c-74dd-4046-a480-8e2f8dfd5447"],
|
||||
|
||||
Cell["\<\
|
||||
When LTemplate is embedded into another package, it supports a few \
|
||||
customization features:\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "626ecd89-cbfc-4337-88a2-b6b8380b001b"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell["\<\
|
||||
The symbol that library messages are associated with can be customized.\
|
||||
\>", "Item",
|
||||
ExpressionUUID -> "bd6578de-767a-4477-9e09-f0ef6e2707dc"],
|
||||
|
||||
Cell["\<\
|
||||
LTemplate can be set up for lazy loading, so that each function gets loaded \
|
||||
only when needed.\
|
||||
\>", "Item",
|
||||
ExpressionUUID -> "caeec10e-d9e6-4ec4-b674-66badb0548b8"]
|
||||
}, Open ]],
|
||||
|
||||
Cell["\<\
|
||||
See the skeleton-project directory for an example of embedding LTemplate.\
|
||||
\>", "Text",
|
||||
ExpressionUUID -> "7cd2aed8-e1d5-401d-8058-ed20cf1575c4"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell["Are there any published packages built on LTemplate?", "Subsection",
|
||||
ExpressionUUID -> "1ccb7075-3970-4518-bcac-634be0af38e5"],
|
||||
|
||||
Cell[TextData[{
|
||||
ButtonBox["IGraph/M",
|
||||
BaseStyle->"Hyperlink",
|
||||
ButtonData->{
|
||||
URL["http://szhorvat.net/mathematica/IGraphM"], None},
|
||||
ButtonNote->"http://szhorvat.net/mathematica/IGraphM"],
|
||||
" is an interface to the ",
|
||||
ButtonBox["igraph network analysis library",
|
||||
BaseStyle->"Hyperlink",
|
||||
ButtonData->{
|
||||
URL["http://igraph.org/"], None},
|
||||
ButtonNote->"http://igraph.org/"],
|
||||
". It is built on top of LTemplate, and it implements a wrapper class for \
|
||||
igraph graphs."
|
||||
}], "Text",
|
||||
ExpressionUUID -> "954ec604-83e0-4c38-acf8-7c72a132ab8f"]
|
||||
}, Open ]]
|
||||
}, Open ]]
|
||||
},
|
||||
WindowSize->{641, 852},
|
||||
WindowMargins->{{183, Automatic}, {Automatic, 49}},
|
||||
PrivateNotebookOptions->{"FileOutlineCache"->False},
|
||||
TrackCellChangeTimes->False,
|
||||
FrontEndVersion->"10.4 for Mac OS X x86 (32-bit, 64-bit Kernel) (April 11, \
|
||||
2016)",
|
||||
StyleDefinitions->"Default.nb"
|
||||
]
|
||||
|
3661
LTemplate/Documentation/LTemplateTutorial.nb
Normal file
3661
LTemplate/Documentation/LTemplateTutorial.nb
Normal file
File diff suppressed because it is too large
Load Diff
2362
LTemplate/IncludeFiles/Doxyfile
Normal file
2362
LTemplate/IncludeFiles/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
2094
LTemplate/IncludeFiles/LTemplate.h
Normal file
2094
LTemplate/IncludeFiles/LTemplate.h
Normal file
File diff suppressed because it is too large
Load Diff
95
LTemplate/IncludeFiles/LTemplate.inc
Normal file
95
LTemplate/IncludeFiles/LTemplate.inc
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Szabolcs Horvát.
|
||||
*
|
||||
* See the file LICENSE.txt for copying permission.
|
||||
*/
|
||||
|
||||
// These #includes are redundant. They are only for the IDE.
|
||||
#include "LTemplate.h"
|
||||
#include "LTemplateHelpers.h"
|
||||
|
||||
|
||||
namespace mma {
|
||||
|
||||
|
||||
WolframLibraryData libData;
|
||||
|
||||
|
||||
namespace detail { // private
|
||||
|
||||
int MBuffer::sync() {
|
||||
// If the last character is a newline, remove it.
|
||||
// This makes it convenient to flush with std::endl
|
||||
if (pptr() > pbase() && pptr()[-1] == '\n')
|
||||
pbump(-1);
|
||||
|
||||
*pptr() = '\0';
|
||||
std::ptrdiff_t n = pptr() - pbase();
|
||||
if (n > 0)
|
||||
mma::print(&buf.front());
|
||||
pbump(-n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::streambuf::int_type MBuffer::overflow(std::streambuf::int_type ch) {
|
||||
if (ch != traits_type::eof()) {
|
||||
massert(pptr() == epptr()); // overflow should only be called if the buffer is out of space
|
||||
|
||||
*pptr() = traits_type::to_char_type(ch);
|
||||
|
||||
std::size_t offset = pptr() - pbase();
|
||||
std::size_t old_buf_size = buf.size() - 1;
|
||||
buf.resize( 2*old_buf_size + 1 );
|
||||
|
||||
setp( &buf.front(), &buf.back() );
|
||||
pbump( offset + 1 );
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
static MBuffer mbuf;
|
||||
|
||||
} // end namespace detail
|
||||
|
||||
|
||||
std::ostream mout(&detail::mbuf);
|
||||
|
||||
|
||||
void message(const char *msg, MessageType type) {
|
||||
if (msg == NULL)
|
||||
return;
|
||||
|
||||
if (libData->AbortQ())
|
||||
return; // trying to use the MathLink connection during an abort will break it
|
||||
|
||||
const char *tag;
|
||||
switch (type) {
|
||||
case M_ERROR:
|
||||
tag = "error";
|
||||
break;
|
||||
case M_WARNING:
|
||||
tag = "warning";
|
||||
break;
|
||||
case M_ASSERT:
|
||||
tag = "assert";
|
||||
break;
|
||||
case M_INFO:
|
||||
default:
|
||||
tag = "info";
|
||||
}
|
||||
|
||||
MLINK link = libData->getMathLink(libData);
|
||||
MLPutFunction(link, "EvaluatePacket", 1);
|
||||
MLPutFunction(link, "Message", 2);
|
||||
MLPutFunction(link, "MessageName", 2);
|
||||
MLPutSymbol(link, LTEMPLATE_MESSAGE_SYMBOL);
|
||||
MLPutString(link, tag);
|
||||
MLPutString(link, msg);
|
||||
libData->processMathLink(link);
|
||||
int pkt = MLNextPacket(link);
|
||||
if (pkt == RETURNPKT)
|
||||
MLNewPacket(link);
|
||||
}
|
||||
|
||||
|
||||
} // end namespace mma
|
22
LTemplate/IncludeFiles/LTemplateCompilerSetup.h
Normal file
22
LTemplate/IncludeFiles/LTemplateCompilerSetup.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef LTEMPLATE_COMPILER_SETUP_H
|
||||
#define LTEMPLATE_COMPILER_SETUP_H
|
||||
|
||||
#if __cplusplus >= 201103L || _MSC_VER >= 1900
|
||||
#define LTEMPLATE_USE_CXX11
|
||||
#endif
|
||||
|
||||
#if LTEMPLATE_MMA_VERSION >= 1040 && defined (LTEMPLATE_USE_CXX11)
|
||||
#define LTEMPLATE_RAWARRAY
|
||||
#endif
|
||||
|
||||
#if LTEMPLATE_MMA_VERSION >= 1200 && defined (LTEMPLATE_USE_CXX11)
|
||||
#define LTEMPLATE_NUMERICARRAY
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // LTEMPLATE_COMPILER_SETUP_H
|
152
LTemplate/IncludeFiles/LTemplateHelpers.h
Normal file
152
LTemplate/IncludeFiles/LTemplateHelpers.h
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Szabolcs Horvát.
|
||||
*
|
||||
* See the file LICENSE.txt for copying permission.
|
||||
*/
|
||||
|
||||
#ifndef LTEMPLATE_HELPERS_H
|
||||
#define LTEMPLATE_HELPERS_H
|
||||
|
||||
#include "LTemplate.h"
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace mma {
|
||||
namespace detail {
|
||||
|
||||
// Functions for getting and setting arguments and return values
|
||||
|
||||
template<typename T>
|
||||
inline TensorRef<T> getTensor(MArgument marg) { return MArgument_getMTensor(marg); }
|
||||
|
||||
template<typename T>
|
||||
inline void setTensor(MArgument marg, TensorRef<T> &val) { MArgument_setMTensor(marg, val.tensor()); }
|
||||
|
||||
template<typename T>
|
||||
inline SparseArrayRef<T> getSparseArray(MArgument marg) { return MArgument_getMSparseArray(marg); }
|
||||
|
||||
template<typename T>
|
||||
inline void setSparseArray(MArgument marg, SparseArrayRef<T> &val) { MArgument_setMSparseArray(marg, val.sparseArray()); }
|
||||
|
||||
template<typename T>
|
||||
inline ImageRef<T> getImage(MArgument marg) { return MArgument_getMImage(marg); }
|
||||
|
||||
template<typename T>
|
||||
inline Image3DRef<T> getImage3D(MArgument marg) { return MArgument_getMImage(marg); }
|
||||
|
||||
inline GenericImageRef getGenericImage(MArgument marg) { return MArgument_getMImage(marg); }
|
||||
inline GenericImage3DRef getGenericImage3D(MArgument marg) { return MArgument_getMImage(marg); }
|
||||
|
||||
template<typename T>
|
||||
inline void setImage(MArgument marg, ImageRef<T> &val) { MArgument_setMImage(marg, val.image()); }
|
||||
|
||||
template<typename T>
|
||||
inline void setImage3D(MArgument marg, Image3DRef<T> &val) { MArgument_setMImage(marg, val.image()); }
|
||||
|
||||
inline void setGenericImage(MArgument marg, GenericImageRef &val) { MArgument_setMImage(marg, val.image()); }
|
||||
inline void setGenericImage3D(MArgument marg, GenericImage3DRef &val) { MArgument_setMImage(marg, val.image()); }
|
||||
|
||||
#ifdef LTEMPLATE_RAWARRAY
|
||||
template<typename T>
|
||||
inline RawArrayRef<T> getRawArray(MArgument marg) { return MArgument_getMRawArray(marg); }
|
||||
inline GenericRawArrayRef getGenericRawArray(MArgument marg) { return MArgument_getMRawArray(marg); }
|
||||
|
||||
template<typename T>
|
||||
inline void setRawArray(MArgument marg, RawArrayRef<T> &val) { MArgument_setMRawArray(marg, val.rawArray()); }
|
||||
inline void setGenericRawArray(MArgument marg, GenericRawArrayRef &val) { MArgument_setMRawArray(marg, val.rawArray()); }
|
||||
#endif // LTEMPLATE_RAWARRAY
|
||||
|
||||
#ifdef LTEMPLATE_NUMERICARRAY
|
||||
template<typename T>
|
||||
inline NumericArrayRef<T> getNumericArray(MArgument marg) { return MArgument_getMNumericArray(marg); }
|
||||
inline GenericNumericArrayRef getGenericNumericArray(MArgument marg) { return MArgument_getMNumericArray(marg); }
|
||||
|
||||
template<typename T>
|
||||
inline void setNumericArray(MArgument marg, NumericArrayRef<T> &val) { MArgument_setMNumericArray(marg, val.numericArray()); }
|
||||
inline void setGenericNumericArray(MArgument marg, GenericNumericArrayRef &val) { MArgument_setMNumericArray(marg, val.numericArray()); }
|
||||
#endif // LTEMPLATE_NUMERICARRAY
|
||||
|
||||
inline complex_t getComplex(MArgument marg) {
|
||||
mcomplex c = MArgument_getComplex(marg);
|
||||
return complex_t(c.ri[0], c.ri[1]);
|
||||
}
|
||||
|
||||
inline void setComplex(MArgument marg, complex_t val) {
|
||||
mcomplex *c = reinterpret_cast<mcomplex *>(&val);
|
||||
MArgument_setComplex(marg, *c);
|
||||
}
|
||||
|
||||
|
||||
inline const char *getString(MArgument marg) {
|
||||
return const_cast<const char *>(MArgument_getUTF8String(marg));
|
||||
}
|
||||
|
||||
inline void setString(MArgument marg, const char *val) {
|
||||
MArgument_setUTF8String(marg, const_cast<char *>(val));
|
||||
}
|
||||
|
||||
|
||||
template<typename Collection>
|
||||
inline IntTensorRef get_collection(const Collection &collection) {
|
||||
IntTensorRef ids = makeVector<mint>(collection.size());
|
||||
|
||||
typename Collection::const_iterator i = collection.begin();
|
||||
mint *j = ids.begin();
|
||||
for (; i != collection.end(); ++i, ++j)
|
||||
*j = i->first;
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
class getObject {
|
||||
std::map<mint, T *> &collection;
|
||||
public:
|
||||
explicit getObject(std::map<mint, T *> &coll) : collection(coll) { }
|
||||
T & operator () (MArgument marg) { return *(collection[MArgument_getInteger(marg)]); }
|
||||
};
|
||||
|
||||
|
||||
// Underlying stream buffer for mma::mout
|
||||
class MBuffer : public std::streambuf {
|
||||
std::vector<char_type> buf;
|
||||
|
||||
public:
|
||||
explicit MBuffer(std::size_t buf_size = 4096) : buf(buf_size + 1) {
|
||||
setp(&buf.front(), &buf.back());
|
||||
}
|
||||
|
||||
protected:
|
||||
int sync();
|
||||
int_type overflow(int_type ch);
|
||||
|
||||
private:
|
||||
MBuffer(const MBuffer &);
|
||||
MBuffer & operator = (const MBuffer &);
|
||||
};
|
||||
|
||||
|
||||
// Used with RAII to ensure that mma::mout is flushed before the exit of any top-level function.
|
||||
struct MOutFlushGuard {
|
||||
~MOutFlushGuard() { mout.flush(); }
|
||||
};
|
||||
|
||||
|
||||
// Handles unknown exceptions in top-level functions.
|
||||
inline void handleUnknownException(const char *what, const char *funname) {
|
||||
std::ostringstream msg;
|
||||
msg << "Unknown exception caught in "
|
||||
<< funname
|
||||
<< ". The library may be in an inconsistent state. It is recommended that you restart the kernel now to avoid instability.";
|
||||
if (what)
|
||||
msg << '\n' << what;
|
||||
message(msg.str(), M_ERROR);
|
||||
}
|
||||
|
||||
|
||||
} // namespace detail
|
||||
} // namespace mma
|
||||
|
||||
#endif // LTEMPLATE_HELPERS_H
|
441
LTemplate/IncludeFiles/mlstream.h
Normal file
441
LTemplate/IncludeFiles/mlstream.h
Normal file
@ -0,0 +1,441 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Szabolcs Horvát.
|
||||
*
|
||||
* See the file LICENSE.txt for copying permission.
|
||||
*/
|
||||
|
||||
#ifndef MLSTREAM_H
|
||||
#define MLSTREAM_H
|
||||
|
||||
/** \file mlstream.h
|
||||
* \brief Auxiliary header for LTemplate to ease reading function arguments and returning values through MathLink.
|
||||
*
|
||||
* LTemplate itself does not depend on mlstream.h, so if you don't use this header,
|
||||
* feel free to remove it from your project. mlstream.h is not meant as a general
|
||||
* MathLink interface. It is specifically designed for handling arguments and return
|
||||
* values in conjunction with LTemplate and `LinkObject`-based functions.
|
||||
* To do this, mlstream functions are usually called in a specific sequence, as
|
||||
* illustrated below.
|
||||
*
|
||||
* Example usage:
|
||||
* \code
|
||||
* void addMult(MLINK link) {
|
||||
* mlStream ml(link, "addMult"); // any errors messages will mention the context "addMult"
|
||||
*
|
||||
* int i, j;
|
||||
* ml >> mlCheckArgs(2) // read off the head List and check argument count
|
||||
* >> i >> j; // read two integer arguments
|
||||
*
|
||||
* // compute the result
|
||||
* int sum = i+j;
|
||||
* int prod = i*j;
|
||||
*
|
||||
* // alias for MLNewPacket, must be used before returning the result
|
||||
* ml.newPacket();
|
||||
*
|
||||
* // we return two results in a list
|
||||
* ml << mlHead("List", 2)
|
||||
* << sum << prod;
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* See `Documentation/Examples/LinkObject` for more examples.
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* Currently, mlstream.h has direct support for sending and receiving the following types:
|
||||
*
|
||||
* **Sending**
|
||||
*
|
||||
* - Signed integers (16-, 32- and 64-bit)
|
||||
* - Floating point numbers
|
||||
* - Strings (`std::string` or null-terminated C string)
|
||||
* - `mma::RealTensorRef` and `mma::IntTensorRef` of arbitrary dimensions
|
||||
* - `std::vector` or `std::list` holding any supported type (with optimization for `std::vector` holding numerical types)
|
||||
* - `std::pair` holding any two supported types
|
||||
* - Symbols (mlSymbol) or functions (mlHead)
|
||||
*
|
||||
* **Receiving**
|
||||
*
|
||||
* - Signed integers (16-, 32- and 64-bit)
|
||||
* - Floating point numbers
|
||||
* - Strings (`std::string` only)
|
||||
* - `std::vector` holding any supported type (with optimization for numerical types)
|
||||
*/
|
||||
|
||||
#include "LTemplate.h"
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
// Sanity checks for the sizes of MathLink integer types.
|
||||
static_assert(sizeof(short) == 2, "MathLink type size mismatch: sizeof(short) != 2.");
|
||||
static_assert(sizeof(int) == 4 , "MathLink type size mismatch: sizeof(int) != 4.");
|
||||
static_assert(sizeof(mlint64) == 8, "MathLink type size mismatch: sizeof(mlint64) != 8.");
|
||||
|
||||
|
||||
/** \brief Wrapper for `MLINK` to allow using extractors and inserters
|
||||
*
|
||||
* \param link is the MLINK object to wrap
|
||||
* \param context is a string that will be prepended to any message reported using error()
|
||||
*/
|
||||
class mlStream {
|
||||
MLINK lp;
|
||||
std::string context;
|
||||
|
||||
public:
|
||||
explicit mlStream(MLINK link) : lp(link) { }
|
||||
mlStream(MLINK link, const std::string &context) : lp(link), context(context) { }
|
||||
|
||||
/// Retrieve the stored `MLINK`
|
||||
MLINK link() { return lp; }
|
||||
|
||||
/// Throws a \ref mma::LibraryError with a given message.
|
||||
[[ noreturn ]] void error(const std::string &err) {
|
||||
std::ostringstream msg;
|
||||
if (! context.empty())
|
||||
msg << context << ": ";
|
||||
msg << err << ".";
|
||||
throw mma::LibraryError(msg.str());
|
||||
}
|
||||
|
||||
/// Equivalent to `MLNewPacket()`
|
||||
void newPacket() {
|
||||
MLNewPacket(lp);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Special
|
||||
|
||||
/// Must be the first item extracted from an mlStream, checks number of arguments and prepares for reading them.
|
||||
struct mlCheckArgs {
|
||||
int argc;
|
||||
|
||||
explicit mlCheckArgs(int argc) : argc(argc) { }
|
||||
};
|
||||
|
||||
inline mlStream & operator >> (mlStream &ml, const mlCheckArgs &ca) {
|
||||
int count;
|
||||
|
||||
if (! MLTestHead(ml.link(), "List", &count))
|
||||
ml.error("argument check: head \"List\" expected");
|
||||
|
||||
if (count != ca.argc){
|
||||
std::ostringstream msg;
|
||||
msg << ca.argc << " argument" << (ca.argc == 1 ? "" : "s") << " expected, " << count << " received";
|
||||
ml.error(msg.str());
|
||||
}
|
||||
|
||||
return ml;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Used for inserting a head with the given argument count into an mlStream.
|
||||
*
|
||||
* Typically used with the head `List` when returning multiple results.
|
||||
*
|
||||
* The following example returns the complex number `3 - 2I`.
|
||||
*
|
||||
* \code
|
||||
* ml << mlHead("Complex", 2) << 3 << -2;
|
||||
* \endcode
|
||||
*/
|
||||
struct mlHead {
|
||||
const char *head;
|
||||
int argc;
|
||||
|
||||
mlHead(const char *head, int argc) : head(head), argc(argc) { }
|
||||
};
|
||||
|
||||
inline mlStream & operator << (mlStream &ml, const mlHead &head) {
|
||||
if (! MLPutFunction(ml.link(), head.head, head.argc)) {
|
||||
std::ostringstream msg;
|
||||
msg << "Cannot put head " << head.head << " with " << head.argc << " arguments";
|
||||
ml.error(msg.str());
|
||||
}
|
||||
return ml;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Used for inserting a symbol into an mlStream
|
||||
*
|
||||
* The following example returns `True` or `False` based on a Boolean variable.
|
||||
*
|
||||
* \code
|
||||
* mlStream ml(link);
|
||||
* bool b;
|
||||
* // ...
|
||||
* ml.newPacket();
|
||||
* ml << (b ? mlSymbol("True") : mlSymbol("False"));
|
||||
* \endcode
|
||||
*
|
||||
* While this is convenient for a single result, Boolean arrays are much faster to transfer as integers.
|
||||
*/
|
||||
struct mlSymbol {
|
||||
const char *symbol;
|
||||
|
||||
explicit mlSymbol(const char *symbol) : symbol(symbol) { }
|
||||
};
|
||||
|
||||
inline mlStream & operator << (mlStream &ml, const mlSymbol &symbol) {
|
||||
if (! MLPutSymbol(ml.link(), symbol.symbol)) {
|
||||
std::ostringstream msg;
|
||||
msg << "Cannot put symbol " << symbol.symbol;
|
||||
ml.error(msg.str());
|
||||
}
|
||||
return ml;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Used for discarding a given number of expressions from an mlStream
|
||||
*
|
||||
* The following example reads 3 arguments, but does not use the second one.
|
||||
*
|
||||
* \code
|
||||
* mlStream ml(link);
|
||||
* ml >> mlCheckArgs(3) >> x >> mlDiscard() >> y;
|
||||
* \endcode
|
||||
*/
|
||||
struct mlDiscard {
|
||||
const int count;
|
||||
explicit mlDiscard(int count = 1) : count(count) { }
|
||||
};
|
||||
|
||||
inline mlStream & operator >> (mlStream &ml, const mlDiscard &drop) {
|
||||
for (int i=0; i < drop.count; ++i)
|
||||
if (! MLTransferExpression(nullptr, ml.link()))
|
||||
ml.error("Cannot discard expression");
|
||||
return ml;
|
||||
}
|
||||
|
||||
|
||||
// Basic types (integer and floating point)
|
||||
|
||||
#define MLSTREAM_DEF_BASIC_GET_INTEGRAL(MTYPE, CTYPE) \
|
||||
template<typename T, \
|
||||
typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value && sizeof(T) == sizeof(CTYPE), int>::type = 0 > \
|
||||
inline mlStream & operator >> (mlStream &ml, T &x) { \
|
||||
if (! MLGet ## MTYPE(ml.link(), reinterpret_cast<CTYPE *>(&x))) \
|
||||
ml.error(#MTYPE " expected"); \
|
||||
return ml; \
|
||||
}
|
||||
|
||||
MLSTREAM_DEF_BASIC_GET_INTEGRAL(Integer16, short)
|
||||
MLSTREAM_DEF_BASIC_GET_INTEGRAL(Integer32, int)
|
||||
MLSTREAM_DEF_BASIC_GET_INTEGRAL(Integer64, mlint64)
|
||||
|
||||
|
||||
#define MLSTREAM_DEF_BASIC_GET(MTYPE, CTYPE) \
|
||||
inline mlStream & operator >> (mlStream &ml, CTYPE &x) { \
|
||||
if (! MLGet ## MTYPE(ml.link(), &x)) \
|
||||
ml.error(#MTYPE " expected"); \
|
||||
return ml; \
|
||||
}
|
||||
|
||||
MLSTREAM_DEF_BASIC_GET(Real32, float)
|
||||
MLSTREAM_DEF_BASIC_GET(Real64, double)
|
||||
MLSTREAM_DEF_BASIC_GET(Real128, mlextended_double)
|
||||
|
||||
|
||||
#define MLSTREAM_DEF_BASIC_PUT_INTEGRAL(MTYPE, CTYPE) \
|
||||
template<typename T, \
|
||||
typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value && sizeof(T) == sizeof(CTYPE), int>::type = 0 > \
|
||||
inline mlStream & operator << (mlStream &ml, T x) { \
|
||||
if (! MLPut ## MTYPE(ml.link(), static_cast<CTYPE>(x))) \
|
||||
ml.error("Cannot return " #MTYPE); \
|
||||
return ml; \
|
||||
}
|
||||
|
||||
MLSTREAM_DEF_BASIC_PUT_INTEGRAL(Integer16, short)
|
||||
MLSTREAM_DEF_BASIC_PUT_INTEGRAL(Integer32, int)
|
||||
MLSTREAM_DEF_BASIC_PUT_INTEGRAL(Integer64, mlint64)
|
||||
|
||||
|
||||
#define MLSTREAM_DEF_BASIC_PUT(MTYPE, CTYPE) \
|
||||
inline mlStream & operator << (mlStream &ml, CTYPE x) { \
|
||||
if (! MLPut ## MTYPE(ml.link(), x)) \
|
||||
ml.error("Cannot return " #MTYPE); \
|
||||
return ml; \
|
||||
}
|
||||
|
||||
MLSTREAM_DEF_BASIC_PUT(Real32, float)
|
||||
MLSTREAM_DEF_BASIC_PUT(Real64, double)
|
||||
MLSTREAM_DEF_BASIC_PUT(Real128, mlextended_double)
|
||||
|
||||
|
||||
// Strings
|
||||
|
||||
inline mlStream & operator >> (mlStream &ml, std::string &s) {
|
||||
const unsigned char *sp;
|
||||
int bytes, chars;
|
||||
if (! MLGetUTF8String(ml.link(), &sp, &bytes, &chars))
|
||||
ml.error("String expected");
|
||||
s.assign(reinterpret_cast<const char *>(sp), bytes);
|
||||
MLReleaseUTF8String(ml.link(), sp, bytes);
|
||||
return ml;
|
||||
}
|
||||
|
||||
|
||||
inline mlStream & operator << (mlStream &ml, const std::string &s) {
|
||||
if (! MLPutUTF8String(ml.link(), reinterpret_cast<const unsigned char *>(s.c_str()), s.size()))
|
||||
ml.error("Cannot return UTF8 string");
|
||||
return ml;
|
||||
}
|
||||
|
||||
inline mlStream & operator << (mlStream &ml, const char *s) {
|
||||
if (! MLPutString(ml.link(), s))
|
||||
ml.error("Cannot return string");
|
||||
return ml;
|
||||
}
|
||||
|
||||
|
||||
// TensorRef
|
||||
|
||||
inline mlStream & operator << (mlStream &ml, mma::IntTensorRef t) {
|
||||
const int maxrank = 16;
|
||||
const int rank = t.rank();
|
||||
const mint *mdims = t.dimensions();
|
||||
int dims[maxrank];
|
||||
massert(rank <= maxrank);
|
||||
std::copy(mdims, mdims + rank, dims);
|
||||
#ifdef MINT_32
|
||||
if (! MLPutInteger32Array(ml.link(), reinterpret_cast<int *>(t.data()), dims, NULL, rank))
|
||||
ml.error("Cannot return Integer Tensor.");
|
||||
#else
|
||||
if (! MLPutInteger64Array(ml.link(), reinterpret_cast<mlint64 *>(t.data()), dims, nullptr, rank))
|
||||
ml.error("Cannot return Integer Tensor.");
|
||||
#endif
|
||||
return ml;
|
||||
}
|
||||
|
||||
inline mlStream & operator << (mlStream &ml, mma::RealTensorRef t) {
|
||||
const int maxrank = 16;
|
||||
const int rank = t.rank();
|
||||
const mint *mdims = t.dimensions();
|
||||
int dims[maxrank];
|
||||
massert(rank <= maxrank);
|
||||
std::copy(mdims, mdims + rank, dims);
|
||||
if (! MLPutReal64Array(ml.link(), t.data(), dims, nullptr, rank))
|
||||
ml.error("Cannot return Real Tensor");
|
||||
return ml;
|
||||
}
|
||||
|
||||
// TODO support complex tensors
|
||||
|
||||
|
||||
// Standard containers -- list
|
||||
|
||||
template<typename T>
|
||||
inline mlStream & operator << (mlStream &ml, const std::list<T> &ls) {
|
||||
ml << mlHead("List", ls.size());
|
||||
for (typename std::list<T>::const_iterator i = ls.begin(); i != ls.end(); ++i)
|
||||
ml << *i;
|
||||
return ml;
|
||||
}
|
||||
|
||||
|
||||
// Standard containers -- vector
|
||||
|
||||
// Put signed integer element types, 16, 32 and 64 bits.
|
||||
#define MLSTREAM_DEF_VEC_PUT_INTEGRAL(MTYPE, CTYPE) \
|
||||
template<typename T, \
|
||||
typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value && sizeof(T) == sizeof(CTYPE), int>::type = 0 > \
|
||||
inline mlStream & operator << (mlStream &ml, const std::vector<T> &vec) { \
|
||||
const CTYPE *data = vec.empty() ? nullptr : reinterpret_cast<const CTYPE *>(vec.data()); \
|
||||
if (! MLPut ## MTYPE ## List(ml.link(), data, vec.size())) \
|
||||
ml.error("Cannot return vector of " #MTYPE); \
|
||||
return ml; \
|
||||
}
|
||||
|
||||
MLSTREAM_DEF_VEC_PUT_INTEGRAL(Integer16, short)
|
||||
MLSTREAM_DEF_VEC_PUT_INTEGRAL(Integer32, int)
|
||||
MLSTREAM_DEF_VEC_PUT_INTEGRAL(Integer64, mlint64)
|
||||
|
||||
// Put floating point element types
|
||||
#define MLSTREAM_DEF_VEC_PUT(MTYPE, CTYPE) \
|
||||
inline mlStream & operator << (mlStream &ml, const std::vector<CTYPE> &vec) { \
|
||||
const CTYPE *data = vec.empty() ? nullptr : vec.data(); \
|
||||
if (! MLPut ## MTYPE ## List(ml.link(), data, vec.size())) \
|
||||
ml.error("Cannot return vector of " #MTYPE); \
|
||||
return ml; \
|
||||
}
|
||||
|
||||
MLSTREAM_DEF_VEC_PUT(Real32, float)
|
||||
MLSTREAM_DEF_VEC_PUT(Real64, double)
|
||||
MLSTREAM_DEF_VEC_PUT(Real128, mlextended_double)
|
||||
|
||||
// Put all other types
|
||||
template<typename T,
|
||||
typename std::enable_if<! (std::is_integral<T>::value && std::is_signed<T>::value && (sizeof(T) == sizeof(short) || sizeof(T) == sizeof(int) || sizeof(T) == sizeof(mlint64)) ), int>::type = 0 >
|
||||
inline mlStream & operator << (mlStream &ml, const std::vector<T> &vec) {
|
||||
ml << mlHead("List", vec.size());
|
||||
for (typename std::vector<T>::const_iterator i = vec.begin(); i != vec.end(); ++i)
|
||||
ml << *i;
|
||||
return ml;
|
||||
}
|
||||
|
||||
// Get signed integer element types
|
||||
#define MLSTREAM_DEF_VEC_GET_INTEGRAL(MTYPE, CTYPE) \
|
||||
template<typename T, \
|
||||
typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value && sizeof(T) == sizeof(CTYPE), int>::type = 0> \
|
||||
inline mlStream & operator >> (mlStream &ml, std::vector<T> &vec) { \
|
||||
CTYPE *data; \
|
||||
int count; \
|
||||
if (! MLGet ## MTYPE ## List(ml.link(), &data, &count)) \
|
||||
ml.error(#MTYPE " list expected"); \
|
||||
vec.assign(data, data+count); \
|
||||
MLRelease ## MTYPE ## List(ml.link(), data, count); \
|
||||
return ml; \
|
||||
}
|
||||
|
||||
MLSTREAM_DEF_VEC_GET_INTEGRAL(Integer16, short)
|
||||
MLSTREAM_DEF_VEC_GET_INTEGRAL(Integer32, int)
|
||||
MLSTREAM_DEF_VEC_GET_INTEGRAL(Integer64, mlint64)
|
||||
|
||||
// Get floating point element types
|
||||
#define MLSTREAM_DEF_VEC_GET(MTYPE, CTYPE) \
|
||||
inline mlStream & operator >> (mlStream &ml, std::vector<CTYPE> &vec) { \
|
||||
CTYPE *data; \
|
||||
int count; \
|
||||
if (! MLGet ## MTYPE ## List(ml.link(), &data, &count)) \
|
||||
ml.error(#MTYPE " list expected"); \
|
||||
vec.assign(data, data+count); \
|
||||
MLRelease ## MTYPE ## List(ml.link(), data, count); \
|
||||
return ml; \
|
||||
}
|
||||
|
||||
MLSTREAM_DEF_VEC_GET(Real32, float)
|
||||
MLSTREAM_DEF_VEC_GET(Real64, double)
|
||||
MLSTREAM_DEF_VEC_GET(Real128, mlextended_double)
|
||||
|
||||
|
||||
// Get all other types
|
||||
template<typename T,
|
||||
typename std::enable_if<! (std::is_integral<T>::value && std::is_signed<T>::value && (sizeof(T) == sizeof(short) || sizeof(T) == sizeof(int) || sizeof(T) == sizeof(mlint64)) ), int>::type = 0 >
|
||||
inline mlStream & operator >> (mlStream &ml, std::vector<T> &vec) {
|
||||
int count;
|
||||
if (! MLTestHead(ml.link(), "List", &count))
|
||||
ml.error("Head \"List\" expected");
|
||||
vec.clear();
|
||||
vec.resize(count);
|
||||
for (auto &el : vec)
|
||||
ml >> el;
|
||||
return ml;
|
||||
}
|
||||
|
||||
|
||||
// Put an std::pair
|
||||
|
||||
template<typename A, typename B>
|
||||
inline mlStream & operator << (mlStream &ml, const std::pair<A,B> &pair) {
|
||||
ml << mlHead("List", 2) << pair.first << pair.second;
|
||||
return ml;
|
||||
}
|
||||
|
||||
#endif // MLSTREAM_H
|
5
LTemplate/Kernel/init.m
Normal file
5
LTemplate/Kernel/init.m
Normal file
@ -0,0 +1,5 @@
|
||||
(* ::Package:: *)
|
||||
|
||||
(* Mathematica Init File *)
|
||||
|
||||
Get["LTemplate`LTemplate`"]
|
21
LTemplate/LICENSE.txt
Normal file
21
LTemplate/LICENSE.txt
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019 Szabolcs Horvát <szhorvat@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
34
LTemplate/LTemplate.m
Normal file
34
LTemplate/LTemplate.m
Normal file
@ -0,0 +1,34 @@
|
||||
(* Mathematica Package *)
|
||||
(* Created by IntelliJ IDEA and http://wlplugin.halirutan.de/ *)
|
||||
|
||||
(* :Title: LTemplate *)
|
||||
(* :Context: LTemplate` *)
|
||||
(* :Author: szhorvat *)
|
||||
(* :Date: 2015-08-03 *)
|
||||
|
||||
(* :Package Version: 0.6 *)
|
||||
(* :Mathematica Version: 10.0 *)
|
||||
(* :Copyright: (c) 2019 Szabolcs Horvat *)
|
||||
(* :License: MIT license, see LICENSE.txt *)
|
||||
(* :Keywords: LibraryLink, C++, Template, Code generation *)
|
||||
(* :Discussion: This package simplifies writing LibraryLink code by auto-generating the boilerplate code. *)
|
||||
|
||||
BeginPackage["LTemplate`", {"SymbolicC`", "CCompilerDriver`"}]
|
||||
|
||||
Unprotect["LTemplate`*"];
|
||||
|
||||
`Private`$private = False;
|
||||
Get["LTemplate`LTemplateInner`"]
|
||||
|
||||
ConfigureLTemplate[] (* use the default configuration *)
|
||||
|
||||
EndPackage[]
|
||||
|
||||
(* Note: Take care not to introduce any new symbols in this section as they would be created in Global` *)
|
||||
|
||||
SetAttributes[Evaluate@Names["LTemplate`*"], {Protected, ReadProtected}];
|
||||
|
||||
(* Add the class context to $ContextPath *)
|
||||
If[Not@MemberQ[$ContextPath, LClassContext[]],
|
||||
PrependTo[$ContextPath, LClassContext[]]
|
||||
];
|
45
LTemplate/LTemplate.qbs
Normal file
45
LTemplate/LTemplate.qbs
Normal file
@ -0,0 +1,45 @@
|
||||
// This is a QBS project file to be used with the Qt Creator IDE
|
||||
|
||||
import qbs
|
||||
|
||||
Product {
|
||||
Depends { name: "cpp" }
|
||||
|
||||
// Set the path to Mathematica's $InstallationDirectory here:
|
||||
property string mmaInstallDir: "/Applications/Mathematica 12.0.app/Contents/"
|
||||
|
||||
cpp.cxxLanguageVersion: "c++11"
|
||||
|
||||
cpp.includePaths: base.concat([
|
||||
mmaInstallDir + "SystemFiles/IncludeFiles/C/",
|
||||
mmaInstallDir + "SystemFiles/Links/MathLink/DeveloperKit/MacOSX-x86-64/CompilerAdditions",
|
||||
"IncludeFiles/",
|
||||
|
||||
// The following are the locations of various libraries used by the example code,
|
||||
// such as boost, CGAL, etc.
|
||||
|
||||
"/opt/local/include",
|
||||
])
|
||||
|
||||
cpp.defines: base.concat([
|
||||
'LTEMPLATE_MESSAGE_SYMBOL="LTemplate`LTemplate"',
|
||||
"LTEMPLATE_MMA_VERSION=1200",
|
||||
])
|
||||
|
||||
FileTagger {
|
||||
patterns: "*.inc"
|
||||
fileTags: ["cpp"]
|
||||
}
|
||||
|
||||
files: [
|
||||
"IncludeFiles/*.h",
|
||||
"IncludeFiles/*.inc",
|
||||
]
|
||||
|
||||
Group {
|
||||
name: "Examples"
|
||||
prefix: "Documentation/Examples/"
|
||||
|
||||
files: ["*/*.h", "*/*.cpp"]
|
||||
}
|
||||
}
|
874
LTemplate/LTemplateInner.m
Normal file
874
LTemplate/LTemplateInner.m
Normal file
@ -0,0 +1,874 @@
|
||||
(* Mathematica Package *)
|
||||
|
||||
(* :Copyright: (c) 2019 Szabolcs Horvat *)
|
||||
(* :License: MIT license, see LICENSE.txt *)
|
||||
|
||||
(* This file is read directly with Get in LTemplate.m or LTemplatePrivate.m *)
|
||||
|
||||
|
||||
LTemplate::usage = "LTemplate[name, {LClass[\[Ellipsis]], LClass[\[Ellipsis]], \[Ellipsis]}] represents a library template.";
|
||||
LClass::usage = "LClass[name, {fun1, fun2, \[Ellipsis]}] represents a class within a template.";
|
||||
LFun::usage =
|
||||
"LFun[name, {arg1, arg2, \[Ellipsis]}, ret] represents a class member function with the given name, argument types and return type.\n" <>
|
||||
"LFun[name, LinkObject, LinkObject] represents a function that uses MathLink/WSTP based passing. The shorthand LFun[name, LinkObject] can also be used.";
|
||||
|
||||
LType::usage =
|
||||
"LType[head] represents an array-like library type corresponding to head.\n" <>
|
||||
"LType[head, etype] represents an array-like library type corresponding to head, with element type etype.\n" <>
|
||||
"LType[head, etype, d] represents an array-like library type corresponding to head, with element type etype and depth/rank d.";
|
||||
|
||||
TranslateTemplate::usage = "TranslateTemplate[template] translates the template into C++ code.";
|
||||
|
||||
LoadTemplate::usage = "LoadTemplate[template] loads the library defined by the template. The library must already be compiled.";
|
||||
UnloadTemplate::usage = "UnloadTemplate[template] attempts to unload the library defined by the template.";
|
||||
|
||||
CompileTemplate::usage =
|
||||
"CompileTemplate[template] compiles the library defined by the template. Required source files must be present in the current directory.\n" <>
|
||||
"CompileTemplate[template, {file1, \[Ellipsis]}] includes additional source files in the compilation.";
|
||||
|
||||
FormatTemplate::usage = "FormatTemplate[template] formats the template in an easy to read way.";
|
||||
|
||||
NormalizeTemplate::usage = "NormalizeTemplate[template] brings the template and the type specifications within to the canonical form used internally by other LTemplate functions.";
|
||||
|
||||
ValidTemplateQ::usage = "ValidTemplateQ[template] returns True if the template syntax is valid.";
|
||||
|
||||
Make::usage = "Make[class] creates an instance of class.";
|
||||
|
||||
LExpressionList::usage = "LExpressionList[class] returns all existing instances of class.";
|
||||
|
||||
LClassContext::usage = "LClassContext[] returns the context where class symbols are created.";
|
||||
|
||||
LExpressionID::usage = "LExpressionID[name] represents the data type corresponding to LClass[name, \[Ellipsis]] in templates.";
|
||||
|
||||
ConfigureLTemplate::usage = "ConfigureLTemplate[options] must be called after loading the LTemplate package privately.";
|
||||
|
||||
Begin["`Private`"] (* Begin Private Context *)
|
||||
|
||||
(* Private for now, use LFun[name, LinkObject, LinkObject] instead. *)
|
||||
LOFun::usage =
|
||||
"LOFun[name] represents a class member function that uses LinkObject for passing and returning arguments. " <>
|
||||
"It is equivalent to LFun[name, LinkObject, LinkObject].";
|
||||
|
||||
(* Mathematica version checks *)
|
||||
|
||||
packageAbort[] := (End[]; EndPackage[]; Abort[]) (* Avoid polluting the context path when aborting early. *)
|
||||
|
||||
minVersion = {10.0, 0}; (* oldest supported Mathematica version *)
|
||||
maxVersion = {12.1, 1}; (* latest Mathematica version the package was tested with *)
|
||||
version = {$VersionNumber, $ReleaseNumber}
|
||||
versionString[{major_, release_}] := StringJoin[ToString /@ {NumberForm[major, {Infinity, 1}], ".", release}]
|
||||
|
||||
If[Not@OrderedQ[{minVersion, version}],
|
||||
Print["LTemplate requires at least Mathematica version " <> versionString[minVersion] <> ". Aborting."];
|
||||
packageAbort[];
|
||||
]
|
||||
|
||||
(* We need to rely on implementation details of SymbolicC, so warn users of yet untested new Mathematica versions. *)
|
||||
If[Not@OrderedQ[{version, maxVersion}] && Not[$private],
|
||||
Print[
|
||||
StringTemplate[
|
||||
"WARNING: LTemplate has not yet been tested with Mathematica ``.\n" <>
|
||||
"The latest supported Mathematica version is ``.\n" <>
|
||||
"Please report any issues you find to szhorvat at gmail.com."
|
||||
][versionString[version], versionString[maxVersion]]
|
||||
]
|
||||
]
|
||||
|
||||
(*************** Package configuration ****************)
|
||||
|
||||
(* Set up package global variables *)
|
||||
|
||||
$packageDirectory = DirectoryName[$InputFileName];
|
||||
$includeDirectory = FileNameJoin[{$packageDirectory, "IncludeFiles"}];
|
||||
|
||||
(* The following symbols are set by ConfigureLTemplate[] *)
|
||||
$messageSymbol := warnConfig
|
||||
$lazyLoading := warnConfig
|
||||
|
||||
(* Show error and abort when ConfigureLTemplate[] was not called. *)
|
||||
warnConfig := (Print["FATAL ERROR: Must call ConfigureLTemplate[] when embedding LTemplate into another package. Aborting ..."]; Abort[])
|
||||
|
||||
ByteArray[{0}]; (* "Prime" ByteArray to work around 10.4 bug where returning ByteArrays works only after they have been used once *)
|
||||
|
||||
LibraryFunction::noinst = "Managed library expression instance does not exist.";
|
||||
|
||||
LTemplate::nofun = "Function `` does not exist.";
|
||||
|
||||
|
||||
Options[ConfigureLTemplate] = { "MessageSymbol" -> LTemplate, "LazyLoading" -> False };
|
||||
|
||||
ConfigureLTemplate[opt : OptionsPattern[]] :=
|
||||
With[{sym = OptionValue["MessageSymbol"]},
|
||||
$messageSymbol = sym;
|
||||
sym::info = "``";
|
||||
sym::warning = "``";
|
||||
sym::error = "``";
|
||||
sym::assert = "Assertion failed: ``.";
|
||||
|
||||
$lazyLoading = OptionValue["LazyLoading"];
|
||||
]
|
||||
|
||||
LClassContext[] = Context[LTemplate] <> "Classes`";
|
||||
|
||||
|
||||
(***************** SymbolicC extensions *******************)
|
||||
|
||||
CDeclareAssign::usage = "CDeclareAssign[type, var, value] represents 'type var = value;'.";
|
||||
SymbolicC`Private`IsCExpression[ _CDeclareAssign ] := True
|
||||
GenerateCode[CDeclareAssign[typeArg_, idArg_, rhs_], opts : OptionsPattern[]] :=
|
||||
Module[{type, id},
|
||||
type = Flatten[{typeArg}];
|
||||
id = Flatten[{idArg}];
|
||||
type = Riffle[ Map[ GenerateCode[#, opts] &, type], " "];
|
||||
id = Riffle[ Map[ GenerateCode[#, opts] &, id], ", "];
|
||||
GenerateCode[CAssign[type <> " " <> id, rhs], opts]
|
||||
]
|
||||
|
||||
CInlineCode::usage = "CInlineCode[\"some code\"] will prevent semicolons from being added at the end of \"some code\" when used in a list.";
|
||||
GenerateCode[CInlineCode[arg_], opts : OptionsPattern[]] := GenerateCode[arg, opts]
|
||||
|
||||
CTryCatch::usage = "CTryCatch[tryCode, catchArg, catchCode] represents 'try { tryCode } catch (catchArg) { catchCode }'.";
|
||||
GenerateCode[CTryCatch[try_, arg_, catch_], opts : OptionsPattern[]] :=
|
||||
GenerateCode[CTry[try], opts] <> "\n" <> GenerateCode[CCatch[arg, catch], opts]
|
||||
|
||||
CTry::usage = "CTry[tryCode] represents the fragment 'try { tryCode }'. Use CTryCatch instead.";
|
||||
GenerateCode[CTry[try_], opts : OptionsPattern[]] :=
|
||||
"try\n" <> GenerateCode[CBlock[try], opts]
|
||||
|
||||
CCatch::usage = "CCatch[catchArg, catchCode] represents the fragment 'catch (catchArg) { catchCode }'. Use CTryCatch instead.";
|
||||
GenerateCode[CCatch[arg_, catch_], opts : OptionsPattern[]] :=
|
||||
"catch (" <> SymbolicC`Private`formatArgument[arg, opts] <> ")\n" <>
|
||||
GenerateCode[CBlock[catch], opts]
|
||||
|
||||
(****************** Generic template processing ****************)
|
||||
|
||||
numericTypePattern = Integer|Real|Complex;
|
||||
rawTypePattern = "Integer8"|"UnsignedInteger8"|"Integer16"|"UnsignedInteger16"|"Integer32"|"UnsignedInteger32"|
|
||||
"Integer64"|"UnsignedInteger64"|"Real32"|"Real64"|"Complex64"|"Complex128";
|
||||
imageTypePattern = "Bit"|"Byte"|"Bit16"|"Real32"|"Real";
|
||||
|
||||
passingMethodPattern = PatternSequence[]|"Shared"|"Manual"|"Constant"|Automatic;
|
||||
|
||||
depthPattern = _Integer?Positive | Verbatim[_];
|
||||
depthNullPattern = PatternSequence[] | depthPattern; (* like depthPattern, but allow empty value*)
|
||||
|
||||
arrayPattern = LType[List, numericTypePattern, depthNullPattern]; (* disallow MTensor without explicit element type specification *)
|
||||
sparseArrayPattern = LType[SparseArray, numericTypePattern, depthNullPattern]; (* disallow SparseArray without explicit element type specification *)
|
||||
rawArrayPattern = LType[RawArray, rawTypePattern] | LType[RawArray];
|
||||
numericArrayPattern = LType[NumericArray, rawTypePattern] | LType[NumericArray]
|
||||
byteArrayPattern = LType[ByteArray];
|
||||
imagePattern = LType[Image|Image3D, imageTypePattern] | LType[Image|Image3D];
|
||||
|
||||
(*
|
||||
Normalizing a template will:
|
||||
- Wrap a bare LClass with LTemplate. This way a bare LClass can be used as a shorter notation for a single-class template.
|
||||
- Convert type names to a canonical form
|
||||
- Convert LFun[name, LinkObject, LinkObject] to LOFun[name]
|
||||
*)
|
||||
|
||||
normalizeTypesRules = Dispatch@{
|
||||
(* convert pattern-like type specifications to type names *)
|
||||
Verbatim[_Integer] -> Integer,
|
||||
Verbatim[_Real] -> Real,
|
||||
Verbatim[_Complex] -> Complex,
|
||||
Verbatim[True|False] -> "Boolean",
|
||||
Verbatim[False|True] -> "Boolean",
|
||||
|
||||
(* convert string heads to symbols *)
|
||||
(* must only be used on type lists as an LTemplate expression may contain other strings *)
|
||||
head : "List"|"SparseArray"|"Image"|"Image3D"|"RawArray"|"NumericArray"|"ByteArray" :> Symbol[head],
|
||||
|
||||
(* convert LibraryDataType to the more general LType *)
|
||||
LibraryDataType[args__] :> LType[args]
|
||||
};
|
||||
|
||||
(* These heads are allowed to appear on their own, without being wrapped in LType/LibraryDataType.
|
||||
This is for consistency with plain LibraryLink. *)
|
||||
nakedHeads = ByteArray|RawArray|NumericArray|Image|Image3D;
|
||||
wrapNakedHeadsRules = Dispatch@{
|
||||
expr : LType[___] :> expr, (* do not wrap if already wrapped *)
|
||||
type : nakedHeads :> LType[type]
|
||||
};
|
||||
|
||||
elemTypeAliases = Dispatch@{
|
||||
LType[h: RawArray|NumericArray, "Byte"] :> LType[h, "UnsignedInteger8"],
|
||||
LType[h: RawArray|NumericArray, "Bit16"] :> LType[h, "UnsignedInteger16"],
|
||||
(* omit "Integer" because the naming is confusing and people may assume it's "Integer64" *)
|
||||
(* LType[h: RawArray|NumericArray, "Integer"] :> LType[h, "Integer32"], *)
|
||||
LType[h: RawArray|NumericArray, "Float"] :> LType[h, "Real32"],
|
||||
LType[h: RawArray|NumericArray, "Double"] :> LType[h, "Real64"],
|
||||
LType[h: RawArray|NumericArray, "Real"] :> LType[h, "Real64"],
|
||||
LType[h: RawArray|NumericArray, "Complex"] :> LType[h, "Complex128"],
|
||||
|
||||
LType[h : Image|Image3D, "UnsignedInteger8"] :> LType[h, "Byte"],
|
||||
LType[h : Image|Image3D, "UnsignedInteger16"] :> LType[h, "Bit16"],
|
||||
LType[h : Image|Image3D, "Float"] :> LType[h, "Real32"],
|
||||
LType[h : Image|Image3D, "Double"] :> LType[h, "Real"],
|
||||
LType[h : Image|Image3D, "Real64"] :> LType[h, "Real"]
|
||||
};
|
||||
|
||||
normalizeFunsRules = Dispatch@{
|
||||
LFun[name_, LinkObject] :> LOFun[name],
|
||||
LFun[name_, LinkObject, LinkObject] :> LOFun[name],
|
||||
LFun[name_, args_List, ret_] :> LFun[name, normalizeTypes[args, 1], normalizeTypes[ret]]
|
||||
};
|
||||
|
||||
(* These rules must only be applied to entire type specifications, not their parts. Use Replace, not ReplaceAll. *)
|
||||
typeRules = Dispatch@{
|
||||
(* allowed forms of tensor specifications include {type}, {type, depth}, {type, depth, passing}, but NOT {type, passing} *)
|
||||
{type : numericTypePattern, depth : depthPattern, pass : passingMethodPattern} :> {LType[List, type, depth], pass},
|
||||
{type : numericTypePattern, pass : passingMethodPattern} :> {LType[List, type], pass},
|
||||
type : LType[__] :> {type}
|
||||
};
|
||||
|
||||
normalizeTypes[types_, level_ : 0] := Replace[types /. normalizeTypesRules /. wrapNakedHeadsRules /. elemTypeAliases, typeRules, {level}]
|
||||
|
||||
NormalizeTemplate[c : LClass[name_, funs_]] := NormalizeTemplate[LTemplate[name, {c}]]
|
||||
NormalizeTemplate[t : LTemplate[name_, classes_]] := t /. normalizeFunsRules
|
||||
NormalizeTemplate[t_] := t
|
||||
|
||||
|
||||
ValidTemplateQ::template = "`` is not a valid template. Templates must follow the syntax LTemplate[name, {class1, class2, \[Ellipsis]}].";
|
||||
ValidTemplateQ::class = "In ``: `` is not a valid class. Classes must follow the syntax LClass[name, {fun1, fun2, \[Ellipsis]}].";
|
||||
ValidTemplateQ::fun = "In ``: `` is not a valid function. Functions must follow the syntax LFun[name, {arg1, arg2, \[Ellipsis]}, ret].";
|
||||
ValidTemplateQ::string = "In ``: String expected instead of ``";
|
||||
ValidTemplateQ::name = "In ``: `` is not a valid name. Names must start with a letter and may only contain letters and digits.";
|
||||
ValidTemplateQ::type = "In ``: `` is not a valid type.";
|
||||
ValidTemplateQ::rettype = "In ``: `` is not a valid return type.";
|
||||
ValidTemplateQ::dupclass = "In ``: Class `` appears more than once.";
|
||||
ValidTemplateQ::dupfun = "In ``: Function `` appears more than once.";
|
||||
|
||||
ValidTemplateQ[tem_] := validateTemplate@NormalizeTemplate[tem]
|
||||
|
||||
|
||||
validateTemplate[tem_] := (Message[ValidTemplateQ::template, tem]; False)
|
||||
validateTemplate[LTemplate[name_String, classes_List]] :=
|
||||
Block[{classlist = {}, location = "template"},
|
||||
validateName[name] && (And @@ validateClass /@ classes)
|
||||
]
|
||||
|
||||
(* must be called within validateTemplate, uses location, classlist *)
|
||||
validateClass[class_] := (Message[ValidTemplateQ::class, location, class]; False)
|
||||
validateClass[LClass[name_, funs_List]] :=
|
||||
Block[{funlist = {}, inclass, nameValid},
|
||||
nameValid = validateName[name];
|
||||
If[MemberQ[classlist, name], Message[ValidTemplateQ::dupclass, location, name]; Return[False]];
|
||||
AppendTo[classlist, name];
|
||||
inclass = name;
|
||||
Block[{location = StringTemplate["class ``"][inclass]},
|
||||
nameValid && (And @@ validateFun /@ funs)
|
||||
]
|
||||
]
|
||||
|
||||
(* must be called within validateClass, uses location, funlist *)
|
||||
validateFun[fun_] := (Message[ValidTemplateQ::fun, location, fun]; False)
|
||||
validateFun[LFun[name_, args_List, ret_]] :=
|
||||
Block[{nameValid},
|
||||
nameValid = validateName[name];
|
||||
If[MemberQ[funlist, name], Message[ValidTemplateQ::dupfun, location, name]; Return[False]];
|
||||
AppendTo[funlist, name];
|
||||
Block[{location = StringTemplate["class ``, function ``"][inclass, name]},
|
||||
nameValid && (And @@ validateType /@ args) && validateReturnType[ret]
|
||||
]
|
||||
]
|
||||
validateFun[LOFun[name_]] :=
|
||||
Block[{nameValid},
|
||||
nameValid = validateName[name];
|
||||
If[MemberQ[funlist, name], Message[ValidTemplateQ::dupfun, location, name]; Return[False]];
|
||||
AppendTo[funlist, name];
|
||||
nameValid
|
||||
]
|
||||
|
||||
(* must be called within validateTemplate, uses location *)
|
||||
validateType[numericTypePattern|"Boolean"|"UTF8String"|LExpressionID[_String]] := True
|
||||
validateType[{arrayPattern|sparseArrayPattern|rawArrayPattern|numericArrayPattern|byteArrayPattern|imagePattern, passingMethodPattern}] := True
|
||||
validateType[type_] := (Message[ValidTemplateQ::type, location, type]; False)
|
||||
|
||||
(* must be called within validateTemplate, uses location *)
|
||||
(* Only "Shared" and Automatic passing allowed in return types. LExpressionID is forbidden. *)
|
||||
validateReturnType["Void"] := True
|
||||
validateReturnType[type : LExpressionID[___] | {___, "Manual"|"Constant"}] := (Message[ValidTemplateQ::rettype, location, type]; False)
|
||||
validateReturnType[type_] := validateType[type]
|
||||
|
||||
(* must be called within validateTemplate, uses location *)
|
||||
validateName[name_] := (Message[ValidTemplateQ::string, location, name]; False)
|
||||
validateName[name_String] :=
|
||||
If[StringMatchQ[name, RegularExpression["[a-zA-Z][a-zA-Z0-9]*"]],
|
||||
True,
|
||||
Message[ValidTemplateQ::name, location, name]; False
|
||||
]
|
||||
|
||||
|
||||
|
||||
(*********** Translate template to library code **********)
|
||||
|
||||
TranslateTemplate[tem_] :=
|
||||
With[{t = NormalizeTemplate[tem]},
|
||||
If[validateTemplate[t],
|
||||
ToCCodeString[transTemplate[t], "Indent" -> 1],
|
||||
$Failed
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
libFunArgs = {{"WolframLibraryData", "libData"}, {"mint", "Argc"}, {"MArgument *", "Args"}, {"MArgument", "Res"}};
|
||||
linkFunArgs = {{"WolframLibraryData", "libData"}, {"MLINK", "mlp"}};
|
||||
libFunRet = "extern \"C\" DLLEXPORT int";
|
||||
|
||||
excType = "const mma::LibraryError &";
|
||||
excName = "libErr";
|
||||
|
||||
varPrefix = "var";
|
||||
var[k_] := varPrefix <> IntegerString[k]
|
||||
|
||||
includeName[classname_String] := classname <> ".h"
|
||||
|
||||
collectionName[classname_String] := classname <> "_collection"
|
||||
|
||||
collectionType[classname_String] := "std::map<mint, " <> classname <> " *>"
|
||||
|
||||
managerName[classname_String] := classname <> "_manager_fun"
|
||||
|
||||
fullyQualifiedSymbolName[sym_Symbol] := Context[sym] <> SymbolName[sym]
|
||||
|
||||
|
||||
setupCollection[classname_String] := {
|
||||
CDeclare[collectionType[classname], collectionName[classname]],
|
||||
"",
|
||||
CInlineCode["namespace mma"], (* workaround for gcc bug, "specialization of template in different namespace" *)
|
||||
CBlock@CFunction["template<> const " <> collectionType[classname] <> " &", "getCollection<" <> classname <> ">", {},
|
||||
CReturn[collectionName[classname]]
|
||||
],
|
||||
"",
|
||||
CFunction["DLLEXPORT void", managerName[classname], {"WolframLibraryData libData", "mbool mode", "mint id"},
|
||||
CInlineCode@StringTemplate[ (* TODO: Check if id exists, use assert *)
|
||||
"\
|
||||
if (mode == 0) { // create
|
||||
`collection`[id] = new `class`();
|
||||
} else { // destroy
|
||||
if (`collection`.find(id) == `collection`.end()) {
|
||||
libData->Message(\"noinst\");
|
||||
return;
|
||||
}
|
||||
delete `collection`[id];
|
||||
`collection`.erase(id);
|
||||
}\
|
||||
"][<|"collection" -> collectionName[classname], "class" -> classname|>]
|
||||
],
|
||||
"",
|
||||
CFunction[libFunRet, classname <> "_get_collection", libFunArgs,
|
||||
{
|
||||
(* Attention: make sure stuff called here won't throw LibraryError *)
|
||||
transRet[
|
||||
{LType[List, Integer, 1]},
|
||||
CCall["mma::detail::get_collection", collectionName[classname]]
|
||||
],
|
||||
CReturn["LIBRARY_NO_ERROR"]
|
||||
}
|
||||
],
|
||||
"",""
|
||||
}
|
||||
|
||||
|
||||
registerClassManager[classname_String] :=
|
||||
CBlock[{
|
||||
"int err",
|
||||
StringTemplate[
|
||||
"err = (*libData->registerLibraryExpressionManager)(\"`class`\", `manager`)"
|
||||
][<|"class" -> classname, "manager" -> managerName[classname]|>],
|
||||
"if (err != LIBRARY_NO_ERROR) return err"
|
||||
}]
|
||||
|
||||
|
||||
unregisterClassManager[classname_String] :=
|
||||
StringTemplate["(*libData->unregisterLibraryExpressionManager)(\"``\")"][classname]
|
||||
|
||||
|
||||
transTemplate[LTemplate[libname_String, classes_]] :=
|
||||
Block[{classlist = {}, classTranslations},
|
||||
classTranslations = transClass /@ classes;
|
||||
{
|
||||
CComment["This file was automatically generated by LTemplate. DO NOT EDIT.", {"", "\n"}],
|
||||
CComment["https://github.com/szhorvat/LTemplate", {"", "\n"}],
|
||||
"",
|
||||
CDefine["LTEMPLATE_MMA_VERSION", ToString@Round[100 $VersionNumber + $ReleaseNumber]],
|
||||
"",
|
||||
CInclude["LTemplate.h"],
|
||||
CInclude["LTemplateHelpers.h"],
|
||||
CInclude /@ includeName /@ classlist,
|
||||
"","",
|
||||
|
||||
CDefine["LTEMPLATE_MESSAGE_SYMBOL", CString[fullyQualifiedSymbolName[$messageSymbol]]],
|
||||
"",
|
||||
CInclude["LTemplate.inc"],
|
||||
|
||||
"","",
|
||||
|
||||
setupCollection /@ classlist,
|
||||
|
||||
CFunction["extern \"C\" DLLEXPORT mint",
|
||||
"WolframLibrary_getVersion", {},
|
||||
"return WolframLibraryVersion"
|
||||
],
|
||||
"",
|
||||
CFunction["extern \"C\" DLLEXPORT int",
|
||||
"WolframLibrary_initialize", {"WolframLibraryData libData"},
|
||||
{
|
||||
CAssign["mma::libData", "libData"],
|
||||
registerClassManager /@ classlist,
|
||||
"return LIBRARY_NO_ERROR"
|
||||
}
|
||||
],
|
||||
"",
|
||||
CFunction["extern \"C\" DLLEXPORT void",
|
||||
"WolframLibrary_uninitialize", {"WolframLibraryData libData"},
|
||||
{
|
||||
unregisterClassManager /@ classlist,
|
||||
"return"
|
||||
}
|
||||
],
|
||||
"","",
|
||||
classTranslations
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
(* must be called within transTemplate *)
|
||||
transClass[LClass[classname_String, funs_]] :=
|
||||
Block[{},
|
||||
AppendTo[classlist, classname];
|
||||
transFun[classname] /@ funs
|
||||
]
|
||||
|
||||
|
||||
funName[classname_][name_] := classname <> "_" <> name
|
||||
|
||||
|
||||
catchExceptions[classname_, funname_] :=
|
||||
Module[{membername = "\"" <> classname <> "::" <> funname <> "()\""},
|
||||
{
|
||||
CCatch[{excType, excName},
|
||||
{
|
||||
CMember[excName, "report()"],
|
||||
CReturn[CMember[excName, "error_code()"]]
|
||||
}
|
||||
]
|
||||
,
|
||||
CCatch[
|
||||
{"const std::exception &", "exc"},
|
||||
{
|
||||
CCall["mma::detail::handleUnknownException", {"exc.what()", membername}],
|
||||
CReturn["LIBRARY_FUNCTION_ERROR"]
|
||||
}
|
||||
]
|
||||
,
|
||||
CCatch["...",
|
||||
{
|
||||
CCall["mma::detail::handleUnknownException", {"NULL", membername}],
|
||||
CReturn["LIBRARY_FUNCTION_ERROR"]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
transFun[classname_][LFun[name_String, args_List, ret_]] :=
|
||||
Block[{index = 0},
|
||||
{
|
||||
CFunction[libFunRet, funName[classname][name], libFunArgs,
|
||||
{
|
||||
CDeclare["mma::detail::MOutFlushGuard", "flushguard"],
|
||||
(* TODO: check Argc is correct, use assert *)
|
||||
"const mint id = MArgument_getInteger(Args[0])",
|
||||
CInlineCode@StringTemplate[
|
||||
"if (`1`.find(id) == `1`.end()) { libData->Message(\"noinst\"); return LIBRARY_FUNCTION_ERROR; }"
|
||||
][collectionName[classname]],
|
||||
"",
|
||||
CTry[
|
||||
(* try *) {
|
||||
transArg /@ args,
|
||||
"",
|
||||
transRet[
|
||||
ret,
|
||||
CPointerMember[CArray[collectionName[classname], "id"], CCall[name, var /@ Range@Length[args]]]
|
||||
]
|
||||
}],
|
||||
(* catch *)
|
||||
catchExceptions[classname, name],
|
||||
"",
|
||||
CReturn["LIBRARY_NO_ERROR"]
|
||||
}
|
||||
],
|
||||
"", ""
|
||||
}
|
||||
]
|
||||
|
||||
transFun[classname_][LOFun[name_String]] :=
|
||||
{
|
||||
CFunction[libFunRet, funName[classname][name], linkFunArgs,
|
||||
{
|
||||
CDeclare["mma::detail::MOutFlushGuard", "flushguard"],
|
||||
CTry[
|
||||
(* try *) {
|
||||
CInlineCode@StringTemplate[
|
||||
"
|
||||
int id;
|
||||
int args = 2;
|
||||
|
||||
if (! MLTestHeadWithArgCount(mlp, \"List\", &args))
|
||||
return LIBRARY_FUNCTION_ERROR;
|
||||
if (! MLGetInteger(mlp, &id))
|
||||
return LIBRARY_FUNCTION_ERROR;
|
||||
if (`collection`.find(id) == `collection`.end()) {
|
||||
libData->Message(\"noinst\");
|
||||
return LIBRARY_FUNCTION_ERROR;
|
||||
}
|
||||
`collection`[id]->`funname`(mlp);
|
||||
"
|
||||
][<| "collection" -> collectionName[classname], "funname" -> name |>]
|
||||
}
|
||||
],
|
||||
(* catch *)
|
||||
catchExceptions[classname, name],
|
||||
"",
|
||||
CReturn["LIBRARY_NO_ERROR"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
transArg[type_] :=
|
||||
Module[{name, cpptype, getfun, setfun},
|
||||
index++;
|
||||
name = var[index];
|
||||
{cpptype, getfun, setfun} = Replace[type, types];
|
||||
{
|
||||
CDeclareAssign[cpptype, name, StringTemplate["`1`(Args[`2`])"][getfun, index]]
|
||||
}
|
||||
]
|
||||
|
||||
transRet[type_, value_] :=
|
||||
Module[{name = "res", cpptype, getfun, setfun},
|
||||
{cpptype, getfun, setfun} = Replace[type, types];
|
||||
{
|
||||
CDeclareAssign[cpptype, name, value],
|
||||
CCall[setfun, {"Res", name}]
|
||||
}
|
||||
]
|
||||
|
||||
transRet["Void", value_] := value
|
||||
|
||||
|
||||
numericTypes = <|
|
||||
Integer -> "mint",
|
||||
Real -> "double",
|
||||
Complex -> "mma::complex_t"
|
||||
|>;
|
||||
|
||||
rawTypes = <|
|
||||
"Integer8" -> "int8_t",
|
||||
"UnsignedInteger8" -> "uint8_t",
|
||||
"Integer16" -> "int16_t",
|
||||
"UnsignedInteger16" -> "uint16_t",
|
||||
"Integer32" -> "int32_t",
|
||||
"UnsignedInteger32" -> "uint32_t",
|
||||
"Integer64" -> "int64_t",
|
||||
"UnsignedInteger64" -> "uint64_t",
|
||||
"Real32" -> "float",
|
||||
"Real64" -> "double",
|
||||
"Complex32" -> "mma::complex_float_t",
|
||||
"Complex64" -> "mma::complex_double_t"
|
||||
|>;
|
||||
|
||||
imageTypes = <|
|
||||
"Bit" -> "mma::im_bit_t",
|
||||
"Byte" -> "mma::im_byte_t",
|
||||
"Bit16" -> "mma::im_bit16_t",
|
||||
"Real32" -> "mma::im_real32_t",
|
||||
"Real" -> "mma::im_real_t"
|
||||
|>;
|
||||
|
||||
|
||||
types = Dispatch@{
|
||||
Integer -> {"mint", "MArgument_getInteger", "MArgument_setInteger"},
|
||||
Real -> {"double", "MArgument_getReal", "MArgument_setReal"},
|
||||
Complex -> {"std::complex<double>", "mma::detail::getComplex", "mma::detail::setComplex"},
|
||||
"Boolean" -> {"bool", "MArgument_getBoolean", "MArgument_setBoolean"},
|
||||
"UTF8String" -> {"const char *", "mma::detail::getString", "mma::detail::setString"},
|
||||
|
||||
{LType[List, type_, ___], ___} :>
|
||||
With[{ctype = numericTypes[type]},
|
||||
{"mma::TensorRef<" <> ctype <> ">", "mma::detail::getTensor<" <> ctype <> ">", "mma::detail::setTensor<" <> ctype <> ">"}
|
||||
],
|
||||
|
||||
{LType[SparseArray, type_, ___], ___} :>
|
||||
With[{ctype = numericTypes[type]},
|
||||
{"mma::SparseArrayRef<" <> ctype <> ">", "mma::detail::getSparseArray<" <> ctype <> ">", "mma::detail::setSparseArray<" <> ctype <> ">"}
|
||||
],
|
||||
|
||||
{LType[RawArray, type_], ___} :>
|
||||
With[
|
||||
{ctype = rawTypes[type]},
|
||||
{"mma::RawArrayRef<" <> ctype <> ">", "mma::detail::getRawArray<" <> ctype <> ">", "mma::detail::setRawArray<" <> ctype <> ">"}
|
||||
],
|
||||
|
||||
{LType[RawArray], ___} -> {"mma::GenericRawArrayRef", "mma::detail::getGenericRawArray", "mma::detail::setGenericRawArray"},
|
||||
|
||||
{LType[NumericArray, type_], ___} :>
|
||||
With[
|
||||
{ctype = rawTypes[type]},
|
||||
{"mma::NumericArrayRef<" <> ctype <> ">", "mma::detail::getNumericArray<" <> ctype <> ">", "mma::detail::setNumericArray<" <> ctype <> ">"}
|
||||
],
|
||||
|
||||
{LType[NumericArray], ___} -> {"mma::GenericNumericArrayRef", "mma::detail::getGenericNumericArray", "mma::detail::setGenericNumericArray"},
|
||||
|
||||
(* Starting with LTemplate 0.6, ByteArray is mapped to NumericArrayRef instead of RawArrayRef *)
|
||||
(* {LType[ByteArray], ___} -> {"mma::RawArrayRef<uint8_t>", "mma::detail::getRawArray<uint8_t>", "mma::detail::setRawArray<uint8_t>"}, *)
|
||||
{LType[ByteArray], ___} -> {"mma::NumericArrayRef<uint8_t>", "mma::detail::getNumericArray<uint8_t>", "mma::detail::setNumericArray<uint8_t>"},
|
||||
|
||||
{LType[Image, type_], ___} :>
|
||||
With[
|
||||
{ctype = imageTypes[type]},
|
||||
{"mma::ImageRef<" <> ctype <> ">", "mma::detail::getImage<" <> ctype <> ">", "mma::detail::setImage<" <> ctype <> ">"}
|
||||
],
|
||||
|
||||
{LType[Image], ___} -> {"mma::GenericImageRef", "mma::detail::getGenericImage", "mma::detail::setGenericImage"},
|
||||
|
||||
{LType[Image3D, type_], ___} :>
|
||||
With[
|
||||
{ctype = imageTypes[type]},
|
||||
{"mma::Image3DRef<" <> ctype <> ">", "mma::detail::getImage3D<" <> ctype <> ">", "mma::detail::setImage3D<" <> ctype <> ">"}
|
||||
],
|
||||
|
||||
{LType[Image3D], ___} -> {"mma::GenericImage3DRef", "mma::detail::getGenericImage3D", "mma::detail::setGenericImage3D"},
|
||||
|
||||
(* This is a special type that translates integer managed expression IDs on the Mathematica side
|
||||
into a class reference on the C++ side. It cannot be returned. *)
|
||||
LExpressionID[classname_String] :> {classname <> " &", "mma::detail::getObject<" <> classname <> ">(" <> collectionName[classname] <> ")", ""}
|
||||
};
|
||||
|
||||
|
||||
|
||||
(**************** Load library ***************)
|
||||
|
||||
(* TODO: Break out loading and compilation into separate files
|
||||
This is to make it easy to include them in other projects *)
|
||||
|
||||
getCollection (* underlies LExpressionList, the get_collection library function is associated with it in loadClass *)
|
||||
|
||||
symName[classname_String] := LClassContext[] <> classname
|
||||
|
||||
|
||||
LoadTemplate[tem_] :=
|
||||
With[{t = NormalizeTemplate[tem]},
|
||||
If[validateTemplate[t],
|
||||
Check[loadTemplate[t], $Failed],
|
||||
$Failed
|
||||
]
|
||||
]
|
||||
|
||||
(* We use FindLibrary for two reasons:
|
||||
1. If the library is not found, we want to fail early with LibraryFunction::notfound
|
||||
2. It is important to pass the full library path to LibraryFunctionLoad[]. If only a simple name is passed,
|
||||
it will use FindLibrary[] to find the appropriate file. FindLibrary[] is several orders of magnitude slower than just
|
||||
loading a function from a shared library. In fact, with this optimization, lazy loading might be pointless, as with
|
||||
full library paths, LibraryFunctionLoad[] is faster than other operations done during template loading.
|
||||
*)
|
||||
loadTemplate[tem : LTemplate[libname_String, classes_]] :=
|
||||
With[{lib = FindLibrary[libname]},
|
||||
Quiet@unloadTemplate[tem];
|
||||
If[lib =!= $Failed,
|
||||
loadClass[lib] /@ classes,
|
||||
Message[LibraryFunction::notfound, libname]
|
||||
];
|
||||
]
|
||||
|
||||
loadClass[libname_][tem : LClass[classname_String, funs_]] := (
|
||||
ClearAll[#]& @ symName[classname];
|
||||
loadFun[libname, classname] /@ funs;
|
||||
With[{sym = Symbol@symName[classname]},
|
||||
MessageName[sym, "usage"] = formatTemplate[tem];
|
||||
sym[id_Integer][(f_String)[___]] /; (Message[LTemplate::nofun, StringTemplate["``::``"][sym, f]]; False) := $Failed;
|
||||
getCollection[sym] = LibraryFunctionLoad[libname, funName[classname]["get_collection"], {}, LibraryDataType[List, Integer, 1]];
|
||||
];
|
||||
)
|
||||
|
||||
|
||||
loadFun[libname_, classname_][LFun[name_String, args_List, ret_]] :=
|
||||
With[{classsym = Symbol@symName[classname], funname = funName[classname][name],
|
||||
loadargs = Prepend[Replace[args, loadingTypes, {1}], Integer],
|
||||
loadret = Replace[ret, loadingTypes]
|
||||
},
|
||||
If[$lazyLoading,
|
||||
classsym[idx_Integer]@name[argumentsx___] :=
|
||||
With[{lfun = LibraryFunctionLoad[libname, funname, loadargs, loadret]},
|
||||
classsym[id_Integer]@name[arguments___] := lfun[id, arguments];
|
||||
classsym[idx]@name[argumentsx]
|
||||
]
|
||||
,
|
||||
With[{lfun = LibraryFunctionLoad[libname, funname, loadargs, loadret]},
|
||||
classsym[id_Integer]@name[arguments___] := lfun[id, arguments];
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
loadFun[libname_, classname_][LOFun[name_String]] :=
|
||||
With[{classsym = Symbol@symName[classname], funname = funName[classname][name]},
|
||||
If[$lazyLoading,
|
||||
classsym[idx_Integer]@name[argumentsx___] :=
|
||||
With[{lfun = LibraryFunctionLoad[libname, funname, LinkObject, LinkObject]},
|
||||
classsym[id_Integer]@name[arguments___] := lfun[id, {arguments}];
|
||||
classsym[idx]@name[argumentsx]
|
||||
]
|
||||
,
|
||||
With[{lfun = LibraryFunctionLoad[libname, funname, LinkObject, LinkObject]},
|
||||
classsym[id_Integer]@name[arguments___] := lfun[id, {arguments}];
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
(* For types that need to be translated to LibraryFunctionLoad compatible forms before loading. *)
|
||||
loadingTypes = Dispatch@{
|
||||
LExpressionID[_] -> Integer,
|
||||
{LType[h: RawArray|NumericArray, ___], passing___} :> {h, passing},
|
||||
{LType[args__], passing___} :> {LibraryDataType[args], passing}
|
||||
};
|
||||
|
||||
|
||||
UnloadTemplate[tem_] :=
|
||||
With[{t = NormalizeTemplate[tem]},
|
||||
If[validateTemplate[t],
|
||||
unloadTemplate[t],
|
||||
$Failed
|
||||
]
|
||||
]
|
||||
|
||||
unloadTemplate[LTemplate[libname_String, classes_]] :=
|
||||
Module[{res},
|
||||
res = LibraryUnload[libname];
|
||||
With[{syms = Symbol /@ symName /@ Cases[classes, LClass[name_, __] :> name]},
|
||||
ClearAll /@ syms;
|
||||
Quiet@Unset[getCollection[#]]& /@ syms;
|
||||
];
|
||||
res
|
||||
]
|
||||
|
||||
|
||||
(* TODO: verify class exists for Make and LExpressionList *)
|
||||
|
||||
Make[class_Symbol] := Make@SymbolName[class] (* SymbolName returns the name of the symbol without a context *)
|
||||
Make[classname_String] := CreateManagedLibraryExpression[classname, Symbol@symName[classname]]
|
||||
|
||||
|
||||
LExpressionList[class_Symbol] := class /@ getCollection[class][]
|
||||
LExpressionList[classname_String] := LExpressionList@Symbol@symName[classname]
|
||||
|
||||
|
||||
(********************* Compile template ********************)
|
||||
|
||||
CompileTemplate::comp = "The compiler specification `` is invalid. It must be a symbol.";
|
||||
|
||||
If[TrueQ[$noCompile],
|
||||
|
||||
(* If CCompilerDriver has not been loaded: *)
|
||||
CompileTemplate::disabled = "Template compilation is disabled.";
|
||||
CompileTemplate[___] := (Message[CompileTemplate::disabled]; $Failed);
|
||||
,
|
||||
|
||||
(* If CCompilerDriver is available: *)
|
||||
CompileTemplate[tem_, sources_List, opt : OptionsPattern[CreateLibrary]] :=
|
||||
With[{t = NormalizeTemplate[tem]},
|
||||
If[validateTemplate[t],
|
||||
compileTemplate[t, sources, opt],
|
||||
$Failed
|
||||
]
|
||||
];
|
||||
CompileTemplate[tem_, opt : OptionsPattern[CreateLibrary]] := CompileTemplate[tem, {}, opt];
|
||||
]
|
||||
|
||||
compileTemplate[tem: LTemplate[libname_String, classes_], sources_, opt : OptionsPattern[CreateLibrary]] :=
|
||||
Catch[
|
||||
Module[{sourcefile, code, includeDirs, classlist, print, driver},
|
||||
print[args__] := Apply[Print, Style[#, Darker@Blue]& /@ {args}];
|
||||
|
||||
(* Determine the compiler driver that will be used. *)
|
||||
(* It is unclear if the "Compiler" option of CreateLibrary supports option lists as a compiler specification
|
||||
like $CCompiler does. Trying to use one frequently leads to errors as of M11.2. This may or may not be a bug.
|
||||
For now we forbid anything but symbol compiler specifications, such as CCompilerDriver`ClangCompiler`ClangCompiler *)
|
||||
driver = OptionValue["Compiler"];
|
||||
If[driver === Automatic, driver = DefaultCCompiler[]];
|
||||
If[driver === $Failed, Throw[$Failed, compileTemplate]];
|
||||
If[Not@MatchQ[driver, _Symbol],
|
||||
Message[CompileTemplate::comp, driver];
|
||||
Throw[$Failed, compileTemplate]
|
||||
];
|
||||
|
||||
print["Current directory is: ", Directory[]];
|
||||
classlist = Cases[classes, LClass[s_String, __] :> s];
|
||||
sourcefile = "LTemplate-" <> libname <> ".cpp";
|
||||
If[Not@FileExistsQ[#],
|
||||
print["File ", #, " does not exist. Aborting."]; Throw[$Failed, compileTemplate]
|
||||
]& /@ (# <> ".h"&) /@ classlist;
|
||||
print["Unloading library ", libname, " ..."];
|
||||
Quiet@LibraryUnload[libname];
|
||||
print["Generating library code ..."];
|
||||
code = TranslateTemplate[tem];
|
||||
If[FileExistsQ[sourcefile], print[sourcefile, " already exists and will be overwritten."]];
|
||||
Export[sourcefile, code, "String"];
|
||||
print["Compiling library code ..."];
|
||||
includeDirs = Flatten[{OptionValue["IncludeDirectories"], $includeDirectory}];
|
||||
|
||||
With[{driver = driver},
|
||||
Internal`InheritedBlock[{driver},
|
||||
SetOptions[driver,
|
||||
"SystemCompileOptions" -> Flatten@{
|
||||
OptionValue[driver, "SystemCompileOptions"],
|
||||
Switch[{$OperatingSystem, driver["Name"][]},
|
||||
{"Windows", "Visual Studio"}, {},
|
||||
{"Windows", "Intel Compiler"}, "/Qstd=c++11",
|
||||
{"MacOSX", "Clang"}, {If[$VersionNumber <= 10.3, "-mmacosx-version-min=10.9", Unevaluated@Sequence[]], "-std=c++11"},
|
||||
{_, _}, "-std=c++11"
|
||||
]
|
||||
}
|
||||
];
|
||||
CreateLibrary[
|
||||
AbsoluteFileName /@ Flatten[{sourcefile, sources}], libname,
|
||||
"IncludeDirectories" -> includeDirs,
|
||||
Sequence @@ FilterRules[{opt}, Except["IncludeDirectories"]]
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
compileTemplate
|
||||
]
|
||||
|
||||
|
||||
(****************** Pretty print a template ********************)
|
||||
|
||||
FormatTemplate[template_] :=
|
||||
With[{t = NormalizeTemplate[template]},
|
||||
(* If the template is invalid, we report errors but we do not abort.
|
||||
Pretty-printing is still useful for invalid templates to facilitate finding mistakes.
|
||||
*)
|
||||
validateTemplate[t];
|
||||
formatTemplate@NormalizeTemplate[t]
|
||||
]
|
||||
|
||||
formatTemplate[template_] :=
|
||||
Block[{LFun, LOFun, LClass, LTemplate, LType, LExpressionID},
|
||||
With[{tem = template},
|
||||
LType /: {LType[head_, rest___], passing : passingMethodPattern} :=
|
||||
If[{passing} =!= {}, passing <> " ", ""] <>
|
||||
ToString[head] <>
|
||||
If[{rest} =!= {}, "<" <> StringTake[ToString[{rest}], {2,-2}] <> ">", ""];
|
||||
LExpressionID[head_String] := "LExpressionID<" <> head <> ">";
|
||||
LFun[name_, args_, ret_] := StringTemplate["`` ``(``)"][ToString[ret], name, StringJoin@Riffle[ToString /@ args, ", "]];
|
||||
LOFun[name_] := StringTemplate["LinkObject ``(LinkObject)"][name];
|
||||
LClass[name_, funs_] := StringTemplate["class ``:\n``"][name, StringJoin@Riffle[" " <> ToString[#] & /@ funs, "\n"]];
|
||||
LTemplate[name_, classes_] := StringTemplate["template ``\n\n"][name] <> Riffle[ToString /@ classes, "\n\n"];
|
||||
tem
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
End[] (* End Private Context *)
|
22
LTemplate/LTemplatePrivate.m
Normal file
22
LTemplate/LTemplatePrivate.m
Normal file
@ -0,0 +1,22 @@
|
||||
(* Mathematica Package *)
|
||||
|
||||
(* :Package Version: 0.5.4 *)
|
||||
(* :Copyright: (c) 2019 Szabolcs Horvat *)
|
||||
(* :License: MIT license, see LICENSE.txt *)
|
||||
|
||||
(*
|
||||
* To include LTemplate privately in another package, load LTemplatePrivate.m using Get[],
|
||||
* then immediately call ConfigureLTemplate[].
|
||||
*)
|
||||
|
||||
BeginPackage["`LTemplate`", {"SymbolicC`", "CCompilerDriver`"}]
|
||||
|
||||
(* Note: Do not Protect symbols when LTemplate is loaded privately. *)
|
||||
|
||||
`Private`$private = True;
|
||||
Quiet[
|
||||
Get@FileNameJoin[{DirectoryName[$InputFileName], "LTemplateInner.m"}],
|
||||
General::shdw (* suppress false shadowing warnings if public LTemplate was loaded first *)
|
||||
]
|
||||
|
||||
EndPackage[]
|
26
LTemplate/LTemplatePrivateNoCompile.m
Normal file
26
LTemplate/LTemplatePrivateNoCompile.m
Normal file
@ -0,0 +1,26 @@
|
||||
(* Mathematica Package *)
|
||||
|
||||
(* :Package Version: 0.5.4 *)
|
||||
(* :Copyright: (c) 2019 Szabolcs Horvat *)
|
||||
(* :License: MIT license, see LICENSE.txt *)
|
||||
|
||||
(*
|
||||
* To include LTemplate privately in another package, and disable compilation support,
|
||||
* load LTemplatePrivateNoCompile.m using Get[], then immediately call ConfigureLTemplate[].
|
||||
* Disabling compilation support will avoid loading CCompilerDriver` and therefore improve
|
||||
* loading performance on Windows. Packages that ship with pre-compiled binaries do not need
|
||||
* compilation support in the LTemplate they embed.
|
||||
*)
|
||||
|
||||
BeginPackage["`LTemplate`", {"SymbolicC`"}]
|
||||
|
||||
(* Note: Do not Protect symbols when LTemplate is loaded privately. *)
|
||||
|
||||
`Private`$private = True;
|
||||
`Private`$noCompile = True;
|
||||
Quiet[
|
||||
Get@FileNameJoin[{DirectoryName[$InputFileName], "LTemplateInner.m"}],
|
||||
General::shdw (* suppress false shadowing warnings if public LTemplate was loaded first *)
|
||||
]
|
||||
|
||||
EndPackage[]
|
Loading…
Reference in New Issue
Block a user