Skip to content

jzakiya/roots

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Roots

Introduction

This gem originally provided two methods root and roots to find all the nth roots of real and complex values.

For details on their mathematical foundation and implementation details see my paper:

Roots in Ruby

https://www.scribd.com/doc/60067570/Roots-in-Ruby

In 2017 I added the methods iroot2 and iroot|irootn to find the integer roots for arbitrary sized integers.

Installation

Add this line to your application's Gemfile:

gem 'roots'

And then execute:

$ bundle

Or install it yourself as:

$ gem install roots

Then require as:

require 'roots'

Description

Starting with Roots 2.0.0 (2017-2-21) the methods iroot2 and irootn were added (with iroot added as an alias to irootn 2017-6-1). With 2.1.0 iroot2 uses optimized Newton's method. With 2.2.0 (2017-6-17) iroot|n uses optimized Newton's method for any nth root. All are instance_methods of class Integer and accurately compute the exact real value square|nth roots for arbitrary sized integers.

If you have an application where you need the exact correct integer real value for roots, especially for arbitrary sized (large) integers, use these methods instead of root|s. These methods work strictly in the integer domain, and do not first create floating point approximations of these roots and then convert them to integers.

They are useful for applications in pure math, Number Theory, Cryptography, etc, where you need to find the exact real integer roots of polynomials, encryption functions, etc.

The methods root and roots work for all the Numeric classes (integers, floats, complex, rationals), and produce floating point results. They, thus, produce floating point approximations to the exact Integer values for real roots for arbitrary sized integers.

Usage

iroot2

Use syntax:  ival.iroot2
Return the largest Integer +root+ of Integer ival such that root**2 <= ival
A negative ival will result in 'nil' being returned.

 9.iroot2 => 3
-9.iroot2 => nil

120.iroot2 => 10
121.iroot2 => 11
121.iroot2.class => Integer

(10**10).iroot2 => 100000
(10**10).root(2) => 100000.0
(10**10).roots(2)[0] => 100000.0+0.0i

(10**11).iroot2 => 316227
(10**11).root(2) => 316227.76601684
(10**11).roots(2)[0] => 316227.76601684+0.0i

(10**110).iroot2 => 10000000000000000000000000000000000000000000000000000000
(10**110).root(2) => 1.0e+55
(10**110).roots(2)[0] => 1.0e+55+0.0i

(10**111).iroot2 => 31622776601683793319988935444327185337195551393252168268
(10**111).root(2) => 3.1622776601683795e+55
(10**111).roots(2)[0] => 3.1622776601683795e+55+0.0i

irootn or iroot

Use syntax:  ival.irootn(n) or ival.iroot(n), where n is an Integer > 1
Return the largest Integer +root+ of Integer ival such that root**n <= ival
A negative ival for an even root n will result in 'nil' being returned.

81.irootn(2) => 9
81.irootn 3 => 4
81.iroot 4 => 3
81.iroot(4).class => Integer

-81.irootn(3) => -4
-81.irootn(4) => nil

100.irootn 4.5 => RuntimeError: root n is < 2 or not an Integer
100.iroot -2   => RuntimeError: root n is < 2 or not an Integer

(10**110).iroot(2)  => 10000000000000000000000000000000000000000000000000000000
(10**110).irootn(3) => 4641588833612778892410076350919446576
(10**110).iroot 4   => 3162277660168379331998893544
(10**110).iroot(5)  => 10000000000000000000000
(10**110).irootn(6) => 2154434690031883721
(10**110).irootn(7) => 5179474679231211
(10**110).irootn(8) => 56234132519034
(10**110).iroot(9)  => 1668100537200
(10**110).iroot 10  => 100000000000

root

Use syntax:  val.root(n,{k})
root(n,k=0) n is root 1/n exponent,  integer > 0
            k is nth ccw root 1..n , integer >=0
If k not given default root returned, which are:
for +val => real root  |val**(1.0/n)|
for -val => real root -|val**(1.0/n)| when n is odd
for -val => first ccw complex root    when n is even

9.root(2) => 3.0
-32.root(5,3) => (-2.0+0.0i)
73.root 6 => 2.04434322
73.root 6,1 => (2.04434322+0.0i)
(-100.43).root 6,6 => (1.86712994-1.07798797i)
Complex(3,19).root 7,4 => (-1.47939161+0.37266673i)

roots

Use syntax:  val.roots(n,{opt})
roots(n,opt=0) n is root 1/n exponent, integer > 0
               opt, optional string input, are:
   0   : default (no input), return array of n ccw roots
