finitefield 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.txt CHANGED
@@ -8,4 +8,9 @@ supported.
8
8
  The initial release of this library is limited in scope to only supporting
9
9
  fields of the form 2^n.
10
10
 
11
-
11
+ Examples illustrating how to use the field are given in the examples directory.
12
+ Currently the following examples are provided:
13
+ * logTables.rb:
14
+ - log and antilog table generation given a field polynomial and generator.
15
+ * raid6.rb:
16
+ - RAID6 Q block generation using finite fields.
@@ -0,0 +1,16 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+
3
+ # = exampleUtils.rb - Utility methods used by the other examples.
4
+ #
5
+ # Copyright (C) 2008 Stephen Doyle
6
+ #
7
+
8
+ # Utility method to print a nicely formatted 16xn table of hex values
9
+ def printTable(table)
10
+ (0...table.length).each do |i|
11
+ printf("%02x ", table[i])
12
+ if i!=0 and i%16==15
13
+ puts ''
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,88 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+
3
+ # = logTables.rb - Generate the anti-log and log tables for a finite field.
4
+ #
5
+ # Copyright (C) 2008 Stephen Doyle
6
+ #
7
+ # This example illustrates using the finitefield library to generate the
8
+ # anti-log and log tables for a finite field for a given field polynomial
9
+ # and generator.
10
+ #
11
+ # The anti-log table for a finite field is constructed using a generator
12
+ # whose successive powers g^n for the range n[0, 255] produce all the
13
+ # in the field without repeating any element.
14
+ #
15
+ # If the anti-log and log tables are available for a finite field,
16
+ # multiplication can be performed very quickly using these tables, e.g.
17
+ # mult(a, b) = anti_log( [log(a) + log(b)] % 0xFF )
18
+ # where + is normal addition, i.e. not addition within the finite field.
19
+ #
20
+
21
+ require 'finitefield'
22
+ require 'exampleUtils'
23
+
24
+ # Compute the inverse or anti log table for a given field polynomial and generator.
25
+ # Note that the last value of the ilogTable is invalid and present in this example
26
+ # as a placeholder to produce a nicely dimensioned array.
27
+ def getILogTable(poly, generator)
28
+ field = FiniteField.new(8, poly)
29
+ ilogTable = [1]
30
+
31
+ 1.upto(0xFF) do |i|
32
+ ilogTable[i] = field.multiply(ilogTable[i-1], generator)
33
+ end
34
+ return ilogTable
35
+ end
36
+
37
+ # Compute the log log table for a given field polynomial and generator.
38
+ def getLogTable(poly, generator)
39
+ # The log table is most easily generated from the inverse log table.
40
+ # Note that the last element in the inverse log table is invalid and so
41
+ # should be discarded to avoid introducing errors into the log table
42
+ # generation.
43
+ ilogTable = getILogTable(poly, generator)[0...-1]
44
+ tmp = {}
45
+ ilogTable.each_with_index { |value, index| tmp[value] = index }
46
+ logTable = [0] + tmp.sort.collect { |x| x[1]}
47
+ return logTable
48
+ end
49
+
50
+
51
+ # Generate and print the anti-log and log tables for two well known fields ...
52
+ # ... the 0x11D field is the default polynomial used for the GF(2^8)
53
+ # computations used in RAID 6 for the generation of the Q parity block.
54
+ puts "Inverse log table for polynomial 0x11D: "
55
+ ilogTable = getILogTable(0x11D, 2)
56
+ printTable(ilogTable)
57
+ puts ''
58
+
59
+ puts "Log table for polynomial 0x11D: "
60
+ logTable = getLogTable(0x11D, 2)
61
+ printTable(logTable)
62
+ puts ''
63
+
64
+ # ... the 0x11B polynomial is the polynomial used in AES computations.
65
+ # See: http://www.cs.utsa.edu/~wagner/laws/FFM.html for further details.
66
+ puts "Inverse log table for polynomial 0x11b:"
67
+ ilogTable = getILogTable(0x11b, 3)
68
+ printTable(ilogTable)
69
+ puts ''
70
+
71
+ puts "Log table for polynomial 0x11b: "
72
+ logTable = getLogTable(0x11b, 3)
73
+ printTable(logTable)
74
+ puts ''
75
+
76
+ # Demonstrate multiplication using the tables.
77
+ a = 0x12
78
+ b = 0x34
79
+
80
+ field = FiniteField.new(8, 0x11D)
81
+ r1 = field.multiply(a, b)
82
+
83
+ ilogTable = getILogTable(0x11D, 2)
84
+ logTable = getLogTable(0x11D, 2)
85
+ r2 = ilogTable[ (logTable[a] + logTable[b]) % 0xFF ]
86
+
87
+ puts "Result using FiniteField.multiply(): #{r1}"
88
+ puts "Result using log tables: #{r2}"
data/examples/raid6.rb ADDED
@@ -0,0 +1,82 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+
3
+ # = raid6.rb - Generate the Q parity block for a RAID 6 array.
4
+ #
5
+ # Copyright (C) 2008 Stephen Doyle
6
+ #
7
+ # This example illustrates using the finitefield library in the context
8
+ # of RAID 6 to generate the Q parity block.
9
+ #
10
+ # == Background
11
+ # RAID 6 provides protection against double disk failures in an array of
12
+ # disks by using two disks in the array to hold parity information. The
13
+ # first parity block is known as the P block and generated by taking an
14
+ # XOR of the data blocks in the disk array (D0 + D1 + ... Dn). This is
15
+ # equivalent to addition over a finite field of the form F(2^8).
16
+ #
17
+ # The second parity block, aka the Q block, in a RAID 6 array is generated
18
+ # by multiplying each byte of the data blocks with a coefficient which is
19
+ # slected based upon the position of that disk in the array. The
20
+ # multiplication here is multiplication over a finite field of the form
21
+ # F(2^8) and the coefficients are taken from the anti-log table from the
22
+ # same field. The default RAID 6 polynimial is 0x11D.
23
+ #
24
+ # == What's covered in the example?
25
+ # This example illustrates the computation of both the P and Q blocks for
26
+ # a sample RAID 6 array using a stripe size of 512 bytes.
27
+ #
28
+
29
+ require 'finitefield'
30
+ require 'exampleUtils'
31
+
32
+ class Raid6
33
+
34
+ # Create a field of GF(2^n) using the specified generator polynomial
35
+ def initialize(polynomial)
36
+ @field = FiniteField.new(8, polynomial)
37
+ end
38
+
39
+ def getPBlock(dataBlocks)
40
+ pBlock = [0] * dataBlocks[0].length
41
+ dataBlocks.each do |blk|
42
+ (0...blk.length).each { |byteIdx| pBlock[byteIdx] ^= blk[byteIdx] }
43
+ end
44
+ return pBlock
45
+ end
46
+
47
+ def getQBlock(dataBlocks, coefficients)
48
+ qBlock = [0] * dataBlocks[0].length
49
+ dataBlocks.each_with_index do |blk, blkIdx|
50
+ (0...blk.length).each do |byteIdx|
51
+ qBlock[byteIdx] ^= @field.multiply(blk[byteIdx], coefficients[blkIdx])
52
+ end
53
+ end
54
+ return qBlock
55
+ end
56
+ end
57
+
58
+ # See logTables.rb for futher details.
59
+ def getILogTable(poly, generator)
60
+ field = FiniteField.new(8, poly)
61
+ ilogTable = [1]
62
+
63
+ 1.upto(0xFF) do |i|
64
+ ilogTable[i] = field.multiply(ilogTable[i-1], generator)
65
+ end
66
+ return ilogTable
67
+ end
68
+
69
+ # Sample data
70
+ data = []
71
+ data[0] = [1]*512
72
+ data[1] = [2]*512
73
+ data[2] = [4]*512
74
+ data[3] = [5]*512
75
+ data[4] = [6]*512
76
+ data[5] = [9]*512
77
+
78
+ # Generate the blocks
79
+ raid = Raid6.new(0x11d)
80
+ coefficients = getILogTable(0x11d, 2)
81
+ pBlk = raid.getPBlock(data)
82
+ qBlk = raid.getQBlock(data, coefficients)
data/lib/finitefield.rb CHANGED
@@ -1,9 +1,38 @@
1
-
2
- # Finite fields of characteristic 2
1
+ # = finitefield.rb - Finite Field Arithmetic
2
+ #
3
+ # Copyright (C) 2008 Stephen Doyle
4
+ #
5
+ # == Features
6
+ # finitefield.rb currently supports arithmetic in finite fields of characteristic 2.
7
+ #
8
+ # The following operations are supported:
9
+ # * Addition
10
+ # * Subtraction
11
+ # * Multiplication
12
+ # * Division
13
+ # * Inverse
14
+ # * Reduction
15
+ # * Binary multiplication
16
+ # * Binary division
17
+ #
18
+ # == Example
19
+ #
20
+ # # Create a field
21
+ # field = FiniteField.new(8, 0x169) # <== F(2^8) with polynomial: 0x169
22
+ # # Addition
23
+ # result = field.add(7, 8)
24
+ # # Subtraction
25
+ # result = field.subtract(8, 5)
26
+ # # Multiplication
27
+ # result = field.multiply(9, 87)
28
+ # # Division
29
+ # result = field.divide(87, 9) # <== result = 87/9
30
+ # # Inverse
31
+ # result = field.inverse(31)
32
+ #
3
33
 
