power_integers.sf 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #!/usr/bin/ruby
  2. # Author: Trizen
  3. # Date: 10 May 2022
  4. # https://github.com/trizen
  5. # Implementation of "PowerInteger" numbers: a + b*w^e
  6. class PowerInteger(a, b, w, e=1) { # represents = a + b*w^e
  7. method to_s {
  8. "PowerInteger(#{a}, #{b}, #{w}, #{e.as_rat})"
  9. }
  10. method stringify {
  11. return a.stringify if (b == 0)
  12. var im = "(#{b.stringify})*(#{w.stringify})^(#{e.as_rat})"
  13. return im if (a == 0)
  14. "#{a.stringify} + #{im}"
  15. }
  16. method to_n {
  17. var v = (a + b*w**e)
  18. if (v.class != :Number) {
  19. return v.to_n
  20. }
  21. return v
  22. }
  23. method neg {
  24. __CLASS__(-a, -b, w, e)
  25. }
  26. method ==(Number n) {
  27. self.to_n == n
  28. }
  29. method ==(__CLASS__ z) {
  30. (a == z.a) && (b == z.b) && (w == z.w) && (e == z.e)
  31. }
  32. method +(Number n) {
  33. __CLASS__(a + n, b, w, e)
  34. }
  35. method +(__CLASS__ z) {
  36. var (x,y) = (z.a, z.b)
  37. if ((w == z.w) && (e == z.e)) {
  38. return __CLASS__(a+x, b+y, w, e)
  39. }
  40. __CLASS__(z + a, b, w, e)
  41. }
  42. __CLASS__.alias_method('+', 'add')
  43. method -(Number n) {
  44. self + -n
  45. }
  46. method -(__CLASS__ z) {
  47. self + -z
  48. }
  49. __CLASS__.alias_method('-', 'sub')
  50. method *(Number n) {
  51. __CLASS__(a*n, b*n, w, e)
  52. }
  53. method *(__CLASS__ z) {
  54. var (x,y) = (z.a, z.b)
  55. # (a + b*w^e) * (x + y*w^e) = (a*y + b*x)*w^e + a*x + b*y*w^(2*e)
  56. if ((z.w == w) && (z.e == e)) {
  57. return (__CLASS__(0, a*y + b*x, w, e) + __CLASS__(a*x, b*y, w, 2*e))
  58. }
  59. # (a + b*w^e) * (x + y*w^r) = y w^r (a + b w^e) + x (a + b w^e)
  60. # (a + b*w^e) * (x + y*w^r) = a y w^r + a x + b y w^(r + e) + b w^e x
  61. if (z.w == w) {
  62. var r = z.e
  63. return (__CLASS__(0, a*y, w, r) + __CLASS__(a*x, b*y, w, r+e) + __CLASS__(0, b*x, w, e))
  64. }
  65. __CLASS__(z * a, z * b, w, e)
  66. }
  67. __CLASS__.alias_method('*', 'mul')
  68. method inv {
  69. Fraction(1, self)
  70. }
  71. method **(Number n) {
  72. if (!n.is_int) {
  73. return self.to_n**n
  74. }
  75. if (n < 0) {
  76. return self**n.abs
  77. }
  78. var c = __CLASS__(1, 0, w, e)
  79. var x = self
  80. for bit in (n.as_bin.chars.flip) {
  81. c *= x if bit
  82. x *= x
  83. }
  84. return c
  85. }
  86. __CLASS__.alias_method('**', 'pow')
  87. method /(Number n) {
  88. __CLASS__(a/n, b/n, w, e)
  89. }
  90. method /(__CLASS__ z) {
  91. self * z.inv
  92. }
  93. }
  94. class Number {
  95. method *(PowerInteger z) {
  96. z * self
  97. }
  98. __CLASS__.alias_method('*', 'mul')
  99. method +(PowerInteger z) {
  100. z + self
  101. }
  102. __CLASS__.alias_method('+', 'add')
  103. method -(PowerInteger z) {
  104. PowerInteger(self, 0, z.w, z.e) - z
  105. }
  106. __CLASS__.alias_method('-', 'sub')
  107. method /(PowerInteger z) {
  108. Fraction(self, z)
  109. }
  110. __CLASS__.alias_method('/', 'div')
  111. }
  112. func sqrtP(n) {
  113. PowerInteger(0, 1, n, 1/2)
  114. }
  115. func cbrtP(n) {
  116. PowerInteger(0, 1, n, 1/3)
  117. }
  118. func solve_cubic_equation(a,b,c,d) {
  119. var D0 = (b*b - 3*a*c)
  120. var D1 = (2*b**3 - 9*a*b*c + 27*a*a*d)
  121. var roots = []
  122. var z = (-1 + sqrtP(-3))/2
  123. var C = cbrtP((D1 - (sgn(D0)||-1)*sqrtP(D1*D1 - 4*D0**3))/2)
  124. 0..2 -> each {|k|
  125. var t = (C * z**k)
  126. var x = -((b + t + D0/t))/(3*a)
  127. roots << x
  128. }
  129. return roots
  130. }
  131. say ":: Solutions to: x^3 + 5*x^2 + 2*x - 8 = 0"
  132. solve_cubic_equation(1, 5, 2, -8).each_kv{|k,v| say ("x_#{k+1} = ", v.stringify) }
  133. say "\n:: Solutions to: x^3 + 4*x^2 + 7*x + 6 = 0"
  134. solve_cubic_equation(1, 4, 7, 6).each_kv{|k,v| say ("x_#{k+1} = ", v.stringify) }
  135. say "\n:: Solutions to: -36*x^3 + 8*x^2 - 82*x + 2850986 = 0:"
  136. solve_cubic_equation(-36, 8, -82, 2850986).each_kv{|k,v| say ("x_#{k+1} = ", v.stringify) }
  137. say "\n:: Solutions to: 15*x^3 - 22*x^2 + 8*x - 7520940423059310542039581 = 0:"
  138. solve_cubic_equation(15, -22, 8, -7520940423059310542039581).each_kv{|k,v| say ("x_#{k+1} = ", v.stringify) }
  139. # Run some tests
  140. assert_eq(
  141. PowerInteger(3, 4, 5, 1/3)*PowerInteger(12, 4, 5, 1/3),
  142. ((3 + 4*cbrt(5)) * (12 + 4*cbrt(5)))
  143. )
  144. assert_eq(
  145. PowerInteger(3, 4, 5, 6)*PowerInteger(12, 4, 5, 2),
  146. ((3 + 4*5**6) * (12 + 4*5**2))
  147. )
  148. assert_eq(
  149. PowerInteger(3, 4, 5, 1/3)*PowerInteger(12, 4, 13, 1/3),
  150. ((3 + 4*cbrt(5)) * (12 + 4*cbrt(13)))
  151. )
  152. assert_eq(
  153. PowerInteger(3, 4, 5, 1/3)*PowerInteger(12, 4, 13, 2),
  154. ((3 + 4*cbrt(5)) * (12 + 4*13**2))
  155. )
  156. __END__
  157. :: Solutions to: x^3 + 5*x^2 + 2*x - 8 = 0
  158. x_1 = (-19 + (-5)*(-28 + (-1/2)*(-24300)^(1/2))^(1/3))/((3)*(-28 + (-1/2)*(-24300)^(1/2))^(1/3)) + (-1/3)*(-28 + (-1/2)*(-24300)^(1/2))^(1/3)
  159. x_2 = (-19 + (5/2 + (-5/2)*(-3)^(1/2))*(-28 + (-1/2)*(-24300)^(1/2))^(1/3))/((-3/2 + (3/2)*(-3)^(1/2))*(-28 + (-1/2)*(-24300)^(1/2))^(1/3)) + (1/6 + (-1/6)*(-3)^(1/2))*(-28 + (-1/2)*(-24300)^(1/2))^(1/3)
  160. x_3 = (-19 + (-5/4 + (-5/4)*(-3)^(1) + (5/2)*(-3)^(1/2))*(-28 + (-1/2)*(-24300)^(1/2))^(1/3))/((3/4 + (3/4)*(-3)^(1) + (-3/2)*(-3)^(1/2))*(-28 + (-1/2)*(-24300)^(1/2))^(1/3)) + (-1/12 + (-1/12)*(-3)^(1) + (1/6)*(-3)^(1/2))*(-28 + (-1/2)*(-24300)^(1/2))^(1/3)
  161. :: Solutions to: x^3 + 4*x^2 + 7*x + 6 = 0
  162. x_1 = (5 + (-4)*(19 + (1/2)*(1944)^(1/2))^(1/3))/((3)*(19 + (1/2)*(1944)^(1/2))^(1/3)) + (-1/3)*(19 + (1/2)*(1944)^(1/2))^(1/3)
  163. x_2 = (5 + (2 + (-2)*(-3)^(1/2))*(19 + (1/2)*(1944)^(1/2))^(1/3))/((-3/2 + (3/2)*(-3)^(1/2))*(19 + (1/2)*(1944)^(1/2))^(1/3)) + (1/6 + (-1/6)*(-3)^(1/2))*(19 + (1/2)*(1944)^(1/2))^(1/3)
  164. x_3 = (5 + (-1 + (-1)*(-3)^(1) + (2)*(-3)^(1/2))*(19 + (1/2)*(1944)^(1/2))^(1/3))/((3/4 + (3/4)*(-3)^(1) + (-3/2)*(-3)^(1/2))*(19 + (1/2)*(1944)^(1/2))^(1/3)) + (-1/12 + (-1/12)*(-3)^(1) + (1/6)*(-3)^(1/2))*(19 + (1/2)*(1944)^(1/2))^(1/3)
  165. :: Solutions to: -36*x^3 + 8*x^2 - 82*x + 2850986 = 0:
  166. x_1 = (8792 + (-8)*(49880745296 + (1/2)*(9952355007856165026816)^(1/2))^(1/3))/((-108)*(49880745296 + (1/2)*(9952355007856165026816)^(1/2))^(1/3)) + (1/108)*(49880745296 + (1/2)*(9952355007856165026816)^(1/2))^(1/3)
  167. x_2 = (8792 + (4 + (-4)*(-3)^(1/2))*(49880745296 + (1/2)*(9952355007856165026816)^(1/2))^(1/3))/((54 + (-54)*(-3)^(1/2))*(49880745296 + (1/2)*(9952355007856165026816)^(1/2))^(1/3)) + (-1/216 + (1/216)*(-3)^(1/2))*(49880745296 + (1/2)*(9952355007856165026816)^(1/2))^(1/3)
  168. x_3 = (8792 + (-2 + (-2)*(-3)^(1) + (4)*(-3)^(1/2))*(49880745296 + (1/2)*(9952355007856165026816)^(1/2))^(1/3))/((-27 + (-27)*(-3)^(1) + (54)*(-3)^(1/2))*(49880745296 + (1/2)*(9952355007856165026816)^(1/2))^(1/3)) + (1/432 + (1/432)*(-3)^(1) + (-1/216)*(-3)^(1/2))*(49880745296 + (1/2)*(9952355007856165026816)^(1/2))^(1/3)
  169. :: Solutions to: 15*x^3 - 22*x^2 + 8*x - 7520940423059310542039581 = 0:
  170. x_1 = (-124 + (22)*(-45689713070085311542890452111/2 + (-1/2)*(2087549880426724544732454788847681930990126035285976729825)^(1/2))^(1/3))/((45)*(-45689713070085311542890452111/2 + (-1/2)*(2087549880426724544732454788847681930990126035285976729825)^(1/2))^(1/3)) + (-1/45)*(-45689713070085311542890452111/2 + (-1/2)*(2087549880426724544732454788847681930990126035285976729825)^(1/2))^(1/3)
  171. x_2 = (-124 + (-11 + (11)*(-3)^(1/2))*(-45689713070085311542890452111/2 + (-1/2)*(2087549880426724544732454788847681930990126035285976729825)^(1/2))^(1/3))/((-45/2 + (45/2)*(-3)^(1/2))*(-45689713070085311542890452111/2 + (-1/2)*(2087549880426724544732454788847681930990126035285976729825)^(1/2))^(1/3)) + (1/90 + (-1/90)*(-3)^(1/2))*(-45689713070085311542890452111/2 + (-1/2)*(2087549880426724544732454788847681930990126035285976729825)^(1/2))^(1/3)
  172. x_3 = (-124 + (11/2 + (11/2)*(-3)^(1) + (-11)*(-3)^(1/2))*(-45689713070085311542890452111/2 + (-1/2)*(2087549880426724544732454788847681930990126035285976729825)^(1/2))^(1/3))/((45/4 + (45/4)*(-3)^(1) + (-45/2)*(-3)^(1/2))*(-45689713070085311542890452111/2 + (-1/2)*(2087549880426724544732454788847681930990126035285976729825)^(1/2))^(1/3)) + (-1/180 + (-1/180)*(-3)^(1) + (1/90)*(-3)^(1/2))*(-45689713070085311542890452111/2 + (-1/2)*(2087549880426724544732454788847681930990126035285976729825)^(1/2))^(1/3)