Conversation
Replaces unsafe usages of const void* with appropriate pointer types for data and functions, making the code maximum portable, safe, and easier to maintain. Detail: Some compilers does not allow casting between data and function pointers, even void* (pointers may have different sizes). Library now compilable both in c11 and c++20. Useful if you need to customize the code with a c++ allocator or use it in projects where c++ source code is required. Broadens usability of the library. For c++, the PR forces the correct overloaded math functions to be picked during function pointer assignments and comparisons, e.g. like pow and fmod. Simplifies casting code in te_eval() by adding a few macros, can extend number of function parameters cleanly.
… cbrt(), log2(), gcd() math functions. Removed ln(): now log(), log2() and log10().
|
Great, I'm looking forward to a C++11 / C++20 compatible tinyexpr! This could make the compilation environment a little easier when integrating tinexpr in a C++11 project (ie no need to check on multiple platforms and compilers that this one file will be compiled as c99 vs the other ones as c++11). |
SirNate0
left a comment
There was a problem hiding this comment.
A few comments. I care less about the ** instead of ^, but I think the changes to use separate function pointer types should be completed to allow up to 7 arguments if that route is preferred. Though at that point I think the closure types should also be broken out, as that would have a separate type with the void* for the context.
| typedef struct te_variable { | ||
| const char *name; | ||
| const void *address; | ||
| union {const double *address; te_fun0 fun0; te_fun1 fun1; te_fun2 fun2;}; |
There was a problem hiding this comment.
If you are splitting the address out into different specific function types, why not include all the way up to 7 arguments? And if not, why not just leave it as is with a single void* function and cast for all of them? Currently, I don't think the tinyexpr code uses any functions with more than 2 arguments, but a simple and relatively common example would be a linear interpolation (lerp) function, or an if function like excel's if(condition,then,else).
| int err; | ||
| /* Compile the expression with variables. */ | ||
| te_expr *expr = te_compile("sqrt(x^2+y^2)", vars, 2, &err); | ||
| te_expr *expr = te_compile("sqrt(x**2+y**2)", vars, 2, &err); |
There was a problem hiding this comment.
Why the change to ** from ^? I don't necessarily oppose it, using Python frequently myself, but it's certainly not a mathematical standard practice (Mathematica, Matlab).
| <expr> = <term> {("+" | "-") <term>} | ||
| <term> = <factor> {("*" | "/" | "%") <factor>} | ||
| <factor> = <power> {"^" <power>} | ||
| <factor> = <power> {"*\*" <power>} |
There was a problem hiding this comment.
Rather than having "*\*" in the markdown, it might make more since to wrap the section in a code block, if that was the reason to use *\* instead of **.
Replaces unsafe usages of const void* with appropriate pointer types for data and functions, making the code maximum portable, safe, and easier to maintain. Detail: Some compilers does not allow casting between data and function pointers, even void* (pointers may have different sizes).
Library now compilable both in c11 and c++20. Useful if you need to customize the code with a c++ allocator or use it in projects where c++ source code is required. Broadens usability of the library.
Note that it is only unnamed structs that requires C11, but unnamed structs are supported on every C99 compiler that I know of (including MSVC which isn't even C99 compliant).
For c++, the PR forces the correct overloaded math functions to be picked during function pointer assignments and comparisons, e.g. like pow and fmod.
Simplifies casting code in te_eval() by adding a few macros, can extend number of function parameters cleanly.