Daqarta
Data AcQuisition And Real-Time Analysis
Scope - Spectrum - Spectrogram - Signal Generator
Software for Windows  The following is from the Daqarta Help system:

# Macro Expressions and Operators

## Introduction:

A macro command consists of the command name followed by an = sign and (usually) a value or expression. The expression may include other internal command names (used as variables), as well as macro variables and constants. Standard math operators and functions are supported. For example:

L.0.ToneFreq=sqrt(R.0.ToneFreq * R.1.ToneFreq) + 100

This sets the Left Stream 0 Tone Frequency to the square root of the product of the Right Stream 0 and Stream 1 Tone Frequencies, plus 100. Here the square root is performed by the sqrt function, but it could have been done by raising the product to the one-half power:

L.0.ToneFreq=(R.0.ToneFreq * R.1.ToneFreq)^0.5 + 100

Note that no spaces may appear before the =, but may be used elsewhere in the expression for clarity.

Macro expressions may be continued over multiple lines by ending each to-be-continued line with an underscore.

## Math Precision:

Most main Daqarta variables are either integers, such as Sample Rate (SmplRate), or fixed-point reals such as Trigger Level TrigLevel), both with 32-bit precision. Either type may be unsigned (like Sample Rate) or signed (like Trigger Level). Reals typically have 16-bit integer and 16-bit fraction parts. Generator Tone Frequency is a special case, with 17-bit integer and 16-bit fraction parts giving 33-bit effective resolution up to 131072.99999 Hz.

Internal on/off state variables like Generator (Gen) act as unsigned integers in math calculations, with values of 0 (off) or 1 (on).

Macro variables Var0-Z and arrays Buf0-7 are signed real numbers with 32-bit integer and 32-bit fraction parts, for 64-bit overall precision. The integer range is approximately +/-2 billion; the fraction resolution is about 9 decimal places.

Macro variables A-Z are 80-bit floating-point real numbers with 64-bit precision (equivalent to about 19 digits) over a range from about 10^4932 down to 10^-4932.

All math expressions are calculated using 80-bit floating-point math. Main or macro variables are converted to this format (if not A-Z which already are), the floating-point calculations are made, and the final result is converted to the format of the left-hand (main or macro) variable for assignment.

You normally don't need to worry about precision for most kinds of calculations in Daqarta, since these are carried out with much greater precision than the variables they will be assigned to. But you might need to be careful if you are doing a large calculation in stages, where intermediate values are assigned to macro variables. In such cases you should use A-Z, not Var0-Z, for maximum precision and to prevent possible overflows or underflows.

For example, suppose you want set the L.0. tone frequency to the sum of the squares of the R.0. and R.1. tone frequencies. The following will always work, because all calculations on the right side are carried out with floating-point values before the left side is assigned:

L.0.ToneFreq=sqrt(R.0.ToneFreq^2 + R.1.ToneFreq^2)

But suppose you decide to break this into stages and assign the squares to intermediate variables VarA and VarB:

```    VarA=R.0.ToneFreq^2
VarB=R.1.ToneFreq^2
L.0.ToneFreq=sqrt(VarA + VarB)
```

This will work just fine, but only as long as neither initial frequency exceeds 46340.95. Above that, the square exceeds the 32-bit positive integer limit of the intermediate variables. This would not be a problem if floating-point variables A and B were substituted for VarA and VarB.

You can use hexadecimal notation for integer values in expressions by preceding the value with 'h', as in A=h3E8, which is equivalent to A=1000. You can enter up to 8 integer and 8 fraction hex characters, as in A=h12345678.12345678. Valid hex characters are 0-9 and A-F (case independent). The first non-valid character will terminate the entry, but will not cause an error. If more than 8 integer characters are encountered, the overall entry is terminated at 8, with the fraction part nulled. Extra characters beyond 8 are ignored.

## Binary Notation:

Binary notation can be used for integer values in expressions by preceding the value with 'b', as in A=b10001, which is equivalent to A=17. This is particularly handy for bit-mapped values such as Multi-Channel Stream selection, like Center#N=b10001. Values are limited to 32 bits.

## ASCII String Entry:

