I am solving sparse system of linear equations with Math.Net Numerics in C#. I'm trying to export this code to dll (using Robert Giesecke's Unmanaged Exports) and run it from Delphi code.
Here is my C# code:
namespace MathNetSolverLib
{
public class ParticleInterpolator
{
public ParticleInterpolator(int eqnumber)
{
n = eqnumber;
b = Vector.Build.DenseOfArray(new double[eqnumber]);
result = Vector.Build.DenseOfArray(new double[eqnumber]);
input_points = new List<Tuple<int, int, double>>();
}
public void solve()
{
using (var writer = new StreamWriter("C:\\users\\s\\desktop\\logb.txt"))
{
for (int i = 0; i < n; ++i)
{
writer.WriteLine(b[i]);
}
}
using (var writer = new StreamWriter("C:\\users\\s\\desktop\\loginput.txt"))
{
for (int i = 0; i < input_points.Count(); ++i)
{
writer.WriteLine(input_points[i]);
}
}
TFQMR solver = new TFQMR();
MathNet.Numerics.LinearAlgebra.Solvers.Iterator<double> iter =
new MathNet.Numerics.LinearAlgebra.Solvers.Iterator<double>();
SparseMatrix sd = SparseMatrix.OfIndexed(n, n, input_points);
solver.Solve(sd, b, result, iter, new DiagonalPreconditioner());
using (var writer = new StreamWriter("C:\\users\\s\\desktop\\logres.txt"))
{
for (int i = 0; i < n; ++i)
{
writer.WriteLine(result[i]);
}
}
}
public int n;
public List<Tuple<int, int, double>> input_points;
public Vector<double> result;
public Vector<double> b;
}
public class Class1
{
[DllExport]
public static ParticleInterpolator create(int eqnumber)
{
return new ParticleInterpolator(eqnumber);
}
[DllExport]
public static void addValue(int row, int col, double value, ParticleInterpolator ins)
{
ins.input_points.Add(new Tuple<int, int, double>(row, col, value));
}
[DllExport]
public static void setRhs(int row, double value, ParticleInterpolator ins)
{
ins.b[row] = value;
}
[DllExport]
public static void solve(ParticleInterpolator ins)
{
ins.solve();
}
[DllExport]
public static double getSolutionByIndex(int index, ParticleInterpolator ins)
{
return ins.result[index];
}
}
}
I have imported this to C# dll like this:
[DllImport("MathNetSolverLib.dll", EntryPoint = "create")]
public static extern int create(int eqnumber);
[DllImport("MathNetSolverLib.dll", EntryPoint = "addValue")]
public static extern void addValue(int row, int col, double value, int ins);
[DllImport("MathNetSolverLib.dll", EntryPoint = "setRhs")]
public static extern void setRhs(int row, double value, int ins);
[DllImport("MathNetSolverLib.dll", EntryPoint = "solve")]
public static extern void solve(int ins);
[DllImport("MathNetSolverLib.dll", EntryPoint = "getSolutionByIndex")]
public static extern double getSolutionByIndex(int index, int ins);
and it works fine.
But when I am trying to import this in Delphi:
function create(n: integer): pointer; stdcall; external MathNetSolverLib;
procedure addValue(row, col: Integer; value:double; p:pointer); stdcall; external MathNetSolverLib;
procedure setRhs(row: Integer; value: double; p:pointer); stdcall; external MathNetSolverLib;
procedure solve(p: pointer); stdcall; external MathNetSolverLib;
function getSolutionByIndex(index: Integer; p:pointer): double; stdcall; external MathNetSolverLib;
the TFQMR solver returns wrong result. It seems that algorithm inside TFQMR has different behaviour.
It is very strange because all input data (variables A, b, n and input_points) are remain the same when calling dll from C# or Delphi (I have checked it).
Does anyone have an idea how to explain this?