Code Monkey home page Code Monkey logo

picomath's Introduction

PicoMath

PicoMath is a header-only C++ library for math expression evaluation. PicoMath is very fast, simple, and customizable.

PicoMath was created to evaluate CSS-like expressions, like "100% - 20px", in the UI layout engine of my 2D game engine, Shinobit Engine. The main design goal of the library is to evaluate the expressions one single time as fast as possible, as layout usually happens when a scene is loaded, or a new UI component is shown, but they are not usually evaluated every frame. Another goal was to make the library as simple as possible, the engine is compiled to WASM and size of the binary matters.

This library is currently used in the MMO browser game GoBattle.io

Build status

Features

  • Header only C++ library: easy integration in your project
  • Very simple and fast
  • Zero allocations in the hot path
    • Uses C++17 std::string_view to lookup variables without copying strings
  • Single pass: The evaluation is performed while parsing.
  • Built-in math functions (e.g. cos(pi))
  • Custom units and percentages (e.g 100% - 10px)
  • User defined variables (e.g. (x + y) * (x + y))
  • User defined functions with multiple arguments (e.g. avg(10, 20, 30))
  • Uses standard C++ containers

How to integrate in your project

Just copy the file /include/picomath.hpp in your project

Usage

Simple evaluation:

#include <picomath.hpp>

using namespace picomath;

PicoMath pm;

auto result = pm.evalExpression("sqrt(100 - 20)");
if (result.isOk()) {
    double r = result.getResult();
    ...
}

Using variables:

#include <picomath.hpp>

using namespace picomath;

PicoMath pm;
auto &x = pm.addVariable("x");

x = 0.0;
while (x < 100.0) {
    // Same expression evaluated with different values of `x`
    auto result = pm.evalExpression("x * x * x");
    if (result.isOk()) {
        double r = result.getResult();
        ...
    }
    x += 1.0;
}

Using units:

#include <picomath.hpp>

using namespace picomath;

PicoMath pm;
pm.addUnit("km") = 1000.0;
pm.addUnit("cm") = 0.01;

auto result = pm.evalExpression("0.5km + 20cm");
if (result.isOk()) {
    double r = result.getResult();
    ...
}

Test

# build test binaries
make

# run tests
make test

# run bench tests
make bench

The default test binaries will be built in release mode. You can make Debug test binaries as well:

make clean
make debug
make test

Benchmarks

PicoMath is pretty fast as it evaluates the expression without allocating memory. Compared to a basic strtolower of the string (2 + 2) * 4 / 10 - 20.02, using the method

std::transform(data.begin(), data.end(), data.begin(), [](unsigned char c) { return std::tolower(c); }));

the evaluation of the same string takes only around 25% more time. Please run the benchmark in your machine to validate the results.

Run on (12 X 2900 MHz CPU s)
CPU Caches:
  L1 Data 32K (x6)  
  L1 Instruction 32K (x6)
  L2 Unified 262K (x6)
  L3 Unified 12582K (x1)
----------------------------------------------------------
Benchmark                   Time           CPU Iterations
----------------------------------------------------------
Baseline tolower           43 ns         43 ns   16254876
Simple expression          54 ns         54 ns   12960515

PicoMath was designed to evaluate a expression in one pass, so to reevaluate the same expression requires parsing again the expression.

Some other libraries use bytecode or ASTs to improve the runtime cost of multiple evaluations of the same expression, but that increases complexity, size and number of allocations. In my tests comparing PicoMath to TinyExpr, you need to evaluate at least three times the same expression to get some benefit of the extra steps.

Contributing and License

Contributors are welcome! โœจ please see CONTRIBUTING for more info.

PicoMath is licensed under a BSD 3-Clause license, see LICENSE for more info.

Please let me know if you use the library in other projects and I can add the link in the readme.

Attribution

This repository was created using the HPP-SKEL repository: https://github.com/mapbox/hpp-skel

picomath's People

Contributors

nitrillo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.