diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 954a19885c..7832a6af1f 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -283,8 +283,8 @@ RUN(NAME test_import_01 LABELS cpython llvm c) RUN(NAME test_import_02 LABELS cpython llvm c) RUN(NAME test_import_03 LABELS cpython llvm c) RUN(NAME test_import_04 IMPORT_PATH .. - LABELS cpython llvm c) -RUN(NAME test_math LABELS cpython llvm) + LABELS cpython llvm) +RUN(NAME test_math LABELS cpython llvm c) RUN(NAME test_numpy_01 LABELS cpython llvm c) RUN(NAME test_numpy_02 LABELS cpython llvm c) RUN(NAME test_numpy_03 LABELS cpython llvm c) diff --git a/src/libasr/codegen/asr_to_c.cpp b/src/libasr/codegen/asr_to_c.cpp index 230b62fd49..fb5077c59a 100644 --- a/src/libasr/codegen/asr_to_c.cpp +++ b/src/libasr/codegen/asr_to_c.cpp @@ -158,7 +158,13 @@ class ASRToCVisitor : public BaseCCPPVisitor counter += 1; ASR::dimension_t* m_dims = nullptr; size_t n_dims = ASRUtils::extract_dimensions_from_ttype(mem_type, m_dims); - sub += indent + convert_variable_decl(*mem_var, true, true, true, true, mem_var_name) + ";\n"; + CDeclarationOptions c_decl_options_; + c_decl_options_.pre_initialise_derived_type = true; + c_decl_options_.use_ptr_for_derived_type = true; + c_decl_options_.use_static = true; + c_decl_options_.force_declare = true; + c_decl_options_.force_declare_name = mem_var_name; + sub += indent + convert_variable_decl(*mem_var, &c_decl_options_) + ";\n"; if( !ASRUtils::is_fixed_size_array(m_dims, n_dims) ) { sub += indent + name + "->" + itr.first + " = " + mem_var_name + ";\n"; } @@ -172,12 +178,34 @@ class ASRToCVisitor : public BaseCCPPVisitor } std::string convert_variable_decl(const ASR::Variable_t &v, - bool pre_initialise_derived_type=true, - bool use_ptr_for_derived_type=true, - bool use_static=true, - bool force_declare=false, - std::string force_declare_name="") + DeclarationOptions* decl_options=nullptr) { + bool pre_initialise_derived_type; + bool use_ptr_for_derived_type; + bool use_static; + bool force_declare; + std::string force_declare_name; + bool declare_as_constant; + std::string const_name; + + if( decl_options ) { + CDeclarationOptions* c_decl_options = reinterpret_cast(decl_options); + pre_initialise_derived_type = c_decl_options->pre_initialise_derived_type; + use_ptr_for_derived_type = c_decl_options->use_ptr_for_derived_type; + use_static = c_decl_options->use_static; + force_declare = c_decl_options->force_declare; + force_declare_name = c_decl_options->force_declare_name; + declare_as_constant = c_decl_options->declare_as_constant; + const_name = c_decl_options->const_name; + } else { + pre_initialise_derived_type = true; + use_ptr_for_derived_type = true; + use_static = true; + force_declare = false; + force_declare_name = ""; + declare_as_constant = false; + const_name = ""; + } std::string sub; bool use_ref = (v.m_intent == LFortran::ASRUtils::intent_out || v.m_intent == LFortran::ASRUtils::intent_inout); @@ -275,8 +303,13 @@ class ASRToCVisitor : public BaseCCPPVisitor } } else { bool is_fixed_size = true; + std::string v_m_name = v.m_name; + if( declare_as_constant ) { + type_name = "const " + type_name; + v_m_name = const_name; + } dims = convert_dims_c(t->n_dims, t->m_dims, v_m_type, is_fixed_size); - sub = format_type_c(dims, type_name, v.m_name, use_ref, dummy); + sub = format_type_c(dims, type_name, v_m_name, use_ref, dummy); } } else if (ASRUtils::is_real(*v_m_type)) { ASR::Real_t *t = ASR::down_cast(v_m_type); @@ -307,8 +340,13 @@ class ASRToCVisitor : public BaseCCPPVisitor } } else { bool is_fixed_size = true; + std::string v_m_name = v.m_name; + if( declare_as_constant ) { + type_name = "const " + type_name; + v_m_name = const_name; + } dims = convert_dims_c(t->n_dims, t->m_dims, v_m_type, is_fixed_size); - sub = format_type_c(dims, type_name, v.m_name, use_ref, dummy); + sub = format_type_c(dims, type_name, v_m_name, use_ref, dummy); } } else if (ASRUtils::is_complex(*v_m_type)) { headers.insert("complex"); @@ -340,8 +378,13 @@ class ASRToCVisitor : public BaseCCPPVisitor } } else { bool is_fixed_size = true; + std::string v_m_name = v.m_name; + if( declare_as_constant ) { + type_name = "const " + type_name; + v_m_name = const_name; + } dims = convert_dims_c(t->n_dims, t->m_dims, v_m_type, is_fixed_size); - sub = format_type_c(dims, type_name, v.m_name, use_ref, dummy); + sub = format_type_c(dims, type_name, v_m_name, use_ref, dummy); } } else if (ASRUtils::is_logical(*v_m_type)) { ASR::Logical_t *t = ASR::down_cast(v_m_type); @@ -731,12 +774,15 @@ R"( indentation_level += 1; std::string open_struct = indent + c_type_name + " " + std::string(x.m_name) + " {\n"; indent.push_back(' '); + CDeclarationOptions c_decl_options_; + c_decl_options_.pre_initialise_derived_type = false; + c_decl_options_.use_ptr_for_derived_type = false; for( size_t i = 0; i < x.n_members; i++ ) { ASR::symbol_t* member = x.m_symtab->get_symbol(x.m_members[i]); LFORTRAN_ASSERT(ASR::is_a(*member)); body += indent + convert_variable_decl( *ASR::down_cast(member), - false, false); + &c_decl_options_); if( !ASR::is_a(*ASRUtils::symbol_type(member)) || ASR::down_cast(member)->m_intent == ASRUtils::intent_return_var ) { body += ";\n"; diff --git a/src/libasr/codegen/asr_to_c_cpp.h b/src/libasr/codegen/asr_to_c_cpp.h index 15cd92b70d..239b93ed64 100644 --- a/src/libasr/codegen/asr_to_c_cpp.h +++ b/src/libasr/codegen/asr_to_c_cpp.h @@ -30,7 +30,6 @@ namespace LFortran { - // Platform dependent fast unique hash: static inline uint64_t get_hash(ASR::asr_t *node) { @@ -43,6 +42,38 @@ struct SymbolInfo bool intrinsic_function = false; }; +struct DeclarationOptions { +}; + +struct CDeclarationOptions: public DeclarationOptions { + bool pre_initialise_derived_type; + bool use_ptr_for_derived_type; + bool use_static; + bool force_declare; + std::string force_declare_name; + bool declare_as_constant; + std::string const_name; + + CDeclarationOptions() : + pre_initialise_derived_type{true}, + use_ptr_for_derived_type{true}, + use_static{true}, + force_declare{false}, + force_declare_name{""}, + declare_as_constant{false}, + const_name{""} { + } +}; + +struct CPPDeclarationOptions: public DeclarationOptions { + bool use_static; + bool use_templates_for_arrays; + + CPPDeclarationOptions() : + use_static{true}, + use_templates_for_arrays{false} { + } +}; template class BaseCCPPVisitor : public ASR::BaseVisitor @@ -376,9 +407,14 @@ R"(#include ASR::Variable_t *arg = LFortran::ASRUtils::EXPR2VAR(x.m_args[i]); LFORTRAN_ASSERT(LFortran::ASRUtils::is_arg_dummy(arg->m_intent)); if( is_c ) { - func += self().convert_variable_decl(*arg, false); + CDeclarationOptions c_decl_options; + c_decl_options.pre_initialise_derived_type = false; + func += self().convert_variable_decl(*arg, &c_decl_options); } else { - func += self().convert_variable_decl(*arg, false, true); + CPPDeclarationOptions cpp_decl_options; + cpp_decl_options.use_static = false; + cpp_decl_options.use_templates_for_arrays = true; + func += self().convert_variable_decl(*arg, &cpp_decl_options); } if (i < x.n_args-1) func += ", "; } @@ -458,6 +494,29 @@ R"(#include } } + for (auto &item : x.m_symtab->get_scope()) { + ASR::symbol_t* var_sym = item.second; + if( ASR::is_a(*var_sym) ) { + ASR::ExternalSymbol_t* v_ext = ASR::down_cast(var_sym); + ASR::symbol_t* v_sym = v_ext->m_external; + if (ASR::is_a(*v_sym)) { + ASR::Variable_t* v = ASR::down_cast(v_sym); + if( v->m_symbolic_value ) { + if( is_c ) { + CDeclarationOptions c_decl_options; + c_decl_options.declare_as_constant = true; + c_decl_options.const_name = v_ext->m_name; + decl += indent + self().convert_variable_decl(*v, &c_decl_options) + ";\n"; + } else { + // TODO: Do for CPP when the use case shows up + decl += indent + self().convert_variable_decl(*v) + ";\n"; + } + src.clear(); + } + } + } + } + current_function = &x; for (size_t i=0; i sv->m_intent == ASRUtils::intent_inout) && is_c && ASRUtils::is_array(sv->m_type) && ASRUtils::is_pointer(sv->m_type)) { - src = "(*" + std::string(ASR::down_cast(s)->m_name) + ")"; + src = "(*" + std::string(ASRUtils::symbol_name(x.m_v)) + ")"; } else { - src = std::string(ASR::down_cast(s)->m_name); + src = std::string(ASRUtils::symbol_name(x.m_v)); } last_expr_precedence = 2; } diff --git a/src/libasr/codegen/asr_to_cpp.cpp b/src/libasr/codegen/asr_to_cpp.cpp index da61503a49..70dda0a753 100644 --- a/src/libasr/codegen/asr_to_cpp.cpp +++ b/src/libasr/codegen/asr_to_cpp.cpp @@ -209,9 +209,20 @@ class ASRToCPPVisitor : public BaseCCPPVisitor return typename_T + "* " + v_name; } - std::string convert_variable_decl(const ASR::Variable_t &v, bool use_static=true, - bool use_templates_for_arrays=false) + std::string convert_variable_decl(const ASR::Variable_t &v, DeclarationOptions* decl_options=nullptr) { + bool use_static; + bool use_templates_for_arrays; + + if( decl_options ) { + CPPDeclarationOptions* cpp_decl_options = reinterpret_cast(decl_options); + use_static = cpp_decl_options->use_static; + use_templates_for_arrays = cpp_decl_options->use_templates_for_arrays; + } else { + use_static = true; + use_templates_for_arrays = false; + } + std::string sub; bool use_ref = (v.m_intent == LFortran::ASRUtils::intent_out || v.m_intent == LFortran::ASRUtils::intent_inout || diff --git a/src/libasr/runtime/lfortran_intrinsics.c b/src/libasr/runtime/lfortran_intrinsics.c index 45ca9a931c..1c9f960f61 100644 --- a/src/libasr/runtime/lfortran_intrinsics.c +++ b/src/libasr/runtime/lfortran_intrinsics.c @@ -246,6 +246,16 @@ LFORTRAN_API double _lfortran_dlog(double x) return log(x); } +LFORTRAN_API float _lfortran_slog1p(float x) +{ + return log1pf(x); +} + +LFORTRAN_API double _lfortran_dlog1p(double x) +{ + return log1p(x); +} + LFORTRAN_API float_complex_t _lfortran_clog(float_complex_t x) { return clogf(x); diff --git a/src/libasr/runtime/lfortran_intrinsics.h b/src/libasr/runtime/lfortran_intrinsics.h index b72fcb57cc..4d71238506 100644 --- a/src/libasr/runtime/lfortran_intrinsics.h +++ b/src/libasr/runtime/lfortran_intrinsics.h @@ -76,6 +76,8 @@ LFORTRAN_API float _lfortran_slog(float x); LFORTRAN_API double _lfortran_dlog(double x); LFORTRAN_API float_complex_t _lfortran_clog(float_complex_t x); LFORTRAN_API double_complex_t _lfortran_zlog(double_complex_t x); +LFORTRAN_API float _lfortran_slog1p(float x); +LFORTRAN_API double _lfortran_dlog1p(double x); LFORTRAN_API float _lfortran_serf(float x); LFORTRAN_API double _lfortran_derf(double x); LFORTRAN_API float _lfortran_serfc(float x); diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index d7117131f5..1d7eb18443 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -4864,13 +4864,30 @@ class BodyVisitor : public CommonVisitor { } } else if (ASR::is_a(*t)) { ASR::Module_t *m = ASR::down_cast(t); - std::string sym_name = value + "@" + x.m_attr; + std::string sym_name = value + "_" + x.m_attr + "_external__"; ASR::symbol_t *sym = current_scope->resolve_symbol(sym_name); if (!sym) { sym = import_from_module(al, m, current_scope, value, x.m_attr, sym_name, x.base.base.loc, false); LFORTRAN_ASSERT(ASR::is_a(*sym)); current_scope->add_symbol(sym_name, sym); + } else { + if( ASR::is_a(*sym) ) { + ASR::ExternalSymbol_t* ext_sym = ASR::down_cast(sym); + if( ext_sym->m_external != m->m_symtab->resolve_symbol(std::string(x.m_attr)) ) { + sym_name = current_scope->get_unique_name(sym_name); + sym = import_from_module(al, m, current_scope, value, + x.m_attr, sym_name, x.base.base.loc, false); + LFORTRAN_ASSERT(ASR::is_a(*sym)); + current_scope->add_symbol(sym_name, sym); + } + } else { + sym_name = current_scope->get_unique_name(sym_name); + sym = import_from_module(al, m, current_scope, value, + x.m_attr, sym_name, x.base.base.loc, false); + LFORTRAN_ASSERT(ASR::is_a(*sym)); + current_scope->add_symbol(sym_name, sym); + } } tmp = ASR::make_Var_t(al, x.base.base.loc, sym); } else { diff --git a/src/runtime/math.py b/src/runtime/math.py index 379581c528..2a5b861144 100644 --- a/src/runtime/math.py +++ b/src/runtime/math.py @@ -563,10 +563,19 @@ def _lfortran_dtan(x: f64) -> f64: def tan(x: f64) -> f64: return _lfortran_dtan(x) +@ccall +def _lfortran_slog(x: f32) -> f32: + pass + +@overload +def log(x: f32) -> f32: + return _lfortran_slog(x) + @ccall def _lfortran_dlog(x: f64) -> f64: pass +@overload def log(x: f64) -> f64: return _lfortran_dlog(x) @@ -682,21 +691,43 @@ def atanh(x: f64) -> f64: def expm1(x: f64) -> f64: return exp(x) - 1.0 +@ccall +def _lfortran_slog1p(x: f32) -> f32: + pass + +@overload +def log1p(x: f32) -> f32: + return _lfortran_slog1p(x) + +@ccall +def _lfortran_dlog1p(x: f64) -> f64: + pass +@overload def log1p(x: f64) -> f64: - return log(1.0 + x) + return _lfortran_dlog1p(x) + +@ccall +def _lfortran_dfmod(x: f64, y: f64) -> f64: + pass +@overload def fmod(x: f64, y: f64) -> f64: if y == 0.0: raise ValueError('math domain error') return _lfortran_dfmod(x, y) - @ccall -def _lfortran_dfmod(x: f64, y: f64) -> f64: +def _lfortran_sfmod(x: f32, y: f32) -> f32: pass +@overload +def fmod(x: f32, y: f32) -> f32: + if y == f32(0.0): + raise ValueError('math domain error') + return _lfortran_sfmod(x, y) + def remainder(x: f64, y: f64) -> f64: q: i64