IntervalArray#

class pandas::IntervalArray#

Extension array type for specialized data storage.

Example#

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

// Use IntervalArray
IntervalArray obj;
// ... operations ...

Constructors#

Signature

Location

Example

IntervalArray(const numpy::NDArray<T>& left, const numpy::NDArray<T>& right, const numpy::NDArray<numpy::bool_>& mask, IntervalClosed closed = IntervalClosed::Right, bool copy = false)

pd_interval_array.h:124

IntervalArray(const numpy::NDArray<T>& left, const numpy::NDArray<T>& right, IntervalClosed closed = IntervalClosed::Right)

pd_interval_array.h:144

explicit IntervalArray(const std::vector<std::optional<std::pair<T, T>>>& values, IntervalClosed closed = IntervalClosed::Right)

pd_interval_array.h:161

Construction#

Signature

Return Type

Location

Example

static IntervalArray from_arrays(const std::vector<T>& left, const std::vector<T>& right, IntervalClosed closed = IntervalClosed::Right)

static IntervalArray

pd_interval_array.h:269

View

static IntervalArray from_arrays(const numpy::NDArray<T>& left, const numpy::NDArray<T>& right, IntervalClosed closed = IntervalClosed::Right)

static IntervalArray

pd_interval_array.h:290

View

static IntervalArray from_breaks(const std::vector<T>& breaks, IntervalClosed closed = IntervalClosed::Right)

static IntervalArray

pd_interval_array.h:230

View

static IntervalArray from_breaks(const numpy::NDArray<T>& breaks, IntervalClosed closed = IntervalClosed::Right)

static IntervalArray

pd_interval_array.h:251

View

static IntervalArray from_tuples(const std::vector<std::pair<T, T>>& tuples, IntervalClosed closed = IntervalClosed::Right)

static IntervalArray

pd_interval_array.h:303

View

Indexing / Selection#

Signature

Return Type

Location

Example

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

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

pd_interval_array.h:558

View

IntervalArray take(const numpy::NDArray<numpy::int64>& indices) const

IntervalArray

pd_interval_array.h:1298

View

Data Manipulation#

Signature

Return Type

Location

Example

IntervalArray dropna() const

IntervalArray

pd_interval_array.h:639

View

Missing Data#

Signature

Return Type

Location

Example

IntervalArray fillna(const std::pair<T, T>& fill_value) const

IntervalArray

pd_interval_array.h:620

View

BooleanArray isna() const

BooleanArray

pd_interval_array.h:593

View

BooleanArray notna() const

BooleanArray

pd_interval_array.h:606

View

Statistics#

Signature

Return Type

Location

Example

size_t count() const

size_t

pd_interval_array.h:661

View

Arithmetic#

Signature

Return Type

Location

Example

const std::string& subtype_override() const

const std::string&

pd_interval_array.h:393

View

Comparison#

Signature

Return Type

Location

Example

numpy::NDArray<T> left() const

numpy::NDArray<T>

pd_interval_array.h:418

View

size_t len() const

size_t

pd_interval_array.h:365

View

numpy::NDArray<T> length() const

numpy::NDArray<T>

pd_interval_array.h:454

View

Sorting#

Signature

Return Type

Location

Example

numpy::NDArray<numpy::int64> argsort() const

numpy::NDArray<numpy::int64>

pd_interval_array.h:985

View

Combining#

Signature

Return Type

Location

Example

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

static IntervalArray

pd_interval_array.h:1362

View

I/O#

Signature

Return Type

Location

Example

std::string to_string() const

std::string

pd_interval_array.h:1265

View

std::vector<std::optional<std::pair<T, T>>> to_tuples() const

std::vector<std::optional<std::pair<T, T>>>

pd_interval_array.h:858

View

Conversion#

Signature

Return Type

Location

Example

IntervalArray copy() const

IntervalArray

pd_interval_array.h:1400

View

Set Operations#

Signature

Return Type

Location

Example

IntervalArray unique() const

IntervalArray

pd_interval_array.h:1070

View

Type Checking#

Signature

Return Type

Location

Example

BooleanArray is_empty() const

BooleanArray

pd_interval_array.h:478

View

bool is_left_closed() const

bool

pd_interval_array.h:400

View

bool is_na(size_t index) const

bool

pd_interval_array.h:578

View

bool is_non_overlapping_monotonic() const

bool

pd_interval_array.h:505

View

bool is_right_closed() const

bool

