rcas 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. checksums.yaml +7 -0
  2. data/CITATION.cff +17 -0
  3. data/DESIGN.md +783 -0
  4. data/LICENSE +21 -0
  5. data/MANUAL.md +6265 -0
  6. data/README.md +267 -0
  7. data/bin/rcas +9 -0
  8. data/bin/rcas-app +9 -0
  9. data/bin/rcas-chat +9 -0
  10. data/lib/rcas/algebraic.rb +481 -0
  11. data/lib/rcas/analysis.rb +966 -0
  12. data/lib/rcas/app/launcher.rb +203 -0
  13. data/lib/rcas/app/public/app.css +402 -0
  14. data/lib/rcas/app/public/app.js +449 -0
  15. data/lib/rcas/app/public/index.html +46 -0
  16. data/lib/rcas/app/server.rb +220 -0
  17. data/lib/rcas/app/window.rb +94 -0
  18. data/lib/rcas/app/worksheet.rb +290 -0
  19. data/lib/rcas/app.rb +168 -0
  20. data/lib/rcas/background.rb +758 -0
  21. data/lib/rcas/chat/assistant.rb +199 -0
  22. data/lib/rcas/chat/picker.rb +164 -0
  23. data/lib/rcas/chat/repl.rb +583 -0
  24. data/lib/rcas/chat/session.rb +137 -0
  25. data/lib/rcas/chat/settings.rb +71 -0
  26. data/lib/rcas/chat/style.rb +30 -0
  27. data/lib/rcas/chat/tool.rb +53 -0
  28. data/lib/rcas/chat/ui.rb +316 -0
  29. data/lib/rcas/chat/usage.rb +62 -0
  30. data/lib/rcas/chat/workspace.rb +132 -0
  31. data/lib/rcas/chat.rb +54 -0
  32. data/lib/rcas/coefficients.rb +170 -0
  33. data/lib/rcas/combinatorics.rb +274 -0
  34. data/lib/rcas/complex_parts.rb +160 -0
  35. data/lib/rcas/constants.rb +129 -0
  36. data/lib/rcas/core_ext.rb +35 -0
  37. data/lib/rcas/decide.rb +501 -0
  38. data/lib/rcas/decompositions.rb +241 -0
  39. data/lib/rcas/differentiate.rb +144 -0
  40. data/lib/rcas/discussion.rb +558 -0
  41. data/lib/rcas/distributions.rb +980 -0
  42. data/lib/rcas/dixon.rb +95 -0
  43. data/lib/rcas/docs.rb +321 -0
  44. data/lib/rcas/domains.rb +728 -0
  45. data/lib/rcas/expand.rb +174 -0
  46. data/lib/rcas/expression.rb +613 -0
  47. data/lib/rcas/factor.rb +605 -0
  48. data/lib/rcas/finite_field.rb +577 -0
  49. data/lib/rcas/fourier.rb +118 -0
  50. data/lib/rcas/fps.rb +678 -0
  51. data/lib/rcas/fraction.rb +126 -0
  52. data/lib/rcas/functions.rb +1136 -0
  53. data/lib/rcas/gcd.rb +112 -0
  54. data/lib/rcas/geometry.rb +266 -0
  55. data/lib/rcas/groebner.rb +162 -0
  56. data/lib/rcas/hold.rb +277 -0
  57. data/lib/rcas/hypothesis.rb +364 -0
  58. data/lib/rcas/inequalities.rb +689 -0
  59. data/lib/rcas/integral_functions.rb +260 -0
  60. data/lib/rcas/integrate.rb +1589 -0
  61. data/lib/rcas/integrate_substitutions.rb +434 -0
  62. data/lib/rcas/interpolate.rb +40 -0
  63. data/lib/rcas/irb.rb +146 -0
  64. data/lib/rcas/laplace.rb +159 -0
  65. data/lib/rcas/latex.rb +556 -0
  66. data/lib/rcas/lattice.rb +172 -0
  67. data/lib/rcas/linear_algebra.rb +117 -0
  68. data/lib/rcas/linear_program.rb +416 -0
  69. data/lib/rcas/lint.rb +79 -0
  70. data/lib/rcas/matrix.rb +531 -0
  71. data/lib/rcas/matrix_multiply.rb +202 -0
  72. data/lib/rcas/multimodular.rb +286 -0
  73. data/lib/rcas/named_polynomials.rb +274 -0
  74. data/lib/rcas/number_theory.rb +443 -0
  75. data/lib/rcas/numerics.rb +825 -0
  76. data/lib/rcas/ode.rb +488 -0
  77. data/lib/rcas/openmath/objects.rb +364 -0
  78. data/lib/rcas/openmath/phrasebook.rb +551 -0
  79. data/lib/rcas/openmath/popcorn.rb +518 -0
  80. data/lib/rcas/openmath/xml.rb +309 -0
  81. data/lib/rcas/openmath.rb +49 -0
  82. data/lib/rcas/petkovsek.rb +165 -0
  83. data/lib/rcas/piecewise.rb +488 -0
  84. data/lib/rcas/plot.rb +763 -0
  85. data/lib/rcas/plot3d.rb +419 -0
  86. data/lib/rcas/poly_matrix.rb +318 -0
  87. data/lib/rcas/poly_recurrence.rb +117 -0
  88. data/lib/rcas/polynomial.rb +466 -0
  89. data/lib/rcas/precision.rb +925 -0
  90. data/lib/rcas/printer.rb +150 -0
  91. data/lib/rcas/product.rb +155 -0
  92. data/lib/rcas/q_difference.rb +296 -0
  93. data/lib/rcas/q_functions.rb +158 -0
  94. data/lib/rcas/q_summation.rb +308 -0
  95. data/lib/rcas/q_zeilberger.rb +199 -0
  96. data/lib/rcas/random.rb +506 -0
  97. data/lib/rcas/rational_function.rb +186 -0
  98. data/lib/rcas/recurrence.rb +323 -0
  99. data/lib/rcas/render.rb +431 -0
  100. data/lib/rcas/results.rb +192 -0
  101. data/lib/rcas/scalar.rb +219 -0
  102. data/lib/rcas/series.rb +726 -0
  103. data/lib/rcas/simplify.rb +649 -0
  104. data/lib/rcas/solve.rb +2002 -0
  105. data/lib/rcas/special.rb +163 -0
  106. data/lib/rcas/statistics.rb +175 -0
  107. data/lib/rcas/steps.rb +835 -0
  108. data/lib/rcas/summation.rb +532 -0
  109. data/lib/rcas/trig.rb +264 -0
  110. data/lib/rcas/van_hoeij.rb +241 -0
  111. data/lib/rcas/vector.rb +175 -0
  112. data/lib/rcas/vector_calculus.rb +411 -0
  113. data/lib/rcas/version.rb +5 -0
  114. data/lib/rcas/zeilberger.rb +358 -0
  115. data/lib/rcas.rb +91 -0
  116. data/package.json +8 -0
  117. metadata +206 -0
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RCAS
4
+ # Rational-function normalisation: one numerator over one denominator with
5
+ # the polynomial gcd cancelled.
6
+ #
7
+ # (1/(a**2*(-1 - 1/a)) + 1/a).cancel # => 1/(1 + a)
8
+ # ((:x**2 - 1)/(:x - 1)).cancel # => 1 + x
9
+ module Fraction
10
+ module_function
11
+
12
+ # => [numerator, denominator] as Polynomials over QQ in all variables, or
13
+ # nil when the expression is not a rational function with rational
14
+ # coefficients.
15
+ def as_fraction(expr, vars = nil)
16
+ vars = (vars || []) | expr.variables
17
+ return nil if vars.empty?
18
+ ring = QQ[*vars]
19
+ constant, table = Expand.table(expr)
20
+ return nil unless rational?(constant)
21
+ # Terms with the same denominator are added over it first, and the
22
+ # groups are then brought together over the lcm of their
23
+ # denominators: multiplying every term's denominator into the running
24
+ # one turned (x + y + 1)**12 expanded over x + y + 1 into a
25
+ # denominator of degree 91 and took nine seconds (third review,
26
+ # section 5).
27
+ groups = {}
28
+ groups[[]] = [ring.call(constant), ring.one]
29
+ table.each do |factors, coeff|
30
+ return nil unless rational?(coeff)
31
+ n = ring.call(coeff)
32
+ d = ring.one
33
+ key = []
34
+ factors.each do |base, exp|
35
+ return nil unless exp.is_a?(Integer)
36
+ bn, bd = begin
37
+ [ring.call(base), ring.one]
38
+ rescue DomainError
39
+ return nil unless base.is_a?(Add) || base.is_a?(Sub) # nested fraction inside a sum
40
+ inner = as_fraction(base) or return nil
41
+ inner.map { |q| q.to_ring(ring) }
42
+ end
43
+ if exp.positive?
44
+ n *= bn**exp
45
+ d *= bd**exp
46
+ key << [base, :up, exp] unless bd.constant?
47
+ else
48
+ n *= bd**(-exp)
49
+ d *= bn**(-exp)
50
+ key << [base, exp]
51
+ end
52
+ end
53
+ key = key.sort_by(&:to_s)
54
+ if (group = groups[key])
55
+ group[0] = group[0] + n
56
+ else
57
+ groups[key] = [n, d]
58
+ end
59
+ end
60
+ num = ring.zero
61
+ den = ring.one
62
+ groups.each_value do |n, d|
63
+ next if n.zero?
64
+ common = den.lcm(d)
65
+ num = num * common.exact_div(den) + n * common.exact_div(d)
66
+ den = common
67
+ end
68
+ g = num.gcd(den)
69
+ [num.exact_div(g), den.exact_div(g)]
70
+ end
71
+
72
+ def cancel(expr)
73
+ pair = as_fraction(expr) or return expr.simplify
74
+ num, den = pair
75
+ lc = den.leading_coefficient
76
+ num *= Scalar.div(Num.new(1), lc)
77
+ den = den.monic
78
+ (den.constant? ? num.to_expr : num.to_expr / den.to_expr).simplify
79
+ end
80
+
81
+ def rational?(v) = v.is_a?(Integer) || v.is_a?(Rational)
82
+
83
+ # Clear square roots from denominators: 1/(1 + sqrt(2)) => -1 + sqrt(2).
84
+ # Handles denominators that are sums of a rational and one surd term.
85
+ def rationalize(expr)
86
+ if (exact = Algebraic.exact(expr))
87
+ return exact.to_expr.simplify
88
+ end
89
+ _, table = Expand.table(expr)
90
+ surd_denominators = table.each_key.flat_map do |factors|
91
+ factors.select { |base, exp| exp.is_a?(Integer) && exp.negative? && surd_sum?(base) }.map(&:first)
92
+ end.uniq
93
+ return expr.simplify if surd_denominators.empty?
94
+ result = expr
95
+ surd_denominators.each do |den|
96
+ conj = conjugate(den)
97
+ norm = (den * conj).expand
98
+ return expr.simplify unless norm.is_a?(Num) && !norm.zero?
99
+ constant, table = Expand.table(result)
100
+ result = Num.new(constant)
101
+ table.each do |factors, coeff|
102
+ e = factors[den]
103
+ if e.is_a?(Integer) && e.negative?
104
+ k = -e
105
+ rest = factors.reject { |b, _| b == den }
106
+ result += (Simplify.rebuild_product(coeff.quo(norm.value**k), rest) * conj**k).expand
107
+ else
108
+ result += Simplify.rebuild_product(coeff, factors)
109
+ end
110
+ end
111
+ end
112
+ result.simplify
113
+ end
114
+
115
+ def surd_sum?(base)
116
+ return false unless base.is_a?(Add) || base.is_a?(Sub)
117
+ constant, terms = Simplify.termize(base)
118
+ terms.size == 1 && terms.each_key.all? { |f| f.all? { |b, e| b.is_a?(Num) && e.is_a?(Rational) } } && (constant.is_a?(Integer) || constant.is_a?(Rational))
119
+ end
120
+
121
+ def conjugate(base)
122
+ constant, terms = Simplify.termize(base)
123
+ Simplify.rebuild_sum(constant, terms.transform_values { |c| -c })
124
+ end
125
+ end
126
+ end