weAut_01 / weAutSys    R 2.2.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines
Defines | Variables
Arithmetic utilities
+ + Utilities and helpers + +

Overview

The arithmetic functions provided by weAutSys fill the gaps of the 8 bit, CISC little endian architecture. Some have no direct substitute.

Those, replacing a C construct or library function are substantially faster. Those modulo, divide and multiply functions are unsigned — even without u in the names &mdash except stated otherwise.

Additionally some constants (values) and logical utilities are provided.

Defines

#define clearBitMask(bitNum)
 Get the 8 bit "Clear bit mask" for the given bit.
#define setBitMask(bitNum)
 Get the 8 bit "Set bit mask" for the given bit.

Optimised Divide functions

u8div_t divByVal10 (uint8_t div) __attribute__((pure))
 Divide an unsigned byte by the constant 10.
u8div_t divWByVal10toByte (uint16_t div) __attribute__((pure))
 Divide an unsigned word by by the constant 10 for a byte quotient.
u16div_t divWByVal1000 (uint16_t div) __attribute__((pure))
 Divide an unsigned word by by the constant 1000.
uint8_t mod16byVal7 (uint16_t val) __attribute__((pure))
 Modulo 7 of an unsigned 16 bit value.
uint8_t mod8byVal7 (uint8_t val) __attribute__((pure))
 Modulo 7 of an unsigned 8 bit value.
uint32_t div32byVal512 (const uint32_t div) __attribute__((pure))
 Divide unsigned 32 bit by the constant 512.
uint16_t div16byVal512 (const uint16_t div) __attribute__((pure))
 Divide unsigned 16 bit by the constant 512.
uint32_t div32byVal1024 (const uint32_t div) __attribute__((pure))
 Divide unsigned 32 bit by the constant 1024.
uint32_t div32byVal2048 (const uint32_t div) __attribute__((pure))
 Divide unsigned 32 bit by the constant 2048.
uint32_t div32byVal256 (const uint32_t div) __attribute__((pure))
 Divide unsigned 32 bit by 256.
uint32_t div32byVal128 (const uint32_t div) __attribute__((pure))
 Divide unsigned 32 bit by the constant 128.
#define mod2pow(div, po2)
 Modulo by power of 2.

Optimised Multiplication functions

uint32_t mul16with8 (const uint16_t f16, const uint8_t f8) __attribute__((pure))
 Multiply unsigned 16 bit with 8 bit.
uint32_t mul16 (const uint16_t ab, const uint16_t cd) __attribute__((pure))
 Multiply unsigned 16 bit with 16 bit.
uint32_t mul16with17 (const uint16_t ab, const uint16_t cd) __attribute__((pure))
 Multiply unsigned 16 bit with 17 bit.
uint32_t mul32withVal512 (const uint32_t fac) __attribute__((pure))
 Multiply unsigned 32 bit with the constant 512.
uint16_t mul16withVal512 (const uint16_t fac) __attribute__((pure))

Optimised Compare functions

uint8_t geU32ModAr (uint32_t a, uint32_t b) __attribute__((always_inline))
 A 32 bit unsigned greater equal (ge) comparison for modulo arithmetic.
uint8_t leU32ModAr (uint32_t a, uint32_t b) __attribute__((always_inline))
 A 32 bit unsigned less or equal (le) comparison for modulo arithmetic.

Endianess Handling functions

void toggle32endian (ucnt32_t *value)
 Toggle the endianess of a 32 bit value.
void toggle16endian (ucnt16_t *value)
 Toggle the endianess of a 16 bit value.
uint16_t convert16endian (uint16_t value)
 Convert the endianess of a 16 bit value.
uint32_t convert32endian (uint32_t value)
 Convert the endianess of a 32 bit value.
void add16littleTo32bigEndian (ucnt32_t *opRes, uint16_t op2)
 Add a normal (little endian) 16 bit value to 32 bit big endian.

Optimised Divide functions (optionally in bootloader)

uint16_t div16 (uint16_t *rem, uint16_t dividend, uint16_t divisor)
 Unsigned 16 bit divide.
uint32_t div24 (uint32_t *rem, uint32_t dividend, uint32_t divisor)
 Unsigned 24 bit divide.
uint32_t div32 (uint32_t *rem, uint32_t dividend, uint32_t divisor)
 Unsigned 32 bit divide.
