Error correcting code experiment

What if there is more errors that code is capable of correcting.
 avatar
unknown
c_cpp
a year ago
26 kB
16
Indexable
#include "pch.h"

//using namespace winrt;
//using namespace Windows::Foundation;




#include <intrin.h>
//#include <x86intrin.h>

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

typedef unsigned char      BYTE;
typedef unsigned short     WORD;
typedef unsigned int       DWORD;
typedef unsigned long long QWORD;

/*                              ** GF(2^6): x^6 + x + 1 */
#define POLY (0x43)

#define ALPHA (0x02)

/*                              ** 5 error correction, 10 syndromes */
#define NSYN (10)

/*                              ** use extended euclid algorithm */
#define EEUCLID 0

/*                              ** display euclid stuff */
#define DISPLAYE 0

/*                              ** display error locator poly */
#define DISPLAYP 0

typedef struct {                 /* vector structure */
    BYTE  size;
    BYTE  data[63];
}VECTOR;

#if EEUCLID
typedef struct {                 /* euclid structure */
    BYTE  size;                 /* # of data bytes */
    BYTE  indx;                 /* index to right side */
    BYTE  data[62];             /* left and right side data */
}EUCLID;
#endif

static __m128i poly;            /* generator poly */
static __m128i invpoly;         /* 2^64 / POLY */

static BYTE exp64[64];          /* exp64 table */
static BYTE log64[64];          /* log64 table */
static BYTE minplyf[128];       /* minimum polynomial flags */
static BYTE minply[64];         /* minimum polynomials */
static BYTE mincnt;             /* # of minimum polymials */

static __m128i psyn[NSYN];      /* syndrome polynomials */
static __m128i invsyn[NSYN];    /* inverse syndrome polynomials */

static __m128i msg;             /* msg.m128i_u64[0] is test message */
static __m128i par;             /* par.m128i_u64[1] is parities */

static QWORD   encmsg;          /* copy of encoded message */

#if EEUCLID
static EUCLID   E0;             /* used by GenpErrors (extended Euclid) */
static EUCLID   E1;
#else
static VECTOR   vB;             /* used by GenpErrors (Berleykamp Massey) */
static VECTOR   vC;
static VECTOR   vT;
static VECTOR   vBx;
#endif

static VECTOR   vSyndromes;
static VECTOR   pErrors;
static VECTOR   pLambda;
static VECTOR   vLocators;
static VECTOR   vOffsets;

static bool poly2rootfailed = false;

static void ListAlphas();
static void Tbli(void);
static void GenPoly(void);
static void Encode(void);
static void GenSyndromes(void);
static void GenpErrors(void);
static void GenOffsets(void);
static void FixErrors(void);
static int  Poly2Root(VECTOR*, VECTOR*);
static BYTE GFPwr(BYTE, BYTE);
static BYTE GFMpy(BYTE, BYTE);
static BYTE GFDiv(BYTE, BYTE);
static void ShowVector(VECTOR*);
#if EEUCLID
static void ShowEuclid(EUCLID*);
#endif
static void InitCombination(int[], int, int);
static int  NextCombination(int[], int, int);

#define GFAdd(a, b) (a^b)
#define GFSub(a, b) (a^b)

