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 18 package java.nio; 19 20 import 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 */ 36 public 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 * @throws 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, long effectiveDirectAddress) { 96 super(3, capacity, effectiveDirectAddress); 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 * @throws 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 * @throws 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 buffers' 177 * position, limit and mark are independent. 178 */ 179 public abstract DoubleBuffer duplicate(); 180 181 /** 182 * Checks whether this double buffer is equal to another object. If {@code 183 * other} is not a {@code DoubleBuffer} then {@code false} is returned. 184 * 185 * <p>Two double buffers are equal if their remaining doubles are equal. 186 * Position, limit, capacity and mark are not considered. 187 * 188 * <p>This method considers two doubles {@code a} and {@code b} to be equal 189 * if {@code a == b} or if {@code a} and {@code b} are both {@code NaN}. 190 * Unlike {@link Double#equals}, this method considers {@code -0.0} and 191 * {@code +0.0} to be equal. 192 * 193 * @param other 194 * the object to compare with this double buffer. 195 * @return {@code true} if this double buffer is equal to {@code other}, 196 * {@code false} otherwise. 197 */ 198 @Override 199 public boolean equals(Object other) { 200 if (!(other instanceof DoubleBuffer)) { 201 return false; 202 } 203 DoubleBuffer otherBuffer = (DoubleBuffer) other; 204 205 if (remaining() != otherBuffer.remaining()) { 206 return false; 207 } 208 209 int myPosition = position; 210 int otherPosition = otherBuffer.position; 211 boolean equalSoFar = true; 212 while (equalSoFar && (myPosition < limit)) { 213 double a = get(myPosition++); 214 double b = otherBuffer.get(otherPosition++); 215 equalSoFar = a == b || (a != a && b != b); 216 } 217 218 return equalSoFar; 219 } 220 221 /** 222 * Returns the double at the current position and increases the position by 223 * 1. 224 * 225 * @return the double at the current position. 226 * @throws BufferUnderflowException 227 * if the position is equal or greater than limit. 228 */ 229 public abstract double get(); 230 231 /** 232 * Reads doubles from the current position into the specified double array 233 * and increases the position by the number of doubles read. 234 * <p> 235 * Calling this method has the same effect as 236 * {@code get(dst, 0, dst.length)}. 237 * 238 * @param dst 239 * the destination double array. 240 * @return this buffer. 241 * @throws BufferUnderflowException 242 * if {@code dst.length} is greater than {@code remaining()}. 243 */ 244 public DoubleBuffer get(double[] dst) { 245 return get(dst, 0, dst.length); 246 } 247 248 /** 249 * Reads doubles from the current position into the specified double array, 250 * starting from the specified offset, and increases the position by the 251 * number of doubles read. 252 * 253 * @param dst 254 * the target double array. 255 * @param dstOffset 256 * the offset of the double array, must not be negative and not 257 * greater than {@code dst.length}. 258 * @param doubleCount 259 * the number of doubles to read, must be no less than zero and 260 * not greater than {@code dst.length - dstOffset}. 261 * @return this buffer. 262 * @throws IndexOutOfBoundsException 263 * if either {@code dstOffset} or {@code doubleCount} is invalid. 264 * @throws BufferUnderflowException 265 * if {@code doubleCount} is greater than {@code remaining()}. 266 */ 267 public DoubleBuffer get(double[] dst, int dstOffset, int doubleCount) { 268 Arrays.checkOffsetAndCount(dst.length, dstOffset, doubleCount); 269 if (doubleCount > remaining()) { 270 throw new BufferUnderflowException(); 271 } 272 for (int i = dstOffset; i < dstOffset + doubleCount; ++i) { 273 dst[i] = get(); 274 } 275 return this; 276 } 277 278 /** 279 * Returns a double at the specified index; the position is not changed. 280 * 281 * @param index 282 * the index, must not be negative and less than limit. 283 * @return a double at the specified index. 284 * @throws IndexOutOfBoundsException 285 * if index is invalid. 286 */ 287 public abstract double get(int index); 288 289 public final boolean hasArray() { 290 return protectedHasArray(); 291 } 292 293 /** 294 * Calculates this buffer's hash code from the remaining chars. The 295 * position, limit, capacity and mark don't affect the hash code. 296 * 297 * @return the hash code calculated from the remaining chars. 298 */ 299 @Override 300 public int hashCode() { 301 int myPosition = position; 302 int hash = 0; 303 long l; 304 while (myPosition < limit) { 305 l = Double.doubleToLongBits(get(myPosition++)); 306 hash = hash + ((int) l) ^ ((int) (l >> 32)); 307 } 308 return hash; 309 } 310 311 /** 312 * Indicates whether this buffer is direct. A direct buffer will try its 313 * best to take advantage of native memory APIs and it may not stay in the 314 * Java heap, so it is not affected by garbage collection. 315 * <p> 316 * A double buffer is direct if it is based on a byte buffer and the byte 317 * buffer is direct. 318 * 319 * @return {@code true} if this buffer is direct, {@code false} otherwise. 320 */ 321 public abstract boolean isDirect(); 322 323 /** 324 * Returns the byte order used by this buffer when converting doubles 325 * from/to bytes. 326 * <p> 327 * If this buffer is not based on a byte buffer, then this always returns 328 * the platform's native byte order. 329 * 330 * @return the byte order used by this buffer when converting doubles 331 * from/to bytes. 332 */ 333 public abstract ByteOrder order(); 334 335 /** 336 * Child class implements this method to realize {@code array()}. 337 * 338 * @see #array() 339 */ 340 abstract double[] protectedArray(); 341 342 /** 343 * Child class implements this method to realize {@code arrayOffset()}. 344 * 345 * @see #arrayOffset() 346 */ 347 abstract int protectedArrayOffset(); 348 349 /** 350 * Child class implements this method to realize {@code hasArray()}. 351 * 352 * @see #hasArray() 353 */ 354 abstract boolean protectedHasArray(); 355 356 /** 357 * Writes the given double to the current position and increases the 358 * position by 1. 359 * 360 * @param d 361 * the double to write. 362 * @return this buffer. 363 * @throws BufferOverflowException 364 * if position is equal or greater than limit. 365 * @throws ReadOnlyBufferException 366 * if no changes may be made to the contents of this buffer. 367 */ 368 public abstract DoubleBuffer put(double d); 369 370 /** 371 * Writes doubles from the given double array to the current position and 372 * increases the position by the number of doubles written. 373 * <p> 374 * Calling this method has the same effect as 375 * {@code put(src, 0, src.length)}. 376 * 377 * @param src 378 * the source double array. 379 * @return this buffer. 380 * @throws BufferOverflowException 381 * if {@code remaining()} is less than {@code src.length}. 382 * @throws ReadOnlyBufferException 383 * if no changes may be made to the contents of this buffer. 384 */ 385 public final DoubleBuffer put(double[] src) { 386 return put(src, 0, src.length); 387 } 388 389 /** 390 * Writes doubles from the given double array, starting from the specified 391 * offset, to the current position and increases the position by the number 392 * of doubles written. 393 * 394 * @param src 395 * the source double array. 396 * @param srcOffset 397 * the offset of double array, must not be negative and not 398 * greater than {@code src.length}. 399 * @param doubleCount 400 * the number of doubles to write, must be no less than zero and 401 * not greater than {@code src.length - srcOffset}. 402 * @return this buffer. 403 * @throws BufferOverflowException 404 * if {@code remaining()} is less than {@code doubleCount}. 405 * @throws IndexOutOfBoundsException 406 * if either {@code srcOffset} or {@code doubleCount} is invalid. 407 * @throws ReadOnlyBufferException 408 * if no changes may be made to the contents of this buffer. 409 */ 410 public DoubleBuffer put(double[] src, int srcOffset, int doubleCount) { 411 Arrays.checkOffsetAndCount(src.length, srcOffset, doubleCount); 412 if (doubleCount > remaining()) { 413 throw new BufferOverflowException(); 414 } 415 for (int i = srcOffset; i < srcOffset + doubleCount; ++i) { 416 put(src[i]); 417 } 418 return this; 419 } 420 421 /** 422 * Writes all the remaining doubles of the {@code src} double buffer to this 423 * buffer's current position, and increases both buffers' position by the 424 * number of doubles copied. 425 * 426 * @param src 427 * the source double buffer. 428 * @return this buffer. 429 * @throws BufferOverflowException 430 * if {@code src.remaining()} is greater than this buffer's 431 * {@code remaining()}. 432 * @throws IllegalArgumentException 433 * if {@code src} is this buffer. 434 * @throws ReadOnlyBufferException 435 * if no changes may be made to the contents of this buffer. 436 */ 437 public DoubleBuffer put(DoubleBuffer src) { 438 if (isReadOnly()) { 439 throw new ReadOnlyBufferException(); 440 } 441 if (src == this) { 442 throw new IllegalArgumentException("src == this"); 443 } 444 if (src.remaining() > remaining()) { 445 throw new BufferOverflowException(); 446 } 447 double[] doubles = new double[src.remaining()]; 448 src.get(doubles); 449 put(doubles); 450 return this; 451 } 452 453 /** 454 * Write a double to the specified index of this buffer and the position is 455 * not changed. 456 * 457 * @param index 458 * the index, must not be negative and less than the limit. 459 * @param d 460 * the double to write. 461 * @return this buffer. 462 * @throws IndexOutOfBoundsException 463 * if index is invalid. 464 * @throws ReadOnlyBufferException 465 * if no changes may be made to the contents of this buffer. 466 */ 467 public abstract DoubleBuffer put(int index, double d); 468 469 /** 470 * Returns a sliced buffer that shares its content with this buffer. 471 * <p> 472 * The sliced buffer's capacity will be this buffer's {@code remaining()}, 473 * and its zero position will correspond to this buffer's current position. 474 * The new buffer's position will be 0, limit will be its capacity, and its 475 * mark is cleared. The new buffer's read-only property and byte order are 476 * the same as this buffer's. 477 * <p> 478 * The new buffer shares its content with this buffer, which means either 479 * buffer's change of content will be visible to the other. The two buffers' 480 * position, limit and mark are independent. 481 */ 482 public abstract DoubleBuffer slice(); 483 } 484