PrimeMillerRabin

Test primes using the Miller-Rabin Method. See http://en.wikipedia.org/wiki/Miller-Rabin_primality_test for more details. For large prime numbers this is significantly faster than Ruby's default method.

Benchmarks

The current standard Ruby Prime Generators are Generator23, EratosthenesSieve, and TrialDivision

The following code was used to compare Miller-Rabin with the existing Ruby Prime Generators:

  require 'prime_miller_rabin'
  require 'benchmark'

  primes = load_primes() # Load primes from an external source

  Prime::MillerRabin.speed_intercept

  generators = {
    MillerRabin: Prime::MillerRabin.new,
    Generator23: Prime::Generator23.new,
    Eratosthenes: Prime::EratosthenesGenerator.new,
    TrialDivision: Prime::TrialDivisionGenerator.new
  }

  padding = ''
  column_width = generators.keys.map(&:size).max
  puts(generators.keys.map { |name| '%-*s' % [column_width, name] }.join('') + '    Number Tested')

  time_limit = 120

  primes.each_with_index do |number|
    timings = generators.map { |name, generator| [name, Benchmark.measure { Prime.prime?(number, generator) }.total] }.to_h
    puts timings.values.map { |x| '%-*.6f' % [column_width, x] }.push(padding).push(number).join(' ')
    generators = generators.delete_if do |name, _|
      if timings[name] > time_limit
        puts "Removing #{name} as it is now exceeding #{time_limit  / 60} minutes to determine primality."
        padding += ' ' * (column_width + 1)
      end
    end
  end

The results (formatted for readability):

MillerRabin Generator23 Eratosthenes TrialDivision Number Tested
0.000 0.000 0.000 0.000 2
0.000 0.000 0.000 0.000 7
0.000 0.000 0.000 0.000 67
0.000 0.000 0.000 0.000 619
0.000 0.000 0.000 0.000 6197
0.000 0.000 0.000 0.000 61813
0.000 0.000 0.000 0.000 618041
0.000 0.000 0.000 0.000 6180341
0.000 0.000 0.000 0.000 61803419
0.000 0.000 0.015 0.016 618034003
0.000 0.015 0.016 0.141 6180339923
0.000 0.015 0.031 1.079 61803398903
0.015 0.063 0.047 6.500 618033988751
0.000 0.156 0.187 64.657 6180339887543
0.000 0.484 0.656 631.251 61803398875019

Removing TrialDivision as it is now exceeding 2 minutes to determine primality

MillerRabin Generator23 Eratosthenes Number Tested
0.000 1.578 1.905 618033988749911
0.000 4.828 5.938 6180339887498971
0.000 15.219 20.453 61803398874989489
0.000 51.344 78.500 618033988749894811
0.000 199.203 604.875 6180339887498948681

Removing Generator23 as it is now exceeding 2 minutes to determine primality

Removing Eratosthenes as it is now exceeding 2 minutes to determine primality

MillerRabin Number Tested
0.000 61803398874989486159
0.000 618033988749894877249
0.000 6180339887498948771861
0.000 61803398874989479329793
0.000 618033988749894843629693
0.000 6180339887498948973166649
0.000 61803398874989485436698673
0.016 618033988749894820007248007
0.000 6180339887498948474950385857
0.000 61803398874989473754387579003
0.000 618033988749894825504806010893
0.000 6180339887498947551360618332249
0.000 61803398874989482269005624377351
0.000 618033988749894786661259224809529
0.000 6180339887498948010727780323950599
0.000 61803398874989484718963821666894041
0.000 618033988749894884083126364088041501
0.015 6180339887498948102961500692498350149
0.000 61803398874989478668431765490160893959
0.000 618033988749894805573783586380189794451
0.000 6180339887498948055737835863801897943079
0.016 61803398874989485393081637096535678255353
0.000 618033988749894834588003257131289987252251
0.000 6180339887498947881652517839295296785350671
0.000 61803398874989486244165414105234617248252037
0.016 618033988749894783213491626788008578938568879
0.000 6180339887498948782872866439052136911913091139
0.000 61803398874989490364029864846980172112537321529
0.000 618033988749894863075479441166460873230870642701
0.016 6180339887498948306236240753237881949152685850683
0.000 61803398874989488254659266067206448022023187726371
0.000 618033988749894861777405226532753966098246560383039
0.000 6180339887498948285467053319098571435030700533743709
0.015 61803398874989477537758550051322222735078764216058197
0.000 618033988749894860448177230747838093194439500102631463
0.000 6180339887498948264199405386539917468569787569258103079
0.016 61803398874989493531029795335430005513685313509163794507
0.000 618033988749894848198012021594053408512953632558975811599
0.000 6180339887498947959306404625379054205386139310393785319457
0.015 61803398874989483774453770978282381091808569225505635565881
0.000 618033988749894815443792511252200669382367419606694849675361
0.016 6180339887498947619220040347787051296966435652506272353222859
0.000 61803398874989487610181945125549561435952112121023814594199579
0.015 618033988749894876101819451255495614359521121210238145941995523
0.000 6180339887498948212955080513466361817213398943496249088445251857
0.016 61803398874989482129550805134663618172133989434962490884452515863
0.000 618033988749894751143429459463296107944467923968039965359763095659
0.016 6180339887498948446795342486410828729802972178101532233394458460333
0.000 61803398874989478481642718356729934335736646975120073823244888571933
0.015 618033988749894856652155661655839578904883367421943720360845238075493
0.016 6180339887498948949645441833030610378635590461796733108293232926654757
3.984 61803398874989480301481173134972953636273741716112229370497596164931657
0.016 618033988749894753974954423641286068895632548351228417905324051774046223
0.016 6180339887498948520546690390581730038298422859710161695046278715245855121
0.015 61803398874989478928365168519136536547194805389435200848107342688424034467
0.016 618033988749894789283651685191365365471948053894352008481073426884240343509
0.015 6180339887498948294571027916661222540210003624234170715361482714540612255771
0.016 61803398874989487766524411943583052027986313265829514720223808493784628461601
0.000 618033988749894800532217995004297294265682700282490226136494383363790190149697
0.016 6180339887498948416698319280344483481399122642162528507048910242032867738649237
0.015 61803398874989489103496864767062961278898774093676800018696699321068267432312833
0.000 618033988749894759394604061974146240391453136348727601568097742524293606434406857
0.016 6180339887498947804570623956855835799750586730828140653471168226341158572966019139
0.016 61803398874989483100696239659303319497571196124462157841676261489768925936587112561
0.015 618033988749894911886802398044952578976757222303513599328195882519406702676701872319
0.016 6180339887498948040470157294423934003086968742249909047796181923571167782622608752829
0.016 61803398874989482130138159641880286889558652991755453590739062278308316616857143476423
0.015 618033988749894793694396209256547719156563080809452726102954734101536945518474539565289
0.016 6180339887498948378655728287161559587390005993824156217900521559920108985586295718806271
0.016 61803398874989483786557282871615595873900059938241562179005215599201089855862957188055087
0.015 618033988749894837865572828716155958739000599382415621790052155992010898558629571880550497
0.016 6180339887498948830968576870427947960714166184011296269736399160078562264717483249716166887
0.016 61803398874989484691182980038148372620548380318615842282676970799517996414125332249876365411
0.015 618033988749894890333863264375057010044603181444123867803013957610391478937847325466187268189
0.016 6180339887498947977001918745221006711878151744937975851870262250979402473717801191356835561549
0.031 61803398874989483475366043046328320673053037727392809823342131810292073999820700166788504093107
0.016 618033988749894819932273008086810192513444296161875893014863280900928542947636248655004447015003
0.015 6180339887498948673607127596915238380081197557204429497142489999473035735094626582962223475327741
0.016 61803398874989482941796095840775292161237938807358930435474042471020354906000153058324802711846941
0.015 618033988749894799063759517380736188495787093956106388067133564520523529500432628412868570787086393
0.016 6180339887498948233471206702023495749890609292500927210972190526722675451480877501491721358521925753
0.015 61803398874989482334712067020234957498906092925009272109721905267226754514808775014917213585219257561

Installation

Add this line to your application's Gemfile:

gem 'prime_miller_rabin'

And then execute:

$ bundle

Or install it yourself as:

$ gem install prime_miller_rabin

Usage

require 'prime_miller_rabin'

# You now have access to Prime::MillerRabin
Prime.prime?(large_number, Prime::MillerRabin.new)

# Even when using the generator, Ruby's method for #prime? is slower than having Miller Rabin determine it directly.
# Miller Rabin can intercept the Prime.prime? function and call Miller Rabin directly when its generator is used.
# To accomplish this use:
Prime::MillerRabin.speed_intercept

# To use the speed intercept and have Miller Rabin be the default prime generator in all cases use:
Prime::MillerRabin.make_default