Vectors in ScienceSuit is extremely flexible to work with. You can read from or change elements of a vector in several ways. For accessing the elements of a vector the following are the possible cases:
The first case is fairly simple; however, the 2^{nd} one requires attention.
Let's start working with the following vector, v: v = 1 2 3 4 5 6 7 8 9 10
Case 1: Accessing to single values
To change a single entry in the vector:
>>v[1]=11
>>v
11 2 3 4 5 6 7 8 9 10
To read a single entry from the vector:
>>v[1]
or >>v(1)
11
Case 2: Accessing to multiple values
Changing the 2^{nd} and the 3^{rd} entries in the vector to number 20:
>>v[{2, 3}] = 20
11 20 20 4 5 6 7 8 9 10
To change all entries to 30:
>>v[{}] = 30
30 30 30 30 30 30 30 30 30 30
Following command changes entries starting from 8^{th} element to 10:
>>v[ { from=8} ] = 10
30 30 30 30 30 30 30
10 10 10
To change entries starting from 2^{nd} element to 4^{th} element to 20:
>>v[ {from=2, to=4} ] = 20
>>v
30
20
20 20 30 30 30 10 10 10
To change entries from 1^{st }element to 10^{th} element changing by every 2^{nd} element to 20:
>>v[ {from=1, to=10, by=2} ] = 40
>>v
40 20
40 20 40 30
40 10
40 10
Let v = 1 2 3 4 5 6 7 8 9 10
Changing 1^{st} and 2^{nd} elements to 20 and 30, respectively:
>>v[ {1, 2} ] = {10, 20}
>>v
10 20 3 4 5 6 7 8 9 10
In the following 2 commands, the number of indices are different than the number of values to be assigned. In such cases, the number of assignment that occurs is the minimum of number of indices and values, i.e. if there are 3 indices and 2 values then only the first 2 indices will be assigned to the 2 values.
>>v[{1, 2, 3}] = {100, 200}
>>v
100
200 3 4 5 6 7 8 9 10
>>v[{1, 2}] = {1, 2,
100}
>>v
1 2 3 4 5 6 7 8 9 10
In a similar fashion, in the following example we request all elements to be changed; however, provide only 3 values. Therefore, only the first 3 entries have been changed.
>>v[{}] = {11, 12,13}
>>v
11 12 13 4 5 6 7 8 9 10
Let's provide 3 values on the right-hand side and request to change to the 3^{rd} element (including the 3^{rd})
>>v[{to=3}] = {1, 2,
3}
>>v
1 2 3 4 5 6 7 8 9 10
In the following command, we want to change 3 entries starting from 5^{th} element, namely 5^{th}, 6^{th} and 7^{th} entries, but provide 4 values on the right-hand side:
>>v[{from=5, to=7}] = {50, 60, 70, 80}
>>v
1 2 3
4 50 60 70 8 9 10
Similar to the previous one, in the following command, we want to change 3 entries; however, this time starting from 7^{th} element, namely 7^{th}, 6^{th} and 5^{th} entries:
>>v[{from=7,
to=5}] = {7, 6, 5}
-- note the order of the assignment,
v[7]=7...
>>v
1 2 3
4 5 6 7 8 9 10
Thus far we provided multiple values using a Lua table. However, we can also use a Vector on the right-hand side. The way assignments work is same as the previous examples. Please note that in the following example the vectors v and a have different sizes.
v = [1 2 3 4 5 6 7 8 9 10] a = [10 20 30 40 50]
>>v[{1, 2}] = a
v = 10
20 3 4 5 6 7 8 9 10
>>v[{}] = a
v= 10 20 30 40 50 6 7 8 9 10
Vector class supports essential arithmetic operations: Let v_{1}, v_{2} and v_{3} denote vectors of same size, m a matrix and a an arbitrary number.
Addition: v_{1}+v_{2}=v_{3} v_{1}+ a=a+v_{1}=v_{2}
Subtraction: v_{1}-v_{2}=v_{3} v_{1}-a=v_{2} a-v_{1}=v_{3}
Multiplication: v_{1}*v_{2}=a v_{1}*v_{2}=m a*v_{1}=v_{2 } v_{1}*v_{2}=v_{3}
Division: v_{1}/v_{2}=v_{3} v_{1}/a=v_{2} a/v_{1}=v_{3}
Exponentiation: v_{1}^a=v2 a^v_{1}=v_{3}
Note: Since a vector can have two shapes, namely column and row, during multiplication the order matters. A row*column=number, whereas a column*row=matrix. If both vectors are of same shape, then the return vector is an element-wise multiplication of both vectors.
Vector data type also supports __pairs and next methods, therefore is an iteratable container.
clone(): Makes a deep copy of the vector itself. The following two commands are equivalent:
>>v1=v:clone()
>>v1=v({})
Both will make a deep copy of v and assign the result to v_{1}.
capacity(): Shows the current capacity of the vector. This is different than member function size. Capacity shows how much memory is allocated for the Vector before it automatically resizes (therefore allocates new memory space).
equal(arg, tol=1E-5): Tests whether the elements of the Vector is equal to a
number (v_{i}==a) or elements of the Vector is equal to the elements of
another Vector (v1_{i}==v2_{i}). The equality test
is done using a predefined tolerance, which is 1E-5. The tolerance level can be
specified by the user.
>>v=std.tovector{1, 2, 3.1, 3, 5, 5}
>>v
1 2 3.1 3 5 5 COL
To obtain the elements in the vector that is equal to 3 using the default tolerance level, in other words ScienceSuit performs the following check:
$$|v[i]-3.0|\le {10}^{-5}$$
>>v:equal(3)
3
Since only one element satisfied the condition, the return value is that element's value, a number.
In the following command, we arbitrarily set the tolerance level to 0.2:
>>v:equal(3, 0.2)
3.1 3 COL
Now, it is seen that more than 1 element satisfied the condition due to a greater tolerance value, therefore, the return value is a vector containing the elements satisfying the condition.
If we want to test whether elements of the two vectors are equal with default tolerance level:
>>v1=std.tovector{1, 2, 3.1, 3, 5, 5}
>>v2=std.tovector{1, 2, 3, 3, 4, 5}
>>v1:equal(v2)
1 1 0 1 0 1 COL
In the above command, ScienceSuit performed the following check:and if the condition is satisfied the returning vector's i^{th} element is set to 1, otherwise to 0. If v and v2 were of different sizes, then an error would be thrown.
If we were to set the tolerance level to 0.2:
>>v1:equal(v2, 0.2)
1 1 1 1 0 1 COL
greater(arg): Works the same way as member function equal, except there is no tolerance defined. Tests for > operator.
greater_equal(arg): Works the same way as member function equal, except there is no tolerance defined. Tests for >= operator.
insert(pos, elem): A number or another vector is inserted to the specified position.
To insert number 10 to the 1^{st} position in the vector:
>>v=std.tovector{1, 2, 3}
>>v:insert(1, 10)
>>v
10 1 2 3 COL
To be able to insert another vector in to a specified position:
>>v=std.tovector{1, 2, 3}
>>v2=std.tovector{10, 20, 30}
>>v:insert(1, v2)
>>v
10 20 30 1 2 3 COL
less(arg): Works the same way as member function equal, except there is no tolerance defined. Tests for the < operator.
less_equal(arg): Works the same way as member function equal, except there is no tolerance defined. Tests for the <= operator.
push_back(arg): Adds an element to the end of the vector. Let v= [1 2
3] and v_{1}=[100 200]
To add a single number at the end of the vector:
>>v:push_back(4)
>>v
1 2 3 4
To append a Lua table (made up of only numbers) to the previously changed vector:
>>t={10, 20, 30}
>>v:push_back(t)
>>v
1 2 3 4 10 20 30
To append another vector to the previously modified vector:
>>v:push_back(v1)
>>v
1 2 3 4 10 20 30 100 200
reserve(num): Reserves memory for the vector to be used. If any operation, such as push_back, that changes the number of elements in the vector is greater than the current capacity then the Vector will automatically reallocate new memory and copy the elements to the new location. The default is 1000.
>>v:capacity()
1000
In the following command, we attempt to reserve number of elements less than the current capacity:<
>>v:reserve(500)
>>v:capacity()
1000
It is seen that the command was not successful since the capacity of the vector is still 1000. However, if we attempt to reserve number of elements greater than the current capacity, the command will succeed:
>>v:reserve(5000)
>>v:capacity()
5000
resize(num): Changes the size of the vector. If the requested new size is less than the current size, elements from the end will be deleted. However, if the requested new size is greater than the current size 0 will be appended. Let v=10 20 30
The original vector v is of size 3. The following command resizes the vector to 2, therefore, the last entry of the vector, number 30, is deleted:
>>v:resize(2)
10 20
Now the size of the vector is 2. If we resize the vector to 4, 0s will be appended:
>>v:resize(4)
10 20 0 0
reverse(): Reverses the order of elements.
>>v=std.tovector{1, 2, 3, 4, 5}
>>v:reverse()
>>v
5 4 3 2 1 COL
shape(): Returns the shape of the Vector. There are 3 different shapes, namely col, row and lnk. The lnk arises only when referred from a Matrix data structure. The default shape for Vector is col.
>>v=std.tovector{1, 2, 3}
>>v:shape()
col
By default, the shape of vectors are col. If we take the transpose of the vector, the shape changes to a row vector as evidenced by the following commands:
>>v2=std.trans(v)
>>v2:shape()
row
shuffle(): Randomly shuffles the positions of the elements in the vector. The size of the vector is not affected. Let v=1 2 3 4 5
>>v:shuffle()
4 1 5 2 3
slice (pos): Slices the vector into two from the given position. The vector is not affected.
>>v=std.tovector{1, 2, 3, 4, 5}
>>v1,v2=v:slice(3)
>>v1
1 2 3 COL
>>v2
4 5 COL
sort (order): The order can be either "A" or "D" for ascending and descending order sorts, respectively.
>>v=std.tovector{1,5,2,7,4}
>>v
1 5 2 7 4 COL
>>v:sort("A")
>>v
1 2 4 5 7 COL