1<?php 2/* Copyright (c) 1998-2016 ILIAS open source, Extended GPL, see docs/LICENSE */ 3 4/** 5 * Class ilMath 6 * Wrapper for mathematical operations 7 * @author Helmut Schottmüller <helmut.schottmueller@mac.com> 8 * @author Michael Jansen <mjansen@databay.de> 9 * $Id$ 10 */ 11class ilMath 12{ 13 /** 14 * @var ilMathAdapter 15 */ 16 protected static $default_adapter = null; 17 18 /** 19 * @param int|float $left_operand 20 * @param int|float $right_operand 21 * @param int $scale 22 * @return mixed 23 */ 24 public static function _add($left_operand, $right_operand, $scale = 50) 25 { 26 $adapter = static::getDefaultAdapter(); 27 28 return $adapter->add($left_operand, $right_operand, $scale); 29 } 30 31 /** 32 * @param int|float $left_operand 33 * @param int|float $right_operand 34 * @param int $scale 35 * @return mixed 36 */ 37 public static function _div($left_operand, $right_operand, $scale = 50) 38 { 39 $adapter = static::getDefaultAdapter(); 40 41 return $adapter->div($left_operand, $right_operand, $scale); 42 } 43 44 /** 45 * @param int|float $operand 46 * @param int|float $modulu 47 * @return int 48 */ 49 public static function _mod($operand, $modulu) 50 { 51 $adapter = static::getDefaultAdapter(); 52 53 return $adapter->mod($operand, $modulu); 54 } 55 56 /** 57 * @param int|float $left_operand 58 * @param int|float $right_operand 59 * @param int $scale 60 * @return mixed 61 */ 62 public static function _mul($left_operand, $right_operand, $scale = 50) 63 { 64 $adapter = static::getDefaultAdapter(); 65 66 return $adapter->mul($left_operand, $right_operand, $scale); 67 } 68 69 /** 70 * @param int|float $left_operand 71 * @param int|float $right_operand 72 * @param int $scale 73 * @return mixed 74 */ 75 public static function _pow($left_operand, $right_operand, $scale = 50) 76 { 77 $adapter = static::getDefaultAdapter(); 78 79 return $adapter->pow($left_operand, $right_operand, $scale); 80 } 81 82 /** 83 * @param int|float $operand 84 * @param int $scale 85 * @return mixed 86 */ 87 public static function _sqrt($operand, $scale = 50) 88 { 89 $adapter = static::getDefaultAdapter(); 90 91 return $adapter->sqrt($operand, $scale); 92 } 93 94 /** 95 * @param int|float $left_operand 96 * @param int|float $right_operand 97 * @param int $scale 98 * @return mixed 99 */ 100 public static function _sub($left_operand, $right_operand, $scale = 50) 101 { 102 $adapter = static::getDefaultAdapter(); 103 104 return $adapter->sub($left_operand, $right_operand, $scale); 105 } 106 107 public static function isCoprimeFraction($numerator, $denominator) 108 { 109 $gcd = self::getGreatestCommonDivisor(abs($numerator), abs($denominator)); 110 111 return $gcd == 1 ? true : false; 112 } 113 114 /** 115 * @param mixed $a 116 * @param mixed $b 117 * @return mixed 118 */ 119 public static function getGreatestCommonDivisor($a, $b) 120 { 121 if ($b > 0) { 122 return self::getGreatestCommonDivisor($b, $a % $b); 123 } else { 124 return $a; 125 } 126 } 127 128 /** 129 * @param ilMathAdapter $adapter 130 */ 131 public static function setDefaultAdapter(ilMathAdapter $adapter) 132 { 133 static::$default_adapter = $adapter; 134 } 135 136 /** 137 * @return ilMathAdapter 138 */ 139 public static function getDefaultAdapter() 140 { 141 if (null === static::$default_adapter) { 142 static::$default_adapter = static::getFirstValidAdapter(); 143 } 144 145 return static::$default_adapter; 146 } 147 148 /** 149 * @param null|string $adapter 150 * @return ilMathAdapter 151 * @throws ilMathException 152 */ 153 public static function getInstance($adapter = null) 154 { 155 if (null === $adapter) { 156 return static::getFirstValidAdapter(); 157 } 158 159 $class_name = 'ilMath' . $adapter . 'Adapter'; 160 $path_to_class = realpath('Services/Math/classes/class.' . $class_name . '.php'); 161 162 if (!is_file($path_to_class) || !is_readable($path_to_class)) { 163 require_once 'Services/Math/exceptions/class.ilMathException.php'; 164 throw new ilMathException(sprintf( 165 'The math adapter %s is not valid, please refer to a class implementing %s', 166 $adapter, 167 ilMathAdapter::class 168 )); 169 } 170 171 require_once $path_to_class; 172 if (!class_exists($class_name) || !is_subclass_of($class_name, ilMathAdapter::class)) { 173 require_once 'Services/Math/exceptions/class.ilMathException.php'; 174 throw new ilMathException(sprintf( 175 'The math adapter class %s is not valid, please refer to a class implementing %s', 176 $class_name, 177 ilMathAdapter::class 178 )); 179 } 180 181 return new $class_name(); 182 } 183 184 /** 185 * @return ilMathAdapter 186 */ 187 public static function getFirstValidAdapter() 188 { 189 if (extension_loaded('bcmath')) { 190 return static::getInstance('BCMath'); 191 } 192 193 return static::getInstance('Php'); 194 } 195 196 /** 197 * Backward compatibility: Map all static calls to an equivalent instance method of the adapter 198 * @param string $method 199 * @param mixed $args 200 * @return mixed 201 */ 202 public static function __callStatic($method, $args) 203 { 204 if (strpos($method, '_') === 0) { 205 $method = substr($method, 1); 206 } 207 208 $adapter = static::getDefaultAdapter(); 209 210 return call_user_func_array([$adapter, $method], $args); 211 } 212} 213