*Appendix A.2. Complex Quantities*

Section 2.2 described data processing for real-valued quantities, but very similar formulae apply to complex quantities. These are also implemented in GTC. A review of measurement uncertainty for complex quantities has been given by Hall [19].

GTC can handle mathematical expressions with a mixture of real-valued and complexvalued quantities and results may be either real or complex uncertain numbers, as is appropriate. An uncertain complex number is implemented as a pair of uncertain real numbers; thus, uncertainty is represented by uncertainties in the real and the imaginary components as well as the correlation coefficient between those components. A convenient format for specifying uncertainty in a complex value is a 2 × 2 variance-covariance matrix. The number of degrees of freedom associated with uncertainty in the real and imaginary components is the same.

Often a complex quantity is evaluated from a small sample of data. In that case, the real and imaginary component estimates are dependent, being evaluated from the same sample; they will also have a finite number of degrees of freedom. As already mentioned, the combination of finite degrees of freedom and correlation creates problems for data processing. However, when converting from a complex quantity to a real one, the modified form of the Welch–Satterthwaite formula can be useful [9]. For example, suppose a complex number *z* = *x* + i*y* has been evaluated from a small sample, *x* = 0.20 and *y* = 0.0, the real and imaginary components each have a variance of 0.1, there is a covariance between the components of 0.05, and there are 10 degrees of freedom. If the real-valued magnitude fo the following:

$$|z| = \sqrt{x^2 + y^2} \dots$$

is of interest, it can be evaluated as follows.

```
from GTC import ucomplex, magnitude
```

```
z = ucomplex(0.20,[0.1,.05,.05,0.1],10)
print("mag(z) = {!r}".format( magnitude(z) ))
```
The result

```
ureal(0.2,0.31622776601683794,10.0)
```
is an uncertain real number with 10 degrees of freedom.

On the other hand, if the result of a calculation is an uncertain complex number, there is an alternative to the Welch–Satterthwaite formula that must be used [20]. Here is an example (from [20]):

```
from GTC import ucomplex
x1 = ucomplex( 1, (0.96,-0.34,-0.34,0.27), 5 )
x2 = ucomplex( 1, (0.51,0.33,0.33,0.31), 3 )
x3 = ucomplex( 1, (0.45,0.28,0.28,1.65), 6 )
z = x1 + x2 + x3
print("z = {0.x}".format( z ))
print("u(z) = {0.u}".format( z ))
print("r(x,y) = {0.r}".format( z ))
print("df(z) = {0.df}".format( z ))
```
which displays the complex value, the standard uncertainties, the correlation coefficient, and the degrees of freedom.

```
z = (3+0j)
u(z) = StandardUncertainty(real=1.3856406460551018, imag=1.493318452306808)
r(x,y) = 0.13048503857331625
df(z) = 11.340977790491408
```
#### *Appendix A.3. Uncertain Number Objects and References*

The combination of uncertain numbers and Python language features can provide intuitive and meaningful representations of a problem domain. In particular, the distinction between random and systematic effects can be elegantly captured in object-oriented designs. However, on rare occasions, the behaviour of the Python variable names that refer to objects in memory can result in confusion. It is interesting to see how this can happen, because it provides insight into the computational processes. Here is a simple example.

Consider the following equations.

$$\begin{aligned} u &= x \\ v &= x + y \\ w &= u + v \end{aligned}$$

What is *∂w*/*∂u*? To find the answer using GTC, we may performing the following (note, partial derivatives are evaluated when elementary uncertainty numbers are declared with an uncertainty of unity):

```
from GTC import ureal, component, result
x = ureal(0,1,label="x")
y = ureal(0,1,label="y")
u=x
v=x+y
w=u+v
print( "partial derivative wrt x =", component(w,x) )
print( "partial derivative wrt u =", component(w,u) )
```
which displays the following.

partial derivative wrtx=2 partial derivative wrtu=2

If we had in mind that *w* = *u* + *v*, this result may come as a surprise because *∂w*/*∂u* = 1 would be expected. However, it is important to remember that the terms in a calculation correspond to uncertain-number objects in memory and not the variable names in code. Both x and u refer here to the same elementary uncertain number. Therefore, equation w=u+v actually corresponds to *w* = 2*x* + *y* in terms of the underlying objects, and so *∂w*/*∂x* = 2 is correct.

Confusion is created by equating the Python variables u=x if it is (incorrectly) assumed that u and x are somehow different. If we intend to take the derivative of *w* = *u* + *v* with respect to *u*, a distinct uncertain-number object must be created for *u* (and designated as an intermediate result to allow an intermediate component of uncertainty to be calculated).

To implement this calculation, we may use the unary "+" operator to create an additional uncertain number representing *u* in memory. This operator copies the numerical attributes of its argument into a new uncertain number. As far as calculation is concerned, this object corresponds to a distinct term. The following code clones x and designates it as an intermediate result to allow the component of uncertainty to be evaluated.

```
x = ureal(0,1,label="x")
y = ureal(0,1,label="y")
u = result(+x,label="u")
v=x+y
w=u+v
print( "partial derivative wrt x =", component(w,x) )
print( "partial derivative wrt u =", component(w,u) )
```
This displays the following.

partial derivative wrtx=2 partial derivative wrtu=1

This situation is unusual. Normally, result() would be applied to an object produced as the result of a calculation; thus, there is almost never a need to clone uncertain numbers as is shown here.
