Technical Documentation
ATOM VECTOR: Operators

A number of arithmetic operators are defined for Atom Vectors (AV). In the following A is an AV of N atoms and D dimensions, V is an AV that has either N atoms and 1 dimension or 1 atom and D dimensions, E is an AV of N atoms and 3 dimensions and s is a scalar, i.e., an integer or a floating point value.

The binary operations are carried out side-by-side, between corresponding elements of the left and right operands. The operands are first checked and the operation is carried out only if the operands are conformal, or can be made conformal. The cross product (Vector Product) requires operands to have exactly three dimensions (and any number of atoms as long as it is the same on both operands). The cross product is carried out individually for each atom; this is not a cross product between the two operands. The scalar product equivalent is implemented as a function: DotPerAtom().

In the first four operations, if the right operand is a scalar (s), the operation is performed side-by-side between individual elements of the left operand and the single scalar value. If necessary, the scalar value is converted to a double precision floating point number before use.

In the Spread & Add and Spread & Multiply operations, the elements of the right operand are replicated either in the atom axis (if the number of atoms in V is one) or in the dimension axis (if the number of dimensions in V is one). This creates an augmented vector that is conformal with the left AV.

As long as operands are conformal, they can be of any variants: Entire or Extract, Mapped or Anonymous. The result AV is always an Entire AV and is either Mapped or Anonymous following the left operand.

The binary operations are:

Operation
Result
Left Operand
Operator
Right Operand
Addition
A
A
+
A or s
Subtraction
A
A
-
A or s
Multiplication
A
A
*
A or s
Division
A
A
/
A or s
Exponentiation
A
A
**
s
Vector Product
E
E
^
E
Spread & Add
A
A
&
V
Spread & Multiply
A
A
|
V

The ^, & and | operators are normally bitwise exclusive-or, bitwise and, and bitwise or operators respectively. However the operations are not meaningful for floating point numbers. Hence, we have redefined these operators for more useful operations. Caution: these operators have very low precedence levels while the ^ and | operators are usually intended to be used at higher precedence. Parentheses should almost always be used with these operators.

In the division operation, the right operand is checked. If at least one element is zero or if the single scalar operand is zero, the error is flagged and no division is attempted.

In the exponentiation operation, the right operand (the power) must be a scalar. If the power is an integer, the exponentiation is accomplished by nested multiplications. If the power is negative, the left operand is checked for the presence of zeroes; if there is at least one zero, the operation is not carried out and the error is flagged. The power is regarded as fractional if it is written as a floating point number even if the fractional part is zero. For fractional powers, the left operand must not contain negative numbers. If the power is negative the left operand is checked for the presence of zeroes (as with negative integer powers).

>>> from Yup.Taro.AtomVect import *
>>> A = AtomVector( numatom=2, sample='UNIFORM' )
>>> A
AtomVector[2:3] {
-0.0277413 0.648549 0.382733
-0.0690634 -0.89526 0.656545
}

>>> B = AtomVector( numatom=2, value=1 )
>>> B
AtomVector[2:3] {
1 1 1
1 1 1
}

>>> A+1
AtomVector[2:3] {
0.972259 1.64855 1.38273
0.930937 0.10474 1.65654
}

>>> A+B
AtomVector[2:3] {
0.972259 1.64855 1.38273
0.930937 0.10474 1.65654
}

>>>

The above example shows how a scalar right operand is treated like an AV that is filled with only one value, the scalar value.

The unary operator abs() is actually a function.

The unary operations are:

Operation
Result
Operator
Operand
Negation
A
-
A
Absolute Values
A
abs()
A
Reciprocation
A
~
A

The reciprocation operator co-opts the bitwise inversion operator. However, the inversion operation is not meaningful for floating point numbers. Thus, we have redefined the operator to return the reciprocal which is after all an inverse.

In the reciprocation operations, the operand is first checked for the presence of zeroes; if at least one is present the operation is not carried out and the error is flagged.

The binary operations also have inplace versions:

Operation
Result
Operator
Operand
Inplace Addition
A
+=
A or s
Inplace Subtraction
A
-=
A or s
Inplace Multiplication
A
*=
A or s
Inplace Division
A
/=
A or s
Inplace Exponentiation
A
**=
s
Inplace Cross Product
E
^=
E
Inplace Spread & Add
A
&=
V
Inplace Spread & Multiply
A
|=
V

These operators are not supported by Python version 1.5.2 and earlier. However, as of version 2.1, Python does not actually perform these operations in place. For example, A += B is interpreted as A = A + B: the addition results in a new AV, the AV referenced by A is removed and A is pointed to the new AV. The scale() method operates in-place and is much more efficient than, and should be used in place of the +=, -= and &= operators. The shift() method operates in-place and is much more efficient than, and should be used in place of the *=, /= and |= operators. See methods.

The following example requires some mental arithmetic. In the (inplace) Spread & Add example, the column vector on the right is duplicated and added to every column of the left operand. In the (inplace) Spread and Multiply example, the row vector on the right is duplicated and multiplied on every row of the left operand.

>>> from Yup.Taro.AtomVect import *
>>> A = AtomVector( numatom=2, numdimen=5, sample='GAUSSIAN' )
>>> x = AtomVector( numatom=2, numdimen=1, sample='UNIFORM' )
>>> y = AtomVector( numatom=1, numdimen=5, sample='UNIFORM' )
>>> A
AtomVector[2:5] {
-1.32624 1.0387 2.26008 0.0746788 -0.190893
-0.214545 -1.74816 0.961699 -0.475478 1.65758
}

>>> x
AtomVector[2:1] {
0.209204
0.135594
}

>>> A &= x
>>> A
AtomVector[2:5] {
-1.11704 1.2479 2.46928 0.283883 0.0183111
-0.0789514 -1.61257 1.09729 -0.339885 1.79318
}

>>> y
AtomVector[1:5] {
0.74572 0.0846278 0.524339 -0.972106 -0.305643
}

>>> A |= y
>>> A
AtomVector[2:5] {
-0.832998 0.105607 1.29474 -0.275965 -0.00559666
-0.0588756 -0.136468 0.575353 0.330404 -0.548071
}

>>>

Be careful of operator precedence. Although we have redefined some operators from their traditional meanings, the precedence of these operators remain as before. As is usual in such cases, copious use of parentheses will remove any ambiguity.

Intro
New
Print
Compare
Operators
Data
Methods
Functions
Subscript
Files

Technical
Introduction
Directory
Vectors
Energy
Model
Assembly
Methods
FPF
FFF
AVF
TaroScript
YammpScript
Python
Utilities

Home
Information
News
User
Technical
Programmer
iYup
Download
Showcase
ETC