pd_interval_array.h:407

View

Other Methods#

Signature

Return Type

Location

Example

numpy::int64 argmax() const

numpy::int64

pd_interval_array.h:1042

View

numpy::int64 argmin() const

numpy::int64

pd_interval_array.h:1018

View

IntervalClosed closed() const

IntervalClosed

pd_interval_array.h:372

View

std::string closed_string() const

std::string

pd_interval_array.h:379

View

BooleanArray contains(T value) const

BooleanArray

pd_interval_array.h:696

View

BooleanArray contains(const numpy::NDArray<T>& values) const

BooleanArray

pd_interval_array.h:734

View

const numpy::NDArray<T>& data_left() const

const numpy::NDArray<T>&

pd_interval_array.h:544

const numpy::NDArray<T>& data_right() const

const numpy::NDArray<T>&

pd_interval_array.h:551

dtype_type dtype() const

dtype_type

pd_interval_array.h:323

View

bool empty() const

bool

pd_interval_array.h:358

View

std::pair<IntegerArray<numpy::int64>, IntervalArray> factorize() const

std::pair<IntegerArray<numpy::int64>, IntervalArray>

pd_interval_array.h:1124

View

fmt_bound(oss, l)

pd_interval_array.h:1254

fmt_bound(oss, r)

pd_interval_array.h:1256

fmt_float(oss, l)

pd_interval_array.h:1204

fmt_float(oss, r)

pd_interval_array.h:1206

bool has_na() const

bool

pd_interval_array.h:674

View

std::string interval_to_string(size_t index) const

std::string

pd_interval_array.h:1176

oss << interval_to_string(i)

oss <<

pd_interval_array.h:1274

FloatingArray<numpy::float64> mid() const

FloatingArray<numpy::float64>

pd_interval_array.h:433

View

size_t nbytes() const

size_t

pd_interval_array.h:337

View

constexpr int ndim() const

constexpr int

pd_interval_array.h:344

View

BooleanArray overlaps(T other_left, T other_right, IntervalClosed other_closed) const

BooleanArray

pd_interval_array.h:781

View

BooleanArray overlaps(T other_left, T other_right) const

BooleanArray

pd_interval_array.h:829

View

numpy::NDArray<T> right() const

numpy::NDArray<T>

pd_interval_array.h:425

View

IntervalArray set_closed(IntervalClosed new_closed) const

IntervalArray

pd_interval_array.h:843

View

IntervalArray set_closed(const std::string& new_closed) const

IntervalArray

pd_interval_array.h:850

View

void set_subtype_override(const std::string& override)

void

pd_interval_array.h:386

View

std::vector<size_t> shape() const

std::vector<size_t>

pd_interval_array.h:351

View

size_t size() const

size_t

pd_interval_array.h:330

View

IntervalArray slice(size_t start, size_t stop, size_t step = 1) const

IntervalArray

pd_interval_array.h:1325

View

void validate_arrays()

void

pd_interval_array.h:57

void validate_bounds()

void

pd_interval_array.h:84

Internal Methods#

1 internal methods (prefixed with underscore)

Code Examples#

The following examples are extracted from the test suite.

