[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