diff --git a/csharp/Directory.Build.props b/csharp/Directory.Build.props
index 66c8acf5003cf..01d079c4744fc 100644
--- a/csharp/Directory.Build.props
+++ b/csharp/Directory.Build.props
@@ -34,7 +34,7 @@
true
- 8.0
+ latest
true
$(CSharpDir)ApacheArrow.snk
diff --git a/csharp/README.md b/csharp/README.md
index 79415837713b1..649e8a722574c 100644
--- a/csharp/README.md
+++ b/csharp/README.md
@@ -79,7 +79,7 @@ for currently available features.
- Int8, Int16, Int32, Int64
- UInt8, UInt16, UInt32, UInt64
-- Float, Double
+- Float, Double, Half-float (.NET 6+)
- Binary (variable-length)
- String (utf-8)
- Null
@@ -126,12 +126,10 @@ for currently available features.
- Dictionary Encoding
- Types
- Tensor
- - Table
- Arrays
- Union
- Dense
- Sparse
- - Half-Float
- Array Operations
- Equality / Comparison
- Casting
diff --git a/csharp/src/Apache.Arrow/Apache.Arrow.csproj b/csharp/src/Apache.Arrow/Apache.Arrow.csproj
index 51f188ae87be8..c57c8e48b9494 100644
--- a/csharp/src/Apache.Arrow/Apache.Arrow.csproj
+++ b/csharp/src/Apache.Arrow/Apache.Arrow.csproj
@@ -1,7 +1,7 @@
- netstandard1.3;netstandard2.0;netcoreapp3.1
+ netstandard1.3;netstandard2.0;netcoreapp3.1;net6.0
true
$(DefineConstants);UNSAFE_BYTEBUFFER;BYTEBUFFER_NO_BOUNDS_CHECK;ENABLE_SPAN_T
@@ -41,4 +41,7 @@
+
+
+
diff --git a/csharp/src/Apache.Arrow/Arrays/ArrowArrayBuilderFactory.cs b/csharp/src/Apache.Arrow/Arrays/ArrowArrayBuilderFactory.cs
index 618ac0212ea5a..ef80edb838162 100644
--- a/csharp/src/Apache.Arrow/Arrays/ArrowArrayBuilderFactory.cs
+++ b/csharp/src/Apache.Arrow/Arrays/ArrowArrayBuilderFactory.cs
@@ -42,6 +42,12 @@ internal static IArrowArrayBuilder>
return new UInt64Array.Builder();
case ArrowTypeId.Int64:
return new Int64Array.Builder();
+ case ArrowTypeId.HalfFloat:
+#if NET5_0_OR_GREATER
+ return new HalfFloatArray.Builder();
+#else
+ throw new NotSupportedException("Half-float arrays are not supported by this target framework.");
+#endif
case ArrowTypeId.Float:
return new FloatArray.Builder();
case ArrowTypeId.Double:
@@ -70,7 +76,6 @@ internal static IArrowArrayBuilder>
case ArrowTypeId.Union:
case ArrowTypeId.Dictionary:
case ArrowTypeId.FixedSizedBinary:
- case ArrowTypeId.HalfFloat:
case ArrowTypeId.Interval:
case ArrowTypeId.Map:
default:
diff --git a/csharp/src/Apache.Arrow/Arrays/ArrowArrayFactory.cs b/csharp/src/Apache.Arrow/Arrays/ArrowArrayFactory.cs
index 819540a46a10b..319dcab17e75c 100644
--- a/csharp/src/Apache.Arrow/Arrays/ArrowArrayFactory.cs
+++ b/csharp/src/Apache.Arrow/Arrays/ArrowArrayFactory.cs
@@ -76,6 +76,11 @@ public static IArrowArray BuildArray(ArrayData data)
case ArrowTypeId.Dictionary:
return new DictionaryArray(data);
case ArrowTypeId.HalfFloat:
+#if NET5_0_OR_GREATER
+ return new HalfFloatArray(data);
+#else
+ throw new NotSupportedException("Half-float arrays are not supported by this target framework.");
+#endif
case ArrowTypeId.Interval:
case ArrowTypeId.Map:
default:
diff --git a/csharp/src/Apache.Arrow/Arrays/HalfFloatArray.cs b/csharp/src/Apache.Arrow/Arrays/HalfFloatArray.cs
new file mode 100644
index 0000000000000..072629e0e8ab8
--- /dev/null
+++ b/csharp/src/Apache.Arrow/Arrays/HalfFloatArray.cs
@@ -0,0 +1,46 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using Apache.Arrow.Types;
+using System;
+
+namespace Apache.Arrow
+{
+ public class HalfFloatArray : PrimitiveArray
+ {
+ public class Builder : PrimitiveArrayBuilder
+ {
+ protected override HalfFloatArray Build(
+ ArrowBuffer valueBuffer, ArrowBuffer nullBitmapBuffer,
+ int length, int nullCount, int offset) =>
+ new HalfFloatArray(valueBuffer, nullBitmapBuffer, length, nullCount, offset);
+ }
+
+ public HalfFloatArray(
+ ArrowBuffer valueBuffer, ArrowBuffer nullBitmapBuffer,
+ int length, int nullCount, int offset)
+ : this(new ArrayData(HalfFloatType.Default, length, nullCount, offset,
+ new[] { nullBitmapBuffer, valueBuffer }))
+ { }
+
+ public HalfFloatArray(ArrayData data)
+ : base(data)
+ {
+ data.EnsureDataType(ArrowTypeId.HalfFloat);
+ }
+
+ public override void Accept(IArrowArrayVisitor visitor) => Accept(this, visitor);
+ }
+}
diff --git a/csharp/src/Apache.Arrow/Ipc/ArrowStreamWriter.cs b/csharp/src/Apache.Arrow/Ipc/ArrowStreamWriter.cs
index e0d241da80608..d9cafc06bffba 100644
--- a/csharp/src/Apache.Arrow/Ipc/ArrowStreamWriter.cs
+++ b/csharp/src/Apache.Arrow/Ipc/ArrowStreamWriter.cs
@@ -38,6 +38,9 @@ internal class ArrowRecordBatchFlatBufferBuilder :
IArrowArrayVisitor,
IArrowArrayVisitor,
IArrowArrayVisitor,
+#if NET5_0_OR_GREATER
+ IArrowArrayVisitor,
+#endif
IArrowArrayVisitor,
IArrowArrayVisitor,
IArrowArrayVisitor,
@@ -87,6 +90,9 @@ public ArrowRecordBatchFlatBufferBuilder()
public void Visit(UInt16Array array) => CreateBuffers(array);
public void Visit(UInt32Array array) => CreateBuffers(array);
public void Visit(UInt64Array array) => CreateBuffers(array);
+#if NET5_0_OR_GREATER
+ public void Visit(HalfFloatArray array) => CreateBuffers(array);
+#endif
public void Visit(FloatArray array) => CreateBuffers(array);
public void Visit(DoubleArray array) => CreateBuffers(array);
public void Visit(TimestampArray array) => CreateBuffers(array);
diff --git a/csharp/src/Apache.Arrow/RecordBatch.Builder.cs b/csharp/src/Apache.Arrow/RecordBatch.Builder.cs
index ec77967aab7cf..b5d5ec9ea0bbf 100644
--- a/csharp/src/Apache.Arrow/RecordBatch.Builder.cs
+++ b/csharp/src/Apache.Arrow/RecordBatch.Builder.cs
@@ -42,6 +42,9 @@ internal ArrayBuilder(MemoryAllocator allocator)
public UInt16Array UInt16(Action action) => Build(new UInt16Array.Builder(), action);
public UInt32Array UInt32(Action action) => Build(new UInt32Array.Builder(), action);
public UInt64Array UInt64(Action action) => Build(new UInt64Array.Builder(), action);
+#if NET5_0_OR_GREATER
+ public HalfFloatArray HalfFloat(Action action) => Build(new HalfFloatArray.Builder(), action);
+#endif
public FloatArray Float(Action action) => Build(new FloatArray.Builder(), action);
public DoubleArray Double(Action action) => Build(new DoubleArray.Builder(), action);
public Decimal128Array Decimal128(Decimal128Type type, Action action) =>
diff --git a/csharp/test/Apache.Arrow.Tests/ArrayBuilderTests.cs b/csharp/test/Apache.Arrow.Tests/ArrayBuilderTests.cs
index 0c58617ad1752..8c90f780720f8 100644
--- a/csharp/test/Apache.Arrow.Tests/ArrayBuilderTests.cs
+++ b/csharp/test/Apache.Arrow.Tests/ArrayBuilderTests.cs
@@ -17,6 +17,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Numerics;
using Xunit;
namespace Apache.Arrow.Tests
@@ -28,36 +29,49 @@ public class ArrayBuilderTests
[Fact]
public void PrimitiveArrayBuildersProduceExpectedArray()
{
- TestArrayBuilder(x => x.Append(10).Append(20).Append(30));
- TestArrayBuilder(x => x.Append(10).Append(20).Append(30));
- TestArrayBuilder(x => x.Append(10).Append(20).Append(30));
- TestArrayBuilder(x => x.Append(10).Append(20).Append(30));
- TestArrayBuilder(x => x.Append(10).Append(20).Append(30));
- TestArrayBuilder(x => x.Append(10).Append(20).Append(30));
- TestArrayBuilder(x => x.Append(10).Append(20).Append(30));
- TestArrayBuilder(x => x.Append(10).Append(20).Append(30));
- TestArrayBuilder(x => x.Append(10).Append(20).Append(30));
- TestArrayBuilder(x => x.Append(10).Append(20).Append(30));
- TestArrayBuilder(x => x.Append(10).Append(20).Append(30));
- TestArrayBuilder(x => x.Append(10).Append(20).Append(30));
+ Test();
+ Test();
+ Test();
+ Test();
+ Test();
+ Test();
+ Test();
+ Test();
+ Test();
+ Test();
+ Test();
+ Test();
+ Test();
+
+ static void Test()
+ where T : struct, INumber
+ where TArray : PrimitiveArray
+ where TBuilder : PrimitiveArrayBuilder, new() =>
+ TestArrayBuilder(x => x.Append(T.CreateChecked(10)).Append(T.CreateChecked(20)).Append(T.CreateChecked(30)));
}
[Fact]
public void PrimitiveArrayBuildersProduceExpectedArrayWithNulls()
{
- TestArrayBuilder(x => x.Append(123).AppendNull().AppendNull().Append(127), 4, 2, 0x09);
- TestArrayBuilder(x => x.Append(123).AppendNull().AppendNull().Append(456), 4, 2, 0x09);
- TestArrayBuilder(x => x.Append(123).AppendNull().AppendNull().Append(456), 4, 2, 0x09);
- TestArrayBuilder(x => x.Append(123).AppendNull().AppendNull().Append(456), 4, 2, 0x09);
- TestArrayBuilder(x => x.Append(123).AppendNull().AppendNull().Append(127), 4, 2, 0x09);
- TestArrayBuilder(x => x.Append(123).AppendNull().AppendNull().Append(456), 4, 2, 0x09);
- TestArrayBuilder(x => x.Append(123).AppendNull().AppendNull().Append(456), 4, 2, 0x09);
- TestArrayBuilder(x => x.Append(123).AppendNull().AppendNull().Append(456), 4, 2, 0x09);
- TestArrayBuilder(x => x.Append(123).AppendNull().AppendNull().Append(456), 4, 2, 0x09);
- TestArrayBuilder(x => x.Append(123).AppendNull().AppendNull().Append(456), 4, 2, 0x09);
- TestArrayBuilder(x => x.Append(123).AppendNull().AppendNull().Append(456), 4, 2, 0x09);
- TestArrayBuilder(x => x.Append(123).AppendNull().AppendNull().Append(456), 4, 2, 0x09);
- TestArrayBuilder(x => x.Append(123).AppendNull().AppendNull().Append(456), 4, 2, 0x09);
+ Test();
+ Test();
+ Test();
+ Test();
+ Test();
+ Test();
+ Test();
+ Test();
+ Test();
+ Test();
+ Test();
+ Test();
+ Test();
+
+ static void Test()
+ where T : struct, INumber
+ where TArray : PrimitiveArray
+ where TBuilder : PrimitiveArrayBuilder, new() =>
+ TestArrayBuilder(x => x.Append(T.CreateChecked(123)).AppendNull().AppendNull().Append(T.CreateChecked(127)), 4, 2, 0x09);
}
[Fact]
@@ -138,7 +152,7 @@ List ConvertStringArrayToList(StringArray array)
[Fact]
public void ListArrayBuilderValidityBuffer()
{
- ListArray listArray = new ListArray.Builder(Int64Type.Default).Append().AppendNull().Build();
+ ListArray listArray = new ListArray.Builder(Int64Type.Default).Append().AppendNull().Build();
Assert.False(listArray.IsValid(2));
}
diff --git a/csharp/test/Apache.Arrow.Tests/ArrowArrayTests.cs b/csharp/test/Apache.Arrow.Tests/ArrowArrayTests.cs
index 1e3d4b12f56d3..af3e0f80e6473 100644
--- a/csharp/test/Apache.Arrow.Tests/ArrowArrayTests.cs
+++ b/csharp/test/Apache.Arrow.Tests/ArrowArrayTests.cs
@@ -14,6 +14,7 @@
// limitations under the License.
using System;
+using System.Numerics;
using Xunit;
namespace Apache.Arrow.Tests
@@ -95,40 +96,54 @@ void TestIsValid(ArrowBuffer valueBuf, ArrowBuffer nullBitmapBuf, int length, in
[Fact]
public void SliceArray()
{
- TestSlice(x => x.Append(10).Append(20).Append(30));
- TestSlice(x => x.Append(10).Append(20).Append(30));
- TestSlice(x => x.Append(10).Append(20).Append(30));
- TestSlice(x => x.Append(10).Append(20).Append(30));
- TestSlice(x => x.Append(10).Append(20).Append(30));
- TestSlice(x => x.Append(10).Append(20).Append(30));
- TestSlice(x => x.Append(10).Append(20).Append(30));
- TestSlice(x => x.Append(10).Append(20).Append(30));
- TestSlice(x => x.Append(10).Append(20).Append(30));
- TestSlice(x => x.Append(10).Append(20).Append(30));
+ TestNumberSlice();
+ TestNumberSlice();
+ TestNumberSlice();
+ TestNumberSlice();
+ TestNumberSlice();
+ TestNumberSlice();
+ TestNumberSlice();
+ TestNumberSlice();
+ TestNumberSlice();
+ TestNumberSlice();
+ TestNumberSlice();
TestSlice(x => x.Append(new DateTime(2019, 1, 1)).Append(new DateTime(2019, 1, 2)).Append(new DateTime(2019, 1, 3)));
TestSlice(x => x.Append(new DateTime(2019, 1, 1)).Append(new DateTime(2019, 1, 2)).Append(new DateTime(2019, 1, 3)));
- TestSlice(x => x.Append(10).Append(20).Append(30));
- TestSlice(x => x.Append(10).Append(20).Append(30));
+ TestNumberSlice();
+ TestNumberSlice();
TestSlice(x => x.Append("10").Append("20").Append("30"));
+
+ static void TestNumberSlice()
+ where T : struct, INumber
+ where TArray : PrimitiveArray
+ where TBuilder : PrimitiveArrayBuilder, new() =>
+ TestSlice(x => x.Append(T.CreateChecked(10)).Append(T.CreateChecked(20)).Append(T.CreateChecked(30)));
}
[Fact]
public void SlicePrimitiveArrayWithNulls()
{
- TestSlice(x => x.Append(10).Append(20).AppendNull().Append(30));
- TestSlice(x => x.Append(10).AppendNull().Append(20).AppendNull().Append(30));
- TestSlice(x => x.Append(10).Append(20).AppendNull().Append(30));
- TestSlice(x => x.Append(10).Append(20).AppendNull().Append(30));
- TestSlice(x => x.Append(10).Append(20).Append(30).AppendNull());
- TestSlice(x => x.Append(10).Append(20).AppendNull().AppendNull().Append(30));
- TestSlice(x => x.Append(10).Append(20).AppendNull().Append(30));
- TestSlice(x => x.Append(10).Append(20).AppendNull().Append(30));
- TestSlice(x => x.AppendNull().Append(10).Append(20).AppendNull().Append(30));
- TestSlice(x => x.Append(10).Append(20).AppendNull().Append(30));
+ TestNumberSlice();
+ TestNumberSlice();
+ TestNumberSlice();
+ TestNumberSlice();
+ TestNumberSlice();
+ TestNumberSlice();
+ TestNumberSlice();
+ TestNumberSlice();
+ TestNumberSlice();
+ TestNumberSlice();
+ TestNumberSlice();
TestSlice(x => x.Append(new DateTime(2019, 1, 1)).Append(new DateTime(2019, 1, 2)).AppendNull().Append(new DateTime(2019, 1, 3)));
TestSlice(x => x.Append(new DateTime(2019, 1, 1)).Append(new DateTime(2019, 1, 2)).AppendNull().Append(new DateTime(2019, 1, 3)));
- TestSlice(x => x.Append(10).AppendNull().Append(30));
- TestSlice(x => x.Append(10).AppendNull().Append(30));
+ TestNumberSlice();
+ TestNumberSlice();
+
+ static void TestNumberSlice()
+ where T : struct, INumber
+ where TArray : PrimitiveArray
+ where TBuilder : PrimitiveArrayBuilder, new() =>
+ TestSlice(x => x.AppendNull().Append(T.CreateChecked(10)).Append(T.CreateChecked(20)).AppendNull().Append(T.CreateChecked(30)));
}
[Fact]
@@ -183,6 +198,7 @@ private class ArraySliceValidator :
IArrowArrayVisitor,
IArrowArrayVisitor,
IArrowArrayVisitor,
+ IArrowArrayVisitor,
IArrowArrayVisitor,
IArrowArrayVisitor,
IArrowArrayVisitor,
@@ -224,6 +240,7 @@ public void Visit(Date64Array array)
public void Visit(Time32Array array) => ValidateArrays(array);
public void Visit(Time64Array array) => ValidateArrays(array);
+ public void Visit(HalfFloatArray array) => ValidateArrays(array);
public void Visit(FloatArray array) => ValidateArrays(array);
public void Visit(DoubleArray array) => ValidateArrays(array);
public void Visit(StringArray array) => ValidateArrays(array);
diff --git a/csharp/test/Apache.Arrow.Tests/ArrowReaderVerifier.cs b/csharp/test/Apache.Arrow.Tests/ArrowReaderVerifier.cs
index 4a15bc7117649..8fde77d930779 100644
--- a/csharp/test/Apache.Arrow.Tests/ArrowReaderVerifier.cs
+++ b/csharp/test/Apache.Arrow.Tests/ArrowReaderVerifier.cs
@@ -74,6 +74,7 @@ private class ArrayComparer :
IArrowArrayVisitor,
IArrowArrayVisitor,
IArrowArrayVisitor,
+ IArrowArrayVisitor,
IArrowArrayVisitor,
IArrowArrayVisitor,
IArrowArrayVisitor,
@@ -110,6 +111,7 @@ public ArrayComparer(IArrowArray expectedArray, bool strictCompare)
public void Visit(UInt16Array array) => CompareArrays(array);
public void Visit(UInt32Array array) => CompareArrays(array);
public void Visit(UInt64Array array) => CompareArrays(array);
+ public void Visit(HalfFloatArray array) => CompareArrays(array);
public void Visit(FloatArray array) => CompareArrays(array);
public void Visit(DoubleArray array) => CompareArrays(array);
public void Visit(BooleanArray array) => CompareArrays(array);
diff --git a/docs/source/status.rst b/docs/source/status.rst
index 73c025a8b7493..3ca82ac3e3bb1 100644
--- a/docs/source/status.rst
+++ b/docs/source/status.rst
@@ -40,7 +40,7 @@ Data Types
+-------------------+-------+-------+-------+------------+-------+-------+-------+
| UInt8/16/32/64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+-------------------+-------+-------+-------+------------+-------+-------+-------+
-| Float16 | | | ✓ | | | ✓ | ✓ |
+| Float16 | | | ✓ | | ✓ (1)| ✓ | ✓ |
+-------------------+-------+-------+-------+------------+-------+-------+-------+
| Float32/64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+-------------------+-------+-------+-------+------------+-------+-------+-------+
@@ -92,7 +92,7 @@ Data Types
| Data type | C++ | Java | Go | JavaScript | C# | Rust | Julia |
| (special) | | | | | | | |
+===================+=======+=======+=======+============+=======+=======+=======+
-| Dictionary | ✓ | ✓ (1) | ✓ | ✓ (1) | ✓ (1) | ✓ (1) | ✓ |
+| Dictionary | ✓ | ✓ (2) | ✓ | ✓ (2) | ✓ (2) | ✓ (2) | ✓ |
+-------------------+-------+-------+-------+------------+-------+-------+-------+
| Extension | ✓ | ✓ | ✓ | | | ✓ | ✓ |
+-------------------+-------+-------+-------+------------+-------+-------+-------+
@@ -101,7 +101,8 @@ Data Types
Notes:
-* \(1) Nested dictionaries not supported
+* \(1) Float16 support in C# is only available when targeting .NET 6+.
+* \(2) Nested dictionaries not supported
.. seealso::
The :ref:`format_columnar` specification.