Calculation Modes
Calculation modes control how exactly a given calculation is performed. The following methods of calculation are used for mathematical operations, and the calculation mode allows you to control which methods are considered.
- The
BCMath
extension orDecimal
extension, which operate on real numbers of arbitrary precision. - The
GMP
extension, which operates on integers. - The
PHP engine
math functions and operations, which work with both integers and floats, and provide a variable amount of precision up to about 12 decimal places.
The default calculation mode is CalcMode::Auto
, which attempts to intelligently select the most computationally efficient mode given the precision needed.
Available Modes
The mode for a given operation is determined from two sources. First, the calculation mode on the value object calling the method is checked. If the calculation mode on the value object is null
, (which is the default value), then the global calculation mode currently set on the CalculationModeProvider
is checked.
The default calculation mode is CalcMode::Auto
, which will contextually use all calculation methods based on the runtime values of the objects in question.
Value-Specific Calculation Modes Persist
If a calculation mode is set for a value object using the setMode()
method, all objects resulting from that calculation will inherit the same mode instead of have the default null
value.
In general this is prefferable and reduces unexpected bugs, however this means that once a value-specific calculation mode is set, all values derived from it will no longer be affected by the global calculation mode.
Auto
The CalcMode::Auto
mode will utilize all available calculation tools in an attempt to provide the most speed possible without compromising the requested scale.
Each mathematical operation may have its own criteria for deciding which calculation method to use, however the general logic of this mode is as follows:
- If all the inputs and outputs of a given calculation can be expected to be integers, the
GMP
functions are used. - If
GMP
cannot be used, the inputs are then checked against the requested scale for the density of native float values. If it can be expected that native floats have enough density to provide the requested scale, then the nativePHP engine
math operations are used. - If neither
GMP
nor thePHP engine
can be used, then the fastest arbitrary precision operation available in your installation is used. For most PHP installations, this will be theBCMath
extension. However, if it is installed then theDecimal
extension is preferred as it is much, much faster.
Precision Mode
In this mode, the best available string math implementation is used when a mathematical operation is performed. By default, these are the functions provided by the BCMath
extension, however a future scope of this project is to provide integration with ext-decimal
.
Native Mode
In this mode, the native PHP engine
math operators are used for calculation. The result is then converted to a string and stored according to the normal behavior of the class in question.
Loss Of Scale
The scale defined in the object is ignored when this mode is used. This will result in values which behave as math operations in PHP would natively, including issues such as overflow and underflow.
Better Performance In Low Scale Situations
As a trade-off for accepting more ambiguous scale in the result, using this mode will decrease the computation required for basic math operations, in some cases quite significantly. If you are absolutely certain that your math will not result in an overflow or underflow, and your application is not sensitive to loss of scale in float
values, using this mode will reduce the cost of each mathematical operation.
Expanding Native Types
With the mode set to native, this library functions as simply an extension to integer and float types that enables representations of imaginary numbers, complex numbers, matrices, coordinates, and statistics. In this way, the library may be useful even if arbitrary scale is not necessary for your application.
Controlling the Mode of Objects
There are two main ways of controlling the mode used by your Fermat objects. The first is through the use of the default mode, and the second is with the use of the setMode()
method.
Default Mode
The mode currently returned by CalculationModeProvider
is used by default for all classes that extend the Number
abstract class. This mode at application start is CalcMode::Auto
, but can be changed at any time using CalculationModeProvider::setCurrentMode()
.
Set Mode
The setMode()
method is available on all classes that extend the Number
abstract class. It sets the mode of the object it is called on to the mode provided.
This setting will null
by default, allowing the object to use the default mode described above. If this is used to set a specific mode on an object, the default mode will be ignored, and the specific mode set will cascade to any objects that object creates through calculations.
Use Only Defined Modes
While setMode()
will accept any integer, you should only ever use inputs that are defined on the CalcMode
enum to avoid unexpected behaviors.
This Method Is Mutable For All Objects
Because of the nature of what this method does, it is mutable for all objects, including any implementations of immutable objects.