Skip to content

Introducing Symbolic Binary operators and i32 to S Casting function #1964

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,8 @@ RUN(NAME structs_26 LABELS cpython llvm c)
RUN(NAME structs_27 LABELS cpython llvm c)

RUN(NAME symbolics_01 LABELS cpython_sym c_sym)
RUN(NAME symbolics_02 LABELS cpython_sym c_sym)
RUN(NAME symbolics_03 LABELS cpython_sym c_sym)

RUN(NAME sizeof_01 LABELS llvm c
EXTRAFILES sizeof_01b.c)
Expand Down
34 changes: 34 additions & 0 deletions integration_tests/symbolics_02.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from sympy import Symbol
from lpython import S

def test_symbolic_operations():
x: S = Symbol('x')
y: S = Symbol('y')

# Addition
z: S = x + y
print(z) # Expected: x + y

# Subtraction
w: S = x - y
print(w) # Expected: x - y

# Multiplication
u: S = x * y
print(u) # Expected: x*y

# Division
v: S = x / y
print(v) # Expected: x/y

# Power
p: S = x ** y
print(p) # Expected: x**y

# Casting
a: S = S(100)
b: S = S(-100)
c: S = a + b
print(c) # Expected: 0

test_symbolic_operations()
21 changes: 21 additions & 0 deletions integration_tests/symbolics_03.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from sympy import Symbol, pi
from lpython import S

def test_operator_chaining():
w: S = S(2)
x: S = Symbol('x')
y: S = Symbol('y')
z: S = Symbol('z')
Pi: S = Symbol('pi')

a: S = x * w
b: S = a + Pi
c: S = b / z
d: S = c ** w

print(a) # Expected: 2*x
print(b) # Expected: pi + 2*x
print(c) # Expected: (pi + 2*x)/z
print(d) # Expected: (pi + 2*x)**2/z**2

test_operator_chaining()
1 change: 1 addition & 0 deletions src/libasr/ASR.asdl
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,7 @@ cast_kind
| RealToUnsignedInteger
| CPtrToUnsignedInteger
| UnsignedIntegerToCPtr
| IntegerToSymbolicExpression

dimension = (expr? start, expr? length)

Expand Down
10 changes: 10 additions & 0 deletions src/libasr/asr_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <libasr/utils.h>
#include <libasr/modfile.h>
#include <libasr/pass/pass_utils.h>
#include <libasr/pass/intrinsic_function_registry.h>

namespace LCompilers {

Expand Down Expand Up @@ -1196,6 +1197,15 @@ ASR::asr_t* make_Cast_t_value(Allocator &al, const Location &a_loc,
double real = value_complex->m_re;
value = ASR::down_cast<ASR::expr_t>(
ASR::make_RealConstant_t(al, a_loc, real, a_type));
} else if (a_kind == ASR::cast_kindType::IntegerToSymbolicExpression) {
Vec<ASR::expr_t*> args;
args.reserve(al, 1);
args.push_back(al, a_arg);
LCompilers::ASRUtils::create_intrinsic_function create_function =
LCompilers::ASRUtils::IntrinsicFunctionRegistry::get_create_function("SymbolicInteger");
value = ASR::down_cast<ASR::expr_t>(create_function(al, a_loc, args,
[](const std::string&, const Location&) {
}));
}
}

