Improved random function generation.

Random function generation logic was broken since it was limiting the
number of unique monomials in the generated function to the total number
of terms. I fixed this by generating each row at a time and keeping
track of monomials and relevant contributions in a map, allowing me to
use the fromMonomialContributionMap static factory method.

I also started moving moving static factory methods to the
PolynomialFunctions class that are not PolynomialFunctionGF2 specific
to make that class slightly less painful to reason about.

Also added a BitVector static factory method to generate bitvectors with
desired hamming weights and its corresponding unit tests.

Finally, I made the And unit tests switchable, but haven't finished
implementing efficient and.  I suspect the unit tests won't run with
less than 20G of RAM as a result.  The final resulting functions still
how about 5 ms for a homomorphic xor evaluation, which is only
marginally worse than the previous 3ms.

Java 8 should make things better with better vectorization.
Additionally, it should be fairly straightforward to parallelize
evaluation.

Resolves #4.
Updated main to save public key to file
Merge branch 'develop' of https://github.com/kryptnostic/fhe-core into develop

* 'develop' of https://github.com/kryptnostic/fhe-core:
  Improved random function generation.