'c'|'C': complex, return array of complex roots
'e'|'E': even, return array even numbered roots
'o'|'O': odd , return array odd  numbered roots
'i'|'I': imag, return array of imaginary roots
'r'|'R': real, return array of real roots
An empty array is returned for an opt with no members.

9348134943.roots(9); -89.roots(4,'real'); 2.2.roots 3,'Im'
For Ruby >= 1.9 can also use a symbol as option: 384.roots 4,:r

Can ask: How many complex roots of x: x.roots(n,'c').size
What's the 3rd 5th root of (4+9i): Complex(4,9).root(5,3)

8.roots 3 => [(2.0+0.0i), (-1.0+1.73205081i), (-1.0-1.73205081i)]

Roots.digits_to_show

With version 1.1.0 this method was added to allow users to set
and see the number of decimal digits displayed. If no input is
given, the number of digits previously set is shown. The default
value is 8. Providing an input value sets the number of digits to
display. An input value < 1 will be set to a value of 1, to
display at least one decimal digit. An input greater than the
maximum digits shown for a given Ruby will display that maximum.


Roots.digits_to_show => 8

10.root 5 => 1.58489319

Roots.digits_to_show 11 => 11

10.root 5 => 1.58489319246

Roots.digits_to_show 16 => 16

10.root 5 => 1.5848931924611136

Roots.digits_to_show 17 => 17

10.root 5 => 1.5848931924611136

Roots.digits_to_show 0 => 1

10.root 5 => 1.6

Mathematical Foundations

For complex number (x+iy) = a*e^(i*arg) = a*[cos(arg) + i*sin(arg)]

The root values of a number are:

1) root(n) = (x + iy)^(1/n)
2) root(n) = (a*e^(i*arg))^(1/n)
3) root(n,k) = (a*e^i*(arg + 2kPI))^(1/n)
4) root(n,k) = a^(1/n)*(e^i*(arg + 2kPI))^(1/n)
5) root(n,k) = |a^(1/n)|*e^i*(arg + 2kPI)/n
6) root(n,k) = |a^(1/n)|*(cos(arg/n+2kPI/n) + i*sin(arg/n+2kPI/n))
   define  mag = |a^(1/n)|, theta = arg/n, and delta = 2PI/n
7) root(n,k)= mag*[cos(theta + k*delta) + i*sin(theta + k*delta)], k=0..n-1

Thus, there are n distinct roots (values).

For integer numbers:

For binary based (digital) computers (cpu), all integers are represented as
binary numbers. To find the root 'n' of an integer 'num' we can use the following
process to find the largest integer nth 'root' such that root**n <= num.

For an integer composed of 'b' bits an nth root 'n' will have at most (b/n + 1) bits.

For squareroots n = 2:
For 9 = 0b1001, it has b = 4 bits, and its squareroot has at most (4/2 + 1) = 3 bits.
The squareroot of 9 is 3 = 0b11, which is 2 bits.

For 100 = 0b1100100, b = 7, and its squareroot has at most (7/2 + 1) = 4 bits.
The squareroot of 100 is 10 = 0b1010, which is 4 bits.

For cuberoots n = 3:
For 8 = 0b1000, it has b = 4 bits, and its cuberoot has at most (4/3 + 1) = 2 bits.
The cuberoot of 8 is 2 = 0b10, which is 2 bits.

For 125 = 0b1111101, b = 7, and its cuberoot has at most (7/3 + 1) = 3 bits.
The cuberoot of 125 is 5 = 0b101, which is 3 bits.

Algorithm:
           bits_shift = (num.bit_length)/n + 1   # determine max number of root bits
           bitn_mask = 1 << bits_shift           # set value for max bit position of root
           root = 0                              # initialize the value for root
           until bitn_mask == 0                  # step through all the bit positions for root
             root |= bitn_mask                   # set current bit position to '1' in root
             root ^= bitn_mask if root**n > num  # set it back to '0' if root too large
             bitn_mask >>= 1                     # set bitn_mask to next smaller bit position
           end
           root                                  # return exact integer value for root

Starting with 2.1.0 Newton's method for squareroots is used instead of bbm.
Starting with 2.2.0 Newton's method for general nth roots is used instead of bbm.
https://en.wikipedia.org/wiki/Nth_root_algorithm

Author

Jabari Zakiya

License

GPL-2.0+

Releases

No releases published

Packages

No packages published

Languages