SymEngine is a module in the extensions, and the classes are a part of it. So first you fire up the interpreter and load the file
*Note :* You will need to have libsymengine(SymEngine C++ library) installed to be able to use the SymEngine extension with Ruby. libsymengine installation instructions and other prerequisite installation instructions can be found here.
require 'symengine'
true
Go ahead and try a function
SymEngine.ascii_art
_____ _____ _
| __|_ _ _____| __|___ ___|_|___ ___
|__ | | | | __| | . | | | -_|
|_____|_ |_|_|_|_____|_|_|_ |_|_|_|___|
|___| |___|
or create a variable
basic = SymEngine::Basic.new
#<SymEngine::Basic:0x00000001e95290>
This shows that we have successfully loaded the module.
Just like there are variables like x, y, and z in a mathematical expression or equation, we have SymEngine::Symbol in SymEngine to represent them. To use a variable, first we need to make a SymEngine::Symbol object with the string we are going to represent the variable with.
puts x = SymEngine::Symbol.new("x")
puts y = SymEngine::Symbol.new("y")
puts z = SymEngine::Symbol.new("z")
x y z
Then we can construct expressions out of them
e = (x-y)*(x**y/z)
e.to_s
"x**y*(x - y)/z"
In SymEngine, every object is an instance of Basic or its subclasses. So, even an instance of SymEngine::Symbol is a Basic object.
x.class
SymEngine::Symbol
x.is_a? SymEngine::Basic
true
Now that we have an expression, we would like to see it's expanded form using #expand
f = e.expand()
f.to_s
"x**(1 + y)/z - x**y*y/z"
Or check if two expressions are same
f == - (x**y*y/z) + (x**y*x/z)
true
But e and f are not equal since they are only mathematically equal, not structurally
e == f
false
Let us suppose you want to know what variables/symbols your expression has. You can do that with the #free_symbols method. The method #free_symbols returns a Set of the symbols that are in an expression.
f.free_symbols
#<Set: {#<SymEngine::Basic:0x00000001f0ca70>, #<SymEngine::Basic:0x00000001f0ca48>, #<SymEngine::Basic:0x00000001f0ca20>}>
Let us use #map method to see the elements of the Set.
f.free_symbols.map { |x| x.to_s }
["x", "y", "z"]
#args returns the terms of the expression,
f.args.map { |x| x.to_s }
["-x**y*y/z", "x**(1 + y)/z"]
or if it is a single term it breaks down the elements
f.args[0].args.map { |k| k.to_s }
["-1", "x**y", "y", "z**(-1)"]
You can make objects of class SymEngine::Integer. It's like regular Integer in ruby kernel, except it can do all the operations a Basic object can like arithmetic operations, etc.
a = SymEngine::Integer.new(12)
b = SymEngine::Integer.new(64)
a**b
And yes it can support numbers of arbitrarily large length.
(a**x).to_s
"12**x"
You can also make objects of class SymEngine::Rational that is the SymEngine counterpart for Rationals in Ruby.
c = Rational('2/3')
d = SymEngine::Rational.new(c)
Like any other Basic object arithmetic operations can be done on this one too.
(a-d).to_s
"34/3"
You need not create an instance of SymEngine::Integer or SymEngine::Rational, every time you want to use them in an expression that uses many Integers. Let us say you already have Integer/Rational object. Even then you can use them without having to create a new SymEngine object.
k = (1 / (x * y) - x * y + 2) * (c + x * y) # c is a Rational object, not SymEngine::Rational
k.to_s
"(2/3 + x*y)*(2 + 1/(x*y) - x*y)"
As you can see, ruby kernel Integers and Rationals interoperate seamlessly with the SymEngine objects.
k.expand.to_s
"7/3 + (2/3)*1/(x*y) + (4/3)*x*y - x**2*y**2"