User Guide for Mathwrist’s Numerical Programming Library

Copyright ©Mathwrist LLC 2023
(October 5, 2023)
Abstract

Mathwrist’s Numerical Programming Library (NPL) is a C++ dynamic linked library (dll) that provides numerical programming tools for scientists and engineers. The library is designed to integrate mathematical concepts, operations and numerical algorithms in an object-oriented approach. Users are expected to have intermediate level C++ programming knowledge and experience. This document is a general guideline to install and use NPL.

1 Installation

Mathwrist uses a standard Windows software installer to deploy the C++ Numerical Programming Library (NPL) product together with a license activation application to user’s machine. The target installation machine is required to have the following configuration in order to run the software:

  • x64-based processors;

  • 64-bit Microsoft Windows operating system11 1 Please contact us at sales@mathwrist.com for licensing and software availability on other platforms.;

  • Microsoft .NET framework 4.822 2 .NET framework 4.8 is a recommended Windows update and generally is installed automatically on Windows platform.

After a trial order is placed or a purchase order is completed on Mathwrist website, our software installer will be available for download. Alternatively, users can check in to their Mathwrist web account and download the installer from their order history. Double click the installer program and follow the standard Windows software setup steps as illustrated in Figure 1.

(a) Start the Setup
(b) Setup Choice
(c) Setup Success
Figure 1: Software Installation Steps

At the “Setup Choice” step in Figure 1(b), it is recommended to use the default installation directory “C:\Program Files\Mathwrist” and install the software for everyone. This requires local admin right on the target machine. After the software is successfully installed, users can find “Mathwrist Activation and NPL” appears in Control Panel|Programs|Programs and Features. Users can also find the “Mathwrist” folder from Windows Start Menu that has a menu item for license activation.

2 License Activation

Mathwrist’s Graphical Debugging Extension (GDE) and NPL products use the same license activation application to connect to Mathwrist’s software licensing server and generate a node-locked license file. Users may need adjust firewall setting to allow the activation application to connect to Internet.

To launch the license activation process, please go to Windows start menu Start Menu|Mathwrist|License Activation. After the license activation application is started, users have the opportunity to acknowledge and accept the “End User License Agreement (EULA)” terms and conditions as illustrated in Figure 2. In the installation directory, users can find a copy of EULA text file “eula-mathwrist.txt”. Mathwrist reserves all rights to update its EULA terms at software distributions.

Figure 2: EULA - Activation

After users accept the EULA terms and conditions, the activation application will then display an introduction screen illustrated in Figure 3. For trial software licensing, please click the “Create a trial license” checkbox at the introduction screen 3. This option allows users to run both GDE and NPL in a 3-month trial period. After the trial expiry, it is impossible to re-generate a new trial license on the same machine. GDE users may continue using the software free of charge with limited features. Please refer to GDE “Overview” user guide for the details of free features. NPL on the other hand always requires a valid software license in order to use the library in a client application.

Figure 3: Introduction - Activation

To purchase our software product, it is required to register a Mathwrist web account with a valid email address as user name. Upon the completion of a purchase order, a product key will be generated and stored in a user’s account. Users need provide this product key to the license activation application.

Next, please click the checkbox to confirm 1) Internet is connected; 2) the hardware ID of the current machine will be collected to generate a node-locked license. The node-locked license will grant users to run Mathwrist’s software only on this current machine. Further, once a node-locked license is generated, users cannot request refund on the purchase order. They may re-run the activation application to retrieve an existing license or download it from the order history page under their web accounts.

The next screen Figure 4 is relevant to purchase orders. It requires users to login to their account with the same credential as they login to Mathwrist web account. Upon successful login, as shown in Figure 5(a), please type in the software product key associated with a purchase order.

Figure 4: Login - Activation

Same as the installer download link, product keys are displayed at the end of an online order checkout session. They can also be retrieved from the order history web page after login to Mathwrist web account. Once the product key is submitted to Mathwrist’s licensing server, the server will then generate a node-locked license and send it back to the activation application as shown in Figure 5(b). Users should save this “license.txt” file to the same installation directory and keep the file name and content unchanged.

(a) Product Key
(b) License Activated
Figure 5: License Activation of a Product

3 Environment Setup

3.1 Environment Variable

Our license activation application automatically creates an environment variable Mathwrist that points to Mathwrist software installation directory. At run time, NPL searches for a valid license file under the path set be this environment variable.

3.2 Installation Directory

Under Mathwrist installation directory, default to “C:\Program Files\Mathwrist”, users can find the following subdirectores:

  • activation: contains binary executable files to activate a node-locked software license.

  • demo: contains C++ demo projects to use NPL and GDE.

  • doc: containts NPL and GDE documentation pdf files.

  • include: is the root directory of NPL C++ include header files.

  • lib: contains C++ lib files to link to NPL.

NPL C++ header files are stored in “ftl” and “npl” subdirectories under the “include” root directory. When creating a Visual Studio C++ project, users need set the project properties C++|General|Additional Include Directories to this “include” root directory.

There are to two C++ lib files “MathwristNPL-D.lib” and “MathwristNPL.lib” under the “lib” directory. They are the 64-bit lib files to link NPL in debug build and release build respectively. Users need add a path to this lib directory in C++ project properties Linker|General|Additional Library Directories.

Users also need set debug and release build properties as the following:

  • Debug build:

    • C/C++|Code Generation: Multi-threaded Debug DLL (/MDd)

    • Linker|Input|Additional Dependencies: add MathwristNPL-D.lib

  • Release build:

    • C/C++|Code Generation: Multi-threaded DLL (/MD)

    • Linker|Input|Additional Dependencies: add MathwristNPL.lib.