/*----------------------------------------------------------------------*/
/*      main                                                            */
/*----------------------------------------------------------------------*/
int main()
{
    int ptn[5];                     /* error bit indexes */
    int n;                          /* number of errors to test */
    int i;
    int ii;

    printf("start\n");


    ListAlphas();               /* list alphas */
    printf("\n");

    Tbli();                     /* init tables */
    GenPoly();                  /* generate poly info */
    /* 36 bits data, 27 bits parity*/
    msg.m128i_u64[0] = 0x1234567890000000ull >> 1;

    printf("data(shifted)=");
    for (ii = 0; ii < 63; ii++)
        printf("%d", ((msg.m128i_u64[0]) & (1ull << ii)) >> ii);
    printf("\n");

    Encode();                   /* encode message */

    long iter = 0;
    bool debug = false;

    encmsg = msg.m128i_u64[0];
    for (n = 6; n <= 6; n++) {    /* test 1 to 5 bit error patterns */
        printf("n=%d\n", n);
        InitCombination(ptn, n, 63);
        while (NextCombination(ptn, n, 63)) {
            msg.m128i_u64[0] = encmsg;
            iter++;
            if (iter % 100000 == 1)
                printf("iteration: %d\n", iter);

            if (debug) {
                printf("counter     =");
                for (ii = 0; ii < 63; ii++)
                    printf("%d", (ii + 1) % 10);
                printf("\n");
                printf("encoded     =");
                for (ii = 0; ii < 63; ii++)
                    printf("%d", (encmsg & (1ull << ii)) >> ii);
                printf("\n");
                printf("introducing %d errors\n", n);
                printf("error bits indexes=");
                for (ii = 0; ii < n; ii++)
                    printf("%d ", ptn[ii]);
                printf("\n");
            }

            for (i = 0; i < n; i++)
                msg.m128i_u64[0] ^= 1ull << ptn[i];

            if (debug) {
                printf("corrupted   =");
                for (ii = 0; ii < 63; ii++)
                    printf("%d", ((msg.m128i_u64[0]) & (1ull << ii)) >> ii);
                printf("\n");
            }

            GenSyndromes();     /* generate syndromes */

            if (debug) {
                printf("syndromes (%d): ", vSyndromes.size);
                for (int ii = 0; ii < vSyndromes.size; ii++)
                    printf("%d ", vSyndromes.data[ii]);
                printf("\n");
            }

            GenpErrors();       /* generate error location info */
            if (poly2rootfailed)
            {
                if (debug)
                    printf("could not decode.\n");
                if (n > 5) {
                    continue;   // this is expected (and desired) for more than five errors
                } 
                else {
                    printf("FATAL: could not decode %d errors", n);
                    printf("error bits indexes=");
                    for (ii = 0; ii < n; ii++)
                        printf("%d ", ptn[ii]);
                    printf("\n");
                    return 1;
                }
            }

            if (debug) {
                printf("pErrors (%d):", pErrors.size);
                for (int ii = 0; ii < pErrors.size; ii++)
                    printf("%d ", pErrors.data[ii]);
                printf("\n");

                printf("vLocators (%d):", vLocators.size);
                for (int ii = 0; ii < vLocators.size; ii++)
                    printf("%d ", vLocators.data[ii]);
                printf("\n");
            }

            GenOffsets();       /* convert to offsets */

            if (debug) {
                printf("vOffsets (%d):", vOffsets.size);
                for (int ii = 0; ii < vOffsets.size; ii++)
                    printf("%d ", vOffsets.data[ii]);
                printf("\n");
            }
            
            FixErrors();        /* correct error bits */

            if (debug) {
                printf("corrected   =");
                for (ii = 0; ii < 63; ii++)
                    printf("%d", (msg.m128i_u64[0] & (1ull << ii)) >> ii);
                printf("\n");
            }

            if (encmsg != msg.m128i_u64[0]) {
                if (debug)
                    printf(" ---------------------------------------------------------------------------- FAILED, tried to correct %d errors\n", vOffsets.size);
            
            }
            else {
                if (debug)
                    printf(" ---------------------------------------------------------------------------- OK, (%d errors corrected)\n", vOffsets.size);
            }

            if (vOffsets.size < 5) {
                printf("FATAL: errors introduced: %d, errors detected: %d\n", n, vOffsets.size);
                printf("error bits indexes=");
                for (ii = 0; ii < n; ii++)
                    printf("%d ", ptn[ii]);
                printf("\n");
                return 1;
            }
        }
    }
    printf("done.\n");
    return 0;
}

/*----------------------------------------------------------------------*/
/*      ListAlphas                                                      */
/*----------------------------------------------------------------------*/
static void ListAlphas()
{
    __m128i d0, alpha;
    DWORD i, j, k;
    k = 0;
    for (j = 2; j < 0x40; j++) {
        alpha.m128i_u64[0] = j;
        d0.m128i_u64[0] = 0x01;
        i = 0;
        while (1) {
            d0 = _mm_clmulepi64_si128(d0, alpha, 0x00);
            if (d0.m128i_u16[0] & 0x0400)
                d0.m128i_u16[0] ^= POLY << 4;
            if (d0.m128i_u16[0] & 0x0200)
                d0.m128i_u16[0] ^= POLY << 3;
            if (d0.m128i_u16[0] & 0x0100)
                d0.m128i_u16[0] ^= POLY << 2;
            if (d0.m128i_u16[0] & 0x0080)
                d0.m128i_u16[0] ^= POLY << 1;
            if (d0.m128i_u16[0] & 0x0040)
                d0.m128i_u16[0] ^= POLY << 0;
            if (d0.m128i_u16[0] == 0x01)
                break;
            i++;
        }
        if (i == 0x3e) {
            printf(" %02x", j);
            if (++k == 8) {
                printf("\n");
                k = 0;
            }
        }
    }
}

