# Class Methods, Operators, and Data Members - 2022.1 English

## Vitis High-Level Synthesis User Guide (UG1399)

Document ID
UG1399
Release Date
2022-06-07
Version
2022.1 English

In general, any valid operation that can be done on a native C/C++ integer data type is supported (using operator overloading) for `ap_[u]fixed` types. In addition to these overloaded operators, some class specific operators and methods are included to ease bit-level operations.

## Binary Arithmetic Operators

``ap_[u]fixed::RType ap_[u]fixed::operator + (ap_[u]fixed op)``

Adds an arbitrary precision fixed-point with a given operand `op`.

The operands can be any of the following integer types:

• ap_[u]fixed
• ap_[u]int
• C/C++

The result type `ap_[u]fixed::RType` depends on the type information of the two operands.

``````ap_fixed<76, 63> Result;

ap_fixed<5, 2> Val1 = 1.125;
ap_fixed<75, 62> Val2 = 6721.35595703125;

Result = Val1 + Val2; //Yields 6722.480957``````

Because `Val2` has the larger bit-width on both integer part and fraction part, the result type has the same bit-width and plus one to be able to store all possible result values.

Specifying the data's width controls resources by using the power functions, as shown below. In similar cases, Xilinx recommends specifying the width of the stored result instead of specifying the width of fixed point operations.

``````ap_ufixed<16,6> x=5;
ap_ufixed<16,7>y=hl::rsqrt<16,6>(x+x); ``````

## Subtraction

``ap_[u]fixed::RType ap_[u]fixed::operator - (ap_[u]fixed op)``

Subtracts an arbitrary precision fixed-point with a given operand `op`.

The result type `ap_[u]fixed::RType` depends on the type information of the two operands.

``````ap_fixed<76, 63> Result;

ap_fixed<5, 2> Val1 = 1625.153;
ap_fixed<75, 62> Val2 = 6721.355992351;

Result = Val2 - Val1; // Yields 6720.23057``````

Because `Val2` has the larger bit-width on both integer part and fraction part, the result type has the same bit-width and plus one to be able to store all possible result values.

## Multiplication

``ap_[u]fixed::RType ap_[u]fixed::operator * (ap_[u]fixed op)``

Multiplies an arbitrary precision fixed-point with a given operand `op`.

``````ap_fixed<80, 64> Result;

ap_fixed<5, 2> Val1 = 1625.153;
ap_fixed<75, 62> Val2 = 6721.355992351;

Result = Val1 * Val2; // Yields 7561.525452``````

This shows the multiplication of `Val1` and `Val2`. The result type is the sum of their integer part bit-width and their fraction part bit width.

## Division

``ap_[u]fixed::RType ap_[u]fixed::operator / (ap_[u]fixed op)``

Divides an arbitrary precision fixed-point by a given operand `op`.

``````ap_fixed<84, 66> Result;

ap_fixed<5, 2> Val1 = 1625.153;
ap_fixed<75, 62> Val2 = 6721.355992351;

Val2 / Val1; // Yields 5974.538628``````

This shows the division of `Val2` and `Val1`. To preserve enough precision:

• The integer bit-width of the result type is sum of the integer bit-width of `Val2` and the fraction bit-width of `Val1`.
• The fraction bit-width of the result type is equal to the fraction bit-width of `Val2`.

## Bitwise OR

``ap_[u]fixed::RType ap_[u]fixed::operator | (ap_[u]fixed op)``

Applies a bitwise operation on an arbitrary precision fixed-point and a given operand `op`.

``````ap_fixed<75, 62> Result;

ap_fixed<5, 2> Val1 = 1625.153;
ap_fixed<75, 62> Val2 = 6721.355992351;

Result = Val1 | Val2; // Yields 6271.480957``````

## Bitwise AND

``ap_[u]fixed::RType ap_[u]fixed::operator & (ap_[u]fixed op)``

Applies a bitwise operation on an arbitrary precision fixed-point and a given operand `op`.

``````ap_fixed<75, 62> Result;

ap_fixed<5, 2> Val1 = 1625.153;
ap_fixed<75, 62> Val2 = 6721.355992351;

