Skip to content

Getting started

Patrick Gleeson edited this page Apr 12, 2021 · 5 revisions

Getting started with MathicallJS

MathicallJS provides fast maths for applications such as simulation and data processing.

If you haven't done so already, read the README for important information about how to load MathicallJS. The README also contains useful background information, including the purpose of the project.

Contents

Fundamentals
Contributing
Examples

Fundamentals

MathicallJS is based around the following core concepts:

Data

Mathematical objects in MathicallJS are represented using Numbers, Arrays or TypedArrays, taking advantage of their inbuilt speed. More importantly, this approach is as flexible as possible; for example, the literal [0, 2] may represent a vector, complex number or array, and is not restricted to being a MathicallJS-specific class instance.

Multidimensional data, such as matrices, are also represented as a single array; this is known as being flattened. A flattened array like [2, 3, 6, 1] uses considerably less memory than its nested counterpart [ [2, 3], [6, 1] ], and can be stored in a TypedArray, which is also much faster. Functions accept either Arrays or TypedArrays, but will output TypedArrays by defualt.

Function-oriented

MathicallJS is function-oriented, meaning functions are called on data instead of by data. For example, the dot product of vectors vec1 and vec2 is vector.dot(vec1, vec2). This works well when using inbuilt data types, and is easy to keep consistent across the entire library. Also, just as an object-oriented library may have different classes for 2D, 3D and 4D vectors, MathicallJS functions often have optimised versions for common data sizes - for example, dot2, dot3 and dot4.

Library structure

MathicallJS is divided into sublibraries, which group functions according to their usage and how they interpret arraylike data. Each sublibrary may also have its own sublibraries, forming a sublibrary chain. For example, the complex sublibrary interprets arrays as complex numbers, and has its own polar sublibrary for working with polar form. Each sublibrary is accessed as a property of the previous, giving us Mathicall.complex.polar.cmult([2,0.57], [3, -1.7]) //[6, -1.13].

Although wordy, the sublibrary chain is great for organisation, especially when different funtions have the same name in different contexts. For example, standard.min(a, b) returns the minimum of two numbers, while array.min(arr) returns the minimum of an array. We can cache functions at the start of a program to avoid being verbose later on:

const vectorRect = Mathicall.vector.rect;
const dot = vectorRect.dot;
const smult = vectorRect.smult;

let myNum = dot([2, 3], [-0.5, 0.1]); //-0.7
let myVec = [4, 5];
let newVec = smult(myVec, myNum); //[-2.8, -3.5]

A more detailed description of the library structure, intended for developers, will be available in the upcoming Developer guide.

Debugging

This feature is incomplete

As a general rule, debug checks are both invaluable and slow. To provide the benefits of errors and warnings during development without hindering the performance of working code, MathicallJS separates debugging into debug mode, used by inserting debug at the end of the sublibrary chain. For example, vector.rect.dot([2, 2], [3, 3]) becomes vector.rect.debug.dot([2, 2], [3, 3]).

debug calls the original function with additional checks for invalid input or output, and throws an error or warning if needed. When used outside of debug mode, MathicallJS functions will assume that they are being used correctly. Invalid input will cause undefined behaviour, which may mean throwing an error, breaking silently, or even working fine. When used in debug mode, this invalid input is handled properly.

Common optional parameters

MathicallJS tries to be minimal with the parameters that functions require - anything not needed to produce a correct result will be taken care of automatically. However, providing a bit of extra information about the input or desired output can speed up computation, reduce memory usage and help MathicallJS integrate better into an existing environment. Here are some common optional parameters:

  • target | Since creating new arrays is expensive, you can often pass functions an existing array where the output will be stored. This is especially useful if you would like to overwrite an input array with the output, or in for-loops where a single output array can be reused in every iteration.

  • sorted | Computations on larger arrays can be much, much faster if we know that the array is sorted. Passing sorted=true into a function lets MathicallJS make use of this information. It doesn't matter whether the input is ascending or descending.

Contributing

If you're interested in contributing to MathicallJS, read CONTRIBUTING.

Examples

Very simple examples are available in the API documentation.