Differences Between: [Versions 400 and 401] [Versions 400 and 402] [Versions 400 and 403]
1 <?php 2 3 namespace PhpOffice\PhpSpreadsheet\Calculation\Engineering; 4 5 use PhpOffice\PhpSpreadsheet\Calculation\Exception; 6 use PhpOffice\PhpSpreadsheet\Calculation\Functions; 7 8 class BitWise 9 { 10 const SPLIT_DIVISOR = 2 ** 24; 11 12 /** 13 * Split a number into upper and lower portions for full 32-bit support. 14 * 15 * @param float|int $number 16 */ 17 private static function splitNumber($number): array 18 { 19 return [floor($number / self::SPLIT_DIVISOR), fmod($number, self::SPLIT_DIVISOR)]; 20 } 21 22 /** 23 * BITAND. 24 * 25 * Returns the bitwise AND of two integer values. 26 * 27 * Excel Function: 28 * BITAND(number1, number2) 29 * 30 * @param int $number1 31 * @param int $number2 32 * 33 * @return int|string 34 */ 35 public static function BITAND($number1, $number2) 36 { 37 try { 38 $number1 = self::validateBitwiseArgument($number1); 39 $number2 = self::validateBitwiseArgument($number2); 40 } catch (Exception $e) { 41 return $e->getMessage(); 42 } 43 $split1 = self::splitNumber($number1); 44 $split2 = self::splitNumber($number2); 45 46 return self::SPLIT_DIVISOR * ($split1[0] & $split2[0]) + ($split1[1] & $split2[1]); 47 } 48 49 /** 50 * BITOR. 51 * 52 * Returns the bitwise OR of two integer values. 53 * 54 * Excel Function: 55 * BITOR(number1, number2) 56 * 57 * @param int $number1 58 * @param int $number2 59 * 60 * @return int|string 61 */ 62 public static function BITOR($number1, $number2) 63 { 64 try { 65 $number1 = self::validateBitwiseArgument($number1); 66 $number2 = self::validateBitwiseArgument($number2); 67 } catch (Exception $e) { 68 return $e->getMessage(); 69 } 70 71 $split1 = self::splitNumber($number1); 72 $split2 = self::splitNumber($number2); 73 74 return self::SPLIT_DIVISOR * ($split1[0] | $split2[0]) + ($split1[1] | $split2[1]); 75 } 76 77 /** 78 * BITXOR. 79 * 80 * Returns the bitwise XOR of two integer values. 81 * 82 * Excel Function: 83 * BITXOR(number1, number2) 84 * 85 * @param int $number1 86 * @param int $number2 87 * 88 * @return int|string 89 */ 90 public static function BITXOR($number1, $number2) 91 { 92 try { 93 $number1 = self::validateBitwiseArgument($number1); 94 $number2 = self::validateBitwiseArgument($number2); 95 } catch (Exception $e) { 96 return $e->getMessage(); 97 } 98 99 $split1 = self::splitNumber($number1); 100 $split2 = self::splitNumber($number2); 101 102 return self::SPLIT_DIVISOR * ($split1[0] ^ $split2[0]) + ($split1[1] ^ $split2[1]); 103 } 104 105 /** 106 * BITLSHIFT. 107 * 108 * Returns the number value shifted left by shift_amount bits. 109 * 110 * Excel Function: 111 * BITLSHIFT(number, shift_amount) 112 * 113 * @param int $number 114 * @param int $shiftAmount 115 * 116 * @return float|int|string 117 */ 118 public static function BITLSHIFT($number, $shiftAmount) 119 { 120 try { 121 $number = self::validateBitwiseArgument($number); 122 $shiftAmount = self::validateShiftAmount($shiftAmount); 123 } catch (Exception $e) { 124 return $e->getMessage(); 125 } 126 127 $result = floor($number * (2 ** $shiftAmount)); 128 if ($result > 2 ** 48 - 1) { 129 return Functions::NAN(); 130 } 131 132 return $result; 133 } 134 135 /** 136 * BITRSHIFT. 137 * 138 * Returns the number value shifted right by shift_amount bits. 139 * 140 * Excel Function: 141 * BITRSHIFT(number, shift_amount) 142 * 143 * @param int $number 144 * @param int $shiftAmount 145 * 146 * @return float|int|string 147 */ 148 public static function BITRSHIFT($number, $shiftAmount) 149 { 150 try { 151 $number = self::validateBitwiseArgument($number); 152 $shiftAmount = self::validateShiftAmount($shiftAmount); 153 } catch (Exception $e) { 154 return $e->getMessage(); 155 } 156 157 $result = floor($number / (2 ** $shiftAmount)); 158 if ($result > 2 ** 48 - 1) { // possible because shiftAmount can be negative 159 return Functions::NAN(); 160 } 161 162 return $result; 163 } 164 165 /** 166 * Validate arguments passed to the bitwise functions. 167 * 168 * @param mixed $value 169 * 170 * @return float|int 171 */ 172 private static function validateBitwiseArgument($value) 173 { 174 self::nullFalseTrueToNumber($value); 175 176 if (is_numeric($value)) { 177 if ($value == floor($value)) { 178 if (($value > 2 ** 48 - 1) || ($value < 0)) { 179 throw new Exception(Functions::NAN()); 180 } 181 182 return floor($value); 183 } 184 185 throw new Exception(Functions::NAN()); 186 } 187 188 throw new Exception(Functions::VALUE()); 189 } 190 191 /** 192 * Validate arguments passed to the bitwise functions. 193 * 194 * @param mixed $value 195 * 196 * @return int 197 */ 198 private static function validateShiftAmount($value) 199 { 200 self::nullFalseTrueToNumber($value); 201 202 if (is_numeric($value)) { 203 if (abs($value) > 53) { 204 throw new Exception(Functions::NAN()); 205 } 206 207 return (int) $value; 208 } 209 210 throw new Exception(Functions::VALUE()); 211 } 212 213 /** 214 * Many functions accept null/false/true argument treated as 0/0/1. 215 * 216 * @param mixed $number 217 */ 218 public static function nullFalseTrueToNumber(&$number): void 219 { 220 $number = Functions::flattenSingleValue($number); 221 if ($number === null) { 222 $number = 0; 223 } elseif (is_bool($number)) { 224 $number = (int) $number; 225 } 226 } 227 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body