summaryrefslogtreecommitdiff
path: root/src/compression/widemuldiv.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/compression/widemuldiv.c')
-rw-r--r--src/compression/widemuldiv.c49
1 files changed, 30 insertions, 19 deletions
diff --git a/src/compression/widemuldiv.c b/src/compression/widemuldiv.c
index 7d03c57..63056f9 100644
--- a/src/compression/widemuldiv.c
+++ b/src/compression/widemuldiv.c
@@ -1,7 +1,7 @@
/* This code is part of the tng compression routines.
*
- * Written by Daniel Spangberg
- * Copyright (c) 2010, 2013, The GROMACS development team.
+ * Written by Daniel Spangberg and Magnus Lundborg
+ * Copyright (c) 2010, 2013-2014 The GROMACS development team.
*
*
* This program is free software; you can redistribute it and/or
@@ -11,6 +11,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "../../include/compression/tng_compress.h"
@@ -31,8 +32,14 @@
#endif /* gcc & x86_64 */
#endif /* TRAJNG X86 GCC INLINE MULDIV */
+#ifdef USE_WINDOWS
+#define TNG_INLINE __inline
+#else
+#define TNG_INLINE inline
+#endif
+
/* Multiply two 32 bit unsigned integers returning a 64 bit unsigned value (in two integers) */
-void Ptngc_widemul(unsigned int i1, unsigned int i2, unsigned int *ohi, unsigned int *olo)
+TNG_INLINE void Ptngc_widemul(unsigned int i1, unsigned int i2, unsigned int *ohi, unsigned int *olo)
{
#if defined(TRAJNG_X86_GCC_INLINE_MULDIV)
__asm__ __volatile__ ("mull %%edx\n\t"
@@ -99,7 +106,7 @@ void Ptngc_widemul(unsigned int i1, unsigned int i2, unsigned int *ohi, unsigned
/* Divide a 64 bit unsigned value in hi:lo with the 32 bit value i and
return the result in result and the remainder in remainder */
-void Ptngc_widediv(unsigned int hi, unsigned int lo, unsigned int i, unsigned int *result, unsigned int *remainder)
+TNG_INLINE void Ptngc_widediv(unsigned int hi, unsigned int lo, unsigned int i, unsigned int *result, unsigned int *remainder)
{
#if defined(TRAJNG_X86_GCC_INLINE_MULDIV)
__asm__ __volatile__ ("divl %%ecx\n\t"
@@ -163,7 +170,7 @@ void Ptngc_widediv(unsigned int hi, unsigned int lo, unsigned int i, unsigned in
/* Add a unsigned int to a largeint. j determines which value in the
largeint to add v1 to. */
-static void largeint_add_gen(unsigned int v1, unsigned int *largeint, int n, int j)
+TNG_INLINE static void largeint_add_gen(const unsigned int v1, unsigned int *largeint, const int n, int j)
{
/* Add with carry. unsigned ints in C wrap modulo 2**bits when "overflowed". */
unsigned int v2=(v1+largeint[j])&0xFFFFFFFFU; /* Add and cap at 32 bits */
@@ -184,46 +191,50 @@ static void largeint_add_gen(unsigned int v1, unsigned int *largeint, int n, int
}
/* Add a unsigned int to a largeint. */
-void Ptngc_largeint_add(unsigned int v1, unsigned int *largeint, int n)
+void Ptngc_largeint_add(const unsigned int v1, unsigned int *largeint, const int n)
{
largeint_add_gen(v1,largeint,n,0);
}
/* Multiply v1 with largeint_in and return result in largeint_out */
-void Ptngc_largeint_mul(unsigned int v1, unsigned int *largeint_in, unsigned int *largeint_out, int n)
+TNG_INLINE void Ptngc_largeint_mul(const unsigned int v1, unsigned int *largeint_in, unsigned int *largeint_out, const int n)
{
int i;
- for (i=0; i<n; i++)
- largeint_out[i]=0U;
- for (i=0; i<n; i++)
+ unsigned int lo,hi;
+
+ memset(largeint_out, 0U, sizeof(unsigned int) * n);
+
+ for (i=0; i<n-1; i++)
{
if (largeint_in[i]!=0U)
{
- unsigned int lo,hi;
Ptngc_widemul(v1,largeint_in[i],&hi,&lo); /* 32x32->64 mul */
largeint_add_gen(lo,largeint_out,n,i);
- if (i+1<n)
- largeint_add_gen(hi,largeint_out,n,i+1);
+ largeint_add_gen(hi,largeint_out,n,i+1);
}
}
+ if (largeint_in[i]!=0U)
+ {
+ Ptngc_widemul(v1,largeint_in[i],&hi,&lo); /* 32x32->64 mul */
+ largeint_add_gen(lo,largeint_out,n,i);
+ }
}
/* Return the remainder from dividing largeint_in with v1. Result of the division is returned in largeint_out */
-unsigned int Ptngc_largeint_div(unsigned int v1, unsigned int *largeint_in, unsigned int *largeint_out, int n)
+TNG_INLINE unsigned int Ptngc_largeint_div(const unsigned int v1, unsigned int *largeint_in, unsigned int *largeint_out, const int n)
{
unsigned int result,remainder=0;
int i;
- unsigned int hi, lo;
+ unsigned int hi;
/* Boot */
hi=0U;
i=n;
while (i)
{
- lo=largeint_in[i-1];
- Ptngc_widediv(hi,lo,v1,&result,&remainder);
- largeint_out[i-1]=result;
- hi=remainder;
i--;
+ Ptngc_widediv(hi,largeint_in[i],v1,&result,&remainder);
+ largeint_out[i]=result;
+ hi=remainder;
}
return remainder;
}
contact: Jan Huwald // Impressum