]> gerrit.simantics Code Review - simantics/3d.git/blob - javax.vecmath/src/javax/vecmath/GVector.java
Included old javax.vecmath 1.5.2 to org.simantics.g3d.feature
[simantics/3d.git] / javax.vecmath / src / javax / vecmath / GVector.java
1 /*
2  * $RCSfile: GVector.java,v $
3  *
4  * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6  *
7  * This code is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License version 2 only, as
9  * published by the Free Software Foundation.  Sun designates this
10  * particular file as subject to the "Classpath" exception as provided
11  * by Sun in the LICENSE file that accompanied this code.
12  *
13  * This code is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16  * version 2 for more details (a copy is included in the LICENSE file that
17  * accompanied this code).
18  *
19  * You should have received a copy of the GNU General Public License version
20  * 2 along with this work; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22  *
23  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
24  * CA 95054 USA or visit www.sun.com if you need additional information or
25  * have any questions.
26  *
27  * $Revision: 1.7 $
28  * $Date: 2008/02/28 20:18:50 $
29  * $State: Exp $
30  */
31
32 package javax.vecmath;
33
34 import java.lang.Math;
35
36 /**
37  * A double precision, general, dynamically-resizable,
38  * one-dimensional vector class.  Index numbering begins with zero.
39  */
40
41 public class GVector implements java.io.Serializable, Cloneable {
42
43     private int length;
44     double[] values;
45
46     // Compatible with 1.1
47     static final long serialVersionUID = 1398850036893875112L;
48
49     /**
50      * Constructs a new GVector of the specified
51      * length with all vector elements initialized to 0.
52      * @param length the number of elements in this GVector.
53      */
54     public GVector(int length)
55         {
56             int i;
57             
58             this.length = length;           
59             values = new double[length];
60             for(i = 0; i < length; i++) values[i] = 0.0;
61         }
62     
63     /**
64      * Constructs a new GVector from the specified array elements.
65      * The length of this GVector is set to the length of the
66      * specified array.  The array elements are copied into this new
67      * GVector.
68      * @param vector the values for the new GVector.
69      */
70     public GVector(double[] vector)
71         {
72             int i;
73             
74             length = vector.length;         
75             values = new double[vector.length];
76             for(i = 0; i < length; i++) values[i] = vector[i];
77         }
78                                                           
79     /**
80      * Constructs a new GVector from the specified vector.
81      * The vector elements are copied into this new GVector.
82      * @param vector the source GVector for this new GVector.
83      */
84     public GVector(GVector vector)
85         {
86             int i;
87         
88             values = new double[vector.length];
89             length = vector.length;
90             for(i = 0; i < length; i++) values[i] = vector.values[i];
91         }
92
93     /**
94       * Constructs a new GVector and copies the initial values
95       * from the specified tuple.
96       * @param tuple the source for the new GVector's initial values
97       */
98     public GVector(Tuple2f tuple)
99         {
100             values = new double[2];
101             values[0] = (double)tuple.x;
102             values[1] = (double)tuple.y;
103             length = 2;
104         }
105
106     /** 
107       * Constructs a new GVector and copies the initial values
108       * from the specified tuple.
109       * @param tuple the source for the new GVector's initial values
110       */ 
111     public GVector(Tuple3f tuple)
112         {
113             values = new double[3];
114             values[0] = (double)tuple.x;
115             values[1] = (double)tuple.y;
116             values[2] = (double)tuple.z;
117             length = 3;
118         }
119
120     /** 
121       * Constructs a new GVector and copies the initial values
122       * from the specified tuple.
123       * @param tuple the source for the new GVector's initial values
124       */ 
125     public GVector(Tuple3d tuple)
126         {
127             values = new double[3];
128             values[0] = tuple.x;
129             values[1] = tuple.y;
130             values[2] = tuple.z;
131             length = 3;
132         }
133
134     /** 
135       * Constructs a new GVector and copies the initial values
136       * from the specified tuple.
137       * @param tuple the source for the new GVector's initial values
138       */ 
139     public GVector(Tuple4f tuple)
140         {
141             values = new double[4];
142             values[0] = (double)tuple.x;
143             values[1] = (double)tuple.y;
144             values[2] = (double)tuple.z;
145             values[3] = (double)tuple.w;
146             length = 4;
147         }
148
149     /** 
150       * Constructs a new GVector and copies the initial values
151       * from the specified tuple.
152       * @param tuple the source for the new GVector's initial values
153       */ 
154     public GVector(Tuple4d tuple)
155         {
156             values = new double[4];
157             values[0] = tuple.x;
158             values[1] = tuple.y;
159             values[2] = tuple.z;
160             values[3] = tuple.w;
161             length = 4;
162         }
163
164     /**
165      * Constructs a new GVector of the specified length and
166      * initializes it by copying the specified number of elements from
167      * the specified array.  The array must contain at least
168      * <code>length</code> elements (i.e., <code>vector.length</code> >=
169      * <code>length</code>.  The length of this new GVector is set to
170      * the specified length.
171      * @param  vector   The array from which the values will be copied.
172      * @param  length   The number of values copied from the array.
173      */
174     public GVector(double vector[], int length) {
175         int i;
176
177         this.length = length;
178         values = new double [length];
179         for(i=0;i<length;i++) {
180             values[i] = vector[i];
181         }
182     }
183
184     /**
185       * Returns the square root of the sum of the squares of this
186       * vector (its length in n-dimensional space).
187       * @return  length of this vector
188       */ 
189  
190     public final double norm()
191     {
192       double sq = 0.0;
193       int i;
194
195         for(i=0;i<length;i++) {
196             sq += values[i]*values[i];
197         }            
198
199         return(Math.sqrt(sq));
200
201     }
202
203     /** 
204       * Returns the sum of the squares of this   
205       * vector (its length squared in n-dimensional space). 
206       * @return  length squared of this vector 
207       */
208     public final double normSquared() 
209     { 
210         double sq = 0.0;
211         int i;
212
213         for(i=0;i<length;i++) {
214             sq += values[i]*values[i];
215         }            
216
217         return(sq);
218     }
219
220     /**
221      * Sets the value of this vector to the normalization of vector v1.
222      * @param v1 the un-normalized vector
223      */  
224     public final void normalize(GVector v1)
225     {
226       double sq = 0.0;
227       int i;
228
229       if( length != v1.length)
230           throw new MismatchedSizeException(VecMathI18N.getString("GVector0"));
231
232        for(i=0;i<length;i++) {
233             sq += v1.values[i]*v1.values[i];
234        }             
235
236        double invMag;
237        invMag = 1.0/Math.sqrt(sq);
238
239        for(i=0;i<length;i++) {
240           values[i] = v1.values[i]*invMag;
241        }
242     }
243
244  
245     /**
246      * Normalizes this vector in place. 
247      */  
248     public final void normalize() 
249     { 
250       double sq = 0.0;
251       int i;
252
253         for(i=0;i<length;i++) {
254             sq += values[i]*values[i];
255         }        
256
257         double invMag;
258         invMag = 1.0/Math.sqrt(sq);
259
260         for(i=0;i<length;i++) {
261             values[i] = values[i]*invMag;
262         }
263
264     } 
265
266     /**
267      * Sets the value of this vector to the scalar multiplication
268      * of the scale factor with the vector v1.
269      * @param s the scalar value
270      * @param v1 the source vector 
271      */  
272     public final void scale(double s, GVector v1)
273     {
274         int i;
275         if( length != v1.length)
276           throw new MismatchedSizeException(VecMathI18N.getString("GVector1"));
277
278         for(i=0;i<length;i++) {
279             values[i] = v1.values[i]*s;
280         }
281     }
282
283     /** 
284      * Scales this vector by the scale factor s. 
285      * @param s the scalar value 
286      */   
287     public final void scale(double s) 
288     { 
289       int i;
290
291         for(i=0;i<length;i++) {
292             values[i] = values[i]*s;
293         }
294     } 
295
296     /**
297      * Sets the value of this vector to the scalar multiplication by s
298      * of vector v1 plus vector v2 (this = s*v1 + v2).
299      * @param s the scalar value
300      * @param v1 the vector to be multiplied
301      * @param v2 the vector to be added
302      */
303     public final void scaleAdd(double s, GVector v1, GVector v2)
304     {
305
306       int i;
307
308       if( v2.length != v1.length ) 
309          throw new MismatchedSizeException(VecMathI18N.getString("GVector2"));
310
311        if( length  != v1.length )
312           throw new MismatchedSizeException(VecMathI18N.getString("GVector3"));
313
314         for(i=0;i<length;i++) {
315             values[i] = v1.values[i]*s + v2.values[i];
316         }
317     }
318
319     /**
320       * Sets the value of this vector to sum of itself and the specified
321       * vector
322       * @param vector the second vector
323       */  
324     public final void add(GVector vector)
325         {
326             int i;
327             
328           if( length  != vector.length )
329              throw new MismatchedSizeException(VecMathI18N.getString("GVector4"));
330
331            for(i = 0; i < length; i++) {
332                 this.values[i] += vector.values[i];
333            }
334         }
335
336     /**
337       * Sets the value of this vector to the vector sum of vectors vector1
338       * and vector2.
339       * @param vector1 the first vector
340       * @param vector2 the second vector
341       */  
342     public final void add(GVector vector1, GVector vector2)
343         {
344          int i;
345
346          if( vector1.length != vector2.length ) 
347            throw new MismatchedSizeException(VecMathI18N.getString("GVector5"));
348
349        if( length  != vector1.length )
350           throw new MismatchedSizeException(VecMathI18N.getString("GVector6"));
351             
352             for(i = 0; i < length; i++)
353                 this.values[i] = vector1.values[i] + vector2.values[i];
354         }
355
356     /**
357       * Sets the value of this vector to the vector difference of itself
358       * and vector (this = this - vector).
359       * @param vector the other vector
360       */  
361     public final void sub(GVector vector) 
362         { 
363             int i;
364             
365            if( length  != vector.length )
366                 throw new MismatchedSizeException(VecMathI18N.getString("GVector7"));
367
368             for(i = 0; i < length; i++) {
369                 this.values[i] -= vector.values[i];
370             }
371         } 
372
373     /**
374       * Sets the value of this vector to the vector difference
375       * of vectors vector1 and vector2 (this = vector1 - vector2).
376       * @param vector1 the first vector
377       * @param vector2 the second vector
378       */  
379     public final void sub(GVector vector1, GVector vector2) 
380         {
381             int i,l;
382             
383
384         if( vector1.length != vector2.length ) 
385           throw new MismatchedSizeException(VecMathI18N.getString("GVector8"));
386
387        if( length  != vector1.length )
388           throw new MismatchedSizeException(VecMathI18N.getString("GVector9"));
389
390             for(i = 0; i < length; i++)
391                 this.values[i] = vector1.values[i] - vector2.values[i];
392         }
393
394     /**
395       * Multiplies matrix m1 times Vector v1 and places the result
396       * into this vector (this = m1*v1).  
397       * @param m1  The matrix in the multiplication
398       * @param v1  The vector that is multiplied
399       */
400     public final void mul(GMatrix m1, GVector v1) {
401        if (m1.getNumCol() != v1.length) 
402           throw new MismatchedSizeException(VecMathI18N.getString("GVector10"));
403
404        if (length  != m1.getNumRow())
405           throw new MismatchedSizeException(VecMathI18N.getString("GVector11"));
406
407        double v[];
408        if (v1 != this) {
409            v = v1.values;
410        } else {
411            v = (double []) values.clone();
412        }
413
414        for(int j=length-1; j>=0; j--){
415           values[j] = 0.0;
416           for(int i=v1.length-1;i>=0; i--){
417             values[j] += m1.values[j][i] * v[i];
418           }
419        }
420      }
421
422     /** 
423       * Multiplies the transpose of vector v1 (ie, v1 becomes a row
424       * vector with respect to the multiplication) times matrix m1 
425       * and places the result into this vector 
426       * (this = transpose(v1)*m1).  The result is technically a 
427       * row vector, but the GVector class only knows about column
428       * vectors, and so the result is stored as a column vector.
429       * @param m1  The matrix in the multiplication
430       * @param v1  The vector that is temporarily transposed
431       */ 
432     public final void mul(GVector v1, GMatrix m1) {   
433         if (m1.getNumRow() != v1.length) 
434           throw new MismatchedSizeException(VecMathI18N.getString("GVector12"));
435
436        if (length  != m1.getNumCol())
437           throw new MismatchedSizeException(VecMathI18N.getString("GVector13"));
438
439        double v[];
440        if (v1 != this) {
441            v = v1.values;
442        } else {
443            v = (double []) values.clone();
444        }
445
446        for (int j=length-1; j>=0; j--){
447           values[j] = 0.0;
448           for(int i=v1.length-1; i>=0; i--){
449              values[j] += m1.values[i][j] * v[i];
450           }
451        }
452      }   
453
454     /** 
455       * Negates the value of this vector: this = -this.
456       */
457     public final void negate() {
458         for(int i=length-1; i>=0; i--) {
459             this.values[i] *= -1.0;
460         }
461     }
462
463     /**
464       * Sets all the values in this vector to zero.
465       */
466     public final void zero() {
467         for (int i=0; i < this.length; i++) {
468             this.values[i] = 0.0;
469         }
470     }
471
472     /**
473       * Changes the size of this vector dynamically.  If the size is increased
474       * no data values will be lost.  If the size is decreased, only those data
475       * values whose vector positions were eliminated will be lost.
476       * @param length  number of desired elements in this vector
477       */
478     public final void setSize(int length) {
479            double[] tmp = new double[length];
480            int i,max;
481
482            if( this.length < length)
483               max = this.length;
484            else
485                max = length;
486
487            for(i=0;i<max;i++) {
488               tmp[i] = values[i];
489            }
490            this.length = length;
491
492            values = tmp;
493
494         }
495
496     /**
497       * Sets the value of this vector to the values found in the array 
498       * parameter. The array should be at least equal in length to
499       * the number of elements in the vector.
500       * @param vector  the source array
501       */  
502     public final void set(double[] vector) {
503         for(int i = length-1; i >=0; i--) 
504             values[i] = vector[i];
505     }
506
507     /**
508       * Sets the value of this vector to the values found in vector vector.
509       * @param vector  the source vector
510       */
511     public final void set(GVector vector) {
512         int i;
513         
514         if (length < vector.length) {
515             length = vector.length;
516             values = new double[length];
517             for(i = 0; i < length; i++) 
518                 values[i] = vector.values[i];
519         }else {
520             for(i = 0; i < vector.length; i++)
521                 values[i] = vector.values[i];
522             for(i = vector.length; i < length; i++)
523                 values[i] = 0.0;
524         }
525     }
526
527     /**
528       * Sets the value of this vector to the values in tuple
529       * @param tuple the source for the new GVector's new values
530       */ 
531     public final void set(Tuple2f tuple)
532         {
533             if (length < 2) {
534                length = 2;
535                values = new double[2];
536             }
537             values[0] = (double)tuple.x;
538             values[1] = (double)tuple.y;
539             for(int i = 2; i < length; i++) values[i] = 0.0;
540
541         }
542
543     /** 
544       * Sets the value of this vector to the values in tuple
545       * @param tuple the source for the new GVector's new values
546       */ 
547     public final void set(Tuple3f tuple)
548         {
549             if (length < 3) {
550                length = 3;
551                values = new double[3];
552             }
553             values[0] = (double)tuple.x;
554             values[1] = (double)tuple.y;
555             values[2] = (double)tuple.z;
556             for(int i = 3; i < length; i++) values[i] = 0.0;
557         }
558
559     /** 
560       * Sets the value of this vector to the values in tuple
561       * @param tuple the source for the new GVector's new values
562       */ 
563     public final void set(Tuple3d tuple)
564         {
565             if (length < 3) {
566                length = 3;
567                values = new double[3];
568             }
569             values[0] = tuple.x;
570             values[1] = tuple.y;
571             values[2] = tuple.z;
572             for(int i = 3; i < length; i++) values[i] = 0.0;
573         }
574
575     /** 
576       * Sets the value of this vector to the values in tuple
577       * @param tuple the source for the new GVector's new values
578       */ 
579     public final void set(Tuple4f tuple)
580         {
581             if (length < 4) {
582                length = 4;
583                values = new double[4];
584             }
585             values[0] = (double)tuple.x;
586             values[1] = (double)tuple.y;
587             values[2] = (double)tuple.z;
588             values[3] = (double)tuple.w;
589             for(int i = 4; i < length; i++) values[i] = 0.0;
590         }
591
592     /** 
593       * Sets the value of this vector to the values in tuple
594       * @param tuple the source for the new GVector's new values
595       */ 
596     public final void set(Tuple4d tuple)
597         {
598             if (length < 4) {
599                length = 4;
600                values = new double[4];
601             }
602             values[0] = tuple.x;
603             values[1] = tuple.y;
604             values[2] = tuple.z;
605             values[3] = tuple.w;
606             for(int i = 4; i < length; i++) values[i] = 0.0;
607         }
608
609     /**
610       * Returns the number of elements in this vector.
611       * @return  number of elements in this vector
612       */
613     public final int getSize()
614         {
615             return values.length;
616         }
617
618     /**
619       * Retrieves the value at the specified index value of this vector.
620       * @param index the index of the element to retrieve (zero indexed)
621       * @return the value at the indexed element
622       */  
623     public final double getElement(int index)
624         {
625             return values[index];
626         }
627
628  
629     /**  
630       * Modifies the value at the specified index of this vector.
631       * @param index  the index if the element to modify (zero indexed) 
632       * @param value  the new vector element value
633       */   
634     public final void setElement(int index, double value)
635         {
636             values[index] = value;
637         }
638
639     /**
640       * Returns a string that contains the values of this GVector.
641       * @return the String representation
642       */  
643     public String toString() {
644       StringBuffer buffer = new StringBuffer(length*8);
645
646       int i;
647
648       for(i=0;i<length;i++) {
649            buffer.append(values[i]).append(" ");
650       }
651
652       return buffer.toString();
653
654     }
655
656
657     /**
658      * Returns a hash code value based on the data values in this
659      * object.  Two different GVector objects with identical data
660      * values (i.e., GVector.equals returns true) will return the
661      * same hash number.  Two GVector objects with different data
662      * members may return the same hash value, although this is not
663      * likely.
664      * @return the integer hash code value
665      */
666     public int hashCode() {
667         long bits = 1L;
668
669         for (int i = 0; i < length; i++) {
670             bits = 31L * bits + VecMathUtil.doubleToLongBits(values[i]);
671         }
672
673         return (int) (bits ^ (bits >> 32));
674     } 
675
676
677     /**
678       * Returns true if all of the data members of GVector vector1 are
679       * equal to the corresponding data members in this GVector.
680       * @param vector1  The vector with which the comparison is made.
681       * @return  true or false
682       */  
683     public boolean equals(GVector vector1)
684         {
685         try { 
686             if( length != vector1.length)   return false;
687
688             for(int i = 0;i<length;i++) {
689               if( values[i] != vector1.values[i]) return false;
690             }
691
692             return true;
693         }
694         catch (NullPointerException e2) { return false; }
695
696          }
697     /**
698      * Returns true if the Object o1 is of type GMatrix and all of the
699      * data members of o1 are equal to the corresponding data members in
700      * this GMatrix.
701      * @param o1  The object with which the comparison is made.
702      * @return  true or false
703      */  
704     public boolean equals(Object o1)
705     {
706         try {   
707             GVector v2 = (GVector) o1;
708
709             if( length != v2.length)   return false;
710
711             for(int i = 0;i<length;i++) {
712               if( values[i] != v2.values[i]) return false;
713             }
714             return true;
715         }
716         catch (ClassCastException   e1) { return false; }
717         catch (NullPointerException e2) { return false; }
718
719     }
720
721    /**
722      * Returns true if the L-infinite distance between this vector
723      * and vector v1 is less than or equal to the epsilon parameter, 
724      * otherwise returns false.  The L-infinite
725      * distance is equal to 
726      * MAX[abs(x1-x2), abs(y1-y2), . . .  ].
727      * @param v1  The vector to be compared to this vector
728      * @param epsilon  the threshold value  
729      */
730     public boolean epsilonEquals(GVector v1, double epsilon)
731     {
732        double diff;
733
734             if( length != v1.length)   return false;
735
736             for(int i = 0;i<length;i++) {
737                 diff = values[i] - v1.values[i];
738                 if( (diff<0?-diff:diff) > epsilon) return false;
739             }
740             return true;
741     }
742
743   /**
744     * Returns the dot product of this vector and vector v1.
745     * @param v1 the other vector
746     * @return the dot product of this and v1
747     */
748    public final double dot(GVector v1)
749      {
750        if( length != v1.length)  
751                throw new MismatchedSizeException(VecMathI18N.getString("GVector14"));
752
753        double result = 0.0;
754        for(int i = 0;i<length;i++) {
755           result += values[i] * v1.values[i];
756        }
757        return result;
758      }
759  
760  
761   /**
762     *  Solves for x in Ax = b, where x is this vector (nx1), A is mxn,
763     *  b is mx1, and A = U*W*transpose(V); U,W,V must
764     *  be precomputed and can be found by taking the singular value 
765     *  decomposition (SVD) of A using the method SVD found in the 
766     *  GMatrix class.
767     *  @param U  The U matrix produced by the GMatrix method SVD
768     *  @param W  The W matrix produced by the GMatrix method SVD
769     *  @param V  The V matrix produced by the GMatrix method SVD
770     *  @param b  The b vector in the linear equation Ax = b
771     */
772    public final void SVDBackSolve(GMatrix U, GMatrix W, GMatrix V, GVector b)
773     {
774        if( !(U.nRow == b.getSize() &&
775              U.nRow == U.nCol      &&
776              U.nRow == W.nRow  ) ) {
777             throw new MismatchedSizeException(VecMathI18N.getString("GVector15"));
778        }
779
780        if( !(W.nCol == values.length &&
781              W.nCol == V.nCol        &&
782              W.nCol == V.nRow  ) ) {
783             throw new MismatchedSizeException(VecMathI18N.getString("GVector23"));
784        }
785
786        GMatrix tmp = new GMatrix( U.nRow, W.nCol);
787        tmp.mul( U, V);
788        tmp.mulTransposeRight( U, W);
789        tmp.invert();
790        mul(tmp, b);
791
792     }
793
794    /**
795      * LU Decomposition Back Solve; this method takes the LU matrix
796      * and the permutation vector produced by the GMatrix method LUD
797      * and solves the equation (LU)*x = b by placing the solution vector
798      * x into this vector.  This vector should be the same length or 
799      * longer than b.  
800      * @param LU  The matrix into which the lower and upper decompostions
801      * have been placed
802      * @param b  The b vector in the equation (LU)*x = b
803      * @param permutation  The row permuations that were necessary to 
804      * produce the LU matrix parameter
805      */ 
806    public final void LUDBackSolve(GMatrix LU, GVector b, GVector permutation)
807    {
808        int size = LU.nRow*LU.nCol;
809
810        double[] temp = new double[size];
811        double[] result = new double[size];
812        int[] row_perm = new int[b.getSize()]; 
813        int i,j;
814
815        if( LU.nRow != b.getSize() ) {
816             throw new MismatchedSizeException(VecMathI18N.getString("GVector16"));
817        }
818
819        if( LU.nRow != permutation.getSize() ) {
820             throw new MismatchedSizeException(VecMathI18N.getString("GVector24"));
821        }
822
823        if (LU.nRow != LU.nCol) {
824             throw new MismatchedSizeException(VecMathI18N.getString("GVector25"));
825        }
826
827         for(i=0;i<LU.nRow;i++) {
828            for(j=0;j<LU.nCol;j++) {
829                temp[i*LU.nCol+j] = LU.values[i][j];
830            }
831         }
832
833        for(i=0;i<size;i++) result[i] = 0.0; 
834        for(i=0;i<LU.nRow;i++) result[i*LU.nCol] = b.values[i]; 
835        for(i=0;i<LU.nCol;i++) row_perm[i] = (int)permutation.values[i]; 
836
837        GMatrix.luBacksubstitution(LU.nRow, temp, row_perm, result);
838
839        for(i=0;i<LU.nRow;i++) this.values[i] = result[i*LU.nCol]; 
840    }
841
842   /**
843     *   Returns the (n-space) angle in radians between this vector and
844     *   the vector parameter; the return value is constrained to the
845     *   range [0,PI].
846     *   @param v1    The other vector
847     *   @return   The angle in radians in the range [0,PI]
848     */
849    public final double angle(GVector v1)
850    {
851    return( Math.acos( this.dot(v1) / ( this.norm()*v1.norm() ) ) );
852    }
853
854
855     /**
856      * @deprecated Use interpolate(GVector, GVector, double) instead
857      */
858     public final void interpolate(GVector v1, GVector v2, float alpha) {
859         interpolate(v1, v2, (double)alpha);
860     }
861
862
863     /**
864      * @deprecated Use interpolate(GVector, double) instead
865      */
866     public final void interpolate(GVector v1, float alpha) {
867         interpolate(v1, (double)alpha);
868     }
869
870
871   /**
872     *  Linearly interpolates between vectors v1 and v2 and places the
873     *  result into this tuple:  this = (1-alpha)*v1 + alpha*v2.
874     *  @param v1  the first vector
875     *  @param v2  the second vector
876     *  @param alpha  the alpha interpolation parameter   
877     */   
878   public final void interpolate(GVector v1, GVector v2, double alpha)
879   {
880         if( v2.length != v1.length ) 
881           throw new MismatchedSizeException(VecMathI18N.getString("GVector20"));
882
883        if( length  != v1.length )
884           throw new MismatchedSizeException(VecMathI18N.getString("GVector21"));
885
886        for(int i=0;i<length;i++) {
887           values[i] = (1-alpha)*v1.values[i] + alpha*v2.values[i];
888        }
889   }
890
891   /**    
892     *  Linearly interpolates between this vector and vector v1 and 
893     *  places the result into this tuple:  this = (1-alpha)*this + alpha*v1.
894     *  @param v1  the first vector 
895     *  @param alpha  the alpha interpolation parameter   
896     */
897   public final void interpolate(GVector v1, double alpha)
898   {
899        if( v1.length != length )
900           throw new MismatchedSizeException(VecMathI18N.getString("GVector22"));
901
902        for(int i=0;i<length;i++) {
903           values[i] = (1-alpha)*values[i] + alpha*v1.values[i];
904        }
905   }
906  
907     /**
908      * Creates a new object of the same class as this object.
909      *
910      * @return a clone of this instance.
911      * @exception OutOfMemoryError if there is not enough memory.
912      * @see java.lang.Cloneable
913      * @since vecmath 1.3
914      */
915     public Object clone() {
916         GVector v1 = null;
917         try {
918             v1 = (GVector)super.clone();
919         } catch (CloneNotSupportedException e) {
920             // this shouldn't happen, since we are Cloneable
921             throw new InternalError();
922         }
923
924         // Also need to clone array of values
925         v1.values = new double[length];
926         for (int i = 0; i < length; i++) {
927             v1.values[i] = values[i];
928         }
929
930         return v1;
931     }
932
933 }