1 16 package org.apache.commons.math.util; 17 18 import java.io.Serializable ; 19 20 71 public class ResizableDoubleArray implements DoubleArray, Serializable { 72 73 74 static final long serialVersionUID = -3485529955529426875L; 75 76 77 public static final int ADDITIVE_MODE = 1; 78 79 80 public static final int MULTIPLICATIVE_MODE = 0; 81 82 87 protected float contractionCriteria = 2.5f; 88 89 97 protected float expansionFactor = 2.0f; 98 99 103 protected int expansionMode = MULTIPLICATIVE_MODE; 104 105 109 protected int initialCapacity = 16; 110 111 114 protected double[] internalArray; 115 116 120 protected int numElements = 0; 121 122 128 protected int startIndex = 0; 129 130 139 public ResizableDoubleArray() { 140 internalArray = new double[initialCapacity]; 141 } 142 143 154 public ResizableDoubleArray(int initialCapacity) { 155 setInitialCapacity(initialCapacity); 156 internalArray = new double[this.initialCapacity]; 157 } 158 159 181 public ResizableDoubleArray(int initialCapacity, float expansionFactor) { 182 this.expansionFactor = expansionFactor; 183 setInitialCapacity(initialCapacity); 184 internalArray = new double[initialCapacity]; 185 setContractionCriteria(expansionFactor +0.5f); 186 } 187 188 207 public ResizableDoubleArray(int initialCapacity, float expansionFactor, 208 float contractionCriteria) { 209 this.expansionFactor = expansionFactor; 210 setContractionCriteria(contractionCriteria); 211 setInitialCapacity(initialCapacity); 212 internalArray = new double[initialCapacity]; 213 } 214 215 236 public ResizableDoubleArray(int initialCapacity, float expansionFactor, 237 float contractionCriteria, int expansionMode) { 238 this.expansionFactor = expansionFactor; 239 setContractionCriteria(contractionCriteria); 240 setInitialCapacity(initialCapacity); 241 setExpansionMode(expansionMode); 242 internalArray = new double[initialCapacity]; 243 } 244 245 250 public synchronized void addElement(double value) { 251 numElements++; 252 if ((startIndex + numElements) > internalArray.length) { 253 expand(); 254 } 255 internalArray[startIndex + (numElements - 1)] = value; 256 if (shouldContract()) { 257 contract(); 258 } 259 } 260 261 277 public synchronized double addElementRolling(double value) { 278 double discarded = internalArray[startIndex]; 279 280 if ((startIndex + (numElements + 1)) > internalArray.length) { 281 expand(); 282 } 283 startIndex += 1; 285 286 internalArray[startIndex + (numElements - 1)] = value; 288 289 if (shouldContract()) { 291 contract(); 292 } 293 return discarded; 294 } 295 296 306 protected void checkContractExpand( 307 float contractionCritera, 308 float expansionFactor) { 309 310 if (contractionCritera < expansionFactor) { 311 String msg = 312 "Contraction criteria can never be smaller than " + 313 "the expansion factor. This would lead to a never " + 314 "ending loop of expansion and contraction as a newly " + 315 "expanded internal storage array would immediately " + 316 "satisfy the criteria for contraction"; 317 throw new IllegalArgumentException (msg); 318 } 319 320 if (contractionCriteria <= 1.0) { 321 String msg = 322 "The contraction criteria must be a number larger " + 323 "than one. If the contractionCriteria is less than or " + 324 "equal to one an endless loop of contraction and " + 325 "expansion would ensue as an internalArray.length " + 326 "== numElements would satisfy the contraction criteria"; 327 throw new IllegalArgumentException (msg); 328 } 329 330 if (expansionFactor <= 1.0) { 331 String msg = 332 "The expansion factor must be a number greater than 1.0"; 333 throw new IllegalArgumentException (msg); 334 } 335 } 336 337 341 public synchronized void clear() { 342 numElements = 0; 343 internalArray = new double[initialCapacity]; 344 } 345 346 351 public synchronized void contract() { 352 double[] tempArray = new double[numElements + 1]; 353 354 System.arraycopy(internalArray, startIndex, tempArray, 0, numElements); 356 internalArray = tempArray; 357 358 startIndex = 0; 360 } 361 362 372 public synchronized void discardFrontElements(int i) { 373 if (i > numElements) { 374 String msg = "Cannot discard more elements than are" + 375 "contained in this array."; 376 throw new IllegalArgumentException (msg); 377 } else if (i < 0) { 378 String msg = "Cannot discard a negative number of elements."; 379 throw new IllegalArgumentException (msg); 380 } else { 381 numElements -= i; 383 startIndex += i; 384 } 385 if (shouldContract()) { 386 contract(); 387 } 388 } 389 390 398 protected synchronized void expand() { 399 400 int newSize = 0; 406 if (expansionMode == MULTIPLICATIVE_MODE) { 407 newSize = (int) Math.ceil(internalArray.length * expansionFactor); 408 } else { 409 newSize = internalArray.length + Math.round(expansionFactor); 410 } 411 double[] tempArray = new double[newSize]; 412 413 System.arraycopy(internalArray, 0, tempArray, 0, internalArray.length); 415 internalArray = tempArray; 416 } 417 418 423 private synchronized void expandTo(int size) { 424 double[] tempArray = new double[size]; 425 System.arraycopy(internalArray, 0, tempArray, 0, internalArray.length); 427 internalArray = tempArray; 428 } 429 430 442 public float getContractionCriteria() { 443 return contractionCriteria; 444 } 445 446 454 public double getElement(int index) { 455 double value = Double.NaN; 456 if (index >= numElements) { 457 String msg = 458 "The index specified: " + index + 459 " is larger than the current number of elements"; 460 throw new ArrayIndexOutOfBoundsException (msg); 461 } else if (index >= 0) { 462 value = internalArray[startIndex + index]; 463 } else { 464 String msg = 465 "Elements cannot be retrieved from a negative array index"; 466 throw new ArrayIndexOutOfBoundsException (msg); 467 } 468 return value; 469 } 470 471 478 public double[] getElements() { 479 double[] elementArray = new double[numElements]; 480 System.arraycopy( internalArray, startIndex, elementArray, 0, 481 numElements); 482 return elementArray; 483 } 484 485 497 public float getExpansionFactor() { 498 return expansionFactor; 499 } 500 501 508 public int getExpansionMode() { 509 return expansionMode; 510 } 511 512 520 int getInternalLength() { 521 return (internalArray.length); 522 } 523 524 530 public int getNumElements() { 531 return (numElements); 532 } 533 534 545 public double[] getValues() { 546 return (internalArray); 547 } 548 549 554 public void setContractionCriteria(float contractionCriteria) { 555 checkContractExpand(contractionCriteria, getExpansionFactor()); 556 this.contractionCriteria = contractionCriteria; 557 } 558 559 560 572 public synchronized void setElement(int index, double value) { 573 if (index < 0) { 574 String msg = "Cannot set an element at a negative index"; 575 throw new ArrayIndexOutOfBoundsException (msg); 576 } 577 if (index + 1 > numElements) { 578 numElements = index + 1; 579 } 580 if ((startIndex + index) >= internalArray.length) { 581 expandTo(startIndex + (index + 1)); 582 } 583 internalArray[startIndex + index] = value; 584 } 585 586 597 public void setExpansionFactor(float expansionFactor) { 598 checkContractExpand(getContractionCriteria(), expansionFactor); 599 this.expansionFactor = expansionFactor; 601 } 602 603 610 public void setExpansionMode(int expansionMode) { 611 if (expansionMode != MULTIPLICATIVE_MODE && 612 expansionMode != ADDITIVE_MODE) { 613 throw new IllegalArgumentException ("Illegal expansionMode setting."); 614 } 615 this.expansionMode = expansionMode; 616 } 617 618 625 protected void setInitialCapacity(int initialCapacity) { 626 if (initialCapacity > 0) { 627 this.initialCapacity = initialCapacity; 628 } else { 629 String msg = 630 "The initial capacity supplied: " + initialCapacity + 631 "must be a positive integer"; 632 throw new IllegalArgumentException (msg); 633 } 634 } 635 636 644 public synchronized void setNumElements(int i) { 645 646 if (i < 0) { 648 String msg = 649 "Number of elements must be zero or a positive " + "integer"; 650 throw new IllegalArgumentException (msg); 651 } 652 653 if ((startIndex + i) > internalArray.length) { 656 expandTo(startIndex + i); 657 } 658 659 numElements = i; 661 } 662 663 669 private synchronized boolean shouldContract() { 670 if (expansionMode == MULTIPLICATIVE_MODE) { 671 return (internalArray.length / numElements) > contractionCriteria; 672 } else { 673 return (internalArray.length - numElements) > contractionCriteria; 674 } 675 } 676 677 686 public int start() { 687 return startIndex; 688 } 689 690 } 691 | Popular Tags |