Toggling a bit in the i-th position can be tricky depending on the variety of inputs you need to support
- scalar vs array
- signed vs unsigned
- fixed-point vs MATLAB integer
- trivial fixed-point scaling vs non-trivial
The following one-liner will cover a lot of fixed-point cases
y = bitxor( u, cast( 2.^(bitIdx-1)*u.Slope, 'like', u ) )
but for signed cases, it will not correctly toggle the sign bit.
For MATLAB integers, you must remove the u.Slope term.
Here is an example to exercise it with fixed-point objects.
u = fi([0,255],0,8,0)
bitIdx = 4
y = bitxor( u, cast( 2.^(bitIdx-1)*u.Slope, 'like', u ) )
[u.bin; y.bin]
This outputs the following.
u =
0 255
numerictype(0,8,0)
bitIdx =
4
y =
8 247
numerictype(0,8,0)
ans =
2×19 char array
'00000000 11111111'
'00001000 11110111'
I believe the attached function bitToggle will handle any case from the list mentioned above.
function y = bitToggle(u,bitIndexBaseOne)
%bitToggle toggle the bit in the i-th position (one based index)
%
% This supports MATLAB integers uint8, int8, ... int64
% and fi objects that have fixed-point types
%
% Both signed and unsigned types are supported.
% Toggling of the signed bit is supported too.
<snip>
The core concept in bitToggle is the same. XOR the input with 2^(bitIndex-1).
But it fully handles the details like sign bit, fixed-point scaling, etc.
To exercise that function, play with the attached script test_bit_toggle.m.
Here is the output for a case with a signed input and non-trivial scaling.
>> test_bit_toggle
Toggle bit index 1
numerictype(1,8,4)
In 10000000 10000001 11111110 11111111 00000000 00000001 00000010 01111111
Out 10000001 10000000 11111111 11111110 00000001 00000000 00000011 01111110
Toggle bit index 2
numerictype(1,8,4)
In 10000000 10000001 11111110 11111111 00000000 00000001 00000010 01111111
Out 10000010 10000011 11111100 11111101 00000010 00000011 00000000 01111101
Toggle bit index 3
numerictype(1,8,4)
In 10000000 10000001 11111110 11111111 00000000 00000001 00000010 01111111
Out 10000100 10000101 11111010 11111011 00000100 00000101 00000110 01111011
Toggle bit index 4
numerictype(1,8,4)
In 10000000 10000001 11111110 11111111 00000000 00000001 00000010 01111111
Out 10001000 10001001 11110110 11110111 00001000 00001001 00001010 01110111
Toggle bit index 5
numerictype(1,8,4)
In 10000000 10000001 11111110 11111111 00000000 00000001 00000010 01111111
Out 10010000 10010001 11101110 11101111 00010000 00010001 00010010 01101111
Toggle bit index 6
numerictype(1,8,4)
In 10000000 10000001 11111110 11111111 00000000 00000001 00000010 01111111
Out 10100000 10100001 11011110 11011111 00100000 00100001 00100010 01011111
Toggle bit index 7
numerictype(1,8,4)
In 10000000 10000001 11111110 11111111 00000000 00000001 00000010 01111111
Out 11000000 11000001 10111110 10111111 01000000 01000001 01000010 00111111
Toggle bit index 8
numerictype(1,8,4)
In 10000000 10000001 11111110 11111111 00000000 00000001 00000010 01111111
Out 00000000 00000001 01111110 01111111 10000000 10000001 10000010 11111111
If you have MATLAB Coder available, the attached script explore_code_gen_bitToggle.m will generate C code for an example of your choice. Here is one example of the generated C code for a signed fixed-point type with non-trivial scaling. The example is designed to produce five different outputs that toggle five different bits. Three bits at the least significant end, and two bits at the most significant end. If the input is signed, toggling of the MS bit is toggling the sign bit.
#include "multiBitToggle.h"
void multiBitToggle(signed char u, signed char *b_y1, signed char *y2,
signed char *y3, signed char *yWlm1, signed char *yWl)
{
*b_y1 = (signed char)((unsigned char)u ^ 1);
*y2 = (signed char)((unsigned char)u ^ 2);
*y3 = (signed char)((unsigned char)u ^ 4);
*yWlm1 = (signed char)((unsigned char)u ^ 64);
*yWl = (signed char)((unsigned char)u ^ 128);
}
Notice that the generated C code is very lean and just does a bitwise XOR with a constant power of two mask.
Also notice how the last line is successfully toggling the sign bit of the int8 input by casting to unsigned prior to the XOR, then casting back to signed.
Regards,
Andy