varnish-cache/vmod/vmod_math_util.c
0
/*-
1
 * Copyright 2025 UPLEX - Nils Goroll Systemoptimierung
2
 * All rights reserved.
3
 *
4
 * Author: Nils Goroll <slink@uplex.de>
5
 *
6
 * Includes code by Bruce Dawson
7
 *
8
 * SPDX-License-Identifier: BSD-2-Clause
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
23
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
 * SUCH DAMAGE.
30
 */
31
32
#include "config.h"
33
34
#include <float.h>
35
#include <math.h>
36
37
#include "cache/cache.h"
38
#include "vcc_math_if.h"
39
40
// macros in math.h code are generic-ish across float/double/long double
41
//lint --e{506} Constant value Boolean
42
//lint --e{736} Loss of precision
43
44
/*
45
 * this is AlmostEqualRelativeAndAbs() by Bruce Dawson
46
 * https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
47
 */
48
VCL_BOOL
49 80
vmod_approx(VRT_CTX, VCL_REAL a, VCL_REAL b, VCL_REAL maxDiff, VCL_REAL maxRelDiff)
50
{
51 80
        (void)ctx;
52
53 80
        if (fpclassify(maxDiff) == FP_ZERO)
54 80
                maxDiff = 4 * DBL_EPSILON;
55
56 80
        if (fpclassify(maxRelDiff) == FP_ZERO)
57 80
                maxRelDiff = DBL_EPSILON;
58
59 80
        VCL_REAL diff = fabs(a - b);
60 80
        if (diff <= maxDiff)
61 40
                return (1);
62
63 40
        a = fabs(a);
64 40
        b = fabs(b);
65 40
        VCL_REAL largest = (b > a) ? b : a;
66
67 40
        if (diff <= largest * maxRelDiff)
68 40
                return (1);
69
70 0
        return (0);
71 80
}
72
73
static int
74 320
valid_fmt(VCL_STRING fmt)
75
{
76 320
        if (fmt == NULL || *fmt != '%')
77 0
                return (0);
78 320
        fmt++;
79 320
        if (*fmt == '.') {
80 160
                fmt++;
81 480
                while (*fmt >= '0' && *fmt <= '9')
82 320
                        fmt++;
83 160
        }
84 320
        switch (*fmt) {
85
        case 'a':
86
        case 'A':
87
        case 'e':
88
        case 'E':
89
        case 'f':
90
        case 'F':
91
        case 'g':
92
        case 'G':
93 280
                return (1);
94
        default:
95 40
                return (0);
96
        }
97 320
}
98
99
VCL_STRING
100 320
vmod_strfromd(VRT_CTX, VCL_STRING fmt, VCL_REAL fp)
101
{
102 320
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
103
104 320
        if (! valid_fmt(fmt)) {
105 80
                VRT_fail(ctx, "math.strfromd(\"%s\", ...): Invalid format",
106 40
                    fmt ? fmt : "<NULL>");
107 40
                return (NULL);
108
        }
109
110 280
        return (WS_Printf(ctx->ws, fmt, fp));
111 320
}