varnish-cache icon indicating copy to clipboard operation
varnish-cache copied to clipboard

vmod: Add vmod_math code generator

Open nigoroll opened this issue 3 months ago • 3 comments

3e1a235457965442efecf3eb393aa597ebf476f9 triggered me to spend time on this which I do not have, because I really think that

Notice that DURATION, REAL and TIME are represented as floating point numbers, and hence testing for (in)equality might be unreliable.

should be followed by "and here is what you should do", which is

if (math.abs(x - y) < epsilon)

So I wrote the code generator I had in mind for long.

It is not finished, because macros and constants from math.h would also need to be wrapped.

The code generator takes the opengroup spec html as an input and only has hard coded mappings for c->VCL types and some argument names, where they are not x,y,z.

Before I spend any more time with this: 👍🏽 or 👎🏽 ?

Supersedes #4001

nigoroll avatar Dec 02 '25 12:12 nigoroll

from #4423: Should also add math.approx, if going ahead.

nigoroll avatar Dec 08 '25 14:12 nigoroll

bugwash: go ahead.

nigoroll avatar Dec 08 '25 14:12 nigoroll

Is a vmod_math still relevant for VCL after a deliberate move of the syntax to structured-field numbers that limit REAL, TIME and DURATION literals to three digits below zero?

I was surprised to see no issue ever opened regarding this new limitation. I see this lack of complaints as some sort of litmus test showing that nobody was doing anything more complicated than simple operations in VCL and that nobody ever had a real case for "advanced" math features.

I have no particular opinion on this topic. Proceeding with a vmod_math will either require silly workarounds like 3141593 / 1000000.0 or back-tracking on sf adoption.

For an approximation function, I would rather advocate for a type method if the ~ operator is rejected:

if (beresp.grace.approx(1d)) {
    # ...
}

But my preference would be ~ too.

dridi avatar Dec 08 '25 14:12 dridi

I have pushed a ready-to-merge update. Compared to the draft, the following has been added:

  • math.approx() implementing a notion of "approximately equal" as per Comparing Floating Point Numbers, 2012 Edition

  • math.strfromd() for REAL string formatting without the limitations of the built-in formatter. The main motivation for adding this function at this point is to make the added test case transparent.

  • math.constant() to access REAL constants from math.h and float.h like DBL_EPSILON or M_PI.

  • math.fpclass() to access INT constants from math.h to compare the return value of math.fpclassify() against.

The following is unrelated (or only marginally related) to the PR:

On the side-track re @dridi: Regarding the sf-ification of all things number, I can still see a good argument for consistency, but it has limitations - like the example you gave, because we limit the precision of literals and when formatting, but not inbetween. And that is a good thing, because otherwise we'd get terrible precision even for simple math operations.

At this point, I lean towards suggesting to drop the sf-ification when parsing literals (to avoid the silly cases you rightly pointed out), but keep the %.3f formatting and the range limit as imposed by VRT_REAL_is_valid(). With the addition of math.strfromd(), there would at least be an alternative where required.

nigoroll avatar Dec 20 '25 16:12 nigoroll

bugwash: for math.strfromd(), check if using fmtcheck is a better option.

nigoroll avatar Jan 07 '26 14:01 nigoroll

On fmtcheck: I worked by strfromd(3), which has:

Therefore, unlike snprintf(), the format string does not have a length modifier character.

It's just a minor difference, but IMHO it's pola to follow the standard function.

The argument "if we provide bessel functions, we might as well provide printf" has some merit, but strfromd(3) has a fixed argument, so it's not the same.

nigoroll avatar Jan 07 '26 15:01 nigoroll