DM2003 Math engine

This article describes architecture of DM2003 calculations and explains how you can customize its mathematical features. DM2003 has two-layer design: simple calculations and data processing functions implemented as scripts, so that users can easily learn and modify them without recompilation of binary units. However, more complicated numerical algorithms such as curve fitting (regression analysis) or expression evaluation (parsing) are unlikely to be modified by end users and "hard coded" in the form of usual binary executables. Relations between DM2003 mathematical interfaces (accessible by script layer) and math engine outlined at the diagram below:

DM2003 mathematical features architecture

First, it should be mentioned that Fitter.dll (stand-alone ActiveX fitting engine) may be compiled in two versions: in version a) it is linked to standard dmmath.dll dynamic link library. In the separate DMFitter setup - in version b) - all math routines compiled in the same DLL, so that there's no need to redistribute dmmath.dll with third party applications, while as of build #345 main DM2003 setup includes Fitter.dll version a).

Generally speaking, there's two ways to customize DM2003 math features:

Second possibility should be considered if you have another calculation engine and prefer to use it instead of DM2003 "native" one. You can create another version of dmmath.dll with the same interface and just replace standard DLL. By the way, you can invoke standard library by your own (of course, you should rename original file) - this method may be used to replace (or extend) separate functions in the dynamic link library.

In many cases however all you need is to add several specific functions to the standard set of functions supported by expression evaluator. This technique used by DM2003.EXE itself, and as you will see below, this is really easy.

Numeric values precision

As of build #300, all DM2003 binary units may be compiled with either 64 bit (double) or 80 bit (long double, or "extended") numeric values precision options. This feature controlled by "doublefloat" conditional compilation key. Certainly, all units including dm2003.exe, fitter.dll and dmmath.dll MUST be built with the same numeric value precision. Unfortunately, Microsoft COM technology as well as all their development tools and languages support only 64 bit double-precision floats, so that numbers are rounded when passed through COM interfaces. Moreover, you can't use Visual Studio to build custom dmmath.dll library in 80-bit mode (for more details, see this epic post on MSDN blogs). From the other hand, development tools that can handle 80 bit floats (such as Delphi) may take advantage of much greater precision and range. Although in my tests no substantial difference between 64 and 80 bit versions of NLSF fitter was detected, at the moment of writing 80-bit version DM2003 is distributed. You can easily determine which version is used: open Script Editor, select VBScript language, enter the code below and compile the script to display message box:

Server.ShowDialog "aboutbox", "precision"

User-defined expression parser functions

DM2003 Math engine (dmmath.dll) exports several procedures, whose definitions are listed in the file named "DMMath.inc", included into the DM2003 VCL controls archive (dm2k3vcl.zip). This library can be configured - it is possible to add new items to the lists of objects (functions and parameters) for string expression evaluators. It should be mentioned that this DLL has two such evaluators (parsers) with different set of parameters: first used in Parse function and second in NLSFParse, LinearFitEx, LMNLSF and LMNLSFEx functions. In order to add user-defined functions for parsers, you should create a "wrapper" DLL that re-exports procedures from the original DLL. Also you should write code for your functions and add pointers to these functions using AddParserObject and AddNLSFParserObject procedures in the initialization code of your DLL as shown in the following code snippet:

{definition of additional function CH(X)}
function CH(var R: TReal): TReal;
begin
  CH:=(exp(R)+exp(-R))/2;
end;

{RE-EXPORT functions from standard dmmath.dll}
exports
  Parse,
  NLSFParse,
  AddParserObject,
  LinearFit,
  LinearFitEx,
  LMNLSF,
  LMNLSFEx,
  AddNLSFParserObject;

begin
{add newly defined CH(X) to BOTH Parsers}
  AddParserObject(@CH, 'CH', 1);
  AddNLSFParserObject(@CH, 'CH', 1);
end.

You can use any compiler that can re-export and call procedures defined in WinAPI-style 32-bit DLLs and can handle 80-bit double precision float point numbers. In  mathengine.zip archive you can find basic implementation of "wrapper" library that adds CH(X) function (dmmath.dpr). Other examples of parser functions may be found in Parser.pas unit in dm2k3vcl.zip.

How to test it

Abovementioned mathengine.zip archive contains compiled dmmath.dll and DM2003 workspace file named "ch.dmw". You should rename original dmmath.dll -> dmmath1.dll, place dmmath.dll in the DM2003 installation folder and open ch.dmw. You will see plot with 2 functional series - one uses Y expression composed from standard functions "(exp(cx)+exp(-cx))/2", and the second uses custom function from wrapper DLL "CH(cx)". Certainly, now you may use CH() in expressions for IDMApplication.LMFit() method. Also it is possible to invoke your custom functions in Fitter.dll version a) expressions because it uses mathematical functions imported from dmmath.dll. Compile and run ch_fit.vbs example from the same archive to test this feature.