diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 028ce8614c..517555188b 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -216,6 +216,4 @@ RUN(NAME test_str_comparison LABELS cpython llvm) RUN(NAME generics_01 LABELS cpython llvm) RUN(NAME generics_array_01 LABELS llvm) - -# Just CPython -RUN(NAME test_statistics LABELS cpython) +RUN(NAME test_statistics LABELS cpython llvm) diff --git a/integration_tests/test_statistics.py b/integration_tests/test_statistics.py index cb101af163..bd1c018fa2 100644 --- a/integration_tests/test_statistics.py +++ b/integration_tests/test_statistics.py @@ -1,4 +1,4 @@ -from statistics import (mean, geometric_mean, harmonic_mean) +from statistics import (mean, geometric_mean, harmonic_mean, fmean) from ltypes import i32, f64, i64 eps: f64 @@ -17,6 +17,26 @@ def test_mean(): k = mean(c) assert abs(k - 5.4) < eps + d: list[i32] + d = [1, 3, 11] + l: f64 + l = mean(d) + assert abs(l - 5) < eps + +def test_fmean(): + a: list[i32] + a = [9, 4, 10] + j: f64 + j = fmean(a) + assert abs(j - 7.666666666666667) < eps + + b: list[f64] + b = [-1.9, -13.8, -6.0, 4.2, 5.9, 9.1] + k: f64 + k = fmean(b) + assert abs(k + 0.41666666666666674) < eps + + def test_geometric_mean(): c: list[i32] c = [1,2,3] @@ -31,10 +51,10 @@ def test_harmonic_mean(): k = harmonic_mean(c) assert abs(k - 4.740458015267175) < eps - def check(): test_mean() test_geometric_mean() test_harmonic_mean() + test_fmean() check() diff --git a/src/libasr/asr_utils.cpp b/src/libasr/asr_utils.cpp index e6907ab710..b57f100ff9 100644 --- a/src/libasr/asr_utils.cpp +++ b/src/libasr/asr_utils.cpp @@ -659,6 +659,11 @@ bool types_equal(const ASR::ttype_t &a, const ASR::ttype_t &b) { } break; } + case (ASR::ttypeType::List) : { + ASR::List_t *a2 = ASR::down_cast(&a); + ASR::List_t *b2 = ASR::down_cast(&b); + return types_equal(*a2->m_type, *b2->m_type); + } case (ASR::ttypeType::Derived) : { ASR::Derived_t *a2 = ASR::down_cast(&a); ASR::Derived_t *b2 = ASR::down_cast(&b); diff --git a/src/libasr/codegen/asr_to_llvm.cpp b/src/libasr/codegen/asr_to_llvm.cpp index b6f2109db3..84c524630b 100644 --- a/src/libasr/codegen/asr_to_llvm.cpp +++ b/src/libasr/codegen/asr_to_llvm.cpp @@ -2195,6 +2195,20 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor type = tuple_api->get_tuple_type(type_code, llvm_el_types)->getPointerTo(); break; } + case (ASR::ttypeType::List) : { + bool is_array_type = false, is_malloc_array_type = false; + bool is_list = true; + ASR::dimension_t *m_dims = nullptr; + ASR::List_t* asr_list = ASR::down_cast(asr_type); + llvm::Type* el_llvm_type = get_type_from_ttype_t(asr_list->m_type, m_storage, + is_array_type, + is_malloc_array_type, + is_list, m_dims, n_dims, + a_kind); + std::string el_type_code = ASRUtils::get_type_code(asr_list->m_type); + type = list_api->get_list_type(el_llvm_type, el_type_code, a_kind)->getPointerTo(); + break; + } default : LFORTRAN_ASSERT(false); } diff --git a/src/runtime/statistics.py b/src/runtime/statistics.py index daa8268b81..555c72a052 100644 --- a/src/runtime/statistics.py +++ b/src/runtime/statistics.py @@ -1,7 +1,11 @@ -from ltypes import i32, f64 +from ltypes import i32, f64, overload + @overload def mean(x: list[i32]) -> f64: + """ + Returns the arithmetic mean of a data sequence of numbers + """ k: i32 = len(x) if k == 0: return 0.0 @@ -11,54 +15,123 @@ def mean(x: list[i32]) -> f64: for i in range(k): sum += x[i] - ans: f64 - ans = sum/k - return ans + return sum/k + + +@overload +def mean(x: list[i64]) -> f64: + """ + Returns the arithmetic mean of a data sequence of numbers + """ + k: i32 = len(x) + if k == 0: + return 0.0 + sum: f64 + sum = 0.0 + i: i32 + + for i in range(k): + sum += x[i] + + return sum/k + + +@overload +def mean(x: list[f32]) -> f64: + """ + Returns the arithmetic mean of a data sequence of numbers + """ + k: i32 = len(x) + if k == 0: + return 0.0 + sum: f64 + sum = 0.0 + i: i32 + + for i in range(k): + sum += x[i] + return sum/k + @overload def mean(x: list[f64]) -> f64: + """ + Returns the arithmetic mean of a data sequence of numbers + """ k: i32 = len(x) if k == 0: return 0.0 sum: f64 sum = 0.0 i: i32 + for i in range(k): sum += x[i] - ans: f64 - ans = sum/k - return ans + return sum/k + + +@overload +def fmean(x: list[i32]) -> f64: + """ + Returns the floating type arithmetic mean of a data sequence of numbers + """ + return mean(x) + + +@overload +def fmean(x: list[i64]) -> f64: + """ + Returns the floating type arithmetic mean of a data sequence of numbers + """ + return mean(x) + + +@overload +def fmean(x: list[f64]) -> f64: + """ + Returns the floating type arithmetic mean of a data sequence of numbers + """ + return mean(x) + @overload +def fmean(x: list[f32]) -> f64: + """ + Returns the floating type arithmetic mean of a data sequence of numbers + """ + return mean(x) + + def geometric_mean(x: list[i32]) -> f64: + """ + Returns the geometric mean of a data sequence of numbers + """ k: i32 = len(x) if k == 0: return 0.0 product: f64 product = 1.0 i: i32 + for i in range(k): - if x[i] < 1: - raise ValueError('geometric mean requires a non-empty dataset containing positive numbers') product *= x[i] - ans: f64 - ans = product**(1/k) - return ans -@overload + return product**(1/k) + + def harmonic_mean(x: list[i32]) -> f64: + """ + Returns the harmonic mean of a data sequence of numbers + """ k: i32 = len(x) if k == 0: return 0.0 sum: f64 sum = 0.0 i: i32 + for i in range(k): - if x[i] < 0: - raise ValueError('harmonic mean does not support negative values') - if x[i] ==0: + if x[i] == 0: return 0.0 sum += 1 / x[i] - ans: f64 - ans = k/sum - return ans + return k/sum