numerals 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0e87d9faabf0392f12d84d026d85d480aa67d32c
4
- data.tar.gz: 67b89570a8c97ae4abe727c730bdc77099ca70d0
3
+ metadata.gz: c2db2456e26dc108b6ffc0e72616b58c94c00eee
4
+ data.tar.gz: 4150c883baaa50b85c7f9f7619b5bde35ec5ff9e
5
5
  SHA512:
6
- metadata.gz: 3c3b97ef87dcda6dec5dce9a8d8449da8b8da3c5faab0664ab4563dfb32f4770b9295271454c6e9c2efbec2be3b72843cf12c6f2d48395e36c7474b8d6be886c
7
- data.tar.gz: 6ff01ddb162578b80b30596adfd38be3fb992509b8ff7aa32018b98815dae4e2449770313728647e9b8af0110e6a0cd4078edc1f4d01754a91a3205ceb7cd93a
6
+ metadata.gz: 755fe267a26a4091942e522f32e335cc5d17adfcd3d24a671a09d251927d40bdf7a2fc8f508f27272de8b1dd310ac160d7bf256079d7c9b44df34bb542724661
7
+ data.tar.gz: e1d04a258486962b14b0c5c1065d017a20ea09bcb15d551579a55f0db3f0a206ebe7b800ce065ca7e9ca0aff832ecb2a0d357b4390228ed7caa5931b684e4d5c
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  Numerals
2
2
  ========
3
3
 
