Created
May 23, 2016 00:10
-
-
Save preetpalS/8f4705fc0ca80f902f3862befd9d7550 to your computer and use it in GitHub Desktop.
Calculations of how many primes can be encoded into a product for fixed-width integer types.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Contains utilities for working with Prime numbers. | |
class Prime | |
class << self | |
def prime?(n) | |
return false if n < 2 | |
return true if n < 4 | |
return false if n.even? | |
(3..(Math.sqrt n).ceil).each do |i| | |
return false if n % i == 0 | |
end | |
true | |
end | |
def primes | |
Enumerator.new do |yielder| | |
yielder.yield 2 | |
to_test = 3 | |
loop do | |
yielder.yield to_test if prime?(to_test) | |
to_test += 2 | |
end | |
end | |
end | |
end | |
end | |
module NativeTypes | |
UNSIGNED_INT8 = { bytes: 1, name: 'uint8_t', | |
range: { min: 0, | |
max: 255 } }.freeze | |
INT8 = { bytes: 1, name: 'int8_t', | |
range: { min: -128, | |
max: 127 } }.freeze | |
UNSIGNED_INT16 = { bytes: 2, name: 'uint16_t', | |
range: { min: 0, | |
max: 65_535 } }.freeze | |
INT16 = { bytes: 2, name: 'int16_t', | |
range: { min: -32_768, | |
max: 32_767 } }.freeze | |
UNSIGNED_INT32 = { bytes: 4, name: 'uint32_t', | |
range: { min: 0, | |
max: 4_294_967_295 } }.freeze | |
INT32 = { bytes: 4, name: 'int32_t', | |
range: { min: -2_147_483_648, | |
max: 2_147_483_647 } }.freeze | |
UNSIGNED_INT64 = { bytes: 8, name: 'uint64_t', | |
range: { min: 0, | |
max: 18_446_744_073_709_551_615 } }.freeze | |
INT64 = { bytes: 8, name: 'int64_t', | |
range: { min: -9_223_372_036_854_775_808, | |
max: 9_223_372_036_854_775_807 } }.freeze | |
end | |
table = [] | |
[NativeTypes::INT8, | |
NativeTypes::UNSIGNED_INT8, | |
NativeTypes::INT16, | |
NativeTypes::UNSIGNED_INT16, | |
NativeTypes::INT32, | |
NativeTypes::UNSIGNED_INT32, | |
NativeTypes::INT64, | |
NativeTypes::UNSIGNED_INT64].each do |native_integral_type| | |
=begin | |
puts <<INTRO | |
Type: #{native_integral_type[:name]} | |
Number of bytes: #{native_integral_type[:bytes]} | |
Range: | |
Min: #{native_integral_type[:range][:min]} | |
Max: #{native_integral_type[:range][:max]} | |
Calculations: | |
INTRO | |
=end | |
product = 1 | |
primes = Prime.primes | |
current_prime_index = 0 | |
current_prime = nil | |
largest_encodable_prime = nil | |
while product <= native_integral_type[:range][:max] | |
largest_encodable_prime = current_prime if current_prime_index > 0 | |
current_prime = primes.next | |
current_prime_index += 1 | |
product = current_prime * product | |
# puts " Current prime: #{current_prime}" | |
# puts " Product: #{product}" | |
end | |
table.push({ | |
largest_encodable_prime: largest_encodable_prime, | |
number_of_encodable_primes: (current_prime_index - 1), | |
bits: (native_integral_type[:bytes] * 8) | |
}.merge(native_integral_type)) | |
=begin | |
puts <<SUMMARY | |
#{native_integral_type[:name]} can encode #{current_prime_index - 1} primes. | |
The largest encodable prime is #{largest_encodable_prime}. | |
SUMMARY | |
=end | |
end | |
table_format = [ | |
{ header: 'Name', | |
func: ->(row) { row[:name] } }, | |
{ header: 'Min', | |
func: ->(row) { row[:range][:min] } }, | |
{ header: 'Max', | |
func: ->(row) { row[:range][:max] } }, | |
{ header: 'Bytes', | |
func: ->(row) { row[:bytes] } }, | |
{ header: 'Bits', | |
func: ->(row) { row[:bits] } }, | |
{ header: 'Number of Encodable Primes', | |
func: ->(row) { row[:number_of_encodable_primes] } }, | |
{ header: 'Largest Encodable Prime', | |
func: ->(row) { row[:largest_encodable_prime] } } | |
] | |
table_format.each_with_index do |tf, index| | |
max_column_length = table.map(&tf[:func]).map(&:to_s).map(&:length).max | |
tf[:length] = [max_column_length, tf[:header].length].max | |
print ' | ' if index > 0 | |
print tf[:header].ljust(tf[:length]) | |
end | |
print "\n" | |
table_format.each_with_index do |tf, index| | |
print '-+-' if index > 0 | |
print ''.ljust(tf[:length], '-') | |
end | |
table.each do |row| | |
print "\n" | |
table_format.each_with_index do |tf, index| | |
print ' | ' if index > 0 | |
print tf[:func].call(row).to_s.ljust(tf[:length]) | |
end | |
end | |
# Results of execution below (Ruby 2.3.0) | |
=begin | |
Name | Min | Max | Bytes | Bits | Number of Encodable Primes | Largest Encodable Prime | |
---------+----------------------+----------------------+-------+------+----------------------------+------------------------ | |
int8_t | -128 | 127 | 1 | 8 | 3 | 5 | |
uint8_t | 0 | 255 | 1 | 8 | 4 | 7 | |
int16_t | -32768 | 32767 | 2 | 16 | 6 | 13 | |
uint16_t | 0 | 65535 | 2 | 16 | 6 | 13 | |
int32_t | -2147483648 | 2147483647 | 4 | 32 | 9 | 23 | |
uint32_t | 0 | 4294967295 | 4 | 32 | 9 | 23 | |
int64_t | -9223372036854775808 | 9223372036854775807 | 8 | 64 | 15 | 47 | |
uint64_t | 0 | 18446744073709551615 | 8 | 64 | 15 | 47 | |
=end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment