Skip to content

Commit 4068a09

Browse files
committed
vmod: Add vmod_math
This adds the following functions: - math.approx() implementing a notion of "approximately equal" as per the reference in the documentation and source code - 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. - functions for all math.h functions and function-like macros like sqrt(), exp() or log(). This uses a python code generator vmod_math_gen.py to extract most of the definitions from the opengroup specification for all the math.h functions and function-like macros and to generate math.constant() and math.fpclass(). The specification document vmod_math_spec.html is deliberately checked in and added to the distribution to avoid curl running for a normal build. As with other generated code, the generated files vmod_math.c and vmod_math.vcc are also added to the dist, but not to git in order to update them for developer builds based on potential changes to vmod_math_gen.py, but to not run the generator for builds from a distribution.
1 parent b5e00bd commit 4068a09

File tree

12 files changed

+1319
-1
lines changed

12 files changed

+1319
-1
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ cscope.*out
8181
/vmod/vcc_*_if.h
8282
/vmod/vmod_*.rst
8383
/vmod/vmod_vcs_version.txt
84+
/vmod/vmod_math.vcc
85+
/vmod/vmod_math.c
8486

8587
# Man-files and binaries
8688
/man/*.1

doc/changes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ Vinyl-Cache NEXT (2026-03-15)
4141
.. PLEASE keep this roughly in commit order as shown by git-log / tig
4242
(new to old)
4343
44+
* Added vmod ``math``.
45+
4446
.. _4389: https://github.com/varnishcache/varnish-cache/issues/4389
4547

4648
* ``req.ttl`` has been renamed to ``req.max_age`` for clarity, with ``req.ttl``

doc/sphinx/Makefile.am

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,10 @@ include/vmod_proxy.generated.rst: $(top_builddir)/vmod/vmod_proxy.rst
206206
cp $(top_builddir)/vmod/vmod_proxy.rst $@
207207
BUILT_SOURCES += include/vmod_proxy.generated.rst
208208

209+
include/vmod_math.generated.rst: $(top_builddir)/vmod/vmod_math.rst
210+
cp $(top_builddir)/vmod/vmod_math.rst $@
211+
BUILT_SOURCES += include/vmod_math.generated.rst
212+
209213
EXTRA_DIST += $(BUILT_SOURCES)
210214
CLEANFILES = $(BUILT_SOURCES)
211215

doc/sphinx/reference/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ Bundled VMODs
3737
vmod_cookie.rst
3838
vmod_directors.rst
3939
vmod_h2.rst
40+
vmod_math.rst
4041
vmod_proxy.rst
4142
vmod_purge.rst
4243
vmod_std.rst

doc/sphinx/reference/vmod_math.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
..
2+
Copyright (c) 2019 Varnish Software AS
3+
SPDX-License-Identifier: BSD-2-Clause
4+
See LICENSE file for full text of license
5+
6+
7+
.. include:: ../include/vmod_math.generated.rst

man/Makefile.am

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ dist_man_MANS = \
2727
vmod_blob.3 \
2828
vmod_unix.3 \
2929
vmod_proxy.3 \
30-
vmod_h2.3
30+
vmod_h2.3 \
31+
vmod_math.3
3132

3233
CLEANFILES = $(dist_man_MANS)
3334

@@ -146,4 +147,8 @@ vmod_proxy.3: $(top_builddir)/vmod/vmod_proxy.man.rst
146147
vmod_h2.3: $(top_builddir)/vmod/vmod_h2.man.rst
147148
$(BUILD_MAN) $? $@
148149

150+
vmod_math.3: $(top_builddir)/vmod/vmod_math.man.rst
151+
$(BUILD_MAN) $? $@
152+
153+
149154
.NOPATH: $(dist_man_MANS)

vmod/Makefile.am

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ include $(srcdir)/automake_boilerplate_h2.am
3333
include $(srcdir)/automake_boilerplate_cookie.am
3434
include $(srcdir)/automake_boilerplate_debug.am
3535
include $(srcdir)/automake_boilerplate_directors.am
36+
include $(srcdir)/automake_boilerplate_math.am
3637
include $(srcdir)/automake_boilerplate_proxy.am
3738
include $(srcdir)/automake_boilerplate_purge.am
3839
include $(srcdir)/automake_boilerplate_std.am
@@ -55,3 +56,17 @@ vmod_debug_symbols_regex = 'Vmod_.*_Data'
5556

5657
# not --strict, not installed
5758
vmodtoolargs_debug = --boilerplate --noinst -o vcc_debug_if
59+
60+
### vmod_math specific
61+
# the specs are deliberately checked in to not make the build
62+
# dependend on external connectivity
63+
vmod_math_spec.html:
64+
curl -o $@ https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/math.h.html
65+
66+
vmod_math.c: vmod_math.vcc
67+
68+
vmod_math.vcc: vmod_math_spec.html vmod_math_gen.py
69+
@PYTHON@ $(srcdir)/vmod_math_gen.py $< vmod_math.vcc vmod_math.c
70+
71+
# avoid running curl when building from a dist
72+
dist_noinst_SCRIPTS = vmod_math_gen.py vmod_math_spec.html

vmod/automake_boilerplate_math.am

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
## Generated by vmodtool.py --boilerplate.
2+
3+
vmod_LTLIBRARIES += libvmod_math.la
4+
dist_vcc_DATA += $(srcdir)/vmod_math.vcc
5+
6+
libvmod_math_la_SOURCES = \
7+
vmod_math.c \
8+
vmod_math_util.c
9+
10+
libvmod_math_la_CFLAGS =
11+
12+
vmodtoolargs_math ?= --strict --boilerplate -o vcc_math_if
13+
vmod_math_symbols_regex ?= Vmod_math_Data
14+
15+
libvmod_math_la_LDFLAGS = \
16+
-export-symbols-regex $(vmod_math_symbols_regex) \
17+
$(AM_LDFLAGS) \
18+
$(VMOD_LDFLAGS) \
19+
-rpath $(vmoddir)
20+
21+
nodist_libvmod_math_la_SOURCES = vcc_math_if.c vcc_math_if.h
22+
23+
EXTRA_libvmod_math_la_DEPENDENCIES = $(nodist_libvmod_math_la_SOURCES)
24+
25+
EXTRA_DIST += automake_boilerplate_math.am
26+
27+
$(libvmod_math_la_OBJECTS): vcc_math_if.h
28+
29+
vcc_math_if.h vmod_math.rst vmod_math.man.rst: vcc_math_if.c
30+
31+
# A doc-change will not update mtime on the .h and .c files, so a
32+
# touch(1) is necessary to signal that vmodtool was in fact run.
33+
vcc_math_if.c: $(VMODTOOL) $(srcdir)/vmod_math.vcc
34+
@PYTHON@ $(VMODTOOL) $(vmodtoolargs_math) $(srcdir)/vmod_math.vcc
35+
touch vcc_math_if.c
36+
37+
clean-local: clean-vmod-math
38+
39+
clean-vmod-math:
40+
rm -f $(nodist_libvmod_math_la_SOURCES)
41+
rm -f vmod_math.rst vmod_math.man.rst

vmod/tests/math_b00000.vtc

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
varnishtest vmod_math
2+
3+
varnish v1 -vcl {
4+
import math;
5+
6+
backend proforma none;
7+
8+
sub vcl_recv {
9+
return (synth(200));
10+
}
11+
12+
sub vcl_synth {
13+
if (req.http.strfromdfmt) {
14+
set resp.http.result = math.strfromd(req.http.strfromdfmt, math.constant(M_PI));
15+
return (deliver);
16+
}
17+
18+
# formatting basics
19+
set resp.http."n.v" = 0.1;
20+
set resp.http."n.13a" = math.strfromd("%.13a", 0.1);
21+
set resp.http."n.17e" = math.strfromd("%.17e", 0.1);
22+
set resp.http."n.17f" = math.strfromd("%.17f", 0.1);
23+
set resp.http."n.g" = math.strfromd("%g", 0.1);
24+
25+
# edge cases where approx makes a difference
26+
27+
set resp.http."sinpi.v" = math.sin(math.constant(M_PI));
28+
set resp.http."sinpi.17f" = math.strfromd("%.17f", math.sin(math.constant(M_PI)));
29+
set resp.http."sinpi.0.equals" = math.sin(math.constant(M_PI)) == 0.0;
30+
set resp.http."sinpi.0.approx" = math.approx(math.sin(math.constant(M_PI)), 0);
31+
set resp.http."sinpi.0.zero" =
32+
math.fpclassify(math.sin(math.constant(M_PI))) ==
33+
math.fpclass(FP_ZERO);
34+
35+
# VRT_DECIMAL_MAX == 0x426d1a94a1fffff8
36+
set resp.http."some1.v" = 999999999999 + 0.999;
37+
set resp.http."some1.f" = math.strfromd("%f", 999999999999 + 0.999);
38+
# VRT_DECIMAL_MAX - ULP == 0x426d1a94a1fffff7
39+
set resp.http."some2.v" = 999999999999 + (9.989 / 10);
40+
set resp.http."some2.f" = math.strfromd("%f", 999999999999 + (9.989 / 10));
41+
42+
set resp.http."some1.some2.equals" =
43+
(999999999999 + 0.999) == (999999999999 + (9.989 / 10));
44+
set resp.http."some1.some2.approx" =
45+
math.approx(999999999999 + 0.999, 999999999999 + (9.989 / 10));
46+
47+
return (deliver);
48+
}
49+
} -start
50+
51+
client c1 {
52+
txreq
53+
rxresp
54+
expect resp.status == 200
55+
56+
expect resp.http.n.v == 0.100
57+
expect resp.http.n.13a == 0x1.999999999999ap-4
58+
expect resp.http.n.17e == 1.00000000000000006e-01
59+
expect resp.http.n.17f == 0.10000000000000001
60+
expect resp.http.n.g == 0.1
61+
62+
expect resp.http.sinpi.v == 0.000
63+
expect resp.http.sinpi.17f == 0.00000000000000012
64+
expect resp.http.sinpi.0.equals == false
65+
expect resp.http.sinpi.0.approx == true
66+
expect resp.http.sinpi.0.zero == false
67+
68+
expect resp.http.some1.v == 999999999999.999
69+
expect resp.http.some1.f == 999999999999.999023
70+
expect resp.http.some2.v == 999999999999.999
71+
expect resp.http.some2.f == 999999999999.998901
72+
expect resp.http.some1.some2.equals == false
73+
expect resp.http.some1.some2.approx == true
74+
75+
txreq -hdr "strfromdfmt: %5f"
76+
rxresp
77+
expect resp.status == 500
78+
} -run

0 commit comments

Comments
 (0)