Skip to content

Instantly share code, notes, and snippets.

@jhorstmann
Last active November 11, 2018 11:24
Show Gist options
  • Save jhorstmann/4c5a843534728889fcffc4da496aa065 to your computer and use it in GitHub Desktop.
Save jhorstmann/4c5a843534728889fcffc4da496aa065 to your computer and use it in GitHub Desktop.
// https://en.wikipedia.org/wiki/Double_dabble
public class DoubleDabble {
static int bcd(int value, int bits) {
int res = value << (16 - bits);
res <<= 3;
for (int i = 3; i < bits; i++) {
// find bcd digits > 4 and incremented them 3
// either bit 4 is set or bit 3 and at least on of bits 2 or 1 is set
// bit 1 in mask ist set if digit > 4
// to get the add operand or the mask with mask<<1
int mask = ((res & 0x88880000) >>> 3)
| (((res & 0x44440000) >>> 2)
& (((res & 0x22220000) >>> 1) | (res & 0x11110000)));
mask |= mask << 1;
res += mask;
res <<= 1;
}
return res >>> 16;
}
static String toString(int value, int bits, int digits) {
char[] chars = new char[digits];
getChars(value, bits, digits, chars, 0);
return new String(chars);
}
static void getChars(int value, int bits, int digits, char[] chars, int offset) {
int bcd = bcd(value, bits);
switch (digits) {
case 1:
chars[offset ] = (char) ('0' + (bcd & 0x0F));
break;
case 2:
chars[offset ] = (char) ('0' + ((bcd & 0xF0) >>> 4));
chars[offset+1] = (char) ('0' + ((bcd & 0x0F)));
break;
case 3:
chars[offset ] = (char) ('0' + ((bcd & 0xF00) >>> 8));
chars[offset+1] = (char) ('0' + ((bcd & 0x0F0) >>> 4));
chars[offset+2] = (char) ('0' + ((bcd & 0x00F)));
break;
case 4:
chars[offset ] = (char) ('0' + ((bcd & 0xF000) >>> 12));
chars[offset+1] = (char) ('0' + ((bcd & 0x0F00) >>> 8));
chars[offset+2] = (char) ('0' + ((bcd & 0x00F0) >>> 4));
chars[offset+3] = (char) ('0' + ((bcd & 0x000F)));
break;
}
}
}
package net.jhorstmann.packedtime;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class DoubleDabbleTest {
@Test
public void testBCD() {
Assertions.assertEquals("36", Integer.toHexString(DoubleDabble.bcd(36, 7)));
Assertions.assertEquals("55", Integer.toHexString(DoubleDabble.bcd(55, 7)));
Assertions.assertEquals("123", Integer.toHexString(DoubleDabble.bcd(123, 7)));
Assertions.assertEquals("243", Integer.toHexString(DoubleDabble.bcd(243, 8)));
Assertions.assertEquals("432", Integer.toHexString(DoubleDabble.bcd(432, 10)));
Assertions.assertEquals("543", Integer.toHexString(DoubleDabble.bcd(543, 10)));
Assertions.assertEquals("765", Integer.toHexString(DoubleDabble.bcd(765, 10)));
Assertions.assertEquals("876", Integer.toHexString(DoubleDabble.bcd(876, 10)));
Assertions.assertEquals("976", Integer.toHexString(DoubleDabble.bcd(976, 10)));
Assertions.assertEquals("9876", Integer.toHexString(DoubleDabble.bcd(9876, 15)));
Assertions.assertEquals("9876", Integer.toHexString(DoubleDabble.bcd(9876, 16)));
}
@Test
public void testToString() {
Assertions.assertEquals("36", DoubleDabble.toString(36, 7, 2));
Assertions.assertEquals("55", DoubleDabble.toString(55, 7, 2));
Assertions.assertEquals("123", DoubleDabble.toString(123, 7, 3));
Assertions.assertEquals("243", DoubleDabble.toString(243, 8, 3));
Assertions.assertEquals("432", DoubleDabble.toString(432, 10, 3));
Assertions.assertEquals("543", DoubleDabble.toString(543, 10, 3));
Assertions.assertEquals("765", DoubleDabble.toString(765, 10, 3));
Assertions.assertEquals("876", DoubleDabble.toString(876, 10, 3));
Assertions.assertEquals("976", DoubleDabble.toString(976, 10, 3));
Assertions.assertEquals("9876", DoubleDabble.toString(9876, 15, 4));
Assertions.assertEquals("9876", DoubleDabble.toString(9876, 16, 4));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment