numerals 0.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +149 -5
- data/lib/numerals/conversions/bigdecimal.rb +209 -9
- data/lib/numerals/conversions/context_conversion.rb +40 -0
- data/lib/numerals/conversions/float.rb +106 -71
- data/lib/numerals/conversions/flt.rb +115 -44
- data/lib/numerals/conversions/integer.rb +32 -3
- data/lib/numerals/conversions/rational.rb +27 -3
- data/lib/numerals/conversions.rb +74 -33
- data/lib/numerals/digits.rb +8 -5
- data/lib/numerals/format/base_scaler.rb +160 -0
- data/lib/numerals/format/exp_setter.rb +218 -0
- data/lib/numerals/format/format.rb +257 -0
- data/lib/numerals/format/input.rb +140 -0
- data/lib/numerals/format/mode.rb +157 -0
- data/lib/numerals/format/notation.rb +51 -0
- data/lib/numerals/format/notations/html.rb +53 -0
- data/lib/numerals/format/notations/latex.rb +48 -0
- data/lib/numerals/format/notations/text.rb +141 -0
- data/lib/numerals/format/output.rb +167 -0
- data/lib/numerals/format/symbols.rb +565 -0
- data/lib/numerals/format/text_parts.rb +35 -0
- data/lib/numerals/format.rb +25 -0
- data/lib/numerals/formatting_aspect.rb +36 -0
- data/lib/numerals/numeral.rb +34 -21
- data/lib/numerals/repeat_detector.rb +99 -0
- data/lib/numerals/rounding.rb +340 -181
- data/lib/numerals/version.rb +1 -1
- data/lib/numerals.rb +4 -2
- data/numerals.gemspec +1 -1
- data/test/test_base_scaler.rb +189 -0
- data/test/test_big_conversions.rb +105 -0
- data/test/test_digits_definition.rb +23 -28
- data/test/test_exp_setter.rb +732 -0
- data/test/test_float_conversions.rb +48 -30
- data/test/test_flt_conversions.rb +476 -80
- data/test/test_format.rb +124 -0
- data/test/test_format_input.rb +226 -0
- data/test/test_format_mode.rb +124 -0
- data/test/test_format_output.rb +789 -0
- data/test/test_integer_conversions.rb +22 -22
- data/test/test_numeral.rb +35 -0
- data/test/test_rational_conversions.rb +28 -28
- data/test/test_repeat_detector.rb +72 -0
- data/test/test_rounding.rb +158 -0
- data/test/test_symbols.rb +32 -0
- metadata +38 -5
- data/lib/numerals/formatting/digits_definition.rb +0 -75
data/lib/numerals/rounding.rb
CHANGED
@@ -1,229 +1,388 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
1
|
+
module Numerals
|
2
|
+
|
3
|
+
# Rounding of Numerals
|
4
|
+
class Rounding < FormattingAspect
|
5
|
+
|
6
|
+
# Rounding defines a rounding mode and a precision,
|
7
|
+
# and is used to establish the desired accuracy of a Numeral result.
|
8
|
+
#
|
9
|
+
# Rounding also defines the base of the numerals to be rounded,
|
10
|
+
# which is 10 by default.
|
11
|
+
#
|
12
|
+
# The rounding mode is the rule used to limit
|
13
|
+
# the precision of a numeral; the rounding modes available are those
|
14
|
+
# of Flt::Num, namely:
|
15
|
+
#
|
16
|
+
# * :half_even
|
17
|
+
# * :half_up
|
18
|
+
# * :half_down
|
19
|
+
# * :ceiling
|
20
|
+
# * :floor
|
21
|
+
# * :up
|
22
|
+
# * :down
|
23
|
+
# * :up05
|
24
|
+
#
|
25
|
+
# Regarding the rounding precision there are two types of Roundings:
|
26
|
+
#
|
27
|
+
# * Fixed (limited) precision: the precision of the rounded result is either
|
28
|
+
# defined as relative (number of significant digits defined by the
|
29
|
+
# precision property) or absolute (number of fractional places
|
30
|
+
# --decimals for base 10-- defined by the places property)
|
31
|
+
# * Free (unlimited) precision, which preserves the value of
|
32
|
+
# the input numeral. As much precision as needed is used to keep
|
33
|
+
# unambiguously the original value. When applied to exact input,
|
34
|
+
# this kind of rounding doesn't perform any rounding.
|
35
|
+
# For approximate input there are two variants:
|
36
|
+
# - Preserving the original value precision, which produces and
|
37
|
+
# approximate output. (All original digits are preserved;
|
38
|
+
# full precision mode). This is the default free precision mode,
|
39
|
+
# established by using the :free symbol for the precision
|
40
|
+
# (or its synonym :preserve).
|
41
|
+
# - Simplifiying or reducing the result to produce an exact output
|
42
|
+
# without unneeded digits to restore the original value within its
|
43
|
+
# original precision (e.g. traling zeros are not keep).
|
44
|
+
# This case can be defined with the :short symbol for the precision
|
45
|
+
# (or its synonum :simplify).
|
46
|
+
#
|
47
|
+
def initialize(*args)
|
48
|
+
DEFAULTS.each do |param, value|
|
49
|
+
instance_variable_set "@#{param}", value
|
32
50
|
end
|
51
|
+
set! *args
|
33
52
|
end
|
34
|
-
assign! options
|
35
|
-
end
|
36
53
|
|
37
|
-
|
54
|
+
DEFAULTS = {
|
55
|
+
mode: :half_even,
|
56
|
+
precision: :short,
|
57
|
+
places: nil,
|
58
|
+
base: 10
|
59
|
+
}
|
38
60
|
|
39
|
-
|
40
|
-
include ModalSupport::StateEquivalent
|
61
|
+
attr_reader :mode, :base
|
41
62
|
|
42
|
-
|
43
|
-
assign! options
|
44
|
-
end
|
63
|
+
include ModalSupport::StateEquivalent
|
45
64
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
65
|
+
set do |*args|
|
66
|
+
options = extract_options(*args)
|
67
|
+
options.each do |option, value|
|
68
|
+
send :"#{option}=", value
|
69
|
+
end
|
70
|
+
end
|
51
71
|
|
52
|
-
|
53
|
-
@
|
54
|
-
@mode = :exact
|
55
|
-
else
|
56
|
-
@mode ||= :half_even
|
72
|
+
def base=(v)
|
73
|
+
@base = v
|
57
74
|
end
|
58
|
-
|
59
|
-
|
60
|
-
@
|
75
|
+
|
76
|
+
def mode=(mode)
|
77
|
+
@mode = mode
|
61
78
|
end
|
62
|
-
@base ||= 10
|
63
|
-
self
|
64
|
-
end
|
65
79
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
{ mode: @mode, precision: @precision }
|
71
|
-
elsif absolute?
|
72
|
-
{ mode: @mode, places: @places }
|
80
|
+
def precision=(v)
|
81
|
+
@precision = v
|
82
|
+
@precision = :simplify if v == 0
|
83
|
+
@places = nil if @precision
|
73
84
|
end
|
74
|
-
end
|
75
85
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
elsif relative?
|
80
|
-
"Rounding[#{@mode.inspect}, precision: #{@precision}]"
|
81
|
-
elsif absolute?
|
82
|
-
"Rounding[#{@mode.inspect}, places: #{@places}]"
|
86
|
+
def places=(v)
|
87
|
+
@places = v
|
88
|
+
@precision = nil if @places
|
83
89
|
end
|
84
|
-
end
|
85
90
|
|
86
|
-
|
87
|
-
|
88
|
-
|
91
|
+
def parameters
|
92
|
+
if @precision
|
93
|
+
{ mode: @mode, precision: @precision, base: @base }
|
94
|
+
else
|
95
|
+
{ mode: @mode, places: @places, base: @base }
|
96
|
+
end
|
97
|
+
end
|
89
98
|
|
90
|
-
|
91
|
-
|
92
|
-
|
99
|
+
def to_s
|
100
|
+
params = parameters
|
101
|
+
DEFAULTS.each do |param, default|
|
102
|
+
params.delete param if params[param] == default
|
103
|
+
end
|
104
|
+
"Rounding[#{params.inspect.unwrap('{}')}]"
|
105
|
+
end
|
93
106
|
|
94
|
-
|
95
|
-
|
96
|
-
|
107
|
+
def inspect
|
108
|
+
to_s
|
109
|
+
end
|
97
110
|
|
98
|
-
|
99
|
-
|
100
|
-
|
111
|
+
# Returns true if the Rounding is of free (unlimited) precision,
|
112
|
+
# which can be either :free (preserving) or :short (simplifying)
|
113
|
+
# regarding approximate input.
|
114
|
+
def free? # unlimited? exact? all? nonrounding? free?
|
115
|
+
[:free, :short].include?(@precision)
|
116
|
+
end
|
101
117
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
@precision
|
106
|
-
else
|
107
|
-
@places + num_integral_digits(value)
|
118
|
+
# Returns true if the Rounding is of fixed (limited) precision.
|
119
|
+
def fixed? # limited? approximate? rounding? fixed?
|
120
|
+
!free?
|
108
121
|
end
|
109
|
-
end
|
110
122
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
@precision - num_integral_digits(value)
|
123
|
+
# Returns true if the Rounding is of fixed precision defined
|
124
|
+
# as a number of fractional places, i.e. independently of the
|
125
|
+
# number to be rounded's magnitude.
|
126
|
+
def absolute?
|
127
|
+
@precision.nil? # fixed? && @precision # !@places.nil?
|
117
128
|
end
|
118
|
-
end
|
119
129
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
# * :tie if the first discarded was half the base and there where no more nonzero digits,
|
127
|
-
# i.e. the original value was a 'tie', exactly halfway between the truncated value
|
128
|
-
# and the next value with the same number of digits.
|
129
|
-
# * :hi if the original value was above the tie value.
|
130
|
-
def round(numeral, options={})
|
131
|
-
round_up = options[:round_up]
|
132
|
-
numeral, round_up = truncate(numeral, round_up)
|
133
|
-
adjust(numeral, round_up)
|
134
|
-
end
|
130
|
+
# Returns true if the Rounding is of fixed precision defined
|
131
|
+
# as a number of significant digits (precision attribute),
|
132
|
+
# i.e. in relation to the number to be rounded's magnitude.
|
133
|
+
def relative?
|
134
|
+
fixed? && !absolute?
|
135
|
+
end
|
135
136
|
|
136
|
-
|
137
|
+
# Returns true if the Rounding is of free precision and
|
138
|
+
# the behaviour for approximate numbers is producing a
|
139
|
+
# simplified (short) result with only the needed digits
|
140
|
+
# to restore the original value within its precision.
|
141
|
+
def simplifying?
|
142
|
+
@precision == :short
|
143
|
+
end
|
137
144
|
|
138
|
-
|
139
|
-
|
140
|
-
|
145
|
+
def short?
|
146
|
+
simplifying?
|
147
|
+
end
|
148
|
+
|
149
|
+
# Returns true if the Rounding is of free precision and
|
150
|
+
# the behaviour for approximate numbers is to keep its
|
151
|
+
# original precision (so it may include trailing zeros)
|
152
|
+
# and the result of rounding will be an approximate numeral.
|
153
|
+
def preserving?
|
154
|
+
@precision == :free
|
155
|
+
end
|
156
|
+
|
157
|
+
def full?
|
158
|
+
preserving?
|
141
159
|
end
|
142
|
-
end
|
143
160
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
else
|
153
|
-
n = precision(numeral)
|
154
|
-
unless n==numeral.digits.size && numeral.approximate?
|
155
|
-
if n < numeral.digits.size - 1
|
156
|
-
rest_digits = numeral.digits[n+1..-1]
|
161
|
+
# Number of significant digits for a given numerical/numeral value.
|
162
|
+
# If no value is passed, the :precision property is returned.
|
163
|
+
def precision(value = nil, options = {})
|
164
|
+
if value.nil?
|
165
|
+
@precision
|
166
|
+
elsif free?
|
167
|
+
if is_exact?(value, options)
|
168
|
+
0
|
157
169
|
else
|
158
|
-
|
170
|
+
num_digits(value, options)
|
159
171
|
end
|
160
|
-
|
161
|
-
|
172
|
+
else # fixed?
|
173
|
+
if absolute?
|
174
|
+
@places + num_integral_digits(value)
|
175
|
+
else # relative?
|
176
|
+
@precision
|
162
177
|
end
|
163
|
-
|
164
|
-
|
165
|
-
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# Number of fractional places for a given numerical/numeral value
|
182
|
+
# If no value is passed, the :places property is returned.
|
183
|
+
def places(value = nil, options = {})
|
184
|
+
if value.nil?
|
185
|
+
@places
|
186
|
+
elsif is_exact?(value, options)
|
187
|
+
@places || 0
|
188
|
+
elsif free?
|
189
|
+
num_digits(value, options) - num_integral_digits(value)
|
190
|
+
else # fixed?
|
191
|
+
if absolute?
|
192
|
+
@places
|
193
|
+
else # relative?
|
194
|
+
@precision - num_integral_digits(value)
|
166
195
|
end
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# Round a numeral. If the numeral has been truncated
|
200
|
+
# the :round_up option must be used to pass the information
|
201
|
+
# about the discarded digits:
|
202
|
+
# * nil if all discarded digits where 0 (the truncated value is exact)
|
203
|
+
# * :lo if there where non-zero discarded digits, but the first discarded digit
|
204
|
+
# is below half the base.
|
205
|
+
# * :tie if the first discarded was half the base and there where no more nonzero digits,
|
206
|
+
# i.e. the original value was a 'tie', exactly halfway between the truncated value
|
207
|
+
# and the next value with the same number of digits.
|
208
|
+
# * :hi if the original value was above the tie value.
|
209
|
+
def round(numeral, options={})
|
210
|
+
round_up = options[:round_up]
|
211
|
+
numeral, round_up = truncate(numeral, round_up)
|
212
|
+
if numeral.exact?
|
213
|
+
numeral
|
214
|
+
else
|
215
|
+
adjust(numeral, round_up)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
# Note: since Rounding has no mutable attributes, default dup is OK
|
220
|
+
# otherwise we'd need to redefine it:
|
221
|
+
# def dup
|
222
|
+
# Rounding[parameters]
|
223
|
+
# end
|
224
|
+
|
225
|
+
private
|
226
|
+
|
227
|
+
def check_base(numeral)
|
228
|
+
if numeral.base != @base
|
229
|
+
raise "Invalid Numeral (base #{numeral.base}) for a base #{@base} Rounding"
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
# Truncate a numeral and return also a round_up value with information about
|
234
|
+
# the digits beyond the truncation point that can be used to round the truncated
|
235
|
+
# numeral. If the numeral has already been truncated, the round_up result of
|
236
|
+
# that prior truncation should be passed as the second argument.
|
237
|
+
|
238
|
+
|
239
|
+
def truncate(numeral, round_up=nil)
|
240
|
+
check_base numeral
|
241
|
+
unless simplifying? # TODO: could simplify this just skiping on free?
|
242
|
+
n = precision(numeral)
|
243
|
+
if n == 0
|
244
|
+
return numeral if numeral.repeating? # or rails inexact...
|
245
|
+
n = numeral.digits.size
|
172
246
|
end
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
247
|
+
unless n >= numeral.digits.size && numeral.approximate?
|
248
|
+
if n < numeral.digits.size - 1
|
249
|
+
rest_digits = numeral.digits[n+1..-1]
|
250
|
+
else
|
251
|
+
rest_digits = []
|
177
252
|
end
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
253
|
+
if numeral.repeating? && numeral.repeat < numeral.digits.size && n >= numeral.repeat
|
254
|
+
rest_digits += numeral.digits[numeral.repeat..-1]
|
255
|
+
end
|
256
|
+
digits = numeral.digits[0, n]
|
257
|
+
if digits.size < n
|
258
|
+
digits += (digits.size...n).map{|i| numeral.digit_value_at(i)}
|
259
|
+
end
|
260
|
+
if numeral.base % 2 == 0
|
261
|
+
tie_digit = numeral.base / 2
|
262
|
+
max_lo = tie_digit - 1
|
183
263
|
else
|
184
|
-
|
264
|
+
max_lo = numeral.base / 2
|
265
|
+
end
|
266
|
+
next_digit = numeral.digit_value_at(n)
|
267
|
+
if next_digit == 0
|
268
|
+
unless round_up.nil? && rest_digits.all?{|d| d == 0}
|
269
|
+
round_up = :lo
|
270
|
+
end
|
271
|
+
elsif next_digit <= max_lo # next_digit < tie_digit
|
272
|
+
round_up = :lo
|
273
|
+
elsif next_digit == tie_digit
|
274
|
+
if round_up || rest_digits.any?{|d| d != 0}
|
275
|
+
round_up = :hi
|
276
|
+
else
|
277
|
+
round_up = :tie
|
278
|
+
end
|
279
|
+
else # next_digit > tie_digit
|
280
|
+
round_up = :hi
|
185
281
|
end
|
186
|
-
|
187
|
-
|
282
|
+
numeral = Numeral[
|
283
|
+
digits, point: numeral.point, sign: numeral.sign,
|
284
|
+
base: numeral.base,
|
285
|
+
normalize: :approximate
|
286
|
+
]
|
188
287
|
end
|
189
|
-
numeral = Numeral[digits, point: numeral.point, sign: numeral.sign, normalize: :approximate]
|
190
288
|
end
|
289
|
+
[numeral, round_up]
|
191
290
|
end
|
192
|
-
[numeral, round_up]
|
193
|
-
end
|
194
291
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
292
|
+
# Adjust a truncated numeral using the round-up information
|
293
|
+
def adjust(numeral, round_up)
|
294
|
+
check_base numeral
|
295
|
+
point, digits = Flt::Support.adjust_digits(
|
296
|
+
numeral.point, numeral.digits.digits_array,
|
297
|
+
round_mode: @mode,
|
298
|
+
negative: numeral.sign == -1,
|
299
|
+
round_up: round_up,
|
300
|
+
base: numeral.base
|
301
|
+
)
|
302
|
+
if numeral.zero? && simplifying?
|
303
|
+
digits = []
|
304
|
+
point = 0
|
305
|
+
end
|
306
|
+
normalization = simplifying? ? :exact : :approximate
|
307
|
+
Numeral[digits, point: point, base: numeral.base, sign: numeral.sign, normalize: normalization]
|
308
|
+
end
|
207
309
|
|
208
|
-
|
310
|
+
ZERO_DIGITS = 0 # 1?
|
209
311
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
ZERO_DIGITS
|
215
|
-
when Numeral
|
216
|
-
if value.zero?
|
312
|
+
# Number of digits in the integer part of the value (excluding leading zeros).
|
313
|
+
def num_integral_digits(value)
|
314
|
+
case value
|
315
|
+
when 0
|
217
316
|
ZERO_DIGITS
|
317
|
+
when Numeral
|
318
|
+
if value.zero?
|
319
|
+
ZERO_DIGITS
|
320
|
+
else
|
321
|
+
if @base != value.base
|
322
|
+
value = value.to_base(@base)
|
323
|
+
end
|
324
|
+
value.normalized(remove_trailing_zeros: true).point
|
325
|
+
end
|
218
326
|
else
|
219
|
-
|
220
|
-
|
327
|
+
Conversions.order_of_magnitude(value, base: @base)
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
def num_digits(value, options)
|
332
|
+
case value
|
333
|
+
when 0
|
334
|
+
ZERO_DIGITS
|
335
|
+
when Numeral
|
336
|
+
if value.zero?
|
337
|
+
ZERO_DIGITS
|
338
|
+
else
|
339
|
+
if @base != value.base
|
340
|
+
value = value.to_base(@base)
|
341
|
+
end
|
342
|
+
if value.repeating?
|
343
|
+
0
|
344
|
+
else
|
345
|
+
value.digits.size
|
346
|
+
end
|
221
347
|
end
|
222
|
-
|
348
|
+
else
|
349
|
+
Conversions.number_of_digits(value, options.merge(base: @base))
|
223
350
|
end
|
224
|
-
else
|
225
|
-
Conversions.order_of_magnitude(value, base: @base)
|
226
351
|
end
|
352
|
+
|
353
|
+
def is_exact?(value, options={})
|
354
|
+
case value
|
355
|
+
when Numeral
|
356
|
+
value.exact?
|
357
|
+
else
|
358
|
+
Conversions.exact?(value, options)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
def extract_options(*args)
|
363
|
+
options = {}
|
364
|
+
args = args.first if args.size == 1 && args.first.kind_of?(Array)
|
365
|
+
args.each do |arg|
|
366
|
+
case arg
|
367
|
+
when Hash
|
368
|
+
options.merge! arg
|
369
|
+
when :short, :simplify
|
370
|
+
options.merge! precision: :short
|
371
|
+
when :free, :preserve
|
372
|
+
options.merge! precision: :free
|
373
|
+
when Symbol
|
374
|
+
options[:mode] = arg
|
375
|
+
when Integer
|
376
|
+
options[:precision] = arg
|
377
|
+
when Rounding
|
378
|
+
options.merge! arg.parameters
|
379
|
+
else
|
380
|
+
raise "Invalid Rounding definition"
|
381
|
+
end
|
382
|
+
end
|
383
|
+
options
|
384
|
+
end
|
385
|
+
|
227
386
|
end
|
228
387
|
|
229
388
|
end
|
data/lib/numerals/version.rb
CHANGED
data/lib/numerals.rb
CHANGED
@@ -2,11 +2,13 @@ require 'modalsupport'
|
|
2
2
|
|
3
3
|
require "numerals/version"
|
4
4
|
require 'numerals/numeral'
|
5
|
+
require 'numerals/formatting_aspect'
|
5
6
|
require 'numerals/rounding'
|
7
|
+
require 'numerals/repeat_detector'
|
6
8
|
require 'numerals/conversions/float'
|
7
9
|
require 'numerals/conversions/integer'
|
8
10
|
require 'numerals/conversions/rational'
|
9
11
|
require 'numerals/conversions/bigdecimal'
|
10
12
|
require 'numerals/conversions/flt'
|
11
|
-
require 'numerals/
|
12
|
-
require 'numerals/formatting/options'
|
13
|
+
require 'numerals/format'
|
14
|
+
# require 'numerals/formatting/options'
|
data/numerals.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency 'flt', "~> 1.
|
21
|
+
spec.add_dependency 'flt', "~> 1.4.6"
|
22
22
|
spec.add_dependency 'modalsupport', "~> 0.9.2"
|
23
23
|
|
24
24
|
spec.add_development_dependency "bundler", "~> 1.6"
|