1: <?php
2: 3: 4: 5: 6: 7: 8: 9:
10:
11: namespace chippyash\Type\Number;
12:
13: use chippyash\Type\Interfaces\GMPInterface;
14: use chippyash\Type\Number\Complex\GMPComplexType;
15: use chippyash\Type\Number\Rational\GMPRationalType;
16: use chippyash\Type\Exceptions\GmpNotSupportedException;
17:
18: 19: 20:
21: class GMPIntType extends IntType implements GMPInterface
22: {
23: protected static $gmpInstalled;
24:
25: 26: 27: 28: 29: 30:
31: public function __construct($value)
32: {
33: if (empty(self::$gmpInstalled) || $this->checkGmpInstalled()) {
34: self::$gmpInstalled = true;
35: } else {
36: throw new GmpNotSupportedException();
37: }
38: parent::__construct($value);
39: }
40:
41: 42: 43: 44: 45:
46: public function negate()
47: {
48: $this->value = gmp_neg($this->value);
49:
50: return $this;
51: }
52:
53: 54: 55: 56: 57:
58: public function asComplex()
59: {
60: return new GMPComplexType(
61: new GMPRationalType(clone $this, new self(1)),
62: new GMPRationalType(new self(0), new self(1))
63: );
64: }
65:
66: 67: 68: 69: 70: 71:
72: public function asRational()
73: {
74: return new GMPRationalType(clone $this, new self(1));
75: }
76:
77: 78: 79: 80: 81:
82: public function asFloatType()
83: {
84: return new FloatType(gmp_strval($this->value));
85: }
86:
87: 88: 89: 90: 91:
92: public function abs()
93: {
94: return new self(gmp_abs($this->value));
95: }
96:
97: 98: 99: 100: 101: 102:
103: public function factors()
104: {
105: $num = $this->cloneValue();
106: $limit = gmp_sqrt($num);
107: $zero = gmp_init(0);
108: $one = gmp_init(1);
109: $ret = array();
110: for ($x = gmp_init(1); gmp_cmp($x, $limit) <= 0; $x = gmp_add($x, $one)) {
111: if (gmp_cmp(gmp_mod($num, $x), $zero) == 0) {
112: $xAsInt = gmp_strval($x);
113: $other = gmp_strval(gmp_div_q($num, $x));
114: $ret[$xAsInt] = $xAsInt;
115: $ret[$other] = $other;
116: }
117: }
118: ksort($ret, SORT_NUMERIC);
119: return array_values($ret);
120: }
121:
122: 123: 124: 125: 126: 127: 128: 129: 130: 131:
132: public function primeFactors()
133: {
134: $number = $this->cloneValue();
135: $divisor = 2;
136: $zero = gmp_init(0);
137: $one = gmp_init(1);
138: $dmax = gmp_sqrt($number);
139: $factors = array();
140: $sieve = array_fill(1, intval(gmp_strval($dmax)), 1);
141: do {
142: $rFlag = false;
143: while (gmp_cmp(gmp_mod($number, $divisor), $zero) == 0) {
144: $factors[$divisor] = (isset($factors[$divisor]) ? $factors[$divisor] + 1 : 1);
145: $number = gmp_div_q($number, $divisor);
146: $rFlag = true;
147: }
148: if ($rFlag) {
149: $dmax = gmp_sqrt($number);
150: }
151: if (gmp_cmp($number, $one) > 0) {
152: for ($i = $divisor; gmp_cmp($i, $dmax) <= 0; $i += $divisor) {
153: $sieve[$i] = 0;
154: }
155: do {
156: $divisor ++;
157: } while (gmp_cmp($divisor, $dmax) < 0 && $sieve[$divisor] != 1 );
158: if (gmp_cmp($divisor, $dmax) > 0) {
159: $key = gmp_strval($number);
160: $factors[$key] = (isset($factors[$key]) ? $factors[$key] + 1 : 1);
161: }
162: }
163: } while (gmp_cmp($number, $one) > 0 && gmp_cmp($divisor, $dmax) <= 0);
164:
165: return $factors;
166: }
167:
168: 169: 170: 171: 172:
173: public function __toString()
174: {
175: return gmp_strval($this->value);
176: }
177:
178: 179: 180: 181: 182: 183:
184: public function get()
185: {
186: return intval(gmp_strval($this->value));
187: }
188:
189: 190: 191: 192: 193:
194: public function gmp()
195: {
196: return $this->value;
197: }
198:
199: 200: 201: 202: 203:
204: public function asGMPIntType()
205: {
206: return clone $this;
207: }
208:
209: 210: 211: 212: 213:
214: public function asIntType()
215: {
216: return new IntType($this->get());
217: }
218:
219: 220: 221: 222: 223:
224: public function asGMPComplex()
225: {
226: return new GMPComplexType(
227: new GMPRationalType(new GMPIntType($this->get()), new GMPIntType(1)),
228: new GMPRationalType(new GMPIntType(0), new GMPIntType(1))
229: );
230: }
231:
232: 233: 234: 235: 236: 237:
238: public function asGMPRational()
239: {
240: return new GMPRationalType(new GMPIntType($this->get()), new GMPIntType(1));
241: }
242:
243: 244: 245: 246: 247: 248: 249:
250: protected function typeOf($value)
251: {
252: if ($this->gmpTypeCheck($value)) {
253: return $value;
254: } else {
255: return gmp_init(intval($value));
256: }
257: }
258:
259: 260: 261:
262: protected function cloneValue()
263: {
264: if (version_compare(PHP_VERSION, '5.6.0') < 0) {
265:
266: return $this->value;
267: }
268:
269: return clone $this->value;
270: }
271:
272:
273: 274: 275: 276: 277: 278:
279: protected function gmpTypeCheck($value)
280: {
281: if (version_compare(PHP_VERSION, '5.6.0') < 0) {
282: return is_resource($value) && get_resource_type($value) == 'GMP integer';
283: }
284:
285: return ($value instanceof \GMP);
286: }
287:
288: 289: 290: 291: 292:
293: protected function checkGmpInstalled()
294: {
295: return extension_loaded('gmp');
296: }
297: }
298: