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