[CLN-list] Patch to convert cl_I to and from a byte stream

Igor Khavkine igor.kh at gmail.com
Sun Aug 13 14:21:17 CEST 2006


On 8/12/06, Richard B. Kreckel <kreckel at ginac.de> wrote:

> Could you, please, resend the patch? The attachment appears to have
> arrived empty.
-------------- next part --------------
diff -Npur cln-1.1.9/src/integer/conv/cl_I_from_BS.cc cln-1.1.9.new/src/integer/conv/cl_I_from_BS.cc
--- cln-1.1.9/src/integer/conv/cl_I_from_BS.cc	1969-12-31 19:00:00.000000000 -0500
+++ cln-1.1.9.new/src/integer/conv/cl_I_from_BS.cc	2006-08-11 11:59:52.911099664 -0400
@@ -0,0 +1,68 @@
+// BS_to_I().
+
+// General includes.
+#include "cl_sysdep.h"
+
+// Specification.
+#include "cl_I.h"
+
+// Implementation.
+
+#include "cl_DS.h"
+
+namespace cln {
+
+/* Assume BS is little endian and is signed. */
+const cl_I BS_to_I (const unsigned char *BS, size_t len)
+{
+  uintD *MSD, *LSD, *start;
+  uintD D;
+  size_t dlen;
+
+  /* Length in digits: ceil(len/sizeof(uintD)) */
+  dlen = (len+sizeof(uintD)-1)/sizeof(uintD);
+  start = new uintD[dlen];
+#if CL_DS_BIG_ENDIAN_P
+  MSD = start;
+  LSD = start+dlen;
+#else
+  LSD = start;
+  MSD = start+dlen;
+#endif
+  size_t i;
+  for (i = sizeof(uintD); i <= len; i += sizeof(uintD))
+  {
+    /* Least significant byte is always the last argument. */
+#if   intDsize == 8
+    D=D1(BS[i-1]);
+#elif intDsize == 16
+    D=D2(BS[i-1],BS[i-2]);
+#elif intDsize == 32
+    D=D4(BS[i-1],BS[i-2],BS[i-3],BS[i-4]);
+#elif intDsize == 64
+    D=D8(BS[i-1],BS[i-2],BS[i-3],BS[i-4],BS[i-5],BS[i-6],BS[i-7],BS[i-8]);
+#else
+#   error "Unsupported value of intDsize" intDsize
+#endif
+    lsprefnext(LSD) = D; // Store digit and move to next least significant.
+  }
+  /* Finish the last digit. */
+  if (i > len) {
+    D = 0;
+    size_t j;
+    for (j = i -= sizeof(uintD); i < len; i++)
+      D |= ((uintD) BS[i]) << (i-j)*8;
+    /* If sign bit is set, pad with 1s,
+     * as requred by 2's-complement notation. */
+    if (BS[len-1]&0x80)
+      for ( ; i<dlen*sizeof(uintD); i++)
+        D |= ((uintD) 0xff) << (i-j)*8;
+    mspref(MSD,0) = D;
+  }
+  cl_I cn = DS_to_I (MSD, dlen);
+  delete [] start;
+
+  return cn;
+}
+
+} // namespace cln
diff -Npur cln-1.1.9/src/integer/conv/cl_I_to_BS.cc cln-1.1.9.new/src/integer/conv/cl_I_to_BS.cc
--- cln-1.1.9/src/integer/conv/cl_I_to_BS.cc	1969-12-31 19:00:00.000000000 -0500
+++ cln-1.1.9.new/src/integer/conv/cl_I_to_BS.cc	2006-08-11 12:02:17.560109672 -0400
@@ -0,0 +1,89 @@
+// I_to_BS().
+
+// General includes.
+#include <string.h> // for memcpy()
+#include "cl_sysdep.h"
+
+// Specification.
+#include "cl_I.h"
+
+// Implementation.
+
+#include "cl_DS.h"
+
+namespace cln {
+
+/* Size of bytestream necessary to store the integer X. */
+size_t I_BS_size (const cl_I& X)
+{
+    // Number of internal digits times the size of a digit.
+    if (fixnump(X))
+        return FN_maxlength * sizeof (uintD);
+    else
+        return TheBignum(X)->length * sizeof (uintD);
+}
+
+/* Copy an individual digit to a byte stream
+ * in little endian order with the Least Significant Byte placed at LSB. */
+static inline void D_to_BS_little_endian (uintD D, uintB *LSB)
+{
+#if CL_CPU_BIG_ENDIAN_P
+    for (int i=0; i<sizeof(uintD); i++, D>>=8)
+        *(LSB++) = (uintB) (D & 0xff);
+#else
+    memcpy (LSB, &D, sizeof(D));
+#endif
+}
+
+/* Copy an individual digit to a byte stream
+ * in big endian order with the Least Significant Byte placed at LSB. */
+static inline void D_to_BS_big_endian (uintD D, uintB *LSB)
+{
+#if CL_CPU_BIG_ENDIAN_P
+    memcpy (LSB-sizeof(uintD)+1, &D, sizeof(D));
+#else
+    for (size_t i=0; i<sizeof(uintD); i++, D>>=8)
+        *(LSB--) = (uintB) (D & 0xff);
+#endif
+}
+
+/* Convert the integer X to a byte stream stored at location BS in
+ * little endian (little_endian != 0) or big endian (little_endian == 0)
+ * order. The resulting integer is stored in 2's complement notation.
+ * Note: the space available after BS must be at least as large
+ * as I_BS_size(X). */
+void I_to_BS (const cl_I& X, int little_endian, unsigned char *BS)
+{
+    size_t len;
+    const uintD *MSD, *LSD;
+    uintB *MSB, *LSB;
+
+    /* Get Digit Sequence representation. */
+    I_to_NDS_nocopy (X, MSD=, len=, LSD=, cl_false, );
+
+    /* Deal with endian issues. */
+#if CL_DS_BIG_ENDIAN_P
+    const int nextD = -1;
+#else
+    const int nextD = 1;
+#endif
+    int nextB;
+    if (little_endian) {
+        LSB = BS;
+        MSB = BS+len-1;
+        nextB = sizeof (uintD);
+    } else {
+        LSB = BS+len-1;
+        MSB = BS;
+        nextB = -(int) sizeof (uintD);
+    }
+
+    /* Store each digit in the correct endian order. */
+    for (size_t i=0; i<len; i++, LSD+=nextD, LSB+=nextB)
+        if (little_endian)
+            D_to_BS_little_endian (*LSD, LSB);
+        else
+            D_to_BS_big_endian (*LSD, LSB);
+}
+
+}  // namespace cln


More information about the CLN-list mailing list