15317bbafSopenharmony_ci/* 25317bbafSopenharmony_ci * Fast QR Code generator library 35317bbafSopenharmony_ci * 45317bbafSopenharmony_ci * Copyright (c) Project Nayuki. (MIT License) 55317bbafSopenharmony_ci * https://www.nayuki.io/page/fast-qr-code-generator-library 65317bbafSopenharmony_ci * 75317bbafSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy of 85317bbafSopenharmony_ci * this software and associated documentation files (the "Software"), to deal in 95317bbafSopenharmony_ci * the Software without restriction, including without limitation the rights to 105317bbafSopenharmony_ci * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 115317bbafSopenharmony_ci * the Software, and to permit persons to whom the Software is furnished to do so, 125317bbafSopenharmony_ci * subject to the following conditions: 135317bbafSopenharmony_ci * - The above copyright notice and this permission notice shall be included in 145317bbafSopenharmony_ci * all copies or substantial portions of the Software. 155317bbafSopenharmony_ci * - The Software is provided "as is", without warranty of any kind, express or 165317bbafSopenharmony_ci * implied, including but not limited to the warranties of merchantability, 175317bbafSopenharmony_ci * fitness for a particular purpose and noninfringement. In no event shall the 185317bbafSopenharmony_ci * authors or copyright holders be liable for any claim, damages or other 195317bbafSopenharmony_ci * liability, whether in an action of contract, tort or otherwise, arising from, 205317bbafSopenharmony_ci * out of or in connection with the Software or the use or other dealings in the 215317bbafSopenharmony_ci * Software. 225317bbafSopenharmony_ci */ 235317bbafSopenharmony_ci 245317bbafSopenharmony_cipackage io.nayuki.fastqrcodegen; 255317bbafSopenharmony_ci 265317bbafSopenharmony_ciimport java.util.Arrays; 275317bbafSopenharmony_ciimport java.util.Objects; 285317bbafSopenharmony_ci 295317bbafSopenharmony_ci 305317bbafSopenharmony_ci// Computes Reed-Solomon error correction codewords for given data codewords. 315317bbafSopenharmony_cifinal class ReedSolomonGenerator { 325317bbafSopenharmony_ci 335317bbafSopenharmony_ci // Use this memoizer to get instances of this class. 345317bbafSopenharmony_ci public static final Memoizer<Integer,ReedSolomonGenerator> MEMOIZER 355317bbafSopenharmony_ci = new Memoizer<>(ReedSolomonGenerator::new); 365317bbafSopenharmony_ci 375317bbafSopenharmony_ci 385317bbafSopenharmony_ci // A table of size 256 * degree, where polynomialMultiply[i][j] = multiply(i, coefficients[j]). 395317bbafSopenharmony_ci // 'coefficients' is the temporary array computed in the constructor. 405317bbafSopenharmony_ci private byte[][] polynomialMultiply; 415317bbafSopenharmony_ci 425317bbafSopenharmony_ci 435317bbafSopenharmony_ci // Creates a Reed-Solomon ECC generator polynomial for the given degree. 445317bbafSopenharmony_ci private ReedSolomonGenerator(int degree) { 455317bbafSopenharmony_ci if (degree < 1 || degree > 255) 465317bbafSopenharmony_ci throw new IllegalArgumentException("Degree out of range"); 475317bbafSopenharmony_ci 485317bbafSopenharmony_ci // The divisor polynomial, whose coefficients are stored from highest to lowest power. 495317bbafSopenharmony_ci // For example, x^3 + 255x^2 + 8x + 93 is stored as the uint8 array {255, 8, 93}. 505317bbafSopenharmony_ci byte[] coefficients = new byte[degree]; 515317bbafSopenharmony_ci coefficients[degree - 1] = 1; // Start off with the monomial x^0 525317bbafSopenharmony_ci 535317bbafSopenharmony_ci // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}), 545317bbafSopenharmony_ci // and drop the highest monomial term which is always 1x^degree. 555317bbafSopenharmony_ci // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D). 565317bbafSopenharmony_ci int root = 1; 575317bbafSopenharmony_ci for (int i = 0; i < degree; i++) { 585317bbafSopenharmony_ci // Multiply the current product by (x - r^i) 595317bbafSopenharmony_ci for (int j = 0; j < coefficients.length; j++) { 605317bbafSopenharmony_ci coefficients[j] = (byte)multiply(coefficients[j] & 0xFF, root); 615317bbafSopenharmony_ci if (j + 1 < coefficients.length) 625317bbafSopenharmony_ci coefficients[j] ^= coefficients[j + 1]; 635317bbafSopenharmony_ci } 645317bbafSopenharmony_ci root = multiply(root, 0x02); 655317bbafSopenharmony_ci } 665317bbafSopenharmony_ci 675317bbafSopenharmony_ci polynomialMultiply = new byte[256][degree]; 685317bbafSopenharmony_ci for (int i = 0; i < polynomialMultiply.length; i++) { 695317bbafSopenharmony_ci for (int j = 0; j < degree; j++) 705317bbafSopenharmony_ci polynomialMultiply[i][j] = (byte)multiply(i, coefficients[j] & 0xFF); 715317bbafSopenharmony_ci } 725317bbafSopenharmony_ci } 735317bbafSopenharmony_ci 745317bbafSopenharmony_ci 755317bbafSopenharmony_ci // Returns the error correction codeword for the given data polynomial and this divisor polynomial. 765317bbafSopenharmony_ci public void getRemainder(byte[] data, int dataOff, int dataLen, byte[] result) { 775317bbafSopenharmony_ci Objects.requireNonNull(data); 785317bbafSopenharmony_ci Objects.requireNonNull(result); 795317bbafSopenharmony_ci int degree = polynomialMultiply[0].length; 805317bbafSopenharmony_ci assert result.length == degree; 815317bbafSopenharmony_ci 825317bbafSopenharmony_ci Arrays.fill(result, (byte)0); 835317bbafSopenharmony_ci for (int i = dataOff, dataEnd = dataOff + dataLen; i < dataEnd; i++) { // Polynomial division 845317bbafSopenharmony_ci byte[] table = polynomialMultiply[(data[i] ^ result[0]) & 0xFF]; 855317bbafSopenharmony_ci for (int j = 0; j < degree - 1; j++) 865317bbafSopenharmony_ci result[j] = (byte)(result[j + 1] ^ table[j]); 875317bbafSopenharmony_ci result[degree - 1] = table[degree - 1]; 885317bbafSopenharmony_ci } 895317bbafSopenharmony_ci } 905317bbafSopenharmony_ci 915317bbafSopenharmony_ci 925317bbafSopenharmony_ci // Returns the product of the two given field elements modulo GF(2^8/0x11D). The arguments and result 935317bbafSopenharmony_ci // are unsigned 8-bit integers. This could be implemented as a lookup table of 256*256 entries of uint8. 945317bbafSopenharmony_ci private static int multiply(int x, int y) { 955317bbafSopenharmony_ci assert x >> 8 == 0 && y >> 8 == 0; 965317bbafSopenharmony_ci // Russian peasant multiplication 975317bbafSopenharmony_ci int z = 0; 985317bbafSopenharmony_ci for (int i = 7; i >= 0; i--) { 995317bbafSopenharmony_ci z = (z << 1) ^ ((z >>> 7) * 0x11D); 1005317bbafSopenharmony_ci z ^= ((y >>> i) & 1) * x; 1015317bbafSopenharmony_ci } 1025317bbafSopenharmony_ci assert z >>> 8 == 0; 1035317bbafSopenharmony_ci return z; 1045317bbafSopenharmony_ci } 1055317bbafSopenharmony_ci 1065317bbafSopenharmony_ci} 107