Result = Val1 & Val2;  // Yields 1.00000``````

## Bitwise XOR

``ap_[u]fixed::RType ap_[u]fixed::operator ^ (ap_[u]fixed op)``

Applies an `xor` bitwise operation on an arbitrary precision fixed-point and a given operand `op`.

``````ap_fixed<75, 62> Result;

ap_fixed<5, 2> Val1 = 1625.153;
ap_fixed<75, 62> Val2 = 6721.355992351;

Result = Val1 ^ Val2; // Yields 6720.480957``````

## Pre-Increment

``ap_[u]fixed ap_[u]fixed::operator ++ ()``

This operator function prefix increases an arbitrary precision fixed-point variable by `1`.

``````ap_fixed<25, 8> Result;
ap_fixed<8, 5> Val1 = 5.125;

Result = ++Val1; // Yields 6.125000``````

## Post-Increment

``ap_[u]fixed ap_[u]fixed::operator ++ (int)``

This operator function postfix:

• Increases an arbitrary precision fixed-point variable by `1`.
• Returns the original val of this arbitrary precision fixed-point.
``````ap_fixed<25, 8> Result;
ap_fixed<8, 5> Val1 = 5.125;

Result = Val1++; // Yields 5.125000``````

## Pre-Decrement

``ap_[u]fixed ap_[u]fixed::operator -- ()``

This operator function prefix decreases this arbitrary precision fixed-point variable by `1`.

``````ap_fixed<25, 8> Result;
ap_fixed<8, 5> Val1 = 5.125;

Result = --Val1; // Yields 4.125000``````

## Post-Decrement

``ap_[u]fixed ap_[u]fixed::operator -- (int)``

This operator function postfix:

• Decreases this arbitrary precision fixed-point variable by `1`.
• Returns the original val of this arbitrary precision fixed-point.
``````ap_fixed<25, 8> Result;
ap_fixed<8, 5> Val1 = 5.125;

Result = Val1--; // Yields 5.125000``````

## Unary Operators

``ap_[u]fixed ap_[u]fixed::operator + ()``

Returns a self copy of an arbitrary precision fixed-point variable.

``````ap_fixed<25, 8> Result;
ap_fixed<8, 5> Val1 = 5.125;

Result = +Val1;  // Yields 5.125000``````

## Subtraction

``ap_[u]fixed::RType ap_[u]fixed::operator - ()``

Returns a negative value of an arbitrary precision fixed-point variable.

``````ap_fixed<25, 8> Result;
ap_fixed<8, 5> Val1 = 5.125;

Result = -Val1; // Yields -5.125000``````

## Equality Zero

``bool ap_[u]fixed::operator ! ()``

This operator function:

• Compares an arbitrary precision fixed-point variable with `0`,
• Returns the result.
``````bool  Result;
ap_fixed<8, 5> Val1 = 5.125;

Result = !Val1; // Yields false``````

## Bitwise Inverse

``ap_[u]fixed::RType ap_[u]fixed::operator ~ ()``

Returns a bitwise complement of an arbitrary precision fixed-point variable.

``````ap_fixed<25, 15> Result;
ap_fixed<8, 5> Val1 = 5.125;

Result = ~Val1; // Yields -5.25``````

## Unsigned Shift Left

``ap_[u]fixed ap_[u]fixed::operator << (ap_uint<_W2> op) ``

This operator function:

• Shifts left by a given integer operand.
• Returns the result.

The operand can be a C/C++ integer type:

• `char`
• `short`
• `int`
• `long`

The return type of the shift left operation is the same width as the type being shifted.

Note: Shift does not support overflow or quantization modes.
``````ap_fixed<25, 15> Result;
ap_fixed<8, 5> Val = 5.375;

ap_uint<4> sh = 2;

Result = Val << sh; // Yields -10.5``````

The bit-width of the result is (`W = 25`, ```I = 15```). Because the shift left operation result type is same as the type of `Val`:

• The high order two bits of `Val` are shifted out.
• The result is -10.5.