from_arrays (pd_test_1_all.cpp:1994)
1984// ============================================================================
1985// Test: from_arrays factory method
1986// ============================================================================
1987void test_from_arrays() {
1988    std::cout << "========= IntervalArray: from_arrays ======================= ";
1989
1990    std::vector<numpy::int64> left_vec = {0, 10, 20};
1991    std::vector<numpy::int64> right_vec = {5, 15, 25};
1992
1993    auto arr = pandas::IntervalArrayInt64::from_arrays(left_vec, right_vec);
1994
1995    if (arr.size() != 3) {
1996        std::cout << "[FAIL] : in test_from_arrays() : size" << std::endl;
1997        return;
1998    }
1999
2000    auto interval1 = arr[1];
2001    if (!interval1.has_value() || interval1->first != 10 || interval1->second != 15) {
2002        std::cout << "[FAIL] : in test_from_arrays() : interval values" << std::endl;
2003        return;
from_arrays (pd_test_1_all.cpp:1994)
1984// ============================================================================
1985// Test: from_arrays factory method
1986// ============================================================================
1987void test_from_arrays() {
1988    std::cout << "========= IntervalArray: from_arrays ======================= ";
1989
1990    std::vector<numpy::int64> left_vec = {0, 10, 20};
1991    std::vector<numpy::int64> right_vec = {5, 15, 25};
1992
1993    auto arr = pandas::IntervalArrayInt64::from_arrays(left_vec, right_vec);
1994
1995    if (arr.size() != 3) {
1996        std::cout << "[FAIL] : in test_from_arrays() : size" << std::endl;
1997        return;
1998    }
1999
2000    auto interval1 = arr[1];
2001    if (!interval1.has_value() || interval1->first != 10 || interval1->second != 15) {
2002        std::cout << "[FAIL] : in test_from_arrays() : interval values" << std::endl;
2003        return;
from_breaks (pd_test_1_all.cpp:1955)
1945}
1946
1947// ============================================================================
1948// Test: from_breaks factory method
1949// ============================================================================
1950void test_from_breaks() {
1951    std::cout << "========= IntervalArray: from_breaks ======================= ";
1952
1953    // Create from breaks
1954    std::vector<numpy::float64> breaks = {0.0, 1.0, 2.0, 3.0, 4.0};
1955    auto arr = pandas::IntervalArrayFloat64::from_breaks(breaks);
1956
1957    if (arr.size() != 4) {
1958        std::cout << "[FAIL] : in test_from_breaks() : size should be n-1" << std::endl;
1959        return;
1960    }
1961
1962    // Check intervals
1963    auto interval0 = arr[0];
1964    if (!interval0.has_value() || interval0->first != 0.0 || interval0->second != 1.0) {
1965        std::cout << "[FAIL] : in test_from_breaks() : first interval" << std::endl;
from_breaks (pd_test_1_all.cpp:1955)
1945}
1946
1947// ============================================================================
1948// Test: from_breaks factory method
1949// ============================================================================
1950void test_from_breaks() {
1951    std::cout << "========= IntervalArray: from_breaks ======================= ";
1952
1953    // Create from breaks
1954    std::vector<numpy::float64> breaks = {0.0, 1.0, 2.0, 3.0, 4.0};
1955    auto arr = pandas::IntervalArrayFloat64::from_breaks(breaks);
1956
1957    if (arr.size() != 4) {
1958        std::cout << "[FAIL] : in test_from_breaks() : size should be n-1" << std::endl;
1959        return;
1960    }
1961
1962    // Check intervals
1963    auto interval0 = arr[0];
1964    if (!interval0.has_value() || interval0->first != 0.0 || interval0->second != 1.0) {
1965        std::cout << "[FAIL] : in test_from_breaks() : first interval" << std::endl;
from_tuples (pd_test_1_all.cpp:2022)
2012// ============================================================================
2013void test_from_tuples() {
2014    std::cout << "========= IntervalArray: from_tuples ======================= ";
2015
2016    std::vector<std::pair<numpy::float64, numpy::float64>> tuples = {
2017        {0.0, 1.5},
2018        {1.5, 3.0},
2019        {3.0, 4.5}
2020    };
2021
2022    auto arr = pandas::IntervalArrayFloat64::from_tuples(tuples);
2023
2024    if (arr.size() != 3) {
2025        std::cout << "[FAIL] : in test_from_tuples() : size" << std::endl;
2026        return;
2027    }
2028
2029    auto interval2 = arr[2];
2030    if (!interval2.has_value() || interval2->first != 3.0 || interval2->second != 4.5) {
2031        std::cout << "[FAIL] : in test_from_tuples() : interval values" << std::endl;
2032        return;
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 ======================= ";
subtype_override (pd_test_3_all.cpp:24889)
24879    return dataframe_tests_bdate_timedelta_range::pd_test_bdate_timedelta_range_main();
24880}
24881// ------------------- pd_test_bdate_timedelta_range (end) ---------------------------
24882
24883// ------------------- pd_test_interval_type_inference (begin) ---------------------------
24884namespace dataframe_tests_interval_type_inference {
24885
24886void pd_test_interval_type_inference_breaks_int() {
24887    std::cout << "========= interval_type_inference_breaks_int ======================= ";
24888    auto idx = pandas::IntervalIndex<double>::from_breaks({0.0, 1.0, 2.0, 3.0});
24889    if (idx.subtype_override() != "int64")
24890        throw std::runtime_error("expected subtype_override 'int64', got '" + idx.subtype_override() + "'");
24891    std::string dtype = idx.dtype_name();
24892    if (dtype.find("int64") == std::string::npos)
24893        throw std::runtime_error("expected dtype containing 'int64', got '" + dtype + "'");
24894    std::string fmt = idx.format_interval(0);
24895    if (fmt.find('.') != std::string::npos)
24896        throw std::runtime_error("expected integer format without decimal, got '" + fmt + "'");
24897    std::cout << " -> tests passed" << std::endl;
24898}
left (pd_test_1_all.cpp:1909)
1899    if (empty.size() != 0) {
1900        std::cout << "[FAIL] : in test_constructors() : default constructor size" << std::endl;
1901        return;
1902    }
1903    if (empty.closed() != pandas::IntervalClosed::Right) {
1904        std::cout << "[FAIL] : in test_constructors() : default closure" << std::endl;
1905        return;
1906    }
1907
1908    // Constructor from left/right arrays
1909    numpy::NDArray<numpy::float64> left(std::vector<size_t>{3});
1910    numpy::NDArray<numpy::float64> right(std::vector<size_t>{3});
1911    left.setElementAt({0}, 0.0);  right.setElementAt({0}, 1.0);
1912    left.setElementAt({1}, 1.0);  right.setElementAt({1}, 2.0);
1913    left.setElementAt({2}, 2.0);  right.setElementAt({2}, 3.0);
1914
1915    pandas::IntervalArrayFloat64 arr1(left, right);
1916    if (arr1.size() != 3) {
1917        std::cout << "[FAIL] : in test_constructors() : array size" << std::endl;
1918        return;
1919    }
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;
length (pd_test_1_all.cpp:2137)
2127    auto mid0 = mid_arr[0];
2128    auto mid1 = mid_arr[1];
2129    auto mid2 = mid_arr[2];
2130    if (!mid0.has_value() || std::abs(mid0.value() - 1.0) > 1e-10 ||
2131        !mid1.has_value() || std::abs(mid1.value() - 3.5) > 1e-10 ||
2132        !mid2.has_value() || std::abs(mid2.value() - 7.5) > 1e-10) {
2133        std::cout << "[FAIL] : in test_left_right_mid_length() : mid()" << std::endl;
2134        return;
2135    }
2136
2137    // Test length()
2138    auto len_arr = arr.length();
2139    if (len_arr.getElementAt({0}) != 2.0 ||
2140        len_arr.getElementAt({1}) != 3.0 ||
2141        len_arr.getElementAt({2}) != 5.0) {
2142        std::cout << "[FAIL] : in test_left_right_mid_length() : length()" << std::endl;
2143        return;
2144    }
2145
2146    std::cout << "-> tests passed" << std::endl;
2147}
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_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];
to_tuples (pd_test_1_all.cpp:13037)
13027    }
13028
13029    std::cout << " -> tests passed" << std::endl;
13030}
13031
13032void pd_test_interval_index_to_tuples() {
13033    std::cout << "========= to_tuples =========================";
13034
13035    auto idx = pandas::IntervalIndex64::from_breaks({0, 1, 2, 3});
13036
13037    auto tuples = idx.to_tuples();
13038
13039    bool passed = (tuples.size() == 3 &&
13040                   tuples[0].has_value() && tuples[0]->first == 0 && tuples[0]->second == 1 &&
13041                   tuples[1].has_value() && tuples[1]->first == 1 && tuples[1]->second == 2 &&
13042                   tuples[2].has_value() && tuples[2]->first == 2 && tuples[2]->second == 3);
13043    if (!passed) {
13044        std::cout << "  [FAIL] : in pd_test_interval_index_to_tuples() : check failed" << std::endl;
13045        throw std::runtime_error("pd_test_interval_index_to_tuples failed");
13046    }
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_empty (pd_test_1_all.cpp:2164)
2154    // Test with right-closed intervals (a, b]
2155    std::vector<std::pair<numpy::float64, numpy::float64>> tuples = {
2156        {0.0, 1.0},   // Not empty
2157        {1.0, 1.0},   // Empty (1, 1] has no points
2158        {2.0, 2.0},   // Empty
2159        {2.0, 3.0}    // Not empty
2160    };
2161
2162    auto arr_right = pandas::IntervalArrayFloat64::from_tuples(tuples, pandas::IntervalClosed::Right);
2163    auto empty_right = arr_right.is_empty();
2164
2165    if (empty_right[0].value_or(true) != false ||
2166        empty_right[1].value_or(false) != true ||
2167        empty_right[2].value_or(false) != true ||
2168        empty_right[3].value_or(true) != false) {
2169        std::cout << "[FAIL] : in test_is_empty() : right-closed" << std::endl;
2170        return;
2171    }
2172
2173    // Test with both-closed intervals [a, b] - [1, 1] is NOT empty
is_left_closed (pd_test_1_all.cpp:12830)
12820}
12821
12822void pd_test_interval_index_is_left_right_closed() {
12823    std::cout << "========= is_left_closed/is_right_closed =========================";
12824
12825    auto idx_right = pandas::IntervalIndex64::from_breaks({0, 1, 2}, pandas::IntervalClosed::Right);
12826    auto idx_left = pandas::IntervalIndex64::from_breaks({0, 1, 2}, pandas::IntervalClosed::Left);
12827    auto idx_both = pandas::IntervalIndex64::from_breaks({0, 1, 2}, pandas::IntervalClosed::Both);
12828    auto idx_neither = pandas::IntervalIndex64::from_breaks({0, 1, 2}, pandas::IntervalClosed::Neither);
12829
12830    bool passed = (!idx_right.is_left_closed() && idx_right.is_right_closed() &&
12831                   idx_left.is_left_closed() && !idx_left.is_right_closed() &&
12832                   idx_both.is_left_closed() && idx_both.is_right_closed() &&
12833                   !idx_neither.is_left_closed() && !idx_neither.is_right_closed());
12834    if (!passed) {
12835        std::cout << "  [FAIL] : in pd_test_interval_index_is_left_right_closed() : check failed" << std::endl;
12836        throw std::runtime_error("pd_test_interval_index_is_left_right_closed failed");
12837    }
12838
12839    std::cout << " -> tests passed" << std::endl;
12840}
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_non_overlapping_monotonic (pd_test_1_all.cpp:2457)
2447// ============================================================================
2448// Test: is_non_overlapping_monotonic
2449// ============================================================================
2450void test_is_non_overlapping_monotonic() {
2451    std::cout << "========= IntervalArray: is_non_overlapping_monotonic ======================= ";
2452
2453    // Monotonic, non-overlapping
2454    std::vector<numpy::float64> breaks1 = {0.0, 1.0, 2.0, 3.0};
2455    auto arr1 = pandas::IntervalArrayFloat64::from_breaks(breaks1, pandas::IntervalClosed::Right);
2456    if (!arr1.is_non_overlapping_monotonic()) {
2457        std::cout << "[FAIL] : in test_is_non_overlapping_monotonic() : should be true for breaks" << std::endl;
2458        return;
2459    }
2460
2461    // Non-monotonic (out of order)
2462    std::vector<std::pair<numpy::float64, numpy::float64>> tuples2 = {
2463        {2.0, 3.0}, {0.0, 1.0}, {1.0, 2.0}
2464    };
2465    auto arr2 = pandas::IntervalArrayFloat64::from_tuples(tuples2);
2466    if (arr2.is_non_overlapping_monotonic()) {
is_right_closed (pd_test_1_all.cpp:12830)
12820}
12821
12822void pd_test_interval_index_is_left_right_closed() {
12823    std::cout << "========= is_left_closed/is_right_closed =========================";
12824
12825    auto idx_right = pandas::IntervalIndex64::from_breaks({0, 1, 2}, pandas::IntervalClosed::Right);
12826    auto idx_left = pandas::IntervalIndex64::from_breaks({0, 1, 2}, pandas::IntervalClosed::Left);
12827    auto idx_both = pandas::IntervalIndex64::from_breaks({0, 1, 2}, pandas::IntervalClosed::Both);
12828    auto idx_neither = pandas::IntervalIndex64::from_breaks({0, 1, 2}, pandas::IntervalClosed::Neither);
12829
12830    bool passed = (!idx_right.is_left_closed() && idx_right.is_right_closed() &&
12831                   idx_left.is_left_closed() && !idx_left.is_right_closed() &&
12832                   idx_both.is_left_closed() && idx_both.is_right_closed() &&
12833                   !idx_neither.is_left_closed() && !idx_neither.is_right_closed());
12834    if (!passed) {
12835        std::cout << "  [FAIL] : in pd_test_interval_index_is_left_right_closed() : check failed" << std::endl;
12836        throw std::runtime_error("pd_test_interval_index_is_left_right_closed failed");
12837    }
12838
12839    std::cout << " -> tests passed" << std::endl;
12840}
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");
closed (pd_test_1_all.cpp:1903)
1893// ============================================================================
1894void test_constructors() {
1895    std::cout << "========= IntervalArray: constructors ======================= ";
1896
1897    // Default constructor
1898    pandas::IntervalArrayFloat64 empty;
1899    if (empty.size() != 0) {
1900        std::cout << "[FAIL] : in test_constructors() : default constructor size" << std::endl;
1901        return;
1902    }
1903    if (empty.closed() != pandas::IntervalClosed::Right) {
1904        std::cout << "[FAIL] : in test_constructors() : default closure" << std::endl;
1905        return;
1906    }
1907
1908    // Constructor from left/right arrays
1909    numpy::NDArray<numpy::float64> left(std::vector<size_t>{3});
1910    numpy::NDArray<numpy::float64> right(std::vector<size_t>{3});
1911    left.setElementAt({0}, 0.0);  right.setElementAt({0}, 1.0);
1912    left.setElementAt({1}, 1.0);  right.setElementAt({1}, 2.0);
1913    left.setElementAt({2}, 2.0);  right.setElementAt({2}, 3.0);
closed_string (pd_test_1_all.cpp:12813)
12803    std::cout << " -> tests passed" << std::endl;
12804}
12805
12806void pd_test_interval_index_closed_string() {
12807    std::cout << "========= closed_string =========================";
12808
12809    auto idx_right = pandas::IntervalIndex64::from_breaks({0, 1, 2}, pandas::IntervalClosed::Right);
12810    auto idx_left = pandas::IntervalIndex64::from_breaks({0, 1, 2}, pandas::IntervalClosed::Left);
12811
12812    bool passed = (idx_right.closed_string() == "right" && idx_left.closed_string() == "left");
12813    if (!passed) {
12814        std::cout << "  [FAIL] : in pd_test_interval_index_closed_string() : closed_string check failed" << std::endl;
12815        throw std::runtime_error("pd_test_interval_index_closed_string failed");
12816    }
12817
12818    std::cout << " -> tests passed" << std::endl;
12819}
12820
12821void pd_test_interval_index_is_left_right_closed() {
12822    std::cout << "========= is_left_closed/is_right_closed =========================";
contains (pd_test_1_all.cpp:2200)
2190// Test: contains method
2191// ============================================================================
2192void test_contains() {
2193    std::cout << "========= IntervalArray: contains ======================= ";
2194
2195    std::vector<numpy::float64> breaks = {0.0, 1.0, 2.0, 3.0};
2196
2197    // Right-closed intervals: (0, 1], (1, 2], (2, 3]
2198    auto arr_right = pandas::IntervalArrayFloat64::from_breaks(breaks, pandas::IntervalClosed::Right);
2199
2200    // Test contains(1.0) - should be in interval 0 but not 1 (since 1 is exclusive on left of interval 1)
2201    auto contains_1 = arr_right.contains(1.0);
2202    // (0, 1] contains 1: yes, (1, 2] contains 1: no (open on left), (2, 3] contains 1: no
2203    if (contains_1[0].value_or(false) != true ||
2204        contains_1[1].value_or(true) != false ||
2205        contains_1[2].value_or(true) != false) {
2206        std::cout << "[FAIL] : in test_contains() : right-closed contains 1.0" << std::endl;
2207        return;
2208    }
2209
2210    // Left-closed intervals: [0, 1), [1, 2), [2, 3)
contains (pd_test_1_all.cpp:2200)
2190// Test: contains method
2191// ============================================================================
2192void test_contains() {
2193    std::cout << "========= IntervalArray: contains ======================= ";
2194
2195    std::vector<numpy::float64> breaks = {0.0, 1.0, 2.0, 3.0};
2196
2197    // Right-closed intervals: (0, 1], (1, 2], (2, 3]
2198    auto arr_right = pandas::IntervalArrayFloat64::from_breaks(breaks, pandas::IntervalClosed::Right);
2199
2200    // Test contains(1.0) - should be in interval 0 but not 1 (since 1 is exclusive on left of interval 1)
2201    auto contains_1 = arr_right.contains(1.0);
2202    // (0, 1] contains 1: yes, (1, 2] contains 1: no (open on left), (2, 3] contains 1: no
2203    if (contains_1[0].value_or(false) != true ||
2204        contains_1[1].value_or(true) != false ||
2205        contains_1[2].value_or(true) != false) {
2206        std::cout << "[FAIL] : in test_contains() : right-closed contains 1.0" << std::endl;
2207        return;
2208    }
2209
2210    // Left-closed intervals: [0, 1), [1, 2), [2, 3)
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        }
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;
mid (pd_test_1_all.cpp:2124)
2114    // Test right()
2115    auto right_arr = arr.right();
2116    if (right_arr.getElementAt({0}) != 2.0 ||
2117        right_arr.getElementAt({1}) != 5.0 ||
2118        right_arr.getElementAt({2}) != 10.0) {
2119        std::cout << "[FAIL] : in test_left_right_mid_length() : right()" << std::endl;
2120        return;
2121    }
2122
2123    // Test mid()
2124    auto mid_arr = arr.mid();
2125    // (0+2)/2=1, (2+5)/2=3.5, (5+10)/2=7.5
2126    auto mid0 = mid_arr[0];
2127    auto mid1 = mid_arr[1];
2128    auto mid2 = mid_arr[2];
2129    if (!mid0.has_value() || std::abs(mid0.value() - 1.0) > 1e-10 ||
2130        !mid1.has_value() || std::abs(mid1.value() - 3.5) > 1e-10 ||
2131        !mid2.has_value() || std::abs(mid2.value() - 7.5) > 1e-10) {
2132        std::cout << "[FAIL] : in test_left_right_mid_length() : mid()" << std::endl;
2133        return;
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            }
overlaps (pd_test_1_all.cpp:2244)
2234// Test: overlaps method
2235// ============================================================================
2236void test_overlaps() {
2237    std::cout << "========= IntervalArray: overlaps ======================= ";
2238
2239    std::vector<numpy::float64> breaks = {0.0, 2.0, 4.0, 6.0};
2240    // Right-closed: (0, 2], (2, 4], (4, 6]
2241    auto arr = pandas::IntervalArrayFloat64::from_breaks(breaks, pandas::IntervalClosed::Right);
2242
2243    // Check overlap with (1, 3]
2244    auto overlap_1_3 = arr.overlaps(1.0, 3.0);
2245    // (0, 2] overlaps (1, 3]? Yes (share 1-2)
2246    // (2, 4] overlaps (1, 3]? Yes (share 2-3)
2247    // (4, 6] overlaps (1, 3]? No
2248    if (overlap_1_3[0].value_or(false) != true ||
2249        overlap_1_3[1].value_or(false) != true ||
2250        overlap_1_3[2].value_or(true) != false) {
2251        std::cout << "[FAIL] : in test_overlaps() : overlaps (1, 3]" << std::endl;
2252        return;
2253    }
overlaps (pd_test_1_all.cpp:2244)
2234// Test: overlaps method
2235// ============================================================================
2236void test_overlaps() {
2237    std::cout << "========= IntervalArray: overlaps ======================= ";
2238
2239    std::vector<numpy::float64> breaks = {0.0, 2.0, 4.0, 6.0};
2240    // Right-closed: (0, 2], (2, 4], (4, 6]
2241    auto arr = pandas::IntervalArrayFloat64::from_breaks(breaks, pandas::IntervalClosed::Right);
2242
2243    // Check overlap with (1, 3]
2244    auto overlap_1_3 = arr.overlaps(1.0, 3.0);
2245    // (0, 2] overlaps (1, 3]? Yes (share 1-2)
2246    // (2, 4] overlaps (1, 3]? Yes (share 2-3)
2247    // (4, 6] overlaps (1, 3]? No
2248    if (overlap_1_3[0].value_or(false) != true ||
2249        overlap_1_3[1].value_or(false) != true ||
2250        overlap_1_3[2].value_or(true) != false) {
2251        std::cout << "[FAIL] : in test_overlaps() : overlaps (1, 3]" << std::endl;
2252        return;
2253    }
right (pd_test_1_all.cpp:1910)
1900        std::cout << "[FAIL] : in test_constructors() : default constructor size" << std::endl;
1901        return;
1902    }
1903    if (empty.closed() != pandas::IntervalClosed::Right) {
1904        std::cout << "[FAIL] : in test_constructors() : default closure" << std::endl;
1905        return;
1906    }
1907
1908    // Constructor from left/right arrays
1909    numpy::NDArray<numpy::float64> left(std::vector<size_t>{3});
1910    numpy::NDArray<numpy::float64> right(std::vector<size_t>{3});
1911    left.setElementAt({0}, 0.0);  right.setElementAt({0}, 1.0);
1912    left.setElementAt({1}, 1.0);  right.setElementAt({1}, 2.0);
1913    left.setElementAt({2}, 2.0);  right.setElementAt({2}, 3.0);
1914
1915    pandas::IntervalArrayFloat64 arr1(left, right);
1916    if (arr1.size() != 3) {
1917        std::cout << "[FAIL] : in test_constructors() : array size" << std::endl;
1918        return;
1919    }
set_closed (pd_test_1_all.cpp:2285)
2275    std::vector<numpy::float64> breaks = {0.0, 1.0, 2.0};
2276    auto arr = pandas::IntervalArrayFloat64::from_breaks(breaks, pandas::IntervalClosed::Right);
2277
2278    if (arr.closed() != pandas::IntervalClosed::Right) {
2279        std::cout << "[FAIL] : in test_set_closed() : initial closure" << std::endl;
2280        return;
2281    }
2282
2283    // Change to left-closed
2284    auto arr_left = arr.set_closed(pandas::IntervalClosed::Left);
2285    if (arr_left.closed() != pandas::IntervalClosed::Left) {
2286        std::cout << "[FAIL] : in test_set_closed() : set to Left" << std::endl;
2287        return;
2288    }
2289
2290    // Original should be unchanged
2291    if (arr.closed() != pandas::IntervalClosed::Right) {
2292        std::cout << "[FAIL] : in test_set_closed() : original changed" << std::endl;
2293        return;
2294    }
set_closed (pd_test_1_all.cpp:2285)
2275    std::vector<numpy::float64> breaks = {0.0, 1.0, 2.0};
2276    auto arr = pandas::IntervalArrayFloat64::from_breaks(breaks, pandas::IntervalClosed::Right);
2277
2278    if (arr.closed() != pandas::IntervalClosed::Right) {
2279        std::cout << "[FAIL] : in test_set_closed() : initial closure" << std::endl;
2280        return;
2281    }
2282
2283    // Change to left-closed
2284    auto arr_left = arr.set_closed(pandas::IntervalClosed::Left);
2285    if (arr_left.closed() != pandas::IntervalClosed::Left) {
2286        std::cout << "[FAIL] : in test_set_closed() : set to Left" << std::endl;
2287        return;
2288    }
2289
2290    // Original should be unchanged
2291    if (arr.closed() != pandas::IntervalClosed::Right) {
2292        std::cout << "[FAIL] : in test_set_closed() : original changed" << std::endl;
2293        return;
2294    }
set_subtype_override (pd_test_3_all.cpp:24977)
24967    std::cout << "========= Interval repr float bounds ====================";
24968    pandas::Interval<double> iv(0.0, 1.5);
24969    if (iv.repr() != "Interval(0.0, 1.5, closed='right')")
24970        throw std::runtime_error("repr mismatch: " + iv.repr());
24971    std::cout << " -> tests passed" << std::endl;
24972}
24973
24974void pd_test_interval_repr_timedelta() {
24975    std::cout << "========= Interval repr timedelta subtype ===============";
24976    pandas::Interval<double> iv(0.0, 86400000000000.0);  // 1 day in nanos
24977    iv.set_subtype_override("timedelta64[ns]");
24978    std::string r = iv.repr();
24979    if (r.find("Timedelta") == std::string::npos)
24980        throw std::runtime_error("expected Timedelta in repr: " + r);
24981    if (r.find("1 days") == std::string::npos)
24982        throw std::runtime_error("expected '1 days' in repr: " + r);
24983    std::cout << " -> tests passed" << std::endl;
24984}
24985
24986void pd_test_interval_str_integer() {
24987    std::cout << "========= Interval to_string integer bounds =============";
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)
slice (pd_test_1_all.cpp:17546)
17536// ============================================================================
17537// Slicing / Indexing Tests
17538// ============================================================================
17539
17540void pd_test_period_index_slice() {
17541    std::cout << "========= slice method ================================";
17542
17543    std::vector<int64_t> ordinals = {0, 1, 2, 3, 4};
17544    pandas::PeriodIndex idx(ordinals, "D");
17545
17546    pandas::PeriodIndex sliced = idx.slice(1, 4);
17547
17548    bool passed = (sliced.size() == 3 &&
17549                   sliced[0].has_value() && *sliced[0] == 1);
17550    if (!passed) {
17551        std::cout << "  [FAIL] : in pd_test_period_index_slice()" << std::endl;
17552        throw std::runtime_error("pd_test_period_index_slice failed");
17553    }
17554
17555    std::cout << " -> tests passed" << std::endl;
17556}