Posts tagged ruby

The Obligatory Miller-Rabin Implementation

At some point in a programmer’s life - perhaps several points - they are obligated to re-implement a primality test.

The Miller-Rabin test is a highly efficient way to determine if a given number is composite or prime. Here is my current implementation, in pure ruby.



module Primal
  attr :primal_s, :primal_d

  def prime?
    val = self.abs
    return true if val == 2
    return false if val % 2 == 0 || val == 1
    @s,@d = Primal::calc_sd(val- 1)
    Primal::witnesses(val).each do |wit|
      0.upto(@s-1) do |r|
        return false if ModMath.pow(wit,@d,val) == 1 && 
          ModMath.pow(wit,2*r*@d,val) == -1
      end
    end
   true 
  end

  class <<self
    #Return the minimal list of effective witnesses for 'sufficiently small'
    #Integers, otherwise derive the full set required for deterministic result.
    def witnesses(n)
     if n < 341550071728321
       [2, 3, 5, 7, 11, 13, 17]
      else
        calculate_witnesses(n)
      end
    end

    def calculate_witnesses(n)
      #Use the full list of possible witnesses for deterministic result
      max_val = [n-1,(2*(Math.log(n))**2).floor].min
      (2..max_val).to_a
    end

    def calc_sd(n)
     v = n; s = 0
     while v > 1 && (v & 0x1 == 0)
       s += 1
       v = v >> 1 
     end
     return s,v
    end
  end
end

#Fast exponentiation to a given modulo base
#Bogarted from http://snippets.dzone.com/posts/show/4636
module ModMath
   def ModMath.pow(base, power, mod)
     result = 1
     while power > 0
       result = (result * base) % mod if power & 1 == 1
       base = (base * base) % mod
       power >>= 1;
     end
     result
   end
end

#Inject the .prime? method into Integer 
  class Integer
    include Primal
  end

In the clear light of day I realized I don’t need the attribute accessors, and my @s and @d variables should be local. I’ll update once I’m near Vim again.

Following