The Arithmetic Module

The arithmetic module provides safe arithmetics for C types. Overflows or underflows in the type's range are reported as errors to the transaction. More...

## Files | |

file | picotm-arithmetic-ctypes.h |

Transactional, safe arithmetics for native C types. | |

file | picotm-arithmetic.h |

Public interfaces of picotm's arithmetic module. | |

The arithmetic module provides safe arithmetic operations for C types. Overflows, underflows and undefined operations are detected and reported to the transaction's recovery code. Supported operations are additions, subtractions, multiplications and divisions.

Additions are in the form `add_<type>_tx()`

where `<type>`

is the name of the C type. For example, overflow-safe addition of two long integer values is performed by the following transaction.

long res = add_long_tx(INT_MAX, INT_MAX);

(picotm_error_as_errno() == ERANGE)) {

// An error happened during an arithmetic operation.

}

The success of this operations depends on the size of type `long`

. If `long`

is 64 bit in size, the addition will return the sum of both operands. If `long`

is only 32 bit in size, which is the same of `int`

on most platforms, the addition will overflow and the function will roll the transaction back to the previous consistent state and report `ERANGE`

to the recovery code.

The arithmetic module comes with support for all native C types. We can define safe addition for application-specific types with the C preprocessor macros `PICOTM_ARITHMETIC_ADD_S_TX()`

, `PICOTM_ARITHMETIC_ADD_U_TX()`

and `PICOTM_ARITHMETIC_ADD_F_TX()`

. The first macro, `PICOTM_ARITHMETIC_ADD_S_TX()`

supports signed integer types; the second macro, `PICOTM_ARITHMETIC_ADD_U_TX()`

, supports unsigned integer types. Finally, the third macro, `PICOTM_ARITHMETIC_ADD_F_TX()`

, supports floating-point types.

For example, an application might use the specialized floating-point type `float100`

, which only contains values from minus 100 to plus 100.

typedef float float100;

#define FLT100_MAX 100 // similar to FLT_MAX from <float.h>

We can use the macro `PICOTM_ARITHMETIC_ADD_F_TX()`

to create an add function that overflows at plus 100 and underflows at minus 100.

float100

float100_add(float100 lhs, float100 rhs)

{

return lhs + rhs;

}

float100

float100_sub(float100 lhs, float100 rhs)

{

return lhs - rhs;

}

PICOTM_ARITHMETIC_ADD_F_TX(float100, float100, FLT100_MAX, 0.f,

float100_add, float_100_sub)

The first two parameters are name and C type of the function. The third parameter is the type's range or extension. For `float100`

it ranges from `-FLT100_MAX`

to `FLT100_MAX`

. The forth paramater is the value of the type's operation's identity element (i.e., the value that does nothing for the operation). For additions, the identity element is *0.* The two final macro parameters are the type's primitive addition and subtraction functions. These functions perform the plain operations without safety checks.

The example macro invocation expands to the following function.

static inline

float100

add_float100_tx(float100 lhs, float100 rhs)

{

... // safe addition

}

A transaction can use it like `add_long_tx()`

in the previous example.

float100 res = add_float100_tx(75.f, 25.f);

(picotm_error_as_errno() == ERANGE)) {

// An error happened during an arithmetic operation.

}

Picotm provides equivalent generator macros for subtraction, multiplication and division of signed integer types, unsigned integer types and floating-point types. Defining subtraction, multiplication and division completes elementary arithmetics for `float100`

. The full example code is shown below.

float100

float100_add(float100 lhs, float100 rhs)

{

return lhs + rhs;

}

float100

float100_sub(float100 lhs, float100 rhs)

{

return lhs - rhs;

}

float100

float100_mul(float100 lhs, float100 rhs)

{

return lhs * rhs;

}

float100

float100_div(float100 lhs, float100 rhs)

{

return lhs / rhs;

}

PICOTM_ARITHMETIC_ADD_F_TX(float100, float100, FLT100_MAX, 0.f,

float100_add, float_100_sub)

PICOTM_ARITHMETIC_SUB_F_TX(float100, float100, FLT100_MAX, 0.f,

float100_add, float_100_sub)

PICOTM_ARITHMETIC_MUL_F_TX(float100, float100, FLT100_MAX, 1.f, 0.f,

float100_mul, float_100_div)

PICOTM_ARITHMETIC_DIV_F_TX(float100, float100, FLT100_MAX, 1.f, 0.f,

float100_div, float_100_div)

The identity element for multiplication and division is *1.* In addition to the identity element, the generator macros for multiplication and division take an additional absorbing element. This is the value the maps each factor to the absorbing element itself. For multiplication this value is *0.* For divisions by the absorbing element, the generated division function rolls the transaction back and returns the errno code `EDOM`

to the recovery mode.

Results or parameters of arithmetics operations should be loaded into the transaction or stored from the transaction using the Transactional Memory module.