If a result of 21.5 is required, `Val` must be cast to `ap_fixed<10, 7>` first -- for example, `ap_ufixed<10, 7>(Val)`.

## Signed Shift Left

``ap_[u]fixed ap_[u]fixed::operator << (ap_int<_W2> op)``

This operator:

• Shifts left by a given integer operand.
• Returns the result.

The shift direction depends on whether the operand is positive or negative.

• If the operand is positive, a shift right is performed.
• If the operand is negative, a shift left (opposite direction) is performed.

The operand can be a C/C++ integer type:

• `char`
• `short`
• `int`
• `long`

The return type of the shift right operation is the same width as the type being shifted.

``````ap_fixed<25, 15,  false> Result;
ap_uint<8, 5> Val = 5.375;

ap_int<4> Sh = 2;
Result = Val << sh; // Shift left, yields -10.25

Sh = -2;
Result = Val << sh; // Shift right, yields 1.25``````

## Unsigned Shift Right

``ap_[u]fixed ap_[u]fixed::operator >> (ap_uint<_W2> op) ``

This operator function:

• Shifts right by a given integer operand.
• Returns the result.

The operand can be a C/C++ integer type:

• `char`
• `short`
• `int`
• `long`

The return type of the shift right operation is the same width as the type being shifted.

``````ap_fixed<25, 15> Result;
ap_fixed<8, 5> Val = 5.375;

ap_uint<4> sh = 2;

Result = Val >> sh; // Yields 1.25``````

If it is necessary to preserve all significant bits, extend fraction part bit-width of the `Val` first, for example ```ap_fixed<10, 5>(Val)```.

## Signed Shift Right

``ap_[u]fixed ap_[u]fixed::operator >> (ap_int<_W2> op) ``

This operator:

• Shifts right by a given integer operand.
• Returns the result.

The shift direction depends on whether operand is positive or negative.

• If the operand is positive, a shift right performed.
• If operand is negative, a shift left (opposite direction) is performed.

The operand can be a C/C++ integer type (`char`, `short`, `int`, or `long`).

The return type of the shift right operation is the same width as type being shifted. For example:

``````ap_fixed<25, 15,  false> Result;
ap_uint<8, 5> Val = 5.375;

ap_int<4> Sh = 2;
Result = Val >> sh; // Shift right, yields 1.25

Sh = -2;
Result = Val >> sh; // Shift left,  yields -10.5

1.25``````

## Equality

``bool ap_[u]fixed::operator == (ap_[u]fixed op)``

This operator compares the arbitrary precision fixed-point variable with a given operand.

Returns `true` if they are equal and `false` if they are not equal.

The type of operand `op` can be `ap_[u]fixed`, `ap_int` or C/C++ integer types. For example:

``````bool Result;

ap_ufixed<8, 5> Val1 = 1.25;
ap_fixed<9, 4> Val2 = 17.25;
ap_fixed<10, 5> Val3 = 3.25;

Result = Val1 == Val2; // Yields  true
Result = Val1 == Val3; // Yields  false``````

## Inequality

``bool ap_[u]fixed::operator != (ap_[u]fixed op)``

This operator compares this arbitrary precision fixed-point variable with a given operand.

Returns `true` if they are not equal and `false` if they are equal.

The type of operand `op` can be:

• ap_[u]fixed
• ap_int
• C or C++ integer types

For example:

``````bool Result;

ap_ufixed<8, 5> Val1 = 1.25;
ap_fixed<9, 4> Val2 = 17.25;
ap_fixed<10, 5> Val3 = 3.25;

Result = Val1 != Val2; // Yields false
Result = Val1 != Val3; // Yields true``````

## Greater than or equal to

``bool ap_[u]fixed::operator >= (ap_[u]fixed op)``

This operator compares a variable with a given operand.

Returns `true` if they are equal or if the variable is greater than the operator and `false` otherwise.

The type of operand `op` can be `ap_[u]fixed`, `ap_int` or C/C++ integer types.

For example:

``````bool Result;

ap_ufixed<8, 5> Val1 = 1.25;
ap_fixed<9, 4> Val2 = 17.25;
ap_fixed<10, 5> Val3 = 3.25;

