001package algs12;
002import stdlib.*;
003/* ***********************************************************************
004 *  Compilation:  javac Vector.java
005 *  Execution:    java Vector
006 *
007 *  Implementation of a vector of real numbers.
008 *
009 *  This class is implemented to be immutable: once the client program
010 *  initialize a Vector, it cannot change any of its fields
011 *  (N or data[i]) either directly or indirectly. Immutability is a
012 *  very desirable feature of a data type.
013 *
014 *  % java Vector
015 *     x     = [ 1.0 2.0 3.0 4.0 ]
016 *     y     = [ 5.0 2.0 4.0 1.0 ]
017 *     z     = [ 6.0 4.0 7.0 5.0 ]
018 *   10z     = [ 60.0 40.0 70.0 50.0 ]
019 *    |x|    = 5.477225575051661
020 *   <x, y>  = 25.0
021 *
022 *
023 *  Note that Vector is also the name of an unrelated Java library class.
024 *
025 *************************************************************************/
026
027public class Vector {
028
029        private final int N;               // length of the vector
030        private final double[] data;       // array of vector's components
031
032
033        // create the zero vector of length n
034        public Vector(int n) {
035                N = n;
036                data = new double[N];
037        }
038
039        // create a vector from either an array or a vararg list
040        // this constructor uses Java's vararg syntax to support
041        // a constructor that takes a variable number of arguments, such as
042        // Vector x = new Vector(1.0, 2.0, 3.0, 4.0);
043        // Vector y = new Vector(5.0, 2.0, 4.0, 1.0);
044        public Vector(double... d) {
045                N = d.length;
046
047                // defensive copy so that client can't alter our copy of data[]
048                data = new double[N];
049                for (int i = 0; i < N; i++)
050                        data[i] = d[i];
051        }
052        // return the length of the vector
053        public int length() {
054                return N;
055        }
056
057        // return the inner product of this Vector a and b
058        public double dot(Vector that) {
059                if (this.N != that.N) throw new Error("Dimensions don't agree");
060                double sum = 0.0;
061                for (int i = 0; i < N; i++)
062                        sum = sum + (this.data[i] * that.data[i]);
063                return sum;
064        }
065
066        // return the Euclidean norm of this Vector
067        public double magnitude() {
068                return Math.sqrt(this.dot(this));
069        }
070
071        // return the Euclidean distance between this and that
072        public double distanceTo(Vector that) {
073                if (this.N != that.N) throw new Error("Dimensions don't agree");
074                return this.minus(that).magnitude();
075        }
076
077        // return this + that
078        public Vector plus(Vector that) {
079                if (this.N != that.N) throw new Error("Dimensions don't agree");
080                Vector c = new Vector(N);
081                for (int i = 0; i < N; i++)
082                        c.data[i] = this.data[i] + that.data[i];
083                return c;
084        }
085
086        // return this + that
087        public Vector minus(Vector that) {
088                if (this.N != that.N) throw new Error("Dimensions don't agree");
089                Vector c = new Vector(N);
090                for (int i = 0; i < N; i++)
091                        c.data[i] = this.data[i] - that.data[i];
092                return c;
093        }
094
095        // return the corresponding coordinate
096        public double cartesian(int i) {
097                return data[i];
098        }
099
100        // create and return a new object whose value is (this * factor)
101        public Vector times(double factor) {
102                Vector c = new Vector(N);
103                for (int i = 0; i < N; i++)
104                        c.data[i] = factor * data[i];
105                return c;
106        }
107
108
109        // return the corresponding unit vector
110        public Vector direction() {
111                if (this.magnitude() == 0.0) throw new Error("Zero-vector has no direction");
112                return this.times(1.0 / this.magnitude());
113        }
114
115
116        // return a string representation of the vector
117        public String toString() {
118                String s = "";
119                for (int i = 0; i < N; i++)
120                        s = s + data[i] + " ";
121                return s;
122        }
123
124
125
126
127        // test client
128        public static void main(String[] args) {
129                double[] xdata = { 1.0, 2.0, 3.0, 4.0 };
130                double[] ydata = { 5.0, 2.0, 4.0, 1.0 };
131                Vector x = new Vector(xdata);
132                Vector y = new Vector(ydata);
133
134                StdOut.println("   x       = " + x);
135                StdOut.println("   y       = " + y);
136
137                Vector z = x.plus(y);
138                StdOut.println("   z       = " + z);
139
140                z = z.times(10.0);
141                StdOut.println(" 10z       = " + z);
142
143                StdOut.println("  |x|      = " + x.magnitude());
144                StdOut.println(" <x, y>    = " + x.dot(y));
145                StdOut.println("dist(x, y) = " + x.distanceTo(y));
146                StdOut.println("dir(x)     = " + x.direction());
147
148        }
149}