2

I need to implement an ECC algorithm on an 8-bit message with 32 bits to work with (32, 8), being new to ECC I started to google and learn a bit about it and ended up coming across two ECC methods, Hamming codes and Reed Solomon. Given that I needed my message to be resilient to 4-8 random bit flips on average I disregarded Hammings and looked into Reed, however, after applying it to my problem I realized it is also not suitable for my use case because while a whole symbol (8 bits) could be flipped, because my errors tend to spread out (on average), it can usually only fix a single error...

Therefore in the end I just settled for my first instinct which is to just copy the data over like so:

00111010 --> 0000 0000 1111 1111 1111 0000 1111 0000

This way every bit is resilient up to 1 error (8 across all bits) by taking the most prominent bits on each actual bit from the encoded message, and every bit can be subject to two bitflips while still detecting there was an error (which is also usable for my use case, eg: input 45: return [45, 173] is still useful).

My question then is if there is any better method, while I am pretty sure there is, I am not sure where to go from here.

By "better method" I mean resilient to even more errors given the (32, 8) ratio.

Mathias Sven
  • 349
  • 3
  • 7
  • 1
    You should ask this on [cs.stackexchange.com](https://cs.stackexchange.com/). – Olivier Sep 09 '21 at 09:38
  • 3
    The classical ECC usually assume that errors come in bursts so that a few words are corrupt. It seems that in your case any bit pattern can arise (equiprobably ?), so it indeed makes sense to quadruple all bits. This way, a single bit error is detected with probability 14/15. It could be useful to intertwine the quadruplicated bits to reduce the chance of the four copies to be corrupt simultaneously. –  Sep 09 '21 at 09:59
  • @Olivier Sorry, yeah that would have probably been more topic-specific... Should I delete here and ask there? – Mathias Sven Sep 09 '21 at 16:50
  • @YvesDaoust I see, yeah the errors are completely random. It is for steganography. – Mathias Sven Sep 09 '21 at 16:54
  • There is also [BCH code](https://en.wikipedia.org/wiki/BCH_code), which would be good for up to 4 bit errors, but David Eisenstat's answer would be good for up to 5 bit errors – rcgldr Sep 09 '21 at 21:29

2 Answers2

2

You can get a distance-11 code pretty easily using randomization.

#include <stdio.h>
#include <stdlib.h>

int main() {
  uint32_t codes[256];
  for (int i = 0; i < 256; i++) {
    printf("%d\n", i);
  retry:
    codes[i] = arc4random();
    for (int j = 0; j < i; j++) {
      if (__builtin_popcount(codes[i] ^ codes[j]) < 11) goto retry;
    }
  }
}
David Eisenstat
  • 64,237
  • 7
  • 60
  • 120
  • This would be good for up to 5 bits in error. Some messages with 6 error bits could differ by 5 bits from multiple entries in codes[]. – rcgldr Sep 09 '21 at 19:19
1

I made a test program for David Eisenstat's example, to show it works for 1 to 5 bits in error. Code is for Visual Studio.

#include <intrin.h>
#include <stdio.h>
#include <stdlib.h>

typedef unsigned int uint32_t;

/*----------------------------------------------------------------------*/
/*      InitCombination - init combination                              */
/*----------------------------------------------------------------------*/
void InitCombination(int a[], int k, int n) {
    for(int i = 0; i < k; i++)
        a[i] = i;
    --a[k-1];
}

/*----------------------------------------------------------------------*/
/*      NextCombination - generate next combination                     */
/*----------------------------------------------------------------------*/
int NextCombination(int a[], int k, int n) {
int pivot = k - 1;
    while (pivot >= 0 && a[pivot] == n - k + pivot)
        --pivot;
    if (pivot == -1)
        return 0;
    ++a[pivot];
    for (int i = pivot + 1; i < k; ++i)
        a[i] = a[pivot] + i - pivot;
    return 1;
}

/*----------------------------------------------------------------------*/
/*      Rnd32 - return pseudo random 32 bit number                      */
/*----------------------------------------------------------------------*/
uint32_t Rnd32()
{
static uint32_t r = 0;
    r = r*1664525+1013904223;
    return r;
}

static uint32_t codes[256];

/*----------------------------------------------------------------------*/
/*      main - test random hamming distance 11 code                     */
/*----------------------------------------------------------------------*/
int main() {
int ptn[5];                                 /* error bit indexes */
int i, j, n;
uint32_t m;
int o, p;
    for (i = 0; i < 256; i++) {             /* generate table */
retry:
        codes[i] = Rnd32();
        for (j = 0; j < i; j++) {
            if (__popcnt(codes[i] ^ codes[j]) < 11) goto retry;
        }
    }
    for(n = 1; n <= 5; n++){                /* test 1 to 5 bit error patterns */
        InitCombination(ptn, n, 32);
        while(NextCombination(ptn, n, 32)){
            for(i = 0; i < 256; i++){
                o = m = codes[i];           /* o = m = coded msg */
                for(j = 0; j < n; j++){     /* add errors to m */
                    m ^= 1<<ptn[j];
                }
                for(j = 0; j < 256; j++){   /* search for code */
                    if((p =__popcnt(m ^ codes[j])) <= 5)
                        break;
                }
                if(i != j){                 /* check for match */
                    printf("fail %u %u\n", i, j);
                    goto exit0;
                }
            }
        }
    }

exit0:
    return 0;
}
rcgldr
  • 27,407
  • 3
  • 36
  • 61
  • Thank you! So far this has been the best algorithm. One thing that I did find in the meantime though is that in the wiki page for [Block Code](https://en.wikipedia.org/wiki/Block_code#Lower_and_upper_bounds_of_block_codes) there is a graph for the max theoretical and also constructible error correction methods for a given (n, k, d). For my problem, it seems that the limit is (28, 8, 12) with 4 bits to spear as seen in this [graph](https://i.imgur.com/MHe8F5s.png). Does that mean that there is a given algorithm that would make my message resilient up to 12 bitflips? – Mathias Sven Sep 10 '21 at 22:48
  • @MathiasSven - look at [Block Code error correction and detection capabilities](https://en.wikipedia.org/wiki/Block_code#Error_detection_and_correction_properties) again. It states that it can correct up to floor((hamming_distance - 1) / 2) errors. In this case, the Hamming distance is 11, so it can correct up to 5 error bits. As commented on David Eisenstat's answer, a 6 error bit case could differ by 5 bits from multiple codes in the table, so a correction attempt would select a valid code, but one that differs by 6+5 = 11 bits from the original code. – rcgldr Sep 10 '21 at 23:38
  • Ohh, my bad, I missed that part about correcting floor(...), thank you for the answer! – Mathias Sven Sep 10 '21 at 23:46
  • 1
    @MathiasSven - You would need a code with a distance of 13 bits to be able to correct 6 error bits, and the 32 bit random number method failed to do this. – rcgldr Sep 10 '21 at 23:48
  • I have been really trying to understand how this works exactly without having to ask further, but I am not really sure how this translates to what I want to do. How do I pass in the 8 bits argument and where in the code is it corrected? Is there a wikipage for this time of ECC? I tried "Randomization ECC" but with not much luck – Mathias Sven Sep 11 '21 at 18:34
  • 1
    @MathiasSven - the code in my answer does this. After creating the codes[] table, then for each message byte, you index the table, and transmit the 32 bit code from codes[message byte]. To decode, you compare the received 32 bit code with all of the values in codes[], stopping at the first one that differs by 5 or fewer bits ((popcnt(received_code ^ codes[index]) <= 5), and the index of that code will be the original message byte, assuming that the number of error bits is <= 5. My example code does this using *i* to represent all 256 possible message bytes, and *j* to confirm a match. – rcgldr Sep 11 '21 at 20:01