This is an automated email from the ASF dual-hosted git repository.
kevingurney pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new c9012a0b53 GH-37391: [MATLAB] Implement the `isequal()` method on
`arrow.array.Array` (#37446)
c9012a0b53 is described below
commit c9012a0b53a692d1640f1f373a9442339cb4526d
Author: sgilmore10 <[email protected]>
AuthorDate: Wed Aug 30 11:40:39 2023 -0400
GH-37391: [MATLAB] Implement the `isequal()` method on `arrow.array.Array`
(#37446)
### Rationale for this change
Currently, it's not possible to determine if two `arrow.array.Array`
instances are equal because the `isequal()` method always returns `false` by
default:
**Example**
```matlab
>> a = arrow.array([1 2 3])
a =
[
1,
2,
3
]
% Compare a with itself.
>> tf = isequal(a, a)
tf =
logical
0
````
### What changes are included in this PR?
1. Defined an `isequal()` overload on the `arrow.array.Array` super-class.
2. Added a new method called `isEqual()` on the
`arrow::matlab::array::proxy::Array` class.
Two arrays are considered equal in the MATLAB Interface if the following
conditions are met:
1. They have the same type
2. They have the same length
3. The same elements are valid
4. Corresponding valid elements are equal.
**NOTE:** NaN values are not considered equal.
**Example**
```matlab
>> a = arrow.array([1 2 3])
a =
[
1,
2,
3
]
% Compare a with itself.
>> tf = isequal(a, a)
tf =
logical
1
```
### Are these changes tested?
Yes. Added positive and negative `isequal` tests for all concrete
subclasses of `arrow.array.Array`.
### Are there any user-facing changes?
Yes. Users can now use `isequal()` with `arrow.array.Array` subclasses.
### Future Directions
1. Implement
[`isequaln`](https://www.mathworks.com/help/matlab/ref/isequaln.html) so that
users can test array equality with NaNs being treated as equal.
* Closes: #37391
Authored-by: Sarah Gilmore <[email protected]>
Signed-off-by: Kevin Gurney <[email protected]>
---
matlab/src/cpp/arrow/matlab/array/proxy/array.cc | 26 ++++++-
matlab/src/cpp/arrow/matlab/array/proxy/array.h | 4 +-
.../cpp/arrow/matlab/tabular/proxy/record_batch.cc | 2 +-
matlab/src/matlab/+arrow/+array/Array.m | 19 +++++
matlab/test/arrow/array/hNumericArray.m | 51 +++++++++++++
matlab/test/arrow/array/tBooleanArray.m | 53 +++++++++++++
matlab/test/arrow/array/tDate32Array.m | 53 +++++++++++++
matlab/test/arrow/array/tFloat32Array.m | 7 ++
matlab/test/arrow/array/tFloat64Array.m | 7 ++
matlab/test/arrow/array/tStringArray.m | 51 +++++++++++++
matlab/test/arrow/array/tTime32Array.m | 66 ++++++++++++++++
matlab/test/arrow/array/tTime64Array.m | 66 ++++++++++++++++
matlab/test/arrow/array/tTimestampArray.m | 89 ++++++++++++++++++++++
13 files changed, 491 insertions(+), 3 deletions(-)
diff --git a/matlab/src/cpp/arrow/matlab/array/proxy/array.cc
b/matlab/src/cpp/arrow/matlab/array/proxy/array.cc
index 8520cf1f21..9dc14c3419 100644
--- a/matlab/src/cpp/arrow/matlab/array/proxy/array.cc
+++ b/matlab/src/cpp/arrow/matlab/array/proxy/array.cc
@@ -35,9 +35,11 @@ namespace arrow::matlab::array::proxy {
REGISTER_METHOD(Array, length);
REGISTER_METHOD(Array, valid);
REGISTER_METHOD(Array, type);
+ REGISTER_METHOD(Array, isEqual);
+
}
- std::shared_ptr<arrow::Array> Array::getArray() {
+ std::shared_ptr<arrow::Array> Array::unwrap() {
return array;
}
@@ -91,4 +93,26 @@ namespace arrow::matlab::array::proxy {
context.outputs[0] = factory.createScalar(proxy_id);
context.outputs[1] =
factory.createScalar(static_cast<int64_t>(type_id));
}
+
+ void Array::isEqual(libmexclass::proxy::method::Context& context) {
+ namespace mda = ::matlab::data;
+
+ const mda::TypedArray<uint64_t> array_proxy_ids = context.inputs[0];
+
+ bool is_equal = true;
+ const auto equals_options = arrow::EqualOptions::Defaults();
+ for (const auto& array_proxy_id : array_proxy_ids) {
+ // Retrieve the Array proxy from the ProxyManager
+ auto proxy =
libmexclass::proxy::ProxyManager::getProxy(array_proxy_id);
+ auto array_proxy = std::static_pointer_cast<proxy::Array>(proxy);
+ auto array_to_compare = array_proxy->unwrap();
+
+ if (!array->Equals(array_to_compare, equals_options)) {
+ is_equal = false;
+ break;
+ }
+ }
+ mda::ArrayFactory factory;
+ context.outputs[0] = factory.createScalar(is_equal);
+ }
}
diff --git a/matlab/src/cpp/arrow/matlab/array/proxy/array.h
b/matlab/src/cpp/arrow/matlab/array/proxy/array.h
index 9019976725..fe28c8a8dd 100644
--- a/matlab/src/cpp/arrow/matlab/array/proxy/array.h
+++ b/matlab/src/cpp/arrow/matlab/array/proxy/array.h
@@ -30,7 +30,7 @@ class Array : public libmexclass::proxy::Proxy {
virtual ~Array() {}
- std::shared_ptr<arrow::Array> getArray();
+ std::shared_ptr<arrow::Array> unwrap();
protected:
@@ -44,6 +44,8 @@ class Array : public libmexclass::proxy::Proxy {
virtual void toMATLAB(libmexclass::proxy::method::Context& context) =
0;
+ void isEqual(libmexclass::proxy::method::Context& context);
+
std::shared_ptr<arrow::Array> array;
};
diff --git a/matlab/src/cpp/arrow/matlab/tabular/proxy/record_batch.cc
b/matlab/src/cpp/arrow/matlab/tabular/proxy/record_batch.cc
index c526bfc81d..7b81eee21e 100644
--- a/matlab/src/cpp/arrow/matlab/tabular/proxy/record_batch.cc
+++ b/matlab/src/cpp/arrow/matlab/tabular/proxy/record_batch.cc
@@ -81,7 +81,7 @@ namespace arrow::matlab::tabular::proxy {
for (const auto& arrow_array_proxy_id : arrow_array_proxy_ids) {
auto proxy =
libmexclass::proxy::ProxyManager::getProxy(arrow_array_proxy_id);
auto arrow_array_proxy =
std::static_pointer_cast<arrow::matlab::array::proxy::Array>(proxy);
- auto arrow_array = arrow_array_proxy->getArray();
+ auto arrow_array = arrow_array_proxy->unwrap();
arrow_arrays.push_back(arrow_array);
}
diff --git a/matlab/src/matlab/+arrow/+array/Array.m
b/matlab/src/matlab/+arrow/+array/Array.m
index 46b46660e7..dbf4abad45 100644
--- a/matlab/src/matlab/+arrow/+array/Array.m
+++ b/matlab/src/matlab/+arrow/+array/Array.m
@@ -69,5 +69,24 @@ classdef (Abstract) Array < matlab.mixin.CustomDisplay & ...
disp(obj.toString());
end
end
+
+ methods
+ function tf = isequal(obj, varargin)
+ narginchk(2, inf);
+ tf = false;
+ % Extract each array's proxy ID
+ proxyIDs = zeros(numel(varargin), 1, "uint64");
+ for ii = 1:numel(varargin)
+ array = varargin{ii};
+ if ~isa(array, "arrow.array.Array")
+ % Return early if array is not a arrow.array.Array
+ return;
+ end
+ proxyIDs(ii) = array.Proxy.ID;
+ end
+ % Invoke isEqual proxy object method
+ tf = obj.Proxy.isEqual(proxyIDs);
+ end
+ end
end
diff --git a/matlab/test/arrow/array/hNumericArray.m
b/matlab/test/arrow/array/hNumericArray.m
index fc5f5a0599..2780ae5668 100644
--- a/matlab/test/arrow/array/hNumericArray.m
+++ b/matlab/test/arrow/array/hNumericArray.m
@@ -149,5 +149,56 @@ classdef hNumericArray < matlab.unittest.TestCase
arrowArray = tc.ArrowArrayConstructorFcn(data);
tc.verifyEqual(arrowArray.Type.ID, tc.ArrowType.ID);
end
+
+ function TestIsEqualTrue(tc)
+ % Verifies arrays are considered equal if:
+ %
+ % 1. Their Type properties are equal
+ % 2. They have the same length (i.e. their Length properties are
equal)
+ % 3. They have the same validity bitmap (i.e. their Valid
properties are equal)
+ % 4. All corresponding valid elements have the same values
+
+ data1 = tc.MatlabArrayFcn([1 2 3 4]);
+ data2 = tc.MatlabArrayFcn([1 2 5 4]);
+ array1 = tc.ArrowArrayConstructorFcn(data1, Valid=[1 2 4]);
+ array2 = tc.ArrowArrayConstructorFcn(data1, Valid=[1 2 4]);
+ array3 = tc.ArrowArrayConstructorFcn(data2, Valid=[1 2 4]);
+
+ tc.verifyTrue(isequal(array1, array2));
+ tc.verifyTrue(isequal(array1, array3));
+
+ % Test supplying more than two arrays to isequal
+ tc.verifyTrue(isequal(array1, array2, array3));
+ end
+
+ function TestIsEqualFalse(tc)
+ % Verify isequal returns false when expected.
+ data1 = tc.MatlabArrayFcn([1 2 3 4]);
+ data2 = tc.MatlabArrayFcn([5 2 3 4]);
+ data3 = tc.MatlabArrayFcn([1 2 3 4 5]);
+ array1 = tc.ArrowArrayConstructorFcn(data1, Valid=[1 2 4]);
+ array2 = tc.ArrowArrayConstructorFcn(data1, Valid=[1 4]);
+ array3 = tc.ArrowArrayConstructorFcn(data2, Valid=[1 2 4]);
+ array4 = arrow.array([true false true false]);
+ array5 = tc.ArrowArrayConstructorFcn(data3, Valid=[1 2 4]);
+
+ % Their validity bitmaps are not equal
+ tc.verifyFalse(isequal(array1, array2));
+
+ % Not all corresponding valid elements are equal
+ tc.verifyFalse(isequal(array1, array3));
+
+ % Their Type properties are not equal
+ tc.verifyFalse(isequal(array1, array4));
+
+ % Their Length properties are not equal
+ tc.verifyFalse(isequal(array1, array5));
+
+ % Comparing an arrow.array.Array to a MATLAB double
+ tc.verifyFalse(isequal(array1, 1));
+
+ % Test supplying more than two arrays to isequal
+ tc.verifyFalse(isequal(array1, array1, array3, array4, array5));
+ end
end
end
diff --git a/matlab/test/arrow/array/tBooleanArray.m
b/matlab/test/arrow/array/tBooleanArray.m
index df7f052597..0a488039a0 100644
--- a/matlab/test/arrow/array/tBooleanArray.m
+++ b/matlab/test/arrow/array/tBooleanArray.m
@@ -158,5 +158,58 @@ classdef tBooleanArray < matlab.unittest.TestCase
arrowArray = tc.ArrowArrayConstructorFcn(data);
tc.verifyEqual(arrowArray.Type.ID, tc.ArrowType.ID);
end
+
+ function TestIsEqualTrue(tc)
+ % Verifies arrays are considered equal if:
+ %
+ % 1. Their Type properties are equal
+ % 2. They have the same length (i.e. their Length properties are
equal)
+ % 3. They have the same validity bitmap (i.e. their Valid
properties are equal)
+ % 4. All corresponding valid elements have the same values
+
+
+ data1 = tc.MatlabArrayFcn([true false true false]);
+ data2 = tc.MatlabArrayFcn([true false false false]);
+ array1 = tc.ArrowArrayConstructorFcn(data1, Valid=[1 2 4]);
+ array2 = tc.ArrowArrayConstructorFcn(data1, Valid=[1 2 4]);
+ array3 = tc.ArrowArrayConstructorFcn(data2, Valid=[1 2 4]);
+
+ tc.verifyTrue(isequal(array1, array2));
+ tc.verifyTrue(isequal(array1, array3));
+
+ % Test supplying more than two arrays to isequal
+ tc.verifyTrue(isequal(array1, array2, array3));
+ end
+
+ function TestIsEqualFalse(tc)
+ % Verify isequal returns false when expected.
+
+ data1 = tc.MatlabArrayFcn([true false true false]);
+ data2 = tc.MatlabArrayFcn([false false true false]);
+ data3 = tc.MatlabArrayFcn([true false true false false]);
+ array1 = tc.ArrowArrayConstructorFcn(data1, Valid=[1 2 4]);
+ array2 = tc.ArrowArrayConstructorFcn(data1, Valid=[1 4]);
+ array3 = tc.ArrowArrayConstructorFcn(data2, Valid=[1 2 4]);
+ array4 = arrow.array([1 2 3 4]);
+ array5 = tc.ArrowArrayConstructorFcn(data3, Valid=[1 2 4]);
+
+ % Their validity bitmaps are not equal
+ tc.verifyFalse(isequal(array1, array2));
+
+ % Not all corresponding valid elements are equal
+ tc.verifyFalse(isequal(array1, array3));
+
+ % Their Type properties are not equal
+ tc.verifyFalse(isequal(array1, array4));
+
+ % Their Length properties are not equal
+ tc.verifyFalse(isequal(array1, array5));
+
+ % Comparing an arrow.array.Array to a MATLAB double
+ tc.verifyFalse(isequal(array1, 1));
+
+ % Test supplying more than two arrays to isequal
+ tc.verifyFalse(isequal(array1, array1, array3, array4, array5));
+ end
end
end
diff --git a/matlab/test/arrow/array/tDate32Array.m
b/matlab/test/arrow/array/tDate32Array.m
index a5fc1c1b64..d7289c1df8 100644
--- a/matlab/test/arrow/array/tDate32Array.m
+++ b/matlab/test/arrow/array/tDate32Array.m
@@ -280,6 +280,59 @@ classdef tDate32Array < matlab.unittest.TestCase
testCase.verifyEqual(actual, expected);
end
+ function TestIsEqualTrue(tc)
+ % Verifies arrays are considered equal if:
+ %
+ % 1. Their Type properties are equal
+ % 2. They have the same length (i.e. their Length properties are
equal)
+ % 3. They have the same validity bitmap (i.e. their Valid
properties are equal)
+ % 4. All corresponding valid elements have the same values
+
+
+ dates1 = datetime(2023, 6, 22) + days(0:4);
+ dates2 = datetime(2023, 6, 22) + days([0 1 5 3 4]);
+
+ array1 = tc.ArrowArrayConstructorFcn(dates1, Valid=[1 2 4]);
+ array2 = tc.ArrowArrayConstructorFcn(dates1, Valid=[1 2 4]);
+ array3 = tc.ArrowArrayConstructorFcn(dates2, Valid=[1 2 4]);
+
+ tc.verifyTrue(isequal(array1, array2));
+ tc.verifyTrue(isequal(array1, array3));
+
+ % Test supplying more than two arrays to isequal
+ tc.verifyTrue(isequal(array1, array2, array3));
+ end
+
+ function TestIsEqualFalse(tc)
+ % Verify isequal returns false when expected.
+ dates1 = datetime(2023, 6, 22) + days(0:4);
+ dates2 = datetime(2023, 6, 22) + days([1 1 2 3 4]);
+ dates3 = datetime(2023, 6, 22) + days(0:5);
+ array1 = tc.ArrowArrayConstructorFcn(dates1, Valid=[1 2 4]);
+ array2 = tc.ArrowArrayConstructorFcn(dates1, Valid=[1 4]);
+ array3 = tc.ArrowArrayConstructorFcn(dates2, Valid=[1 2 4]);
+ array4 = arrow.array([true false true false]);
+ array5 = tc.ArrowArrayConstructorFcn(dates3, Valid=[1 2 4]);
+
+ % Their validity bitmaps are not equal
+ tc.verifyFalse(isequal(array1, array2));
+
+ % Not all corresponding valid elements are equal
+ tc.verifyFalse(isequal(array1, array3));
+
+ % Their Type properties are not equal
+ tc.verifyFalse(isequal(array1, array4));
+
+ % Their Length properties are not equal
+ tc.verifyFalse(isequal(array1, array5));
+
+ % Comparing an arrow.array.Array to a MATLAB double
+ tc.verifyFalse(isequal(array1, 1));
+
+ % Test supplying more than two arrays to isequal
+ tc.verifyFalse(isequal(array1, array1, array3, array4, array5));
+ end
+
end
methods
diff --git a/matlab/test/arrow/array/tFloat32Array.m
b/matlab/test/arrow/array/tFloat32Array.m
index 2ec9b90b4d..8a583c6b64 100644
--- a/matlab/test/arrow/array/tFloat32Array.m
+++ b/matlab/test/arrow/array/tFloat32Array.m
@@ -110,5 +110,12 @@ classdef tFloat32Array < hNumericArray
testCase.verifyEqual(arrowArray.Valid, [true; false; true]);
testCase.verifyEqual(toMATLAB(arrowArray), single([1; NaN; 3]));
end
+
+ function TestNanIsEqualFalse(testCase)
+ % Verify corresponding NaN values are not considered equal.
+ matlabArray = single([1 2 NaN 4]);
+ arrowArray = testCase.ArrowArrayConstructorFcn(matlabArray,
InferNulls=false);
+ testCase.verifyFalse(isequal(arrowArray, arrowArray));
+ end
end
end
diff --git a/matlab/test/arrow/array/tFloat64Array.m
b/matlab/test/arrow/array/tFloat64Array.m
index a39a3d1e62..ec2871a124 100755
--- a/matlab/test/arrow/array/tFloat64Array.m
+++ b/matlab/test/arrow/array/tFloat64Array.m
@@ -115,5 +115,12 @@ classdef tFloat64Array < hNumericArray
testCase.verifyEqual(arrowArray.Valid, [true; false; true]);
testCase.verifyEqual(toMATLAB(arrowArray), [1; NaN; 3]);
end
+
+ function TestNanIsEqualFalse(testCase)
+ % Verify corresponding NaN values are not considered equal.
+ matlabArray = [1 2 NaN 4];
+ arrowArray = testCase.ArrowArrayConstructorFcn(matlabArray,
InferNulls=false);
+ testCase.verifyFalse(isequal(arrowArray, arrowArray));
+ end
end
end
diff --git a/matlab/test/arrow/array/tStringArray.m
b/matlab/test/arrow/array/tStringArray.m
index 85628ce421..f042a21ff8 100644
--- a/matlab/test/arrow/array/tStringArray.m
+++ b/matlab/test/arrow/array/tStringArray.m
@@ -228,5 +228,56 @@ classdef tStringArray < matlab.unittest.TestCase
matlabArray = char.empty(1, 0);
tc.verifyError(@() tc.ArrowArrayConstructorFcn(matlabArray),
"arrow:array:InvalidType");
end
+
+ function TestIsEqualTrue(tc)
+ % Verifies arrays are considered equal if:
+ %
+ % 1. Their Type properties are equal
+ % 2. They have the same length (i.e. their Length properties are
equal)
+ % 3. They have the same validity bitmap (i.e. their Valid
properties are equal)
+ % 4. All corresponding valid elements have the same values
+
+ data1 = tc.MatlabArrayFcn(["1" "2" "3" "4"]);
+ data2 = tc.MatlabArrayFcn(["1" "2" "5" "4"]);
+ array1 = tc.ArrowArrayConstructorFcn(data1, Valid=[1 2 4]);
+ array2 = tc.ArrowArrayConstructorFcn(data1, Valid=[1 2 4]);
+ array3 = tc.ArrowArrayConstructorFcn(data2, Valid=[1 2 4]);
+
+ tc.verifyTrue(isequal(array1, array2));
+ tc.verifyTrue(isequal(array1, array3));
+
+ % Test supplying more than two arrays to isequal
+ tc.verifyTrue(isequal(array1, array2, array3));
+ end
+
+ function TestIsEqualFalse(tc)
+ % Verify isequal returns false when expected.
+ data1 = tc.MatlabArrayFcn(["1" "2" "3" "4"]);
+ data2 = tc.MatlabArrayFcn(["5" "2" "3" "4"]);
+ data3 = tc.MatlabArrayFcn(["1" "2" "3" "4" "5"]);
+ array1 = tc.ArrowArrayConstructorFcn(data1, Valid=[1 2 4]);
+ array2 = tc.ArrowArrayConstructorFcn(data1, Valid=[1 4]);
+ array3 = tc.ArrowArrayConstructorFcn(data2, Valid=[1 2 4]);
+ array4 = arrow.array([true false true false]);
+ array5 = tc.ArrowArrayConstructorFcn(data3, Valid=[1 2 4]);
+
+ % Their validity bitmaps are not equal
+ tc.verifyFalse(isequal(array1, array2));
+
+ % Not all corresponding valid elements are equal
+ tc.verifyFalse(isequal(array1, array3));
+
+ % Their Type properties are not equal
+ tc.verifyFalse(isequal(array1, array4));
+
+ % Their Length properties are not equal
+ tc.verifyFalse(isequal(array1, array5));
+
+ % Comparing an arrow.array.Array to a MATLAB double
+ tc.verifyFalse(isequal(array1, 1));
+
+ % Test supplying more than two arrays to isequal
+ tc.verifyFalse(isequal(array1, array1, array3, array4, array5));
+ end
end
end
diff --git a/matlab/test/arrow/array/tTime32Array.m
b/matlab/test/arrow/array/tTime32Array.m
index e874889e58..b593b2630c 100644
--- a/matlab/test/arrow/array/tTime32Array.m
+++ b/matlab/test/arrow/array/tTime32Array.m
@@ -208,6 +208,72 @@ classdef tTime32Array < matlab.unittest.TestCase
fcn = @() testCase.ArrowArrayConstructorFcn(numbers);
testCase.verifyError(fcn, "arrow:array:InvalidType");
end
+
+ function TestIsEqualTrue(tc, Unit)
+ % Verifies arrays are considered equal if:
+ %
+ % 1. Their Type properties are equal
+ % 2. They have the same length (i.e. their Length properties are
equal)
+ % 3. They have the same validity bitmap (i.e. their Valid
properties are equal)
+ % 4. All corresponding valid elements have the same values
+
+ times1 = seconds([1 2 3 4]);
+ times2 = seconds([1 2 10 4]);
+
+ array1 = tc.ArrowArrayConstructorFcn(times1, TimeUnit=Unit,
Valid=[1 2 4]);
+ array2 = tc.ArrowArrayConstructorFcn(times1, TimeUnit=Unit,
Valid=[1 2 4]);
+ array3 = tc.ArrowArrayConstructorFcn(times2, TimeUnit=Unit,
Valid=[1 2 4]);
+
+ tc.verifyTrue(isequal(array1, array2));
+ tc.verifyTrue(isequal(array1, array3));
+
+ % Test supplying more than two arrays to isequal
+ tc.verifyTrue(isequal(array1, array2, array3));
+ end
+
+ function TestIsEqualFalse(tc, Unit)
+ % Verify isequal returns false when expected.
+ times1 = seconds([1 2 3 4]);
+ times2 = seconds([1 1 2 3]);
+ times3 = seconds([1 2 3 4 5]);
+
+ array1 = tc.ArrowArrayConstructorFcn(times1, TimeUnit=Unit,
Valid=[1 2 4]);
+ array2 = tc.ArrowArrayConstructorFcn(times1, TimeUnit=Unit,
Valid=[1 4]);
+ array3 = tc.ArrowArrayConstructorFcn(times2, TimeUnit=Unit,
Valid=[1 2 4]);
+ array4 = arrow.array([true false true false]);
+ array5 = tc.ArrowArrayConstructorFcn(times3, Valid=[1 2 4]);
+
+ % Their validity bitmaps are not equal
+ tc.verifyFalse(isequal(array1, array2));
+
+ % Not all corresponding valid elements are equal
+ tc.verifyFalse(isequal(array1, array3));
+
+ % Their Type properties are not equal
+ tc.verifyFalse(isequal(array1, array4));
+
+ % Their Length properties are not equal
+ tc.verifyFalse(isequal(array1, array5));
+
+ % Comparing an arrow.array.Array to a MATLAB double
+ tc.verifyFalse(isequal(array1, 1));
+
+ % Test supplying more than two arrays to isequal
+ tc.verifyFalse(isequal(array1, array1, array3, array4, array5));
+ end
+
+ function TestIsEqualFalseTimeUnitMistmatch(tc)
+ % Verify two Time32Arrays are not considered equal if they have
+ % different TimeUnit values.
+
+ times1 = seconds([1 2 3 4]);
+
+ array1 = tc.ArrowArrayConstructorFcn(times1, TimeUnit="Second");
+ array2 = tc.ArrowArrayConstructorFcn(times1,
TimeUnit="Millisecond");
+
+ % arrays are not equal
+ tc.verifyFalse(isequal(array1, array2));
+ end
end
methods
diff --git a/matlab/test/arrow/array/tTime64Array.m
b/matlab/test/arrow/array/tTime64Array.m
index 973a8e6b6a..ea4fec3da6 100644
--- a/matlab/test/arrow/array/tTime64Array.m
+++ b/matlab/test/arrow/array/tTime64Array.m
@@ -224,6 +224,72 @@ classdef tTime64Array < matlab.unittest.TestCase
expected = milliseconds(1.0030030);
testCase.verifyEqual(duration(array), expected);
end
+
+ function TestIsEqualTrue(tc, Unit)
+ % Verifies arrays are considered equal if:
+ %
+ % 1. Their Type properties are equal
+ % 2. They have the same length (i.e. their Length properties are
equal)
+ % 3. They have the same validity bitmap (i.e. their Valid
properties are equal)
+ % 4. All corresponding valid elements have the same values
+
+ times1 = seconds([1 2 3 4]);
+ times2 = seconds([1 2 10 4]);
+
+ array1 = tc.ArrowArrayConstructorFcn(times1, TimeUnit=Unit,
Valid=[1 2 4]);
+ array2 = tc.ArrowArrayConstructorFcn(times1, TimeUnit=Unit,
Valid=[1 2 4]);
+ array3 = tc.ArrowArrayConstructorFcn(times2, TimeUnit=Unit,
Valid=[1 2 4]);
+
+ tc.verifyTrue(isequal(array1, array2));
+ tc.verifyTrue(isequal(array1, array3));
+
+ % Test supplying more than two arrays to isequal
+ tc.verifyTrue(isequal(array1, array2, array3));
+ end
+
+ function TestIsEqualFalse(tc, Unit)
+ % Verify isequal returns false when expected.
+
+ times1 = seconds([1 2 3 4]);
+ times2 = seconds([1 1 2 3]);
+ times3 = seconds([1 2 3 4 5]);
+
+ array1 = tc.ArrowArrayConstructorFcn(times1, TimeUnit=Unit,
Valid=[1 2 4]);
+ array2 = tc.ArrowArrayConstructorFcn(times1, TimeUnit=Unit,
Valid=[1 4]);
+ array3 = tc.ArrowArrayConstructorFcn(times2, TimeUnit=Unit,
Valid=[1 2 4]);
+ array4 = arrow.array([true false true false]);
+ array5 = tc.ArrowArrayConstructorFcn(times3, Valid=[1 2 4]);
+
+ % Their validity bitmaps are not equal
+ tc.verifyFalse(isequal(array1, array2));
+
+ % Not all corresponding valid elements are equal
+ tc.verifyFalse(isequal(array1, array3));
+
+ % Their Type properties are not equal
+ tc.verifyFalse(isequal(array1, array4));
+
+ % Their Length properties are not equal
+ tc.verifyFalse(isequal(array1, array5));
+
+ % Comparing an arrow.array.Array to a MATLAB double
+ tc.verifyFalse(isequal(array1, 1));
+
+ % Test supplying more than two arrays to isequal
+ tc.verifyFalse(isequal(array1, array1, array3, array4, array5));
+ end
+
+ function TestIsEqualFalseTimeUnitMistmatch(tc)
+ % Verify two Time64Arrays are not considered equal if they have
+ % different TimeUnit values.
+ times1 = seconds([1 2 3 4]);
+
+ array1 = tc.ArrowArrayConstructorFcn(times1,
TimeUnit="Nanosecond");
+ array2 = tc.ArrowArrayConstructorFcn(times1,
TimeUnit="Microsecond");
+
+ % arrays are not equal
+ tc.verifyFalse(isequal(array1, array2));
+ end
end
methods
diff --git a/matlab/test/arrow/array/tTimestampArray.m
b/matlab/test/arrow/array/tTimestampArray.m
index 5b7182c386..cf273b3de2 100644
--- a/matlab/test/arrow/array/tTimestampArray.m
+++ b/matlab/test/arrow/array/tTimestampArray.m
@@ -179,8 +179,97 @@ classdef tTimestampArray < matlab.unittest.TestCase
testCase.verifyEqual(arrowArray.Length, int64(0));
testCase.verifyEqual(arrowArray.Valid, logical.empty(0, 1));
testCase.verifyEqual(toMATLAB(arrowArray), datetime.empty(0, 1));
+ end
+
+ function TestIsEqualTrue(tc, TimeZone)
+ % Verifies arrays are considered equal if:
+ %
+ % 1. Their Type properties are equal
+ % 2. They have the same length (i.e. their Length properties are
equal)
+ % 3. They have the same validity bitmap (i.e. their Valid
properties are equal)
+ % 4. All corresponding valid elements have the same values
+
+ dates1 = datetime(2023, 6, 22, TimeZone=TimeZone) + days(0:4);
+ dates2 = datetime(2023, 6, 22, TimeZone=TimeZone) + days([0 1 5 3
4]);
+
+ array1 = tc.ArrowArrayConstructorFcn(dates1, Valid=[1 2 4]);
+ array2 = tc.ArrowArrayConstructorFcn(dates1, Valid=[1 2 4]);
+ array3 = tc.ArrowArrayConstructorFcn(dates2, Valid=[1 2 4]);
+
+ tc.verifyTrue(isequal(array1, array2));
+ tc.verifyTrue(isequal(array1, array3));
+
+ % Test supplying more than two arrays to isequal
+ tc.verifyTrue(isequal(array1, array2, array3));
+ end
+
+ function TestIsEqualFalse(tc, TimeZone)
+ % Verify isequal returns false when expected.
+
+ dates1 = datetime(2023, 6, 22, TimeZone=TimeZone) + days(0:4);
+ dates2 = datetime(2023, 6, 22, TimeZone=TimeZone) + days([1 1 2 3
4]);
+ dates3 = datetime(2023, 6, 22, TimeZone=TimeZone) + days(0:5);
+ array1 = tc.ArrowArrayConstructorFcn(dates1, Valid=[1 2 4]);
+ array2 = tc.ArrowArrayConstructorFcn(dates1, Valid=[1 4]);
+ array3 = tc.ArrowArrayConstructorFcn(dates2, Valid=[1 2 4]);
+ array4 = arrow.array([true false true false]);
+ array5 = tc.ArrowArrayConstructorFcn(dates3, Valid=[1 2 4]);
+
+ % Their validity bitmaps are not equal
+ tc.verifyFalse(isequal(array1, array2));
+
+ % Not all corresponding valid elements are equal
+ tc.verifyFalse(isequal(array1, array3));
+
+ % Their Type properties are not equal
+ tc.verifyFalse(isequal(array1, array4));
+ % Their Length properties are not equal
+ tc.verifyFalse(isequal(array1, array5));
+
+ % Comparing an arrow.array.Array to a MATLAB double
+ tc.verifyFalse(isequal(array1, 1));
+
+ % Test supplying more than two arrays to isequal
+ tc.verifyFalse(isequal(array1, array1, array3, array4, array5));
+ end
+
+ function TestIsEqualFalseTimeZoneMistmatch(tc)
+ % Verify two TimestampArrays are not considered equal if one
+ % has a TimeZone and one does not.
+ dates1 = datetime(2023, 6, 22, TimeZone="America/Anchorage") +
days(0:4);
+ dates2 = dates1 - tzoffset(dates1);
+ dates2.TimeZone = '';
+
+ array1 = tc.ArrowArrayConstructorFcn(dates1);
+ array2 = tc.ArrowArrayConstructorFcn(dates2);
+
+ % arrays are not equal
+ tc.verifyFalse(isequal(array1, array2));
+ end
+
+ function TestIsEqualSameInstantDifferentTimeZone(tc)
+ % Verify two TimestampArrays are not considered equal if
+ % they represent the same "instant in time", but have different
+ % TimeZone values.
+ dates1 = datetime(2023, 6, 22, TimeZone="America/Anchorage") +
days(0:4);
+ dates2 = dates1;
+ dates2.TimeZone = "America/New_York";
+
+ array1 = tc.ArrowArrayConstructorFcn(dates1);
+ array2 = tc.ArrowArrayConstructorFcn(dates2);
+
+ % arrays are not equal
+ tc.verifyFalse(isequal(array1, array2));
+ end
+ function TestIsEqualFalseTimeUnitMistmatch(tc, TimeZone)
+ % Verify two TimestampArrays are not considered equal if their
+ % TimeUnit values differ.
+ dates1 = datetime(2023, 6, 22, TimeZone=TimeZone) + days(0:4);
+ array1 = tc.ArrowArrayConstructorFcn(dates1,
TimeUnit="Millisecond");
+ array2 = tc.ArrowArrayConstructorFcn(dates1,
TimeUnit="Microsecond");
+ tc.verifyFalse(isequal(array1, array2));
end
end