TimedeltaArray#

class pandas::TimedeltaArray#

Extension array type for specialized data storage.

Example#

#include <pandas/pandas.h>
using namespace pandas;

// Use TimedeltaArray
TimedeltaArray obj;
// ... operations ...

Constructors#

Signature

Location

Example

TimedeltaArray(const numpy::NDArray<numpy::timedelta64>& data, const numpy::NDArray<numpy::bool_>& mask, bool copy = false)

pd_timedelta_array.h:208

View

TimedeltaArray(const numpy::NDArray<int64_t>& data, const numpy::NDArray<numpy::bool_>& mask, numpy::DateTimeUnit unit, bool copy = false)

pd_timedelta_array.h:239

View

explicit TimedeltaArray(const numpy::NDArray<numpy::timedelta64>& data)

pd_timedelta_array.h:254

View

explicit TimedeltaArray(const std::vector<std::optional<numpy::timedelta64>>& values)

pd_timedelta_array.h:305

View

explicit TimedeltaArray(const std::vector<std::string>& duration_strings)

pd_timedelta_array.h:328

View

Construction#

Signature

Return Type

Location

Example

static TimedeltaArray from_sequence(const std::vector<std::optional<numpy::timedelta64>>& scalars)

static TimedeltaArray

pd_timedelta_array.h:550

Indexing / Selection#

Signature

Return Type

Location

Example

numpy::timedelta64 at(size_t index) const

numpy::timedelta64

pd_timedelta_array.h:457

View

const numpy::NDArray<numpy::bool_>& mask() const

const numpy::NDArray<numpy::bool_>&

pd_timedelta_array.h:437

View

TimedeltaArray take(const std::vector<size_t>& indices, bool allow_fill = false, std::optional<numpy::timedelta64> fill_value = std::nullopt) const

TimedeltaArray

pd_timedelta_array.h:504

View

Data Manipulation#

Signature

Return Type

Location

Example

TimedeltaArray dropna() const

TimedeltaArray

pd_timedelta_array.h:601

View

Missing Data#

Signature

Return Type

Location

Example

TimedeltaArray fillna(const numpy::timedelta64& value) const

TimedeltaArray

pd_timedelta_array.h:586

View

numpy::NDArray<numpy::bool_> isna() const

numpy::NDArray<numpy::bool_>

pd_timedelta_array.h:479

View

numpy::NDArray<numpy::bool_> notna() const

numpy::NDArray<numpy::bool_>

pd_timedelta_array.h:486

View

Statistics#

Signature

Return Type

Location

Example

size_t count() const

size_t

pd_timedelta_array.h:652

View

std::optional<numpy::timedelta64> max() const

std::optional<numpy::timedelta64>

pd_timedelta_array.h:960

View

std::optional<numpy::timedelta64> min() const

std::optional<numpy::timedelta64>

pd_timedelta_array.h:951

View

Comparison#

Signature

Return Type

Location

Example

size_t len() const

size_t

pd_timedelta_array.h:408

View

Sorting#

Signature

Return Type

Location

Example

numpy::NDArray<size_t> argsort(bool ascending = true, const std::string& na_position = "last") const

numpy::NDArray<size_t>

pd_timedelta_array.h:877

View

Combining#

Signature

Return Type

Location

Example

static TimedeltaArray concat(const std::vector<TimedeltaArray>& arrays)

static TimedeltaArray

pd_timedelta_array.h:557

View

I/O#

Signature

Return Type

Location

Example

std::vector<std::optional<PyTimedelta>> to_pytimedelta() const

std::vector<std::optional<PyTimedelta>>

pd_timedelta_array.h:1104

View

std::string to_string() const

std::string

pd_timedelta_array.h:1500

View

Conversion#

Signature

Return Type

Location

Example

TimedeltaArray copy() const

TimedeltaArray

pd_timedelta_array.h:497

View

Set Operations#

Signature

Return Type

Location

Example

TimedeltaArray unique() const

TimedeltaArray

pd_timedelta_array.h:815

View

Type Checking#

Signature

Return Type

Location

Example

bool is_na(size_t index) const

bool

pd_timedelta_array.h:468

View

BooleanArray is_negative() const

BooleanArray

pd_timedelta_array.h:1218

View

BooleanArray is_positive() const

BooleanArray

pd_timedelta_array.h:1199

View

BooleanArray is_zero() const

BooleanArray

pd_timedelta_array.h:1237

View

Other Methods#

Signature

Return Type

Location

Example

TimedeltaArray abs() const

TimedeltaArray

pd_timedelta_array.h:1398

View

std::optional<size_t> argmax() const

std::optional<size_t>

pd_timedelta_array.h:929

View

std::optional<size_t> argmin() const

std::optional<size_t>

pd_timedelta_array.h:909

View

TimedeltaArray ceil(const std::string& freq) const

TimedeltaArray

pd_timedelta_array.h:1446

View

DataFrame components_to_dataframe() const

DataFrame

pd_timedelta_array.h:1527

const numpy::NDArray<int64_t>& data() const

const numpy::NDArray<int64_t>&

pd_timedelta_array.h:430

View

IntegerArray<numpy::int64> days() const

IntegerArray<numpy::int64>

pd_timedelta_array.h:973

View

void detect_unit()

void

pd_timedelta_array.h:1556

dtype_type dtype() const

dtype_type

pd_timedelta_array.h:366

View

bool empty() const

bool

pd_timedelta_array.h:401

View

std::pair<numpy::NDArray<numpy::int64>, TimedeltaArray> factorize() const

std::pair<numpy::NDArray<numpy::int64>, TimedeltaArray>

pd_timedelta_array.h:841

View

TimedeltaArray floor(const std::string& freq) const

TimedeltaArray

pd_timedelta_array.h:1421

View

static inline int64_t floor_div(int64_t a, int64_t b)

static inline int64_t

pd_timedelta_array.h:161

bool has_na() const

bool

pd_timedelta_array.h:665

View

IntegerArray<numpy::int64> microseconds() const

IntegerArray<numpy::int64>

pd_timedelta_array.h:1016

View

IntegerArray<numpy::int64> nanoseconds() const

IntegerArray<numpy::int64>

pd_timedelta_array.h:1039

View

size_t nbytes() const

size_t

pd_timedelta_array.h:380

View

constexpr int ndim() const

constexpr int

pd_timedelta_array.h:387

View

static int64_t parse_freq_to_seconds(const std::string& freq)

static int64_t

pd_timedelta_array.h:1560

std::string repr() const

std::string

pd_timedelta_array.h:1517

View

TimedeltaArray round(const std::string& freq) const

TimedeltaArray

pd_timedelta_array.h:1471

View

IntegerArray<numpy::int64> seconds() const

IntegerArray<numpy::int64>

pd_timedelta_array.h:992

View

std::vector<size_t> shape() const

std::vector<size_t>

pd_timedelta_array.h:394

View

size_t size() const

size_t

pd_timedelta_array.h:373

View

numpy::timedelta64 td(duration_strings[i])

numpy::timedelta64

pd_timedelta_array.h:340

View

FloatingArray<numpy::float64> total_seconds() const

FloatingArray<numpy::float64>

pd_timedelta_array.h:1077

View

numpy::DateTimeUnit unit() const

numpy::DateTimeUnit

pd_timedelta_array.h:415

View

void validate_arrays()

void

pd_timedelta_array.h:1534

Internal Methods#

2 internal methods (prefixed with underscore)

Code Examples#

The following examples are extracted from the test suite.

