Search in sources :

Example 1 with GrowQueue_I8

use of org.ddogleg.struct.GrowQueue_I8 in project BoofCV by lessthanoptimal.

the class ReidSolomonCodes method correctErrors.

/**
 * Use Forney algorithm to compute correction values.
 *
 * @param message (Input/Output) The message which is to be corrected. Just the message. ECC not required.
 * @param length_msg_ecc (Input) length of message and ecc code
 * @param errorLocations (Input) locations of bytes in message with errors.
 */
void correctErrors(GrowQueue_I8 message, int length_msg_ecc, GrowQueue_I8 syndromes, GrowQueue_I8 errorLocator, GrowQueue_I32 errorLocations) {
    // TODO avoid new
    GrowQueue_I8 err_eval = new GrowQueue_I8();
    findErrorEvaluator(syndromes, errorLocator, err_eval);
    // Compute error positions
    // TODO avoid new
    GrowQueue_I8 X = GrowQueue_I8.zeros(errorLocations.size);
    for (int i = 0; i < errorLocations.size; i++) {
        int coef_pos = (length_msg_ecc - errorLocations.data[i] - 1);
        X.data[i] = (byte) math.power(2, coef_pos);
    // The commented out code below replicates exactly how the reference code works. This code above
    // seems to work just as well and passes all the unit tests
    // int coef_pos = math.max_value-(length_msg_ecc-errorLocations.data[i]-1);
    // X.data[i] = (byte)math.power_n(2,-coef_pos);
    }
    GrowQueue_I8 err_loc_prime_tmp = new GrowQueue_I8(X.size);
    // storage for error magnitude polynomial
    for (int i = 0; i < X.size; i++) {
        int Xi = X.data[i] & 0xFF;
        int Xi_inv = math.inverse(Xi);
        // Compute the polynomial derivative
        err_loc_prime_tmp.size = 0;
        for (int j = 0; j < X.size; j++) {
            if (i == j)
                continue;
            err_loc_prime_tmp.data[err_loc_prime_tmp.size++] = (byte) GaliosFieldOps.subtract(1, math.multiply(Xi_inv, X.data[j] & 0xFF));
        }
        // compute the product, which is the denominator of Forney algorithm (errata locator derivative)
        int err_loc_prime = 1;
        for (int j = 0; j < err_loc_prime_tmp.size; j++) {
            err_loc_prime = math.multiply(err_loc_prime, err_loc_prime_tmp.data[j] & 0xFF);
        }
        int y = math.polyEval_S(err_eval, Xi_inv);
        y = math.multiply(math.power(Xi, 1), y);
        // Compute the magnitude
        int magnitude = math.divide(y, err_loc_prime);
        // only apply a correction if it's part of the message and not the ECC
        int loc = errorLocations.get(i);
        if (loc < message.size)
            message.data[loc] = (byte) ((message.data[loc] & 0xFF) ^ magnitude);
    }
}
Also used : GrowQueue_I8(org.ddogleg.struct.GrowQueue_I8)

Example 2 with GrowQueue_I8

use of org.ddogleg.struct.GrowQueue_I8 in project BoofCV by lessthanoptimal.

the class ReidSolomonCodes method findErrorLocatorPolynomialBM.

/**
 * Computes the error locator polynomial using  Berlekamp-Massey algorithm [1]
 *
 * <p>[1] Massey, J. L. (1969), "Shift-register synthesis and BCH decoding" (PDF), IEEE Trans.
 * Information Theory, IT-15 (1): 122–127</p>
 *
 * @param syndromes (Input) The syndromes
 * @param errorLocator (Output) Error locator polynomial. Coefficients are large to small.
 */
void findErrorLocatorPolynomialBM(GrowQueue_I8 syndromes, GrowQueue_I8 errorLocator) {
    // error polynomial
    GrowQueue_I8 C = errorLocator;
    // previous error polynomial
    GrowQueue_I8 B = new GrowQueue_I8();
    // TODO remove new from this function
    initToOne(C, syndromes.size + 1);
    initToOne(B, syndromes.size + 1);
    GrowQueue_I8 tmp = new GrowQueue_I8(syndromes.size);
    // int L = 0;
    // int m = 1; // stores how much B is 'shifted' by
    int b = 1;
    for (int n = 0; n < syndromes.size; n++) {
        // Compute discrepancy delta
        int delta = syndromes.data[n] & 0xFF;
        for (int j = 1; j < C.size; j++) {
            delta ^= math.multiply(C.data[C.size - j - 1] & 0xFF, syndromes.data[n - j] & 0xFF);
        }
        // B = D^m * B
        B.data[B.size++] = 0;
        if (delta != 0) {
            int scale = math.multiply(delta, math.inverse(b));
            math.polyAddScaleB(C, B, scale, tmp);
            if (B.size <= C.size) {
            // if 2*L > N ---- Step 4
            // m += 1;
            } else {
                // if 2*L <= N --- Step 5
                B.setTo(C);
                // L = n+1-L;
                b = delta;
            // m = 1;
            }
            C.setTo(tmp);
        }
    }
    removeLeadingZeros(C);
}
Also used : GrowQueue_I8(org.ddogleg.struct.GrowQueue_I8)