uint32_t div32by24 (uint32_t *rem, uint32_t dividend, uint32_t divisor)
 Unsigned 32 bit divide by 24 bit.
uint32_t div32by16 (uint16_t *rem, uint32_t dividend, uint16_t divisor)
 Unsigned 32 bit divide by 16 bit.

Variables

uint8_t const clearBitMasks [8]
 Clear bit masks (table in flash memory)
uint8_t const setBitMasks [8]
 Set bit masks (table in flash memory)

Define Documentation

#define mod2pow (   div,
  po2 
)

Modulo by power of 2.

This is a fast modulo implementation for an architecture without a divide instruction. As long as the (AVR-GC) C-compiler does not optimise power of 2 modulo this gives a quite significant performance improvement.

Warning: If po2 is not an unsigned power of 2 (i.e. just one bit set) this will not give the correct arithmetic result.

Parameters:
divthe (unsigned) dividend
po2the (unsigned) quotient (must be a power of 2 and >= 2)
Returns:
div % po2
#define setBitMask (   bitNum)

Get the 8 bit "Set bit mask" for the given bit.

Parameters:
bitNumthe bit number; the value will be taken modulo 8, i.e. 0..7
Returns:
the mask to set the given bit in a byte (by OR)
See also:
setBitMasks
clearBitMask()
Examples:
main.c.
#define clearBitMask (   bitNum)

Get the 8 bit "Clear bit mask" for the given bit.

Parameters:
bitNumthe bit number; the value will be taken modulo 8, i.e. 0..7
Returns:
the mask to clear the given bit in a byte (by AND)
See also:
clearBitMasks
setBitMask()

This array of length 8 in flash memory contains the masks to set bits 0 .. 7 by ORing. Hence the values are 1, 2, 4 .... 128 (0x80).

Examples:
main.c.

Function Documentation

u8div_t divByVal10 ( uint8_t  div)

Divide an unsigned byte by the constant 10.

ATmega µ-controllers don't have any divide in their (RISC) instruction set. Nevertheless getting quotient and remainder by 10 in 8 bit unsigned arithmetic is needed quite often (even in loops).

Hence no effort was spared to make this a good implementation for uint8_t dividends. This function is faster than direct usage of avr-gcc C compiler's / and % operators and also faster than using stdlib.h's div(...,10). The same is true for all the other divide functions coming with weAutSys and its serial bootloader.

Returns:
the quotient and the remainder.
Parameters:
divthe dividend (byte, unsigned, 0..255)
See also:
divWByVal10toByte(uint16_t)
divWByVal1000(uint16_t)
twoDigs(char*, uint8_t)
u8div_t divWByVal10toByte ( uint16_t  div)

Divide an unsigned word by by the constant 10 for a byte quotient.

ATmega µ-controllers don't have any divide in their (RISC) instruction set. Getting quotient and remainder by 10 is, nevertheless, needed quite often — especially for decimal formatting.

In that use case the dividends (div) are often in the range 0..999. That may be achieved for larger numbers by divWByVal1000. Hence this is a highly optimised implementation for those small 16 bit dividends (0..999). It will fail without warning if the div is 1286 or above!

It's the user's responsibility not to use this function outside its operation range. On the other hand the implementation is much faster than all equivalents expressed with avr-gcc or libc functions.

Returns:
the quotient and the remainder.
Parameters:
divthe dividend (16 Bit, unsigned, 0..1286)
See also:
divByVal10(uint8_t)
divWByVal1000(uint16_t)
u16div_t divWByVal1000 ( uint16_t  div)

Divide an unsigned word by by the constant 1000.

ATmega µ-controllers don't have any divide in their (RISC) instruction set. Getting quotient and remainder by 1000 is sometimes needed — for example as divide and conquer for subsequent divide by 10 on decimal formatting.

This implementation returns quotient and the remainder as 16 bit values (in an u16div_t), even if 8 bit would suffice for the quotient.

Returns:
the quotient and the remainder.
Parameters:
divthe dividend (16 Bit, unsigned, 0..65535)
See also:
divWByVal10toByte(uint16_t)
threeDigs(char*, uint16_t)
uint8_t mod16byVal7 ( uint16_t  val)

Modulo 7 of an unsigned 16 bit value.

This is an efficient result = val % 7 without using any divide functions.