4
+ [![Gem Version](https://badge.fury.io/rb/numerals.svg)](http://badge.fury.io/rb/numerals)
5
+ [![Build Status](https://travis-ci.org/jgoizueta/numerals.svg)](https://travis-ci.org/jgoizueta/numerals)
6
+
4
7
  The Numerals module provides formatted input/output for numeric types.
5
8
 
6
9
  ## Use
data/Rakefile CHANGED
@@ -17,3 +17,5 @@ Rake::RDocTask.new do |rdoc|
17
17
  rdoc.rdoc_files.include('README*')
18
18
  rdoc.rdoc_files.include('lib/**/*.rb')
19
19
  end
20
+
21
+ task :default => :test
@@ -11,4 +11,3 @@ require 'numerals/conversions/rational'
11
11
  require 'numerals/conversions/bigdecimal'
12
12
  require 'numerals/conversions/flt'
13
13
  require 'numerals/format'
14
- # require 'numerals/formatting/options'
@@ -1,98 +1,102 @@
1
- module Numerals::Conversions
1
+ module Numerals
2
2
 
3
- class <<self
4
- def [](type, options = nil)
5
- if type.respond_to?(:numerals_conversion)
6
- type.numerals_conversion(options || {})
3
+ module Conversions
4
+
5
+ class <<self
6
+ def [](type, options = nil)
7
+ if type.respond_to?(:numerals_conversion)
8
+ type.numerals_conversion(options || {})
9
+ end
7
10
  end
8
- end
9
11
 
10
- def order_of_magnitude(number, options={})
11
- self[number.class, options[:type_options]].order_of_magnitude(number, options)
12
- end
12
+ def order_of_magnitude(number, options={})
13
+ self[number.class, options[:type_options]].order_of_magnitude(number, options)
14
+ end
13
15
 
14
- def number_of_digits(number, options={})
15
- self[number.class, options[:type_options]].number_of_digits(number, options)
16
- end
16
+ def number_of_digits(number, options={})
17
+ self[number.class, options[:type_options]].number_of_digits(number, options)
18
+ end
17
19
 
18
- # Convert Numeral to Number
19
- #
20
- # read numeral, options={}
21
- #
22
- # If the input numeral is approximate and the destination type
23
- # allows for arbitrary precision, then the destination context
24
- # precision will be ignored and the precision of the input will be
25
- # preserved. The :simplify option affects this case by generating
26
- # only the mininimun number of digits needed.
27
- #
28
- # The :exact option will prevent this behaviour and always treat
29
- # input as exact.
30
- #
31
- # Valid output options:
32
- #
33
- # * :type class of the output number
34
- # * :context context (in the case of Flt::Num, Float) for the output
35
- # * :simplify (for approximate input numeral/arbitrary precision type only)
36
- # * :exact treat input numeral as if exact
37
- #
38
- def read(numeral, options={})
39
- selector = options[:context] || options[:type]
40
- exact_input = options[:exact]
41
- approximate_simplified = options[:simplify]
42
- conversions = self[selector, options[:type_options]]
43
- conversions.read(numeral, exact_input, approximate_simplified)
44
- end
20
+ # Convert Numeral to Number
21
+ #
22
+ # read numeral, options={}
23
+ #
24
+ # If the input numeral is approximate and the destination type
25
+ # allows for arbitrary precision, then the destination context
26
+ # precision will be ignored and the precision of the input will be
27
+ # preserved. The :simplify option affects this case by generating
28
+ # only the mininimun number of digits needed.
29
+ #
30
+ # The :exact option will prevent this behaviour and always treat
31
+ # input as exact.
32
+ #
33
+ # Valid output options:
34
+ #
35
+ # * :type class of the output number
36
+ # * :context context (in the case of Flt::Num, Float) for the output
37
+ # * :simplify (for approximate input numeral/arbitrary precision type only)
38
+ # * :exact treat input numeral as if exact
39
+ #
40
+ def read(numeral, options={})
41
+ selector = options[:context] || options[:type]
42
+ exact_input = options[:exact]
43
+ approximate_simplified = options[:simplify]
44
+ conversions = self[selector, options[:type_options]]
45
+ conversions.read(numeral, exact_input, approximate_simplified)
46
+ end
45
47
 
46
- # Convert Number to Numeral
47
- #
48
- # write number, options={}
49
- #
50
- # Valid options:
51
- #
52
- # * :rounding (a Rounding) (which defines output base as well)
53
- # * :exact (exact input indicator)
54
- #
55
- # Approximate mode:
56
- #
57
- # If the input is treated as an approximation
58
- # (which is the case for types such as Flt::Num, Float,...
59
- # unless the :exact option is true) then no 'spurious' digits
60
- # will be shown (digits that can take any value and the numeral
61
- # still would convert to the original number if rounded to the same precision)
62
- #
63
- # In approximate mode, if rounding is simplifying? (:short), the shortest representation
64
- # which rounds back to the origina number with the same precision is used.
65
- # If rounding is :free and the output base is the same as the number
66
- # internal radix, the exact precision (trailing zeros) of the number
67
- # is represented.
68
- #
69
- # Exact mode:
70
- #
71
- # Is used for 'exact' types (such as Integer, Rational) or when the :exact
72
- # option is defined to be true.
73
- #
74
- # The number is treated as an exact value, and converted according to
75
- # Rounding. (in this case the :free and :short precision roundings are
76
- # equivalent)
77
- #
78
- def write(number, options = {})
79
- output_rounding = Rounding[options[:rounding] || Rounding[]]
80
- conversion = self[number.class, options[:type_options]]
81
- exact_input = conversion.exact?(number, options)
82
- conversion.write(number, exact_input, output_rounding)
83
- end
48
+ # Convert Number to Numeral
49
+ #
50
+ # write number, options={}
51
+ #
52
+ # Valid options:
53
+ #
54
+ # * :rounding (a Rounding) (which defines output base as well)
55
+ # * :exact (exact input indicator)
56
+ #
57
+ # Approximate mode:
58
+ #
59
+ # If the input is treated as an approximation
60
+ # (which is the case for types such as Flt::Num, Float,...
61
+ # unless the :exact option is true) then no 'spurious' digits
62
+ # will be shown (digits that can take any value and the numeral
63
+ # still would convert to the original number if rounded to the same precision)
64
+ #
65
+ # In approximate mode, if rounding is simplifying? (:short), the shortest representation
66
+ # which rounds back to the origina number with the same precision is used.
67
+ # If rounding is :free and the output base is the same as the number
68
+ # internal radix, the exact precision (trailing zeros) of the number
69
+ # is represented.
70
+ #
71
+ # Exact mode:
72
+ #
73
+ # Is used for 'exact' types (such as Integer, Rational) or when the :exact
74
+ # option is defined to be true.
75
+ #
76
+ # The number is treated as an exact value, and converted according to
77
+ # Rounding. (in this case the :free and :short precision roundings are
78
+ # equivalent)
79
+ #
80
+ def write(number, options = {})
81
+ output_rounding = Rounding[options[:rounding] || Rounding[]]
82
+ conversion = self[number.class, options[:type_options]]
83
+ exact_input = conversion.exact?(number, options)
84
+ conversion.write(number, exact_input, output_rounding)
85
+ end
84
86
 
85
- def exact?(number, options = {})
86
- self[number.class, options[:type_options]].exact?(number, options)
87
- end
87
+ def exact?(number, options = {})
88
+ self[number.class, options[:type_options]].exact?(number, options)
89
+ end
88
90
 
89
- private
91
+ private
90
92
 
91
- def extract_mode_from_args!(args)
92
- if [:fixed, :free, :exact, :approximate].include?(args.first)
93
- args.shift
93
+ def extract_mode_from_args!(args)
94
+ if [:fixed, :free, :exact, :approximate].include?(args.first)
95
+ args.shift
96
+ end
94
97
  end
95
98
  end
99
+
96
100
  end
97
101
 
98
102
  end
@@ -1,40 +1,44 @@
1
1
  require 'numerals/conversions'
2
2
  require 'flt'
3
3
 
4
- # Base class for Conversions of type with context
5
- class Numerals::ContextConversion
4
+ module Numerals
6
5
 
7
- def initialize(context_or_type, options={})
8
- if Class === context_or_type && context_or_type.respond_to?(:context)
9
- @type = context_or_type
10
- @context = @type.context
11
- elsif context_or_type.respond_to?(:num_class)
12
- @context = context_or_type
13
- @type = @context.num_class
14
- else
15
- raise "Invalid Conversion definition"
6
+ # Base class for Conversions of type with context
7
+ class ContextConversion
8
+
9
+ def initialize(context_or_type, options={})
10
+ if Class === context_or_type && context_or_type.respond_to?(:context)
11
+ @type = context_or_type
12
+ @context = @type.context
13
+ elsif context_or_type.respond_to?(:num_class)
14
+ @context = context_or_type
15
+ @type = @context.num_class
16
+ else
17
+ raise "Invalid Conversion definition"
18
+ end
19
+ self.input_rounding = options[:input_rounding]
16
20
  end
17
- self.input_rounding = options[:input_rounding]
18
- end
19
21
 
20
- attr_reader :context, :type, :input_rounding
22
+ attr_reader :context, :type, :input_rounding
21
23
 
22
- def input_rounding=(rounding)
23
- if rounding
24
- if rounding == :context
25
- @input_rounding = Rounding[@context.rounding, precision: @context.precision, base: @context.radix]
26
- else
27
- rounding = Rounding[base: @context.radix].set!(rounding)
28
- if rounding.base == @context.radix
29
- @input_rounding = rounding
24
+ def input_rounding=(rounding)
25
+ if rounding
26
+ if rounding == :context
27
+ @input_rounding = Rounding[@context.rounding, precision: @context.precision, base: @context.radix]
30
28
  else
31
- # The rounding precision is not meaningful for the destination type on input
32
- @input_rounding = Rounding[rounding.mode, base: @context.radix]
29
+ rounding = Rounding[base: @context.radix].set!(rounding)
30
+ if rounding.base == @context.radix
31
+ @input_rounding = rounding
32
+ else
33
+ # The rounding precision is not meaningful for the destination type on input
34
+ @input_rounding = Rounding[rounding.mode, base: @context.radix]
35
+ end
33
36
  end
37
+ else
38
+ @input_rounding = nil
34
39
  end
35
- else
36
- @input_rounding = nil
37
40
  end
41
+
38
42
  end
39
43
 
40
44
  end
@@ -1,233 +1,237 @@
1
1
  require 'numerals/conversions/context_conversion'
2
2
 
3
- class Numerals::FltConversion < Numerals::ContextConversion
4
-
5
- # Options:
6
- #
7
- # * :input_rounding (optional, a non-exact Rounding or rounding mode)
8
- # which is used when input is approximate as the assumed rounding
9
- # mode which would be used so that the result numeral rounds back
10
- # to the input number. :context can be used to use the
11
- # numeric context as input rounding.
12
- # input_rounding is also used to round input ...
13
- #
14
- def initialize(context_or_type, options={})
15
- super
16
- end
17
-
18
- def order_of_magnitude(value, options={})
19
- base = options[:base] || 10 # value.num_class.radix
20
- if value.class.radix == base
21
- value.adjusted_exponent + 1
22
- else
23
- value.abs.log(base).floor + 1
3
+ module Numerals
4
+
5
+ class FltConversion < ContextConversion
6
+
7
+ # Options:
8
+ #
9
+ # * :input_rounding (optional, a non-exact Rounding or rounding mode)
10
+ # which is used when input is approximate as the assumed rounding
11
+ # mode which would be used so that the result numeral rounds back
12
+ # to the input number. :context can be used to use the
13
+ # numeric context as input rounding.
14
+ # input_rounding is also used to round input ...
15
+ #
16
+ def initialize(context_or_type, options={})
17
+ super
24
18
  end
25
- end
26
19
 
27
- def number_of_digits(value, options={})
28
- base = options[:base] || 10
29
- if base == @context.radix
30
- value.number_of_digits
31
- else
32
- x.class.context[precision: value.number_of_digits].necessary_digits(base)
20
+ def order_of_magnitude(value, options={})
21
+ base = options[:base] || 10 # value.num_class.radix
22
+ if value.class.radix == base
23
+ value.adjusted_exponent + 1
24
+ else
25
+ value.abs.log(base).floor + 1
26
+ end
33
27
  end
34
- end
35
-
36
- def exact?(value, options={})
37
- options[:exact]
38
- end
39
28
 
40
- # mode is either :exact or :approximate
41
- def number_to_numeral(number, mode, rounding)
42
- if number.special? # @context.special?(number)
43
- special_num_to_numeral(number)
44
- else
45
- if mode == :exact
46
- exact_num_to_numeral number, rounding
47
- else # mode == :approximate
48
- approximate_num_to_numeral(number, rounding)
29
+ def number_of_digits(value, options={})
30
+ base = options[:base] || 10
31
+ if base == @context.radix
32
+ value.number_of_digits
33
+ else
34
+ x.class.context[precision: value.number_of_digits].necessary_digits(base)
49
35
  end
50
36
  end
51
- end
52
37
 
53
- def numeral_to_number(numeral, mode)
54
- if numeral.special?
55
- special_numeral_to_num numeral
56
- elsif mode == :fixed
57
- fixed_numeral_to_num numeral
58
- else # mode == :free
59
- free_numeral_to_num numeral
38
+ def exact?(value, options={})
39
+ options[:exact]
60
40
  end
61
- end
62
-
63
- def write(number, exact_input, output_rounding)
64
- output_base = output_rounding.base
65
- input_base = @context.radix
66
41
 
67
- if number.special? # @context.special?(number)
68
- special_num_to_numeral number
69
- elsif exact_input
70
- if output_base == input_base && output_rounding.free?
71
- # akin to number.format(base: output_base, simplified: true)
72
- general_num_to_numeral number, output_rounding, false
42
+ # mode is either :exact or :approximate
43
+ def number_to_numeral(number, mode, rounding)
44
+ if number.special? # @context.special?(number)
45
+ special_num_to_numeral(number)
73
46
  else
74
- # akin to number.format(base: output_base, exact: true)
75
- exact_num_to_numeral number, output_rounding
47
+ if mode == :exact
48
+ exact_num_to_numeral number, rounding
49
+ else # mode == :approximate
50
+ approximate_num_to_numeral(number, rounding)
51
+ end
76
52
  end
77
- else
78
- if output_base == input_base && output_rounding.preserving?
79
- # akin to number.format(base: output_base)
80
- Numeral.from_coefficient_scale(
81
- number.sign*number.coefficient, number.integral_exponent,
82
- approximate: true, base: output_base
83
- )
84
- elsif output_rounding.simplifying?
85
- # akin to number.forma(base: output_base, simplify: true)
86
- general_num_to_numeral number, output_rounding, false
53
+ end
54
+
55
+ def numeral_to_number(numeral, mode)
56
+ if numeral.special?
57
+ special_numeral_to_num numeral
58
+ elsif mode == :fixed
59
+ fixed_numeral_to_num numeral
60
+ else # mode == :free
61
+ free_numeral_to_num numeral
62
+ end
63
+ end
64
+
65
+ def write(number, exact_input, output_rounding)
66
+ output_base = output_rounding.base
67
+ input_base = @context.radix
68
+
69
+ if number.special? # @context.special?(number)
70
+ special_num_to_numeral number
71
+ elsif exact_input
72
+ if output_base == input_base && output_rounding.free?
73
+ # akin to number.format(base: output_base, simplified: true)
74
+ general_num_to_numeral number, output_rounding, false
75
+ else
76
+ # akin to number.format(base: output_base, exact: true)
77
+ exact_num_to_numeral number, output_rounding
78
+ end
87
79
  else
88
- # akin to number.forma(base: output_base, all_digits: true)
89
- general_num_to_numeral number, output_rounding, true
80
+ if output_base == input_base && output_rounding.preserving?
81
+ # akin to number.format(base: output_base)
82
+ Numeral.from_coefficient_scale(
83
+ number.sign*number.coefficient, number.integral_exponent,
84
+ approximate: true, base: output_base
85
+ )
86
+ elsif output_rounding.simplifying?
87
+ # akin to number.forma(base: output_base, simplify: true)
88
+ general_num_to_numeral number, output_rounding, false
89
+ else
90
+ # akin to number.forma(base: output_base, all_digits: true)
91
+ general_num_to_numeral number, output_rounding, true
92
+ end
90
93
  end
91
94
  end
92
- end
93
95
 
94
- def read(numeral, exact_input, approximate_simplified)
95
- if numeral.special?
96
- special_numeral_to_num numeral
97
- elsif numeral.approximate? && !exact_input
98
- if approximate_simplified
99
- # akin to @context.Num(numeral_text, :short)
100
- short_numeral_to_num numeral
96
+ def read(numeral, exact_input, approximate_simplified)
97
+ if numeral.special?
98
+ special_numeral_to_num numeral
99
+ elsif numeral.approximate? && !exact_input
100
+ if approximate_simplified
101
+ # akin to @context.Num(numeral_text, :short)
102
+ short_numeral_to_num numeral
103
+ else
104
+ # akin to @context.Num(numeral_text, :free)
105
+ free_numeral_to_num numeral
106
+ end
101
107
  else
102
- # akin to @context.Num(numeral_text, :free)
103
- free_numeral_to_num numeral
108
+ # akin to @context.Num(numeral_text, :fixed)
109
+ fixed_numeral_to_num numeral
104
110
  end
105
- else
106
- # akin to @context.Num(numeral_text, :fixed)
107
- fixed_numeral_to_num numeral
108
111
  end
109
- end
110
112
 
111
- private
113
+ private
112
114
 
113
- def special_num_to_numeral(x)
114
- if x.nan?
115
- Numeral.nan
116
- elsif x.infinite?
117
- Numeral.infinity @context.sign(x)
115
+ def special_num_to_numeral(x)
116
+ if x.nan?
117
+ Numeral.nan
118
+ elsif x.infinite?
119
+ Numeral.infinity @context.sign(x)
120
+ end
118
121
  end
119
- end
120
122
 
121
- def exact_num_to_numeral(number, rounding)
122
- quotient = number.to_r
123
- numeral = Numerals::Numeral.from_quotient(quotient, base: rounding.base)
124
- unless rounding.free?
125
- numeral = rounding.round(numeral)
123
+ def exact_num_to_numeral(number, rounding)
124
+ quotient = number.to_r
125
+ numeral = Numerals::Numeral.from_quotient(quotient, base: rounding.base)
126
+ unless rounding.free?
127
+ numeral = rounding.round(numeral)
128
+ end
129
+ numeral
126
130
  end
127
- numeral
128
- end
129
131
 
130
- def approximate_num_to_numeral(number, rounding)
131
- all_digits = !rounding.free?
132
- general_num_to_numeral(number, rounding, all_digits)
133
- end
132
+ def approximate_num_to_numeral(number, rounding)
133
+ all_digits = !rounding.free?
134
+ general_num_to_numeral(number, rounding, all_digits)
135
+ end
134
136
 
135
- def general_num_to_numeral(x, rounding, all_digits)
136
- sign, coefficient, exponent = x.split # @context.split(x)
137
- precision = x.number_of_digits
138
- output_base = rounding.base
137
+ def general_num_to_numeral(x, rounding, all_digits)
138
+ sign, coefficient, exponent = x.split # @context.split(x)
139
+ precision = x.number_of_digits
140
+ output_base = rounding.base
139
141
 
140
- # here rounding_mode is not the output rounding mode, but the rounding mode used for input
141
- rounding_mode = (@input_rounding || rounding).mode
142
+ # here rounding_mode is not the output rounding mode, but the rounding mode used for input
143
+ rounding_mode = (@input_rounding || rounding).mode
142
144
 
143
- formatter = Flt::Support::Formatter.new(
144
- @context.radix, @context.etiny, output_base, raise_on_repeat: false
145
- )
146
- formatter.format(
147
- x, coefficient, exponent, rounding_mode, precision, all_digits
148
- )
145
+ formatter = Flt::Support::Formatter.new(
146
+ @context.radix, @context.etiny, output_base, raise_on_repeat: false
147
+ )
148
+ formatter.format(
149
+ x, coefficient, exponent, rounding_mode, precision, all_digits
150
+ )
149
151
 
150
- dec_pos, digits = formatter.digits
151
- rep_pos = formatter.repeat
152
+ dec_pos, digits = formatter.digits
153
+ rep_pos = formatter.repeat
152
154
 
153
- normalization = :approximate
155
+ normalization = :approximate
154
156
 
155
- numeral = Numerals::Numeral[digits, sign: sign, point: dec_pos, rep_pos: formatter.repeat, base: output_base, normalize: normalization]
157
+ numeral = Numerals::Numeral[digits, sign: sign, point: dec_pos, rep_pos: formatter.repeat, base: output_base, normalize: normalization]
156
158
 
157
- numeral = rounding.round(numeral, round_up: formatter.round_up)
159
+ numeral = rounding.round(numeral, round_up: formatter.round_up)
158
160
 
159
- numeral
160
- end
161
-
162
- def special_numeral_to_num(numeral)
163
- case numeral.special
164
- when :nan
165
- @context.nan
166
- when :inf
167
- @context.infinity numeral.sign
161
+ numeral
168
162
  end
169
- end
170
163
 
171
- def fixed_numeral_to_num(numeral)
172
- # consider:
173
- # return exact_numeral_to_num(numeral) if numeral.exact?
174
- if numeral.base == @context.radix
175
- unless @context.exact?
176
- rounding = Rounding[@context.rounding, precision: @context.precision, base: @context.radix]
177
- numeral = rounding.round(numeral)
164
+ def special_numeral_to_num(numeral)
165
+ case numeral.special
166
+ when :nan
167
+ @context.nan
168
+ when :inf
169
+ @context.infinity numeral.sign
178
170
  end
179
- same_base_numeral_to_num numeral
180
- else
181
- if numeral.repeating? # numeral.exact?
182
- exact_numeral_to_num(numeral)
171
+ end
172
+
173
+ def fixed_numeral_to_num(numeral)
174
+ # consider:
175
+ # return exact_numeral_to_num(numeral) if numeral.exact?
176
+ if numeral.base == @context.radix
177
+ unless @context.exact?
178
+ rounding = Rounding[@context.rounding, precision: @context.precision, base: @context.radix]
179
+ numeral = rounding.round(numeral)
180
+ end
181
+ same_base_numeral_to_num numeral
183
182
  else
184
- general_numeral_to_num numeral, :fixed
183
+ if numeral.repeating? # numeral.exact?
184
+ exact_numeral_to_num(numeral)
185
+ else
186
+ general_numeral_to_num numeral, :fixed
187
+ end
185
188
  end
186
189
  end
187
- end
188
-
189
- def same_base_numeral_to_num(numeral)
190
- sign, coefficient, scale = numeral.split
191
- @context.Num sign, coefficient, scale
192
- end
193
-
194
- def exact_numeral_to_num(numeral)
195
- @context.Num Rational(*numeral.to_quotient), :fixed
196
- end
197
190
 
198
- def free_numeral_to_num(numeral)
199
- if numeral.base == @context.radix
200
- same_base_numeral_to_num numeral
201
- else
202
- general_numeral_to_num numeral, :free
191
+ def same_base_numeral_to_num(numeral)
192
+ sign, coefficient, scale = numeral.split
193
+ @context.Num sign, coefficient, scale
203
194
  end
204
- end
205
195
 
206
- def short_numeral_to_num(numeral)
207
- general_numeral_to_num numeral, :short
208
- end
196
+ def exact_numeral_to_num(numeral)
197
+ @context.Num Rational(*numeral.to_quotient), :fixed
198
+ end
209
199
 
210
- def general_numeral_to_num(numeral, mode)
211
- sign, coefficient, scale = numeral.split
212
- reader = Flt::Support::Reader.new(mode: mode)
213
- if @input_rounding
214
- rounding_mode = @input_rounding.mode
215
- else
216
- rounding_Mode = @context.rounding
200
+ def free_numeral_to_num(numeral)
201
+ if numeral.base == @context.radix
202
+ same_base_numeral_to_num numeral
203
+ else
204
+ general_numeral_to_num numeral, :free
205
+ end
217
206
  end
218
- reader.read(@context, rounding_mode, sign, coefficient, scale, numeral.base).tap do
219
- # @exact = reader.exact?
207
+
208
+ def short_numeral_to_num(numeral)
209
+ general_numeral_to_num numeral, :short
220
210
  end
221
- end
222
211
 
223
- end
212
+ def general_numeral_to_num(numeral, mode)
213
+ sign, coefficient, scale = numeral.split
214
+ reader = Flt::Support::Reader.new(mode: mode)
215
+ if @input_rounding
216
+ rounding_mode = @input_rounding.mode
217
+ else
218
+ rounding_Mode = @context.rounding
219
+ end
220
+ reader.read(@context, rounding_mode, sign, coefficient, scale, numeral.base).tap do
221
+ # @exact = reader.exact?
222
+ end
223
+ end
224
224
 
225
- def (Flt::Num).numerals_conversion(options = {})
226
- Numerals::FltConversion.new(self, options)
227
- end
225
+ end
228
226
 
229
- class Flt::Num::ContextBase
230
- def numerals_conversion(options = {})
227
+ def (Flt::Num).numerals_conversion(options = {})
231
228
  Numerals::FltConversion.new(self, options)
232
229
  end
230
+
231
+ class Flt::Num::ContextBase
232
+ def numerals_conversion(options = {})
233
+ Numerals::FltConversion.new(self, options)
234
+ end
235
+ end
236
+
233
237
  end
@@ -144,9 +144,9 @@ module Numerals
144
144
  end
145
145
 
146
146
  # Convert base digits to scaled base digits
147
- def self.ugrouped_digits(digits, base, base_scale)
147
+ def self.ungrouped_digits(digits, base, base_scale)
148
148
  digits.flat_map { |d|
149
- group = Numeral::Digits[base: base]
149
+ group = Digits[base: base]
150
150
  group.value = d
151
151
  ungrouped = group.digits_array
152
152
  if ungrouped.size < base_scale
@@ -104,7 +104,7 @@ module Numerals
104
104
 
105
105
  if @mode.base_scale > 1
106
106
  # De-scale the significand base
107
- digits = Format::BaseScaler.ugrouped_digits(digits, base, @mode.base_scale)
107
+ digits = Format::BaseScaler.ungrouped_digits(digits, base, @mode.base_scale)
108
108
  point *= @mode.base_scale
109
109
  repeat *= @mode.base_scale if repeat
110
110
  end
@@ -34,7 +34,7 @@ module Numerals
34
34
  else
35
35
  # show base suffix as a subscript
36
36
  subscript = format.symbols.base_suffix || base.to_s
37
- º output << "<sub>#{subscript}</sub>"
37
+ output << "<sub>#{subscript}</sub>"
38
38
  end
39
39
  end
40
40
  if text_parts.exponent_value != 0 || format.mode.mode == :scientific
@@ -1,3 +1,3 @@
1
1
  module Numerals
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -1,10 +1,11 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
2
 
3
3
  require 'numerals'
4
- include Numerals
5
4
 
6
5
  class TestBaseScaler < Test::Unit::TestCase # < Minitest::Test
7
6
 
7
+ include Numerals
8
+
8
9
  def digits_string(part, base)
9
10
  part.map{|d| d.to_s(base)}.join
10
11
  end
@@ -2,10 +2,10 @@ require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
2
 
3
3
  require 'numerals'
4
4
  require 'flt/bigdecimal'
5
- include Numerals
6
5
 
7
6
  class TestBigConversions < Test::Unit::TestCase # < Minitest::Test
8
7
 
8
+ include Numerals
9
9
 
10
10
  def test_write_special
11
11
  context = BigDecimal.context
@@ -2,11 +2,12 @@
2
2
 
3
3
  require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
4
4
  require 'test/unit'
5
- include Numerals
6
5
  require 'yaml'
7
6
 
8
7
  class TestDigitsDefinition < Test::Unit::TestCase
9
8
 
9
+ include Numerals
10
+
10
11
  DEFAULT_DIGITS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
11
12
  MAX_TEST_BASE = DEFAULT_DIGITS.size
12
13
 
@@ -1,10 +1,11 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
2
 
3
3
  require 'numerals'
4
- include Numerals
5
4
 
6
5
  class TestExpSetter < Test::Unit::TestCase # < Minitest::Test
7
6
 
7
+ include Numerals
8
+
8
9
  def check_setter(numeral, n=nil)
9
10
  adjust = Format::ExpSetter[numeral]
10
11
  adjust.integer_part_size = n if n
@@ -1,10 +1,10 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
2
 
3
3
  require 'numerals'
4
- include Numerals
5
4
 
6
5
  class TestFloatConversions < Test::Unit::TestCase # < Minitest::Test
7
6
 
7
+ include Numerals
8
8
 
9
9
  def test_write_special
10
10
  assert_equal Numeral.nan, Conversions.write(Float.context.nan)
@@ -1,10 +1,11 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
2
 
3
3
  require 'numerals'
4
- include Numerals
5
4
 
6
5
  class TestFltConversions < Test::Unit::TestCase # < Minitest::Test
7
6
 
7
+ include Numerals
8
+
8
9
  def test_write_special_binary
9
10
  context = Flt::BinNum.context = Flt::BinNum::FloatContext
10
11
  type = Flt::BinNum
@@ -1,9 +1,10 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
- include Numerals
3
2
  require 'yaml'
4
3
 
5
4
  class TestFormat < Test::Unit::TestCase # < Minitest::Test
6
5
 
6
+ include Numerals
7
+
7
8
  def test_mutated_copy
8
9
  f1 = Format[Rounding[precision: 3, base: 2]]
9
10
 
@@ -1,9 +1,10 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
- include Numerals
3
2
  require 'yaml'
4
3
 
5
4
  class TestFormatInput < Test::Unit::TestCase # < Minitest::Test
6
5
 
6
+ include Numerals
7
+
7
8
  def assert_same_flt(x, y)
8
9
  assert_equal x.class, y.class, x.to_s
9
10
  assert_equal x.split, y.split, x.to_s
@@ -1,10 +1,11 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
2
 
3
3
  require 'numerals/rounding'
4
- include Numerals
5
4
 
6
5
  class TestFormatMode < Test::Unit::TestCase # < Minitest::Test
7
6
 
7
+ include Numerals
8
+
8
9
  def test_format_mode_constructor
9
10
  mode = Format::Mode[:scientific]
10
11
  assert mode.scientific?
@@ -1,10 +1,11 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
- include Numerals
3
2
  require 'yaml'
4
3
  require 'tempfile'
5
4
 
6
5
  class TestFormatOutput < Test::Unit::TestCase # < Minitest::Test
7
6
 
7
+ include Numerals
8
+
8
9
  def test_write_float_dec
9
10
  assert_equal '1', Format[rounding: :short].write(1.0)
10
11
  assert_equal '1', Format[].write(1.0)
@@ -1,10 +1,11 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
2
 
3
3
  require 'numerals'
4
- include Numerals
5
4
 
6
5
  class TestIntegerConversions < Test::Unit::TestCase # < Minitest::Test
7
6
 
7
+ include Numerals
8
+
8
9
  def test_read_special
9
10
  assert_raise(ZeroDivisionError){ Conversions.read(Numeral.nan, type: Integer) }
10
11
  assert_raise(ZeroDivisionError){ Conversions.read(Numeral.infinity, type: Integer) }
@@ -1,9 +1,10 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
- include Numerals
3
2
  require 'yaml'
4
3
 
5
4
  class TestNumeral < Test::Unit::TestCase # < Minitest::Test
6
5
 
6
+ include Numerals
7
+
7
8
  def test_numeral_reference_constructors
8
9
  # We'll use this forms as reference for comparisons:
9
10
  # Numeral[digits, base: ..., point: ... , repeat: ...]
@@ -0,0 +1,13 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
+
3
+ class TestQualified < Test::Unit::TestCase # < Minitest::Test
4
+
5
+ def test_qualified_use
6
+ assert_equal '1', Numerals::Format[].write(1.0)
7
+ assert_equal '1.00', Numerals::Format[Numerals::Rounding[precision: 3]].write(1.0)
8
+ assert_equal '1.000', Numerals::Format[Numerals::Rounding[places: 3]].write(1.0)
9
+ assert_equal '1234567.1234', Numerals::Format[rounding: :short].write(1234567.1234)
10
+ assert_equal '1234567.123', Numerals::Format[Numerals::Rounding[places: 3]].write(1234567.1234)
11
+ end
12
+
13
+ end
@@ -1,10 +1,11 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
2
 
3
3
  require 'numerals'
4
- include Numerals
5
4
 
6
5
  class TestRationalConversions < Test::Unit::TestCase # < Minitest::Test
7
6
 
7
+ include Numerals
8
+
8
9
  def test_read_special
9
10
  assert_raise(ZeroDivisionError){ Conversions.read(Numeral.nan, type: Rational) }
10
11
  assert_raise(ZeroDivisionError){ Conversions.read(Numeral.infinity, type: Rational) }
@@ -1,10 +1,11 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
2
 
3
3
  require 'numerals'
4
- include Numerals
5
4
 
6
5
  class TestRepeatDetector < Test::Unit::TestCase # < Minitest::Test
7
6
 
7
+ include Numerals
8
+
8
9
  def test_repeat_detector
9
10
 
10
11
  assert_equal(
@@ -1,10 +1,11 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
2
 
3
3
  require 'numerals/rounding'
4
- include Numerals
5
4
 
6
5
  class TestRounding < Test::Unit::TestCase # < Minitest::Test
7
6
 
7
+ include Numerals
8
+
8
9
  def test_rounding
9
10
  r = Rounding[:half_even, places: 0]
10
11
  assert_equal Numeral[1,0,0, point: 3, normalize: :approximate], r.round(Numeral[1,0,0,5, point: 3])
@@ -1,10 +1,11 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
2
2
 
3
3
  require 'numerals/rounding'
4
- include Numerals
5
4
 
6
5
  class TestSymbols < Test::Unit::TestCase # < Minitest::Test
7
6
 
7
+ include Numerals
8
+
8
9
  def test_symbols
9
10
  s = Format::Symbols[show_plus: false]
10
11
  s2 = s[uppercase: true]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: numerals
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Javier Goizueta
@@ -123,6 +123,7 @@ files:
123
123
  - test/test_format_output.rb
124
124
  - test/test_integer_conversions.rb
125
125
  - test/test_numeral.rb
126
+ - test/test_qualified.rb
126
127
  - test/test_rational_conversions.rb
127
128
  - test/test_repeat_detector.rb
128
129
  - test/test_rounding.rb
@@ -166,6 +167,7 @@ test_files:
166
167
  - test/test_format_output.rb
167
168
  - test/test_integer_conversions.rb
168
169
  - test/test_numeral.rb
170
+ - test/test_qualified.rb
169
171
  - test/test_rational_conversions.rb
170
172
  - test/test_repeat_detector.rb
171
173
  - test/test_rounding.rb