Result = Val1 >= Val2; // Yields true
Result = Val1 >= Val3; // Yields false``````

## Less than or equal to

``bool ap_[u]fixed::operator <= (ap_[u]fixed op)``

This operator compares a variable with a given operand, and return `true` if it is equal to or less than the operand and `false` if not.

The type of operand op can be `ap_[u]fixed`, `ap_int` or C/C++ integer types.

For example:

``````bool Result;

ap_ufixed<8, 5> Val1 = 1.25;
ap_fixed<9, 4> Val2 = 17.25;
ap_fixed<10, 5> Val3 = 3.25;

Result = Val1 <= Val2; // Yields true
Result = Val1 <= Val3; // Yields true``````

## Greater than

``bool ap_[u]fixed::operator > (ap_[u]fixed op)``

This operator compares a variable with a given operand, and return `true` if it is greater than the operand and `false` if not.

The type of operand `op` can be `ap_[u]fixed`, `ap_int`, or C/C++ integer types.

For example:

``````bool Result;

ap_ufixed<8, 5> Val1 = 1.25;
ap_fixed<9, 4> Val2 = 17.25;
ap_fixed<10, 5> Val3 = 3.25;

Result = Val1 > Val2; // Yields false
Result = Val1 > Val3; // Yields false``````

## Less than

``bool ap_[u]fixed::operator < (ap_[u]fixed op)``

This operator compares a variable with a given operand, and return `true` if it is less than the operand and `false` if not.

The type of operand op can be `ap_[u]fixed`, `ap_int`, or C/C++ integer types. For example:

``````bool Result;

ap_ufixed<8, 5> Val1 = 1.25;
ap_fixed<9, 4> Val2 = 17.25;
ap_fixed<10, 5> Val3 = 3.25;

Result = Val1 < Val2; // Yields false
Result = Val1 < Val3; // Yields true``````

## Bit-Select and Set

``af_bit_ref ap_[u]fixed::operator [] (int bit) ``

This operator selects one bit from an arbitrary precision fixed-point value and returns it.

The returned value is a reference value that can set or clear the corresponding bit in the `ap_[u]fixed` variable. The bit argument must be an integer value and it specifies the index of the bit to select. The least significant bit has index `0`. The highest permissible index is one less than the bit-width of this `ap_[u]fixed` variable.

The result type is `af_bit_ref` with a value of either `0` or `1`. For example:

``````ap_int<8, 5> Value = 1.375;

Value; // Yields  1
Value; // Yields  0

Value = 1; // Yields 1.875
Value = 0; // Yields 0.875``````

## Bit Range

``````af_range_ref af_(u)fixed::range (unsigned Hi, unsigned Lo)
af_range_ref af_(u)fixed::operator [] (unsigned Hi, unsigned Lo) ``````

This operation is similar to bit-select operator [] except that it operates on a range of bits instead of a single bit.

It selects a group of bits from the arbitrary precision fixed-point variable. The `Hi` argument provides the upper range of bits to be selected. The `Lo` argument provides the lowest bit to be selected. If `Lo` is larger than `Hi` the bits selected are returned in the reverse order.

The return type `af_range_ref` represents a reference in the range of the `ap_[u]fixed` variable specified by `Hi` and `Lo`. For example:

``````ap_uint<4> Result = 0;
ap_ufixed<4, 2> Value = 1.25;
ap_uint<8> Repl = 0xAA;

Result = Value.range(3, 0); // Yields: 0x5
Value(3, 0) = Repl(3, 0); // Yields: -1.5

// when Lo > Hi, return the reverse bits string
Result = Value.range(0, 3); // Yields: 0xA``````

## Range Select

``````af_range_ref af_(u)fixed::range ()
af_range_ref af_(u)fixed::operator []``````

This operation is the special case of the range select operator `[]`. It selects all bits from this arbitrary precision fixed-point value in the normal order.

The return type `af_range_ref` represents a reference to the range specified by Hi = W - 1 and Lo = 0. For example:

``````ap_uint<4> Result = 0;

ap_ufixed<4, 2> Value = 1.25;
ap_uint<8> Repl = 0xAA;