Parameters:
valthe unsigned number
Returns:
the remainder by 7 for val (0..6)
uint8_t mod8byVal7 ( uint8_t  val)

Modulo 7 of an unsigned 8 bit value.

This is an efficient result = val % 7 without using any divide functions.

Parameters:
valthe unsigned number
Returns:
the remainder by 7 for val (0..6)
uint32_t mul16with8 ( const uint16_t  f16,
const uint8_t  f8 
)

Multiply unsigned 16 bit with 8 bit.

This function calculates the the product of an 8 and a 16 bit number and returns the (24 bit) result as 32 bit.

The (ASM) implementation is far more efficient and the usage is less error prone as what could be expressed in C and then made by (AVR-) GCC.

Parameters:
f16the 16 bit (unsigned) factor
f8the 8 bit (unsigned) factor
Returns:
the product f16 * f8 (It is a 24 bit value, bits 24..31 are 0)
See also:
mul16
mul16with17
uint32_t mul16 ( const uint16_t  ab,
const uint16_t  cd 
)

Multiply unsigned 16 bit with 16 bit.

This function calculates the the product of two 16 bit numbers and returns the 32 bit result.

The (ASM) implementation is far more efficient and the usage is less error prone as what could be expressed in C and then made by (AVR-) GCC.

Parameters:
abthe first 16 bit (unsigned) factor
cdthe second 16 bit (unsigned) factor
Returns:
the product ab * cd
See also:
mul16with8
mul16with17
uint32_t mul16with17 ( const uint16_t  ab,
const uint16_t  cd 
)

Multiply unsigned 16 bit with 17 bit.

This function calculates the the product of a 16 bit number with a 17 bit number and returns the 32 bit result. The second factor cd is supplied as 16 bit unsigned number with bit 16 implied as 1. Hence the second factor is in the range 65536 .. 131071, as is e.g SECONDS_IN_DAY.

This implementation is far more efficient as what could be expressed in C and then made by (AVR-) GCC.

Parameters:
abthe first 16 bit (unsigned) factor
cdthe second 17 bit (unsigned) factor
Returns:
the product ab * (cd + 0x10000)
See also:
mul16with8
mul16
uint32_t mul32withVal512 ( const uint32_t  fac)

Multiply unsigned 32 bit with the constant 512.

This function calculates the the product of a 32 bit number with the constant 512 and returns the 32 bit result. This multiplication is needed for certain memory card operations (sector number to byte address e.g.).

This implementation is far more efficient as what could be expressed in C and then made by (AVR-) GCC.

Parameters:
facthe 32 bit (unsigned) factor
fac's upper 9 bits are ignored and should be 0 to get a arithmetically correct result
Returns:
the product fac * 512
See also:
mul16with8
mul16
div32byVal512
uint32_t div32byVal512 ( const uint32_t  div)

Divide unsigned 32 bit by the constant 512.

This function calculates the the quotient of a 32 bit number resulting from division by 512 and returns the 32 bit result. This division is needed for certain memory card operations (with 512 byte sectors e.g.).

This implementation is far more efficient as what could be expressed in C and then made by (AVR-) GCC.

Parameters:
divthe 32 bit (unsigned) dividend
Returns:
the quotient div / 512
See also:
mul32withVal512
div16byVal512
div32byVal1024
div32byVal2048
uint16_t div16byVal512 ( const uint16_t  div)

Divide unsigned 16 bit by the constant 512.

This function calculates the the quotient of a 16 bit number resulting from division by 512 and returns the 16 bit result. This division is needed for certain memory card operations (with 512 byte sectors e.g.).

This implementation is far more efficient as what could be expressed in C and then made by (AVR-) GCC.

Parameters:
divthe 16 bit (unsigned) dividend
Returns:
the quotient div / 512
See also:
div32byVal512
mul32withVal512
div32byVal1024
div32byVal2048
uint32_t div32byVal1024 ( const uint32_t  div)

Divide unsigned 32 bit by the constant 1024.

This function calculates the the quotient of a 32 bit number resulting from division by 1024 and returns the 32 bit result. This division is needed for certain memory card operations.

This implementation is far more efficient as what could be expressed in C and then made by (AVR-) GCC.

Parameters:
divthe 32 bit (unsigned) dividend
Returns:
the quotient div / 1024
See also:
mul32withVal512
uint32_t div32byVal2048 ( const uint32_t  div)

