LMath
About
LMath is a mathematical library for Free Pascal (FPC) and Lazarus. It's a further development of DMath from Jean Debord. It is entirely written in Pascal and does not depend on external libraries.
LMath provides routines and demo programs for numerical analysis, including mathematical functions, probabilities, matrices, optimization, linear and nonlinear equations, integration, Fast Fourier Transform, random numbers, curve fitting, statistics and graphics.
Author: Viatcheslav V. Nesterov (glorfin)
License: LGPL 3.0
Changes from DMath
- Units uVectorHelper, uVecUtils, uVecFunc and uVecPrn in lmMathUtil package define several handy functions for work with arrays.
- Unit uMatrix in lmLineAlgebra defines several general operations over vectors and matrices.
- COBYLA algorithm (Constrained Optimization by Linear Approximation, M. Powell) for tasks of constrained optimization included in lmOptimum package, unit uCobyla.
- Procedure for constrained non-linear regression ConstrNLFit in the unit uConstrLNFit which uses COBYLA algorithm included in lmRegression package.
- Procedure LinProgSolve in the unit uLinSimplex, package lmOptimum implements simplex method for solution of linear programming problems.
- Unit uintPoints in lmGenMath package defines operators over TIntPoint, similar to uRealPoints.
- Unit uUnitsFormat in lmMathUtils package allows now using of long prefixes (for example, "pico") along with short ("p") ones.
- Other additions appear as the library evolves.
Structure of the library
The library is organized as 13 relatively small packages:
- lmGenMath. This package defines several important data structures, used later in the whole library, some utility functions, basic math functions and special functions. All other packages of the library depend on lmGenMath.
- lmMathUtil. Various function for manipulations with arrays, sorting and formatting. Depends on lmGenMath.
- lmLinearAlgebra. Operations over vectors and matrices. Depends on lmMathUtil and lmGenMath.
- lmPolynoms. Evaluation of polynomials, polynomial roots finding, polynomial critical points finding. Depends on lmGenMath and lmLinearAlgebra.
- lmIntegrals. Numeric integrating and solving differential equations. Depends on lmGenMath.
- lmRandoms. Generation of random numbers. Depends on lmGenMath.
- lmMathStat. Descriptive statistics, hypothesis testing, collection of various distributions. Depends on lmGenMath and lmLinearAlgebra.
- lmOptimum. Algorithms of function minimization. Somewhat artificially, unit uEval for evaluation of an expression, is included into this package. Depends on lmGenMath, lmLinearAlgebra, lmRandoms, lmMathStat.
- lmNonLinEq. Finding roots of non-linear equations. Depends on lmGenMath, lmLinearAlgebra, lmOptimum.
- lmDSP. Functions for digital signal processing. Convolution, collection of filters and Fourier Transform procedures.
- lmRegression. Functions for linear and non-linear regression, curve fitting. Collection of common models. Depends on lmLinearAlgebra, lmPolynoms, lmOptimum, lmMathUtil.
- lmSpecRegress. Collection of field-specific models for data fitting. Depends on lmGenMath and lmRegression.
- lmPlotter. Routines for data and functions plotting. Depends on lmGenMath, lmMathUtil and LCL.
Download
Installation
Download and unpack file "LMath_and_Components_x_x_x.zip". Open and compile packages:
- lmGenMath,
- lmMathUtil,
- lmLinearAlgebra,
- lmPolynoms,
- lmIntegrals,
- lmRandoms,
- lmMathStat,
- lmOptimum,
- lmNonLinEq,
- lmRegression,
- lmSpecRegress,
- lmDSP,
- lmPlotter,
in this order. Afterwards you may compile LMath.pkg, which does not have any additional code but simply depends on all these packages. Therefore, if you add dependency on LMath to your project, it is not necessary to add every single package.
Alternatively, if you have Project Groups package installed in your Lazarus IDE, you can open and compile LMath project group, select LMath target and compile it.
You do not need to install LMath in the IDE, simply add packages to the dependencies of your project and needed units to the uses clause of your units.
If you are going to use LMComponents, open LMComponents package, compile and install it.
LMComponents
LMComponents is included in the LMath distro. It contains units:
Unit lmPointsVec
TPoints is a class wrapper around TRealPointVector (see LMath.pdf, Chapter 2). Its properties X[index] and Y[index] provide access to X and Y fields as to separate arrays of Float; if the package was compiled with -dDebug setting, range check is done for Index. However, use of X and Y properties has a considerable penalty on performance. Direct access to underlying array TPoints.Points is provided for use in time-critical code sections, but in general it is safer to use X and Y properties. If Append procedure is used for adding new points, Count is adjusted automatically; by exceeding current Capacity, memory is automatically reallocated. In addition, many utility methods and properties are provided, such as MaxX, MaxY, MinX, MinY; RemovePoints allows to remove subarray from an arbitrary index; constructor Combine allows to create TPoints from two vectors of Float; opposite to it, Extract is a mean to extract X or Y as vector of Float; SortX and SortY sort Points as names suggest.
Unit lmFilters
Unit lmFilters includes several digital filters of a signal. They are implemented as non-visual components:
- TDigFilter. Ancestor class for all digital filters.
- TOneFreqFilter. Ancestor class for all filters with a single corner frequency.
- TFIRFilter. Ancestor class for filters with finite impulse responce filters.
- TMovAvFilter. Moving average filter
- TGaussFilter. Gaussian filter. The only one, which can be used only for filtering ready data, but not real time.
- TMedianFilter. Median filter.
Most of them can be used both for filtering of earlier sampled data and for filtering in real time, during data acquisition. To make the components format-independent, data points are fed into filter with user-defined OnInput event and returned by another user-defined OnOutput event. You can drop a component onto a form and define OnInput and OnOutput events. Afterwards, set sampling rate and cut-off frequency by call of SetupFilter method. For moving average filter, one has an alternative to define averaging window length instead of defining sampling rate and cut-off frequency. For median filter, this is the only possibility, because for this filter cut-off frequency is not defined. After setting up the filter properties, either call Filter method for off-line filtering of existing data, or initiate filtering in real time. To do so, call InitFiltering once, and then call NextPoint method whenever new datapoint is aquired. Method Filter calls OnInput event when needs a next input value, and OnOutput when it is ready to return a next output value. Similarly, NextPoint calls OnInput and OnOutput when is invoked. This technique with OnInput and OnOutput events makes the components independent of a format of data which are filtered.
Implemented are gaussian filter, moving average filter, which are probably the best “smoothing” filters for time domain, and median filter which is ideal to remove short spikes preserving sharp edges. One-pole high-pass filter, notch filter and Chebyshev filter are implemented in lmRecursFilters unit. All of these filters except Gaussian can be used for both real time and off-line filtering. Gaussian filter requires forward and backward filtering, hence, can be used only off line.
Unit lmRecursFilters
Several components implementing infinite impulse response filters are defined in this unit:
- THighPassFilter
- TNarrowBandFilter
- TNotchFilter
- TBandPassFilter
- TChebyshevFilter
Unit lmCoordSys
TCoordSys component implemented in this unit is relatively simple Cartesian coordinate plane for drawing points, lines, graphical primitives and mathematical functions in user’s coordinates. Component is derived from TPanel, so, you can place other components, for example, scale edits, on top of it.
Usage: place the component on your form, in the Object Inspector define positions of axes, distance between grid lines (in user space) as well as coordinate limits (MinX, MaxX, MinY, MaxY). Define TPen properties which are used for drawing axes, grid lines and user data, as well as numeric format for axis numbering.
For drawing of user’s data define OnDrawData event; all your drawing must occur within it.
Coordinates are converted between user space and screen coordinates with UserToScreen, ScreenToUser, XUserToScreen, YUserToScreen, XScreenToUser and YScreenToUser functions, but you seldom need to call them directly. Procedures PutLine, GoToXY, LineTo, Circle, Aim, FillRect are provided for drawing graphical primitives and data in user’s space. Procedure FastDraw serves for fast drawing of arrays of TPoint sorted for X coordinate; DrawSpline and DrawFunc provide plotting of data and mathematical functions.
Canvas property is published, allowing to define easily own drawing procedures. All drawing of user’s data must occur in OnDrawData event, which is called from Paint procedure.
Unit lmNumericEdits
- TFloatEdit class
Unit lmNumericInputDialogs
- function IntervalQuery
- function FloatInputDialog
Comparision with AlgLib
Q: I'm trying to use some math libraries in my apps. What is the advantage of LMath compared to, for example, ALGLIB (Free Edition)? Maybe it's got something to do with the license or the open source code or what?
A (glorfin): Well, license, yes. Free AlgLib is distributed under strict GPL, while LMath under modified LGPL. Besides, in my view, it is easier to use. At list, when I was not yet supporter of LMath and was choosing between AlgLib and DMath for my own project (Nest-o-Patch, https://sourceforge.net/projects/nestopatch/, I found building DMath much easier, and LMath is organized as set of Lazarus packages, which makes it even more easy. LMath includes some components; I think that filtering components may be most interesting among them. Package MathUtils makes (in my view) easier work with arrays of real numbers.
Having said all that, I don't think, one can say that LMath is better than AlgLib; it is largely question of taste and one's needs. For example, in many cases AlgLib is written in more efficient way and can be preferred for really intensive calculations (though it is also question of testing); procedures in LMath are often easier to understand, exactly because they are not obscured by heavy optimizations.
See also
Comprehensive documentation about LMath and LMComponents in pdf form: