1 /* 2 * Hunt - A refined core library for D programming language. 3 * 4 * Copyright (C) 2018-2019 HuntLabs 5 * 6 * Website: https://www.huntlabs.net/ 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.Integer; 13 14 import hunt.Byte; 15 import hunt.Exceptions; 16 import hunt.Nullable; 17 import hunt.Number; 18 import hunt.util.Comparator; 19 20 import std.conv; 21 22 class Integer : AbstractNumber!int 23 { 24 25 /** 26 * Returns the number of one-bits in the two's complement binary 27 * representation of the specified {@code int} value. This function is 28 * sometimes referred to as the <i>population count</i>. 29 * 30 * @param i the value whose bits are to be counted 31 * @return the number of one-bits in the two's complement binary 32 * representation of the specified {@code int} value. 33 * @since 1.5 34 */ 35 enum int MIN_VALUE = 0x80000000; 36 37 /** 38 * A constant holding the maximum value an {@code int} can 39 * have, 2!(sup)31</sup>-1. 40 */ 41 enum int MAX_VALUE = 0x7fffffff; 42 43 static int bitCount(int i) 44 { 45 // HD, Figure 5-2 46 i = i - ((i >>> 1) & 0x55555555); 47 i = (i & 0x33333333) + ((i >>> 2) & 0x33333333); 48 i = (i + (i >>> 4)) & 0x0f0f0f0f; 49 i = i + (i >>> 8); 50 i = i + (i >>> 16); 51 return i & 0x3f; 52 } 53 54 enum char[] digits = [ 55 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 56 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 57 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' 58 ]; 59 60 /** 61 * Returns the number of zero bits preceding the highest-order 62 * ("leftmost") one-bit in the two's complement binary representation 63 * of the specified {@code int} value. Returns 32 if the 64 * specified value has no one-bits in its two's complement representation, 65 * in other words if it is equal to zero. 66 * 67 * <p>Note that this method is closely related to the logarithm base 2. 68 * For all positive {@code int} values x: 69 * <ul> 70 * <li>floor(log!(sub)2</sub>(x)) = {@code 31 - numberOfLeadingZeros(x)} 71 * <li>ceil(log!(sub)2</sub>(x)) = {@code 32 - numberOfLeadingZeros(x - 1)} 72 * </ul> 73 * 74 * @param i the value whose number of leading zeros is to be computed 75 * @return the number of zero bits preceding the highest-order 76 * ("leftmost") one-bit in the two's complement binary representation 77 * of the specified {@code int} value, or 32 if the value 78 * is equal to zero. 79 * @since 1.5 80 */ 81 static int numberOfLeadingZeros(int i) 82 { 83 // HD, Figure 5-6 84 if (i == 0) 85 return 32; 86 int n = 1; 87 if (i >>> 16 == 0) 88 { 89 n += 16; 90 i <<= 16; 91 } 92 if (i >>> 24 == 0) 93 { 94 n += 8; 95 i <<= 8; 96 } 97 if (i >>> 28 == 0) 98 { 99 n += 4; 100 i <<= 4; 101 } 102 if (i >>> 30 == 0) 103 { 104 n += 2; 105 i <<= 2; 106 } 107 n -= i >>> 31; 108 return n; 109 } 110 111 /** 112 * Returns the number of zero bits following the lowest-order ("rightmost") 113 * one-bit in the two's complement binary representation of the specified 114 * {@code int} value. Returns 32 if the specified value has no 115 * one-bits in its two's complement representation, in other words if it is 116 * equal to zero. 117 * 118 * @param i the value whose number of trailing zeros is to be computed 119 * @return the number of zero bits following the lowest-order ("rightmost") 120 * one-bit in the two's complement binary representation of the 121 * specified {@code int} value, or 32 if the value is equal 122 * to zero. 123 * @since 1.5 124 */ 125 static int numberOfTrailingZeros(int i) 126 { 127 // HD, Figure 5-14 128 int y; 129 if (i == 0) 130 return 32; 131 int n = 31; 132 y = i << 16; 133 if (y != 0) 134 { 135 n = n - 16; 136 i = y; 137 } 138 y = i << 8; 139 if (y != 0) 140 { 141 n = n - 8; 142 i = y; 143 } 144 y = i << 4; 145 if (y != 0) 146 { 147 n = n - 4; 148 i = y; 149 } 150 y = i << 2; 151 if (y != 0) 152 { 153 n = n - 2; 154 i = y; 155 } 156 return n - ((i << 1) >>> 31); 157 } 158 159 override int opCmp(Object o) 160 { 161 if (o is null) 162 throw new NullPointerException(); 163 Number n = cast(Number) o; 164 if (n is null) 165 throw new Exception("Number needed."); 166 return compare(this.value, n.intValue()); 167 } 168 169 int opCmp(long n) 170 { 171 return compare(this.value, n); 172 } 173 174 /** 175 * Returns a hash code for a {@code double} value; compatible with 176 * {@code Double.hashCode()}. 177 * 178 * @param value the value to hash 179 * @return a hash code value for a {@code double} value. 180 * @since 1.8 181 */ 182 override size_t toHash() @safe nothrow 183 { 184 return cast(size_t) value; 185 } 186 187 /** 188 * Compares this object against the specified object. The result 189 * is {@code true} if and only if the argument is not 190 * {@code null} and is a {@code Double} object that 191 * represents a {@code double} that has the same value as the 192 * {@code double} represented by this object. For this 193 * purpose, two {@code double} values are considered to be 194 * the same if and only if the method {@link 195 * #doubleToLongBits(double)} returns the identical 196 * {@code long} value when applied to each. 197 * 198 * <p>Note that in most cases, for two instances of class 199 * {@code Double}, {@code d1} and {@code d2}, the 200 * value of {@code d1.equals(d2)} is {@code true} if and 201 * only if 202 * 203 * <blockquote> 204 * {@code d1.doubleValue() == d2.doubleValue()} 205 * </blockquote> 206 * 207 * <p>also has the value {@code true}. However, there are two 208 * exceptions: 209 * <ul> 210 * <li>If {@code d1} and {@code d2} both represent 211 * {@code Double.NaN}, then the {@code equals} method 212 * returns {@code true}, even though 213 * {@code Double.NaN==Double.NaN} has the value 214 * {@code false}. 215 * <li>If {@code d1} represents {@code +0.0} while 216 * {@code d2} represents {@code -0.0}, or vice versa, 217 * the {@code equal} test has the value {@code false}, 218 * even though {@code +0.0==-0.0} has the value {@code true}. 219 * </ul> 220 * This definition allows hash tables to operate properly. 221 * @param obj the object to compare with. 222 * @return {@code true} if the objects are the same; 223 * {@code false} otherwise. 224 * @see java.lang.Double#doubleToLongBits(double) 225 */ 226 // override bool opEquals(Object obj) { 227 // auto dl = cast(Integer)obj; 228 // if(dl !is null) 229 // return value == dl.intValue; 230 231 // return false; 232 // } 233 234 // alias opEquals = Nullable!int.opEquals; 235 236 /** 237 * The value of the {@code Integer}. 238 * 239 * @serial 240 */ 241 // private int value; 242 243 /** 244 * Constructs a newly allocated {@code Integer} object that 245 * represents the specified {@code int} value. 246 * 247 * @param value the value to be represented by the 248 * {@code Integer} object. 249 */ 250 this(int value) 251 { 252 super(value); 253 } 254 255 static int parseInt(string s) 256 { 257 auto i = to!long(s); 258 if (i < MIN_VALUE || i > MAX_VALUE) 259 { 260 throw new Exception("Value " ~ s ~ " out of range from input "); 261 } 262 263 return cast(int) i; 264 } 265 266 /** 267 * Parses the string argument as a signed integer in the radix 268 * specified by the second argument. The characters in the string 269 * must all be digits of the specified radix (as determined by 270 * whether {@link java.lang.Character#digit(char, int)} returns a 271 * nonnegative value), except that the first character may be an 272 * ASCII minus sign {@code '-'} ({@code '\u005Cu002D'}) to 273 * indicate a negative value or an ASCII plus sign {@code '+'} 274 * ({@code '\u005Cu002B'}) to indicate a positive value. The 275 * resulting integer value is returned. 276 * 277 * <p>An exception of type {@code NumberFormatException} is 278 * thrown if any of the following situations occurs: 279 * <ul> 280 * <li>The first argument is {@code null} or is a string of 281 * length zero. 282 * 283 * <li>The radix is either smaller than 284 * {@link java.lang.Character#MIN_RADIX} or 285 * larger than {@link java.lang.Character#MAX_RADIX}. 286 * 287 * <li>Any character of the string is not a digit of the specified 288 * radix, except that the first character may be a minus sign 289 * {@code '-'} ({@code '\u005Cu002D'}) or plus sign 290 * {@code '+'} ({@code '\u005Cu002B'}) provided that the 291 * string is longer than length 1. 292 * 293 * <li>The value represented by the string is not a value of type 294 * {@code int}. 295 * </ul> 296 * 297 * <p>Examples: 298 * <blockquote><pre> 299 * parseInt("0", 10) returns 0 300 * parseInt("473", 10) returns 473 301 * parseInt("+42", 10) returns 42 302 * parseInt("-0", 10) returns 0 303 * parseInt("-FF", 16) returns -255 304 * parseInt("1100110", 2) returns 102 305 * parseInt("2147483647", 10) returns 2147483647 306 * parseInt("-2147483648", 10) returns -2147483648 307 * parseInt("2147483648", 10) throws a NumberFormatException 308 * parseInt("99", 8) throws a NumberFormatException 309 * parseInt("Kona", 10) throws a NumberFormatException 310 * parseInt("Kona", 27) returns 411787 311 * </pre></blockquote> 312 * 313 * @param s the {@code String} containing the integer 314 * representation to be parsed 315 * @param radix the radix to be used while parsing {@code s}. 316 * @return the integer represented by the string argument in the 317 * specified radix. 318 * @exception NumberFormatException if the {@code String} 319 * does not contain a parsable {@code int}. 320 */ 321 static int parseInt(string s, int radix) 322 { 323 return to!int(s, radix); 324 } 325 326 /** 327 * Cache to support the object identity semantics of autoboxing for values between 328 * -128 and 127 (inclusive) as required by JLS. 329 * 330 * The cache is initialized on first usage. The size of the cache 331 * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option. 332 * During VM initialization, java.lang.Integer.IntegerCache.high property 333 * may be set and saved in the private system properties in the 334 * sun.misc.VM class. 335 */ 336 337 private static class IntegerCache 338 { 339 static int low = -128; 340 static int high; 341 static Integer[] cache; 342 343 static this() 344 { 345 // high value may be configured by property 346 int h = 127; 347 // string integerCacheHighPropValue = 348 // sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); 349 // if (integerCacheHighPropValue !is null) { 350 // try { 351 // int i = parseInt(integerCacheHighPropValue); 352 // i = Math.max(i, 127); 353 // // Maximum array size is Integer.MAX_VALUE 354 // h = Math.min(i, Integer.MAX_VALUE - (-low) -1); 355 // } catch( NumberFormatException nfe) { 356 // // If the property cannot be parsed into an int, ignore it. 357 // } 358 // } 359 high = h; 360 361 cache = new Integer[(high - low) + 1]; 362 int j = low; 363 for (int k = 0; k < cache.length; k++) 364 cache[k] = new Integer(j++); 365 366 // range [-128, 127] must be interned (JLS7 5.1.7) 367 assert(IntegerCache.high >= 127); 368 } 369 370 private this() 371 { 372 } 373 } 374 375 /** 376 * Returns an {@code Integer} instance representing the specified 377 * {@code int} value. If a new {@code Integer} instance is not 378 * required, this method should generally be used in preference to 379 * the constructor {@link #Integer(int)}, as this method is likely 380 * to yield significantly better space and time performance by 381 * caching frequently requested values. 382 * 383 * This method will always cache values in the range -128 to 127, 384 * inclusive, and may cache other values outside of this range. 385 * 386 * @param i an {@code int} value. 387 * @return an {@code Integer} instance representing {@code i}. 388 * @since 1.5 389 */ 390 static Integer valueOf(int i) 391 { 392 if (i >= IntegerCache.low && i <= IntegerCache.high) 393 return IntegerCache.cache[i + (-IntegerCache.low)]; 394 return new Integer(i); 395 } 396 397 /** 398 * Returns an {@code Integer} object holding the value 399 * extracted from the specified {@code String} when parsed 400 * with the radix given by the second argument. The first argument 401 * is interpreted as representing a signed integer in the radix 402 * specified by the second argument, exactly as if the arguments 403 * were given to the {@link #parseInt(java.lang.String, int)} 404 * method. The result is an {@code Integer} object that 405 * represents the integer value specified by the string. 406 * 407 * <p>In other words, this method returns an {@code Integer} 408 * object equal to the value of: 409 * 410 * <blockquote> 411 * {@code new Integer(Integer.parseInt(s, radix))} 412 * </blockquote> 413 * 414 * @param s the string to be parsed. 415 * @param radix the radix to be used in interpreting {@code s} 416 * @return an {@code Integer} object holding the value 417 * represented by the string argument in the specified 418 * radix. 419 * @exception NumberFormatException if the {@code String} 420 * does not contain a parsable {@code int}. 421 */ 422 static Integer valueOf(string s, int radix) 423 { 424 return Integer.valueOf(parseInt(s, radix)); 425 } 426 427 /** 428 * Returns an {@code Integer} object holding the 429 * value of the specified {@code String}. The argument is 430 * interpreted as representing a signed decimal integer, exactly 431 * as if the argument were given to the {@link 432 * #parseInt(java.lang.String)} method. The result is an 433 * {@code Integer} object that represents the integer value 434 * specified by the string. 435 * 436 * <p>In other words, this method returns an {@code Integer} 437 * object equal to the value of: 438 * 439 * <blockquote> 440 * {@code new Integer(Integer.parseInt(s))} 441 * </blockquote> 442 * 443 * @param s the string to be parsed. 444 * @return an {@code Integer} object holding the value 445 * represented by the string argument. 446 * @exception NumberFormatException if the string cannot be parsed 447 * as an integer. 448 */ 449 static Integer valueOf(string s) 450 { 451 return Integer.valueOf(parseInt(s, 10)); 452 } 453 454 // Bit twiddling 455 456 /** 457 * The number of bits used to represent an {@code int} value in two's 458 * complement binary form. 459 * 460 * @since 1.5 461 */ 462 enum int SIZE = int.sizeof * Byte.SIZE; // 32; 463 464 /** 465 * The number of bytes used to represent an {@code int} value in two's 466 * complement binary form. 467 * 468 * @since 1.8 469 */ 470 enum int BYTES = int.sizeof; // SIZE / Byte.SIZE; 471 472 /** 473 * Returns the value obtained by rotating the two's complement binary 474 * representation of the specified {@code int} value left by the 475 * specified number of bits. (Bits shifted out of the left hand, or 476 * high-order, side reenter on the right, or low-order.) 477 * 478 * <p>Note that left rotation with a negative distance is equivalent to 479 * right rotation: {@code rotateLeft(val, -distance) == rotateRight(val, 480 * distance)}. Note also that rotation by any multiple of 32 is a 481 * no-op, so all but the last five bits of the rotation distance can be 482 * ignored, even if the distance is negative: {@code rotateLeft(val, 483 * distance) == rotateLeft(val, distance & 0x1F)}. 484 * 485 * @param i the value whose bits are to be rotated left 486 * @param distance the number of bit positions to rotate left 487 * @return the value obtained by rotating the two's complement binary 488 * representation of the specified {@code int} value left by the 489 * specified number of bits. 490 * @since 1.5 491 */ 492 public static int rotateLeft(int i, int distance) 493 { 494 return (i << distance) | (i >>> -distance); 495 } 496 497 /** 498 * Returns the value obtained by rotating the two's complement binary 499 * representation of the specified {@code int} value right by the 500 * specified number of bits. (Bits shifted out of the right hand, or 501 * low-order, side reenter on the left, or high-order.) 502 * 503 * <p>Note that right rotation with a negative distance is equivalent to 504 * left rotation: {@code rotateRight(val, -distance) == rotateLeft(val, 505 * distance)}. Note also that rotation by any multiple of 32 is a 506 * no-op, so all but the last five bits of the rotation distance can be 507 * ignored, even if the distance is negative: {@code rotateRight(val, 508 * distance) == rotateRight(val, distance & 0x1F)}. 509 * 510 * @param i the value whose bits are to be rotated right 511 * @param distance the number of bit positions to rotate right 512 * @return the value obtained by rotating the two's complement binary 513 * representation of the specified {@code int} value right by the 514 * specified number of bits. 515 * @since 1.5 516 */ 517 public static int rotateRight(int i, int distance) 518 { 519 return (i >>> distance) | (i << -distance); 520 } 521 522 }