float-formats 0.1.1 → 0.2.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/History.txt +27 -32
- data/Manifest.txt +10 -18
- data/README.txt +330 -327
- data/Rakefile +38 -4
- data/lib/float-formats.rb +9 -9
- data/lib/float-formats/bytes.rb +463 -303
- data/lib/float-formats/classes.rb +1950 -1605
- data/lib/float-formats/formats.rb +633 -669
- data/lib/float-formats/native.rb +144 -272
- data/lib/float-formats/version.rb +4 -4
- data/tasks/ann.rake +80 -0
- data/tasks/bones.rake +20 -0
- data/tasks/gem.rake +192 -0
- data/tasks/git.rake +40 -0
- data/tasks/manifest.rake +48 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +39 -0
- data/tasks/rdoc.rake +50 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +279 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- data/test/gen_test_data.rb +119 -119
- data/test/test_arithmetic.rb +36 -0
- data/test/test_bytes.rb +43 -0
- data/test/test_data.yaml +1667 -1667
- data/test/test_float_formats.rb +208 -0
- data/test/test_helper.rb +2 -1
- data/test/test_native-float.rb +84 -77
- metadata +123 -60
- data/config/hoe.rb +0 -73
- data/config/requirements.rb +0 -17
- data/script/destroy +0 -14
- data/script/destroy.cmd +0 -1
- data/script/generate +0 -14
- data/script/generate.cmd +0 -1
- data/script/txt2html +0 -74
- data/script/txt2html.cmd +0 -1
- data/tasks/deployment.rake +0 -34
- data/tasks/environment.rake +0 -7
- data/tasks/website.rake +0 -17
- data/test/test_float-formats.rb +0 -169
data/Rakefile
CHANGED
@@ -1,4 +1,38 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# Look in the tasks/setup.rb file for the various options that can be
|
2
|
+
# configured in this Rakefile. The .rake files in the tasks directory
|
3
|
+
# are where the options are used.
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bones'
|
7
|
+
Bones.setup
|
8
|
+
rescue LoadError
|
9
|
+
load 'tasks/setup.rb'
|
10
|
+
end
|
11
|
+
|
12
|
+
ensure_in_path 'lib'
|
13
|
+
#require 'float-formats'
|
14
|
+
require 'float-formats/version'
|
15
|
+
|
16
|
+
task :default => 'spec:run'
|
17
|
+
|
18
|
+
depend_on 'flt', '1.0.0'
|
19
|
+
depend_on 'nio', '0.2.4'
|
20
|
+
|
21
|
+
PROJ.name = 'float-formats'
|
22
|
+
PROJ.description = "Floating-Point Formats"
|
23
|
+
PROJ.authors = 'Javier Goizueta'
|
24
|
+
PROJ.email = 'javier@goizueta.info'
|
25
|
+
PROJ.version = Flt::FORMATS_VERSION::STRING
|
26
|
+
PROJ.rubyforge.name = 'float-formats'
|
27
|
+
PROJ.url = "http://#{PROJ.rubyforge.name}.rubyforge.org"
|
28
|
+
PROJ.rdoc.opts = [
|
29
|
+
"--main", "README.txt",
|
30
|
+
'--title', 'Float-Formats Documentation',
|
31
|
+
"--opname", "index.html",
|
32
|
+
"--line-numbers",
|
33
|
+
"--inline-source"
|
34
|
+
]
|
35
|
+
depend_on 'nio', '>=0.2.0'
|
36
|
+
depend_on 'flt', '>=1.0.0'
|
37
|
+
|
38
|
+
# EOF
|
data/lib/float-formats.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
$:.unshift File.dirname(__FILE__)
|
2
|
-
|
3
|
-
require 'float-formats/version'
|
4
|
-
require 'float-formats/bytes'
|
5
|
-
require 'float-formats/classes'
|
6
|
-
require 'float-formats/formats'
|
7
|
-
|
8
|
-
#
|
9
|
-
module
|
10
|
-
end
|
2
|
+
|
3
|
+
require 'float-formats/version'
|
4
|
+
require 'float-formats/bytes'
|
5
|
+
require 'float-formats/classes'
|
6
|
+
require 'float-formats/formats'
|
7
|
+
|
8
|
+
# Flt contains constants for common floating point formats.
|
9
|
+
module Flt
|
10
|
+
end
|
data/lib/float-formats/bytes.rb
CHANGED
@@ -1,304 +1,464 @@
|
|
1
|
-
# Float-Formats
|
2
|
-
# Support for binary data representations
|
3
|
-
|
4
|
-
require 'nio'
|
5
|
-
|
6
|
-
|
7
|
-
require '
|
8
|
-
|
9
|
-
module
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
#
|
57
|
-
def
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
#
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
#
|
170
|
-
def
|
171
|
-
|
172
|
-
end
|
173
|
-
|
174
|
-
|
175
|
-
#
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
1
|
+
# Float-Formats
|
2
|
+
# Support for binary data representations
|
3
|
+
require 'nio'
|
4
|
+
require 'nio/sugar'
|
5
|
+
|
6
|
+
require 'enumerator'
|
7
|
+
require 'delegate'
|
8
|
+
|
9
|
+
module Flt
|
10
|
+
|
11
|
+
class Bits
|
12
|
+
# Define a bit string given the number of bits and
|
13
|
+
# optinally the initial value (as an integer).
|
14
|
+
def initialize(num_bits,v=0)
|
15
|
+
@n = num_bits
|
16
|
+
@v = v
|
17
|
+
end
|
18
|
+
|
19
|
+
# convert to text representation in a given base
|
20
|
+
def to_s(base=2)
|
21
|
+
n = Bits.power_of_two(base)
|
22
|
+
if n
|
23
|
+
fmt = Nio::Fmt.default.base(base,true).mode(:fix,:exact)
|
24
|
+
digits = (size+n-1)/n
|
25
|
+
fmt.pad0s!(digits)
|
26
|
+
@v.nio_write(fmt)
|
27
|
+
else
|
28
|
+
@v.to_s(base)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# produce bit string from a text representation
|
33
|
+
def self.from_s(txt,base=2,len=nil)
|
34
|
+
txt = txt.tr('., _','')
|
35
|
+
v = txt.to_i(base)
|
36
|
+
if len.nil?
|
37
|
+
n = power_of_two(base)
|
38
|
+
if n
|
39
|
+
len = txt.size * n
|
40
|
+
end
|
41
|
+
end
|
42
|
+
from_i v, len
|
43
|
+
end
|
44
|
+
|
45
|
+
# convert to integer
|
46
|
+
def to_i
|
47
|
+
@v
|
48
|
+
end
|
49
|
+
|
50
|
+
# produce bit string from an integer
|
51
|
+
def self.from_i(v,len=nil)
|
52
|
+
len ||= (Math.log(v)/Math.log(2)).ceil # v.to_s(2).size
|
53
|
+
Bits.new(len,v)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Access a bit value. The least significant bit has index 0.
|
57
|
+
def [](i)
|
58
|
+
(@v >> i) & 1
|
59
|
+
end
|
60
|
+
|
61
|
+
# Set a bit. The least significant bit has index 0. The bit value
|
62
|
+
# can be passed as an integer or a boolean value.
|
63
|
+
def []=(i,b)
|
64
|
+
b = (b && b!=0) ? 1 : 0
|
65
|
+
@v &= ~(1 << i)
|
66
|
+
@v |= (b << i)
|
67
|
+
b
|
68
|
+
end
|
69
|
+
|
70
|
+
# number of bits
|
71
|
+
def size
|
72
|
+
@n
|
73
|
+
end
|
74
|
+
|
75
|
+
protected
|
76
|
+
|
77
|
+
def self.is_power_of_two?(v)
|
78
|
+
if v==0
|
79
|
+
false
|
80
|
+
else
|
81
|
+
v &= (v-1)
|
82
|
+
if v==0
|
83
|
+
true
|
84
|
+
else
|
85
|
+
false
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.power_of_two(v)
|
91
|
+
if is_power_of_two?(v)
|
92
|
+
n = 0
|
93
|
+
while v!=1
|
94
|
+
n += 1
|
95
|
+
v >>= 1
|
96
|
+
end
|
97
|
+
n
|
98
|
+
else
|
99
|
+
nil
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
class Bytes < DelegateClass(String)
|
106
|
+
|
107
|
+
def initialize(bytes)
|
108
|
+
case bytes
|
109
|
+
when Bytes
|
110
|
+
@bytes = bytes.to_s
|
111
|
+
when Array
|
112
|
+
@bytes = bytes.pack("C*")
|
113
|
+
else
|
114
|
+
@bytes = bytes.to_str
|
115
|
+
end
|
116
|
+
@bytes.force_encoding(Encoding::BINARY) if RUBY_VERSION>="1.9.0"
|
117
|
+
super @bytes
|
118
|
+
end
|
119
|
+
|
120
|
+
def dup
|
121
|
+
Bytes.new @bytes.dup
|
122
|
+
end
|
123
|
+
|
124
|
+
if RUBY_VERSION>="1.9.0"
|
125
|
+
def size
|
126
|
+
bytesize
|
127
|
+
end
|
128
|
+
alias _get_str []
|
129
|
+
alias _set_str []=
|
130
|
+
def [](*params)
|
131
|
+
if params.size == 1 && !params.first.kind_of?(Range)
|
132
|
+
_get_str(params.first).ord # bytes.to_a[params.first]
|
133
|
+
else
|
134
|
+
Bytes.new(_get_str(*params))
|
135
|
+
end
|
136
|
+
end
|
137
|
+
def []=(i,v)
|
138
|
+
_set_str i, v.chr(Encoding::BINARY)
|
139
|
+
end
|
140
|
+
else
|
141
|
+
alias _get_str []
|
142
|
+
def [](*params)
|
143
|
+
if params.size == 1
|
144
|
+
_get_str(params.first)
|
145
|
+
else
|
146
|
+
Bytes.new(_get_str(*params))
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def +(b)
|
152
|
+
Bytes.new(to_str + b.to_str)
|
153
|
+
end
|
154
|
+
|
155
|
+
# return an hex representation of a byte string
|
156
|
+
def to_hex(sep_bytes=false)
|
157
|
+
hx = @bytes.unpack('H*')[0].upcase
|
158
|
+
if sep_bytes
|
159
|
+
sep = ""
|
160
|
+
(0...hx.size).step(2) do |i|
|
161
|
+
sep << " " unless i==0
|
162
|
+
sep << hx[i,2]
|
163
|
+
end
|
164
|
+
hx = sep
|
165
|
+
end
|
166
|
+
hx
|
167
|
+
end
|
168
|
+
|
169
|
+
# generate a byte string from an hex representation
|
170
|
+
def Bytes.from_hex(hex)
|
171
|
+
Bytes.new [hex.tr(' ','')].pack('H*')
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
# Reverse the order of the bits in each byte.
|
176
|
+
def reverse_byte_bits!
|
177
|
+
@bytes = @bytes.unpack('b*').pack("B*")[0]
|
178
|
+
__setobj__ @bytes
|
179
|
+
self
|
180
|
+
end
|
181
|
+
|
182
|
+
def reverse_byte_bits
|
183
|
+
dup.reverse_byte_bits!
|
184
|
+
end
|
185
|
+
|
186
|
+
# Reverse the order of the nibbles in each byte.
|
187
|
+
def reverse_byte_nibbles!
|
188
|
+
w = ""
|
189
|
+
@bytes.each_byte do |b|
|
190
|
+
w << ((b >> 4)|((b&0xF)<<4))
|
191
|
+
end
|
192
|
+
@bytes = w
|
193
|
+
__setobj__ @bytes
|
194
|
+
self
|
195
|
+
end
|
196
|
+
def reverse_byte_nibbles
|
197
|
+
dup.reverse_byte_nibbles!
|
198
|
+
end
|
199
|
+
|
200
|
+
# reverse the order of bytes in 16-bit words
|
201
|
+
def reverse_byte_pairs!
|
202
|
+
w = ""
|
203
|
+
(0...@bytes.size).step(2) do |i|
|
204
|
+
w << @bytes[i+1]
|
205
|
+
w << @bytes[i]
|
206
|
+
end
|
207
|
+
@bytes = w
|
208
|
+
__setobj__ @bytes
|
209
|
+
self
|
210
|
+
end
|
211
|
+
|
212
|
+
def reverse_byte_pairs
|
213
|
+
dup.reverse_byte_pairs!
|
214
|
+
end
|
215
|
+
|
216
|
+
# Supported endianness modes for byte strings are:
|
217
|
+
# [<tt>:little_endian</tt>] (Intel order): least significant bytes come first.
|
218
|
+
# [<tt>:big_endian</tt>] (Network order): most significant bytes come first.
|
219
|
+
# [<tt>:little_big_endian</tt> or <tt>:middle_endian</tt>] (PDP-11 order): each pair of bytes
|
220
|
+
# (16-bit word) has the bytes in little endian order, but the words
|
221
|
+
# are stored in big endian order (we assume the number of bytes is even).
|
222
|
+
# Note that the <tt>:big_little_endian</tt> order which would logically complete the set is
|
223
|
+
# not currently supported as it has no known uses.
|
224
|
+
def convert_endianness!(from_endianness, to_endianness)
|
225
|
+
if from_endianness!=to_endianness
|
226
|
+
if ([:little_endian,:big_endian]+[from_endianness, to_endianness]).uniq.size==2
|
227
|
+
# no middle_endian order
|
228
|
+
reverse!
|
229
|
+
else
|
230
|
+
# from or to is middle_endian
|
231
|
+
if [:middle_endian, :little_big_endian].include?(to_endianness)
|
232
|
+
# from little_big_endian
|
233
|
+
convert_endianness!(from_endianness, :big_endian).reverse_byte_pairs!
|
234
|
+
else
|
235
|
+
# from little_big_endian
|
236
|
+
reverse_byte_pairs!.convert_endianness!(:big_endian, to_endianness)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
self
|
241
|
+
end
|
242
|
+
|
243
|
+
def convert_endianness(from_endianness, to_endianness)
|
244
|
+
dup.convert_endianness!(from_endianness, to_endianness)
|
245
|
+
end
|
246
|
+
|
247
|
+
# Binary data is handled here in three representations:
|
248
|
+
# as an Integer
|
249
|
+
# as a byte sequence (String) (with specific endianness)
|
250
|
+
# an an hex-string (nibble values) (with specific endianness)
|
251
|
+
|
252
|
+
# Convert a byte string to an integer
|
253
|
+
def to_i(byte_endianness=:little_endian, bits_little_endian=false)
|
254
|
+
i = 0
|
255
|
+
bytes = convert_endianness(byte_endianness, :big_endian)
|
256
|
+
bytes = bytes.reverse_byte_bits if bits_little_endian
|
257
|
+
bytes.each_byte do |b|
|
258
|
+
i <<= 8
|
259
|
+
i |= b
|
260
|
+
end
|
261
|
+
i
|
262
|
+
end
|
263
|
+
|
264
|
+
# Convert an integer to a byte string
|
265
|
+
def Bytes.from_i(i, len=0, byte_endianness=:little_endian, bits_little_endian=false)
|
266
|
+
return nil if i<0
|
267
|
+
bytes = Bytes.new("")
|
268
|
+
while i>0
|
269
|
+
b = (i&0xFF)
|
270
|
+
bytes << b
|
271
|
+
i >>= 8
|
272
|
+
end
|
273
|
+
bytes << 0 while bytes.size<len
|
274
|
+
bytes.reverse_byte_bits! if bits_little_endian
|
275
|
+
bytes.convert_endianness!(:little_endian, byte_endianness)
|
276
|
+
bytes
|
277
|
+
end
|
278
|
+
|
279
|
+
# convert a byte string to separate fixed-width bit-fields as integers
|
280
|
+
def to_bitfields(lens,byte_endianness=:little_endian, bits_little_endian=false)
|
281
|
+
fields = []
|
282
|
+
i = to_i(byte_endianness,bits_little_endian)
|
283
|
+
for len in lens
|
284
|
+
mask = (1<<len)-1
|
285
|
+
fields << (i&mask)
|
286
|
+
i >>= len
|
287
|
+
end
|
288
|
+
fields
|
289
|
+
end
|
290
|
+
|
291
|
+
# pack fixed-width bit-fields as integers into a byte string
|
292
|
+
def Bytes.from_bitfields(lens,fields,byte_endianness=:little_endian, bits_little_endian=false)
|
293
|
+
i = 0
|
294
|
+
lens = lens.reverse
|
295
|
+
fields = fields.reverse
|
296
|
+
|
297
|
+
bits = 0
|
298
|
+
|
299
|
+
(0...lens.size).each do |j|
|
300
|
+
i <<= lens[j]
|
301
|
+
i |= fields[j]
|
302
|
+
bits += lens[j]
|
303
|
+
end
|
304
|
+
from_i i,(bits+7)/8,byte_endianness, bits_little_endian
|
305
|
+
end
|
306
|
+
|
307
|
+
def to_bits(byte_endianness=:little_endian, bits_little_endian=false,nbits=nil)
|
308
|
+
i = to_i(byte_endianness, bits_little_endian)
|
309
|
+
nbits ||= 8*size
|
310
|
+
Bits.from_i(i,nbits)
|
311
|
+
end
|
312
|
+
|
313
|
+
def Bytes.from_bits(bits,byte_endianness=:little_endian, bits_little_endian=false,nbits=nil)
|
314
|
+
nbits ||= (bits.size+7)/8
|
315
|
+
from_i bits.to_i, nbits, byte_endianness, bits_little_endian
|
316
|
+
end
|
317
|
+
|
318
|
+
end
|
319
|
+
|
320
|
+
|
321
|
+
module_function
|
322
|
+
|
323
|
+
# DPD (Densely Packed Decimal) encoding
|
324
|
+
|
325
|
+
# The bcd2dpd and dpd2bcd methods are adapted from Mike Cowlishaw's Rexx program:
|
326
|
+
# (mfc 2000.10.03; Rexx version with new equations 2007.02.01)
|
327
|
+
# available at http://www2.hursley.ibm.com/decimal/DPDecimal.html
|
328
|
+
|
329
|
+
# Negate a bit. Auxiliar method for DPD conversions
|
330
|
+
def bitnot(b)
|
331
|
+
(~b)&1
|
332
|
+
end
|
333
|
+
|
334
|
+
# Compress BCD to Densely Packed Decimal
|
335
|
+
#
|
336
|
+
# adapted from Mike Cowlishaw's Rexx program:
|
337
|
+
# http://www2.hursley.ibm.com/decimal/DPDecimal.html
|
338
|
+
def bcd2dpd(arg)
|
339
|
+
# assign each bit to a variable, named as in the description
|
340
|
+
a,b,c,d,e,f,g,h,i,j,k,m = ("%012B"%arg).split('').collect{|bit| bit.to_i}
|
341
|
+
|
342
|
+
# derive the result bits, using boolean expressions only
|
343
|
+
#-- [the operators are: '&'=AND, '|'=OR, '\'=NOT.]
|
344
|
+
p=b | (a & j) | (a & f & i)
|
345
|
+
q=c | (a & k) | (a & g & i)
|
346
|
+
r=d
|
347
|
+
s=(f & (bitnot(a) | bitnot(i))) | (bitnot(a) & e & j) | (e & i)
|
348
|
+
t=g | (bitnot(a) & e &k) | (a & i)
|
349
|
+
u=h
|
350
|
+
v=a | e | i
|
351
|
+
w=a | (e & i) | (bitnot(e) & j)
|
352
|
+
x=e | (a & i) | (bitnot(a) & k)
|
353
|
+
y=m
|
354
|
+
|
355
|
+
# concatenate the bits and return
|
356
|
+
# result = [p,q,r,s,t,u,v,w,x,y].collect{|bit| bit.to_s}.inject{|aa,bb|aa+bb}.to_i(2)
|
357
|
+
result = 0
|
358
|
+
[p,q,r,s,t,u,v,w,x,y].each do |bit|
|
359
|
+
result <<= 1
|
360
|
+
result |= bit
|
361
|
+
end
|
362
|
+
result
|
363
|
+
end
|
364
|
+
|
365
|
+
# Expand Densely Packed Decimal to BCD
|
366
|
+
#
|
367
|
+
# adapted from Mike Cowlishaw's Rexx program:
|
368
|
+
# http://www2.hursley.ibm.com/decimal/DPDecimal.html
|
369
|
+
def dpd2bcd(arg)
|
370
|
+
|
371
|
+
# assign each bit to a variable, named as in the description
|
372
|
+
p,q,r,s,t,u,v,w,x,y = ("%010B"%arg).split('').collect{|bit| bit.to_i}
|
373
|
+
|
374
|
+
# derive the result bits, using boolean expressions only
|
375
|
+
a= (v & w) & (bitnot(s) | t | bitnot(x))
|
376
|
+
b=p & (bitnot(v) | bitnot(w) | (s & bitnot(t) & x))
|
377
|
+
c=q & (bitnot(v) | bitnot(w) | (s & bitnot(t) & x))
|
378
|
+
d=r
|
379
|
+
e=v & ((bitnot(w) & x) | (bitnot(t) & x) | (s & x))
|
380
|
+
f=(s & (bitnot(v) | bitnot(x))) | (p & bitnot(s) & t & v & w & x)
|
381
|
+
g=(t & (bitnot(v) | bitnot(x))) | (q & bitnot(s) & t & w)
|
382
|
+
h=u
|
383
|
+
i=v & ((bitnot(w) & bitnot(x)) | (w & x & (s | t)))
|
384
|
+
j=(bitnot(v) & w) | (s & v & bitnot(w) & x) | (p & w & (bitnot(x) | (bitnot(s) & bitnot(t))))
|
385
|
+
k=(bitnot(v) & x) | (t & bitnot(w) & x) | (q & v & w & (bitnot(x) | (bitnot(s) & bitnot(t))))
|
386
|
+
m=y
|
387
|
+
# concatenate the bits and return
|
388
|
+
# result = [a,b,c,d,e,f,g,h,i,j,k,m].collect{|bit| bit.to_s}.inject{|aa,bb|aa+bb}.to_i(2)
|
389
|
+
result = 0
|
390
|
+
[a,b,c,d,e,f,g,h,i,j,k,m].each do |bit|
|
391
|
+
result <<= 1
|
392
|
+
result |= bit
|
393
|
+
end
|
394
|
+
result
|
395
|
+
end
|
396
|
+
|
397
|
+
# Pack a bcd digits string into DPD
|
398
|
+
def hexbcd_to_dpd(bcd, endianness=:big_endian)
|
399
|
+
|
400
|
+
n = bcd.size
|
401
|
+
dpd = 0
|
402
|
+
dpd_bits = 0
|
403
|
+
|
404
|
+
i = 0
|
405
|
+
m = n%3
|
406
|
+
if m>0
|
407
|
+
v = bcd2dpd(bcd[0,m].to_i(16))
|
408
|
+
i += m
|
409
|
+
n -= m
|
410
|
+
bits = m==1 ? 4 : 7
|
411
|
+
dpd_bits += bits
|
412
|
+
dpd <<= bits
|
413
|
+
dpd |= v
|
414
|
+
end
|
415
|
+
|
416
|
+
while n>0
|
417
|
+
v = bcd2dpd(bcd[i,3].to_i(16))
|
418
|
+
i += 3
|
419
|
+
n -= 3
|
420
|
+
bits = 10
|
421
|
+
dpd_bits += bits
|
422
|
+
dpd <<= bits
|
423
|
+
dpd |= v
|
424
|
+
end
|
425
|
+
|
426
|
+
[dpd, dpd_bits]
|
427
|
+
end
|
428
|
+
|
429
|
+
# Unpack DPD digits
|
430
|
+
def dpd_to_hexbcd(dpd, dpd_bits, endianness=:big_endian)
|
431
|
+
|
432
|
+
bcd = ""
|
433
|
+
|
434
|
+
while dpd_bits>=10
|
435
|
+
v = dpd2bcd(dpd & 0x3FF)
|
436
|
+
dpd >>= 10
|
437
|
+
dpd_bits -= 10
|
438
|
+
bcd = ("%03X"%v)+bcd
|
439
|
+
end
|
440
|
+
|
441
|
+
if dpd_bits>0
|
442
|
+
case dpd_bits
|
443
|
+
when 4
|
444
|
+
v = dpd & 0xF
|
445
|
+
n = 1
|
446
|
+
when 7
|
447
|
+
v = dpd & 0x7F
|
448
|
+
n = 2
|
449
|
+
else
|
450
|
+
raise "Invalid DPD data"
|
451
|
+
end
|
452
|
+
v = dpd2bcd(v,true)
|
453
|
+
bcd = ("%0#{n}X"%v)+bcd
|
454
|
+
end
|
455
|
+
|
456
|
+
bcd = bcd.reverse if endianness==:little_endian
|
457
|
+
|
458
|
+
bcd
|
459
|
+
|
460
|
+
end
|
461
|
+
|
462
|
+
|
463
|
+
|
304
464
|
end
|