TimedeltaArray (pd_test_3_all.cpp:27945)
27935static pandas::TimedeltaArray make_tda(const std::vector<double>& ns_values) {
27936    std::vector<std::optional<numpy::timedelta64>> vals;
27937    vals.reserve(ns_values.size());
27938    for (double ns : ns_values) {
27939        if (std::isnan(ns)) {
27940            vals.push_back(std::nullopt);
27941        } else {
27942            vals.push_back(numpy::timedelta64(static_cast<int64_t>(ns), numpy::DateTimeUnit::Nanosecond));
27943        }
27944    }
27945    return pandas::TimedeltaArray(vals);
27946}
27947
27948void pd_test_td_decompose_positive() {
27949    std::cout << "  -- pd_test_td_decompose_positive --" << std::endl;
27950    int fail = 0;
27951    constexpr int64_t NS = 1000000000LL;
27952    int64_t total_ns = (1 * 86400 + 2 * 3600 + 3 * 60 + 4) * NS;
27953    auto tda = make_tda({static_cast<double>(total_ns)});
27954    auto days = tda.days();
27955    auto secs = tda.seconds();
TimedeltaArray (pd_test_3_all.cpp:27945)
27935static pandas::TimedeltaArray make_tda(const std::vector<double>& ns_values) {
27936    std::vector<std::optional<numpy::timedelta64>> vals;
27937    vals.reserve(ns_values.size());
27938    for (double ns : ns_values) {
27939        if (std::isnan(ns)) {
27940            vals.push_back(std::nullopt);
27941        } else {
27942            vals.push_back(numpy::timedelta64(static_cast<int64_t>(ns), numpy::DateTimeUnit::Nanosecond));
27943        }
27944    }
27945    return pandas::TimedeltaArray(vals);
27946}
27947
27948void pd_test_td_decompose_positive() {
27949    std::cout << "  -- pd_test_td_decompose_positive --" << std::endl;
27950    int fail = 0;
27951    constexpr int64_t NS = 1000000000LL;
27952    int64_t total_ns = (1 * 86400 + 2 * 3600 + 3 * 60 + 4) * NS;
27953    auto tda = make_tda({static_cast<double>(total_ns)});
27954    auto days = tda.days();
27955    auto secs = tda.seconds();
TimedeltaArray (pd_test_3_all.cpp:27945)
27935static pandas::TimedeltaArray make_tda(const std::vector<double>& ns_values) {
27936    std::vector<std::optional<numpy::timedelta64>> vals;
27937    vals.reserve(ns_values.size());
27938    for (double ns : ns_values) {
27939        if (std::isnan(ns)) {
27940            vals.push_back(std::nullopt);
27941        } else {
27942            vals.push_back(numpy::timedelta64(static_cast<int64_t>(ns), numpy::DateTimeUnit::Nanosecond));
27943        }
27944    }
27945    return pandas::TimedeltaArray(vals);
27946}
27947
27948void pd_test_td_decompose_positive() {
27949    std::cout << "  -- pd_test_td_decompose_positive --" << std::endl;
27950    int fail = 0;
27951    constexpr int64_t NS = 1000000000LL;
27952    int64_t total_ns = (1 * 86400 + 2 * 3600 + 3 * 60 + 4) * NS;
27953    auto tda = make_tda({static_cast<double>(total_ns)});
27954    auto days = tda.days();
27955    auto secs = tda.seconds();
TimedeltaArray (pd_test_3_all.cpp:27945)
27935static pandas::TimedeltaArray make_tda(const std::vector<double>& ns_values) {
27936    std::vector<std::optional<numpy::timedelta64>> vals;
27937    vals.reserve(ns_values.size());
27938    for (double ns : ns_values) {
27939        if (std::isnan(ns)) {
27940            vals.push_back(std::nullopt);
27941        } else {
27942            vals.push_back(numpy::timedelta64(static_cast<int64_t>(ns), numpy::DateTimeUnit::Nanosecond));
27943        }
27944    }
27945    return pandas::TimedeltaArray(vals);
27946}
27947
27948void pd_test_td_decompose_positive() {
27949    std::cout << "  -- pd_test_td_decompose_positive --" << std::endl;
27950    int fail = 0;
27951    constexpr int64_t NS = 1000000000LL;
27952    int64_t total_ns = (1 * 86400 + 2 * 3600 + 3 * 60 + 4) * NS;
27953    auto tda = make_tda({static_cast<double>(total_ns)});
27954    auto days = tda.days();
27955    auto secs = tda.seconds();
TimedeltaArray (pd_test_3_all.cpp:27945)
27935static pandas::TimedeltaArray make_tda(const std::vector<double>& ns_values) {
27936    std::vector<std::optional<numpy::timedelta64>> vals;
27937    vals.reserve(ns_values.size());
27938    for (double ns : ns_values) {
27939        if (std::isnan(ns)) {
27940            vals.push_back(std::nullopt);
27941        } else {
27942            vals.push_back(numpy::timedelta64(static_cast<int64_t>(ns), numpy::DateTimeUnit::Nanosecond));
27943        }
27944    }
27945    return pandas::TimedeltaArray(vals);
27946}
27947
27948void pd_test_td_decompose_positive() {
27949    std::cout << "  -- pd_test_td_decompose_positive --" << std::endl;
27950    int fail = 0;
27951    constexpr int64_t NS = 1000000000LL;
27952    int64_t total_ns = (1 * 86400 + 2 * 3600 + 3 * 60 + 4) * NS;
27953    auto tda = make_tda({static_cast<double>(total_ns)});
27954    auto days = tda.days();
27955    auto secs = tda.seconds();
at (pd_test_1_all.cpp:6581)
6571            // Test isna/notna with float data
6572            {
6573                std::map<std::string, std::vector<numpy::float64>> float_data;
6574                float_data["X"] = {1.0, std::nan(""), 3.0};
6575                float_data["Y"] = {4.0, 5.0, std::nan("")};
6576                pandas::DataFrame df_na(float_data);
6577
6578                auto na_mask = df_na.isna();
6579                // Row 1, col 0 (X) should be NA
6580                if (!na_mask.getElementAt({1, 0})) {
6581                    std::cout << "  [FAIL] : in pd_test_dataframe_manipulation() : isna at (1,0) should be true" << std::endl;
6582                    throw std::runtime_error("pd_test_dataframe_manipulation failed: isna at (1,0)");
6583                }
6584                // Row 2, col 1 (Y) should be NA
6585                if (!na_mask.getElementAt({2, 1})) {
6586                    std::cout << "  [FAIL] : in pd_test_dataframe_manipulation() : isna at (2,1) should be true" << std::endl;
6587                    throw std::runtime_error("pd_test_dataframe_manipulation failed: isna at (2,1)");
6588                }
6589                // Row 0, col 0 should NOT be NA
6590                if (na_mask.getElementAt({0, 0})) {
6591                    std::cout << "  [FAIL] : in pd_test_dataframe_manipulation() : isna at (0,0) should be false" << std::endl;
mask (pd_test_1_all.cpp:9119)
9109void pd_test_datetime_mixin_array_constructor() {
9110    std::cout << "========= DatetimeTDMixin array constructor =========================";
9111
9112    // Create DatetimeArray with some values
9113    numpy::NDArray<numpy::datetime64> data(std::vector<size_t>{3});
9114    data.setElementAt({0}, numpy::datetime64(1000000000000000000LL, numpy::DateTimeUnit::Nanosecond));  // ~2001
9115    data.setElementAt({1}, numpy::datetime64(1500000000000000000LL, numpy::DateTimeUnit::Nanosecond));  // ~2017
9116    data.setElementAt({2}, numpy::datetime64(1600000000000000000LL, numpy::DateTimeUnit::Nanosecond));  // ~2020
9117
9118    numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{3});
9119    mask.setElementAt({0}, numpy::bool_(false));
9120    mask.setElementAt({1}, numpy::bool_(false));
9121    mask.setElementAt({2}, numpy::bool_(false));
9122
9123    pandas::DatetimeArray arr(data, mask);
9124    pandas::DatetimeTDMixin idx(arr, "timestamps");
9125
9126    bool passed = (idx.size() == 3 && !idx.empty() &&
9127                   idx.name().has_value() && *idx.name() == "timestamps" &&
9128                   idx.inferred_type() == "datetime");
take (pd_test_1_all.cpp:5903)
5893// Inherited Operations Tests
5894// ============================================================================
5895
5896void pd_test_categorical_index_take() {
5897    std::cout << "========= inherited take ==============================";
5898
5899    pandas::CategoricalArray arr({"a", "b", "c", "d"});
5900    pandas::CategoricalIndex idx(arr);
5901
5902    std::vector<size_t> indices = {0, 2, 3};
5903    pandas::ExtensionIndex<pandas::CategoricalArray> taken = idx.take(indices);
5904
5905    bool passed = (taken.size() == 3);
5906    if (!passed) {
5907        std::cout << "  [FAIL] : in pd_test_categorical_index_take()" << std::endl;
5908        throw std::runtime_error("pd_test_categorical_index_take failed");
5909    }
5910
5911    std::cout << " -> tests passed" << std::endl;
5912}
dropna (pd_test_1_all.cpp:531)
521        }
522
523        // Test isna array
524        numpy::NDArray<numpy::bool_> na_mask = arr.isna();
525        if (na_mask.getSize() != 4) {
526            std::cout << "  [FAIL] : in pd_test_categorical_array_na_handling() : isna size != 4" << std::endl;
527            throw std::runtime_error("pd_test_categorical_array_na_handling failed: isna size != 4");
528        }
529
530        // Test dropna
531        pandas::CategoricalArray dropped = arr.dropna();
532        if (dropped.size() != 2) {
533            std::cout << "  [FAIL] : in pd_test_categorical_array_na_handling() : dropna size != 2" << std::endl;
534            throw std::runtime_error("pd_test_categorical_array_na_handling failed: dropna size != 2");
535        }
536
537        // Test fillna (fill with existing category)
538        pandas::CategoricalArray filled = arr.fillna("a");  // 'a' is in categories
539        if (filled.has_na()) {
540            std::cout << "  [FAIL] : in pd_test_categorical_array_na_handling() : fillna should have no NA" << std::endl;
541            throw std::runtime_error("pd_test_categorical_array_na_handling failed: fillna should have no NA");
fillna (pd_test_1_all.cpp:537)
527            throw std::runtime_error("pd_test_categorical_array_na_handling failed: isna size != 4");
528        }
529
530        // Test dropna
531        pandas::CategoricalArray dropped = arr.dropna();
532        if (dropped.size() != 2) {
533            std::cout << "  [FAIL] : in pd_test_categorical_array_na_handling() : dropna size != 2" << std::endl;
534            throw std::runtime_error("pd_test_categorical_array_na_handling failed: dropna size != 2");
535        }
536
537        // Test fillna (fill with existing category)
538        pandas::CategoricalArray filled = arr.fillna("a");  // 'a' is in categories
539        if (filled.has_na()) {
540            std::cout << "  [FAIL] : in pd_test_categorical_array_na_handling() : fillna should have no NA" << std::endl;
541            throw std::runtime_error("pd_test_categorical_array_na_handling failed: fillna should have no NA");
542        }
543
544        std::cout << " -> tests passed" << std::endl;
545    }
546
547    void pd_test_categorical_array_add_categories() {
isna (pd_test_1_all.cpp:524)
514            throw std::runtime_error("pd_test_categorical_array_na_handling failed: has_na() should be true");
515        }
516
517        // Test count (non-NA)
518        if (arr.count() != 2) {
519            std::cout << "  [FAIL] : in pd_test_categorical_array_na_handling() : count() != 2" << std::endl;
520            throw std::runtime_error("pd_test_categorical_array_na_handling failed: count() != 2");
521        }
522
523        // Test isna array
524        numpy::NDArray<numpy::bool_> na_mask = arr.isna();
525        if (na_mask.getSize() != 4) {
526            std::cout << "  [FAIL] : in pd_test_categorical_array_na_handling() : isna size != 4" << std::endl;
527            throw std::runtime_error("pd_test_categorical_array_na_handling failed: isna size != 4");
528        }
529
530        // Test dropna
531        pandas::CategoricalArray dropped = arr.dropna();
532        if (dropped.size() != 2) {
533            std::cout << "  [FAIL] : in pd_test_categorical_array_na_handling() : dropna size != 2" << std::endl;
534            throw std::runtime_error("pd_test_categorical_array_na_handling failed: dropna size != 2");
notna (pd_test_1_all.cpp:6595)
6585                if (!na_mask.getElementAt({2, 1})) {
6586                    std::cout << "  [FAIL] : in pd_test_dataframe_manipulation() : isna at (2,1) should be true" << std::endl;
6587                    throw std::runtime_error("pd_test_dataframe_manipulation failed: isna at (2,1)");
6588                }
6589                // Row 0, col 0 should NOT be NA
6590                if (na_mask.getElementAt({0, 0})) {
6591                    std::cout << "  [FAIL] : in pd_test_dataframe_manipulation() : isna at (0,0) should be false" << std::endl;
6592                    throw std::runtime_error("pd_test_dataframe_manipulation failed: isna at (0,0)");
6593                }
6594
6595                auto notna_mask = df_na.notna();
6596                if (notna_mask.getElementAt({1, 0})) {
6597                    std::cout << "  [FAIL] : in pd_test_dataframe_manipulation() : notna at (1,0) should be false" << std::endl;
6598                    throw std::runtime_error("pd_test_dataframe_manipulation failed: notna at (1,0)");
6599                }
6600            }
6601
6602            // Test fillna
6603            {
6604                std::map<std::string, std::vector<numpy::float64>> float_data;
6605                float_data["X"] = {1.0, std::nan(""), 3.0};
count (pd_test_1_all.cpp:66)
56        if (arr.is_na(0)) {
57            std::cout << "  [FAIL] : in pd_test_boolean_array_na_handling() : is_na(0) should be false" << std::endl;
58            throw std::runtime_error("pd_test_boolean_array_na_handling failed: is_na(0) should be false");
59        }
60
61        if (!arr.has_na()) {
62            std::cout << "  [FAIL] : in pd_test_boolean_array_na_handling() : has_na() should be true" << std::endl;
63            throw std::runtime_error("pd_test_boolean_array_na_handling failed: has_na() should be true");
64        }
65
66        if (arr.count() != 2) {
67            std::cout << "  [FAIL] : in pd_test_boolean_array_na_handling() : count() should be 2" << std::endl;
68            throw std::runtime_error("pd_test_boolean_array_na_handling failed: count() should be 2");
69        }
70
71        std::cout << " -> tests passed" << std::endl;
72    }
73
74    void pd_test_boolean_array_kleene_and() {
75        std::cout << "========= BooleanArray: Kleene AND ======================= ";
max (pd_test_1_all.cpp:771)
761        pandas::CategoricalArray arr = pandas::CategoricalArray::from_codes(codes, cats, true);  // ordered
762
763        // Test min
764        std::optional<std::string> min_val = arr.min();
765        if (!min_val.has_value() || *min_val != "low") {
766            std::cout << "  [FAIL] : in pd_test_categorical_array_ordered_operations() : min != 'low'" << std::endl;
767            throw std::runtime_error("pd_test_categorical_array_ordered_operations failed: min != 'low'");
768        }
769
770        // Test max
771        std::optional<std::string> max_val = arr.max();
772        if (!max_val.has_value() || *max_val != "high") {
773            std::cout << "  [FAIL] : in pd_test_categorical_array_ordered_operations() : max != 'high'" << std::endl;
774            throw std::runtime_error("pd_test_categorical_array_ordered_operations failed: max != 'high'");
775        }
776
777        // Test unordered throws for min/max
778        pandas::CategoricalArray unordered = arr.as_unordered();
779        bool threw = false;
780        try {
781            unordered.min();
min (pd_test_1_all.cpp:764)
754    }
755
756    void pd_test_categorical_array_ordered_operations() {
757        std::cout << "========= CategoricalArray: ordered operations (min/max) ======================= ";
758
759        std::vector<std::string> cats = {"low", "medium", "high"};
760        std::vector<numpy::int32> codes = {0, 2, 1, 0, -1};  // low, high, medium, low, NA
761        pandas::CategoricalArray arr = pandas::CategoricalArray::from_codes(codes, cats, true);  // ordered
762
763        // Test min
764        std::optional<std::string> min_val = arr.min();
765        if (!min_val.has_value() || *min_val != "low") {
766            std::cout << "  [FAIL] : in pd_test_categorical_array_ordered_operations() : min != 'low'" << std::endl;
767            throw std::runtime_error("pd_test_categorical_array_ordered_operations failed: min != 'low'");
768        }
769
770        // Test max
771        std::optional<std::string> max_val = arr.max();
772        if (!max_val.has_value() || *max_val != "high") {
773            std::cout << "  [FAIL] : in pd_test_categorical_array_ordered_operations() : max != 'high'" << std::endl;
774            throw std::runtime_error("pd_test_categorical_array_ordered_operations failed: max != 'high'");
len (pd_test_3_all.cpp:20867)
20857    auto title_result = s.str().title();
20858    if (title_result[0] != "Hello World" || title_result[1] != "Hello World" || title_result[2] != "Hello World") {
20859        std::cout << "  [FAIL] : title() failed" << std::endl;
20860        throw std::runtime_error("pd_test_str_capitalize_title: title() failed");
20861    }
20862
20863    std::cout << " -> tests passed" << std::endl;
20864}
20865
20866// ============================================================================
20867// Test str().len()
20868// ============================================================================
20869
20870void pd_test_str_len() {
20871    std::cout << "========= Series.str().len() ============================";
20872
20873    pandas::Series<std::string> s({"a", "bb", "ccc", ""});
20874
20875    auto lens = s.str().len();
20876    if (lens[0] != 1 || lens[1] != 2 || lens[2] != 3 || lens[3] != 0) {
20877        std::cout << "  [FAIL] : len() failed" << std::endl;
argsort (pd_test_1_all.cpp:1304)
1294        std::cout << "========= DatetimeArray: sorting ======================= ";
1295
1296        pandas::DatetimeArray arr(std::vector<std::string>{
1297            "2023-06-15",
1298            "NaT",
1299            "2023-01-01",
1300            "2023-12-31"
1301        });
1302
1303        // argsort ascending
1304        auto indices = arr.argsort(true, "last");
1305        // Expected order: 2023-01-01(2), 2023-06-15(0), 2023-12-31(3), NaT(1)
1306        if (indices.getElementAt({0}) != 2) {
1307            std::cout << "  [FAIL] : argsort: first should be index 2 (2023-01-01)" << std::endl;
1308            throw std::runtime_error("pd_test_datetime_array_sorting failed: argsort first");
1309        }
1310        if (indices.getElementAt({3}) != 1) {
1311            std::cout << "  [FAIL] : argsort: last should be index 1 (NaT)" << std::endl;
1312            throw std::runtime_error("pd_test_datetime_array_sorting failed: NaT position");
1313        }
concat (pd_test_1_all.cpp:17717)
17707}
17708
17709void pd_test_period_index_concat() {
17710    std::cout << "========= concat factory ==============================";
17711
17712    std::vector<int64_t> ordinals1 = {0, 1};
17713    std::vector<int64_t> ordinals2 = {2, 3};
17714    pandas::PeriodIndex idx1(ordinals1, "D");
17715    pandas::PeriodIndex idx2(ordinals2, "D");
17716
17717    pandas::PeriodIndex concatenated = pandas::PeriodIndex::concat({idx1, idx2});
17718
17719    bool passed = (concatenated.size() == 4);
17720    if (!passed) {
17721        std::cout << "  [FAIL] : in pd_test_period_index_concat()" << std::endl;
17722        throw std::runtime_error("pd_test_period_index_concat failed");
17723    }
17724
17725    std::cout << " -> tests passed" << std::endl;
17726}
to_pytimedelta (pd_test_3_all.cpp:5952)
5942    }
5943
5944    std::cout << " -> tests passed" << std::endl;
5945}
5946
5947// ============================================================================
5948// Category 21: Timedelta Plan 9 - Missing Functions
5949// ============================================================================
5950
5951void pd_test_3_all_timedelta_to_pytimedelta() {
5952    std::cout << "========= Timedelta.to_pytimedelta() =================";
5953
5954    // Test PyTimedelta struct
5955    pandas::PyTimedelta td1;
5956    if (td1.days != 0 || td1.seconds != 0 || td1.microseconds != 0) {
5957        throw std::runtime_error("PyTimedelta default constructor failed");
5958    }
5959
5960    pandas::PyTimedelta td2(5, 3600, 500000);
5961    if (td2.days != 5 || td2.seconds != 3600 || td2.microseconds != 500000) {
5962        throw std::runtime_error("PyTimedelta parameterized constructor failed");
to_string (pd_test_1_all.cpp:2693)
2683        pandas::PeriodArray arr_m(std::vector<std::string>{
2684            "2020-01",
2685            "NaT",
2686            "2025-06"
2687        }, "M");
2688
2689        // Year
2690        auto years = arr_m.year();
2691        auto y0 = years[0];
2692        if (!y0.has_value() || y0.value() != 2020) {
2693            std::cout << "  [FAIL] : year[0] should be 2020, got " << (y0.has_value() ? std::to_string(y0.value()) : "NA") << std::endl;
2694            throw std::runtime_error("pd_test_period_array_year_month_quarter failed: year[0]");
2695        }
2696
2697        auto y1 = years[1];
2698        if (y1.has_value()) {
2699            std::cout << "  [FAIL] : year[1] should be NA (NaT)" << std::endl;
2700            throw std::runtime_error("pd_test_period_array_year_month_quarter failed: year[1] should be NA");
2701        }
2702
2703        auto y2 = years[2];
copy (pd_test_1_all.cpp:5798)
5788// ============================================================================
5789// Copy/Rename Tests
5790// ============================================================================
5791
5792void pd_test_categorical_index_copy() {
5793    std::cout << "========= copy ========================================";
5794
5795    pandas::CategoricalArray arr({"a", "b", "c"});
5796    pandas::CategoricalIndex idx(arr, "original");
5797
5798    pandas::CategoricalIndex copied = idx.copy();
5799
5800    bool passed = (copied.size() == idx.size() && copied.name() == idx.name() &&
5801                   copied.categories() == idx.categories() && copied.ordered() == idx.ordered());
5802    if (!passed) {
5803        std::cout << "  [FAIL] : in pd_test_categorical_index_copy()" << std::endl;
5804        throw std::runtime_error("pd_test_categorical_index_copy failed");
5805    }
5806
5807    std::cout << " -> tests passed" << std::endl;
5808}
unique (pd_test_1_all.cpp:1345)
1335        pandas::DatetimeArray arr(std::vector<std::string>{
1336            "2023-01-01",
1337            "2023-06-15",
1338            "2023-01-01",
1339            "NaT",
1340            "2023-06-15",
1341            "NaT"
1342        });
1343
1344        // unique
1345        auto uniq = arr.unique();
1346        // Should have: NaT, 2023-01-01, 2023-06-15 (3 unique values)
1347        if (uniq.size() != 3) {
1348            std::cout << "  [FAIL] : unique size should be 3, got " << uniq.size() << std::endl;
1349            throw std::runtime_error("pd_test_datetime_array_unique failed: size");
1350        }
1351
1352        // factorize
1353        auto [codes, uniques] = arr.factorize();
1354        // Codes for NaT should be -1
1355        if (codes.getElementAt({3}) != -1) {
is_na (pd_test_1_all.cpp:51)
41    void pd_test_boolean_array_na_handling() {
42        std::cout << "========= BooleanArray: NA handling ======================= ";
43
44        pandas::BooleanArray arr({
45            std::optional<bool>(true),
46            std::nullopt,  // NA at index 1
47            std::optional<bool>(false)
48        });
49
50        if (!arr.is_na(1)) {
51            std::cout << "  [FAIL] : in pd_test_boolean_array_na_handling() : is_na(1) should be true" << std::endl;
52            throw std::runtime_error("pd_test_boolean_array_na_handling failed: is_na(1) should be true");
53        }
54
55        if (arr.is_na(0)) {
56            std::cout << "  [FAIL] : in pd_test_boolean_array_na_handling() : is_na(0) should be false" << std::endl;
57            throw std::runtime_error("pd_test_boolean_array_na_handling failed: is_na(0) should be false");
58        }
59
60        if (!arr.has_na()) {
is_negative (pd_test_1_all.cpp:4269)
4259        if (!pos[0].has_value() || !pos[0].value()) {
4260            std::cout << "  [FAIL] : 1 day should be positive" << std::endl;
4261            throw std::runtime_error("pd_test_timedelta_array_boolean_props failed: is_positive");
4262        }
4263        if (!pos[1].has_value() || pos[1].value()) {
4264            std::cout << "  [FAIL] : -5 hours should not be positive" << std::endl;
4265            throw std::runtime_error("pd_test_timedelta_array_boolean_props failed: not positive");
4266        }
4267
4268        // is_negative
4269        auto neg = arr.is_negative();
4270        if (!neg[1].has_value() || !neg[1].value()) {
4271            std::cout << "  [FAIL] : -5 hours should be negative" << std::endl;
4272            throw std::runtime_error("pd_test_timedelta_array_boolean_props failed: is_negative");
4273        }
4274        if (!neg[0].has_value() || neg[0].value()) {
4275            std::cout << "  [FAIL] : 1 day should not be negative" << std::endl;
4276            throw std::runtime_error("pd_test_timedelta_array_boolean_props failed: not negative");
4277        }
4278
4279        // is_zero
is_positive (pd_test_1_all.cpp:4258)
4248        std::cout << "========= TimedeltaArray: boolean properties ======================= ";
4249
4250        pandas::TimedeltaArray arr({
4251            std::optional<numpy::timedelta64>(numpy::timedelta64(1, numpy::DateTimeUnit::Day)),   // positive
4252            std::optional<numpy::timedelta64>(numpy::timedelta64(-5, numpy::DateTimeUnit::Hour)), // negative
4253            std::optional<numpy::timedelta64>(numpy::timedelta64(0, numpy::DateTimeUnit::Second)), // zero
4254            std::nullopt
4255        });
4256
4257        // is_positive
4258        auto pos = arr.is_positive();
4259        if (!pos[0].has_value() || !pos[0].value()) {
4260            std::cout << "  [FAIL] : 1 day should be positive" << std::endl;
4261            throw std::runtime_error("pd_test_timedelta_array_boolean_props failed: is_positive");
4262        }
4263        if (!pos[1].has_value() || pos[1].value()) {
4264            std::cout << "  [FAIL] : -5 hours should not be positive" << std::endl;
4265            throw std::runtime_error("pd_test_timedelta_array_boolean_props failed: not positive");
4266        }
4267
4268        // is_negative
is_zero (pd_test_1_all.cpp:4280)
4270        if (!neg[1].has_value() || !neg[1].value()) {
4271            std::cout << "  [FAIL] : -5 hours should be negative" << std::endl;
4272            throw std::runtime_error("pd_test_timedelta_array_boolean_props failed: is_negative");
4273        }
4274        if (!neg[0].has_value() || neg[0].value()) {
4275            std::cout << "  [FAIL] : 1 day should not be negative" << std::endl;
4276            throw std::runtime_error("pd_test_timedelta_array_boolean_props failed: not negative");
4277        }
4278
4279        // is_zero
4280        auto zero = arr.is_zero();
4281        if (!zero[2].has_value() || !zero[2].value()) {
4282            std::cout << "  [FAIL] : 0 seconds should be zero" << std::endl;
4283            throw std::runtime_error("pd_test_timedelta_array_boolean_props failed: is_zero");
4284        }
4285
4286        // NA should propagate
4287        if (pos[3].has_value() || neg[3].has_value() || zero[3].has_value()) {
4288            std::cout << "  [FAIL] : NaT should propagate to boolean props" << std::endl;
4289            throw std::runtime_error("pd_test_timedelta_array_boolean_props failed: NaT propagation");
4290        }
abs (pd_test_1_all.cpp:283)
273            std::optional<bool>(true)
274        });
275
276        auto s = arr.sum();
277        if (!s.has_value() || s.value() != 3) {
278            std::cout << "  [FAIL] : in pd_test_boolean_array_reductions() : sum should be 3" << std::endl;
279            throw std::runtime_error("pd_test_boolean_array_reductions failed: sum");
280        }
281
282        auto m = arr.mean();
283        if (!m.has_value() || std::abs(m.value() - 0.75) > 0.001) {
284            std::cout << "  [FAIL] : in pd_test_boolean_array_reductions() : mean should be 0.75" << std::endl;
285            throw std::runtime_error("pd_test_boolean_array_reductions failed: mean");
286        }
287
288        std::cout << " -> tests passed" << std::endl;
289    }
290
291    void pd_test_boolean_array_dtype() {
292        std::cout << "========= BooleanArray: dtype ======================= ";
argmax (pd_test_1_all.cpp:1323)
1313        }
1314
1315        // argmin
1316        auto min_idx = arr.argmin();
1317        if (!min_idx.has_value() || min_idx.value() != 2) {
1318            std::cout << "  [FAIL] : argmin should be 2 (2023-01-01)" << std::endl;
1319            throw std::runtime_error("pd_test_datetime_array_sorting failed: argmin");
1320        }
1321
1322        // argmax
1323        auto max_idx = arr.argmax();
1324        if (!max_idx.has_value() || max_idx.value() != 3) {
1325            std::cout << "  [FAIL] : argmax should be 3 (2023-12-31)" << std::endl;
1326            throw std::runtime_error("pd_test_datetime_array_sorting failed: argmax");
1327        }
1328
1329        std::cout << " -> tests passed" << std::endl;
1330    }
1331
1332    void pd_test_datetime_array_unique() {
1333        std::cout << "========= DatetimeArray: unique/factorize ======================= ";
argmin (pd_test_1_all.cpp:1316)
1306        if (indices.getElementAt({0}) != 2) {
1307            std::cout << "  [FAIL] : argsort: first should be index 2 (2023-01-01)" << std::endl;
1308            throw std::runtime_error("pd_test_datetime_array_sorting failed: argsort first");
1309        }
1310        if (indices.getElementAt({3}) != 1) {
1311            std::cout << "  [FAIL] : argsort: last should be index 1 (NaT)" << std::endl;
1312            throw std::runtime_error("pd_test_datetime_array_sorting failed: NaT position");
1313        }
1314
1315        // argmin
1316        auto min_idx = arr.argmin();
1317        if (!min_idx.has_value() || min_idx.value() != 2) {
1318            std::cout << "  [FAIL] : argmin should be 2 (2023-01-01)" << std::endl;
1319            throw std::runtime_error("pd_test_datetime_array_sorting failed: argmin");
1320        }
1321
1322        // argmax
1323        auto max_idx = arr.argmax();
1324        if (!max_idx.has_value() || max_idx.value() != 3) {
1325            std::cout << "  [FAIL] : argmax should be 3 (2023-12-31)" << std::endl;
1326            throw std::runtime_error("pd_test_datetime_array_sorting failed: argmax");
ceil (pd_test_1_all.cpp:4949)
4939                throw std::runtime_error("pd_test_arithmetic_series_round failed: round failed");
4940            }
4941
4942            auto f = a.floor();
4943            passed = std::abs(f[0] - 1.0) < 0.001 && std::abs(f[2] - 3.0) < 0.001 && std::abs(f[3] - (-2.0)) < 0.001;
4944            if (!passed) {
4945                std::cout << "  [FAIL] : in pd_test_arithmetic_series_round() : floor failed" << std::endl;
4946                throw std::runtime_error("pd_test_arithmetic_series_round failed: floor failed");
4947            }
4948
4949            auto c = a.ceil();
4950            passed = std::abs(c[0] - 2.0) < 0.001 && std::abs(c[2] - 4.0) < 0.001 && std::abs(c[3] - (-1.0)) < 0.001;
4951            if (!passed) {
4952                std::cout << "  [FAIL] : in pd_test_arithmetic_series_round() : ceil failed" << std::endl;
4953                throw std::runtime_error("pd_test_arithmetic_series_round failed: ceil failed");
4954            }
4955
4956            // Round with decimals
4957            pandas::Series<double> b({1.234, 2.567, 3.891});
4958            auto r2 = b.round(2);
4959            passed = std::abs(r2[0] - 1.23) < 0.001 && std::abs(r2[1] - 2.57) < 0.001;
data (pd_test_1_all.cpp:9114)
9104        throw std::runtime_error("pd_test_datetime_mixin_default_constructor failed");
9105    }
9106
9107    std::cout << " -> tests passed" << std::endl;
9108}
9109
9110void pd_test_datetime_mixin_array_constructor() {
9111    std::cout << "========= DatetimeTDMixin array constructor =========================";
9112
9113    // Create DatetimeArray with some values
9114    numpy::NDArray<numpy::datetime64> data(std::vector<size_t>{3});
9115    data.setElementAt({0}, numpy::datetime64(1000000000000000000LL, numpy::DateTimeUnit::Nanosecond));  // ~2001
9116    data.setElementAt({1}, numpy::datetime64(1500000000000000000LL, numpy::DateTimeUnit::Nanosecond));  // ~2017
9117    data.setElementAt({2}, numpy::datetime64(1600000000000000000LL, numpy::DateTimeUnit::Nanosecond));  // ~2020
9118
9119    numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{3});
9120    mask.setElementAt({0}, numpy::bool_(false));
9121    mask.setElementAt({1}, numpy::bool_(false));
9122    mask.setElementAt({2}, numpy::bool_(false));
9123
9124    pandas::DatetimeArray arr(data, mask);
days (pd_test_1_all.cpp:4160)
4150    void pd_test_timedelta_array_component_days() {
4151        std::cout << "========= TimedeltaArray: days component ======================= ";
4152
4153        pandas::TimedeltaArray arr({
4154            std::optional<numpy::timedelta64>(numpy::timedelta64(3, numpy::DateTimeUnit::Day)),
4155            std::nullopt,
4156            std::optional<numpy::timedelta64>(numpy::timedelta64(36, numpy::DateTimeUnit::Hour))  // 1.5 days
4157        });
4158
4159        auto days_arr = arr.days();
4160
4161        auto d0 = days_arr[0];
4162        if (!d0.has_value() || d0.value() != 3) {
4163            std::cout << "  [FAIL] : days[0] should be 3" << std::endl;
4164            throw std::runtime_error("pd_test_timedelta_array_component_days failed: days[0]");
4165        }
4166
4167        auto d1 = days_arr[1];
4168        if (d1.has_value()) {
4169            std::cout << "  [FAIL] : days[1] should be NA (NaT)" << std::endl;
dtype (pd_test_1_all.cpp:295)
285            throw std::runtime_error("pd_test_boolean_array_reductions failed: mean");
286        }
287
288        std::cout << " -> tests passed" << std::endl;
289    }
290
291    void pd_test_boolean_array_dtype() {
292        std::cout << "========= BooleanArray: dtype ======================= ";
293
294        pandas::BooleanArray arr;
295        if (arr.dtype().name() != "boolean") {
296            std::cout << "  [FAIL] : in pd_test_boolean_array_dtype() : dtype name should be 'boolean'" << std::endl;
297            throw std::runtime_error("pd_test_boolean_array_dtype failed: dtype name");
298        }
299
300        if (arr.dtype().kind() != "b") {
301            std::cout << "  [FAIL] : in pd_test_boolean_array_dtype() : dtype kind should be 'b'" << std::endl;
302            throw std::runtime_error("pd_test_boolean_array_dtype failed: dtype kind");
303        }
304
305        std::cout << " -> tests passed" << std::endl;
empty (pd_test_1_all.cpp:941)
931#include "../pandas/pd_config.h"
932
933namespace dataframe_tests {
934
935namespace dataframe_tests_config {
936
937    void pd_test_config_version() {
938        std::cout << "========= df_config: version info ======================= ";
939        const char* version = pandas::DataFrameInfo::version();
940        if (version == nullptr || std::string(version).empty()) {
941            std::cout << "[FAIL] : in pd_test_config_version() : version is null or empty" << std::endl;
942            throw std::runtime_error("pd_test_config_version failed: version is null or empty");
943        }
944        std::cout << "-> tests passed" << std::endl;
945    }
946
947    void pd_test_config_na_repr() {
948        std::cout << "========= df_config: NA representation ======================= ";
949        const char* na_repr = pandas::DataFrameConfig::get_na_repr();
950        if (na_repr == nullptr) {
factorize (pd_test_1_all.cpp:1353)
1343        // unique
1344        auto uniq = arr.unique();
1345        // Should have: NaT, 2023-01-01, 2023-06-15 (3 unique values)
1346        if (uniq.size() != 3) {
1347            std::cout << "  [FAIL] : unique size should be 3, got " << uniq.size() << std::endl;
1348            throw std::runtime_error("pd_test_datetime_array_unique failed: size");
1349        }
1350
1351        // factorize
1352        auto [codes, uniques] = arr.factorize();
1353        // Codes for NaT should be -1
1354        if (codes.getElementAt({3}) != -1) {
1355            std::cout << "  [FAIL] : factorize: NaT code should be -1" << std::endl;
1356            throw std::runtime_error("pd_test_datetime_array_unique failed: NaT code");
1357        }
1358        // Same values should have same codes
1359        if (codes.getElementAt({0}) != codes.getElementAt({2})) {
1360            std::cout << "  [FAIL] : factorize: 2023-01-01 values should have same code" << std::endl;
1361            throw std::runtime_error("pd_test_datetime_array_unique failed: same code");
1362        }
floor (pd_test_1_all.cpp:4942)
4932            pandas::Series<double> a({1.4, 2.5, 3.6, -1.4, -2.5});
4933
4934            auto r = a.round();
4935            bool passed = std::abs(r[0] - 1.0) < 0.001 && std::abs(r[2] - 4.0) < 0.001;
4936            if (!passed) {
4937                std::cout << "  [FAIL] : in pd_test_arithmetic_series_round() : round failed" << std::endl;
4938                throw std::runtime_error("pd_test_arithmetic_series_round failed: round failed");
4939            }
4940
4941            auto f = a.floor();
4942            passed = std::abs(f[0] - 1.0) < 0.001 && std::abs(f[2] - 3.0) < 0.001 && std::abs(f[3] - (-2.0)) < 0.001;
4943            if (!passed) {
4944                std::cout << "  [FAIL] : in pd_test_arithmetic_series_round() : floor failed" << std::endl;
4945                throw std::runtime_error("pd_test_arithmetic_series_round failed: floor failed");
4946            }
4947
4948            auto c = a.ceil();
4949            passed = std::abs(c[0] - 2.0) < 0.001 && std::abs(c[2] - 4.0) < 0.001 && std::abs(c[3] - (-1.0)) < 0.001;
4950            if (!passed) {
4951                std::cout << "  [FAIL] : in pd_test_arithmetic_series_round() : ceil failed" << std::endl;
has_na (pd_test_1_all.cpp:61)
51        if (!arr.is_na(1)) {
52            std::cout << "  [FAIL] : in pd_test_boolean_array_na_handling() : is_na(1) should be true" << std::endl;
53            throw std::runtime_error("pd_test_boolean_array_na_handling failed: is_na(1) should be true");
54        }
55
56        if (arr.is_na(0)) {
57            std::cout << "  [FAIL] : in pd_test_boolean_array_na_handling() : is_na(0) should be false" << std::endl;
58            throw std::runtime_error("pd_test_boolean_array_na_handling failed: is_na(0) should be false");
59        }
60
61        if (!arr.has_na()) {
62            std::cout << "  [FAIL] : in pd_test_boolean_array_na_handling() : has_na() should be true" << std::endl;
63            throw std::runtime_error("pd_test_boolean_array_na_handling failed: has_na() should be true");
64        }
65
66        if (arr.count() != 2) {
67            std::cout << "  [FAIL] : in pd_test_boolean_array_na_handling() : count() should be 2" << std::endl;
68            throw std::runtime_error("pd_test_boolean_array_na_handling failed: count() should be 2");
69        }
70
71        std::cout << " -> tests passed" << std::endl;
microseconds (pd_test_1_all.cpp:19701)
19691    constexpr int64_t NS_PER_US = 1000LL;
19692    std::vector<std::optional<numpy::timedelta64>> values = {
19693        make_td(0),                        // 0 us
19694        make_td(500 * NS_PER_US),          // 500 us
19695        make_td(NS_PER_SEC + 100 * NS_PER_US)  // 1 sec + 100 us
19696    };
19697    pandas::TimedeltaArray arr(values);
19698    pandas::TimedeltaIndex idx(arr);
19699
19700    auto microseconds = idx.microseconds();
19701
19702    bool passed = (microseconds.size() == 3);
19703    if (!passed) {
19704        std::cout << "  [FAIL] : in pd_test_timedelta_index_microseconds()" << std::endl;
19705        throw std::runtime_error("pd_test_timedelta_index_microseconds failed");
19706    }
19707
19708    std::cout << " -> tests passed" << std::endl;
19709}
nanoseconds (pd_test_1_all.cpp:9379)
9369        std::cout << "  [FAIL] : in pd_test_datetime_as_unit() : as_unit check failed" << std::endl;
9370        throw std::runtime_error("pd_test_datetime_as_unit failed");
9371    }
9372
9373    std::cout << " -> tests passed" << std::endl;
9374}
9375
9376void pd_test_timedelta_as_unit() {
9377    std::cout << "========= TimedeltaTDMixin as_unit =========================";
9378
9379    // Create index in nanoseconds (1 hour, 2 hours)
9380    numpy::NDArray<numpy::timedelta64> data(std::vector<size_t>{2});
9381    data.setElementAt({0}, numpy::timedelta64(3600000000000LL, numpy::DateTimeUnit::Nanosecond));   // 1 hour
9382    data.setElementAt({1}, numpy::timedelta64(7200000000000LL, numpy::DateTimeUnit::Nanosecond));   // 2 hours
9383
9384    numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{2});
9385    mask.setElementAt({0}, numpy::bool_(false));
9386    mask.setElementAt({1}, numpy::bool_(false));
9387
9388    pandas::TimedeltaArray arr(data, mask);
9389    pandas::TimedeltaTDMixin idx(arr, "durations");
nbytes (pd_test_1_all.cpp:6214)
6204            }
6205
6206            // Test empty DataFrame
6207            pandas::DataFrame empty_df;
6208            if (!empty_df.empty()) {
6209                std::cout << "  [FAIL] : in pd_test_dataframe_properties() : should be empty" << std::endl;
6210                throw std::runtime_error("pd_test_dataframe_properties failed: should be empty");
6211            }
6212
6213            // Test nbytes > 0 for non-empty
6214            if (df.nbytes() == 0) {
6215                std::cout << "  [FAIL] : in pd_test_dataframe_properties() : nbytes should be > 0" << std::endl;
6216                throw std::runtime_error("pd_test_dataframe_properties failed: nbytes should be > 0");
6217            }
6218
6219            // Test columns index
6220            if (df.columns().size() != 3) {
6221                std::cout << "  [FAIL] : in pd_test_dataframe_properties() : columns size != 3" << std::endl;
6222                throw std::runtime_error("pd_test_dataframe_properties failed: columns size != 3");
6223            }
ndim (pd_test_1_all.cpp:6195)
6185            pandas::DataFrame df(data);
6186
6187            // Test shape
6188            auto shape = df.shape();
6189            if (shape.size() != 2 || shape[0] != 4 || shape[1] != 3) {
6190                std::cout << "  [FAIL] : in pd_test_dataframe_properties() : shape mismatch" << std::endl;
6191                throw std::runtime_error("pd_test_dataframe_properties failed: shape mismatch");
6192            }
6193
6194            // Test ndim
6195            if (df.ndim() != 2) {
6196                std::cout << "  [FAIL] : in pd_test_dataframe_properties() : ndim != 2" << std::endl;
6197                throw std::runtime_error("pd_test_dataframe_properties failed: ndim != 2");
6198            }
6199
6200            // Test empty
6201            if (df.empty()) {
6202                std::cout << "  [FAIL] : in pd_test_dataframe_properties() : should not be empty" << std::endl;
6203                throw std::runtime_error("pd_test_dataframe_properties failed: should not be empty");
6204            }
repr (pd_test_1_all.cpp:10906)
10896    std::cout << " -> tests passed" << std::endl;
10897}
10898
10899void pd_test_extension_index_repr() {
10900    std::cout << "========= repr =========================";
10901
10902    pandas::CategoricalArray arr({"a", "b", "c"});
10903    // Use ExtensionIndex<CategoricalArray> directly to test base class repr
10904    pandas::ExtensionIndex<pandas::CategoricalArray> idx(arr, "test");
10905
10906    std::string repr_str = idx.repr();
10907
10908    bool passed = (!repr_str.empty() && repr_str.find("ExtensionIndex") != std::string::npos);
10909    if (!passed) {
10910        std::cout << "  [FAIL] : in pd_test_extension_index_repr() : repr check failed" << std::endl;
10911        throw std::runtime_error("pd_test_extension_index_repr failed");
10912    }
10913
10914    std::cout << " -> tests passed" << std::endl;
10915}
round (pd_test_1_all.cpp:1688)
1678    void pd_test_floating_array_rounding() {
1679        std::cout << "========= FloatingArray: rounding ======================= ";
1680
1681        pandas::FloatingArray<double> arr({
1682            std::optional<double>(1.234),
1683            std::optional<double>(2.567),
1684            std::nullopt
1685        });
1686
1687        auto rounded = arr.round(2);
1688        if (std::abs(rounded[0].value() - 1.23) > 0.001 ||
1689            std::abs(rounded[1].value() - 2.57) > 0.001) {
1690            std::cout << "  [FAIL] : in pd_test_floating_array_rounding() : round(2)" << std::endl;
1691            throw std::runtime_error("pd_test_floating_array_rounding failed: round(2)");
1692        }
1693
1694        if (!rounded.is_na(2)) {
1695            std::cout << "  [FAIL] : in pd_test_floating_array_rounding() : round should preserve NA" << std::endl;
1696            throw std::runtime_error("pd_test_floating_array_rounding failed: NA preservation");
1697        }
seconds (pd_test_1_all.cpp:4192)
4182    void pd_test_timedelta_array_component_seconds() {
4183        std::cout << "========= TimedeltaArray: seconds component ======================= ";
4184
4185        pandas::TimedeltaArray arr({
4186            std::optional<numpy::timedelta64>(numpy::timedelta64(90, numpy::DateTimeUnit::Second)),  // 90 secs
4187            std::optional<numpy::timedelta64>(numpy::timedelta64(3700, numpy::DateTimeUnit::Second)), // 1h + 100s
4188            std::nullopt
4189        });
4190
4191        auto secs = arr.seconds();
4192
4193        auto s0 = secs[0];
4194        if (!s0.has_value() || s0.value() != 90) {
4195            std::cout << "  [FAIL] : seconds[0] should be 90" << std::endl;
4196            throw std::runtime_error("pd_test_timedelta_array_component_seconds failed: seconds[0]");
4197        }
4198
4199        auto s1 = secs[1];
4200        if (!s1.has_value() || s1.value() != 3700) {
4201            std::cout << "  [FAIL] : seconds[1] should be 3700" << std::endl;
shape (pd_test_1_all.cpp:6188)
6178            std::cout << "========= properties =======================";
6179
6180            std::map<std::string, std::vector<numpy::float64>> data;
6181            data["A"] = {1.0, 2.0, 3.0, 4.0};
6182            data["B"] = {5.0, 6.0, 7.0, 8.0};
6183            data["C"] = {9.0, 10.0, 11.0, 12.0};
6184
6185            pandas::DataFrame df(data);
6186
6187            // Test shape
6188            auto shape = df.shape();
6189            if (shape.size() != 2 || shape[0] != 4 || shape[1] != 3) {
6190                std::cout << "  [FAIL] : in pd_test_dataframe_properties() : shape mismatch" << std::endl;
6191                throw std::runtime_error("pd_test_dataframe_properties failed: shape mismatch");
6192            }
6193
6194            // Test ndim
6195            if (df.ndim() != 2) {
6196                std::cout << "  [FAIL] : in pd_test_dataframe_properties() : ndim != 2" << std::endl;
6197                throw std::runtime_error("pd_test_dataframe_properties failed: ndim != 2");
6198            }
size (pd_test_1_all.cpp:22)
12#include "../pandas/pd_boolean_array.h"
13
14namespace dataframe_tests {
15
16namespace dataframe_tests_boolean_array {
17    void pd_test_boolean_array_constructors() {
18        std::cout << "========= BooleanArray: constructors ======================= ";
19
20        // Default constructor
21        pandas::BooleanArray arr1;
22        if (arr1.size() != 0) {
23            std::cout << "  [FAIL] : in pd_test_boolean_array_constructors() : default constructor size != 0" << std::endl;
24            throw std::runtime_error("pd_test_boolean_array_constructors failed: default constructor size != 0");
25        }
26
27        // Initializer list constructor
28        pandas::BooleanArray arr2({
29            std::optional<bool>(true),
30            std::optional<bool>(false),
31            std::nullopt,
32            std::optional<bool>(true)
td (pd_test_1_all.cpp:9535)
9525    }
9526
9527    std::cout << " -> tests passed" << std::endl;
9528}
9529
9530void pd_test_timedelta_rounding_params() {
9531    std::cout << "========= Timedelta rounding with DST params =====";
9532
9533    // Create a Timedelta: 1h 30m 45s
9534    // Constructor is: (days, hours, minutes, seconds, ...)
9535    pandas::Timedelta td(0, 1, 30, 45);  // 0 days, 1h, 30m, 45s
9536
9537    // Test floor with ambiguous/nonexistent params
9538    pandas::Timedelta floored = td.floor("h", "raise", "raise");
9539    std::cout << std::endl << "  floor('h'): " << floored.toString();
9540
9541    // Test ceil with ambiguous/nonexistent params
9542    pandas::Timedelta ceiled = td.ceil("h", "raise", "raise");
9543    std::cout << std::endl << "  ceil('h'): " << ceiled.toString();
9544
9545    // Test round with ambiguous/nonexistent params
total_seconds (pd_test_1_all.cpp:4224)
4214    void pd_test_timedelta_array_total_seconds() {
4215        std::cout << "========= TimedeltaArray: total_seconds ======================= ";
4216
4217        pandas::TimedeltaArray arr({
4218            std::optional<numpy::timedelta64>(numpy::timedelta64(1, numpy::DateTimeUnit::Day)),
4219            std::optional<numpy::timedelta64>(numpy::timedelta64(1, numpy::DateTimeUnit::Hour)),
4220            std::nullopt
4221        });
4222
4223        auto total = arr.total_seconds();
4224
4225        auto t0 = total[0];
4226        if (!t0.has_value() || std::abs(t0.value() - 86400.0) > 0.001) {
4227            std::cout << "  [FAIL] : total_seconds[0] should be 86400" << std::endl;
4228            throw std::runtime_error("pd_test_timedelta_array_total_seconds failed: total_seconds[0]");
4229        }
4230
4231        auto t1 = total[1];
4232        if (!t1.has_value() || std::abs(t1.value() - 3600.0) > 0.001) {
4233            std::cout << "  [FAIL] : total_seconds[1] should be 3600" << std::endl;
unit (pd_test_1_all.cpp:9284)
9274    data.setElementAt({0}, numpy::datetime64(1000LL, numpy::DateTimeUnit::Nanosecond));
9275    data.setElementAt({1}, numpy::datetime64(2000LL, numpy::DateTimeUnit::Nanosecond));
9276
9277    numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{2});
9278    mask.setElementAt({0}, numpy::bool_(false));
9279    mask.setElementAt({1}, numpy::bool_(false));
9280
9281    pandas::DatetimeArray arr(data, mask);
9282    pandas::DatetimeTDMixin idx(arr);
9283
9284    std::string unit = idx.unit();
9285
9286    bool passed = (unit == "ns");  // nanosecond
9287    if (!passed) {
9288        std::cout << "  [FAIL] : in pd_test_datetime_unit_property() : unit property check failed, got '" << unit << "'" << std::endl;
9289        throw std::runtime_error("pd_test_datetime_unit_property failed");
9290    }
9291
9292    std::cout << " -> tests passed" << std::endl;
9293}