xref: /dokuwiki/vendor/splitbrain/lesserphp/src/Functions/Math.php (revision e6380ba37d6b3f7dd03146b3c03030ccc8c1b297)
1*e6380ba3SAndreas Gohr<?php
2*e6380ba3SAndreas Gohr
3*e6380ba3SAndreas Gohrnamespace LesserPHP\Functions;
4*e6380ba3SAndreas Gohr
5*e6380ba3SAndreas Gohruse Exception;
6*e6380ba3SAndreas Gohruse LesserPHP\Constants;
7*e6380ba3SAndreas Gohruse LesserPHP\Utils\Asserts;
8*e6380ba3SAndreas Gohruse LesserPHP\Utils\Util;
9*e6380ba3SAndreas Gohr
10*e6380ba3SAndreas Gohr/**
11*e6380ba3SAndreas Gohr * Implements the math functions for LESS
12*e6380ba3SAndreas Gohr *
13*e6380ba3SAndreas Gohr * @link https://lesscss.org/functions/#math-functions
14*e6380ba3SAndreas Gohr */
15*e6380ba3SAndreas Gohrclass Math extends AbstractFunctionCollection
16*e6380ba3SAndreas Gohr{
17*e6380ba3SAndreas Gohr    /** @inheritdoc */
18*e6380ba3SAndreas Gohr    public function getFunctions(): array
19*e6380ba3SAndreas Gohr    {
20*e6380ba3SAndreas Gohr        return [
21*e6380ba3SAndreas Gohr            'ceil' => [$this, 'ceil'],
22*e6380ba3SAndreas Gohr            'floor' => [$this, 'floor'],
23*e6380ba3SAndreas Gohr            'percentage' => [$this, 'percentage'],
24*e6380ba3SAndreas Gohr            'round' => [$this, 'round'],
25*e6380ba3SAndreas Gohr            'sqrt' => [$this, 'sqrt'],
26*e6380ba3SAndreas Gohr            'abs' => [$this, 'abs'],
27*e6380ba3SAndreas Gohr            'sin' => [$this, 'sin'],
28*e6380ba3SAndreas Gohr            'asin' => [$this, 'asin'],
29*e6380ba3SAndreas Gohr            'cos' => [$this, 'cos'],
30*e6380ba3SAndreas Gohr            'acos' => [$this, 'acos'],
31*e6380ba3SAndreas Gohr            'tan' => [$this, 'tan'],
32*e6380ba3SAndreas Gohr            'atan' => [$this, 'atan'],
33*e6380ba3SAndreas Gohr            'pi' => [$this, 'pi'],
34*e6380ba3SAndreas Gohr            'pow' => [$this, 'pow'],
35*e6380ba3SAndreas Gohr            'mod' => [$this, 'mod'],
36*e6380ba3SAndreas Gohr            'min' => [$this, 'min'],
37*e6380ba3SAndreas Gohr            'max' => [$this, 'max'],
38*e6380ba3SAndreas Gohr        ];
39*e6380ba3SAndreas Gohr    }
40*e6380ba3SAndreas Gohr
41*e6380ba3SAndreas Gohr
42*e6380ba3SAndreas Gohr    /**
43*e6380ba3SAndreas Gohr     * Rounds up to the next highest integer
44*e6380ba3SAndreas Gohr     *
45*e6380ba3SAndreas Gohr     * @link https://lesscss.org/functions/#math-functions-ceil
46*e6380ba3SAndreas Gohr     * @throws Exception
47*e6380ba3SAndreas Gohr     */
48*e6380ba3SAndreas Gohr    public function ceil(array $arg): array
49*e6380ba3SAndreas Gohr    {
50*e6380ba3SAndreas Gohr        $value = Asserts::assertNumber($arg);
51*e6380ba3SAndreas Gohr        return ['number', ceil($value), $arg[2]];
52*e6380ba3SAndreas Gohr    }
53*e6380ba3SAndreas Gohr
54*e6380ba3SAndreas Gohr    /**
55*e6380ba3SAndreas Gohr     * Rounds down to the next lowest integer
56*e6380ba3SAndreas Gohr     *
57*e6380ba3SAndreas Gohr     * @link https://lesscss.org/functions/#math-functions-floor
58*e6380ba3SAndreas Gohr     * @throws Exception
59*e6380ba3SAndreas Gohr     */
60*e6380ba3SAndreas Gohr    public function floor(array $arg): array
61*e6380ba3SAndreas Gohr    {
62*e6380ba3SAndreas Gohr        $value = Asserts::assertNumber($arg);
63*e6380ba3SAndreas Gohr        return ['number', floor($value), $arg[2]];
64*e6380ba3SAndreas Gohr    }
65*e6380ba3SAndreas Gohr
66*e6380ba3SAndreas Gohr    /**
67*e6380ba3SAndreas Gohr     * Converts a floating point number into a percentage string
68*e6380ba3SAndreas Gohr     *
69*e6380ba3SAndreas Gohr     * @link https://lesscss.org/functions/#math-functions-percentage
70*e6380ba3SAndreas Gohr     * @throws Exception
71*e6380ba3SAndreas Gohr     */
72*e6380ba3SAndreas Gohr    public function percentage(array $arg): array
73*e6380ba3SAndreas Gohr    {
74*e6380ba3SAndreas Gohr        $num = Asserts::assertNumber($arg);
75*e6380ba3SAndreas Gohr        return ['number', $num * 100, '%'];
76*e6380ba3SAndreas Gohr    }
77*e6380ba3SAndreas Gohr
78*e6380ba3SAndreas Gohr    /**
79*e6380ba3SAndreas Gohr     * Applies rounding
80*e6380ba3SAndreas Gohr     *
81*e6380ba3SAndreas Gohr     * @link https://lesscss.org/functions/#math-functions-round
82*e6380ba3SAndreas Gohr     * @throws Exception
83*e6380ba3SAndreas Gohr     */
84*e6380ba3SAndreas Gohr    public function round(array $arg): array
85*e6380ba3SAndreas Gohr    {
86*e6380ba3SAndreas Gohr        if ($arg[0] != 'list') {
87*e6380ba3SAndreas Gohr            $value = Asserts::assertNumber($arg);
88*e6380ba3SAndreas Gohr            return ['number', round($value), $arg[2]];
89*e6380ba3SAndreas Gohr        } else {
90*e6380ba3SAndreas Gohr            $value = Asserts::assertNumber($arg[2][0]);
91*e6380ba3SAndreas Gohr            $precision = Asserts::assertNumber($arg[2][1]);
92*e6380ba3SAndreas Gohr            return ['number', round($value, $precision), $arg[2][0][2]];
93*e6380ba3SAndreas Gohr        }
94*e6380ba3SAndreas Gohr    }
95*e6380ba3SAndreas Gohr
96*e6380ba3SAndreas Gohr    /**
97*e6380ba3SAndreas Gohr     * Calculates square root of a number
98*e6380ba3SAndreas Gohr     *
99*e6380ba3SAndreas Gohr     * @link https://lesscss.org/functions/#math-functions-sqrt
100*e6380ba3SAndreas Gohr     * @throws Exception
101*e6380ba3SAndreas Gohr     */
102*e6380ba3SAndreas Gohr    public function sqrt(array $num): float
103*e6380ba3SAndreas Gohr    {
104*e6380ba3SAndreas Gohr        return sqrt(Asserts::assertNumber($num));
105*e6380ba3SAndreas Gohr    }
106*e6380ba3SAndreas Gohr
107*e6380ba3SAndreas Gohr    /**
108*e6380ba3SAndreas Gohr     * Calculates absolute value of a number. Keeps units as they are.
109*e6380ba3SAndreas Gohr     *
110*e6380ba3SAndreas Gohr     * @link https://lesscss.org/functions/#math-functions-abs
111*e6380ba3SAndreas Gohr     * @throws Exception
112*e6380ba3SAndreas Gohr     */
113*e6380ba3SAndreas Gohr    public function abs(array $num): array
114*e6380ba3SAndreas Gohr    {
115*e6380ba3SAndreas Gohr        return ['number', abs(Asserts::assertNumber($num)), $num[2]];
116*e6380ba3SAndreas Gohr    }
117*e6380ba3SAndreas Gohr
118*e6380ba3SAndreas Gohr    /**
119*e6380ba3SAndreas Gohr     * Calculates sine function
120*e6380ba3SAndreas Gohr     *
121*e6380ba3SAndreas Gohr     * @link https://lesscss.org/functions/#math-functions-sin
122*e6380ba3SAndreas Gohr     * @throws Exception
123*e6380ba3SAndreas Gohr     */
124*e6380ba3SAndreas Gohr    public function sin(array $num): float
125*e6380ba3SAndreas Gohr    {
126*e6380ba3SAndreas Gohr        return sin(Asserts::assertNumber($num));
127*e6380ba3SAndreas Gohr    }
128*e6380ba3SAndreas Gohr
129*e6380ba3SAndreas Gohr    /**
130*e6380ba3SAndreas Gohr     * Calculates arcsine function
131*e6380ba3SAndreas Gohr     *
132*e6380ba3SAndreas Gohr     * @link https://lesscss.org/functions/#math-functions-asin
133*e6380ba3SAndreas Gohr     * @throws Exception
134*e6380ba3SAndreas Gohr     */
135*e6380ba3SAndreas Gohr    public function asin(array $num): array
136*e6380ba3SAndreas Gohr    {
137*e6380ba3SAndreas Gohr        $num = asin(Asserts::assertNumber($num));
138*e6380ba3SAndreas Gohr        return ['number', $num, 'rad'];
139*e6380ba3SAndreas Gohr    }
140*e6380ba3SAndreas Gohr
141*e6380ba3SAndreas Gohr    /**
142*e6380ba3SAndreas Gohr     * Calculates cosine function
143*e6380ba3SAndreas Gohr     *
144*e6380ba3SAndreas Gohr     * @link https://lesscss.org/functions/#math-functions-cos
145*e6380ba3SAndreas Gohr     * @throws Exception
146*e6380ba3SAndreas Gohr     */
147*e6380ba3SAndreas Gohr    public function cos(array $num): float
148*e6380ba3SAndreas Gohr    {
149*e6380ba3SAndreas Gohr        return cos(Asserts::assertNumber($num));
150*e6380ba3SAndreas Gohr    }
151*e6380ba3SAndreas Gohr
152*e6380ba3SAndreas Gohr    /**
153*e6380ba3SAndreas Gohr     * Calculates arccosine function
154*e6380ba3SAndreas Gohr     *
155*e6380ba3SAndreas Gohr     * @link https://lesscss.org/functions/#math-functions-acos
156*e6380ba3SAndreas Gohr     * @throws Exception
157*e6380ba3SAndreas Gohr     */
158*e6380ba3SAndreas Gohr    public function acos(array $num): array
159*e6380ba3SAndreas Gohr    {
160*e6380ba3SAndreas Gohr        $num = acos(Asserts::assertNumber($num));
161*e6380ba3SAndreas Gohr        return ['number', $num, 'rad'];
162*e6380ba3SAndreas Gohr    }
163*e6380ba3SAndreas Gohr
164*e6380ba3SAndreas Gohr    /**
165*e6380ba3SAndreas Gohr     * Calculates tangent function
166*e6380ba3SAndreas Gohr     *
167*e6380ba3SAndreas Gohr     * @link https://lesscss.org/functions/#math-functions-tan
168*e6380ba3SAndreas Gohr     * @throws Exception
169*e6380ba3SAndreas Gohr     */
170*e6380ba3SAndreas Gohr    public function tan(array $num): float
171*e6380ba3SAndreas Gohr    {
172*e6380ba3SAndreas Gohr        return tan(Asserts::assertNumber($num));
173*e6380ba3SAndreas Gohr    }
174*e6380ba3SAndreas Gohr
175*e6380ba3SAndreas Gohr    /**
176*e6380ba3SAndreas Gohr     * Calculates arctangent function
177*e6380ba3SAndreas Gohr     *
178*e6380ba3SAndreas Gohr     * @link https://lesscss.org/functions/#math-functions-atan
179*e6380ba3SAndreas Gohr     * @throws Exception
180*e6380ba3SAndreas Gohr     */
181*e6380ba3SAndreas Gohr    public function atan(array $num): array
182*e6380ba3SAndreas Gohr    {
183*e6380ba3SAndreas Gohr        $num = atan(Asserts::assertNumber($num));
184*e6380ba3SAndreas Gohr        return ['number', $num, 'rad'];
185*e6380ba3SAndreas Gohr    }
186*e6380ba3SAndreas Gohr
187*e6380ba3SAndreas Gohr    /**
188*e6380ba3SAndreas Gohr     * Return the value of pi
189*e6380ba3SAndreas Gohr     *
190*e6380ba3SAndreas Gohr     * @link https://lesscss.org/functions/#math-functions-pi
191*e6380ba3SAndreas Gohr     */
192*e6380ba3SAndreas Gohr    public function pi(): float
193*e6380ba3SAndreas Gohr    {
194*e6380ba3SAndreas Gohr        return pi();
195*e6380ba3SAndreas Gohr    }
196*e6380ba3SAndreas Gohr
197*e6380ba3SAndreas Gohr    /**
198*e6380ba3SAndreas Gohr     * Returns the value of the first argument raised to the power of the second argument.
199*e6380ba3SAndreas Gohr     *
200*e6380ba3SAndreas Gohr     * @link https://lesscss.org/functions/#math-functions-pow
201*e6380ba3SAndreas Gohr     * @throws Exception
202*e6380ba3SAndreas Gohr     */
203*e6380ba3SAndreas Gohr    public function pow(array $args): array
204*e6380ba3SAndreas Gohr    {
205*e6380ba3SAndreas Gohr        [$base, $exp] = Asserts::assertArgs($args, 2, 'pow');
206*e6380ba3SAndreas Gohr        return ['number', Asserts::assertNumber($base) ** Asserts::assertNumber($exp), $args[2][0][2]];
207*e6380ba3SAndreas Gohr    }
208*e6380ba3SAndreas Gohr
209*e6380ba3SAndreas Gohr    /**
210*e6380ba3SAndreas Gohr     * Returns the value of the first argument modulus second argument.
211*e6380ba3SAndreas Gohr     *
212*e6380ba3SAndreas Gohr     * @link https://lesscss.org/functions/#math-functions-mod
213*e6380ba3SAndreas Gohr     * @throws Exception
214*e6380ba3SAndreas Gohr     */
215*e6380ba3SAndreas Gohr    public function mod(array $args): array
216*e6380ba3SAndreas Gohr    {
217*e6380ba3SAndreas Gohr        [$a, $b] = Asserts::assertArgs($args, 2, 'mod');
218*e6380ba3SAndreas Gohr        return ['number', Asserts::assertNumber($a) % Asserts::assertNumber($b), $args[2][0][2]];
219*e6380ba3SAndreas Gohr    }
220*e6380ba3SAndreas Gohr
221*e6380ba3SAndreas Gohr    /**
222*e6380ba3SAndreas Gohr     * Returns the lowest of one or more values
223*e6380ba3SAndreas Gohr     *
224*e6380ba3SAndreas Gohr     * @link https://lesscss.org/functions/#math-functions-min
225*e6380ba3SAndreas Gohr     * @throws Exception
226*e6380ba3SAndreas Gohr     */
227*e6380ba3SAndreas Gohr    public function min(array $args): array
228*e6380ba3SAndreas Gohr    {
229*e6380ba3SAndreas Gohr        $values = Asserts::assertMinArgs($args, 1, 'min');
230*e6380ba3SAndreas Gohr
231*e6380ba3SAndreas Gohr        $first_format = $values[0][2];
232*e6380ba3SAndreas Gohr
233*e6380ba3SAndreas Gohr        $min_index = 0;
234*e6380ba3SAndreas Gohr        $min_value = $values[0][1];
235*e6380ba3SAndreas Gohr
236*e6380ba3SAndreas Gohr        for ($a = 0; $a < sizeof($values); $a++) {
237*e6380ba3SAndreas Gohr            $converted = Util::convert($values[$a], $first_format);
238*e6380ba3SAndreas Gohr
239*e6380ba3SAndreas Gohr            if ($converted[1] < $min_value) {
240*e6380ba3SAndreas Gohr                $min_index = $a;
241*e6380ba3SAndreas Gohr                $min_value = $values[$a][1];
242*e6380ba3SAndreas Gohr            }
243*e6380ba3SAndreas Gohr        }
244*e6380ba3SAndreas Gohr
245*e6380ba3SAndreas Gohr        return $values[$min_index];
246*e6380ba3SAndreas Gohr    }
247*e6380ba3SAndreas Gohr
248*e6380ba3SAndreas Gohr    /**
249*e6380ba3SAndreas Gohr     * Returns the highest of one or more values
250*e6380ba3SAndreas Gohr     *
251*e6380ba3SAndreas Gohr     * @link https://lesscss.org/functions/#math-functions-max
252*e6380ba3SAndreas Gohr     * @throws Exception
253*e6380ba3SAndreas Gohr     */
254*e6380ba3SAndreas Gohr    public function max(array $args): array
255*e6380ba3SAndreas Gohr    {
256*e6380ba3SAndreas Gohr        $values = Asserts::assertMinArgs($args, 1, 'max');
257*e6380ba3SAndreas Gohr
258*e6380ba3SAndreas Gohr        $first_format = $values[0][2];
259*e6380ba3SAndreas Gohr
260*e6380ba3SAndreas Gohr        $max_index = 0;
261*e6380ba3SAndreas Gohr        $max_value = $values[0][1];
262*e6380ba3SAndreas Gohr
263*e6380ba3SAndreas Gohr        for ($a = 0; $a < sizeof($values); $a++) {
264*e6380ba3SAndreas Gohr            $converted = Util::convert($values[$a], $first_format);
265*e6380ba3SAndreas Gohr
266*e6380ba3SAndreas Gohr            if ($converted[1] > $max_value) {
267*e6380ba3SAndreas Gohr                $max_index = $a;
268*e6380ba3SAndreas Gohr                $max_value = $values[$a][1];
269*e6380ba3SAndreas Gohr            }
270*e6380ba3SAndreas Gohr        }
271*e6380ba3SAndreas Gohr
272*e6380ba3SAndreas Gohr        return $values[$max_index];
273*e6380ba3SAndreas Gohr    }
274*e6380ba3SAndreas Gohr}
275