- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
When I want to use GMP functions, the names used in the documentation like "mpz_fdiv_qr" do not seem to work
looking at the mkl_core.dll, I see names likemkl_gmp___gmpz_fdiv_qr, and with these names I can build a custom library.
Now the next problem shows up: how to map data structures, like "mpz_t" to a C# environment?
There isa pretty large amount of GMP examples for C in the "examples" subdirectory, but this does not really help me to map the structures to C#.
The frequently mentioned article "Using Intel MKL in your C# program" does not explain that either.
Please provide some hints how to map the needed structs to C#
Thanks - Franz
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello, Franz,
You can find an example of the C# structure for the corresponding MKL VML C structure in the article. You can find this structure also in the vddiv.cs MKL C# example:
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)]
public struct VmlErrorContext
{
public int iCode; /* Error status value */
public int iIndex; /* Index for bad array element,
* or bad array dimension,
* or bad array pointer */
public double dbA1; /* Error argument 1 */
public double dbA2; /* Error argument 2 */
public double dbR1; /* Error result 1 */
public double dbR2; /* Error result 2 */
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=64)]
public String cFuncName; /* Function name */
int iFuncNameLen; /* Length of functionname*/
}
The structure mpz_t includes pointer and size_t fields. C# provides platform-independent types IntPtr and UIntPtr to map such kind of C types. See the dfti_d1.cs MKL C# example.
You can find the full table of data type correspondence in any PInvoke tutorial. See for instance MSDN documentation.
WBR,
Vladimir
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
However I am stuck with 2 problems:
1. I can not make the function mpz_get_str work. Whatever I try to marshal the string parameters, the program terminates with error codes which I do not find anywhere (no matter whether i run the program in the command line or in a VS environment.)The first parametr char* str is the problem. Reading multiple PInvoke tutorials and the relevant chapter of Donis Marshal's book on C# did not help me to find a workable solution.
Here is the function in question and a piece of its documentation:
- Function: char * mpz_get_str (char *str, int base, mpz_t op)
Among other things I tried a marhalling likeConvert op to a string of digits in base base. The base argument may vary from 2 to 62 or from 2 to 36.
For base in the range 2..36, digits and lower-case letters are used; for 2..36, digits and upper-case letters are used; for 37..62, digits, upper-case letters, and lower-case letters (in that significance order) are used.
If str is
NULL
, the result string is allocated using the current allocation function (see Custom Allocation). The block will bestrlen(str)+1
bytes, that being exactly enough for the string and null-terminator.
[DllImport("mkl.dll", CallingConvention = CallingConvention.Cdecl,
ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.LPStr)]
internal static extern
string mkl_gmp___gmpz_get_str(
[MarshalAs(UnmanagedType.LPStr)]
[In, Out] ref StringBuilder s,
[In] int bas,
[In] ref mpz_t inp);
[DllImport("mkl.dll", CallingConvention = CallingConvention.Cdecl,
ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.LPStr)]
internal static extern
string mkl_gmp___gmpz_get_str(
[MarshalAs(UnmanagedType.LPStr)]
[In, Out] ref StringBuilder s,
[In] int bas,
[In] ref mpz_t inp);
This problem is a show stopper for me, it prevents me from getting back meaningful output from MKL GMP.
2. Working with Int64 integers does not function as expected.
There are no compile-time or runtime errors, but I can see viaset/get roundtrips that only the low 32 bits are used.Signatures see below.
/** GMPI native mpz_init_set_si declaration */
[DllImport("mkl.dll", CallingConvention = CallingConvention.Cdecl,
ExactSpelling = true, SetLastError = false)]
internal static extern void mkl_gmp___gmpz_init_set_si(
[In, Out]ref mpz_t big,
[In]Int64 n);
/** GMPI native mpz_get_si declaration */
[DllImport("mkl.dll", CallingConvention = CallingConvention.Cdecl,
ExactSpelling = true, SetLastError = true)]
internal static extern Int64 mkl_gmp___gmpz_get_si(
[In] ref mpz_t big);
Please provide hints how to solve this.
Thanks - Franz
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello Franz,
We are working on the issue. Now I see one general mistake in your code. The names with the prefix mkl_gmp are internal MKL names. Therefore you should not use them. You can find correct names in the mkl_gmp.h file. For instance, use __gmpz_get_str instead of mpz_get_str:
#define mpz_get_str __gmpz_get_str
Regards,
Vladimir
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I did the dumpbin /exports command for mkl_core.dll, and all the names for the integer functions work correctly, also the results are ok with the exception of the ...get_str function (see above).
I will soon report another issue with the ...get_si function which does not seem to report the correct sign.
With the ...get_str issue, I could not make any progess and still need your help.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello Franz,
Generally external and internal MKL functions have different set of arguments.
I know the problem and I'm trying to find a solution.
Thanks,
Vladimir
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The code belowworks:
using System;
using System.Security;
using System.Runtime.InteropServices;
using mkl;
public class test_str
{
private test_str() {}
public static void Main(string[] args) {
String str_in = "18446744073709551616";
String str_out = " ";
STR.mpz_t rop = new STR.mpz_t();
STR.mpz_init ( ref rop );
STR.mpz_set_str ( ref rop, str_in, 10);
String ss = STR.mpz_get_str ( str_out, 10, ref rop );
Console.WriteLine(ss);
}
}
namespace mkl
{
public sealed class STR
{
private STR() {}
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)]
public struct mpz_t
{
public int _mp_alloc; /* number of limbs allocated by the library in a native way */
public UIntPtr _mp_size; /* sign of this field indicates the sign of the big number */
/* the absolute value is the number of limbs in the big number */
public IntPtr _mp_d; /* points to limbs allocated for the big number */
}
public static void mpz_init(ref mpz_t integer)
{
STRNative.__gmpz_init (ref integer);
}
public static void mpz_set_str(ref mpz_t rop, String str, int base_)
{
STRNative.__gmpz_set_str (ref rop, str, base_);
}
public static String mpz_get_str(String s, int bas, ref mpz_t inp)
{
return STRNative.__gmpz_get_str(s, bas, ref inp);
}
}
[SuppressUnmanagedCodeSecurity]
internal sealed class STRNative
{
private STRNative() {}
[DllImport("mkl.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern
void __gmpz_init ([In, Out] ref STR.mpz_t integer);
[DllImport("mkl.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern
int __gmpz_set_str (ref STR.mpz_t rop, [MarshalAs(UnmanagedType.LPStr)] [In] String str, int base_);
[DllImport("mkl.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.LPStr)]
internal static extern
string __gmpz_get_str([MarshalAs(UnmanagedType.LPStr)] [In, Out] String s,
[In] int bas,
[In] ref STR.mpz_t inp);
}
}
Add three functions to build custom dll:
__gmpz_get_str
__gmpz_init
__gmpz_set_str
Regards,
Vladimir
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Unfortunately this does NOT solve the problem on my side.
There must be a difference somewhere (maybe due to Windows 7 and the 64 bit environment ...)
Below I posted my summary, and I sent some more information via a separate channel.
With the Visual Studio debugger, I get the following additional information:
Das Programm "[6560] MKL_Cons2.vshost.exe: Verwaltet" wurde mit Code -1073740940 (0xc0000374) beendet.
Looking for information regarding the return code 0xc0000374, I found a huge number of forum entries most of which did not tell me anything.
I searched MSDN and found the following link:
http://blogs.msdn.com/b/jiangyue/archive/2010/03/16/windows-heap-overrun-monitoring.aspx
To me, this seems to get closer to the problem. There must be a problem with the string handling somewhere between C# and the native environment which leads to the heap corruption. But I do not have the means to really find the root cause of the problem.
I believe that somebody needs to have a detailed look at the implementation of the get_str function in MKL .
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I still have the situation that the program terminates with0xc0000374 as soon as I call get_str with exactly the code as suggested in this thread. So there MUST be another problem.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello Franz,
Please try to use the following idea:
public static String mpz_get_str(String s, int bas, ref mpz_t inp)
{
String m_str = "...........This is manged string................";
// convert managed string to ANSI and copy it into unmanaged memory
IntPtr u_str = Marshal.StringToHGlobalAnsi(m_str);
IntPtr u_ret = __gmpz_get_str(u_str, bas, ref inp);
// convert string back
String m_ret = Marshal.PtrToStringAnsi(u_ret);
// release unmanaged memory
Marshal.FreeHGlobal(u_str);
return m_ret;
}
[DllImport("mkl.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr __gmpz_get_str(IntPtr s, [In] int bas, [In] ref STR.mpz_t inp);
It works directly with the unmanaged memory, so do not forgetto reserve enough room to keep the requested string and to free memory manually.
Regards,
Vladimir
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page