Divide unsigned 32 bit by the constant 2048.

This function calculates the the quotient of a 32 bit number resulting from division by 2048 and returns the 32 bit result. This division is needed for certain memory card operations.

This implementation is far more efficient as what could be expressed in C and then made by (AVR-) GCC.

Parameters:
divthe 32 bit (unsigned) dividend
Returns:
the quotient div / 2048
See also:
mul32withVal512
uint32_t div32byVal256 ( const uint32_t  div)

Divide unsigned 32 bit by 256.

This function calculates the the quotient of a 32 bit number resulting from division by 2048 and returns the 32 bit result. This division is needed for certain memory card operations.

This implementation is far more efficient as what could be expressed in C and then made by (AVR-) GCC.

Parameters:
divthe 32 bit (unsigned) dividend
Returns:
the quotient div / 256
See also:
mul32withVal512
uint32_t div32byVal128 ( const uint32_t  div)

Divide unsigned 32 bit by the constant 128.

This function calculates the the quotient of a 32 bit number resulting from division by 2048 and returns the 32 bit result. This division is needed for certain memory card operations.

This implementation is far more efficient as what could be expressed in C and then made by (AVR-) GCC.

Parameters:
divthe 32 bit (unsigned) dividend
Returns:
the quotient div / 128
See also:
mul32withVal512
uint8_t geU32ModAr ( uint32_t  a,
uint32_t  b 
)

A 32 bit unsigned greater equal (ge) comparison for modulo arithmetic.

This function will return true if a >= b, whereby a and b are considered as (counter) values in modulo 2**32 arithmetic. In that sense geU32ModAr(0x0001, 0xFFFE) will return true as 0x0001 is (as counter / modulo value) by 2 higher than 0xFFFE.

That will work correctly for differences less than 2**31 and, as said, very well over the "wrapping border".

Note:
Those who remember a Windows98 exploding after running a bit longer than 49 days will know why we need this type of comparison for a 32 bit milliseconds counter (e.g.).
Parameters:
awill be compared to
bby a >= b in modulo arithmetic sense
See also:
msClock()
leU32ModAr
uint8_t leU32ModAr ( uint32_t  a,
uint32_t  b 
)

A 32 bit unsigned less or equal (le) comparison for modulo arithmetic.

This function will return true if a <= b, whereby a and b a considered as (counter) values in modulo 2**32 arithmetic. It is the counterpart to geU32ModAr() (but, n.b., not the inverse).

Parameters:
awill be compared to
bby a <= b in modulo arithmetic sense
See also:
geU32ModAr
void toggle32endian ( ucnt32_t value)

Toggle the endianess of a 32 bit value.

Parameters:
valuethe value to convert
See also:
toggle16endian(ucnt16_t *)
void toggle16endian ( ucnt16_t value)

Toggle the endianess of a 16 bit value.

Parameters:
valuethe value to convert
See also:
toggle32endian(ucnt32_t *)
convert16endian
uint16_t convert16endian ( uint16_t  value)

Convert the endianess of a 16 bit value.

Parameters:
valuethe value to convert
Returns:
value with inverted endianess
See also:
toggle6endian
uint32_t convert32endian ( uint32_t  value)

Convert the endianess of a 32 bit value.

Parameters:
valuethe value to convert
Returns:
value with inverted endianess
See also:
toggle6endian
void add16littleTo32bigEndian ( ucnt32_t opRes,
uint16_t  op2 
)

Add a normal (little endian) 16 bit value to 32 bit big endian.

This type of addition is needed by uIP and this is the "good" architecture specific implementation.

Parameters:
opResthe 32 bit big endian (network order) sum and summand
op2the 16 bit little endian summand
See also:
toggle32endian(ucnt32_t *)
uint16_t div16 ( uint16_t *  rem,
uint16_t  dividend,
uint16_t  divisor 
)

Unsigned 16 bit divide.

This functions's effect is

    result (return)  = dividend / divisor;
    *rem  = dividend % divisor;

As of June 13 this function is more than twice as fast — and shorter — as the code generated by the AVR-GCC C compiler.

Anyway divide is a quite expensive operation for an 8 bit RISC machine without a divide instruction. Hence the using divide operators (and their direct replacements e.g. by this function, even though optimised as said) is discouraged. For special cases use the faster implementations like divWByVal1000() — or, at least, use the function with the smallest possible operand and result types.

