#ifndef _LFSR_H
#define _LFSR_H

static __always_inline u32 lfsr_taps(int bits)
{
#define _IF_BITS_EQ(x) \
       if ((x) == bits)

       /*
        * Feedback terms copied from
        * http://users.ece.cmu.edu/~koopman/lfsr/index.html
        */
       _IF_BITS_EQ(4)  return 0x0009;
       _IF_BITS_EQ(5)  return 0x0012;
       _IF_BITS_EQ(6)  return 0x0021;
       _IF_BITS_EQ(7)  return 0x0041;
       _IF_BITS_EQ(8)  return 0x008E;
       _IF_BITS_EQ(9)  return 0x0108;
       _IF_BITS_EQ(10) return 0x0204;
       _IF_BITS_EQ(11) return 0x0402;
       _IF_BITS_EQ(12) return 0x0829;
       _IF_BITS_EQ(13) return 0x100D;
       _IF_BITS_EQ(14) return 0x2015;
       _IF_BITS_EQ(15) return 0x4122;
       _IF_BITS_EQ(16) return 0x8112;
       _IF_BITS_EQ(17) return 0x102C9;
       _IF_BITS_EQ(18) return 0x20195;
       _IF_BITS_EQ(19) return 0x403FE;
       _IF_BITS_EQ(20) return 0x80637;
       _IF_BITS_EQ(21) return 0x100478;
       _IF_BITS_EQ(22) return 0x20069E;
       _IF_BITS_EQ(23) return 0x4004B2;
       _IF_BITS_EQ(24) return 0x800B87;
       _IF_BITS_EQ(25) return 0x10004F3;
       _IF_BITS_EQ(26) return 0x200072D;
       _IF_BITS_EQ(27) return 0x40006AE;
       _IF_BITS_EQ(28) return 0x80009E3;
       _IF_BITS_EQ(29) return 0x10000583;
       _IF_BITS_EQ(30) return 0x20000C92;
#undef _IF_BITS_EQ

       /* Unreachable */
       return 0;
}

/*
 * Please note that LFSR doesn't work with a start state of 0.
 */
static inline u32 lfsr(u32 val, u32 taps)
{
       u32 bit = val & 1;

       val >>= 1;
       if (bit)
               val ^= taps;
       return val;
}

#endif /* _LFSR_H_ */
