• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
allocate(int capacity)48     public static DoubleBuffer allocate(int capacity) {
49         if (capacity < 0) {
50             throw new IllegalArgumentException("capacity < 0: " + capacity);
51         }
52         return new ReadWriteDoubleArrayBuffer(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      */
wrap(double[] array)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      */
wrap(double[] array, int start, int doubleCount)87     public static DoubleBuffer wrap(double[] array, int start, int doubleCount) {
88         Arrays.checkOffsetAndCount(array.length, start, doubleCount);
89         DoubleBuffer buf = new ReadWriteDoubleArrayBuffer(array);
90         buf.position = start;
91         buf.limit = start + doubleCount;
92         return buf;
93     }
94 
DoubleBuffer(int capacity)95     DoubleBuffer(int capacity) {
96         super(3, capacity, null);
97     }
98 
array()99     public final double[] array() {
100         return protectedArray();
101     }
102 
arrayOffset()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      */
asReadOnlyBuffer()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      */
compact()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      */
compareTo(DoubleBuffer otherBuffer)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      */
duplicate()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
equals(Object other)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      */
get()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      */
get(double[] dst)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      */
get(double[] dst, int dstOffset, int doubleCount)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      */
get(int index)289     public abstract double get(int index);
290 
hasArray()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
hashCode()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      */
isDirect()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      */
order()335     public abstract ByteOrder order();
336 
337     /**
338      * Child class implements this method to realize {@code array()}.
339      *
340      * @see #array()
341      */
protectedArray()342     abstract double[] protectedArray();
343 
344     /**
345      * Child class implements this method to realize {@code arrayOffset()}.
346      *
347      * @see #arrayOffset()
348      */
protectedArrayOffset()349     abstract int protectedArrayOffset();
350 
351     /**
352      * Child class implements this method to realize {@code hasArray()}.
353      *
354      * @see #hasArray()
355      */
protectedHasArray()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      */
put(double d)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      */
put(double[] src)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      */
put(double[] src, int srcOffset, int doubleCount)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      */
put(DoubleBuffer src)439     public DoubleBuffer put(DoubleBuffer src) {
440         if (src == this) {
441             throw new IllegalArgumentException("src == this");
442         }
443         if (src.remaining() > remaining()) {
444             throw new BufferOverflowException();
445         }
446         double[] doubles = new double[src.remaining()];
447         src.get(doubles);
448         put(doubles);
449         return this;
450     }
451 
452     /**
453      * Write a double to the specified index of this buffer and the position is
454      * not changed.
455      *
456      * @param index
457      *            the index, must not be negative and less than the limit.
458      * @param d
459      *            the double to write.
460      * @return this buffer.
461      * @exception IndexOutOfBoundsException
462      *                if index is invalid.
463      * @exception ReadOnlyBufferException
464      *                if no changes may be made to the contents of this buffer.
465      */
put(int index, double d)466     public abstract DoubleBuffer put(int index, double d);
467 
468     /**
469      * Returns a sliced buffer that shares its content with this buffer.
470      * <p>
471      * The sliced buffer's capacity will be this buffer's {@code remaining()},
472      * and its zero position will correspond to this buffer's current position.
473      * The new buffer's position will be 0, limit will be its capacity, and its
474      * mark is cleared. The new buffer's read-only property and byte order are
475      * the same as this buffer's.
476      * <p>
477      * The new buffer shares its content with this buffer, which means either
478      * buffer's change of content will be visible to the other. The two buffer's
479      * position, limit and mark are independent.
480      *
481      * @return a sliced buffer that shares its content with this buffer.
482      */
slice()483     public abstract DoubleBuffer slice();
484 }
485