The run time dlls “MathwristNPL-D.dll” and “MathwristNPL.dll” are directly stored under Mathwrist installation directory. Users need add a path to this directory in their environment variable PATH settings in order to load NPL dlls at run time.

4 FTL

Mathwrist has its own C++ “Fundamental Template Library” (ftl), which is a lightweight implementation of some utility tools to facilitate internal software development. The goal of ftl is to avoid over-generalization and reduce the footprint of templates in NPL.

The _cloneable.h and _iterator.h two headers under “include\ftl” directory are used internally for NPL implementation only. They are not involved at NPL API level hence not documented.

4.1 _exception.h

This header defines a C++ class mathwrist::ftl::Exception. NPL may throw exception objects of this class for various causes in the library. In general, users need not concern about how to create objects from this class. The following code illustrates catching exceptions thrown from NPL and retrieving error messages or error codes.

1 try
2 {
3    // Call NPL library
4 }
5 catch (const ftl::Exception& e)
6 {
7    // Retrieve error code
8    int error_code = e.cause().code();
10    // Print error message
11    std::cout << e << std::endl;
12 }

4.2 _buffer.h

This header file defines a dynamically allocated buffer class mathwrist::ftl::Buffer<T> for template type T. At API level, NPL could take const ftl::Buffer<T>& as input argument or ftl::Buffer<T>& as output argument. GDE automatically recognizes a ftl::Buffer<double> object as a vector-type plottable object.

The public functions of this buffer class are documented in place in the _buffer.h header file. Please note that the buffer class does NOT perform index range checks. It is user’s responsibility to ensure a buffer object has correct size and index access.

5 Programming with NPL

5.1 Predefined Constants

NPL uses a set of predefined double constants, hardcoded in header file “constants.h”. Some of them are real mathematical constants. Some of them on the other hand serve as practically decent numerical default values. It is not our interest to debate what are “truly” constants, what are the “true” values on certain platform architect and why some C++ std numeric limits are not used. Users are welcome to choose appropriate alternatives in their applications unless explicitly stated in NPL documentation.

5.2 C++ Raw Pointers

NPL API accepts C++ raw pointers as arguments. Whenever NPL caches user provided raw pointers as class data members, i.e. the x and y pointers to create piecewise functions, our API documentation will explicitly state this situation. It is required that the underlying memory of these pointers is valid during the entire lifecycle of the pointer-holding object.

Typically, NPL API functions take a C++ raw pointer together with a size argument that specifies the number of elements allocated in the pointed memory. However when the context has no ambiguity regarding the size, NPL API might simply take the pointer alone as the following example.

1 size_t BSplineCurve::n_basis() const;
2 void BSplineCurve::set_basis_coeff(const double* _beta);

In this example, a BSplineCurve object consists of certain number of B-spline basis. The number of basis coefficients provided through the pointer argument _beta is assumed exactly equal to the number of basis stored in the BSplineCurve object. The query function n_basis() can retrieve the number of basis. In such situations, it is user’s responsibility to ensure pointer _beta has correct number of basis coefficients.

As a general principle, when NPL receives input from raw pointers provided by users, it is users’ responsibility to manage the memory of their pointers. If NPL provides a pointer to users, the pointer associated memory is managed by NPL.

5.3 Matrix Arguments in User Defined Functions

In various places, e.g. the objective function for numerical optimization, users need supply a user-defined function that is derived from the FunctionND interface. This n-d function interface takes Matrix objects as input and output arguments. As a convention, it is ensured that whenever a user-defined function is called inside the library, NPL always passes matrix arguments that have all elements stored in contiguous memory. These matrix arguments support iterator access. It is also legitimate to obtain raw pointers from these matrix objects, illustrated as the code example.

1 struct F : public FunctionND
2 {
3    double eval(const Matrix& x, Matrix* _g=0, Matrix* _H=0) const
4    {
5       // raw pointer to matrix elements in row-major storage
6       const double* p_x = &x(0,0);
7       double* p_g = _g ? &(*_g)(0,0)) : 0;
8       double* p_H = _H ? &(*_H)(0,0)) : 0;
10       ...
11    }
12    ...
13 };

5.4 Numerical Range

NPL uses Bound class to define a numerical range. A numerical value x,x<1.e300 is considered as a bounded quantity. The lower bound and upper bound parameters provided to Bound class constructor need be strictly in (-1.e300,1.e300). In addition, NPL assumes ±=±1.e308. A quantity exceeds the “infinity” value typically suggests numerical noise. It is a good practice to formulate mathematical problems into numerically normalized problems, i.e. properly scaled.

When we compare double quantity a to b, NPL uses |a-b|1+|b|<ϵ to test the equality condition, where ϵ usually is a tolerance control parameter passed down from API level functions. In occasional cases when the equality comparison involves “exactness”, i.e. test if a knot point is hit, NPL takes ϵ=ϵM, where ϵM=1.11e-16 is the “machine epsilon” defined in constants.h. In all other cases and when tolerance control is not specified, we use default value ϵ=ϵN, where ϵN=1.e-12 is the “numerical epsilon” defined constants.h.

5.5 Thread Safety

NPL internally does not apply any threading or concurrency protection. It could be considered as “thread safe” in the sense that there is no writable local static data being used inside the library. Further, MathwristNPL-D.dll and MathwristNPL.dll are built with Microsoft multithreaded runtime libraries. So NPL can be used in a multithreading environment.

In general however, concurrent access to the same NPL object from different threads should be avoided unless they are simple query functions. In particular, NPL math objects may hold mutable resources to facilitate efficienct calculation. So a C++ const member function does not necessarily imply “read only” access in NPL. As a general principle, calling computing routines on a shared object from different threads should be avoided.