DMath is DirectXMath for All – Part 1
(originally published on codeproject.com)
DirectXMath is a great SIMD-friendly Visual Studio C++ Math Library. It requires Visual Studio 2010 and later and targets Windows Vista and later. It can also be used with operating systems based on the neon-arm processor.
DirectXMath is mostly used for game, multimedia and image processing programming, but is also frequently a tool in physics and electronics modeling, artificial intelligence and other areas of science and math.
You cannot use
DirectXMath if you develop in any programming language other than C++ or even if you develop with a non-Microsoft C++ compiler.
DMath is totally developed in x86 and x64 Assembly Language and contains all 547 functions of
DMath is not a SIMD-friendly library, it is a 100% SIMD library. While
DirectXMath uses special C++ structures to align data to memory before using SIMD through intrinsics,
DMath makes the alignment within the Assembly Language itself. This makes it possible to use all the features of
DirectXMath from any programming language. The
DMath library has been tested extensively over many months, it appears stable but like any other software, it may contain bugs and, of course, is subject to improvements.
DMath versus DirectXMath
DMathis fully compatible with
DirectXMath, i.e., you will obtain the same output. Well, not 100% correct, in a small number of cases, the output from
DMathis more precise because the algorithm is better. For example,
DMath XMVectorPowcomes very close to the results of the Windows Calculator for power calculations while
DirectXMathdiverges noticeably for large exponents. You can safely infer that we believe that the Windows Calculator has a good algorithm to calculate powers 🙂
- In most cases,
DMathis faster than
DirectXMath, but not dramatically faster. We found that where
DirectXMathis a little bit faster is related to the fact that it inlines almost every call to a function.
DMathinlines a lot of calls as well, but not as many. On the other hand,
DMathis clearly faster in functions where
DirectXMathuses x87 floating point instructions for calculations and there is a bunch of them within
DMathcan be used with old Windows operating systems (it was tested in Windows 2000) because SSE instructions depend much more on the CPU than on the operating system itself.
DMathis simpler to use because many of
DirectXMathspecial structures and types are just meant to solve alignment problems in C++.
DMathsolves them inside the Assembly Language itself – and you should not use such structures and types with
DMath! For example, even from Visual Studio C++ don’t use variables of type
DMath is contained in 2 DLLs, one is compiled for x86 using the CDecl calling convention and the other for x64 Intel processors using the Windows ABI. We plan for the short term to provide static linking facilities instead of the DLLs for people that have more advanced needs. And in the future, if it is worth the effort, we may compile for other operating systems of the Intel family, but currently we are all committed with Windows.
What DMath Contains?
As mentioned earlier,
DMath contains 547 functions which are the whole contents counterpart of the same number of functions included in the various files that make up the
We have not included in this article Collision functions, other than the
TriangleTests functions because they are not part of the
DirectXMath Library proper. However, we will deal with them in forthcoming articles.
Using DMath from C#
- C#, and the .NET languages in general, are, in my opinion, the most difficult languages to interface with native code. Add to that the sad fact that I am not an expert in .NET languages, so the simple perception that I was able to make
DMathwork with C# makes me feel happy. Probably, you can improve on my solution and I would love to see people come up with alternatives.
Now, a little correction, I was lying! C# is not actually interfacing with
DMath, I made a .NET library in C++ CLI that C# references. Most complications I had to deal with are actually on the C++ CLI side, the C# side is the application you will be developing and I don’t think you will find difficulties to get it up and running. If you are a Visual Basic aficionado, you will find your way as easily because, as I mentioned, the interface nitty gritties are in the C++ CLI library.
- From C#, the
DMathfunctions are contained in 2 namespaces defined in C++ CLI (in the DMathLib.h file):
DMathLibnamespace contains most functions and structures (see csharpns1.zip, for the C# semantics of such elements). Note that structure names are prefixed with “
dm” in relation to their
Collisionnamespace contains the 4
TriangleTestsfunctions (see csharpns2.zip, for the C# semantics of such elements).
- When making an application, bear in mind that you have 3 DLLs to deal with: 1 native x86 DLL (DMathCDll32.dll), 1 native x64 DLL (DMathDll64.dll) and 1 .NET library DLL (DMathLib.dll).
The best way to deal with all this is make a solution with the .NET library project and your application project (see our demo).Your C# application must be built either for x86 or x64, the ALL CPUs alternative will not work.
To automate things and copy the correct DLLs to the Output folder according to the CPU bitness, edit the Project file of your application and add the following lines (see our demo):
<ItemGroup Condition="'$(Platform)'=='x64'"> <Content Include="DMathDll64.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> </ItemGroup> <ItemGroup Condition="'$(Platform)'=='x86'"> <Content Include="DMathCDll32.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> </ItemGroup> <ItemGroup> <Reference Include="DMathLib" Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> <HintPath>Debug\DMathLib.dll</HintPath> </Reference> <Reference Include="DMathLib" Condition="'$(Configuration)|$(Platform)' == 'Release|x86'"> <HintPath>Release\DMathLib.dll</HintPath> </Reference> <Reference Include="DMathLib" Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> <HintPath>x64\Release\DMathLib.dll</HintPath> </Reference> <Reference Include="DMathLib" Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> <HintPath>x64\Debug\DMathLib.dll</HintPath> </Reference>
4-After building the application, you will need to include in the distribution either the x86 (if you compiled for x86) or the x64 native DLL (if you compiled for x64) and the library DLL. When we are able to provide static linking (see above) instead of the native DLLs you will be able to have a standalone application, as explained in our previous articles, Mixing .NET and Assembly Language in a standalone 32-bit EXE and Mixing .Net and Assembly Language in a standalone 64-bit EXE,
Our Demo tests almost every
DMath function – not all, because some functions are just slight variations of others. You will see that the results are presented extremely fast in spite of some functions being very complex. No wonders for this, there are Assembly Language behind the scenes that more than compensate for all the marshaling hips and hops.
A previous note at this point, I am aware that some of the parameter values used in the demo are not realistic, even when not trapped by the
assert functions. But the purpose of the demo is just to show how to use each function. BTW, I have tested separately each function with
DirectXMath in a C++ application to confirm that the results are the same, and they are.
The solution was built with Visual Studio 2015. The
DMathLib project uses the VS 2013 toolset, so Visual Studio 2015 may invite you to upgrade. I would decline the upgrade, if I intend to run at least on Windows 7 without further complications. But you can accept the challenge and deal with it.
What is Next?
This article is part 1 of a number not yet established of parts. All will depend on the audience’s interest, I have no clue about that.