codeplea / tinyexpr

tiny recursive descent expression parser, compiler, and evaluation engine for math expressions
https://codeplea.com/tinyexpr
zlib License
1.6k stars 244 forks source link

Feature Request: Implement ternary evalutation #95

Closed Sercurio closed 1 year ago

Sercurio commented 2 years ago

It would be great to can use the ternary operator in evaluated expression.

Ex: x / 16 ? 1 : 0

Blake-Madden commented 1 year ago

I added an if() ternary function to the C++ fork of tinyexpr. @codeplea, would you like for me to make a PR backporting that?

codeplea commented 1 year ago

@Blake-Madden Thanks, but I think this is a bit out of scope for TinyExpr.

@Sercurio if C++ is ok for your use-case, give @Blake-Madden's code at https://github.com/Blake-Madden/tinyexpr-plusplus a try.

Sercurio commented 1 year ago

I found that C++ is not enough quick for my use case. Can you give me hints on how to implement ternary on this project ?

Does add that kind of switch case to base function will work ?

case TERNOK_COND:
        next_token(s);
        ret = list(s);
        CHECK_NULL(ret);

        if (s->type != TERNOK_TRUE)
        {
            s->type = TOK_ERROR;
        }
        else
        {
            next_token(s);
        }
        break;
    case TERNOK_TRUE:
        next_token(s);
        ret = list(s);
        CHECK_NULL(ret);

        if (s->type != TERNOK_FALSE)
        {
            s->type = TOK_ERROR;
        }
        else
        {
            next_token(s);
        }
        break;

I know there are some fixes to do, but I just want to understand the workflow for this use case who need three "parts" to parse

Thanks !

codeplea commented 1 year ago

You can easily add a function, like if, without changing any internal code.

https://github.com/codeplea/tinyexpr#binding-to-custom-functions

It does have the slight disadvantage that all arguments will be evaluated before the function is called.

codeplea commented 1 year ago

I found that C++ is not enough quick for my use case.

It's doubtful that C++ is the culprit here.

Sercurio commented 1 year ago

You can easily add a function, like if, without changing any internal code.

https://github.com/codeplea/tinyexpr#binding-to-custom-functions

It does have the slight disadvantage that all arguments will be evaluated before the function is called.

I have already do that, but I would like to stick to the bytebeat standard and it's the ternary form of the if that is used...

I found that C++ is not enough quick for my use case.

It's doubtful that C++ is the culprit here.

It's because I'm running the program on a mcu that need to display information on a screen, check for interface inputs, generate sound at 8Khz, after seeing the Black-Madden benchmark it's near 1000% slower, I prefer the quick program...

Blake-Madden commented 1 year ago

You can easily add a function, like if, without changing any internal code. https://github.com/codeplea/tinyexpr#binding-to-custom-functions It does have the slight disadvantage that all arguments will be evaluated before the function is called.

I have already do that, but I would like to stick to the bytebeat standard and it's the ternary form of the if that is used...

I found that C++ is not enough quick for my use case.

It's doubtful that C++ is the culprit here.

It's because I'm running the program on a mcu that need to display information on a screen, check for interface inputs, generate sound at 8Khz, after seeing the Black-Madden benchmark it's near 1000% slower, I prefer the quick program...

I'm my case, the performance problem comes from replacing the union with std::variant. That provides type safety and makes adding functions easier, but comes at a performance cost. I make a note of that on the readme page.

From the benchmark tests, I was seeing tinyexpr++ running at about 50% the performance of tinyexpr (i.e., 100% slower) for the more complex formulas I'm surprised to see something 1,000% slower, but I'd be happy to look at any test formulas you could provide.

Sercurio commented 1 year ago
Capture d’écran 2023-06-01 à 00 29 04

i.e. the speed paragraph of your project

The last row show that complex formulas run about 1000% slower. Moreover, I'm not very comfortable with C++ and doesn't understand it like I understand C that is simpler for me. Your project is very nice Blake-Madden and you helped me a lot ! But I think that the C version of TinyExpr suit more my project !

I have modified tinyexpr with all logical and bitwise operations, the only thing that is missing is the ternary form of the if. But the algorithm is different of the others function because of it's form.

Blake-Madden commented 1 year ago

Oh, I understand. Sorry, I thought you meant 1000% slower than tinyexpr. Yes, tinyexpr++ definitely will be 1000% slower than native C sometimes. Although I do want to revisit that and see if I can optimize a little more.

Totally understand not being comfortable with C++. It certainly has mutated into a very..."interesting"...language in the last few years :)

Good luck with the ternary operator. I would be very curious to see a PR for that here!