DoubleBuffer.java revision fe5da19e0e366286cd4d95f7628fe9442b9062c8
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package java.nio; 19 20import java.util.Arrays; 21 22/** 23 * A buffer of doubles. 24 * <p> 25 * A double buffer can be created in either one of the following ways: 26 * <ul> 27 * <li>{@link #allocate(int) Allocate} a new double array and create a buffer 28 * based on it;</li> 29 * <li>{@link #wrap(double[]) Wrap} an existing double array to create a new 30 * buffer;</li> 31 * <li>Use 32 * {@link java.nio.ByteBuffer#asDoubleBuffer() ByteBuffer.asDoubleBuffer} to 33 * create a double buffer based on a byte buffer.</li> 34 * </ul> 35 */ 36public abstract class DoubleBuffer extends Buffer implements 37 Comparable<DoubleBuffer> { 38 39 /** 40 * Creates a double buffer based on a newly allocated double array. 41 * 42 * @param capacity 43 * the capacity of the new buffer. 44 * @return the created double buffer. 45 * @throws IllegalArgumentException 46 * if {@code capacity} is less than zero. 47 */ 48 public static DoubleBuffer allocate(int capacity) { 49 if (capacity < 0) { 50 throw new IllegalArgumentException("capacity < 0: " + capacity); 51 } 52 return new DoubleArrayBuffer(new double[capacity]); 53 } 54 55 /** 56 * Creates a new double buffer by wrapping the given double array. 57 * <p> 58 * Calling this method has the same effect as 59 * {@code wrap(array, 0, array.length)}. 60 * 61 * @param array 62 * the double array which the new buffer will be based on. 63 * @return the created double buffer. 64 */ 65 public static DoubleBuffer wrap(double[] array) { 66 return wrap(array, 0, array.length); 67 } 68 69 /** 70 * Creates a new double buffer by wrapping the given double array. 71 * <p> 72 * The new buffer's position will be {@code start}, limit will be 73 * {@code start + doubleCount}, capacity will be the length of the array. 74 * 75 * @param array 76 * the double array which the new buffer will be based on. 77 * @param start 78 * the start index, must not be negative and not greater than 79 * {@code array.length}. 80 * @param doubleCount 81 * the length, must not be negative and not greater than 82 * {@code array.length - start}. 83 * @return the created double buffer. 84 * @exception IndexOutOfBoundsException 85 * if either {@code start} or {@code doubleCount} is invalid. 86 */ 87 public static DoubleBuffer wrap(double[] array, int start, int doubleCount) { 88 Arrays.checkOffsetAndCount(array.length, start, doubleCount); 89 DoubleBuffer buf = new DoubleArrayBuffer(array); 90 buf.position = start; 91 buf.limit = start + doubleCount; 92 return buf; 93 } 94 95 DoubleBuffer(int capacity) { 96 super(3, capacity, null); 97 } 98 99 public final double[] array() { 100 return protectedArray(); 101 } 102 103 public final int arrayOffset() { 104 return protectedArrayOffset(); 105 } 106 107 /** 108 * Returns a read-only buffer that shares its content with this buffer. 109 * <p> 110 * The returned buffer is guaranteed to be a new instance, even if this 111 * buffer is read-only itself. The new buffer's position, limit, capacity 112 * and mark are the same as this buffer's. 113 * <p> 114 * The new buffer shares its content with this buffer, which means that this 115 * buffer's change of content will be visible to the new buffer. The two 116 * buffer's position, limit and mark are independent. 117 * 118 * @return a read-only version of this buffer. 119 */ 120 public abstract DoubleBuffer asReadOnlyBuffer(); 121 122 /** 123 * Compacts this double buffer. 124 * <p> 125 * The remaining doubles will be moved to the head of the buffer, staring 126 * from position zero. Then the position is set to {@code remaining()}; the 127 * limit is set to capacity; the mark is cleared. 128 * 129 * @return this buffer. 130 * @exception ReadOnlyBufferException 131 * if no changes may be made to the contents of this buffer. 132 */ 133 public abstract DoubleBuffer compact(); 134 135 /** 136 * Compare the remaining doubles of this buffer to another double buffer's 137 * remaining doubles. 138 * 139 * @param otherBuffer 140 * another double buffer. 141 * @return a negative value if this is less than {@code other}; 0 if this 142 * equals to {@code other}; a positive value if this is greater 143 * than {@code other}. 144 * @exception ClassCastException 145 * if {@code other} is not a double buffer. 146 */ 147 public int compareTo(DoubleBuffer otherBuffer) { 148 int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining() 149 : otherBuffer.remaining(); 150 int thisPos = position; 151 int otherPos = otherBuffer.position; 152 double thisDouble, otherDouble; 153 while (compareRemaining > 0) { 154 thisDouble = get(thisPos); 155 otherDouble = otherBuffer.get(otherPos); 156 // checks for double and NaN inequality 157 if ((thisDouble != otherDouble) 158 && ((thisDouble == thisDouble) || (otherDouble == otherDouble))) { 159 return thisDouble < otherDouble ? -1 : 1; 160 } 161 thisPos++; 162 otherPos++; 163 compareRemaining--; 164 } 165 return remaining() - otherBuffer.remaining(); 166 } 167 168 /** 169 * Returns a duplicated buffer that shares its content with this buffer. 170 * <p> 171 * The duplicated buffer's position, limit, capacity and mark are the same 172 * as this buffer's. The duplicated buffer's read-only property and byte 173 * order are the same as this buffer's, too. 174 * <p> 175 * The new buffer shares its content with this buffer, which means either 176 * buffer's change of content will be visible to the other. The two buffer's 177 * position, limit and mark are independent. 178 * 179 * @return a duplicated buffer that shares its content with this buffer. 180 */ 181 public abstract DoubleBuffer duplicate(); 182 183 /** 184 * Checks whether this double buffer is equal to another object. If {@code 185 * other} is not a {@code DoubleBuffer} then {@code false} is returned. 186 * 187 * <p>Two double buffers are equal if their remaining doubles are equal. 188 * Position, limit, capacity and mark are not considered. 189 * 190 * <p>This method considers two doubles {@code a} and {@code b} to be equal 191 * if {@code a == b} or if {@code a} and {@code b} are both {@code NaN}. 192 * Unlike {@link Double#equals}, this method considers {@code -0.0} and 193 * {@code +0.0} to be equal. 194 * 195 * @param other 196 * the object to compare with this double buffer. 197 * @return {@code true} if this double buffer is equal to {@code other}, 198 * {@code false} otherwise. 199 */ 200 @Override 201 public boolean equals(Object other) { 202 if (!(other instanceof DoubleBuffer)) { 203 return false; 204 } 205 DoubleBuffer otherBuffer = (DoubleBuffer) other; 206 207 if (remaining() != otherBuffer.remaining()) { 208 return false; 209 } 210 211 int myPosition = position; 212 int otherPosition = otherBuffer.position; 213 boolean equalSoFar = true; 214 while (equalSoFar && (myPosition < limit)) { 215 double a = get(myPosition++); 216 double b = otherBuffer.get(otherPosition++); 217 equalSoFar = a == b || (a != a && b != b); 218 } 219 220 return equalSoFar; 221 } 222 223 /** 224 * Returns the double at the current position and increases the position by 225 * 1. 226 * 227 * @return the double at the current position. 228 * @exception BufferUnderflowException 229 * if the position is equal or greater than limit. 230 */ 231 public abstract double get(); 232 233 /** 234 * Reads doubles from the current position into the specified double array 235 * and increases the position by the number of doubles read. 236 * <p> 237 * Calling this method has the same effect as 238 * {@code get(dst, 0, dst.length)}. 239 * 240 * @param dst 241 * the destination double array. 242 * @return this buffer. 243 * @exception BufferUnderflowException 244 * if {@code dst.length} is greater than {@code remaining()}. 245 */ 246 public DoubleBuffer get(double[] dst) { 247 return get(dst, 0, dst.length); 248 } 249 250 /** 251 * Reads doubles from the current position into the specified double array, 252 * starting from the specified offset, and increases the position by the 253 * number of doubles read. 254 * 255 * @param dst 256 * the target double array. 257 * @param dstOffset 258 * the offset of the double array, must not be negative and not 259 * greater than {@code dst.length}. 260 * @param doubleCount 261 * the number of doubles to read, must be no less than zero and 262 * not greater than {@code dst.length - dstOffset}. 263 * @return this buffer. 264 * @exception IndexOutOfBoundsException 265 * if either {@code dstOffset} or {@code doubleCount} is invalid. 266 * @exception BufferUnderflowException 267 * if {@code doubleCount} is greater than {@code remaining()}. 268 */ 269 public DoubleBuffer get(double[] dst, int dstOffset, int doubleCount) { 270 Arrays.checkOffsetAndCount(dst.length, dstOffset, doubleCount); 271 if (doubleCount > remaining()) { 272 throw new BufferUnderflowException(); 273 } 274 for (int i = dstOffset; i < dstOffset + doubleCount; ++i) { 275 dst[i] = get(); 276 } 277 return this; 278 } 279 280 /** 281 * Returns a double at the specified index; the position is not changed. 282 * 283 * @param index 284 * the index, must not be negative and less than limit. 285 * @return a double at the specified index. 286 * @exception IndexOutOfBoundsException 287 * if index is invalid. 288 */ 289 public abstract double get(int index); 290 291 public final boolean hasArray() { 292 return protectedHasArray(); 293 } 294 295 /** 296 * Calculates this buffer's hash code from the remaining chars. The 297 * position, limit, capacity and mark don't affect the hash code. 298 * 299 * @return the hash code calculated from the remaining chars. 300 */ 301 @Override 302 public int hashCode() { 303 int myPosition = position; 304 int hash = 0; 305 long l; 306 while (myPosition < limit) { 307 l = Double.doubleToLongBits(get(myPosition++)); 308 hash = hash + ((int) l) ^ ((int) (l >> 32)); 309 } 310 return hash; 311 } 312 313 /** 314 * Indicates whether this buffer is direct. A direct buffer will try its 315 * best to take advantage of native memory APIs and it may not stay in the 316 * Java heap, so it is not affected by garbage collection. 317 * <p> 318 * A double buffer is direct if it is based on a byte buffer and the byte 319 * buffer is direct. 320 * 321 * @return {@code true} if this buffer is direct, {@code false} otherwise. 322 */ 323 public abstract boolean isDirect(); 324 325 /** 326 * Returns the byte order used by this buffer when converting doubles 327 * from/to bytes. 328 * <p> 329 * If this buffer is not based on a byte buffer, then this always returns 330 * the platform's native byte order. 331 * 332 * @return the byte order used by this buffer when converting doubles 333 * from/to bytes. 334 */ 335 public abstract ByteOrder order(); 336 337 /** 338 * Child class implements this method to realize {@code array()}. 339 * 340 * @see #array() 341 */ 342 abstract double[] protectedArray(); 343 344 /** 345 * Child class implements this method to realize {@code arrayOffset()}. 346 * 347 * @see #arrayOffset() 348 */ 349 abstract int protectedArrayOffset(); 350 351 /** 352 * Child class implements this method to realize {@code hasArray()}. 353 * 354 * @see #hasArray() 355 */ 356 abstract boolean protectedHasArray(); 357 358 /** 359 * Writes the given double to the current position and increases the 360 * position by 1. 361 * 362 * @param d 363 * the double to write. 364 * @return this buffer. 365 * @exception BufferOverflowException 366 * if position is equal or greater than limit. 367 * @exception ReadOnlyBufferException 368 * if no changes may be made to the contents of this buffer. 369 */ 370 public abstract DoubleBuffer put(double d); 371 372 /** 373 * Writes doubles from the given double array to the current position and 374 * increases the position by the number of doubles written. 375 * <p> 376 * Calling this method has the same effect as 377 * {@code put(src, 0, src.length)}. 378 * 379 * @param src 380 * the source double array. 381 * @return this buffer. 382 * @exception BufferOverflowException 383 * if {@code remaining()} is less than {@code src.length}. 384 * @exception ReadOnlyBufferException 385 * if no changes may be made to the contents of this buffer. 386 */ 387 public final DoubleBuffer put(double[] src) { 388 return put(src, 0, src.length); 389 } 390 391 /** 392 * Writes doubles from the given double array, starting from the specified 393 * offset, to the current position and increases the position by the number 394 * of doubles written. 395 * 396 * @param src 397 * the source double array. 398 * @param srcOffset 399 * the offset of double array, must not be negative and not 400 * greater than {@code src.length}. 401 * @param doubleCount 402 * the number of doubles to write, must be no less than zero and 403 * not greater than {@code src.length - srcOffset}. 404 * @return this buffer. 405 * @exception BufferOverflowException 406 * if {@code remaining()} is less than {@code doubleCount}. 407 * @exception IndexOutOfBoundsException 408 * if either {@code srcOffset} or {@code doubleCount} is invalid. 409 * @exception ReadOnlyBufferException 410 * if no changes may be made to the contents of this buffer. 411 */ 412 public DoubleBuffer put(double[] src, int srcOffset, int doubleCount) { 413 Arrays.checkOffsetAndCount(src.length, srcOffset, doubleCount); 414 if (doubleCount > remaining()) { 415 throw new BufferOverflowException(); 416 } 417 for (int i = srcOffset; i < srcOffset + doubleCount; ++i) { 418 put(src[i]); 419 } 420 return this; 421 } 422 423 /** 424 * Writes all the remaining doubles of the {@code src} double buffer to this 425 * buffer's current position, and increases both buffers' position by the 426 * number of doubles copied. 427 * 428 * @param src 429 * the source double buffer. 430 * @return this buffer. 431 * @exception BufferOverflowException 432 * if {@code src.remaining()} is greater than this buffer's 433 * {@code remaining()}. 434 * @exception IllegalArgumentException 435 * if {@code src} is this buffer. 436 * @exception ReadOnlyBufferException 437 * if no changes may be made to the contents of this buffer. 438 */ 439 public DoubleBuffer put(DoubleBuffer src) { 440 if (isReadOnly()) { 441 throw new ReadOnlyBufferException(); 442 } 443 if (src == this) { 444 throw new IllegalArgumentException("src == this"); 445 } 446 if (src.remaining() > remaining()) { 447 throw new BufferOverflowException(); 448 } 449 double[] doubles = new double[src.remaining()]; 450 src.get(doubles); 451 put(doubles); 452 return this; 453 } 454 455 /** 456 * Write a double to the specified index of this buffer and the position is 457 * not changed. 458 * 459 * @param index 460 * the index, must not be negative and less than the limit. 461 * @param d 462 * the double to write. 463 * @return this buffer. 464 * @exception IndexOutOfBoundsException 465 * if index is invalid. 466 * @exception ReadOnlyBufferException 467 * if no changes may be made to the contents of this buffer. 468 */ 469 public abstract DoubleBuffer put(int index, double d); 470 471 /** 472 * Returns a sliced buffer that shares its content with this buffer. 473 * <p> 474 * The sliced buffer's capacity will be this buffer's {@code remaining()}, 475 * and its zero position will correspond to this buffer's current position. 476 * The new buffer's position will be 0, limit will be its capacity, and its 477 * mark is cleared. The new buffer's read-only property and byte order are 478 * the same as this buffer's. 479 * <p> 480 * The new buffer shares its content with this buffer, which means either 481 * buffer's change of content will be visible to the other. The two buffer's 482 * position, limit and mark are independent. 483 * 484 * @return a sliced buffer that shares its content with this buffer. 485 */ 486 public abstract DoubleBuffer slice(); 487} 488