Example 3 with GrowQueue_I8

use of org.ddogleg.struct.GrowQueue_I8 in project BoofCV by lessthanoptimal.

the class TestReidSolomonCodes method computeECC_python.

/**
 * Compare against results from python tutorial
 */
@Test
public void computeECC_python() {
    byte[] a = new byte[] { 0x40, (byte) 0xd2, 0x75, 0x47, 0x76, 0x17, 0x32, 0x06, 0x27, 0x26, (byte) 0x96, (byte) 0xc6, (byte) 0xc6, (byte) 0x96, 0x70, (byte) 0xec };
    byte[] b = new byte[] { (byte) 0xbc, 0x2a, (byte) 0x90, 0x13, 0x6b, (byte) 0xaf, (byte) 0xef, (byte) 0xfd, 0x4b, (byte) 0xe0 };
    GrowQueue_I8 message = new GrowQueue_I8();
    GrowQueue_I8 ecc = new GrowQueue_I8();
    message.data = a;
    message.size = a.length;
    ReidSolomonCodes alg = new ReidSolomonCodes(8, 0x11d);
    alg.generator(10);
    alg.computeECC(message, ecc);
    assertEquals(10, ecc.size);
    for (int i = 0; i < b.length; i++) {
        assertEquals(b[i], ecc.data[i]);
    }
}
Also used : GrowQueue_I8(org.ddogleg.struct.GrowQueue_I8) Test(org.junit.Test)

Example 4 with GrowQueue_I8

use of org.ddogleg.struct.GrowQueue_I8 in project BoofCV by lessthanoptimal.

the class TestReidSolomonCodes method correct_random.

/**
 * Randomly correct the message and ECC. See if the message is correctly reconstructed.
 */
@Test
public void correct_random() {
    GrowQueue_I8 ecc = new GrowQueue_I8();
    // should be able to recover from 4 errors
    int nsyn = 10;
    ReidSolomonCodes alg = new ReidSolomonCodes(8, primitive8);
    alg.generator(nsyn);
    for (int i = 0; i < 20000; i++) {
        GrowQueue_I8 message = randomMessage(100);
        GrowQueue_I8 corrupted = message.copy();
        alg.computeECC(message, ecc);
        // apply noise to the message
        int numErrors = rand.nextInt(6);
        for (int j = 0; j < numErrors; j++) {
            int selected = rand.nextInt(message.size);
            // make sure it changes even if the same number is selected twice
            corrupted.data[selected] ^= (0x12 + j);
        }
        // corrupt the ecc code
        if (numErrors < 5 && rand.nextInt(5) < 1) {
            numErrors++;
            ecc.data[rand.nextInt(ecc.size)] ^= 0x13;
        }
        alg.correct(corrupted, ecc);
        assertEquals(corrupted.size, message.size);
        for (int j = 0; j < corrupted.size; j++) {
            assertEquals(corrupted.get(j), message.get(j));
        }
    }
}
Also used : GrowQueue_I8(org.ddogleg.struct.GrowQueue_I8) Test(org.junit.Test)

Example 5 with GrowQueue_I8

use of org.ddogleg.struct.GrowQueue_I8 in project BoofCV by lessthanoptimal.

the class TestReidSolomonCodes method computeECC.

@Test
public void computeECC() {
    GrowQueue_I8 message = randomMessage(50);
    GrowQueue_I8 ecc = new GrowQueue_I8();
    ReidSolomonCodes alg = new ReidSolomonCodes(8, primitive8);
    alg.generator(6);
    alg.computeECC(message, ecc);
    assertEquals(6, ecc.size);
    int numNotZero = 0;
    for (int i = 0; i < ecc.size; i++) {
        if (0 != ecc.data[i])
            numNotZero++;
    }
    assertTrue(numNotZero >= 5);
// numerical properties are tested by computeSyndromes
}
Also used : GrowQueue_I8(org.ddogleg.struct.GrowQueue_I8) Test(org.junit.Test)

Aggregations

GrowQueue_I8 (org.ddogleg.struct.GrowQueue_I8)30 Test (org.junit.Test)22 GrowQueue_I32 (org.ddogleg.struct.GrowQueue_I32)3 GrayU16 (boofcv.struct.image.GrayU16)1 File (java.io.File)1 Buffer (java.nio.Buffer)1 ByteBuffer (java.nio.ByteBuffer)1