I have been reviewing/testing several BigFloat libraries over the last few weeks to see what it would take to add support for this to the scripting language.

A BigFloat library needs to meet several criteria: compile under Visual C++ 2008, use a BSD/MIT/similar license, support logarithmic/trigonometric/etc. functions, have a C++ wrapper, be stable/tested, and so on. This really narrows down the options. After looking through a large number of libraries (including Boost, APFloat, LibBF, and many more), compiling and testing them (many needed code changes before they would compile), I whittled down the options to TTMath and MAPM.

TTMath is not arbitrary precision. The required precision is set at compile time. It is thread-safe. I set it to use Big<2,4> floats to allow a 128bit number for the Mantissa. The larger the <E,M>, the slower it gets, so this was a practical choice and provides support for reasonably large numbers and precision. In my script unit tests, which repeatedly call a variety of commands and identifiers such as /set/inc/dec/$calc()/$base()/math/trig/log/etc. functions, it is at least four times slower than normal calculations - slower depending on the type of call. For Big<4,8>, it is eight times slower.

MAPM is arbitrary precision. It is old and well-tested. It has both thread/non-thread safe calls. mIRC currently uses the non-thread-safe calls as it is not used in any multi-thread contexts. By chance, I found an updated version at https://github.com/achan001/MAPM-5. It compiles easily and has a C++ wrapper and supports all of the necessary functions. The only major issue is that on an out-of-memory error, MAPM immediately exits() the application with no freeing/unwinding/error reporting. I made several attempts to update it to unwind and report errors correctly in a thread-safe way but this snowballed into hundreds of code changes. In the end, I tried a different approach and made as few changes to the MAPM code as possible to allow it to unwind safely, free memory where necessary, and to set a non-thread-safe global error flag. Not ideal but a step in the right direction. In my script unit tests, it is two times slower than normal calculations and gets gradually slower as the numbers you use increase in size.

The latest beta uses the MAPM library.

To support bigfloats, inline branching code and overloaded functions were added that duplicate, line for line, the existing, unchanged non-bigfloat code. The following were updated:

/var /set /inc /dec /hinc /hdec /if /while
$base() $calc() $isnum() $rand()
$abs() $ceil() $floor() $int() $min() max() $rand() $round()
$acos() $asin() $atan() $atan2() $cos() $cosh() $hypot()
$log() $log10() $sin() $sinh() $tan() $tanh() $sqrt()

Bigfloat can be enabled in two ways:

First, by using the /bigfloat [on|off] command to enable it for a script locally. It will remain enabled until the script exits.

Second, by using a %var that ends in .bf, ie. %var.bf. This naming convention allows vars to be recognized as bigfloats in the scripting language both visually and internally. The parser enables the bigfloat state the moment it comes across a %var.bf and only for the command in which it is found.

The bigfloat state is propagated forward through called commands/identifiers.

A script can use $bigfloat to check if bigfloat is enabled or not.

This feature is still at the experimental stage, so will need testing. Please let me know if you spot any issues.