View Javadoc
1   //******************************************************************************
2   //
3   // File:    DoubleBuf.java
4   // Package: edu.rit.mp
5   // Unit:    Class edu.rit.mp.DoubleBuf
6   //
7   // This Java source file is copyright (C) 2007 by Alan Kaminsky. All rights
8   // reserved. For further information, contact the author, Alan Kaminsky, at
9   // ark@cs.rit.edu.
10  //
11  // This Java source file is part of the Parallel Java Library ("PJ"). PJ is free
12  // software; you can redistribute it and/or modify it under the terms of the GNU
13  // General Public License as published by the Free Software Foundation; either
14  // version 3 of the License, or (at your option) any later version.
15  //
16  // PJ is distributed in the hope that it will be useful, but WITHOUT ANY
17  // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18  // A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19  //
20  // Linking this library statically or dynamically with other modules is making a
21  // combined work based on this library. Thus, the terms and conditions of the GNU
22  // General Public License cover the whole combination.
23  //
24  // As a special exception, the copyright holders of this library give you
25  // permission to link this library with independent modules to produce an
26  // executable, regardless of the license terms of these independent modules, and
27  // to copy and distribute the resulting executable under terms of your choice,
28  // provided that you also meet, for each linked independent module, the terms
29  // and conditions of the license of that module. An independent module is a module
30  // which is not derived from or based on this library. If you modify this library,
31  // you may extend this exception to your version of the library, but you are not
32  // obligated to do so. If you do not wish to do so, delete this exception
33  // statement from your version.
34  //
35  // A copy of the GNU General Public License is provided in the file gpl.txt. You
36  // may also obtain a copy of the GNU General Public License on the World Wide
37  // Web at http://www.gnu.org/licenses/gpl.html.
38  //
39  //******************************************************************************
40  package edu.rit.mp;
41  
42  import java.nio.ByteBuffer;
43  
44  import edu.rit.mp.buf.DoubleArrayBuf;
45  import edu.rit.mp.buf.DoubleArrayBuf_1;
46  import edu.rit.mp.buf.DoubleItemBuf;
47  import edu.rit.mp.buf.DoubleMatrixBuf;
48  import edu.rit.mp.buf.DoubleMatrixBuf_1;
49  import edu.rit.mp.buf.EmptyDoubleBuf;
50  import edu.rit.mp.buf.SharedDoubleArrayBuf;
51  import edu.rit.mp.buf.SharedDoubleArrayBuf_1;
52  import edu.rit.mp.buf.SharedDoubleBuf;
53  import edu.rit.pj.reduction.SharedDouble;
54  import edu.rit.pj.reduction.SharedDoubleArray;
55  import edu.rit.util.Arrays;
56  import edu.rit.util.Range;
57  
58  /**
59   * Class DoubleBuf is the abstract base class for a buffer of double items sent
60   * or received using the Message Protocol (MP). In a message, a double item is
61   * represented as eight bytes, most significant byte first.
62   * <P>
63   * A buffer may be used to send one or more messages at the same time in
64   * multiple threads. If a buffer is being used to send a message or messages,
65   * the buffer must not be used to receive a message at the same time.
66   * <P>
67   * A buffer may be used to receive one message at a time. If a buffer is being
68   * used to receive a message, the buffer must not be used to receive another
69   * message in a different thread, and the buffer must not be used to send a
70   * message or messages.
71   * <P>
72   * A buffer is a conduit for retrieving and storing data in some underlying data
73   * structure. If the underlying data structure is multiple thread safe, then one
74   * thread can be retrieving or storing data via the buffer at the same time as
75   * other threads are accessing the data structure. If the underlying data
76   * structure is not multiple thread safe, then other threads must not access the
77   * data structure while one thread is retrieving or storing data via the buffer.
78   * <P>
79   * To create a DoubleBuf, call one of the following static factory methods:
80   * <UL>
81   * <LI><code>emptyBuffer()</code>
82   * <LI><code>buffer()</code>
83   * <LI><code>buffer (double)</code>
84   * <LI><code>buffer (double[])</code>
85   * <LI><code>sliceBuffer (double[], Range)</code>
86   * <LI><code>sliceBuffers (double[], Range[])</code>
87   * <LI><code>buffer (double[][])</code>
88   * <LI><code>rowSliceBuffer (double[][], Range)</code>
89   * <LI><code>rowSliceBuffers (double[][], Range[])</code>
90   * <LI><code>colSliceBuffer (double[][], Range)</code>
91   * <LI><code>colSliceBuffers (double[][], Range[])</code>
92   * <LI><code>patchBuffer (double[][], Range, Range)</code>
93   * <LI><code>patchBuffers (double[][], Range[], Range[])</code>
94   * <LI><code>buffer (SharedDouble)</code>
95   * <LI><code>buffer (SharedDoubleArray)</code>
96   * <LI><code>sliceBuffer (SharedDoubleArray, Range)</code>
97   * <LI><code>sliceBuffers (SharedDoubleArray, Range[])</code>
98   * </UL>
99   *
100  * @author Alan Kaminsky
101  * @version 03-May-2008
102  */
103 public abstract class DoubleBuf
104         extends Buf {
105 
106 // Hidden constructors.
107     /**
108      * Construct a new double buffer.
109      *
110      * @param theLength Number of items.
111      * @exception IllegalArgumentException (unchecked exception) Thrown if
112      * <code>theLength</code> &lt; 0.
113      */
114     protected DoubleBuf(int theLength) {
115         super(Constants.TYPE_DOUBLE, theLength);
116     }
117 
118 // Exported operations.
119     /**
120      * Create an empty buffer. The buffer's length is 0. The buffer's item type
121      * is double.
122      *
123      * @return Empty buffer.
124      */
125     public static DoubleBuf emptyBuffer() {
126         return new EmptyDoubleBuf();
127     }
128 
129     /**
130      * Create a buffer for a double item. The item is stored in the
131      * <code>item</code> field of the buffer.
132      *
133      * @return Buffer.
134      */
135     public static DoubleItemBuf buffer() {
136         return new DoubleItemBuf();
137     }
138 
139     /**
140      * Create a buffer for a double item with the given initial value. The item
141      * is stored in the <code>item</code> field of the buffer.
142      *
143      * @param item Initial value of the <code>item</code> field.
144      * @return Buffer.
145      */
146     public static DoubleItemBuf buffer(double item) {
147         return new DoubleItemBuf(item);
148     }
149 
150     /**
151      * Create a buffer for the entire given double array. The returned buffer
152      * encompasses all the elements in <code>theArray</code>.
153      *
154      * @param theArray Array.
155      * @return Buffer.
156      * @exception NullPointerException (unchecked exception) Thrown if
157      * <code>theArray</code> is null.
158      */
159     public static DoubleBuf buffer(double[] theArray) {
160         if (theArray == null) {
161             throw new NullPointerException("DoubleBuf.buffer(): theArray is null");
162         }
163         int nr = Arrays.length(theArray);
164         return new DoubleArrayBuf_1(theArray, new Range(0, nr - 1));
165     }
166 
167     /**
168      * Create a buffer for one slice of the given double array. The returned
169      * buffer encompasses <code>theRange</code> of elements in <code>theArray</code>.
170      * The range's stride may be 1 or greater than 1.
171      *
172      * @param theArray Array.
173      * @param theRange Range of elements to include.
174      * @return Buffer.
175      * @exception NullPointerException (unchecked exception) Thrown if
176      * <code>theArray</code> is null or
177      * <code>theRange</code> is null.
178      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
179      * <code>theArray</code> does not include all the indexes in <code>theRange</code>.
180      */
181     public static DoubleBuf sliceBuffer(double[] theArray,
182             Range theRange) {
183         if (theArray == null) {
184             throw new NullPointerException("DoubleBuf.sliceBuffer(): theArray is null");
185         }
186         int nr = Arrays.length(theArray);
187         if (0 > theRange.lb() || theRange.ub() >= nr) {
188             throw new IndexOutOfBoundsException("DoubleBuf.sliceBuffer(): theArray index range = 0.."
189                     + (nr - 1) + ", theRange = " + theRange);
190         }
191         if (theRange.stride() == 1) {
192             return new DoubleArrayBuf_1(theArray, theRange);
193         } else {
194             return new DoubleArrayBuf(theArray, theRange);
195         }
196     }
197 
198     /**
199      * Create an array of buffers for multiple slices of the given double array.
200      * The returned buffer array has the same length as
201      * <code>theRanges</code>. Each element [<I>i</I>] of the returned buffer array
202      * encompasses the elements of <code>theArray</code> specified by
203      * <code>theRanges[i]</code>. Each range's stride may be 1 or greater than 1.
204      *
205      * @param theArray Array.
206      * @param theRanges Array of ranges of elements to include.
207      * @return Array of buffers.
208      * @exception NullPointerException (unchecked exception) Thrown if
209      * <code>theArray</code> is null or
210      * <code>theRanges</code> or any element thereof is null.
211      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
212      * <code>theArray</code>'s allocation does not include any element of
213      * <code>theRanges</code>.
214      */
215     public static DoubleBuf[] sliceBuffers(double[] theArray,
216             Range[] theRanges) {
217         int n = theRanges.length;
218         DoubleBuf[] result = new DoubleBuf[n];
219         for (int i = 0; i < n; ++i) {
220             result[i] = sliceBuffer(theArray, theRanges[i]);
221         }
222         return result;
223     }
224 
225     /**
226      * Create a buffer for the entire given double matrix. The returned buffer
227      * encompasses all the rows and all the columns in
228      * <code>theMatrix</code>.
229      *
230      * @param theMatrix Matrix.
231      * @return Buffer.
232      * @exception NullPointerException (unchecked exception) Thrown if
233      * <code>theMatrix</code> is null.
234      */
235     public static DoubleBuf buffer(double[][] theMatrix) {
236         if (theMatrix == null) {
237             throw new NullPointerException("DoubleBuf.buffer(): theMatrix is null");
238         }
239         int nr = Arrays.rowLength(theMatrix);
240         int nc = Arrays.colLength(theMatrix, 0);
241         return new DoubleMatrixBuf_1(theMatrix, new Range(0, nr - 1), new Range(0, nc - 1));
242     }
243 
244     /**
245      * Create a buffer for one row slice of the given double matrix. The
246      * returned buffer encompasses <code>theRowRange</code> of rows, and all the
247      * columns, in <code>theMatrix</code>. The range's stride may be 1 or greater
248      * than 1.
249      *
250      * @param theMatrix Matrix.
251      * @param theRowRange Range of rows to include.
252      * @return Buffer.
253      * @exception NullPointerException (unchecked exception) Thrown if
254      * <code>theMatrix</code> is null or
255      * <code>theRowRange</code> is null.
256      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
257      * <code>theMatrix</code>'s allocation does not include <code>theRowRange</code>.
258      */
259     public static DoubleBuf rowSliceBuffer(double[][] theMatrix,
260             Range theRowRange) {
261         if (theMatrix == null) {
262             throw new NullPointerException("DoubleBuf.rowSliceBuffer(): theMatrix is null");
263         }
264         int nr = Arrays.rowLength(theMatrix);
265         if (0 > theRowRange.lb() || theRowRange.ub() >= nr) {
266             throw new IndexOutOfBoundsException("DoubleBuf.rowSliceBuffer(): theMatrix row index range = 0.."
267                     + (nr - 1) + ", theRowRange = " + theRowRange);
268         }
269         int nc = Arrays.colLength(theMatrix, theRowRange.lb());
270         if (theRowRange.stride() == 1) {
271             return new DoubleMatrixBuf_1(theMatrix, theRowRange, new Range(0, nc - 1));
272         } else {
273             return new DoubleMatrixBuf(theMatrix, theRowRange, new Range(0, nc - 1));
274         }
275     }
276 
277     /**
278      * Create an array of buffers for multiple row slices of the given double
279      * matrix. The returned buffer array has the same length as
280      * <code>theRowRanges</code>. Each element [<I>i</I>] of the returned buffer
281      * array encompasses the rows of <code>theMatrix</code> specified by
282      * <code>theRowRanges[i]</code> and all the columns of <code>theMatrix</code>. Each
283      * range's stride may be 1 or greater than 1.
284      *
285      * @param theMatrix Matrix.
286      * @param theRowRanges Array of ranges of rows to include.
287      * @return Array of buffers.
288      * @exception NullPointerException (unchecked exception) Thrown if
289      * <code>theMatrix</code> is null or
290      * <code>theRowRanges</code> or any element thereof is null.
291      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
292      * <code>theMatrix</code>'s allocation does not include any element of
293      * <code>theRowRanges</code>.
294      */
295     public static DoubleBuf[] rowSliceBuffers(double[][] theMatrix,
296             Range[] theRowRanges) {
297         int n = theRowRanges.length;
298         DoubleBuf[] result = new DoubleBuf[n];
299         for (int i = 0; i < n; ++i) {
300             result[i] = rowSliceBuffer(theMatrix, theRowRanges[i]);
301         }
302         return result;
303     }
304 
305     /**
306      * Create a buffer for one column slice of the given double matrix. The
307      * returned buffer encompasses all the rows, and <code>theColRange</code> of
308      * columns, in <code>theMatrix</code>. The range's stride may be 1 or greater
309      * than 1.
310      *
311      * @param theMatrix Matrix.
312      * @param theColRange Range of columns to include.
313      * @return Buffer.
314      * @exception NullPointerException (unchecked exception) Thrown if
315      * <code>theMatrix</code> is null or
316      * <code>theColRange</code> is null.
317      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
318      * <code>theMatrix</code>'s allocation does not include <code>theColRange</code>.
319      */
320     public static DoubleBuf colSliceBuffer(double[][] theMatrix,
321             Range theColRange) {
322         if (theMatrix == null) {
323             throw new NullPointerException("DoubleBuf.colSliceBuffer(): theMatrix is null");
324         }
325         int nr = Arrays.rowLength(theMatrix);
326         int nc = Arrays.colLength(theMatrix, 0);
327         if (0 > theColRange.lb() || theColRange.ub() >= nc) {
328             throw new IndexOutOfBoundsException("DoubleBuf.colSliceBuffer(): theMatrix column index range = 0.."
329                     + (nc - 1) + ", theColRange = " + theColRange);
330         }
331         if (theColRange.stride() == 1) {
332             return new DoubleMatrixBuf_1(theMatrix, new Range(0, nr - 1), theColRange);
333         } else {
334             return new DoubleMatrixBuf(theMatrix, new Range(0, nr - 1), theColRange);
335         }
336     }
337 
338     /**
339      * Create an array of buffers for multiple column slices of the given double
340      * matrix. The returned buffer array has the same length as
341      * <code>theColRanges</code>. Each element [<I>i</I>] of the returned buffer
342      * array encompasses all the rows of <code>theMatrix</code> and the columns of
343      * <code>theMatrix</code> specified by <code>theColRanges[i]</code>. Each range's
344      * stride may be 1 or greater than 1.
345      *
346      * @param theMatrix Matrix.
347      * @param theColRanges Array of ranges of columns to include.
348      * @return Array of buffers.
349      * @exception NullPointerException (unchecked exception) Thrown if
350      * <code>theMatrix</code> is null or
351      * <code>theColRanges</code> or any element thereof is null.
352      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
353      * <code>theMatrix</code>'s allocation does not include any element of
354      * <code>theColRanges</code>.
355      */
356     public static DoubleBuf[] colSliceBuffers(double[][] theMatrix,
357             Range[] theColRanges) {
358         int n = theColRanges.length;
359         DoubleBuf[] result = new DoubleBuf[n];
360         for (int i = 0; i < n; ++i) {
361             result[i] = colSliceBuffer(theMatrix, theColRanges[i]);
362         }
363         return result;
364     }
365 
366     /**
367      * Create a buffer for one patch of the given double matrix. The returned
368      * buffer encompasses <code>theRowRange</code> of rows, and <code>theColRange</code>
369      * of columns, in <code>theMatrix</code>. Each range's stride may be 1 or
370      * greater than 1.
371      *
372      * @param theMatrix Matrix.
373      * @param theRowRange Range of rows to include.
374      * @param theColRange Range of columns to include.
375      * @return Buffer.
376      * @exception NullPointerException (unchecked exception) Thrown if
377      * <code>theMatrix</code> is null,
378      * <code>theRowRange</code> is null, or <code>theColRange</code> is null.
379      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
380      * <code>theMatrix</code>'s allocation does not include <code>theRowRange</code> and
381      * <code>theColRange</code>.
382      */
383     public static DoubleBuf patchBuffer(double[][] theMatrix,
384             Range theRowRange,
385             Range theColRange) {
386         if (theMatrix == null) {
387             throw new NullPointerException("DoubleBuf.patchBuffer(): theMatrix is null");
388         }
389         int nr = Arrays.rowLength(theMatrix);
390         if (0 > theRowRange.lb() || theRowRange.ub() >= nr) {
391             throw new IndexOutOfBoundsException("DoubleBuf.patchBuffer(): theMatrix row index range = 0.."
392                     + (nr - 1) + ", theRowRange = " + theRowRange);
393         }
394         int nc = Arrays.colLength(theMatrix, theRowRange.lb());
395         if (0 > theColRange.lb() || theColRange.ub() >= nc) {
396             throw new IndexOutOfBoundsException("DoubleBuf.patchBuffer(): theMatrix column index range = 0.."
397                     + (nc - 1) + ", theColRange = " + theColRange);
398         }
399         if (theRowRange.stride() == 1 && theColRange.stride() == 1) {
400             return new DoubleMatrixBuf_1(theMatrix, theRowRange, theColRange);
401         } else {
402             return new DoubleMatrixBuf(theMatrix, theRowRange, theColRange);
403         }
404     }
405 
406     /**
407      * Create an array of buffers for multiple patches of the given double
408      * matrix. The length of the returned buffer array is equal to the length of
409      * <code>theRowRanges</code> times the length of <code>theColRanges</code>. Each
410      * element of the returned buffer array encompasses the rows given in one
411      * element of <code>theRowRanges</code> array, and the columns given in one
412      * element of <code>theColRanges</code> array, in all possible combinations, of
413      * <code>theMatrix</code>. Each range's stride may be 1 or greater than 1.
414      *
415      * @param theMatrix Matrix.
416      * @param theRowRanges Array of ranges of rows to include.
417      * @param theColRanges Array of ranges of columns to include.
418      * @return Array of buffers.
419      * @exception NullPointerException (unchecked exception) Thrown if
420      * <code>theMatrix</code> is null,
421      * <code>theRowRanges</code> or any element thereof is null, or
422      * <code>theColRanges</code> or any element thereof is null.
423      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
424      * <code>theMatrix</code>'s allocation does not include any element of
425      * <code>theRowRanges</code> or
426      * <code>theColRanges</code>.
427      */
428     public static DoubleBuf[] patchBuffers(double[][] theMatrix,
429             Range[] theRowRanges,
430             Range[] theColRanges) {
431         int m = theRowRanges.length;
432         int n = theColRanges.length;
433         DoubleBuf[] result = new DoubleBuf[m * n];
434         int k = 0;
435         for (int i = 0; i < m; ++i) {
436             Range rowrange = theRowRanges[i];
437             for (int j = 0; j < n; ++j) {
438                 result[k++]
439                         = patchBuffer(theMatrix, rowrange, theColRanges[j]);
440             }
441         }
442         return result;
443     }
444 
445     /**
446      * Create a buffer for a shared double item. The item is wrapped in an
447      * instance of class {@linkplain edu.rit.pj.reduction.SharedDouble
448      * SharedDouble}. Use the methods of the SharedDouble object to access the
449      * actual item.
450      *
451      * @param item SharedDouble object that wraps the item.
452      * @exception NullPointerException (unchecked exception) Thrown if
453      * <code>item</code> is null.
454      * @return a {@link edu.rit.mp.DoubleBuf} object.
455      */
456     public static DoubleBuf buffer(SharedDouble item) {
457         if (item == null) {
458             throw new NullPointerException("DoubleBuf.buffer(): item is null");
459         }
460         return new SharedDoubleBuf(item);
461     }
462 
463     /**
464      * Create a buffer for the entire given shared double array. The returned
465      * buffer encompasses all the elements in <code>theArray</code>.
466      *
467      * @param theArray Array.
468      * @return Buffer.
469      * @exception NullPointerException (unchecked exception) Thrown if
470      * <code>theArray</code> is null.
471      */
472     public static DoubleBuf buffer(SharedDoubleArray theArray) {
473         if (theArray == null) {
474             throw new NullPointerException("DoubleBuf.buffer(): theArray is null");
475         }
476         int nr = theArray.length();
477         return new SharedDoubleArrayBuf_1(theArray, new Range(0, nr - 1));
478     }
479 
480     /**
481      * Create a buffer for one slice of the given shared double array. The
482      * returned buffer encompasses <code>theRange</code> of elements in
483      * <code>theArray</code>. The range's stride may be 1 or greater than 1.
484      *
485      * @param theArray Array.
486      * @param theRange Range of elements to include.
487      * @return Buffer.
488      * @exception NullPointerException (unchecked exception) Thrown if
489      * <code>theArray</code> is null or
490      * <code>theRange</code> is null.
491      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
492      * <code>theArray</code> does not include all the indexes in <code>theRange</code>.
493      */
494     public static DoubleBuf sliceBuffer(SharedDoubleArray theArray,
495             Range theRange) {
496         if (theArray == null) {
497             throw new NullPointerException("DoubleBuf.sliceBuffer(): theArray is null");
498         }
499         int nr = theArray.length();
500         if (0 > theRange.lb() || theRange.ub() >= nr) {
501             throw new IndexOutOfBoundsException("DoubleBuf.sliceBuffer(): theArray index range = 0.."
502                     + (nr - 1) + ", theRange = " + theRange);
503         }
504         if (theRange.stride() == 1) {
505             return new SharedDoubleArrayBuf_1(theArray, theRange);
506         } else {
507             return new SharedDoubleArrayBuf(theArray, theRange);
508         }
509     }
510 
511     /**
512      * Create an array of buffers for multiple slices of the given shared double
513      * array. The returned buffer array has the same length as
514      * <code>theRanges</code>. Each element [<I>i</I>] of the returned buffer array
515      * encompasses the elements of <code>theArray</code> specified by
516      * <code>theRanges[i]</code>. Each range's stride may be 1 or greater than 1.
517      *
518      * @param theArray Array.
519      * @param theRanges Array of ranges of elements to include.
520      * @return Array of buffers.
521      * @exception NullPointerException (unchecked exception) Thrown if
522      * <code>theArray</code> is null or
523      * <code>theRanges</code> or any element thereof is null.
524      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
525      * <code>theArray</code>'s allocation does not include any element of
526      * <code>theRanges</code>.
527      */
528     public static DoubleBuf[] sliceBuffers(SharedDoubleArray theArray,
529             Range[] theRanges) {
530         int n = theRanges.length;
531         DoubleBuf[] result = new DoubleBuf[n];
532         for (int i = 0; i < n; ++i) {
533             result[i] = sliceBuffer(theArray, theRanges[i]);
534         }
535         return result;
536     }
537 
538     /**
539      * Obtain the given item from this buffer.
540      * <P>
541      * The <code>get()</code> method must not block the calling thread; if it does,
542      * all message I/O in MP will be blocked.
543      *
544      * @param i Item index in the range 0 .. <code>length()</code>-1.
545      * @return Item at index <code>i</code>.
546      */
547     public abstract double get(int i);
548 
549     /**
550      * Store the given item in this buffer.
551      * <P>
552      * The <code>put()</code> method must not block the calling thread; if it does,
553      * all message I/O in MP will be blocked.
554      *
555      * @param i Item index in the range 0 .. <code>length()</code>-1.
556      * @param item Item to be stored at index <code>i</code>.
557      */
558     public abstract void put(int i,
559             double item);
560 
561     /**
562      * {@inheritDoc}
563      *
564      * Copy items from the given buffer to this buffer. The number of items
565      * copied is this buffer's length or <code>theSrc</code>'s length, whichever is
566      * smaller. If <code>theSrc</code> is this buffer, the <code>copy()</code> method
567      * does nothing.
568      * <P>
569      * The default implementation of the <code>copy()</code> method calls the
570      * <code>defaultCopy()</code> method. A subclass can override the
571      * <code>copy()</code> method to use a more efficient algorithm.
572      * @exception ClassCastException (unchecked exception) Thrown if
573      * <code>theSrc</code>'s item data type is not the same as this buffer's item
574      * data type.
575      */
576     public void copy(Buf theSrc) {
577         if (theSrc != this) {
578             defaultCopy((DoubleBuf) theSrc, this);
579         }
580     }
581 
582     /**
583      * {@inheritDoc}
584      *
585      * Fill this buffer with the given item. The <code>item</code> is assigned to
586      * each element in this buffer.
587      * <P>
588      * The <code>item</code> must be an instance of class Double. If the
589      * <code>item</code> is null, 0.0 is assigned to each element in this buffer.
590      * @exception ClassCastException (unchecked exception) Thrown if the
591      * <code>item</code>'s data type is not the same as this buffer's item data
592      * type.
593      */
594     public void fill(Object item) {
595         double value = item == null ? 0.0 : ((Double) item).doubleValue();
596         for (int i = 0; i < myLength; ++i) {
597             put(i, value);
598         }
599     }
600 
601     /**
602      * Create a temporary buffer with the same type of items and the same length
603      * as this buffer. The new buffer items are stored in a newly created array,
604      * separate from the storage for this buffer's items.
605      *
606      * @return a {@link edu.rit.mp.Buf} object.
607      */
608     public Buf getTemporaryBuf() {
609         return buffer(new double[myLength]);
610     }
611 
612 // Hidden operations.
613     /**
614      * Skip as many items as possible from the given byte buffer.
615      *
616      * @param num Number of items to skip.
617      * @param buffer Buffer.
618      *
619      * @return Number of items actually skipped.
620      */
621     int skipItems(int num,
622             ByteBuffer buffer) {
623         int n = Math.min(num, buffer.remaining() / 8);
624         buffer.position(buffer.position() + 8 * n);
625         return n;
626     }
627 
628     /**
629      * Copy items from the given source buffer to the given destination buffer.
630      * The number of items copied is <code>theSrc</code>'s length or
631      * <code>theDst</code>'s length, whichever is smaller. Each item is copied
632      * individually using the <code>get()</code> and <code>put()</code> methods. It is
633      * assumed that <code>theSrc</code> is not the same as <code>theDst</code>.
634      *
635      * @param theSrc Source of items to copy.
636      * @param theDst Destination of items to copy.
637      */
638     protected static void defaultCopy(DoubleBuf theSrc,
639             DoubleBuf theDst) {
640         int n = Math.min(theSrc.myLength, theDst.myLength);
641         for (int i = 0; i < n; ++i) {
642             theDst.put(i, theSrc.get(i));
643         }
644     }
645 
646 }