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> < 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 }