Result = Value.range(); // Yields: 0x5
Value() = Repl(3, 0); // Yields: -1.5``````

## Length

``int ap_[u]fixed::length ()``

This function returns an integer value that provides the number of bits in an arbitrary precision fixed-point value. It can be used with a type or a value. For example:

``````ap_ufixed<128, 64> My128APFixed;

int bitwidth = My128APFixed.length(); // Yields 128``````

## Fixed to Double

``double ap_[u]fixed::to_double ()``

This member function returns this fixed-point value in form of IEEE double precision format. For example:

``````ap_ufixed<256, 77> MyAPFixed = 333.789;
double Result;

Result = MyAPFixed.to_double(); // Yields 333.789``````

## Fixed to Float

``float ap_[u]fixed::to_float()``

This member function returns this fixed-point value in form of IEEE float precision format. For example:

``````ap_ufixed<256, 77> MyAPFixed = 333.789;
float Result;

Result = MyAPFixed.to_float();  // Yields 333.789``````

## Fixed to Half-Precision Floating Point

``half ap_[u]fixed::to_half()``

This member function return this fixed-point value in form of HLS half-precision (16-bit) float precision format. For example:

``````ap_ufixed<256, 77> MyAPFixed = 333.789;
half Result;

Result = MyAPFixed.to_half();  // Yields 333.789``````

## Fixed to ap_int

``ap_int ap_[u]fixed::to_ap_int ()``

This member function explicitly converts this fixed-point value to `ap_int` that captures all integer bits (fraction bits are truncated). For example:

``````ap_ufixed<256, 77> MyAPFixed = 333.789;
ap_uint<77> Result;

Result = MyAPFixed.to_ap_int(); //Yields 333``````

## Fixed to Integer

``````int ap_[u]fixed::to_int ()
unsigned ap_[u]fixed::to_uint ()
ap_slong ap_[u]fixed::to_int64 ()
ap_ulong ap_[u]fixed::to_uint64 ()``````

This member function explicitly converts this fixed-point value to C built-in integer types. For example:

``````ap_ufixed<256, 77> MyAPFixed = 333.789;
unsigned int  Result;

Result = MyAPFixed.to_uint(); //Yields 333

unsigned long long Result;
Result = MyAPFixed.to_uint64(); //Yields 333``````

The `ap_[u]fixed<>` types are provided with several static members that allow the size and configuration of data types to be determined at compile time. The data type is provided with the `static const` members: `width`, `iwidth`, `qmode` and `omode`:

``````static const int width = _AP_W;
static const int iwidth = _AP_I;
static const ap_q_mode qmode = _AP_Q;
static const ap_o_mode omode = _AP_O;``````

You can use these data members to extract the following information from any existing `ap_[u]fixed<>` data type:

`width`
The width of the data type.
`iwidth`
The width of the integer part of the data type.
`qmode`
The quantization mode of the data type.
`omode`
The overflow mode of the data type.

For example, you can use these data members to extract the data width of an existing `ap_[u]fixed<>` data type to create another `ap_[u]fixed<>` data type at compile time.

The following example shows how the size of variable `Res` is automatically defined as 1-bit greater than variables `Val1` and `Val2` with the same quantization modes:

``````// Definition of basic data type
#define INPUT_DATA_WIDTH 12
#define IN_INTG_WIDTH 6
#define IN_QMODE AP_RND_ZERO
#define IN_OMODE AP_WRAP
typedef ap_fixed<INPUT_DATA_WIDTH, IN_INTG_WIDTH, IN_QMODE, IN_OMODE> data_t;
// Definition of variables
data_t Val1, Val2;
// Res is automatically sized at run-time to be 1-bit greater than INPUT_DATA_WIDTH
// The bit growth in Res will be in the integer bits
ap_int<data_t::width+1, data_t::iwidth+1, data_t::qmode, data_t::omode> Res = Val1 +
Val2;``````

This ensures that Vitis HLS correctly models the bit-growth caused by the addition even if you update the value of INPUT_DATA_WIDTH, IN_INTG_WIDTH, or the quantization modes for `data_t`.