数式パーサーライブラリ ExprTk (C++)

# ExprTk
ExprTkはC++の数式パーサーライブラリ(MIT License)です。昨日，その存在を知りました。

https://www.partow.net/programming/exprtk/index.html

# 四則演算のサンプルコード
例えば，2つのバイナリファイルを変数x,yとして，（ExprTkのビルトイン機能の範囲で）x,yを含む任意の数式を評価し，評価結果をバイナルファイルに出力するコードはこんな感じになります。Copilotに書いてもらって，ほんの少し修正しました。

```cpp:array_calc.cpp
#include <iostream>
#include <fstream>
#include <string>
#include "exprtk.hpp"

// Define the expression parser
typedef float T;
typedef exprtk::symbol_table<T> symbol_table_t;
typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t;

int main(int argc, char* argv[])
{
    if (argc != 5)
    {
        std::cerr << "Example usage: " << argv[0] << " file_x.bin file_y.bin \"x+y\" result.bin" << std::endl;
        return 1;
    }

    // Parse command line arguments
    std::string expr_str = argv[3];
    std::string output_file = argv[4];

    // Load binary files
    std::ifstream file_x(argv[1], std::ios::binary);
    std::ifstream file_y(argv[2], std::ios::binary);
    std::ofstream result_file(output_file, std::ios::binary);

    if (!file_x || !file_y || !result_file)
    {
        std::cerr << "Error: opening files." << std::endl;
        return 1;
    }

    // Create expression parser
    symbol_table_t symbol_table;
    T x_val, y_val;
    symbol_table.add_variable("x", x_val);
    symbol_table.add_variable("y", y_val);

    expression_t expression;
    expression.register_symbol_table(symbol_table);

    parser_t parser;
    if (parser.compile(expr_str, expression) == false)
    {
        std::cerr << "Error: compiling expression." << std::endl;
        return 1;
    }

    // Evaluate expression for each pair of values
    while (file_x.read(reinterpret_cast<char*>(&x_val), sizeof(T)) &&
           file_y.read(reinterpret_cast<char*>(&y_val), sizeof(T)))
    {
        T result = expression.value();

        result_file.write(reinterpret_cast<const char*>(&result), sizeof(T));
    }

    std::cout << "Calculation completed. Results written to " << output_file << std::endl;

    return 0;
}
```

"開発者コマンド プロンプト for VS2015"を立ち上げて，こちらのコマンドでビルドしました。
```:ビルドコマンド
cl.exe array_calc.cpp /O2 /EHsc /bigobj
```

# 四則演算してみた
試しに，2つのfloat型のバイナリファイル(要素数200×200の画像)の四則演算をしてみました。
```:実行コマンド
array_calc.exe image1.bin image2.bin "x+y" result_add.bin
array_calc.exe image1.bin image2.bin "x-y" result_sub.bin
array_calc.exe image1.bin image2.bin "x*y" result_mul.bin
array_calc.exe image1.bin image2.bin "(y>0)?(x/y):0" result_div.bin
```
三項演算子(?:)も普通に使えます。


| image1.bin | image2.bin |
|---|---|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440702/a75562ab-113f-5ca8-29d8-70650596b084.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440702/35a1a404-a358-57b0-4200-f32c91842326.png)|

| result_add.bin | result_sub.bin |
|---|---|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440702/ab1c0c68-f5da-f44a-1a4f-900bd31ba6cd.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440702/ff3fd853-3942-b01f-95cf-78f4dcd2d3f7.png)|

| result_mul.bin | result_div.bin |
|---|---|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440702/fadea586-472b-7da6-e534-5f14f37f69b9.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440702/4ad445f4-e520-1c05-5cba-d22d422c5f12.png)|

いずれも正しく計算されていました（ImageJでの計算結果と比較）。この程度の要素数であれば，計算も瞬殺した。


# ビルトインされている演算子や関数など

何というか，フツーに思いつく演算子や関数はひと通り組み込まれている感じです。
本家サイトにも一覧表示されていますが，こちらのリポジトリの方が見やすいかも。

https://github.com/ArashPartow/exprtk

本家サイトの[計算例](https://www.partow.net/programming/exprtk/index.html#examples)を見ると，単純な四則演算だけでなく，数式というよりコードに近いものも書けて，フィルタ処理や離散フーリエ変換なども実行できるようで，かなり汎用的です。


# 最後に
名だたる企業がフツーに使っているようです。
["ExprTk" "数式"](https://www.google.com/search?q=%22ExprTk%22+%22%E6%95%B0%E5%BC%8F%22&oq=%22ExprTk%22+%22%E6%95%B0%E5%BC%8F%22) でググっても，まともな日本語サイトは２件しかヒットしないけど。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440702/f8771608-d78f-1183-e7f5-36fb9bc718e1.png)

以上