/* This code is part of the tng compression routines. * * Written by Daniel Spangberg * Copyright (c) 2010, 2013, The GROMACS development team. * * * This program is free software; you can redistribute it and/or * modify it under the terms of the Revised BSD License. */ #include #include #include "compression/tng_compress.h" /* 64 bit integers are not required in this part of the program. But they improve the running speed if present. If 64 bit integers are available define the symbol HAVE64BIT. It should get automatically defined by the defines in my64bit.h */ #include "compression/my64bit.h" #include "compression/widemuldiv.h" #ifndef TRAJNG_X86_GCC_INLINE_MULDIV #if defined(__GNUC__) && defined(__i386__) #define TRAJNG_X86_GCC_INLINE_MULDIV #endif /* gcc & i386 */ #if defined(__GNUC__) && defined(__x86_64__) #define TRAJNG_X86_GCC_INLINE_MULDIV #endif /* gcc & x86_64 */ #endif /* TRAJNG X86 GCC INLINE MULDIV */ /* 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) { #if defined(TRAJNG_X86_GCC_INLINE_MULDIV) __asm__ __volatile__ ("mull %%edx\n\t" : "=a" (i1), "=d" (i2) : "a" (i1),"d" (i2) : "cc"); *ohi=i2; *olo=i1; #else /* TRAJNG X86 GCC INLINE MULDIV */ #ifdef HAVE64BIT my_uint64_t res= ((my_uint64_t)i1) * ((my_uint64_t)i2); *olo=res & 0xFFFFFFFFU; *ohi=(res>>32) & 0xFFFFFFFFU; #else /* HAVE64BIT */ unsigned int bits=16; unsigned int L_m=(1<>bits; b_L=i2 & L_m; b_U=i2>>bits; /* Do a*a=>2a multiply where a is half number of bits in an int */ x=a_L*b_L; x_LL=x & L_m; x_LU=x>>bits; x=a_U*b_L; x_LU+=x & L_m; x_UL=x>>bits; x=a_L*b_U; x_LU+=x & L_m; x_UL+=x>>bits; x=a_U*b_U; x_UL+=x & L_m; x_UU=x>>bits; /* Combine results */ x_UL+=x_LU>>bits; x_LU&=L_m; x_UU+=x_UL>>bits; x_UL&=L_m; x_U=(x_UU<>(bits2-hibit); s_L=(i<lo) { unsigned int t; hi--; /* Borrow */ t=allbits-s_L; lo+=t+1; } else lo-=s_L; /* Set bit. */ res|=rmask; } rmask>>=1; s_L>>=1; if (s_U & 1U) s_L|=hibit_mask; s_U>>=1; } *remainder=lo; *result=res; #endif /* HAVE64BIT */ #endif /* TRAJNG X86 GCC INLINE MULDIV */ } /* 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) { /* 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 */ unsigned int carry=0; if ((((unsigned int)-1)&0xFFFFFFFFU) -v164 mul */ largeint_add_gen(lo,largeint_out,n,i); if (i+1