4
34
  class FiniteField
5
35
  attr_reader :polynomial
6
- attr_reader :p
7
36
 
8
37
  # Create a field of GF(2^n) using the specified generator polynomial
9
38
  def initialize(n, polynomial)
@@ -50,7 +79,7 @@ class FiniteField
50
79
  return result
51
80
  end
52
81
 
53
- # Reduce the input value by modulo with the generator polynomial
82
+ # Reduce the input value by modulo with the generator polynomial, i.e. result = a % polynomial.
54
83
  def reduce(a)
55
84
  result = 0
56
85
  i = degree(a)
@@ -80,28 +109,27 @@ class FiniteField
80
109
  auxillary[2] = 1
81
110
  i = 2
82
111
 
83
- # puts "#{remainder[i].to_s(base=16)} #{quotient[i].to_s(base=16)} #{auxillary[i].to_s(base=16)}"
84
-
85
112
  while(remainder[i] > 1)
86
113
  i += 1
87
114
  result = binary_div(remainder[i-2], remainder[i-1])
88
115
  remainder[i] = result[1]
89
116
  quotient[i] = result[0]
90
117
  auxillary[i] = binary_mul(quotient[i], auxillary[i-1]) ^ auxillary[i-2]
91
- # puts "#{remainder[i].to_s(base=16)} #{quotient[i].to_s(base=16)} #{auxillary[i].to_s(base=16)}"
92
118
  end
93
119
 
94
120
  return auxillary[i]
95
121
  end
96
122
 
97
- # Division of two field elements (rhs/lhs). This is the same as
98
- # rhs * lhs^-1 i.e. multiply(rhs, inverse(lhs))
123
+ # Division of two field elements (lhs/rhs). This is the same as
124
+ # lhs * rhs^-1 i.e. multiply(lhs, inverse(rhs))
99
125
  def divide(lhs, rhs)
100
126
  multiply(lhs, inverse(rhs))
101
127
  end
102
128
 
103
129
  # Find the degree of the polynomial representing the input field
104
130
  # element v. This takes O(degree(v)) operations.
131
+ #
132
+ # Example: degree(0x141) = 8 ==> 0x141 = x^8 + x^6 + 1
105
133
  def degree(v)
106
134
  if v != 0
107
135
  result = -1
@@ -114,7 +142,7 @@ class FiniteField
114
142
  return 0
115
143
  end
116
144
 
117
- # Binary multiplication. Or more explicitly - multiplication over a binary field
145
+ # Binary multiplication. Or more explicitly - multiplication over a binary field.
118
146
  def binary_mul(lhs, rhs)
119
147
  result = 0
120
148
  a = [degree(lhs), degree(rhs)].max
@@ -127,7 +155,7 @@ class FiniteField
127
155
  return result
128
156
  end
129
157
 
130
- # Binary division. Or more explicitly - division over a binary field
158
+ # Binary division. Or more explicitly - division over a binary field.
131
159
  def binary_div(lhs, rhs)
132
160
  q = 0
133
161
  r = lhs
@@ -145,3 +173,4 @@ class FiniteField
145
173
  end
146
174
 
147
175
  end
176
+
data/test/tc_basic.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
2
 
3
+ # Copyright (C) 2008 Stephen Doyle
4
+
3
5
  require 'test/unit'
4
6
  require 'finitefield'
5
7
 
data/test/tc_gf2.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
2
 
3
+ # Copyright (C) 2008 Stephen Doyle
4
+
3
5
  require 'test/unit'
4
6
  require 'finitefield'
5
7
 
@@ -1,5 +1,7 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
2
 
3
+ # Copyright (C) 2008 Stephen Doyle
4
+
3
5
  require 'test/unit'
4
6
  require 'tc_basic'
5
7
  require 'tc_gf2'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: finitefield
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Doyle
@@ -9,12 +9,12 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-10-24 00:00:00 +01:00
12
+ date: 2008-12-22 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
16
16
  description: Finite Field implementation in Ruby.
17
- email: stephendoyle75@gmail.com
17
+ email:
18
18
  executables: []
19
19
 
20
20
  extensions: []
@@ -28,13 +28,18 @@ files:
28
28
  - test/ts_finitefield.rb
29
29
  - test/tc_basic.rb
30
30
  - test/tc_gf2.rb
31
- has_rdoc: false
31
+ - examples/exampleUtils.rb
32
+ - examples/logTables.rb
33
+ - examples/raid6.rb
34
+ has_rdoc: true
32
35
  homepage: http://finitefield.rubyforge.org/
33
36
  post_install_message:
34
- rdoc_options: []
35
-
37
+ rdoc_options:
38
+ - --title
39
+ - FiniteField Documentation
36
40
  require_paths:
37
41
  - lib
42
+ - lib
38
43
  required_ruby_version: !ruby/object:Gem::Requirement
39
44
  requirements:
40
45
  - - ">="
@@ -49,10 +54,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
49
54
  version:
50
55
  requirements: []
51
56
 
52
- rubyforge_project:
57
+ rubyforge_project: finitefield
53
58
  rubygems_version: 1.0.1
54
59
  signing_key:
55
60
  specification_version: 2
56
61
  summary: Finite Field implementation in Ruby.
57
- test_files: []
58
-
62
+ test_files:
63
+ - test/ts_finitefield.rb