fixed_point 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/HISTORY.md ADDED
@@ -0,0 +1,14 @@
1
+ HISTORY/Changelog
2
+ =================
3
+
4
+ 0.1.0
5
+ -----
6
+
7
+ Improved API, to_b, to_h, to_i, to_f
8
+ Working hex output
9
+
10
+ 0.0.1
11
+ -----
12
+
13
+ Define number of integer and fractional bits with real/integer value input.
14
+
data/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ Copyright (c) 2011, Morgan Prior
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+ * Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ * Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+ * Neither the name of the organization nor the
12
+ names of its contributors may be used to endorse or promote products
13
+ derived from this software without specific prior written permission.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
19
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ FixedPoint
2
+ ============
3
+
4
+ For modeling fixed point signed and unsigned data types and having nice function for printing hex and binary forms.
5
+
6
+ Install
7
+ -------
8
+
9
+ gem install fixed_point
10
+
11
+ Usage
12
+ -----
13
+
14
+ Checkout the examples folder, but here are a few:
15
+
16
+ require 'fixed_point'
17
+
18
+ #Create fixed point format, Signed, 12 integer bits, 4 fractional bits
19
+ format = FixedPoint::Format.new(1, 12, 4)
20
+
21
+ #Create fixed_point with value 1024.75
22
+ fix_num = FixedPoint::Number.new(1024.75, format )
23
+
24
+ puts fix_num.to_f # Float
25
+ puts fix_num.to_h # Hexadecimal
26
+ puts fix_num.to_b # Binary
27
+
28
+ TODO
29
+ ----
30
+
31
+
32
+ LICENSE
33
+ -------
34
+
35
+ See the LICENSE file
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ file_list = FileList['spec/*_spec.rb']
4
+
5
+ RSpec::Core::RakeTask.new('spec') do |t|
6
+ t.pattern = file_list
7
+ t.rspec_opts = ["--colour", "--format progress"]
8
+ end
9
+
10
+ desc 'Default: run specs.'
11
+ task :default => 'spec'
@@ -0,0 +1,13 @@
1
+ module FixedPoint
2
+ VERSION = '0.1.0'
3
+ end
4
+
5
+ begin
6
+ require_relative 'fixed_point/format'
7
+ require_relative 'fixed_point/fixdt'
8
+ require_relative 'fixed_point/number'
9
+ rescue
10
+ require 'fixed_point/format'
11
+ require 'fixed_point/fixdt'
12
+ require 'fixed_point/number'
13
+ end
@@ -0,0 +1,8 @@
1
+ module FixedPoint
2
+ class Fixdt < Format
3
+ #Designed to be compatible with Matlab/Simulink types
4
+ def initialize(signed, width, frac_bits)
5
+ super( signed, width-frac_bits, frac_bits )
6
+ end
7
+ end
8
+ end #module FixedPoint
@@ -0,0 +1,55 @@
1
+ module FixedPoint
2
+
3
+ class Format
4
+
5
+ attr_reader :signed, :int_bits, :frac_bits
6
+
7
+ # Calculated attributes
8
+ attr_reader :width
9
+ attr_reader :resolution, :max_value, :min_value
10
+ attr_reader :max_int_signed, :max_int_unsigned
11
+ attr_reader :max_frac
12
+ attr_reader :max_signed, :max_unsigned
13
+
14
+ def initialize(signed, int_bits, frac_bits)
15
+ @signed = signed
16
+ @int_bits = int_bits
17
+ @frac_bits = frac_bits
18
+
19
+ calculate_attributes(signed, int_bits, frac_bits)
20
+ end
21
+
22
+ def signed?
23
+ (@signed == 1)
24
+ end
25
+
26
+ #Format Should hold the maxim possible values
27
+ #not part of number (Value)
28
+ def calculate_attributes(signed, int_bits, frac_bits)
29
+ @width = int_bits + frac_bits
30
+
31
+ #Calculate Number ranges
32
+ @resolution = 2**(-@frac_bits)
33
+ @max_frac = 1 - 2**(-@frac_bits)
34
+ @max_int_signed = ( 2**(@int_bits - 1) - 1)
35
+ @max_int_unsigned = ( 2**@int_bits - 1)
36
+ @max_signed = @max_int_signed + @max_frac
37
+ @max_unsigned = @max_int_unsigned + @max_frac
38
+
39
+ @min_signed = (-2**(@int_bits-1))
40
+ @min_unsigned = 0
41
+
42
+ #Set Max/Min values
43
+ if signed?
44
+ @max_value = @max_signed
45
+ @min_value = @min_signed
46
+ else
47
+ @max_value = @max_unsigned
48
+ @min_value = @min_unsigned
49
+ end
50
+
51
+ end
52
+
53
+ end
54
+
55
+ end #module FixedPoint
@@ -0,0 +1,312 @@
1
+ module FixedPoint
2
+
3
+ class Number
4
+ attr_reader :source #Input value
5
+ attr_reader :format
6
+
7
+ ############################################
8
+ #### Note
9
+ ## All methods which set the @source value
10
+ ## must also set the @quantised value.
11
+ ## Every thing else is calculated on the fly
12
+ ## based on those 2 values
13
+ ############################################
14
+
15
+
16
+ ####################################
17
+ ### Init
18
+ ####################################
19
+ def initialize(number, input_format=Format.new(1,12,20), decimal_mark=".")
20
+ @source = number
21
+ @format = input_format
22
+ @decimal_mark = decimal_mark
23
+
24
+ @warnings = false
25
+
26
+ #Now construct values based on config data
27
+ @quantised = quantise_value( source )
28
+ end
29
+
30
+ ####################################
31
+ ### Number overflow/underflow flags
32
+ ####################################
33
+ def overflow?
34
+ @overflow
35
+ end
36
+
37
+ def underflow?
38
+ @underflow
39
+ end
40
+
41
+ ####################################
42
+ ### Methods to return number formats
43
+ ####################################
44
+ def bin
45
+ binary
46
+ end
47
+
48
+ def hex
49
+ hexadecimal
50
+ end
51
+
52
+ #To Binary form
53
+ def to_b
54
+ binary
55
+ end
56
+
57
+ #To Hexadecimal form
58
+ def to_h
59
+ hexadecimal
60
+ end
61
+
62
+ #To Floating Point form, quantised version of _source_
63
+ def to_f
64
+ @quantised
65
+ end
66
+
67
+ #To Integer, limited integer part of _source_
68
+ def to_i
69
+ @quantised.to_i
70
+ end
71
+
72
+ # Method returns fractional section of fixed point type
73
+ # not a to_ method as it is not representative of the whole number
74
+ def frac
75
+ (@quantised - to_i)
76
+ end
77
+
78
+ def fraction
79
+ frac
80
+ end
81
+
82
+ ####################################
83
+ ### Methods to calculate formats
84
+ ####################################
85
+ def binary
86
+ #Take signed quantised value and create binary string
87
+ if (@quantised < 0) and fraction.nonzero?
88
+ # Fractional numbers not negative
89
+ # So the integer part is 1 less than other wise would be and add 1+frac
90
+ ret_bin_int = (@format.max_int_unsigned + to_i )
91
+ frac_value = 1 + fraction
92
+ end
93
+
94
+ if (@quantised < 0) and fraction.zero?
95
+ ret_bin_int = (@format.max_int_unsigned + to_i + 1 )
96
+ frac_value = fraction
97
+ end
98
+
99
+ if @quantised >= 0
100
+ ret_bin_int = self.to_i
101
+ frac_value = fraction
102
+ end
103
+
104
+ ## Convert to binary String and extend to correct length
105
+ ret_bin_int = ret_bin_int.to_s(2).rjust(@format.int_bits, '0')
106
+
107
+ ## Normalise Fractional (fractional bits shifted to appear as integer)
108
+ ret_bin_frac = Integer(frac_value * 2**@format.frac_bits)
109
+ ret_bin_frac = ret_bin_frac.to_s(2).rjust(@format.frac_bits, '0' )
110
+
111
+ #Decide if we need to add Decimal( Binary ) Point
112
+ if @format.frac_bits > 0
113
+ binary_string = ret_bin_int + @decimal_mark + ret_bin_frac
114
+ else
115
+ binary_string = ret_bin_int
116
+ end
117
+
118
+ return binary_string
119
+ end
120
+
121
+ def hexadecimal
122
+ #Clean Binary code (remove _ - . etc)
123
+ clean_binary = to_b.scan(/[01]/).join('')
124
+
125
+ #Convert to unsigned int then to hex
126
+ hex = clean_binary.to_i(2).to_s(16)
127
+ hex_chars = (@format.width/4.0).ceil
128
+
129
+ ## Extend to the correct length
130
+ ## Negative numbers will already have MSBs this if for small +VE
131
+ return hex.rjust(hex_chars, '0')
132
+ end
133
+
134
+ ####################################
135
+ ### Methods to set value from fixed point format
136
+ ####################################
137
+ def binary=(text)
138
+ if text.match(/([01]*)(.?)([01]*)/ )
139
+ set_int = $1
140
+ int_bits = $1.size
141
+
142
+ @decimal_mark = $2
143
+ set_frac = $3
144
+ frac_bits = $3.size
145
+
146
+ #TODO Warn if the number of bits supplied does not match @format
147
+
148
+ ## This should now create a new format type
149
+ # Do not change the Signed format as can not detect that from bit pattern
150
+ @format = Format.new(@format.signed, int_bits, frac_bits)
151
+
152
+ ###########################
153
+ ### Routine to generate source from binary
154
+ ###########################
155
+ @source = 0.0
156
+ index = 0
157
+ set_int.reverse.each_char do |x|
158
+ if x == "1"
159
+ #If input is signed then MSB is negative
160
+ if ((index + 1) == @format.int_bits) and (@format.signed?)
161
+ @source = @source + -2**index
162
+ else
163
+ @source = @source + 2**index
164
+ end
165
+ end
166
+ index = index + 1
167
+ end
168
+
169
+ index = 1
170
+ set_frac.each_char do |x|
171
+ if x == "1"
172
+ @source = @source + 2**-index
173
+ end
174
+ index = index + 1
175
+ end
176
+ ################################
177
+
178
+ ## Set the Quantised value
179
+ @quantised = @source
180
+
181
+ return binary
182
+ else
183
+ puts "ERROR invalid input binary\(#{text}\)"
184
+ return nil
185
+ end
186
+ end
187
+
188
+ #def hex=( text )
189
+ #end
190
+
191
+
192
+ #TODO
193
+ #def log
194
+ #def log2
195
+
196
+ def warnings( val=true )
197
+ @warnings = val
198
+ end
199
+
200
+ private
201
+
202
+ def check_for_overflow_underflow( source, format)
203
+ overflow = false
204
+ underflow = false
205
+
206
+ #WARN +VE
207
+ if (source > 0) and (source > format.max_value)
208
+ puts "WARNING Maximum number is #{format.max_value} input was #{source}" if @warnings
209
+ overflow = true
210
+ end
211
+
212
+ ##WARN -VE
213
+ if (source < 0) and (source < format.min_value)
214
+ puts "WARNING Minimum number is #{format.min_value} input was #{source}" if @warnings
215
+ underflow = true
216
+ end
217
+
218
+ return [overflow, underflow]
219
+ end
220
+
221
+
222
+ def quantise_value( source )
223
+ #Overflow / Underflow flags
224
+ @overflow, @underflow = check_for_overflow_underflow( source, @format)
225
+
226
+ ## Create fractional only number
227
+ source_frac = source - source.to_i
228
+
229
+ #Logic for fractional negative numbers is different
230
+ if (( source < 0) and source_frac.nonzero? )
231
+ #Integer bits become 1 more negative
232
+ number_int = Integer( source )-1
233
+
234
+ #The @fractional part inverts so int+frac = original number
235
+ number_frac = ( source - number_int)
236
+ else
237
+ # Create Integer only number
238
+ number_int = source.to_i
239
+
240
+ #Fractional Part
241
+ number_frac = source_frac
242
+ end
243
+
244
+
245
+ if overflow?
246
+ if @format.signed?
247
+ number_int = @format.max_int_signed
248
+ number_frac = @format.max_frac
249
+ else
250
+ number_int = @format.max_int_unsigned
251
+ number_frac = @format.max_frac
252
+ end
253
+ end
254
+
255
+ if underflow?
256
+ if @format.signed?
257
+ number_int = 2**(@format.int_bits-1)
258
+ number_frac = 0
259
+ else
260
+ number_int = 0
261
+ number_frac = 0
262
+ end
263
+ end
264
+
265
+ ##Roll the integer number over the number space so binary conversion gives correct Twos complement
266
+ if number_int < 0
267
+ number_int = @format.max_int_unsigned + (number_int + 1)
268
+ end
269
+
270
+ ###################################
271
+ ### Quantized Fractional value
272
+ ###################################
273
+ # Normalise, represent as integer
274
+ # Fractional data is removed by the integer.
275
+ # We are only left with @format.frac_bits worth of data
276
+ number_frac_quant = (number_frac * 2**@format.frac_bits).to_i / (2**@format.frac_bits).to_f
277
+
278
+ # TODO Comment on what this is actually doing
279
+ # some sought of signed conversion
280
+ if (@source < 0) and number_frac_quant.nonzero?
281
+ number_int = number_int - @format.max_int_unsigned
282
+ number_frac_quant = number_frac_quant - 1
283
+ end
284
+
285
+ if (@source < 0) and number_frac_quant.zero?
286
+ number_int = number_int - @format.max_int_unsigned - 1
287
+ number_frac_quant = 0
288
+ end
289
+
290
+ return (number_int + number_frac_quant)
291
+ end ## quantise_input
292
+
293
+
294
+
295
+
296
+
297
+ ## Taking methd out until covered by tests
298
+ #def normalised
299
+ # #This use to be only for positive numbers
300
+ #
301
+ # # This function shiftes the fixedpoint number
302
+ # # so it can be represented as an integer.
303
+ # return Integer((@quantised)*(2**@format.frac_bits))
304
+ #end
305
+
306
+ def FixedPoint_debug(msg)
307
+ if true == false
308
+ puts msg
309
+ end
310
+ end
311
+ end #class number
312
+ end #module FixedPoint
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ describe FixedPoint do
4
+
5
+ it "Negative Integers -1 " do
6
+ format = FixedPoint::Format.new(1,4,0)
7
+ fixt = FixedPoint::Number.new(-1.0, format, "_")
8
+
9
+ fixt.source.should == -1.0
10
+ fixt.to_f.should == -1.0
11
+ fixt.to_i.should == -1
12
+ fixt.frac.should == 0.0
13
+ fixt.to_h.should == "f"
14
+ fixt.to_b.should == "1111"
15
+ end
16
+
17
+ it "Negative Integers -2 " do
18
+ format = FixedPoint::Format.new(1,4,0)
19
+ fixt = FixedPoint::Number.new(-2.0, format, "_")
20
+
21
+ fixt.source.should == -2.0
22
+ fixt.to_f.should == -2.0
23
+ fixt.to_i.should == -2
24
+ fixt.frac.should == 0.0
25
+ fixt.to_h.should == "e"
26
+ fixt.to_b.should == "1110"
27
+ end
28
+
29
+ it "Negative Integers -1.5 " do
30
+ format = FixedPoint::Format.new(1,4,4)
31
+ fixt = FixedPoint::Number.new(-1.5, format, "_")
32
+
33
+ fixt.source.should == -1.5
34
+ fixt.to_f.should == -1.5
35
+ fixt.to_i.should == -1
36
+ fixt.frac.should == -0.5
37
+ fixt.to_h.should == "e8"
38
+ fixt.to_b.should == "1110_1000"
39
+ end
40
+ it "Negative Integers -2.25 " do
41
+ format = FixedPoint::Format.new(1,4,4)
42
+ fixt = FixedPoint::Number.new(-2.25, format, "_")
43
+
44
+ fixt.source.should == -2.25
45
+ fixt.to_f.should == -2.25
46
+ fixt.to_i.should == -2
47
+ fixt.frac.should == -0.25
48
+ fixt.to_h.should == "dc"
49
+ fixt.to_b.should == "1101_1100"
50
+ end
51
+
52
+ end
@@ -0,0 +1,311 @@
1
+ require 'spec_helper'
2
+
3
+ # def initialize(number, Format.new(signed=1, int_bits=12, frac_bits=20), decimal_mark=".")
4
+ # source Input Number
5
+ # to_f quantised value as float
6
+ # to_i quantised value as integer
7
+ # frac fractional part of quantised value
8
+ # to_h quantised value as string formatted as hex
9
+ # to_b quantised value as string formatted as binary
10
+ #
11
+
12
+ describe FixedPoint do
13
+
14
+ it "Returns 0.0 for initalise of 0" do
15
+ fixt = FixedPoint::Number.new(0)
16
+
17
+ fixt.source.should == 0.0
18
+ fixt.to_f.should == 0.0
19
+ fixt.to_i.should == 0
20
+ fixt.frac.should == 0.0
21
+ fixt.to_h.should == "00000000"
22
+ fixt.to_b.should == "000000000000.00000000000000000000"
23
+ end
24
+
25
+ it "Integers 0 " do
26
+ format = FixedPoint::Format.new(1,8,0)
27
+ fixt = FixedPoint::Number.new(7.0, format, "_")
28
+
29
+ fixt.source.should == 7.0
30
+ fixt.to_f.should == 7.0
31
+ fixt.to_i.should == 7
32
+ fixt.frac.should == 0.0
33
+ fixt.to_h.should == "07"
34
+ fixt.to_b.should == "00000111"
35
+ end
36
+
37
+ it "Different Decimal Mark _ instead of ." do
38
+ format = FixedPoint::Format.new(1,12,20)
39
+ fixt = FixedPoint::Number.new(0, format, "_")
40
+
41
+ fixt.source.should == 0.0
42
+ fixt.to_f.should == 0.0
43
+ fixt.to_i.should == 0
44
+ fixt.frac.should == 0.0
45
+ fixt.to_h.should == "00000000"
46
+ fixt.to_b.should == "000000000000_00000000000000000000"
47
+ end
48
+
49
+ (1...20).to_a.reverse_each do |x|
50
+ int_bits = 12
51
+ it "Returns 0.0 for initalise of 0 with #{x} fractional bits" do
52
+ format = FixedPoint::Format.new(1, int_bits, x)
53
+ fixt = FixedPoint::Number.new(0, format)
54
+ #fixt = FixedPoint::Number.new(0,1,int_bits,x)
55
+
56
+ fixt.source.should == 0.0
57
+ fixt.to_f.should == 0.0
58
+ fixt.to_i.should == 0
59
+ fixt.frac.should == 0.0
60
+ #Calculate hex length and fill with 0's
61
+ hex = ""
62
+ hex_length = ((x.to_f+int_bits.to_f)/4).ceil
63
+ hex_length.times { hex += "0" }
64
+ fixt.to_h.should == hex
65
+ #Calculate binary fractional length and fill with 0's
66
+ lsbs = ""
67
+ x.times { lsbs += "0" }
68
+ fixt.to_b.should == "000000000000.#{lsbs}"
69
+ end
70
+ end
71
+
72
+
73
+ it "Zero fractional bits " do
74
+ format = FixedPoint::Format.new(1,12,0)
75
+ fixt = FixedPoint::Number.new(0, format, "_")
76
+
77
+ fixt.source.should == 0.0
78
+ fixt.to_f.should == 0.0
79
+ fixt.to_i.should == 0
80
+ fixt.frac.should == 0.0
81
+ fixt.to_h.should == "000"
82
+ fixt.to_b.should == "000000000000"
83
+ end
84
+
85
+
86
+ it "returns 2.5 for initalise of 2.5" do
87
+ fixt = FixedPoint::Number.new(2.5)
88
+
89
+ fixt.source.should == 2.5
90
+ fixt.to_f.should == 2.5
91
+ fixt.to_i.should == 2
92
+ fixt.frac.should == 0.5
93
+ fixt.to_h.should == "00280000"
94
+ fixt.to_b.should == "000000000010.10000000000000000000"
95
+ end
96
+
97
+
98
+ it "Truncates fractional numbers correctly" do
99
+ format = FixedPoint::Format.new(1,12,1)
100
+ fixt = FixedPoint::Number.new(2.501, format)
101
+
102
+ fixt.source.should == 2.501
103
+ fixt.to_f.should == 2.5
104
+ fixt.to_i.should == 2
105
+ fixt.frac.should == 0.5
106
+ fixt.to_h.should == "0005"
107
+ fixt.to_b.should == "000000000010.1"
108
+ end
109
+
110
+ ##############################################
111
+ ### Overflow Section
112
+ ##############################################
113
+ it "Forced Overflow 4 Int Bits, 0 fractional bits " do
114
+ format = FixedPoint::Format.new(1, 4, 0)
115
+ fixt = FixedPoint::Number.new(2**3, format, "_")
116
+
117
+ fixt.source.should == 2**3
118
+ fixt.to_f.should == 2**3-1
119
+ fixt.to_i.should == 2**3-1
120
+ fixt.frac.should == 0.0
121
+ fixt.to_h.should == "7"
122
+ fixt.to_b.should == "0111"
123
+ fixt.overflow?.should == true
124
+ fixt.underflow?.should == false
125
+ end
126
+
127
+ it "Forced Overflow Zero fractional bits " do
128
+ format = FixedPoint::Format.new(1, 12, 0)
129
+ fixt = FixedPoint::Number.new(2**11, format, "_")
130
+
131
+ fixt.source.should == 2**11
132
+ fixt.to_f.should == 2**11-1
133
+ fixt.to_i.should == 2**11-1
134
+ fixt.frac.should == 0.0
135
+ fixt.to_h.should == "7ff"
136
+ fixt.to_b.should == "011111111111"
137
+ fixt.overflow?.should == true
138
+ fixt.underflow?.should == false
139
+ end
140
+
141
+ it "Forced Overflow 4 fractional bits " do
142
+ format = FixedPoint::Format.new(1, 12, 4)
143
+ fixt = FixedPoint::Number.new(2**11, format, ".")
144
+
145
+ max_fractional_value = (1.0/2) + (1.0/4) + (1.0/8) + (1.0/16)
146
+
147
+ fixt.source.should == 2**11
148
+ fixt.to_f.should == 2**11 -1 + max_fractional_value
149
+ fixt.to_i.should == 2**11 -1
150
+ fixt.frac.should == max_fractional_value
151
+ fixt.to_h.should == "7fff"
152
+ fixt.to_b.should == "011111111111.1111"
153
+ fixt.overflow?.should == true
154
+ fixt.underflow?.should == false
155
+ end
156
+
157
+ it "Forced Overflow Large overflow" do
158
+ format = FixedPoint::Format.new(1, 12, 4)
159
+ fixt = FixedPoint::Number.new(2**17, format, ".")
160
+
161
+ fixt.source.should == 2**17
162
+
163
+ max_fractional_value = (1.0/2) + (1.0/4) + (1.0/8) + (1.0/16)
164
+
165
+ fixt.to_f.should == 2**11 -1 + max_fractional_value
166
+ fixt.to_i.should == 2**11 -1
167
+ fixt.frac.should == max_fractional_value
168
+ fixt.to_h.should == "7fff"
169
+ fixt.to_b.should == "011111111111.1111"
170
+ fixt.overflow?.should == true
171
+ fixt.underflow?.should == false
172
+ end
173
+
174
+ ##############################################
175
+ ### Underflow Section
176
+ ##############################################
177
+ #Max Negative value
178
+ it "Forced Overflow Zero fractional bits " do
179
+ format = FixedPoint::Format.new(1, 12, 0)
180
+ fixt = FixedPoint::Number.new(-2**11, format, "_")
181
+
182
+ fixt.source.should == -2**11
183
+ fixt.to_f.should == -2**11
184
+ fixt.to_i.should == -2**11
185
+ fixt.frac.should == 0.0
186
+ fixt.to_h.should == "800"
187
+ fixt.to_b.should == "100000000000"
188
+ fixt.overflow?.should == false
189
+ fixt.underflow?.should == false
190
+ end
191
+
192
+ it "Forced Overflow Zero fractional bits " do
193
+ format = FixedPoint::Format.new(1, 12, 0)
194
+ fixt = FixedPoint::Number.new(-2**11-1, format,"_")
195
+
196
+ fixt.source.should == -2**11-1
197
+ fixt.to_f.should == -2**11
198
+ fixt.to_i.should == -2**11
199
+ fixt.frac.should == 0.0
200
+ fixt.to_h.should == "800"
201
+ fixt.to_b.should == "100000000000"
202
+ fixt.overflow?.should == false
203
+ fixt.underflow?.should == true
204
+ end
205
+
206
+ it "Forced Overflow 4 fractional bits " do
207
+ format = FixedPoint::Format.new(1, 12, 4)
208
+ fixt = FixedPoint::Number.new(-2**11-1, format, ".")
209
+
210
+ fixt.source.should == -2**11-1
211
+ fixt.to_f.should == -2**11
212
+ fixt.to_i.should == -2**11
213
+ fixt.frac.should == 0.0
214
+ fixt.to_h.should == "8000"
215
+ fixt.to_b.should == "100000000000.0000"
216
+ fixt.overflow?.should == false
217
+ fixt.underflow?.should == true
218
+ end
219
+
220
+ it "Forced Overflow Large overflow" do
221
+ format = FixedPoint::Format.new(1, 12, 4)
222
+ fixt = FixedPoint::Number.new(-2**17, format, ".")
223
+
224
+
225
+ fixt.source.should == -2**17
226
+ fixt.to_f.should == -2**11
227
+ fixt.to_i.should == -2**11
228
+ fixt.frac.should == 0.0
229
+ fixt.to_h.should == "8000"
230
+ fixt.to_b.should == "100000000000.0000"
231
+ fixt.overflow?.should == false
232
+ fixt.underflow?.should == true
233
+ end
234
+
235
+
236
+ it "Creating via binary form 011_01" do
237
+ fixt = FixedPoint::Number.new(0)
238
+
239
+ fixt.binary = "011_01"
240
+ fixt.source.should == 3.25
241
+ fixt.to_f.should == 3.25
242
+ fixt.to_i.should == 3
243
+ fixt.frac.should == 0.25
244
+ fixt.to_h.should == "0d"
245
+ fixt.to_b.should == "011_01"
246
+ fixt.overflow?.should == false
247
+ fixt.underflow?.should == false
248
+ end
249
+
250
+ it "Creating via binary form 0_1" do
251
+ fixt = FixedPoint::Number.new(0)
252
+
253
+ fixt.binary = "0_1"
254
+ fixt.source.should == 0.5
255
+ fixt.to_f.should == 0.5
256
+ fixt.to_i.should == 0
257
+ fixt.frac.should == 0.5
258
+ fixt.to_h.should == "1"
259
+ fixt.to_b.should == "0_1"
260
+ fixt.overflow?.should == false
261
+ fixt.underflow?.should == false
262
+ end
263
+
264
+ it "Creating Signed via binary form 1000_1" do
265
+ fixt = FixedPoint::Number.new(0)
266
+
267
+ fixt.binary = "1000_1"
268
+ fixt.source.should == -7.5
269
+ fixt.to_f.should == -7.5
270
+ fixt.to_i.should == -7
271
+ fixt.frac.should == -0.5
272
+ fixt.to_h.should == "11"
273
+ fixt.to_b.should == "1000_1"
274
+ fixt.overflow?.should == false
275
+ fixt.underflow?.should == false
276
+ end
277
+
278
+ it "Creating Unsigned via binary form 1000_1" do
279
+ format = FixedPoint::Format.new(0, 12, 20)
280
+ fixt = FixedPoint::Number.new(0,format)
281
+
282
+ fixt.binary = "1000_1"
283
+ fixt.source.should == 8.5
284
+ fixt.to_f.should == 8.5
285
+ fixt.to_i.should == 8
286
+ fixt.frac.should == 0.5
287
+ fixt.to_h.should == "11"
288
+ fixt.to_b.should == "1000_1"
289
+ fixt.overflow?.should == false
290
+ fixt.underflow?.should == false
291
+ end
292
+
293
+ it "Creating Unsigned binary form 1000_1 using Fixdt datatype" do
294
+ format = FixedPoint::Fixdt.new(0, 32, 20) #Signed,width,frac_bits
295
+ fixt = FixedPoint::Number.new(0,format)
296
+
297
+ fixt.binary = "1000_1"
298
+ fixt.source.should == 8.5
299
+ fixt.to_f.should == 8.5
300
+ fixt.to_i.should == 8
301
+ fixt.frac.should == 0.5
302
+ fixt.to_h.should == "11"
303
+ fixt.to_b.should == "1000_1"
304
+ fixt.overflow?.should == false
305
+ fixt.underflow?.should == false
306
+ end
307
+
308
+ #need overflow test
309
+ #need underflow test
310
+ #Integer only binary test
311
+ end
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
2
+
3
+ require 'rspec'
4
+ require 'fixed_point'
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fixed_point
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Morgan Prior
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-01-21 00:00:00 +00:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Fixed Point numerical type for simulating fixed point calculations
23
+ email: fixed_point_gem@amaras-tech.co.uk
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - LICENSE
32
+ - README.md
33
+ - HISTORY.md
34
+ - Rakefile
35
+ - lib/fixed_point/fixdt.rb
36
+ - lib/fixed_point/format.rb
37
+ - lib/fixed_point/number.rb
38
+ - lib/fixed_point.rb
39
+ - spec/fixed_point_negative_spec.rb
40
+ - spec/fixed_point_spec.rb
41
+ - spec/spec_helper.rb
42
+ has_rdoc: true
43
+ homepage: http://amaras-tech.co.uk/software/fixed_point
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options: []
48
+
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ hash: 3
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ requirements: []
70
+
71
+ rubyforge_project:
72
+ rubygems_version: 1.6.2
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: Fixed Point numerical type
76
+ test_files: []
77
+