Parameters:
rempointer to remainder; if null the remainder is lost
dividendthe number to be divided
divisorthe divisor
Returns:
the quotient divisor / dividend
See also:
div24
div32
uint32_t div24 ( uint32_t *  rem,
uint32_t  dividend,
uint32_t  divisor 
)

Unsigned 24 bit divide.

This functions's effect is

    result (return)  = dividend / divisor;
    *rem  = dividend % divisor;

This function is quite similar to div32. It also shares the 32 bit parameter and return types (as avr-gcc C has no 24 bit type). Nevertheless it just operates on and returns 24 bit unsigned numbers — just ignoring respectively setting 0 the upper byte.

So it is about twice as fast as the optimised div32.

Parameters:
rempointer to the 32 bit variable for the 24 bit remainder; if null the remainder is lost; upper byte will be 0.
dividendthe 24 bit number to be divided (upper byte ignored)
divisorthe 24 bit divisor (upper byte ignored)
Returns:
the 24 bit quotient divisor / dividend (upper byte 0)
See also:
div16
uint32_t div32 ( uint32_t *  rem,
uint32_t  dividend,
uint32_t  divisor 
)

Unsigned 32 bit divide.

This functions's effect is

    result (return)  = dividend / divisor;
    *rem  = dividend % divisor;

As of June 13 this function is more than twice as fast — and shorter — as the code generated by the AVR-GCC C compiler.

32 Bit divide is a very expensive operation for an 8 bit RISC machine without a divide instruction and only single bit shifts for one byte.
Hence the using it this division by C operators and % or even this optimimised replacement function is discouraged. For special cases use the faster implementations like divWByVal1000() — or, at least, use the function with the smallest possible operand and result types. div16 e.g. will be four times faster.

Parameters:
rempointer to remainder; if null the remainder is lost
dividendthe number to be divided
divisorthe divisor
Returns:
the quotient divisor / dividend
See also:
div16
div24
uint32_t div32by24 ( uint32_t *  rem,
uint32_t  dividend,
uint32_t  divisor 
)

Unsigned 32 bit divide by 24 bit.

This functions's effect is

    result (return)  = dividend / divisor;
    *rem  = dividend % divisor;

This function is quite similar to div32 respectively div24 or a mix of both. It shares the 32 bit parameter and return types (as avr-gcc C has no 24 bit type).

The divisor and remainder are 24 bit numbers (upper 32 bit byte ignored or set 0). The dividend and the quotient are 32 bit.

It is about 20% faster than div32 (which is quite a lot on a RICS without division).

Parameters:
rempointer to the 32 bit variable for the 24 bit remainder; if null the remainder is lost; upper byte will be 0.
dividendthe 32 bit number to be divided
divisorthe 24 bit divisor (upper 32 bit byte ignored)
Returns:
the 32 bit quotient divisor / dividend (upper byte 0)
See also:
div16
uint32_t div32by16 ( uint16_t *  rem,
uint32_t  dividend,
uint16_t  divisor 
)

Unsigned 32 bit divide by 16 bit.

This functions's effect is

    result (return)  = dividend / divisor;
    *rem  = dividend % divisor;

This function is quite similar to div32 respectively div16 or a mix of both.

The divisor and remainder are 16 bit numbers. The dividend and the quotient are 32 bit.

It is about 35% faster than div32 (which is quite a lot on a RICS without division).

Parameters:
rempointer to the 16 bit remainder; if null the remainder is lost
dividendthe 32 bit number to be divided
divisorthe 16 bit divisor
Returns:
the 32 bit quotient divisor / dividend
See also:
div24

Variable Documentation

uint8_t const setBitMasks[8]

Set bit masks (table in flash memory)

This array of length 8 in flash memory contains the masks to set bits 0 .. 7 by ORing. Hence the values are 1, 2, 4 .... 128 (0x80).

See also:
clearBitMasks
setBitMask()
uint8_t const clearBitMasks[8]

Clear bit masks (table in flash memory)

This array of length 8 in flash memory contains the masks to clear bits 0 .. 7 by ANDing. Hence the values are ~1, ~2, ~4 .... ~128 (0x7F).

See also:
setBitMasks
clearBitMask()