[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