/*----------------------------------------------------------------------*/
/*      Tbli                                                            */
/*----------------------------------------------------------------------*/
static void Tbli()              /* init tables */
{
    __m128i d0, alpha;
    BYTE* p0, * p1;
    alpha.m128i_u64[0] = ALPHA; /* init exp64 table */
    d0.m128i_u64[0] = 0x01;
    p0 = exp64;
    for (p1 = p0 + 64; p0 < p1;) {
        *p0++ = d0.m128i_u8[0];
        d0 = _mm_clmulepi64_si128(d0, alpha, 0x00);
        if (d0.m128i_u16[0] & 0x0400)
            d0.m128i_u16[0] ^= POLY << 4;
        if (d0.m128i_u16[0] & 0x0200)
            d0.m128i_u16[0] ^= POLY << 3;
        if (d0.m128i_u16[0] & 0x0100)
            d0.m128i_u16[0] ^= POLY << 2;
        if (d0.m128i_u16[0] & 0x0080)
            d0.m128i_u16[0] ^= POLY << 1;
        if (d0.m128i_u16[0] & 0x0040)
            d0.m128i_u16[0] ^= POLY << 0;
    }

    p0 = exp64;                 /* init log64 table */
    p1 = log64;
    *p1 = 0;
    for (d0.m128i_u8[0] = 0; d0.m128i_u8[0] < 63; d0.m128i_u8[0] += 1)
        *(p1 + *p0++) = d0.m128i_u8[0];
}

/*----------------------------------------------------------------------*/
/*      GenPoly                                                         */
/*----------------------------------------------------------------------*/
static void GenPoly(void)
{
    QWORD M;
    QWORD N;
    QWORD Q;
    DWORD x=0;
    BYTE mpoly;                     /* test polynomial */
    BYTE sum;                       /* sum, looking for zeroes */
    BYTE apwr;                      /* alpha to power */
    BYTE i, j;

    /* find minimum and non-duplicate polynomials for m[1] -> m[NSYN] */
    i = 0;
    do {
        apwr = GFPwr(ALPHA, ++i);
        for (mpoly = 0x02; mpoly <= 0x7f; mpoly++) {
            sum = 0;
            for (j = 0; j <= 6; j++) {
                if (mpoly & (1 << j))
                    sum ^= GFPwr(apwr, j);
            }
            if (sum == 0) {
                if (minplyf[mpoly] != 0)
                    continue;
                minplyf[mpoly] = 1;
                minply[mincnt] = mpoly;
                mincnt += 1;
                break;
            }
        }
    } while (i < NSYN);

    /* generate least common multiple encoding polynomial */
    poly.m128i_u64[0] = minply[0];
    for (i = 1; i < mincnt; i++) {
        poly.m128i_u64[1] = minply[i];
        poly = _mm_clmulepi64_si128(poly, poly, 0x01);
    }

    /* generate inverse of encoding polynomial */
    unsigned long tmpx = x;
    _BitScanReverse64(&tmpx, poly.m128i_u64[0]);
    x = tmpx;
    M = 1ull << x;
    N = M >> 1;
    Q = 0x0ull;
    for (i = 0; i < 65 - x; i++) {
        N <<= 1;
        Q <<= 1;
        if (N & M) {
            Q |= 1;
            N ^= (poly.m128i_u64[0]);
        }
    }
    invpoly.m128i_u64[0] = Q;
}

/*----------------------------------------------------------------------*/
/*      Encode                                                          */
/*----------------------------------------------------------------------*/
static void Encode(void)
{
    par = _mm_clmulepi64_si128(msg, invpoly, 0x00); /* par[1] = quotient */
    par = _mm_clmulepi64_si128(par, poly, 0x01);    /* par[0] = product */
    par.m128i_u64[0] ^= msg.m128i_u64[0];           /* par[0] = remainder */
    msg.m128i_u64[0] |= par.m128i_u64[0];           /* msg[0] = encoded message */
}

