001/* 002* ParameterVector -- A n-dimensional vector of Parameter objects. 003* 004* Copyright (C) 2009-2014 by Joseph A. Huwaldt. 005* All rights reserved. 006* 007* This library is free software; you can redistribute it and/or 008* modify it under the terms of the GNU Lesser General Public 009* License as published by the Free Software Foundation; either 010* version 2 of the License, or (at your option) any later version. 011* 012* This library is distributed in the hope that it will be useful, 013* but WITHOUT ANY WARRANTY; without even the implied warranty of 014* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015* Lesser General Public License for more details. 016* 017* You should have received a copy of the GNU Lesser General Public License 018* along with this program; if not, write to the Free Software 019* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 020* Or visit: http://www.gnu.org/licenses/lgpl.html 021**/ 022package jahuwaldt.js.param; 023 024import java.util.List; 025 026import javax.measure.unit.Unit; 027import javax.measure.unit.SI; 028import javax.measure.unit.NonSI; 029import javax.measure.converter.UnitConverter; 030import javax.measure.converter.ConversionException; 031import javax.measure.quantity.*; 032 033import javolution.lang.MathLib; 034import javolution.context.ObjectFactory; 035import javolution.context.StackContext; 036import javolution.lang.ValueType; 037import javolution.util.FastTable; 038import javolution.xml.XMLFormat; 039import javolution.xml.stream.XMLStreamException; 040import javolution.xml.XMLSerializable; 041 042import org.jscience.mathematics.number.Float64; 043import org.jscience.mathematics.vector.*; 044 045 046/** 047* <p> This class represents an n-dimensional {@link Vector vector} of {@link Parameter} 048* elements sharing the same units.</p> 049* 050* <p> Modified by: Joseph A. Huwaldt </p> 051* 052* @author Joseph A. Huwaldt Date: March 27, 2009 053* @version March 1, 2014 054**/ 055public class ParameterVector<Q extends Quantity> extends AbstractParamVector<Q,ParameterVector<Q>> 056 implements ValueType, XMLSerializable { 057 058 private static final long serialVersionUID = -1026285730707259617L; 059 060 /** 061 * Constant used to identify the X (0) coordinate in the vector. 062 **/ 063 public static final int X = 0; 064 065 /** 066 * Constant used to identify the Y (1) coordinate in the vector. 067 **/ 068 public static final int Y = 1; 069 070 /** 071 * Constant used to identify the Z (2) coordinate in the vector. 072 **/ 073 public static final int Z = 2; 074 075 076 /** 077 * The coordinates are stored in this vector. 078 * Serialization is handled by this class since Float64Vector is not Serializable. 079 **/ 080 protected transient Float64Vector _data; 081 082 /** 083 * Holds the unit of the coordinates. 084 **/ 085 protected Unit<Q> _unit; 086 087 088 /** 089 * Returns a 2D {@link ParameterVector} instance holding the specified <code>double</code> values 090 * stated in the specified units. 091 * 092 * @param x the x value stated in the specified unit. 093 * @param y the y value stated in the specified unit. 094 * @param unit the unit in which the coordinates are stated. 095 * @return the vector having the specified values. 096 */ 097 public static <Q extends Quantity> ParameterVector<Q> valueOf(double x, double y, Unit<Q> unit) { 098 ParameterVector<Q> V = newInstance(unit); 099 100 V._data = Float64Vector.valueOf(x, y); 101 102 return V; 103 } 104 105 /** 106 * Returns a {@link ParameterVector} instance holding the specified <code>double</code> values 107 * stated in the specified units. 108 * 109 * @param x the x value stated in the specified unit. 110 * @param y the y value stated in the specified unit. 111 * @param z the z value stated in the specified unit. 112 * @param unit the unit in which the coordinates are stated. 113 * @return the vector having the specified values. 114 */ 115 public static <Q extends Quantity> ParameterVector<Q> valueOf(double x, double y, double z, Unit<Q> unit) { 116 ParameterVector<Q> V = newInstance(unit); 117 118 V._data = Float64Vector.valueOf(x, y, z); 119 120 return V; 121 } 122 123 /** 124 * Returns a {@link ParameterVector} instance holding the specified <code>double</code> values 125 * stated in the specified units. 126 * 127 * @param unit the unit in which the coordinates are stated. 128 * @param values A list of values to store in the vector. 129 * @return the vector having the specified values. 130 */ 131 public static <Q extends Quantity> ParameterVector<Q> valueOf(Unit<Q> unit, double... values) { 132 ParameterVector<Q> V = newInstance(unit); 133 134 V._data = Float64Vector.valueOf(values); 135 136 return V; 137 } 138 139 /** 140 * Returns a {@link ParameterVector} instance holding the specified <code>Parameter</code> values. 141 * All the values are converted to the same units as the x value. 142 * 143 * @param x the x value. 144 * @param y the y value. 145 * @param z the z value. 146 * @return the vector having the specified values in the units of x. 147 */ 148 public static <Q extends Quantity> ParameterVector<Q> valueOf(Parameter<Q> x, Parameter<Q> y, Parameter<Q> z) { 149 150 Unit<Q> unit = x.getUnit(); 151 ParameterVector<Q> V = newInstance(unit); 152 V._data = Float64Vector.valueOf(x.getValue(), y.getValue(unit), z.getValue(unit)); 153 154 return V; 155 } 156 157 /** 158 * Returns a {@link ParameterVector} instance holding the specified <code>Parameter</code> values. 159 * All the values are converted to the same units as the first value. 160 * 161 * @param values A list of values to store in the vector. 162 * @return the vector having the specified values in the units of x. 163 */ 164 public static <Q extends Quantity> ParameterVector<Q> valueOf(List<Parameter<Q>> values) { 165 FastTable<Float64> valueList = FastTable.newInstance(); 166 167 Unit<Q> unit = values.get(0).getUnit(); 168 int size = values.size(); 169 for (int i=0; i < size; ++i) { 170 Parameter<Q> param = values.get(i); 171 Float64 value = Float64.valueOf(param.getValue(unit)); 172 valueList.add(value); 173 } 174 175 ParameterVector<Q> V = newInstance(unit); 176 V._data = Float64Vector.valueOf(valueList); 177 178 FastTable.recycle(valueList); 179 180 return V; 181 } 182 183 /** 184 * Returns a {@link ParameterVector} instance holding the specified <code>Parameter</code> values. 185 * All the values are converted to the same units as the first value. 186 * 187 * @param values A list of values to store in the vector. 188 * @return the vector having the specified values in the units of x. 189 */ 190 public static <Q extends Quantity> ParameterVector<Q> valueOf(Parameter<Q>... values) { 191 FastTable<Float64> valueList = FastTable.newInstance(); 192 193 Unit<Q> unit = values[0].getUnit(); 194 int size = values.length; 195 for (int i=0; i < size; ++i) { 196 Parameter<Q> param = values[i]; 197 Float64 value = Float64.valueOf(param.getValue(unit)); 198 valueList.add(value); 199 } 200 201 ParameterVector<Q> V = newInstance(unit); 202 V._data = Float64Vector.valueOf(valueList); 203 204 FastTable.recycle(valueList); 205 206 return V; 207 } 208 209 /** 210 * Returns a {@link ParameterVector} instance containing the specified vector of Float64 values 211 * stated in the specified units. 212 * 213 * @param vector the vector of Float64 values stated in the specified unit. 214 * @param unit the unit in which the coordinates are stated. 215 * @return the vector having the specified values. 216 */ 217 public static <Q extends Quantity> ParameterVector<Q> valueOf(Vector<Float64> vector, Unit<Q> unit) { 218 219 ParameterVector<Q> V = newInstance(unit); 220 V._data = Float64Vector.valueOf(vector); 221 222 return V; 223 } 224 225 /** 226 * Returns a {@link ParameterVector} instance containing the 227 * specified vector of Parameter values with compatible units. 228 * All the values are converted to the same units as the 1st value. 229 * 230 * @param vector the vector of Parameter values stated in the specified unit. 231 * @return the vector having the specified values. 232 */ 233 public static <Q extends Quantity> ParameterVector<Q> valueOf(Vector<Parameter<Q>> vector) { 234 if (vector instanceof ParameterVector) 235 return (ParameterVector<Q>)vector; 236 237 Unit<Q> unit = vector.get(0).getUnit(); 238 FastTable<Float64> valueList = FastTable.newInstance(); 239 240 int size = vector.getDimension(); 241 for (int i=0; i < size; ++i) { 242 Parameter<Q> param = vector.get(i); 243 Float64 value = Float64.valueOf(param.getValue(unit)); 244 valueList.add(value); 245 } 246 247 ParameterVector<Q> V = newInstance(unit); 248 V._data = Float64Vector.valueOf(valueList); 249 250 FastTable.recycle(valueList); 251 252 return V; 253 } 254 255 256 /** 257 * Returns a Vector3D representation of this vector if possible. 258 * 259 * @return A Vector3D that is equivalent to this vector 260 * @throws DimensionException if this vector has any number of dimensions 261 * other than 3. 262 **/ 263 @Override 264 public Vector3D<Q> toVector3D() { 265 if (getDimension() != 3) 266 throw new DimensionException( RESOURCES.getString("pvNumElementsErr") ); 267 return (Vector3D<Q>)Vector3D.valueOf(this); 268 } 269 270 /** 271 * Return the specified {@link Vector3D} object as a <code>ParameterVector</code> instance. 272 * 273 * @param vector The <code>Vector3D</code> object to be converted to a <code>ParameterVector</code>. 274 * @return A <code>ParameterVector</code> instance that is equivalent to the 275 * supplied <code>Vector3D</code> object. 276 **/ 277 @Override 278 public ParameterVector<Q> fromVector3D(Vector3D<Q> vector) { 279 return (ParameterVector<Q>)ParameterVector.valueOf(vector); 280 } 281 282 /** 283 * Returns the number of elements held by this vector. 284 * 285 * @return this vector dimension. 286 */ 287 @Override 288 public int getDimension() { 289 return _data.getDimension(); 290 } 291 292 /** 293 * Returns the value of a Parameter from this vector. 294 * 295 * @param i the dimension index. 296 * @return the value of the parameter at <code>i</code>. 297 * @throws IndexOutOfBoundsException <code>(i < 0) || (i >= dimension())</code> 298 */ 299 @Override 300 public Parameter<Q> get(int i) { 301 return Parameter.valueOf(getValue(i), getUnit()); 302 } 303 304 /** 305 * Returns the value of the Parameter in this vector as a <code>double</code>, 306 * stated in this vector's {@link #getUnit unit}. 307 * 308 * @param i the dimension index. 309 * @return the value of the Parameter at <code>i</code>. 310 * @throws IndexOutOfBoundsException <code>(i < 0) || (i >= dimension())</code> 311 */ 312 @Override 313 public double getValue(int i) { 314 return _data.getValue(i); 315 } 316 317 /** 318 * Returns the {@link #norm}, magnitude, or length value of this vector. 319 * 320 * @return <code>this.norm().doubleValue()</code>. 321 */ 322 @Override 323 public double normValue() { 324 return _data.normValue(); 325 } 326 327 /** 328 * Returns the negation of this vector. 329 * 330 * @return <code>-this</code>. 331 */ 332 @Override 333 public ParameterVector<Q> opposite() { 334 ParameterVector<Q> V = newInstance(this._unit); 335 V._data = this._data.opposite(); 336 return V; 337 } 338 339 /** 340 * Returns the sum of this vector with the one specified. 341 * The unit of the output vector will be the units of 342 * this vector. 343 * 344 * @param that the vector to be added. 345 * @return <code>this + that</code>. 346 * @throws DimensionException if vector dimensions are different. 347 * @throws ConversionException if the input vector is not in units 348 * consistent with this vector. 349 */ 350 @Override 351 public ParameterVector<Q> plus(Vector<Parameter<Q>> that) { 352 353 if (that.getDimension() != this.getDimension()) 354 throw new DimensionException(); 355 356 // Convert input vector to a Float64Vector (with unit conversion if necessary). 357 Float64Vector thatData = toFloat64Vector(that, this._unit); 358 359 ParameterVector<Q> V = newInstance(this._unit); 360 V._data = this._data.plus(thatData); 361 362 return V; 363 } 364 365 /** 366 * Returns the sum of this vector with the parameter specified. 367 * The input parameter is added to each component of this vector. 368 * The unit of the output vector will be the units of 369 * this vector. 370 * 371 * @param that the parameter to be added to each element of this vector. 372 * @return <code>this + that</code>. 373 */ 374 @Override 375 public ParameterVector<Q> plus(Parameter<Q> that) { 376 377 // Convert input parameter to the units of this vector. 378 double thatValue = that.getValue(this._unit); 379 380 StackContext.enter(); 381 try { 382 FastTable<Float64> valueList = FastTable.newInstance(); 383 int numDims = _data.getDimension(); 384 for (int i = 0; i < numDims; ++i) { 385 double value = this._data.getValue(i) + thatValue; 386 valueList.add(Float64.valueOf(value)); 387 } 388 ParameterVector<Q> V = newInstance(this._unit); 389 V._data = Float64Vector.valueOf(valueList); 390 391 return StackContext.outerCopy(V); 392 } finally { 393 StackContext.exit(); 394 } 395 } 396 397 /** 398 * Returns the difference between this vector and the one specified. 399 * The unit of the output vector will be the units of 400 * this vector. 401 * 402 * @param that the vector to be subtracted. 403 * @return <code>this - that</code>. 404 * @throws DimensionException if vector dimensions are different. 405 * @throws ConversionException if the input vector is not in units 406 * consistent with this vector. 407 */ 408 @Override 409 public ParameterVector<Q> minus(Vector<Parameter<Q>> that) { 410 411 if (that.getDimension() != this.getDimension()) 412 throw new DimensionException(); 413 414 // Convert input vector to a Float64Vector (with unit conversion if necessary). 415 Float64Vector thatData = toFloat64Vector(that, this._unit); 416 417 ParameterVector<Q> V = newInstance(this._unit); 418 V._data = this._data.minus(thatData); 419 420 return V; 421 } 422 423 /** 424 * Subtracts the supplied Parameter from each element of this vector and returns 425 * the result. The unit of the output vector will be the units of 426 * this vector. 427 * 428 * @param that the Parameter to be subtracted from each element of this vector. 429 * @return <code>this - that</code>. 430 */ 431 @Override 432 public ParameterVector<Q> minus(Parameter<Q> that) { 433 434 // Convert input parameter to the units of this vector. 435 double thatValue = that.getValue(this._unit); 436 437 StackContext.enter(); 438 try { 439 FastTable<Float64> valueList = FastTable.newInstance(); 440 int numDims = _data.getDimension(); 441 for (int i = 0; i < numDims; ++i) { 442 double value = this._data.getValue(i) - thatValue; 443 valueList.add(Float64.valueOf(value)); 444 } 445 ParameterVector<Q> V = newInstance(this._unit); 446 V._data = Float64Vector.valueOf(valueList); 447 448 return StackContext.outerCopy(V); 449 } finally { 450 StackContext.exit(); 451 } 452 } 453 454 /** 455 * Returns the product of this vector with the specified coefficient. 456 * 457 * @param k the coefficient multiplier. 458 * @return <code>this times k</code> 459 */ 460 @Override 461 @SuppressWarnings({ "unchecked", "rawtypes" }) 462 public ParameterVector times(Parameter k) { 463 ParameterVector V = FACTORY.object(); 464 465 V._unit = Parameter.productOf(this.getUnit(), k.getUnit()); 466 V._data = this._data.times(k.getValue()); 467 468 return V; 469 } 470 471 /** 472 * Returns the product of this vector with the specified coefficient. 473 * 474 * @param k the coefficient multiplier. 475 * @return <code>this times k</code> 476 */ 477 @Override 478 public ParameterVector<Q> times(double k) { 479 ParameterVector<Q> V = newInstance(this._unit); 480 V._data = _data.times(k); 481 return V; 482 } 483 484 /** 485 * Returns the dot product of this vector with the one specified. 486 * 487 * @param that the vector multiplier. 488 * @return <code>this times that</code> 489 * @throws DimensionException if <code>this.dimension() != that.dimension()</code> 490 * @see <a href="http://en.wikipedia.org/wiki/Dot_product"> 491 * Wikipedia: Dot Product</a> 492 */ 493 @SuppressWarnings("rawtypes") 494 @Override 495 public Parameter times(Vector that) { 496 497 if (that.getDimension() != this.getDimension()) 498 throw new DimensionException(); 499 500 // Convert input vector to a Float64Vector. 501 @SuppressWarnings("unchecked") 502 Float64Vector thatData = toFloat64Vector(that, null); 503 504 Float64 f = this._data.times(thatData); 505 Unit<?> unit = Parameter.productOf(this.getUnit(),((Parameter)that.get(X)).getUnit()); 506 507 return Parameter.valueOf(f.doubleValue(), unit); 508 } 509 510 /** 511 * Returns the element-by-element product of this vector with the one specified. 512 * 513 * @param that the vector multiplier. 514 * @return <code>this .* that</code> 515 * @throws DimensionException if <code>this.dimension() != that.dimension()</code> 516 */ 517 @SuppressWarnings("rawtypes") 518 public ParameterVector timesEBE(Vector that) { 519 520 if (that.getDimension() != this.getDimension()) 521 throw new DimensionException(); 522 523 StackContext.enter(); 524 try { 525 // Convert input vector to a Float64Vector. 526 @SuppressWarnings("unchecked") 527 Float64Vector thatData = toFloat64Vector(that, null); 528 529 Unit<?> unit = Parameter.productOf(this.getUnit(), ((Parameter) that.get(X)).getUnit()); 530 531 // Carry out the multiplication. 532 FastTable<Float64> valueList = FastTable.newInstance(); 533 int size = getDimension(); 534 for (int i = 0; i < size; ++i) { 535 double value = this._data.getValue(i) * thatData.getValue(i); 536 valueList.add(Float64.valueOf(value)); 537 } 538 539 ParameterVector<?> V = newInstance(unit); 540 V._data = Float64Vector.valueOf(valueList); 541 542 return StackContext.outerCopy(V); 543 } finally { 544 StackContext.exit(); 545 } 546 } 547 548 /** 549 * Returns the cross product of two vectors. 550 * 551 * @param that the vector multiplier. 552 * @return <code>this x that</code> 553 * @throws DimensionException if <code>(that.getDimension() != this.getDimension())</code> 554 * @see <a href="http://en.wikipedia.org/wiki/Cross_product"> 555 * Wikipedia: Cross Product</a> 556 */ 557 @SuppressWarnings({ "unchecked", "rawtypes" }) 558 @Override 559 public ParameterVector cross(Vector that) { 560 561 if (that.getDimension() != this.getDimension()) 562 throw new DimensionException(); 563 564 // Convert input vector to a Float64Vector. 565 Float64Vector thatData = toFloat64Vector(that, null); 566 567 Unit<?> unit = Parameter.productOf(this.getUnit(), ((Parameter)that.get(X)).getUnit()); 568 569 ParameterVector V = newInstance(unit); 570 V._data = this._data.cross(thatData); 571 572 return V; 573 } 574 575 /** 576 * Returns this vector with each element divided by the specified divisor. 577 * 578 * @param that the divisor. 579 * @return <code>this / that</code>. 580 */ 581 public ParameterVector<?> divide(Parameter<?> that) { 582 return times(that.inverse()); 583 } 584 585 /** 586 * Returns this vector converted to a unit vector by dividing all the 587 * vector's elements by the length ({@link #norm}) of this vector. 588 **/ 589 @SuppressWarnings("unchecked") 590 public ParameterVector<Dimensionless> toUnitVector() { 591 double magnitude = this.normValue(); 592 if (this.getUnit().equals(Dimensionless.UNIT) && MathLib.abs(magnitude-1) <= Parameter.EPS) 593 return (ParameterVector<Dimensionless>)this; 594 ParameterVector<Dimensionless> V = newInstance(Dimensionless.UNIT); 595 V._data = this._data.times(1.0/magnitude); 596 return V; 597 } 598 599 /** 600 * Returns a copy of this vector 601 * {@link javolution.context.AllocatorContext allocated} 602 * by the calling thread (possibly on the stack). 603 * 604 * @return an identical and independent copy of this vector. 605 */ 606 @Override 607 public ParameterVector<Q> copy() { 608 return copyOf(this); 609 } 610 611 /** 612 * Returns the unit in which the {@link #getValue values} in this vector 613 * are stated in. 614 **/ 615 @Override 616 public Unit<Q> getUnit() { 617 return _unit; 618 } 619 620 /** 621 * Returns the equivalent to this vector but stated in the 622 * specified unit. 623 * 624 * @param unit the unit of the vector to be returned. 625 * @return a vector equivalent to this vector but stated in the 626 * specified unit. 627 * @throws ConversionException if the current model does not allows for 628 * conversion to the specified unit. 629 */ 630 @SuppressWarnings("unchecked") 631 @Override 632 public <R extends Quantity> ParameterVector<R> to(Unit<R> unit) { 633 if ((_unit == unit) || this._unit.equals(unit)) 634 return (ParameterVector<R>)this; 635 636 StackContext.enter(); 637 try { 638 UnitConverter cvtr = Parameter.converterOf(_unit, unit); 639 if (cvtr == UnitConverter.IDENTITY) { // No conversion necessary. 640 ParameterVector<R> result = (ParameterVector<R>) copyOf(this); 641 result._unit = unit; 642 return StackContext.outerCopy((ParameterVector<R>)result); 643 } 644 645 FastTable<Float64> valueList = FastTable.newInstance(); 646 int size = _data.getDimension(); 647 for (int i = 0; i < size; ++i) { 648 double value = cvtr.convert(_data.getValue(i)); 649 valueList.add(Float64.valueOf(value)); 650 } 651 652 ParameterVector<R> result = newInstance(unit); 653 result._data = Float64Vector.valueOf(valueList); 654 655 return StackContext.outerCopy(result); 656 } finally { 657 StackContext.exit(); 658 } 659 } 660 661 /** 662 * Casts this ParameterVector to a parameterized unit of specified nature or 663 * throw a <code>ClassCastException</code> if the dimension of the 664 * specified quantity and this parameter's unit dimension do not match. 665 * 666 * @param type the quantity class identifying the nature of the unit. 667 * @return this ParameterVector parameterized with the specified type. 668 * @throws ClassCastException if the dimension of this parameter's unit is different 669 * from the specified quantity dimension. 670 * @throws UnsupportedOperationException if the specified quantity class 671 * does not have a public static field named "UNIT" holding the 672 * standard unit for the quantity. 673 */ 674 @SuppressWarnings("unchecked") 675 public <T extends Quantity> ParameterVector<T> asType(Class<T> type) throws ClassCastException { 676 @SuppressWarnings("unused") 677 Unit<T> u = _unit.asType(type); // If no exception is thrown, the cast is valid. 678 return (ParameterVector<T>)this; 679 } 680 681 /** 682 * Returns the values stored in this vector, stated in this vector's 683 * {@link #getUnit unit}, as a Float64Vector. 684 **/ 685 public Float64Vector toFloat64Vector() { 686 return _data; 687 } 688 689 /** 690 * Compares this ParameterVector against the specified object for strict 691 * equality (same values and same units). 692 * 693 * @param obj the object to compare with. 694 * @return <code>true</code> if this vector is identical to that 695 * vector; <code>false</code> otherwise. 696 **/ 697 @Override 698 public boolean equals(Object obj) { 699 if (this == obj) 700 return true; 701 if ((obj == null) || (obj.getClass() != this.getClass())) 702 return false; 703 704 ParameterVector<?> that = (ParameterVector<?>)obj; 705 if(!this._data.equals(that._data)) 706 return false; 707 708 return this._unit.equals(that._unit); 709 } 710 711 /** 712 * Returns the hash code for this parameter. 713 * 714 * @return the hash code value. 715 */ 716 @Override 717 public int hashCode() { 718 int hash = 7; 719 720 int var_code = _unit.hashCode(); 721 hash = hash*31 + var_code; 722 723 var_code = _data.hashCode(); 724 hash = hash*31 + var_code; 725 726 return hash; 727 } 728 729 /** 730 * Convert a vector of Parameter objects to a Float64Vector stated in 731 * the specified units. If the units are null, no conversion occurs. 732 **/ 733 private static <Q extends Quantity> Float64Vector toFloat64Vector(Vector<Parameter<Q>> that, Unit<Q> unit) { 734 735 StackContext.enter(); 736 try { 737 Float64Vector thatData; 738 Unit<?> oldUnit; 739 if (that instanceof ParameterVector) { 740 ParameterVector<Q> V = ((ParameterVector<Q>) that); 741 thatData = V.toFloat64Vector(); 742 oldUnit = V.getUnit(); 743 744 } else if (that instanceof Coordinate3D) { 745 Vector3D<Q> T = ((Coordinate3D<Q>) that).toVector3D(); 746 if (!Length.UNIT.isCompatible(T.getUnit())) 747 throw new ConversionException(RESOURCES.getString("incompatibleUnits"). 748 replace("<NAME/>", "input vector").replace("<TYPE/>", "length")); 749 oldUnit = T.getUnit(); 750 thatData = T.toFloat64Vector(); 751 752 } else { 753 ParameterVector<Q> V = valueOf(that); 754 thatData = V.toFloat64Vector(); 755 oldUnit = V.getUnit(); 756 } 757 758 759 // Convert that vector's units to the specified units if necessary. 760 if (unit != null) { 761 if (!unit.equals(oldUnit)) { 762 UnitConverter cvtr = Parameter.converterOf(oldUnit, unit); 763 if (cvtr != UnitConverter.IDENTITY) { 764 FastTable<Float64> valueList = FastTable.newInstance(); 765 int size = thatData.getDimension(); 766 for (int i = 0; i < size; ++i) { 767 double value = cvtr.convert(thatData.getValue(i)); 768 valueList.add(Float64.valueOf(value)); 769 } 770 thatData = Float64Vector.valueOf(valueList); 771 } 772 } 773 } 774 775 return StackContext.outerCopy(thatData); 776 } finally { 777 StackContext.exit(); 778 } 779 } 780 781 782 /** 783 * During serialization, this will write out the Float64Vector as a 784 * simple series of <code>double</code> values. This method is ONLY called by the Java 785 * Serialization mechanism and should not otherwise be used. 786 **/ 787 private void writeObject( java.io.ObjectOutputStream out ) throws java.io.IOException { 788 789 // Call the default write object method. 790 out.defaultWriteObject(); 791 792 // Write out the number of elements. 793 int size = _data.getDimension(); 794 out.writeInt( size ); 795 796 // Write out the coordinate values. 797 for (int i=0; i < size; ++i) 798 out.writeDouble( _data.getValue(i) ); 799 800 } 801 802 /** 803 * During de-serialization, this will handle the reconstruction 804 * of the Float64Vector. This method is ONLY called by the Java 805 * Serialization mechanism and should not otherwise be used. 806 **/ 807 private void readObject( java.io.ObjectInputStream in ) throws java.io.IOException, ClassNotFoundException { 808 809 // Call the default read object method. 810 in.defaultReadObject(); 811 812 // Read in the number of elements. 813 int size = in.readInt(); 814 815 // Read in the coordinate values. 816 FastTable<Float64> valueList = FastTable.newInstance(); 817 for (int i=0; i < size; ++i ) { 818 double value = in.readDouble(); 819 valueList.add(Float64.valueOf(value)); 820 } 821 822 _data = Float64Vector.valueOf(valueList); 823 824 FastTable.recycle(valueList); 825 } 826 827 /** 828 * Holds the default XML representation. For example: 829 * <pre> 830 * <ParameterVector unit = "m"> 831 * <Float64 value="1.0" /> 832 * <Float64 value="0.0" /> 833 * <Float64 value="2.0" /> 834 * </ParameterVector> 835 * </pre> 836 */ 837 @SuppressWarnings("rawtypes") 838 protected static final XMLFormat<ParameterVector> XML = new XMLFormat<ParameterVector>(ParameterVector.class) { 839 840 @Override 841 public ParameterVector<?> newInstance(Class<ParameterVector> cls, InputElement xml) throws XMLStreamException { 842 843 Unit<?> unit = Unit.valueOf(xml.getAttribute("unit")); 844 ParameterVector<?> V = ParameterVector.newInstance(unit); 845 846 FastTable<Float64> valueList = FastTable.newInstance(); 847 while (xml.hasNext()) { 848 Float64 value = xml.getNext(); 849 valueList.add(value); 850 } 851 V._data = Float64Vector.valueOf(valueList); 852 853 FastTable.recycle(valueList); 854 855 return V; 856 } 857 858 @Override 859 public void read(InputElement xml, ParameterVector V) throws XMLStreamException { 860 // Nothing to do. 861 } 862 863 @Override 864 public void write(ParameterVector V, OutputElement xml) throws XMLStreamException { 865 866 xml.setAttribute("unit", V._unit.toString()); 867 int size = V._data.getDimension(); 868 for (int i=0; i < size; ++i) 869 xml.add(V._data.get(i)); 870 871 } 872 }; 873 874 /////////////////////// 875 // Factory creation. // 876 /////////////////////// 877 878 protected ParameterVector() {} 879 880 @SuppressWarnings("rawtypes") 881 private static final ObjectFactory<ParameterVector> FACTORY = new ObjectFactory<ParameterVector>() { 882 @Override 883 protected ParameterVector create() { 884 return new ParameterVector(); 885 } 886 }; 887 888 /** 889 * Return a new instance of the ParameterVector class with the specified unit. 890 * The <code>_data</code> value will be undefined and must be set before 891 * using the returned object for anything. 892 **/ 893 @SuppressWarnings("unchecked") 894 protected static <Q extends Quantity> ParameterVector<Q> newInstance(Unit<Q> unit) { 895 if (unit == null) 896 throw new NullPointerException("Unit can not be null."); 897 ParameterVector<Q> measure = FACTORY.object(); 898 measure._unit = unit; 899 return measure; 900 } 901 902 @SuppressWarnings("unchecked") 903 private static <Q extends Quantity> ParameterVector<Q> copyOf(ParameterVector<Q> original) { 904 ParameterVector<Q> measure = FACTORY.object(); 905 measure._unit = original._unit; 906 measure._data = original._data.copy(); 907 return measure; 908 } 909 910 911 /** 912 * Tests the methods in this class. 913 **/ 914 public static void main (String args[]) { 915 System.out.println("Testing ParameterVector: test = result [correct result]"); 916 917 ParameterVector<Length> v1 = ParameterVector.valueOf(1, 2, 3, NonSI.FOOT); 918 System.out.println("v1 = " + v1); 919 System.out.println(" converted to m = " + v1.to(SI.METER) + " [{0.3048 m, 0.6096 m, 0.9144 m}]"); 920 System.out.println(" v1.norm() = " + v1.norm() + " [3.74165738677394 ft]"); 921 System.out.println(" v1.opposite() = " + v1.opposite() + " [{-1.0 ft, -2.0 ft, -3.0 ft}]"); 922 System.out.println(" v1.toUnitVector() = " + v1.toUnitVector() + " [{0.267261241912424 , 0.534522483824849 , 0.801783725737273 }]"); 923 924 Parameter<Length> point = Parameter.valueOf(24, NonSI.INCH); 925 System.out.println("point = " + point); 926 System.out.println(" v1 + point = " + v1.plus(point) + " [{3.0 ft, 4.0 ft, 5.0 ft}]"); 927 System.out.println(" v1 - point = " + v1.minus(point) + " [{-1.0 ft, 0.0 ft, 1.0 ft}]"); 928 System.out.println(" v1 * 2 = " + v1.times(2) + " [{2.0 ft, 4.0 ft, 6.0 ft}]"); 929 930 ParameterVector<?> areaVector = (ParameterVector<?>)v1.times(point); 931 System.out.println(" v1 * point = " + areaVector); 932 System.out.println(" converted to ft² = " + areaVector.to(NonSI.SQUARE_FOOT) + " [{2.0 ft², 4.0 ft², 6.0 ft²}]"); 933 934 935 ParameterVector<Length> v2 = ParameterVector.valueOf(1, 1, 1, SI.METER); 936 ParameterVector<?> v1xv2 = (ParameterVector<?>)v1.cross(v2); 937 System.out.println("v2 = " + v2); 938 System.out.println(" v1 + v2 = " + v1.plus(v2) + " [{4.28083989501312 ft, 5.28083989501312 ft, 6.28083989501312 ft}]"); 939 System.out.println(" v1 - v2 = " + v1.minus(v2) + " [{-2.28083989501312 ft, -1.28083989501312 ft, -0.280839895013123 ft}]"); 940 System.out.println(" v1 · v2 = " + v1.times(v2.to(NonSI.FOOT)) + " [19.6850393700787 ft²]"); 941 System.out.println(" v1.cross(v2) = " + v1xv2.to(NonSI.FOOT.pow(2)) + " [{-3.28083989501312 ft^2, 6.56167979002625 ft^2, -3.28083989501312 ft^2}]"); 942 System.out.println(" v1.angle(v2) = " + v1.angle(v2).to(NonSI.DEGREE_ANGLE) + " [73.6090476746643 deg]"); 943 944 // Write out XML data. 945 try { 946 System.out.println(); 947 948 // Creates some useful aliases for class names. 949 javolution.xml.XMLBinding binding = new javolution.xml.XMLBinding(); 950 binding.setAlias(org.jscience.mathematics.number.Float64.class, "Float64"); 951 952 javolution.xml.XMLObjectWriter writer = javolution.xml.XMLObjectWriter.newInstance(System.out); 953 writer.setIndentation(" "); 954 writer.setBinding(binding); 955 writer.write(v1, "ParameterVector", ParameterVector.class); 956 writer.flush(); 957 958 System.out.println(); 959 } catch (Exception e) { 960 e.printStackTrace(); 961 } 962 } 963}