You can use quoted strings of up to 8 characters to enter the equivalent ASCII value. For example, N="12345678" is the equivalent of N=h31323334.35363738, which in decimal would be N=825373492.207858516. This is useful for values that will later be displayed with the alphanumeric format (A) option.

Floating-point variables A-Z and 64-bit fixed-point variables Var0-VarZ allow all 8 characters as shown above. Integer variables U0-UZ and Q0-QZ only allow 4 characters. In either case, excess characters are ignored.

If you use only 4 characters, such as N=1234 (so that only integers are used in the actual internal number), and the value is then incremented, the next ASCII character will be displayed. For example, after N=N+1, then Msg=N(A) would display "1235". Likewise, if you had used N="ABCD" then after incrementing it would be "ABCE".

Note that the above is completely separate from either Str0-Str7 string arrays or Buf0-Buf7 macro array string storage, which can hold up to 2048 characters each and are more suitable for general string operations.

## Math Constants:

The built-in constants pi and e may be used in any numeric expression where a variable or constant can be used. They have 80-bit precision.

## Arithmetic Operators:

Macro expressions may use the following arithmetic operators:

```    +  Add
-  Subtract (or negation)
*  Multiply
/  Divide
^  Power
%  Modulus (remainder after division)
>> Right binary shift
<< Left binary shift
```

Note: Division by zero yields "infinity" (roughly 10^4932) with the sign of the numerator. Zero divided by zero gives a unity result by default. You can change the 0/0 behavior to give zero or "negative infinity" via the Posn#Z command.

Examples: Assuming A = 5 and B = 3,

```    A + B = 8
A - B = 2
A * B = 15
A / B = 1.66667
A ^ B = 125
A % B = 2
A >> B = 5 * 2^-3 = 0.625
A << B = 5 * 2^3 = 40
```

Note: The % modulo operation on integers is the ordinary remainder after division. For real numbers it is equivalent to doing a normal division, truncating the quotient to an integer, multiplying by the original denominator, and subtracting from the numerator. Example:

```    A = 1234.567
B = 54.321
A % B = A - cint(A / B) * B
= 1234.567 - int(22.727...) * 54.321
= 1234.567 - 22 * 54.321
= 1234.567 - 1195.062
= 39.505
```

Caution: The basic arithmetic operations return floating-point results. This can cause problems when using right binary shift (>>) with integers. For example, if UA=1 then UA>>1 returns 0.500, not 0. If you then assign that directly to an integer as with UA=UA>>1 it will automatically be rounded back up to 1. Instead, use UA=int(UA>>1) to truncate instead of rounding.

## Logical Operators:

Logical (True/False or Boolean) operators regard any value above zero as True, and any value of zero or less as False. The result of a logical operation is always True = 1 or False = 0.

```    && Logical AND
|| Logical OR
## Logical XOR (exclusive OR)
!  Logical NOT (unary)
```

Examples: Assuming A = 7 (logical True) and B = -3 (logical False),

```    A && B = False = 0
A || B = True = 1
A ## B = True = 1
!A = False = 0
```

## Bitwise Binary Operators:

Bitwise binary operations are logical operations that act on all bits of integer values. Non-integers (fixed-point or floating-point real values) are truncated to integers by these operators.

```    &  Bitwise AND
|  Bitwise OR
#  Bitwise XOR (exclusive OR)
~  Bitwise NOT (unary)
```

Examples: Assuming A = 5 (binary 0101) and B = 3 (binary 0011),

```        A = 0000000000000101 = 5
B = 0000000000000011 = 3
A & B = 0000000000000001 = 1
A | B = 0000000000000111 = 7
A # B = 0000000000000110 = 6
~A = 1111111111111010 = -6
~B = 1111111111111100 = -4
```

Note that operators may not be paired. Instead of C=A*-B, use C=-B*A or C=A*(-B).

## Operator Precedence:

Operators have an order of priority or precedence in expressions. Higher-order operations are performed first, then their results are combined with lower-order operations.

• Logical NOT
• Power
• Multiply, Divide, Modulus, Binary Shift, AND
• Add, Subtract, OR, XOR, Binary NOT

For example, in A + B^2 * C - D the B^2 term is found first, then multipled by C, then A-D is added.

You can use parentheses to change the order of operations, such as A + B^(2 * C) - D, GO: