A Brief History of dotMath
The initial design of .Math came about in 1997 with a need to create a function evaluator in C++. After looking around for commercial libraries, the pieces available generally reached a complexity we weren’t requiring and too expensive. We had a need for fairly simple equations (such as 4x^2 2
x 24) where we would perform a wide range of values for x and evaluate each one. I went back to my college compiler books, read up on the subject and decided I could handle the problem myself. I decided to expose the variables thorough an interface and allow them to be discovered and set. At this point the code supported a minimal set of trig-functions. This implementation ran approximately 75,000 calculations per second on a Pentium 2 450.
Creating the Compiler
I used similar implementations on other projects and contemplated createing a ‘true’ compiler. The speed increase would be significant, but never significant enough to warrant the time spent. Then, in 2000, I decided to go ahead tackle the problem. It became apparent I could make this into a nice O-O based structure with the implementation classes compiled in C++ and instantiated as-needed. This structure gave me the opportunity to make the compiler extensible by registering new functions with the framework. Given the O-O framework, the first two-passes are handled by the code, while the linking was handled during the application compile. It’s a different way of looking at the compilation problem, but much simpler in terms of building and delivering the solution. I took this implementation and ported it to an early Visual Basic.NET implementation to test how the new language O-O features behaved.
Multi-Parameter Functions and Binary Operators
Shortly after creating the compiler, the need for more complex functions arose. These functions were modeled after the Excel format with comma-separators. I quickly realized that each function within the statement could be handled as a separate compiled function that shared the same variable space with the rest of the equation. At that point, the implementation became very simple. The most intriguing function then became the If-statement as such:
if( condition, then-result, else-result )
The if-statement required the use of binary operators (<, >, <=, <>, etc). The binary operation returns a 1 for true or a 0 for false. The if statement only tests for 0 equality – perform else portion if 0, otherwise perform then portion.
Porting to C# and the .NET Platform
I ported the code to C# in 2003 out of interest in reviving the code. I later used the project in 2004 to provide dimensionality support to a planning application.
There are a number of directions the code can take, including code optimization and levelization of the called objects. Levelization offers the biggest payback because the current implementation relies heavily on the call-stack. Getting away from the call-stack will remove the reliance on the memory allocations and jumps that become significant when doing millions of operations. I believe levelization of the function calls would involve using an accumulator structure for storing operation values one at a time.