program now using polyomial class to calculate FCS

This commit is contained in:
Hubert Tylkowski 2018-07-01 14:06:25 +02:00
parent 2e16ad8b73
commit 446a46fd69
7 changed files with 241 additions and 185 deletions

View File

@ -3,158 +3,46 @@ package com.tylkowski.crc;
import java.util.Arrays;
class CrcTask {
private String message;
private short[] messageAsShortArray;
private short[] polyGenerator;
private String rawMessage;
CrcTask(String message) {
this.rawMessage = message;
this.message = formatMessage(toBinaryString(message)) + "0000000000000000";
createGeneratingPolynomial();
public CrcTask() {
}
private String formatMessage(String message) {
int firstNonZeroVal = 0;
boolean found = false;
StringBuilder validString = new StringBuilder();
while (!found && firstNonZeroVal < message.length()) {
if (message.charAt(firstNonZeroVal) == 48) {
firstNonZeroVal++;
} else {
found = true;
public Polynomial encode(String message) {
Polynomial g = new Polynomial("[1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1]", 2); //G(X)
Polynomial l = new Polynomial("[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]", 2); // L(X) 16 * 1
Polynomial m = new Polynomial("[" + formatMessageToBinaryArrayPolynomial(message) + "]", 2);
m.reverse();
Polynomial tmp2 = new Polynomial(l);
for (int i = 0; i < m.getSize(); i++) {
tmp2.append(0, 0);
}
Polynomial tmp = new Polynomial(m);
for (int i = 0; i < 16; i++) {
tmp.append(0, 0);
}
Polynomial sum = tmp.add(tmp2);
Polynomial fcsPoly = sum.moduloPolyDivide(g);
while (fcsPoly.getSize() < 16) {
fcsPoly.append(0, 0);
}
fcsPoly.reverse();
return fcsPoly;
}
for (int i = firstNonZeroVal; i < message.length(); i++) {
if (message.charAt(i) == 48) {
validString.append(0);
} else {
validString.append(1);
}
}
StringBuilder msg = new StringBuilder(validString.toString());
while (msg.length() % 8 != 0) {
msg.insert(0, "0");
public String generateFCSChars(Polynomial poly) {
String binString = Arrays.toString(poly.getPolynomialArray());
binString = binString.replace(",", "");
binString = binString.replace("]", "");
binString = binString.replace("[", "");
binString = binString.replace(" ", "");
return "0x" + Integer.toHexString(Integer.parseInt(binString, 2));
}
return msg.toString();
}
private String generateFCS() {
while (true) {
if (messageAsShortArray[0] == 0) {
messageAsShortArray = Arrays.copyOfRange(messageAsShortArray, 1, messageAsShortArray.length);
} else {
short[] piece = Arrays.copyOfRange(messageAsShortArray, 0, Math.min(polyGenerator.length, messageAsShortArray.length));
if (piece.length < polyGenerator.length) {
fillPolynomial(piece);
return createTwoCharsOfFCS(piece);
}
short[] remainder = calcXOR(piece, polyGenerator);
remainder = removeUnecessaryZeros(remainder);
messageAsShortArray = createMessageFromRemainderAndPartFromOldMessage(remainder, messageAsShortArray);
}
}
}
private String createTwoCharsOfFCS(short[] piece) {
short[] firstPiece = Arrays.copyOfRange(piece, 0, 8);
short[] secondPiece = Arrays.copyOfRange(piece, piece.length - 8, piece.length);
short[] mergedPieces = new short[firstPiece.length + secondPiece.length];
for (int i = 0; i < firstPiece.length; i++) {
mergedPieces[i] = firstPiece[i];
mergedPieces[i + 8] = secondPiece[i];
}
return "0x" + Integer.toHexString(Integer.parseInt(shortArrayToBinaryString(mergedPieces), 2));
}
private short[] createMessageFromRemainderAndPartFromOldMessage(short[] remainder, short[] msg) {
short[] tempArr = new short[remainder.length + msg.length - polyGenerator.length];
System.arraycopy(remainder, 0, tempArr, 0, remainder.length);
int diff = polyGenerator.length - remainder.length;
System.arraycopy(msg, remainder.length + diff, tempArr, remainder.length, msg.length - diff - remainder.length);
msg = tempArr;
return msg;
}
private short[] removeUnecessaryZeros(short[] remainder) {
int firstNonZeroVal = 0;
boolean found = false;
while (!found && firstNonZeroVal < remainder.length) {
if (remainder[firstNonZeroVal] == 0) {
firstNonZeroVal++;
} else {
found = true;
}
}
return Arrays.copyOfRange(remainder, firstNonZeroVal, remainder.length);
}
private short[] calcXOR(short[] piece, short[] polyGenerator) {
int a = Integer.parseInt(shortArrayToBinaryString(piece), 2);
int b = Integer.parseInt(shortArrayToBinaryString(polyGenerator), 2);
String binaryString = Integer.toBinaryString(a ^ b);
return convertBinaryStringToShortArray(binaryString);
}
private String shortArrayToBinaryString(short[] value) {
StringBuilder binaryString = new StringBuilder();
for (Short a : value) {
binaryString.append(a);
}
return binaryString.toString();
}
private void fillPolynomial(short[] piece) {
while (piece.length % 8 != 0) {
piece = addZeroAtBeginningOfArray(piece);
}
}
private short[] addZeroAtBeginningOfArray(short[] piece) {
short[] tempArray = new short[piece.length + 1];
tempArray[0] = 0;
System.arraycopy(piece, 0, tempArray, 1, piece.length);
return tempArray;
}
private short[] convertBinaryStringToShortArray(String binaryString) {
short[] shortArray = new short[binaryString.length()];
for (int i = 0; i < binaryString.length(); i++) {
if (binaryString.charAt(i) == 48) {
shortArray[i] = 0;
} else {
shortArray[i] = 1;
}
}
return shortArray;
}
private void createGeneratingPolynomial() {
polyGenerator = new short[17];
for (int i = 0; i < 17; i++) {
polyGenerator[i] = 0;
}
polyGenerator[0] = 1;
polyGenerator[4] = 1;
polyGenerator[11] = 1;
polyGenerator[16] = 1;
}
private short[] swapPolynomialValues(short[] poly) {
for (int i = 0; i < polyGenerator.length - 1; i++) {
poly[i] = (short) ((poly[i] + 1) % 2);
}
return poly;
}
String encode() {
messageAsShortArray = convertBinaryStringToShortArray(message);
messageAsShortArray = swapPolynomialValues(messageAsShortArray);
return rawMessage + generateFCS();
private String formatMessageToBinaryArrayPolynomial(String message) {
String msgBinString = toBinaryString(message);
msgBinString = msgBinString.replace("1", "1,");
msgBinString = msgBinString.replace("0", "0,");
msgBinString = msgBinString.substring(0, msgBinString.length() - 1);
return msgBinString;
}
private String letterToBinaryString(char letter) {
@ -166,33 +54,6 @@ class CrcTask {
return binaryString.toString();
}
boolean decode(String encodedString) {
String fcs = encodedString.substring(encodedString.indexOf("0x"), encodedString.length());
encodedString = encodedString.replace(fcs, "");
encodedString = toBinaryString(encodedString);
encodedString = encodedString + toBinaryStringFromHexValue(fcs);
encodedString = fillPoly(encodedString);
short[] encodedShortArray = convertBinaryStringToShortArray(encodedString);
encodedShortArray = swapPolynomialValues(encodedShortArray);
while (true) {
if (!shortArrayContains(encodedShortArray, 1)) {
return true;
}
if (encodedShortArray[0] == 0) {
encodedShortArray = Arrays.copyOfRange(encodedShortArray, 1, encodedShortArray.length);
} else {
short[] piece = Arrays.copyOfRange(encodedShortArray, 0, Math.min(polyGenerator.length, encodedShortArray.length));
if (piece.length < polyGenerator.length) {
return false;
}
short[] remainder = calcXOR(piece, polyGenerator);
remainder = removeUnecessaryZeros(remainder);
encodedShortArray = createMessageFromRemainderAndPartFromOldMessage(remainder, encodedShortArray);
}
}
}
private String toBinaryStringFromHexValue(String hexString) {
hexString = hexString.substring(2, hexString.length());
return String.valueOf(Integer.toBinaryString(Integer.parseInt(hexString, 16)));
@ -206,20 +67,31 @@ class CrcTask {
return stringBuilder.toString();
}
private boolean shortArrayContains(short[] encodedShortArray, int value) {
for (short item : encodedShortArray) {
if (item == value) {
return true;
public boolean decode(String messageString) {
Polynomial g = new Polynomial("[1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1]", 2);
Polynomial l = new Polynomial("[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]", 2);
String fcs = messageString.substring(messageString.indexOf("0x"), messageString.length());
messageString = messageString.replace(fcs, "");
messageString = toBinaryString(messageString);
String messageAsBinaryString = messageString + toBinaryStringFromHexValue(fcs);
Polynomial message = new Polynomial("[" + toPolynomialStringFromBinaryString(messageAsBinaryString) + "]", 2);
message.reverse();
for (int i = 0; i < 16; i++) {
message.append(0,0);
}
Polynomial tmp = new Polynomial(l);
for (int i = 0; i < messageAsBinaryString.length(); i++) {
tmp.append(0, 0);
}
return false;
Polynomial sum = message.add(tmp);
message = sum.moduloPolyDivide(g);
return message.haveOnlyZeros();
}
private String fillPoly(String encodedString) {
StringBuilder stringBuilder = new StringBuilder(encodedString);
while (stringBuilder.length() % 8 != 0) {
stringBuilder.insert(0, "0");
}
return stringBuilder.toString();
private String toPolynomialStringFromBinaryString(String msgBinString) {
msgBinString = msgBinString.replace("1", "1,");
msgBinString = msgBinString.replace("0", "0,");
msgBinString = msgBinString.substring(0, msgBinString.length() - 1);
return msgBinString;
}
}

View File

@ -7,13 +7,15 @@ public class Main {
// example "1" "b" -> this will encode string "b" and return FCS
// example "2" "bX" -> this will decode string "bX" and return true if it is valid or false if not
// X - FCS
CrcTask crcTask = new CrcTask(args[1]);
CrcTask crcTask = new CrcTask();
if (args[0].equals("1")) {
//create FCS
System.out.println(crcTask.encode());
System.out.println(args[1] + crcTask.generateFCSChars(crcTask.encode(args[1])));
} else if (args[0].equals("2")) {
// check fcs
if (args[1].length() >= 3) System.out.println(crcTask.decode(args[1]));
if (args[1].length() >= 3) {
System.out.println(crcTask.decode(args[1]));
}
}
}

View File

@ -0,0 +1,182 @@
package com.tylkowski.crc;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Polynomial {
private int[] polynomial;
private int modulo;
public Polynomial(String polyString, int modulo) {
this.polynomial = parsePolynomialString(polyString);
this.modulo = modulo;
}
public Polynomial(int[] polynomial, int modulo) {
this.polynomial = polynomial;
this.modulo = modulo;
}
public Polynomial(List<Integer> polynomial, int modulo) {
this.polynomial = polynomial.stream().mapToInt(i -> i).toArray();
this.modulo = modulo;
}
public Polynomial(Polynomial polynomial) {
this.polynomial = polynomial.getPolynomialArray();
this.modulo = polynomial.getModulo();
}
public void append(int index, int value) {
ArrayList<Integer> poly = asArrayList();
poly.add(index, value);
polynomial = poly.stream().mapToInt(i -> i).toArray();
}
private int[] parsePolynomialString(String poly) {
poly = poly.substring(1, poly.length() - 1);
return Arrays.stream(poly.split(",\\s*")).map(String::trim).mapToInt(Integer::parseInt).toArray();
}
public int[] getPolynomialArray() {
return polynomial;
}
public int getModulo() {
return modulo;
}
public Polynomial subtract(Polynomial polyTwo) {
Polynomial polyOne = new Polynomial(this);
ArrayList<Integer> result = new ArrayList<>();
for (int i = 0; i < polyOne.getSize(); ++i) {
if (i < polyTwo.getSize()) {
result.add(Math.floorMod(polyOne.coeffAt(i) - polyTwo.coeffAt(i), modulo));
} else {
result.add(polyOne.coeffAt(i));
}
}
return new Polynomial(result, modulo);
}
public int getSize() {
return polynomial.length;
}
public int coeffAt(int i) {
return polynomial[i];
}
public void set(int index, int value) {
polynomial[index] = value;
}
public List<Integer> asList() {
return Arrays.stream(polynomial).boxed().collect(Collectors.toList());
}
public ArrayList<Integer> asArrayList() {
ArrayList<Integer> result = new ArrayList<>();
for (int i = 0; i < polynomial.length; i++) {
result.add(polynomial[i]);
}
return result;
}
public Polynomial add(Polynomial polyTwo) {
int size = Math.max(polynomial.length, polyTwo.getSize());
int[] result = new int[size];
for (int i = 0; i < size; i++) {
int res = 0;
if (i >= polynomial.length) {
res = polyTwo.coeffAt(i);
}
if (i >= polyTwo.getSize()) {
res = polynomial[i];
}
if (i < polynomial.length && i < polyTwo.getSize()) {
res = polynomial[i] + polyTwo.coeffAt(i);
}
result[i] = res;
}
Polynomial resultPoly = new Polynomial(result, modulo);
resultPoly = resultPoly.moduloPoly(resultPoly);
return resultPoly;
}
public Polynomial multiplyByNumber(int a) {
ArrayList<Integer> result = new ArrayList<>();
for (int i = 0; i < polynomial.length; i++) {
result.add((polynomial[i] * a) % modulo);
}
return new Polynomial(result, modulo);
}
public boolean haveOnlyZeros() {
return !asArrayList().contains(1);
}
public Polynomial moduloPoly(Polynomial poly) {
for (int i = 0; i < poly.getSize(); i++) {
while (poly.coeffAt(i) < 0) {
poly.getPolynomialArray()[i] = poly.getPolynomialArray()[i] + modulo;
}
poly.getPolynomialArray()[i] = poly.getPolynomialArray()[i] % modulo;
}
return poly;
}
private int findZero(int a, int b, int modulo) {
for (int i = 0; i <= modulo; i++) {
if ((a + (-(b * i))) == 0) {
return i;
}
}
return -1;
}
public Polynomial moduloPolyDivide(Polynomial polyTwo) {
Polynomial polyOne = new Polynomial(this);
Polynomial quotient = new Polynomial("[0]", polyOne.getModulo());
Polynomial rem = new Polynomial(polyOne);
Polynomial tmpPoly;
int polyOneIterator = polyOne.getSize() - 1;
int polyTwoIterator = polyTwo.getSize() - 1;
for (int i = 0; i < polyOneIterator - polyTwoIterator; i++) {
quotient.append(0, 0);
}
int quotientIterator = quotient.getSize() - 1;
int tmpZero;
while (polyOneIterator >= polyTwoIterator) {
tmpZero = findZero(rem.coeffAt(polyOneIterator), polyTwo.coeffAt(polyTwoIterator), polyOne.getModulo());
quotient.set(quotientIterator--, tmpZero);
tmpPoly = polyTwo.multiplyByNumber(tmpZero);
while (tmpPoly.getSize() <= polyOneIterator) {
tmpPoly.append(0, 0);
}
rem = rem.subtract(tmpPoly);
polyOneIterator--;
}
return rem;
}
@Override
public String toString() {
return "Polynomial{" +
"polynomial=" + Arrays.toString(polynomial) +
", modulo=" + modulo +
'}';
}
public void reverse() {
int[] temp = Arrays.copyOf(getPolynomialArray(), getPolynomialArray().length);
for (int i = 0; i < temp.length; i++) {
polynomial[i] = temp[temp.length - i - 1];
}
}
}