[Gtdb-commits] r48 - pkg/gt.db/src

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Mon Mar 15 16:54:25 CET 2010


Author: dahinds
Date: 2010-03-15 16:54:25 +0100 (Mon, 15 Mar 2010)
New Revision: 48

Modified:
   pkg/gt.db/src/encode.c
Log:
- Added C code for packing, unpacking 1/2/4-bit vectors



Modified: pkg/gt.db/src/encode.c
===================================================================
--- pkg/gt.db/src/encode.c	2010-03-12 06:38:07 UTC (rev 47)
+++ pkg/gt.db/src/encode.c	2010-03-15 15:54:25 UTC (rev 48)
@@ -34,6 +34,8 @@
 #define _(String) (String)
 #endif
 
+#define isRaw(x) (TYPEOF(x) == RAWSXP)
+
 /*---------------------------------------------------------------------*/
 
 /*
@@ -88,3 +90,86 @@
 	UNPROTECT(1);
 	return ans;
 }
+
+/*---------------------------------------------------------------------*/
+
+/*
+  Unpack a raw vector of packed 1/2/4-bit quantities into bytes
+*/
+
+SEXP do_unpack_bits(SEXP sr, SEXP sb)
+{
+	SEXP ans;
+	const unsigned char *src;
+	unsigned char *out, mask;
+	int i, j, nb, len, bits;
+
+	if (!isRaw(sr))
+		error(_("first argument should be a raw vector"));
+
+	bits = asInteger(sb);
+	if ((bits != 1) && (bits != 2) && (bits != 4))
+		error(_("invalid 'bits' (must be 1, 2, or 4)"));
+	nb = 8/bits;
+	mask = (1<<bits)-1;
+
+	len = LENGTH(sr);
+	PROTECT(ans = allocVector(RAWSXP, len*nb));
+	src = RAW(sr);
+	out = RAW(ans);
+
+	for (i = 0; i < len; i++, src++) {
+		unsigned char s = *src;
+		for (j = 0; j < nb; j++, out++) {
+			*out = s & mask;
+			s >>= bits;
+		}
+	}
+	UNPROTECT(1);
+	return ans;
+}
+
+/*
+  Unpack a raw vector of packed 1/2/4-bit quantities into bytes
+*/
+
+SEXP do_pack_bits(SEXP sr, SEXP sb)
+{
+	SEXP ans;
+	const unsigned char *src;
+	unsigned char *out, mask;
+	int i, j, nb, len, bits, rem;
+
+	if (!isRaw(sr))
+		error(_("first argument should be a raw vector"));
+
+	bits = asInteger(sb);
+	if ((bits != 1) && (bits != 2) && (bits != 4))
+		error(_("invalid 'bits' (must be 1, 2, or 4)"));
+	nb = 8/bits;
+	mask = (1<<bits)-1;
+
+	len = LENGTH(sr) / nb;
+	rem = LENGTH(sr) % nb;
+	PROTECT(ans = allocVector(RAWSXP, len + (rem > 0)));
+	src = RAW(sr);
+	out = RAW(ans);
+
+	for (i = 0; i < len; i++, out++) {
+		unsigned char x = 0;
+		for (j = 0; j < 8; j += nb, src++) {
+			x |= (*src & mask) << j;
+		}
+		*out = x;
+	}
+
+	if (rem) {
+		*out = 0;
+		for (i = 0; i < rem; i++, src++) {
+			*out |= (*src & mask) << (i*nb);
+		}
+	}
+
+	UNPROTECT(1);
+	return ans;
+}



More information about the Gtdb-commits mailing list