/*----------------------------------------------------------------------*/
/*      GenSyndromes                                                    */
/*----------------------------------------------------------------------*/
static void GenSyndromes(void)
{
    QWORD M;
    DWORD x=0;
    BYTE i, ap, s;
    vSyndromes.size = NSYN;
    for (i = 0; i < NSYN; i++) {
        M = msg.m128i_u64[0];
        ap = GFPwr(ALPHA, i + 1);
        s = 0;
        while (M) {
            unsigned long tmpx = x;
            _BitScanReverse64(&tmpx, M);
            x = tmpx;
            M ^= 1ull << x;
            s ^= GFPwr(ap, x);
        }
        vSyndromes.data[i] = s;
    }
}

#if EEUCLID
/*----------------------------------------------------------------------*/
/*      GenpErrors     generate pErrors via Euclid division algorithm   */
/*----------------------------------------------------------------------*/
static void GenpErrors(void)
{
    /* R[] is msb first | A[] is msb last (reversed) */
    EUCLID* pED;                            /* R[i-2] | A[i-1] */
    EUCLID* pER;                            /* R[i-1] | A[i-2] */
    EUCLID* pET;                            /* temp */
    int     i, j;
    BYTE    bME;                            /* max errors possible */
    BYTE    bQuot;                          /* quotient */

    /*      E0 = initial ED: E0.R[-1] = x^MAXERR, E0.A[0] = 1 */
    E0.size = vSyndromes.size + 2;
    E0.indx = vSyndromes.size + 1;
    E0.data[0] = 1;
    memset(&E0.data[1], 0, vSyndromes.size * sizeof(BYTE));
    E0.data[E0.indx] = 1;
    pED = &E0;

    /*      E1 = initial ER: E1.R[0] = syndrome polynomial, E1.A[-1] = 0 */
    E1.size = vSyndromes.size + 2;
    E1.indx = vSyndromes.size + 1;
    E1.data[0] = 0;
    for (i = 1; i < E1.indx; i++) {
        E1.data[i] = vSyndromes.data[vSyndromes.size - i];
    }
    E1.data[E1.indx] = 0;
    pER = &E1;

    /*      init bME */
    bME = vSyndromes.size / 2;

    /*      Euclid algorithm */

    while (1) {                           /* while degree ER.R > max errors */
#if DISPLAYE
        printf("ED: ");
        ShowEuclid(pED);
        printf("ER: ");
        ShowEuclid(pER);
#endif
        while ((pER->data[0] == 0) &&    /* shift dvsr left until msb!=0 */
            (pER->indx != 0)) {        /*  or fully shifted left */
            pER->indx--;
            memcpy(&pER->data[0], &pER->data[1], (pER->size - 1) * sizeof(BYTE));
            pER->data[pER->size - 1] = 0;
        }

        if (pER->indx <= bME) {           /* if degree ER.R[] <= bME, break */
            break;
        }

        while (1) {                       /* while more sub-steps */
            if (pED->data[0]) {           /*   if ED.R[] msb!=0, update ED, ER */
                bQuot = GFDiv(pED->data[0], pER->data[0]); /* Q=ED.R[msb]/ER.R[msb] */
                for (i = 0; i < pER->indx; i++) {            /* ED.R[]=ED.R[]-Q*ER.R[] */
                    pED->data[i] = GFSub(pED->data[i], GFMpy(bQuot, pER->data[i]));
                }
                for (i = pED->indx; i < pER->size; i++) {    /* ER.A[]=ER.A[]-Q*ED.A[] */
                    pER->data[i] = GFSub(pER->data[i], GFMpy(bQuot, pED->data[i]));
                }
            }
            if (pED->indx == pER->indx) { /*   if sub-steps done, break */
                break;
            }
            pED->indx--;                /*   shift ED left */
            memcpy(&pED->data[0], &pED->data[1], (pED->size - 1) * sizeof(BYTE));
            pED->data[pED->size - 1] = 0;
        }

        pET = pER;                      /* swap ED, ER */
        pER = pED;
        pED = pET;
    }

    pErrors.size = pED->size - pED->indx; /* set pErrors.size */

    if ((pER->indx) >= pErrors.size) {    /*  if degree ER.R too high */
        printf("GenpErrors remainder.size >= errors.size\n");
        goto fail0;
    }

#if 0
    j = pErrors.size - 1;       /* right shift ER if Omega has leading zeroes */
    while (pER->indx < j) {
        pER->indx++;
        for (i = pER->size - 1; i;) {
            i--;
            pER->data[i + 1] = pER->data[i];
        }
        pER->data[0] = 0;
    }
#if DISPLAYE
    printf("EX: ");
    ShowEuclid(pER);
#endif
#endif

    /*      pErrors = ED.A[] without unreversing = Lambda reversed */
    j = pED->indx;
    for (i = 0; i < pErrors.size; i++) {
        pErrors.data[i] = pED->data[j];
        j++;
    }

#if DISPLAYE
    printf("pErrors (e):    ");
    ShowVector(&pErrors);
#endif

    /*      Make most significant coef pErrors == 1 (divide by it) */
    bQuot = pErrors.data[0];
    if (bQuot == 0) {
        printf("GenpErrors most sig coef of pErrors == 0\n");
        pLambda.size = 1;
        pLambda.data[0] = 1;
        goto fail0;
    }
    for (i = 0; i < pErrors.size; i++) {
        pErrors.data[i] = GFDiv(pErrors.data[i], bQuot);
    }
#if DISPLAYE
    printf("pErrors (E):    ");
    ShowVector(&pErrors);
#endif

    /*      Find roots of pErrors (if fail, then set for no roots) */

    if (Poly2Root(&vLocators, &pErrors)) {    /* solve error poly */
        printf("GenpErrors poly2root failed \n");
    fail0:
        pErrors.size = 1;                   /* handle no root case */
        pErrors.data[0] = 1;
        vLocators.size = 0;
    }
}

#else

/*----------------------------------------------------------------------*/
/*      GenpErrors      generate pErrors via Berklekamp Massey          */
/*      note poly most signifcant index == 0                            */
/*----------------------------------------------------------------------*/
static void GenpErrors(void)
{
    BYTE i, j, n;
    BYTE L, m;
    BYTE b, d;
    BYTE db;

    b = 1;                              /* discrepancy when L last updated */
    L = 0;                              /* number of errors */
    m = 1;                              /* # iterations since L last updated */
    vB.size = 1;
    vB.data[0] = 1;
    vC.size = 1;
    vC.data[0] = 1;

    for (n = 0; n < vSyndromes.size; n++) {
        if (n & 1) {                        /* BCH only, if odd step, d == 0 */
            m += 1;
            continue;
        }
        d = vSyndromes.data[n];         /* calculate discrepancy */
        for (i = 1; i <= L; i++) {
            d = GFAdd(d, GFMpy(vC.data[(vC.size - 1) - i], vSyndromes.data[n - i]));
        }
        if (d == 0) {                     /* if 0 increment m, continue */
            m += 1;
            continue;
        }
        vT.size = vC.size;              /* vT = vC */
        memcpy(vT.data, vC.data, vC.size);
        db = GFDiv(d, b);                /* db = (d/b) */
        vBx.size = vB.size + m;           /* Bx = x^m B */
        memcpy(vBx.data, vB.data, vB.size);
        memset(&vBx.data[vB.size], 0, m);
        for (i = 0; i < vBx.size; i++) {  /* Bx *= db */
            vBx.data[i] = GFMpy(vBx.data[i], db);
        }
        j = vBx.size - vC.size;         /* right shift vBx or vC */
        if (((char)j) > 0) {
            for (i = vBx.size; i > j; ) {
                i--;
                vC.data[i] = vC.data[i - j];
            }
            memset(vC.data, 0, j);
            vC.size += j;
        }
        else if (((char)j) < 0) {
            j = -j;
            for (i = vC.size; i > j; ) {
                i--;
                vBx.data[i] = vBx.data[i - j];
            }
            memset(vBx.data, 0, j);
            vBx.size += j;
        }
        for (i = 0; i < vC.size; i++) {   /* C -= Bx */
            vC.data[i] = GFSub(vC.data[i], vBx.data[i]);
        }
        if (n < 2 * L) {                    /* if L not increasing */
            m += 1;
            continue;
        }
        vB.size = vT.size;              /*   B = T */
        memcpy(vB.data, vT.data, vT.size);
        L = n + 1 - L;                  /* update L */
        b = d;                          /* update b */
        m = 1;
    }                         /* reset m */

    pErrors.size = vC.size;             /* pErrors = reversed VC */
    for (i = 0; i < vC.size; i++)
        pErrors.data[i] = vC.data[vC.size - 1 - i];

    poly2rootfailed = false;
    if (Poly2Root(&vLocators, &pErrors)) {    /* solve error poly */
        //printf("GenpErrors poly2root failed \n");
        poly2rootfailed = true;
        pErrors.size = 1;                   /* handle no root case */
        pErrors.data[0] = 1;
        vLocators.size = 0;
    }
}

#endif

/*----------------------------------------------------------------------*/
/*      GenOffsets                                                      */
/*----------------------------------------------------------------------*/
static void GenOffsets(void)
{
    BYTE i;
    vOffsets.size = vLocators.size;
    for (i = 0; i < vLocators.size; i++) {
        vOffsets.data[i] = log64[vLocators.data[i]];
    }
}

/*----------------------------------------------------------------------*/
/*      FixErrors                                                       */
/*----------------------------------------------------------------------*/
static void FixErrors()
{
    BYTE i;
    for (i = 0; i < vOffsets.size; i++)
        msg.m128i_u64[0] ^= 1ull << vOffsets.data[i];
}

/*----------------------------------------------------------------------*/
/*      Poly2Root(pVDst, pPSrc)         find roots of poly              */
/*----------------------------------------------------------------------*/
static int Poly2Root(VECTOR* pVDst, VECTOR* pPSrc)
{
    BYTE    bLcr;                           /* current locator */
    BYTE    bSum;                           /* current sum */
    BYTE    bV;                             /* index to pVDst */
    BYTE    i, j;

    pVDst->size = pPSrc->size - 1;        /* set dest size */

    if (!pVDst->size)                    /* exit if null */
        return(0);

    bV = 0;
    bLcr = 1;
    for (j = 0; j < 63; j++) {
        bSum = 0;                       /* sum up terms */
        for (i = 0; i < pPSrc->size; i++) {
            bSum = GFMpy(bSum, bLcr);
            bSum = GFAdd(bSum, pPSrc->data[i]);
        }

        if (!bSum) {                      /* if a root */
            if (bV == pVDst->size) {      /*    exit if too many roots */
                return(1);
            }
            pVDst->data[bV] = bLcr;     /*    add locator */
            bV++;
        }

        bLcr = GFMpy(bLcr, ALPHA);
    }     /* set up next higher alpha */

    if (bV != pVDst->size)               /* exit if not enough roots */
        return(1);

    return(0);
}

/*----------------------------------------------------------------------*/
/*      GFPwr                                                           */
/*----------------------------------------------------------------------*/
static BYTE GFPwr(BYTE m0, BYTE m1)
{
    return exp64[(BYTE)((log64[m0] * (DWORD)m1) % 63)];
}

/*----------------------------------------------------------------------*/
/*      GFMpy                                                           */
/*----------------------------------------------------------------------*/
static BYTE GFMpy(BYTE m0, BYTE m1) /* multiply */
{
    int m2;
    if (0 == m0 || 0 == m1)
        return(0);
    m2 = log64[m0] + log64[m1];
    if (m2 > 63)
        m2 -= 63;
    return(exp64[m2]);
}

/*----------------------------------------------------------------------*/
/*      GFDiv                                                           */
/*----------------------------------------------------------------------*/
static BYTE GFDiv(BYTE m0, BYTE m1) /* divide */
{
    int m2;
    if (0 == m0)
        return(0);
    m2 = log64[m0] - log64[m1];
    if (m2 < 0)
        m2 += 63;
    return(exp64[m2]);
}

/*----------------------------------------------------------------------*/
/*      ShowVector                                                      */
/*----------------------------------------------------------------------*/
static void ShowVector(VECTOR* pVSrc)
{
    BYTE    i;
    for (i = 0; i < pVSrc->size; ) {
        printf(" %02x", pVSrc->data[i]);
        i++;
        if (0 == (i & 0xf)) {
            printf("\n");
        }
    }
    printf("\n");
}


#if EEUCLID
/*----------------------------------------------------------------------*/
/*      ShowEuclid                                                      */
/*----------------------------------------------------------------------*/
static void ShowEuclid(EUCLID* pESrc)
{
    BYTE    i;
    for (i = 0; i < pESrc->indx; i++) {
        printf(" %02x", pESrc->data[i]);
    }
    printf("|");
    for (; i < pESrc->size; i++) {
        printf("%02x ", pESrc->data[i]);
    }
    printf("\n");
}
#endif

/*----------------------------------------------------------------------*/
/*      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;
}
Editor is loading...
Leave a Comment