Expand Down
13 changes: 11 additions & 2 deletions src/libasr/codegen/asr_to_c_cpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1634,6 +1634,9 @@ R"(#include <stdio.h>
last_expr_precedence = 2;
break;
}
case (ASR::cast_kindType::IntegerToSymbolicExpression): {
break;
}
default : throw CodeGenError("Cast kind " + std::to_string(x.m_kind) + " not implemented",
x.base.base.loc);
}
Expand Down Expand Up @@ -2382,8 +2385,13 @@ R"(#include <stdio.h>
SET_INTRINSIC_NAME(Exp2, "exp2");
SET_INTRINSIC_NAME(Expm1, "expm1");
SET_INTRINSIC_NAME(SymbolicSymbol, "Symbol");
SET_INTRINSIC_NAME(SymbolicInteger, "Integer");
SET_INTRINSIC_NAME(SymbolicPi, "pi");
case (static_cast<int64_t>(ASRUtils::IntrinsicFunctions::SymbolicAdd)): {
case (static_cast<int64_t>(ASRUtils::IntrinsicFunctions::SymbolicAdd)):
case (static_cast<int64_t>(ASRUtils::IntrinsicFunctions::SymbolicSub)):
case (static_cast<int64_t>(ASRUtils::IntrinsicFunctions::SymbolicMul)):
case (static_cast<int64_t>(ASRUtils::IntrinsicFunctions::SymbolicDiv)):
case (static_cast<int64_t>(ASRUtils::IntrinsicFunctions::SymbolicPow)): {
LCOMPILERS_ASSERT(x.n_args == 2);
this->visit_expr(*x.m_args[0]);
std::string arg1 = src;
Expand All @@ -2404,7 +2412,8 @@ R"(#include <stdio.h>
src = out;
} else if (x.n_args == 1) {
this->visit_expr(*x.m_args[0]);
if (x.m_intrinsic_id != static_cast<int64_t>(ASRUtils::IntrinsicFunctions::SymbolicSymbol)) {
if ((x.m_intrinsic_id != static_cast<int64_t>(ASRUtils::IntrinsicFunctions::SymbolicSymbol)) &&
(x.m_intrinsic_id != static_cast<int64_t>(ASRUtils::IntrinsicFunctions::SymbolicInteger))) {
out += "(" + src + ")";
src = out;
}
Expand Down
37 changes: 33 additions & 4 deletions src/libasr/codegen/c_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,14 @@ class CCPPDSUtils {
return result;
}

std::string generate_binary_operator_code(std::string value, std::string target, std::string operatorName) {
size_t delimiterPos = value.find(",");
std::string leftPart = value.substr(0, delimiterPos);
std::string rightPart = value.substr(delimiterPos + 1);
std::string result = operatorName + "(" + target + ", " + leftPart + ", " + rightPart + ");";
return result;
}

std::string get_deepcopy_symbolic(ASR::expr_t *value_expr, std::string value, std::string target) {
std::string result;
if (ASR::is_a<ASR::Var_t>(*value_expr)) {
Expand All @@ -645,22 +653,43 @@ class CCPPDSUtils {
break;
}
case LCompilers::ASRUtils::IntrinsicFunctions::SymbolicAdd: {
size_t delimiterPos = value.find(",");
std::string leftPart = value.substr(0, delimiterPos);
std::string rightPart = value.substr(delimiterPos + 1);
result = "basic_add(" + target + ", " + leftPart + ", " + rightPart + ");";
result = generate_binary_operator_code(value, target, "basic_add");
break;
}
case LCompilers::ASRUtils::IntrinsicFunctions::SymbolicSub: {
result = generate_binary_operator_code(value, target, "basic_sub");
break;
}
case LCompilers::ASRUtils::IntrinsicFunctions::SymbolicMul: {
result = generate_binary_operator_code(value, target, "basic_mul");
break;
}
case LCompilers::ASRUtils::IntrinsicFunctions::SymbolicDiv: {
result = generate_binary_operator_code(value, target, "basic_div");
break;
}
case LCompilers::ASRUtils::IntrinsicFunctions::SymbolicPow: {
result = generate_binary_operator_code(value, target, "basic_pow");
break;
}
case LCompilers::ASRUtils::IntrinsicFunctions::SymbolicPi: {
result = "basic_const_pi(" + target + ");";
break;
}
case LCompilers::ASRUtils::IntrinsicFunctions::SymbolicInteger: {
result = "integer_set_si(" + target + ", " + value + ");";
break;
}
default: {
throw LCompilersException("IntrinsicFunction: `"
+ LCompilers::ASRUtils::get_intrinsic_name(intrinsic_id)
+ "` is not implemented");
}
}
} else if (ASR::is_a<ASR::Cast_t>(*value_expr)) {
ASR::Cast_t* cast_expr = ASR::down_cast<ASR::Cast_t>(value_expr);
std::string cast_value_expr = get_deepcopy_symbolic(cast_expr->m_value, value, target);
return cast_value_expr;
}
return result;
}
Expand Down
Loading