Module: Fibonaccia
- Extended by:
- BigMath, Enumerable
- Includes:
- BigMath
- Defined in:
- lib/fibonaccia/module-doc.rb,
lib/fibonaccia.rb,
lib/fibonaccia/version.rb,
lib/fibonaccia/exceptions.rb
Overview
The Fibonaccia module simply provides three things to Ruby code:
-
Access to a constant,
Fibonaccia.PHI
(φ), which is the value of the Golden Ratio (see the Wikipedia article) either to whatever precision Ruby is using, or to an arbitrarily great precision usingBigDecimal
semantics; -
The Fibonacci sequence, to however many terms you desire (and your resources can support);
-
Coördinates to construct a golden spiral (not the Fibonacci spiral, which is an approximation of the golden spiral). Not yet implemented.
Defined Under Namespace
Modules: ClassMethods Classes: Exception, NotPositiveInteger
Constant Summary collapse
- BDPrecision =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
The number of digits of precision we want for our
BigDecimal
operations. BigDecimal::double_fig
- PHI_Float =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Note:Use
Fibonaccia.PHI
orFibonaccia.PHI(false)
to access this value.Phi (φ), the golden ratio. φ can be simply expressed by a formula, but it’s an irrational number, meaning that the default precision is implementation-specific.
Provide a
Float
value which uses the default precision. (1.0 + Math.sqrt(5)) / 2.0
- PHI =
Default value of φ as a
Float
.Referencing
PHI
as a constant (Fibonaccia::PHI
) is equivalent to:Fibonaccia.PHI(false)
Use PHI
(true)
to obtain theBigDecimal
representation. calculated_constant
- PHI_BigDecimal =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Note:Use
Fibonaccia.PHI(true)
to access this value.Provide a value for φ using an arbitrarily large precision.
(1.0 + BigDecimal.new(5).sqrt(BDPrecision)) / 2.0
- B_Float =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Constant used to construct a Golden Spiral. See the Wikipedia article for details of its definition and use. This constant is a
Float
value. For greater precision, use B_BigDecimal. (2.0 * Math.log(PHI_Float)) / Math::PI
- B_BigDecimal =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Constant used to construct a Golden Spiral. See the Wikipedia article for details of its definition and use. This constant is a
BigDecimal
value. If you don’t need arbitrarily great precision, use B_BigDecimal instead. ((2.0 * BigMath.log(PHI_BigDecimal, BDPrecision)) / BigMath.PI(BDPrecision))
- C_Float =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Constant used to construct a Golden Spiral. See the Wikipedia article for details of its definition and use. This constant is a
Float
value. For greater precision, use B_BigDecimal. Math.exp(B_Float)
- C_BigDecimal =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Constant used to construct a Golden Spiral. See the Wikipedia article for details of its definition and use. This constant is a
BigDecimal
value. If you don’t need arbitrarily great precision, use B_BigDecimal instead. BigMath.exp(B_BigDecimal, BDPrecision)
- SEED =
First three terms of the Fibonacci sequence, which is our seed and our minimum internal series.
[ 0, 1, 1 ].freeze
- MIN_TERMS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Minimum number of terms in the series – the seed values.
SEED.count
- SERIES =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Array of Fibonacci numbers to however many terms have been evolved. Defined as a constant because the underlying array structure is mutable even for constants, and it’s pre-seeded with the first three terms.
SEED.dup
- MINIMUM_RUBY_VERSION =
Minimum version of Ruby we support.
Versionomy.parse('1.9.3')
- VERSION =
Frozen string representation of the module version number.
@version.to_s.freeze
Class Method Summary collapse
-
.[](first_term, nterms = 1) ⇒ Object
Alias for Fibonaccia.slice ( q.v.).
-
.each {|Integer| ... } ⇒ Array<Integer>, Enumerator
Iterate over the current internal series, yielding each value in turn.
-
.extend_series(nterms) ⇒ void
private
This method is called to extend the SERIES array if necessary.
-
.grow(nterms) ⇒ Integer
Extend the internal series by the specified number of terms.
-
.included(klass) ⇒ void
Method invoked when a scope does an
include Fibonaccia
. -
.is_fibonacci?(val) ⇒ Boolean
See if value appears in the Fibonacci series.
-
.last ⇒ Integer
Return the last value in the internal series.
-
.PHI(extended = false) ⇒ Float, BigDecimal
Constant Phi (φ), the golden ratio.
-
.reset ⇒ void
Reset the internal series to just the seed value.
-
.series ⇒ Array<Integer>
Copy of the internal series.
-
.shrink(nterms) ⇒ Integer
Shrink the internal series by the specified number of terms.
-
.slice(first_term, nterms = 1) ⇒ Integer, ...
Obtain a slice (see Array#slice) of the Fibonacci series.
-
.terms ⇒ Integer
The number of terms in the internal series.
-
.terms=(nterms) ⇒ Integer
Set the internal series to a specific number of terms.
-
.version ⇒ Versionomy
Returns the Versionomy representation of the package version number.
-
.VERSION ⇒ String
Returns the package version number as a string.
Class Method Details
.[](first_term, nterms = 1) ⇒ Object
Alias for slice ( q.v.).
This is included because it’s probably more human-readable to find the n-th term of the sequence using the syntax
Fibonaccia[n]
522 |
# File 'lib/fibonaccia.rb', line 522 define_method(:[], self.instance_method(:slice)) |
.each {|Integer| ... } ⇒ Array<Integer>, Enumerator
Iterate over the current internal series, yielding each value in turn.
411 412 413 414 |
# File 'lib/fibonaccia.rb', line 411 def each(&block) result = SERIES.each(&block) return result end |
.extend_series(nterms) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
This method is called to extend the SERIES array if necessary.
289 290 291 292 293 294 295 296 |
# File 'lib/fibonaccia.rb', line 289 def extend_series(nterms) nterms = [ 0, nterms.to_i ].max n = [ 0, nterms - self.terms ].max n.times do SERIES << (SERIES[-2] + SERIES[-1]) end return nil end |
.grow(nterms) ⇒ Integer
Extend the internal series by the specified number of terms.
310 311 312 313 314 315 316 317 |
# File 'lib/fibonaccia.rb', line 310 def grow(nterms) unless (nterms.kind_of?(Integer) && (nterms >= 0)) msg = 'argument must be a non-negative integer' raise(Fibonaccia::NotPositiveInteger, msg) end self.extend_series(self.terms + nterms) return self.terms end |
.included(klass) ⇒ void
This method returns an undefined value.
Method invoked when a scope does an include Fibonaccia
. We simply emit a warning message and do nothing else.
178 179 180 181 182 |
# File 'lib/fibonaccia.rb', line 178 def included(klass) warn("#warning: #{self.name} " + 'is not intended for use as a mix-in, but it does no harm') return nil end |
.is_fibonacci?(val) ⇒ Boolean
See if value appears in the Fibonacci series.
Check to see if the given value is found in the Fibonacci series, using the transform described at https://en.wikipedia.org/wiki/Fibonacci_number#Recognizing_Fibonacci_numbers.
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 |
# File 'lib/fibonaccia.rb', line 549 def is_fibonacci?(val) # # Needs to be an integer. # return false unless (val.respond_to?(:floor) && (val.floor == val)) # # Needs to be non-negative. # return false if (val < 0) return true if (SERIES.include?(val)) # # Easy checks are done, time for some math-fu. # val = BigDecimal.new(val) [ +4, -4 ].each do |c| eqterm = 5 * (val**2) + c root = eqterm.sqrt(BDPrecision) return true if (root.floor == root) end return false end |
.last ⇒ Integer
432 433 434 435 |
# File 'lib/fibonaccia.rb', line 432 def last result = SERIES.last return result end |
.PHI(extended = false) ⇒ Float, BigDecimal
Constant Phi (φ), the golden ratio.
φ can be simply expressed by a formula, but it’s an irrational number, meaning that the default precision is implementation-specific. PHI allows you to access the value either at the implementation precision, or the BigDecimal
extended precision.
219 220 221 222 223 224 |
# File 'lib/fibonaccia.rb', line 219 def PHI(extended=false) result = (extended \ ? PHI_BigDecimal \ : PHI_Float) return result end |
.reset ⇒ void
This method returns an undefined value.
Reset the internal series to just the seed value.
This can be used to free up memory.
394 395 396 397 |
# File 'lib/fibonaccia.rb', line 394 def reset SERIES.replace(SEED) return nil end |
.series ⇒ Array<Integer>
Since this is a duplicate of the module-internal array, it can have a significant impact on memory usage if the series has been extended to any great length.
Copy of the internal series.
Return a dup
of the internal series, to however many terms it has grown.
274 275 276 |
# File 'lib/fibonaccia.rb', line 274 def series return SERIES.dup end |
.shrink(nterms) ⇒ Integer
The series cannot be shrunk to fewer than the SEED elements.
Shrink the internal series by the specified number of terms.
336 337 338 339 340 341 342 343 344 |
# File 'lib/fibonaccia.rb', line 336 def shrink(nterms) unless (nterms.kind_of?(Integer) && (nterms >= 0)) msg = 'argument must be a non-negative integer' raise(Fibonaccia::NotPositiveInteger, msg) end nterms = [ MIN_TERMS, self.terms - nterms ].max SERIES.replace(SERIES.take(nterms)) return self.terms end |
.slice(first_term, nterms = 1) ⇒ Integer, ...
The internal series is zero-based, which means the first term is numbered 0
.
Obtain a slice (see Array#slice) of the Fibonacci series.
The internal series will be extended, if necessary, to include all terms requested.
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 |
# File 'lib/fibonaccia.rb', line 465 def slice(first_term, nterms=1) args = { 'first_term' => first_term, 'nterms' => nterms, } # # Sanity-check our arguments; be more informative than the default # # TypeError: no implicit conversion of <class> into Integer # args.each do |argname,argval| unless (argval.kind_of?(Integer)) raise(ArgumentError, "#{argname} must be an integer") end end nterms = [ 1, nterms ].max if (first_term < 0) endpoint = [ 0, self.terms + first_term + nterms ].max else endpoint = first_term + nterms end Fibonaccia.extend_series(endpoint) # # We're going to pass this along to the array's own #slice # method, so build its argument list appropriately. # args = [ first_term ] args << nterms unless (nterms == 1) result = SERIES.slice(*args) # # If we got a multi-element slice, make sure we don't return our # master sequence! Ruby shouldn't let it happen, but defensive # programing is all. # result = result.dup if (result === SERIES) return result end |
.terms ⇒ Integer
The number of terms in the internal series.
Similar to the #count method provided by the Enumerable
mix-in, but a more direct approach – and complementary to the terms= method.
356 357 358 359 |
# File 'lib/fibonaccia.rb', line 356 def terms result = SERIES.count return result end |
.terms=(nterms) ⇒ Integer
The series cannot be shrunk to fewer than the SEED elements.
Set the internal series to a specific number of terms.
373 374 375 376 377 378 379 380 381 382 383 384 385 |
# File 'lib/fibonaccia.rb', line 373 def terms=(nterms) unless (nterms.kind_of?(Integer) && (nterms >= 0)) msg = 'argument must be a non-negative integer' raise(Fibonaccia::NotPositiveInteger, msg) end nterms = [ MIN_TERMS, nterms ].max if (nterms > self.terms) self.grow(nterms - self.terms) elsif (nterms < self.terms) self.shrink(self.terms - nterms) end return self.terms end |
.version ⇒ Versionomy
Returns the Versionomy representation of the package version number.
72 73 74 |
# File 'lib/fibonaccia/version.rb', line 72 def self.version return @version end |
.VERSION ⇒ String
Returns the package version number as a string.
82 83 84 |
# File 'lib/fibonaccia/version.rb', line 82 def self.VERSION return self.const_get('VERSION') end |