From c07f5bceacd5efbdfd2ab3a673916d2ff46078c8 Mon Sep 17 00:00:00 2001 From: James Duong Date: Tue, 26 Sep 2023 12:18:52 -0700 Subject: [PATCH 01/56] GH-37705: [Java] Extra input methods for VarChar writers (#37883) ### Rationale for this change Improve the convenience of using VarCharWriter and LargeVarCharWriter interfaces. Also allow users to avoid unnecessary overhead creating Arrow buffers when writing String and Text data. ### What changes are included in this PR? Add write() methods for Text and String types. Ensure these methods are part of the writer interfaces and not just the Impls.### Are these changes tested? ### Are these changes tested? Yes. ### Are there any user-facing changes? No. * Closes: #37705 Authored-by: James Duong Signed-off-by: David Li --- .../templates/AbstractFieldWriter.java | 10 +++ .../codegen/templates/ComplexWriters.java | 21 ++++- .../complex/writer/TestSimpleWriter.java | 81 +++++++++++++++---- 3 files changed, 94 insertions(+), 18 deletions(-) diff --git a/java/vector/src/main/codegen/templates/AbstractFieldWriter.java b/java/vector/src/main/codegen/templates/AbstractFieldWriter.java index 5e6580b6131c1..bb4ee45eaa073 100644 --- a/java/vector/src/main/codegen/templates/AbstractFieldWriter.java +++ b/java/vector/src/main/codegen/templates/AbstractFieldWriter.java @@ -142,6 +142,16 @@ public void write(${name}Holder holder) { } + <#if minor.class?ends_with("VarChar")> + public void write${minor.class}(${friendlyType} value) { + fail("${name}"); + } + + public void write${minor.class}(String value) { + fail("${name}"); + } + + public void writeNull() { diff --git a/java/vector/src/main/codegen/templates/ComplexWriters.java b/java/vector/src/main/codegen/templates/ComplexWriters.java index 4ae4c4f75f208..51a52a6e3070d 100644 --- a/java/vector/src/main/codegen/templates/ComplexWriters.java +++ b/java/vector/src/main/codegen/templates/ComplexWriters.java @@ -44,7 +44,11 @@ public class ${eName}WriterImpl extends AbstractFieldWriter { final ${name}Vector vector; - public ${eName}WriterImpl(${name}Vector vector) { +<#if minor.class?ends_with("VarChar")> + private final Text textBuffer = new Text(); + + +public ${eName}WriterImpl(${name}Vector vector) { this.vector = vector; } @@ -120,11 +124,19 @@ public void write(Nullable${minor.class}Holder h) { } - <#if minor.class == "VarChar"> + <#if minor.class?ends_with("VarChar")> + @Override public void write${minor.class}(${friendlyType} value) { vector.setSafe(idx(), value); vector.setValueCount(idx()+1); } + + @Override + public void write${minor.class}(String value) { + textBuffer.set(value); + vector.setSafe(idx(), textBuffer); + vector.setValueCount(idx()+1); + } <#if minor.class?starts_with("Decimal")> @@ -256,6 +268,11 @@ public interface ${eName}Writer extends BaseWriter { public void writeTo${minor.class}(ByteBuffer value, int offset, int length); +<#if minor.class?ends_with("VarChar")> + public void write${minor.class}(${friendlyType} value); + + public void write${minor.class}(String value); + } diff --git a/java/vector/src/test/java/org/apache/arrow/vector/complex/writer/TestSimpleWriter.java b/java/vector/src/test/java/org/apache/arrow/vector/complex/writer/TestSimpleWriter.java index 7c06509b23c87..ef918b13fb691 100644 --- a/java/vector/src/test/java/org/apache/arrow/vector/complex/writer/TestSimpleWriter.java +++ b/java/vector/src/test/java/org/apache/arrow/vector/complex/writer/TestSimpleWriter.java @@ -22,9 +22,14 @@ import org.apache.arrow.memory.BufferAllocator; import org.apache.arrow.memory.RootAllocator; import org.apache.arrow.vector.LargeVarBinaryVector; +import org.apache.arrow.vector.LargeVarCharVector; import org.apache.arrow.vector.VarBinaryVector; +import org.apache.arrow.vector.VarCharVector; import org.apache.arrow.vector.complex.impl.LargeVarBinaryWriterImpl; +import org.apache.arrow.vector.complex.impl.LargeVarCharWriterImpl; import org.apache.arrow.vector.complex.impl.VarBinaryWriterImpl; +import org.apache.arrow.vector.complex.impl.VarCharWriterImpl; +import org.apache.arrow.vector.util.Text; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -45,9 +50,9 @@ public void terminate() throws Exception { } @Test - public void testWriteByteArrayToVarBinary() { + public void testWriteByteArrayToVarBinary() throws Exception { try (VarBinaryVector vector = new VarBinaryVector("test", allocator); - VarBinaryWriterImpl writer = new VarBinaryWriterImpl(vector)) { + VarBinaryWriter writer = new VarBinaryWriterImpl(vector)) { byte[] input = new byte[] { 0x01, 0x02 }; writer.writeToVarBinary(input); byte[] result = vector.get(0); @@ -56,9 +61,9 @@ public void testWriteByteArrayToVarBinary() { } @Test - public void testWriteByteArrayWithOffsetToVarBinary() { + public void testWriteByteArrayWithOffsetToVarBinary() throws Exception { try (VarBinaryVector vector = new VarBinaryVector("test", allocator); - VarBinaryWriterImpl writer = new VarBinaryWriterImpl(vector)) { + VarBinaryWriter writer = new VarBinaryWriterImpl(vector)) { byte[] input = new byte[] { 0x01, 0x02 }; writer.writeToVarBinary(input, 1, 1); byte[] result = vector.get(0); @@ -67,9 +72,9 @@ public void testWriteByteArrayWithOffsetToVarBinary() { } @Test - public void testWriteByteBufferToVarBinary() { + public void testWriteByteBufferToVarBinary() throws Exception { try (VarBinaryVector vector = new VarBinaryVector("test", allocator); - VarBinaryWriterImpl writer = new VarBinaryWriterImpl(vector)) { + VarBinaryWriter writer = new VarBinaryWriterImpl(vector)) { byte[] input = new byte[] { 0x01, 0x02 }; ByteBuffer buffer = ByteBuffer.wrap(input); writer.writeToVarBinary(buffer); @@ -79,9 +84,9 @@ public void testWriteByteBufferToVarBinary() { } @Test - public void testWriteByteBufferWithOffsetToVarBinary() { + public void testWriteByteBufferWithOffsetToVarBinary() throws Exception { try (VarBinaryVector vector = new VarBinaryVector("test", allocator); - VarBinaryWriterImpl writer = new VarBinaryWriterImpl(vector)) { + VarBinaryWriter writer = new VarBinaryWriterImpl(vector)) { byte[] input = new byte[] { 0x01, 0x02 }; ByteBuffer buffer = ByteBuffer.wrap(input); writer.writeToVarBinary(buffer, 1, 1); @@ -91,9 +96,9 @@ public void testWriteByteBufferWithOffsetToVarBinary() { } @Test - public void testWriteByteArrayToLargeVarBinary() { + public void testWriteByteArrayToLargeVarBinary() throws Exception { try (LargeVarBinaryVector vector = new LargeVarBinaryVector("test", allocator); - LargeVarBinaryWriterImpl writer = new LargeVarBinaryWriterImpl(vector)) { + LargeVarBinaryWriter writer = new LargeVarBinaryWriterImpl(vector)) { byte[] input = new byte[] { 0x01, 0x02 }; writer.writeToLargeVarBinary(input); byte[] result = vector.get(0); @@ -102,9 +107,9 @@ public void testWriteByteArrayToLargeVarBinary() { } @Test - public void testWriteByteArrayWithOffsetToLargeVarBinary() { + public void testWriteByteArrayWithOffsetToLargeVarBinary() throws Exception { try (LargeVarBinaryVector vector = new LargeVarBinaryVector("test", allocator); - LargeVarBinaryWriterImpl writer = new LargeVarBinaryWriterImpl(vector)) { + LargeVarBinaryWriter writer = new LargeVarBinaryWriterImpl(vector)) { byte[] input = new byte[] { 0x01, 0x02 }; writer.writeToLargeVarBinary(input, 1, 1); byte[] result = vector.get(0); @@ -113,9 +118,9 @@ public void testWriteByteArrayWithOffsetToLargeVarBinary() { } @Test - public void testWriteByteBufferToLargeVarBinary() { + public void testWriteByteBufferToLargeVarBinary() throws Exception { try (LargeVarBinaryVector vector = new LargeVarBinaryVector("test", allocator); - LargeVarBinaryWriterImpl writer = new LargeVarBinaryWriterImpl(vector)) { + LargeVarBinaryWriter writer = new LargeVarBinaryWriterImpl(vector)) { byte[] input = new byte[] { 0x01, 0x02 }; ByteBuffer buffer = ByteBuffer.wrap(input); writer.writeToLargeVarBinary(buffer); @@ -125,9 +130,9 @@ public void testWriteByteBufferToLargeVarBinary() { } @Test - public void testWriteByteBufferWithOffsetToLargeVarBinary() { + public void testWriteByteBufferWithOffsetToLargeVarBinary() throws Exception { try (LargeVarBinaryVector vector = new LargeVarBinaryVector("test", allocator); - LargeVarBinaryWriterImpl writer = new LargeVarBinaryWriterImpl(vector)) { + LargeVarBinaryWriter writer = new LargeVarBinaryWriterImpl(vector)) { byte[] input = new byte[] { 0x01, 0x02 }; ByteBuffer buffer = ByteBuffer.wrap(input); writer.writeToLargeVarBinary(buffer, 1, 1); @@ -135,4 +140,48 @@ public void testWriteByteBufferWithOffsetToLargeVarBinary() { Assert.assertArrayEquals(new byte[] { 0x02 }, result); } } + + @Test + public void testWriteStringToVarChar() throws Exception { + try (VarCharVector vector = new VarCharVector("test", allocator); + VarCharWriter writer = new VarCharWriterImpl(vector)) { + String input = "testInput"; + writer.writeVarChar(input); + String result = vector.getObject(0).toString(); + Assert.assertEquals(input, result); + } + } + + @Test + public void testWriteTextToVarChar() throws Exception { + try (VarCharVector vector = new VarCharVector("test", allocator); + VarCharWriter writer = new VarCharWriterImpl(vector)) { + String input = "testInput"; + writer.writeVarChar(new Text(input)); + String result = vector.getObject(0).toString(); + Assert.assertEquals(input, result); + } + } + + @Test + public void testWriteStringToLargeVarChar() throws Exception { + try (LargeVarCharVector vector = new LargeVarCharVector("test", allocator); + LargeVarCharWriter writer = new LargeVarCharWriterImpl(vector)) { + String input = "testInput"; + writer.writeLargeVarChar(input); + String result = vector.getObject(0).toString(); + Assert.assertEquals(input, result); + } + } + + @Test + public void testWriteTextToLargeVarChar() throws Exception { + try (LargeVarCharVector vector = new LargeVarCharVector("test", allocator); + LargeVarCharWriter writer = new LargeVarCharWriterImpl(vector)) { + String input = "testInput"; + writer.writeLargeVarChar(new Text(input)); + String result = vector.getObject(0).toString(); + Assert.assertEquals(input, result); + } + } } From 23c1bf9ff74b749c11385b38911d6aa8d85e180c Mon Sep 17 00:00:00 2001 From: Dominik Moritz Date: Tue, 26 Sep 2023 15:36:22 -0400 Subject: [PATCH 02/56] MINOR: [JS] update link to issues (#37882) Update link to use GitHub for issues. --- js/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/package.json b/js/package.json index 1ee0e11bca5b9..11bbe24f0244c 100644 --- a/js/package.json +++ b/js/package.json @@ -35,7 +35,7 @@ "author": "Apache Software Foundation", "license": "Apache-2.0", "bugs": { - "url": "https://issues.apache.org/jira/projects/ARROW" + "url": "https://github.com/apache/arrow/issues" }, "homepage": "https://github.com/apache/arrow/blob/main/js/README.md", "files": [ From 517d849b5813788ea23cf938629f668cba8b4fb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Cumplido?= Date: Tue, 26 Sep 2023 22:48:44 +0200 Subject: [PATCH 03/56] GH-37858: [Docs][JS] Fix check of remote URL to generate JS docs (#37870) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Rationale for this change JS Docs are currently not being generated. ### What changes are included in this PR? Use a regex check instead of an equality to cover both remote set with `.git` and without for upstream. Added also a fix to generate docs from origin from forks if necessary. ### Are these changes tested? Via archery ### Are there any user-facing changes? No * Closes: #37858 Authored-by: Raúl Cumplido Signed-off-by: Sutou Kouhei --- ci/scripts/js_build.sh | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ci/scripts/js_build.sh b/ci/scripts/js_build.sh index c97733257a721..d61f74f0b7ca1 100755 --- a/ci/scripts/js_build.sh +++ b/ci/scripts/js_build.sh @@ -32,12 +32,14 @@ yarn lint:ci yarn build if [ "${BUILD_DOCS_JS}" == "ON" ]; then - if [ "$(git config --get remote.origin.url)" == "https://github.com/apache/arrow.git" ]; then - yarn doc - elif [ "$(git config --get remote.upstream.url)" == "https://github.com/apache/arrow.git" ]; then - yarn doc --gitRemote upstream - elif [ "$(git config --get remote.apache.url)" == "git@github.com:apache/arrow.git" ]; then + # If apache or upstream are defined use those as remote. + # Otherwise use origin which could be a fork on PRs. + if [ "$(git config --get remote.apache.url)" == "git@github.com:apache/arrow.git" ]; then yarn doc --gitRemote apache + elif [[ "$(git config --get remote.upstream.url)" =~ "https://github.com/apache/arrow" ]]; then + yarn doc --gitRemote upstream + elif [[ "$(basename -s .git $(git config --get remote.origin.url))" == "arrow" ]]; then + yarn doc else echo "Failed to build docs because the remote is not set correctly. Please set the origin or upstream remote to https://github.com/apache/arrow.git or the apache remote to git@github.com:apache/arrow.git." exit 0 From e038498c70207df1ac64b1aa276a5fd5e3cd306b Mon Sep 17 00:00:00 2001 From: James Duong Date: Tue, 26 Sep 2023 13:52:07 -0700 Subject: [PATCH 04/56] GH-25659: [Java] Add DefaultVectorComparators for Large types (#37887) ### Rationale for this change Support additional vector types in DefaultVectorComparators to make arrow-algorithm easier to use. ### What changes are included in this PR? Add DefaultVectorComparators for large vector types (LargeVarCharVector and LargeVarBinaryVector). ### Are these changes tested? Yes. ### Are there any user-facing changes? No. * Closes: #25659 Authored-by: James Duong Signed-off-by: David Li --- .../sort/DefaultVectorComparators.java | 16 ++++++------ .../sort/TestDefaultVectorComparator.java | 26 +++++++++++++++++++ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/java/algorithm/src/main/java/org/apache/arrow/algorithm/sort/DefaultVectorComparators.java b/java/algorithm/src/main/java/org/apache/arrow/algorithm/sort/DefaultVectorComparators.java index 99d66f94261ee..4f9c8b7d71bab 100644 --- a/java/algorithm/src/main/java/org/apache/arrow/algorithm/sort/DefaultVectorComparators.java +++ b/java/algorithm/src/main/java/org/apache/arrow/algorithm/sort/DefaultVectorComparators.java @@ -25,7 +25,6 @@ import org.apache.arrow.memory.util.ArrowBufPointer; import org.apache.arrow.memory.util.ByteFunctionHelpers; import org.apache.arrow.vector.BaseFixedWidthVector; -import org.apache.arrow.vector.BaseVariableWidthVector; import org.apache.arrow.vector.BigIntVector; import org.apache.arrow.vector.BitVector; import org.apache.arrow.vector.DateDayVector; @@ -50,6 +49,7 @@ import org.apache.arrow.vector.UInt4Vector; import org.apache.arrow.vector.UInt8Vector; import org.apache.arrow.vector.ValueVector; +import org.apache.arrow.vector.VariableWidthVector; import org.apache.arrow.vector.complex.BaseRepeatedValueVector; /** @@ -112,7 +112,7 @@ public static VectorValueComparator createDefaultComp } else if (vector instanceof TimeStampVector) { return (VectorValueComparator) new TimeStampComparator(); } - } else if (vector instanceof BaseVariableWidthVector) { + } else if (vector instanceof VariableWidthVector) { return (VectorValueComparator) new VariableWidthComparator(); } else if (vector instanceof BaseRepeatedValueVector) { VectorValueComparator innerComparator = @@ -675,14 +675,14 @@ public VectorValueComparator createNew() { } /** - * Default comparator for {@link org.apache.arrow.vector.BaseVariableWidthVector}. + * Default comparator for {@link org.apache.arrow.vector.VariableWidthVector}. * The comparison is in lexicographic order, with null comes first. */ - public static class VariableWidthComparator extends VectorValueComparator { + public static class VariableWidthComparator extends VectorValueComparator { - private ArrowBufPointer reusablePointer1 = new ArrowBufPointer(); + private final ArrowBufPointer reusablePointer1 = new ArrowBufPointer(); - private ArrowBufPointer reusablePointer2 = new ArrowBufPointer(); + private final ArrowBufPointer reusablePointer2 = new ArrowBufPointer(); @Override public int compare(int index1, int index2) { @@ -699,7 +699,7 @@ public int compareNotNull(int index1, int index2) { } @Override - public VectorValueComparator createNew() { + public VectorValueComparator createNew() { return new VariableWidthComparator(); } } @@ -743,7 +743,7 @@ public int compareNotNull(int index1, int index2) { @Override public VectorValueComparator createNew() { VectorValueComparator newInnerComparator = innerComparator.createNew(); - return new RepeatedValueComparator(newInnerComparator); + return new RepeatedValueComparator<>(newInnerComparator); } @Override diff --git a/java/algorithm/src/test/java/org/apache/arrow/algorithm/sort/TestDefaultVectorComparator.java b/java/algorithm/src/test/java/org/apache/arrow/algorithm/sort/TestDefaultVectorComparator.java index 62051197740d8..bdae85110aa62 100644 --- a/java/algorithm/src/test/java/org/apache/arrow/algorithm/sort/TestDefaultVectorComparator.java +++ b/java/algorithm/src/test/java/org/apache/arrow/algorithm/sort/TestDefaultVectorComparator.java @@ -35,6 +35,8 @@ import org.apache.arrow.vector.Float8Vector; import org.apache.arrow.vector.IntVector; import org.apache.arrow.vector.IntervalDayVector; +import org.apache.arrow.vector.LargeVarBinaryVector; +import org.apache.arrow.vector.LargeVarCharVector; import org.apache.arrow.vector.SmallIntVector; import org.apache.arrow.vector.TimeMicroVector; import org.apache.arrow.vector.TimeMilliVector; @@ -47,6 +49,9 @@ import org.apache.arrow.vector.UInt2Vector; import org.apache.arrow.vector.UInt4Vector; import org.apache.arrow.vector.UInt8Vector; +import org.apache.arrow.vector.ValueVector; +import org.apache.arrow.vector.VarBinaryVector; +import org.apache.arrow.vector.VarCharVector; import org.apache.arrow.vector.complex.ListVector; import org.apache.arrow.vector.testing.ValueVectorDataPopulator; import org.apache.arrow.vector.types.TimeUnit; @@ -911,4 +916,25 @@ public void testCheckNullsOnCompareIsTrueWithEmptyVectors() { assertTrue(comparator.checkNullsOnCompare()); } } + + @Test + public void testVariableWidthDefaultComparators() { + try (VarCharVector vec = new VarCharVector("test", allocator)) { + verifyVariableWidthComparatorReturned(vec); + } + try (VarBinaryVector vec = new VarBinaryVector("test", allocator)) { + verifyVariableWidthComparatorReturned(vec); + } + try (LargeVarCharVector vec = new LargeVarCharVector("test", allocator)) { + verifyVariableWidthComparatorReturned(vec); + } + try (LargeVarBinaryVector vec = new LargeVarBinaryVector("test", allocator)) { + verifyVariableWidthComparatorReturned(vec); + } + } + + private static void verifyVariableWidthComparatorReturned(V vec) { + VectorValueComparator comparator = DefaultVectorComparators.createDefaultComparator(vec); + assertEquals(DefaultVectorComparators.VariableWidthComparator.class, comparator.getClass()); + } } From 7dc9f69a8a77345d0ec7920af9224ef96d7f5f78 Mon Sep 17 00:00:00 2001 From: Alenka Frim Date: Wed, 27 Sep 2023 16:23:26 +0200 Subject: [PATCH 05/56] GH-36590: [Docs] Support Pydata Sphinx Theme 0.14.0 (#36591) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Preview: http://crossbow.voltrondata.com/pr_docs/36591/ ### Rationale for this change The Pydata Sphinx Theme that we use for our documentation has been pinned due to bigger changes in the theme layout. It needs to be unpinned and our layout needs to be updated. ### What changes are included in this PR? Update of the Pydata Sphinx Theme and changes to our layout/structure: - dark/light mode - top menu bar - search button in the top right navigation bar - drop down from the theme layout in the top right navigation bar - version warnings bar from the theme layout - main landing page and the landing page for the dev docs ⚠️ Needs an update of the [versions.json](https://github.com/apache/arrow-site/blob/AlenkaF-patch-1/docs/_static/versions.json) ### Are these changes tested? Yes, locally. Will also add docs preview via GitHub actions. ### Are there any user-facing changes? No. * Closes: #32451 * Closes: #36590 Lead-authored-by: AlenkaF Co-authored-by: Sutou Kouhei Signed-off-by: Joris Van den Bossche --- ci/conda_env_sphinx.txt | 2 +- dev/release/01-prepare-test.rb | 3 +- dev/release/post-11-bump-versions-test.rb | 3 +- dev/release/utils-update-docs-versions.py | 10 +- docs/requirements.txt | 3 +- docs/source/_static/arrow-dark.png | Bin 0 -> 91541 bytes docs/source/_static/theme_overrides.css | 85 +------- docs/source/_static/versions.json | 47 +++-- docs/source/_static/versionwarning.js | 2 + docs/source/_templates/docs-sidebar.html | 25 --- docs/source/_templates/layout.html | 10 - docs/source/_templates/version-switcher.html | 60 ------ docs/source/c_glib/index.rst | 2 + docs/source/conf.py | 37 +++- docs/source/cpp/index.rst | 55 +++-- .../continuous_integration/index.rst | 1 + .../continuous_integration/overview.rst | 2 +- docs/source/developers/contributing.rst | 190 ----------------- .../developers/images/book-open-solid.svg | 2 +- docs/source/developers/images/bug-solid.svg | 2 +- docs/source/developers/images/code-solid.svg | 2 +- docs/source/developers/images/users-solid.svg | 2 +- docs/source/developers/index.rst | 198 +++++++++++++++++- docs/source/developers/overview.rst | 6 +- docs/source/developers/release.rst | 2 + docs/source/format/index.rst | 7 +- docs/source/index.rst | 115 ++++++---- docs/source/java/index.rst | 3 + docs/source/js/index.rst | 2 + docs/source/python/index.rst | 8 +- docs/source/r/index.rst | 2 + 31 files changed, 416 insertions(+), 472 deletions(-) create mode 100644 docs/source/_static/arrow-dark.png delete mode 100644 docs/source/_templates/docs-sidebar.html delete mode 100644 docs/source/_templates/version-switcher.html delete mode 100644 docs/source/developers/contributing.rst diff --git a/ci/conda_env_sphinx.txt b/ci/conda_env_sphinx.txt index bd08937ae81be..af1bfe9b780f4 100644 --- a/ci/conda_env_sphinx.txt +++ b/ci/conda_env_sphinx.txt @@ -20,7 +20,7 @@ breathe doxygen ipython numpydoc -pydata-sphinx-theme==0.8 +pydata-sphinx-theme sphinx-autobuild sphinx-design sphinx-copybutton diff --git a/dev/release/01-prepare-test.rb b/dev/release/01-prepare-test.rb index 1062e8b06c090..54437e9da60ce 100644 --- a/dev/release/01-prepare-test.rb +++ b/dev/release/01-prepare-test.rb @@ -170,7 +170,8 @@ def test_version_pre_tag "+ \"name\": \"#{@release_compatible_version} (stable)\",", "+ {", "+ \"name\": \"#{@previous_compatible_version}\",", - "+ \"version\": \"#{@previous_compatible_version}/\"", + "+ \"version\": \"#{@previous_compatible_version}/\",", + "+ \"url\": \"https://arrow.apache.org/docs/#{@previous_compatible_version}/\"", "+ },", ], ], diff --git a/dev/release/post-11-bump-versions-test.rb b/dev/release/post-11-bump-versions-test.rb index 0ef4646236740..8253472ccc5b9 100644 --- a/dev/release/post-11-bump-versions-test.rb +++ b/dev/release/post-11-bump-versions-test.rb @@ -148,7 +148,8 @@ def test_version_post_tag "+ \"name\": \"#{@release_compatible_version} (stable)\",", "+ {", "+ \"name\": \"#{@previous_compatible_version}\",", - "+ \"version\": \"#{@previous_compatible_version}/\"", + "+ \"version\": \"#{@previous_compatible_version}/\",", + "+ \"url\": \"https://arrow.apache.org/docs/#{@previous_compatible_version}/\"", "+ },", ], ], diff --git a/dev/release/utils-update-docs-versions.py b/dev/release/utils-update-docs-versions.py index 6e0137b7c84df..7ca4059214db5 100644 --- a/dev/release/utils-update-docs-versions.py +++ b/dev/release/utils-update-docs-versions.py @@ -50,11 +50,15 @@ # Create new versions new_versions = [ {"name": f"{dev_compatible_version} (dev)", - "version": "dev/"}, + "version": "dev/", + "url": "https://arrow.apache.org/docs/dev/"}, {"name": f"{stable_compatible_version} (stable)", - "version": ""}, + "version": "", + "url": "https://arrow.apache.org/docs/", + "preferred": True}, {"name": previous_compatible_version, - "version": f"{previous_compatible_version}/"}, + "version": f"{previous_compatible_version}/", + "url": f"https://arrow.apache.org/docs/{previous_compatible_version}/"}, *old_versions[2:], ] with open(main_versions_path, 'w') as json_file: diff --git a/docs/requirements.txt b/docs/requirements.txt index a4e5f7197b553..37a50d51dd54c 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -5,10 +5,9 @@ breathe ipython numpydoc -pydata-sphinx-theme==0.8 +pydata-sphinx-theme sphinx-autobuild sphinx-design sphinx-copybutton -sphinxcontrib-jquery sphinx==6.2 pandas diff --git a/docs/source/_static/arrow-dark.png b/docs/source/_static/arrow-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..618204a2370a56120e6809228498cac5d98ca54c GIT binary patch literal 91541 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 literal 0 HcmV?d00001 diff --git a/docs/source/_static/theme_overrides.css b/docs/source/_static/theme_overrides.css index e64d40f1116e5..eeba0ef4cce6e 100644 --- a/docs/source/_static/theme_overrides.css +++ b/docs/source/_static/theme_overrides.css @@ -21,43 +21,15 @@ /* Customizing with theme CSS variables */ :root { - --pst-color-active-navigation: 215, 70, 51; - --pst-color-link-hover: 215, 70, 51; - --pst-color-headerlink: 215, 70, 51; - /* Use normal text color (like h3, ..) instead of primary color */ - --pst-color-h1: var(--color-text-base); - --pst-color-h2: var(--color-text-base); - /* Use softer blue from bootstrap's default info color */ - --pst-color-info: 23, 162, 184; - --pst-header-height: 0px; -} - -code { - color: rgb(215, 70, 51); -} - -.footer { - text-align: center; -} - -/* Ensure the logo is properly displayed */ - -.navbar-brand { - height: auto; - width: auto; -} - -a.navbar-brand img { - height: auto; - width: auto; - max-height: 15vh; - max-width: 100%; + /* Change header hight to make the logo a bit larger */ + --pst-header-height: 6rem; + /* Make headings more bold */ + --pst-font-weight-heading: 600; } /* Contibuting landing page overview cards */ .contrib-card { - background: #fff; border-radius: 0; padding: 30px 10px 20px 10px; margin: 10px 0px; @@ -70,12 +42,12 @@ a.navbar-brand img { .contrib-card .sd-card-img-top { margin: 2px; height: 75px; + background: none !important; } .contrib-card .sd-card-title { - /* color: rgb(var(--pst-color-h1)) !important; */ + color: var(--pst-color-primary); font-size: var(--pst-font-size-h3); - /* font-weight: bold; */ padding: 1rem 0rem 0.5rem 0rem; } @@ -112,48 +84,3 @@ dl.cpp.enumerator { p.breathe-sectiondef-title { margin-top: 1rem; } - -/* Limit the max height of the sidebar navigation section. Because in our -custimized template, there is more content above the navigation, i.e. -larger logo: if we don't decrease the max-height, it will overlap with -the footer. -Details: min(15vh, 110px) for the logo size, 8rem for search box etc*/ - -@media (min-width:720px) { - @supports (position:-webkit-sticky) or (position:sticky) { - .bd-links { - max-height: calc(100vh - min(15vh, 110px) - 8rem) - } - } -} - -/* Styling to get the version dropdown and search box side-by-side on wide screens */ - -#version-search-wrapper { - width: inherit; - display: flex; - flex-wrap: wrap; - justify-content: left; - align-items: center; -} - -#version-button { - padding-left: 0.5rem; - padding-right: 1rem; -} - -#search-box { - flex: 1 0 12em; -} - -/* Fix table text wrapping in RTD theme, - * see https://rackerlabs.github.io/docs-rackspace/tools/rtd-tables.html - */ - -@media screen { - table.docutils td { - /* !important prevents the common CSS stylesheets from overriding - this as on RTD they are loaded after this stylesheet */ - white-space: normal !important; - } -} diff --git a/docs/source/_static/versions.json b/docs/source/_static/versions.json index f91b0a17e7774..8d9c5878c8213 100644 --- a/docs/source/_static/versions.json +++ b/docs/source/_static/versions.json @@ -1,62 +1,73 @@ [ { "name": "14.0 (dev)", - "version": "dev/" + "version": "dev/", + "url": "https://arrow.apache.org/docs/dev/" }, { "name": "13.0 (stable)", - "version": "" + "version": "", + "url": "https://arrow.apache.org/docs/", + "preferred": true }, { "name": "12.0", - "version": "12.0/" - }, - { - "name": "12.0", - "version": "12.0/" + "version": "12.0/", + "url": "https://arrow.apache.org/docs/12.0/" }, { "name": "11.0", - "version": "11.0/" + "version": "11.0/", + "url": "https://arrow.apache.org/docs/11.0/" }, { "name": "10.0", - "version": "10.0/" + "version": "10.0/", + "url": "https://arrow.apache.org/docs/10.0/" }, { "name": "9.0", - "version": "9.0/" + "version": "9.0/", + "url": "https://arrow.apache.org/docs/9.0/" }, { "name": "8.0", - "version": "8.0/" + "version": "8.0/", + "url": "https://arrow.apache.org/docs/8.0/" }, { "name": "7.0", - "version": "7.0/" + "version": "7.0/", + "url": "https://arrow.apache.org/docs/7.0/" }, { "name": "6.0", - "version": "6.0/" + "version": "6.0/", + "url": "https://arrow.apache.org/docs/6.0/" }, { "name": "5.0", - "version": "5.0/" + "version": "5.0/", + "url": "https://arrow.apache.org/docs/5.0/" }, { "name": "4.0", - "version": "4.0/" + "version": "4.0/", + "url": "https://arrow.apache.org/docs/4.0/" }, { "name": "3.0", - "version": "3.0/" + "version": "3.0/", + "url": "https://arrow.apache.org/docs/3.0/" }, { "name": "2.0", - "version": "2.0/" + "version": "2.0/", + "url": "https://arrow.apache.org/docs/2.0/" }, { "name": "1.0", - "version": "1.0/" + "version": "1.0/", + "url": "https://arrow.apache.org/docs/dev/" } ] diff --git a/docs/source/_static/versionwarning.js b/docs/source/_static/versionwarning.js index 601b93b75ddd8..e53c160ed98f7 100644 --- a/docs/source/_static/versionwarning.js +++ b/docs/source/_static/versionwarning.js @@ -17,6 +17,8 @@ (function() { // adapted 2022-11 from https://mne.tools/versionwarning.js + // Not used anymore for versions 14.0.0 and higher + // Kept for older docs versions (13.0.0 and lower) if (location.hostname == 'arrow.apache.org') { $.getJSON("https://arrow.apache.org/docs/_static/versions.json", function(data){ var latestStable = data[1].name.replace(" (stable)",""); diff --git a/docs/source/_templates/docs-sidebar.html b/docs/source/_templates/docs-sidebar.html deleted file mode 100644 index 26d42a82f1d5c..0000000000000 --- a/docs/source/_templates/docs-sidebar.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - -
- -{% include "version-switcher.html" %} - - - -
- - diff --git a/docs/source/_templates/layout.html b/docs/source/_templates/layout.html index ca39e8e5a8fae..956e0142c5062 100644 --- a/docs/source/_templates/layout.html +++ b/docs/source/_templates/layout.html @@ -22,13 +22,3 @@ {% endblock %} - -{# Silence the navbar #} -{% block docs_navbar %} -{% endblock %} - -{# Add version warnings #} -{% block footer %} - {{ super() }} - -{% endblock %} diff --git a/docs/source/_templates/version-switcher.html b/docs/source/_templates/version-switcher.html deleted file mode 100644 index 24a8c15ac0102..0000000000000 --- a/docs/source/_templates/version-switcher.html +++ /dev/null @@ -1,60 +0,0 @@ - - - diff --git a/docs/source/c_glib/index.rst b/docs/source/c_glib/index.rst index 56db23f2a2040..b10524eb2e8a5 100644 --- a/docs/source/c_glib/index.rst +++ b/docs/source/c_glib/index.rst @@ -15,6 +15,8 @@ .. specific language governing permissions and limitations .. under the License. +.. _c-glib: + C/GLib docs =========== diff --git a/docs/source/conf.py b/docs/source/conf.py index 23b7070c4a84e..e9e8969f55254 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -115,7 +115,6 @@ 'IPython.sphinxext.ipython_console_highlighting', 'IPython.sphinxext.ipython_directive', 'numpydoc', - "sphinxcontrib.jquery", 'sphinx_design', 'sphinx_copybutton', 'sphinx.ext.autodoc', @@ -288,16 +287,37 @@ # further. For a list of options available for each theme, see the # documentation. # + html_theme_options = { "show_toc_level": 2, "use_edit_page_button": True, + "logo": { + "image_light": "_static/arrow.png", + "image_dark": "_static/arrow-dark.png", + }, + "header_links_before_dropdown": 2, + "header_dropdown_text": "Language implementations", + "navbar_end": ["version-switcher", "theme-switcher", "navbar-icon-links"], + "icon_links": [ + { + "name": "GitHub", + "url": "https://github.com/apache/arrow", + "icon": "fa-brands fa-square-github", + }, + { + "name": "Twitter", + "url": "https://twitter.com/ApacheArrow", + "icon": "fa-brands fa-square-twitter", + }, + ], + "show_version_warning_banner": True, + "switcher": { + "json_url": "/docs/_static/versions.json", + "version_match": version, + }, } html_context = { - "switcher_json_url": "/docs/_static/versions.json", - "switcher_template_url": "https://arrow.apache.org/docs/{version}", - # for local testing - # "switcher_template_url": "http://0.0.0.0:8000/docs/{version}", "github_user": "apache", "github_repo": "arrow", "github_version": "main", @@ -319,7 +339,7 @@ # The name of an image file (relative to this directory) to place at the top # of the sidebar. # -html_logo = "_static/arrow.png" +# html_logo = "_static/arrow.png" # The name of an image file (relative to this directory) to use as a favicon of # the docs. This file should be a Windows icon file (.ico) being 16x16 or @@ -354,10 +374,9 @@ # Custom sidebar templates, maps document names to template names. # -html_sidebars = { +# html_sidebars = { # '**': ['sidebar-logo.html', 'sidebar-search-bs.html', 'sidebar-nav-bs.html'], - '**': ['docs-sidebar.html'], -} +# } # The base URL which points to the root of the HTML documentation, # used for canonical url diff --git a/docs/source/cpp/index.rst b/docs/source/cpp/index.rst index e06453e202979..6d4d4aaa8148c 100644 --- a/docs/source/cpp/index.rst +++ b/docs/source/cpp/index.rst @@ -15,6 +15,8 @@ .. specific language governing permissions and limitations .. under the License. +.. _cpp: + C++ Implementation ================== @@ -25,9 +27,9 @@ Welcome to the Apache Arrow C++ implementation documentation! :padding: 2 2 0 0 :class-container: sd-text-center - .. grid-item-card:: Basic understanding + .. grid-item-card:: Getting started :class-card: contrib-card - :shadow: md + :shadow: none Start here to gain a basic understanding of Arrow with an installation and linking guide, documentation of @@ -37,14 +39,14 @@ Welcome to the Apache Arrow C++ implementation documentation! .. button-link:: getting_started.html :click-parent: - :color: secondary + :color: primary :expand: - Getting started + To Getting started .. grid-item-card:: User Guide :class-card: contrib-card - :shadow: md + :shadow: none Explore more specific topics and underlying concepts of Arrow C++ @@ -53,19 +55,19 @@ Welcome to the Apache Arrow C++ implementation documentation! .. button-link:: user_guide.html :click-parent: - :color: secondary + :color: primary :expand: - User Guide + To the User Guide .. grid:: 2 :gutter: 4 :padding: 2 2 0 0 :class-container: sd-text-center - .. grid-item-card:: Examples of use + .. grid-item-card:: Examples :class-card: contrib-card - :shadow: md + :shadow: none Find the description and location of the examples using Arrow C++ library @@ -74,14 +76,14 @@ Welcome to the Apache Arrow C++ implementation documentation! .. button-link:: examples/index.html :click-parent: - :color: secondary + :color: primary :expand: - Examples + To the Examples - .. grid-item-card:: Reference documentation + .. grid-item-card:: API Reference :class-card: contrib-card - :shadow: md + :shadow: none Explore Arrow’s API reference documentation @@ -89,10 +91,32 @@ Welcome to the Apache Arrow C++ implementation documentation! .. button-link:: api.html :click-parent: - :color: secondary + :color: primary + :expand: + + To the API Reference + +.. grid:: 1 + :gutter: 4 + :padding: 2 2 0 0 + :class-container: sd-text-center + + .. grid-item-card:: Cookbook + :class-card: contrib-card + :shadow: none + + Collection of recipes which demonstrate how to + solve many common tasks that users might need + to perform when working with arrow data + + +++ + + .. button-link:: https://arrow.apache.org/cookbook/cpp/ + :click-parent: + :color: primary :expand: - API Reference + To the Cookbook .. toctree:: :maxdepth: 2 @@ -102,3 +126,4 @@ Welcome to the Apache Arrow C++ implementation documentation! user_guide Examples api + C++ cookbook diff --git a/docs/source/developers/continuous_integration/index.rst b/docs/source/developers/continuous_integration/index.rst index 6e8e26981c549..f988b5ab69d50 100644 --- a/docs/source/developers/continuous_integration/index.rst +++ b/docs/source/developers/continuous_integration/index.rst @@ -15,6 +15,7 @@ .. specific language governing permissions and limitations .. under the License. +.. _continuous_integration: ********************** Continuous Integration diff --git a/docs/source/developers/continuous_integration/overview.rst b/docs/source/developers/continuous_integration/overview.rst index 1d82e845a3360..3e155bf6001e9 100644 --- a/docs/source/developers/continuous_integration/overview.rst +++ b/docs/source/developers/continuous_integration/overview.rst @@ -20,7 +20,7 @@ Continuous Integration ====================== -Continuous Integration for Arrow is fairly complex as it needs to run across different combinations of package managers, compilers, versions of multiple sofware libraries, operating systems, and other potential sources of variation. In this article, we will give an overview of its main components and the relevant files and directories. +Continuous Integration for Arrow is fairly complex as it needs to run across different combinations of package managers, compilers, versions of multiple software libraries, operating systems, and other potential sources of variation. In this article, we will give an overview of its main components and the relevant files and directories. Some files central to Arrow CI are: diff --git a/docs/source/developers/contributing.rst b/docs/source/developers/contributing.rst deleted file mode 100644 index 6dc2a4e0147d6..0000000000000 --- a/docs/source/developers/contributing.rst +++ /dev/null @@ -1,190 +0,0 @@ -.. 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. - -.. highlight:: console - -.. _contributing: - -**************************** -Contributing to Apache Arrow -**************************** - -**Thanks for your interest in the Apache Arrow project.** - -Arrow is a large project and may seem overwhelming when you're -first getting involved. Contributing code is great, but that's -probably not the first place to start. There are lots of ways to -make valuable contributions to the project and community. - -This page provides some orientation for how to get involved. It also offers -some recommendations on how to get the best results when engaging with the -community. - -Code of Conduct -=============== - -All participation in the Apache Arrow project is governed by the ASF's -`Code of Conduct `_. - -.. grid:: 2 - :gutter: 4 - :padding: 2 2 0 0 - :class-container: sd-text-center - - .. grid-item-card:: Community - :img-top: ./images/users-solid.svg - :class-card: contrib-card - :shadow: md - - A good first step to getting involved in the Arrow project is to join - the mailing lists and participate in discussions where you can. - - +++ - - .. button-link:: https://arrow.apache.org/community/ - :click-parent: - :color: secondary - :expand: - - Apache Arrow Community - - .. grid-item-card:: Bug reports - :img-top: ./images/bug-solid.svg - :class-card: contrib-card - :shadow: md - - Alerting us to unexpected behavior and missing features, even - if you can't solve the problems yourself, help us understand - and prioritize work to improve the libraries. - - +++ - - .. button-ref:: bug-reports - :ref-type: ref - :click-parent: - :color: secondary - :expand: - - Bugs and Features - -.. dropdown:: Communicating through the mailing lists - :animate: fade-in-slide-down - :class-title: sd-fs-5 - :class-container: sd-shadow-md - - Projects in The Apache Software Foundation ("the ASF") use public, archived - mailing lists to create a public record of each project's development - activities and decision-making process. - - While lacking the immediacy of chat or other forms of communication, - the mailing lists give participants the opportunity to slow down and be - thoughtful in their responses, and they help developers who are spread across - many timezones to participate more equally. - - Read more on the `Apache Arrow Community `_ - page. - -.. dropdown:: Improve documentation - :animate: fade-in-slide-down - :class-title: sd-fs-5 - :class-container: sd-shadow-md - - A great way to contribute to the project is to improve documentation. If you - found some docs to be incomplete or inaccurate, share your hard-earned knowledge - with the rest of the community. - - Documentation improvements are also a great way to gain some experience with - our submission and review process, discussed below, without requiring a lot - of local development environment setup. In fact, many documentation-only changes - can be made directly in the GitHub web interface by clicking the "edit" button. - This will handle making a fork and a pull request for you. - - * :ref:`documentation` - * :ref:`building-docs` - -.. grid:: 2 - :gutter: 4 - :padding: 2 2 0 0 - :class-container: sd-text-center - - .. grid-item-card:: New Contributors - :img-top: ./images/book-open-solid.svg - :class-card: contrib-card - :shadow: md - - First time contributing? - - The New Contributor's Guide provides necessary information for - contributing to the Apache Arrow project. - - +++ - - .. button-ref:: guide-introduction - :ref-type: ref - :click-parent: - :color: secondary - :expand: - - New Contributor's guide - - .. grid-item-card:: Overview - :img-top: ./images/code-solid.svg - :class-card: contrib-card - :shadow: md - - A short overview of the contributing process we follow - and some additional information you might need if you are not - new to the contributing process in general. - +++ - - .. button-ref:: contrib-overview - :ref-type: ref - :click-parent: - :color: secondary - :expand: - - Contributing overview - -Language specific -================= - -Connection to the specific language development pages: - -.. tab-set:: - - .. tab-item:: C++ - - * :ref:`cpp-development` - * :ref:`C++ Development Guidelines ` - * :ref:`building-arrow-cpp` - - .. tab-item:: Java - - * :doc:`java/index` - - .. tab-item:: Python - - * :ref:`python-development` - - .. tab-item:: R - - * `Arrow R Package: Developer environment setup `_ - * `Arrow R Package: Common developer workflow tasks `_ - - .. tab-item:: Ruby - - * `Red Arrow - Apache Arrow Ruby `_ diff --git a/docs/source/developers/images/book-open-solid.svg b/docs/source/developers/images/book-open-solid.svg index cbc8ed27256ca..9586e249be060 100644 --- a/docs/source/developers/images/book-open-solid.svg +++ b/docs/source/developers/images/book-open-solid.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/source/developers/images/bug-solid.svg b/docs/source/developers/images/bug-solid.svg index f842cb240544f..49cc04a1f0f6e 100644 --- a/docs/source/developers/images/bug-solid.svg +++ b/docs/source/developers/images/bug-solid.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/source/developers/images/code-solid.svg b/docs/source/developers/images/code-solid.svg index 725f767148b2c..4bbd567528ef8 100644 --- a/docs/source/developers/images/code-solid.svg +++ b/docs/source/developers/images/code-solid.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/source/developers/images/users-solid.svg b/docs/source/developers/images/users-solid.svg index a04d7fe2fd4a0..4bdf638a70f89 100644 --- a/docs/source/developers/images/users-solid.svg +++ b/docs/source/developers/images/users-solid.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/source/developers/index.rst b/docs/source/developers/index.rst index f6a15a6c5452e..c2f10c9e95c47 100644 --- a/docs/source/developers/index.rst +++ b/docs/source/developers/index.rst @@ -15,12 +15,206 @@ .. specific language governing permissions and limitations .. under the License. +.. highlight:: console + +.. _developers: + +Development +=========== + +Connection to the specific language development pages: + +.. tab-set:: + + .. tab-item:: C++ + + * :ref:`cpp-development` + * :ref:`C++ Development Guidelines ` + * :ref:`building-arrow-cpp` + + .. tab-item:: Java + + * :doc:`java/index` + + .. tab-item:: Python + + * :ref:`python-development` + + .. tab-item:: R + + * `Arrow R Package: Developer environment setup `_ + * `Arrow R Package: Common developer workflow tasks `_ + + .. tab-item:: Ruby + + * `Red Arrow - Apache Arrow Ruby `_ + +.. _contributing: + +Contributing to Apache Arrow +============================ + +**Thanks for your interest in the Apache Arrow project.** + +Arrow is a large project and may seem overwhelming when you're +first getting involved. Contributing code is great, but that's +probably not the first place to start. There are lots of ways to +make valuable contributions to the project and community. + +This page provides some orientation for how to get involved. It also offers +some recommendations on how to get the best results when engaging with the +community. + +Code of Conduct +--------------- + +All participation in the Apache Arrow project is governed by the ASF's +`Code of Conduct `_. + +.. grid:: 2 + :gutter: 4 + :padding: 2 2 0 0 + :class-container: sd-text-center + + .. grid-item-card:: Apache Arrow Community + :img-top: ./images/users-solid.svg + :class-card: contrib-card + :shadow: none + + A good first step to getting involved in the Arrow project is to join + the mailing lists and participate in discussions where you can. + + +++ + + .. button-link:: https://arrow.apache.org/community/ + :click-parent: + :color: primary + :expand: + + To Apache Arrow Community + + .. grid-item-card:: Bug reports and feature requests + :img-top: ./images/bug-solid.svg + :class-card: contrib-card + :shadow: none + + Alerting us to unexpected behavior and missing features, even + if you can't solve the problems yourself, help us understand + and prioritize work to improve the libraries. + + +++ + + .. button-ref:: bug-reports + :ref-type: ref + :click-parent: + :color: primary + :expand: + + To Bug reports and feature requests + +.. dropdown:: Communicating through the mailing lists + :animate: fade-in-slide-down + :class-title: sd-fs-5 + :class-container: sd-shadow-none + + Projects in The Apache Software Foundation ("the ASF") use public, archived + mailing lists to create a public record of each project's development + activities and decision-making process. + + While lacking the immediacy of chat or other forms of communication, + the mailing lists give participants the opportunity to slow down and be + thoughtful in their responses, and they help developers who are spread across + many timezones to participate more equally. + + Read more on the `Apache Arrow Community `_ + page. + +.. dropdown:: Improve documentation + :animate: fade-in-slide-down + :class-title: sd-fs-5 + + A great way to contribute to the project is to improve documentation. If you + found some docs to be incomplete or inaccurate, share your hard-earned knowledge + with the rest of the community. + + Documentation improvements are also a great way to gain some experience with + our submission and review process, discussed below, without requiring a lot + of local development environment setup. In fact, many documentation-only changes + can be made directly in the GitHub web interface by clicking the "edit" button. + This will handle making a fork and a pull request for you. + + * :ref:`documentation` + * :ref:`building-docs` + +.. grid:: 2 + :gutter: 4 + :padding: 2 2 0 0 + :class-container: sd-text-center + + .. grid-item-card:: New Contributor's guide + :img-top: ./images/book-open-solid.svg + :class-card: contrib-card + + First time contributing? + + The New Contributor's Guide provides necessary information for + contributing to the Apache Arrow project. + + +++ + + .. button-ref:: guide-introduction + :ref-type: ref + :click-parent: + :color: primary + :expand: + + To the New Contributor's guide + + .. grid-item-card:: Contributing Overview + :img-top: ./images/code-solid.svg + :class-card: contrib-card + + A short overview of the contributing process we follow + and some additional information you might need if you are not + new to the contributing process in general. + +++ + + .. button-ref:: contrib-overview + :ref-type: ref + :click-parent: + :color: primary + :expand: + + To Contributing overview + +.. dropdown:: Continuous Integration + :animate: fade-in-slide-down + :class-title: sd-fs-5 + :class-container: sd-shadow-none + + Continuous Integration needs to run across different combinations of package managers, compilers, versions of multiple + software libraries, operating systems, and other potential sources of variation. + + Read more on the :ref:`continuous_integration` page. + +.. dropdown:: Benchmarks + :animate: fade-in-slide-down + :class-title: sd-fs-5 + :class-container: sd-shadow-none + + How to use the benchmark suite can be found on the :ref:`benchmarks` page. + +.. dropdown:: Release Guide + :animate: fade-in-slide-down + :class-title: sd-fs-5 + :class-container: sd-shadow-none + + To learn about the detailed information on the steps followed to perform a release, see :ref:`release`. + .. toctree:: :maxdepth: 2 - :caption: Development :hidden: - contributing bug_reports guide/index overview diff --git a/docs/source/developers/overview.rst b/docs/source/developers/overview.rst index 272f3dbd98074..c7bc4273313bc 100644 --- a/docs/source/developers/overview.rst +++ b/docs/source/developers/overview.rst @@ -45,7 +45,7 @@ checklist for using ``git``: .. dropdown:: How to squash local commits? :animate: fade-in-slide-down - :class-container: sd-shadow-md + :class-container: sd-shadow-none Abort the rebase with: @@ -78,7 +78,7 @@ checklist for using ``git``: .. dropdown:: Setting rebase to be default :animate: fade-in-slide-down - :class-container: sd-shadow-md + :class-container: sd-shadow-none If you set the following in your repo's ``.git/config``, the ``--rebase`` option can be omitted from the ``git pull`` command, as it is implied by default. @@ -136,7 +136,7 @@ will merge the pull request. This is done with a .. dropdown:: Details on squash merge :animate: fade-in-slide-down - :class-container: sd-shadow-md + :class-container: sd-shadow-none A pull request is merged with a squash merge so that all of your commits will be registered as a single commit to the main branch; this simplifies the diff --git a/docs/source/developers/release.rst b/docs/source/developers/release.rst index 066400b33ffb5..6924c2d714e8b 100644 --- a/docs/source/developers/release.rst +++ b/docs/source/developers/release.rst @@ -15,6 +15,8 @@ .. specific language governing permissions and limitations .. under the License. +.. _release: + ======================== Release Management Guide ======================== diff --git a/docs/source/format/index.rst b/docs/source/format/index.rst index 1771b36d76128..ae2baf128b472 100644 --- a/docs/source/format/index.rst +++ b/docs/source/format/index.rst @@ -15,10 +15,13 @@ .. specific language governing permissions and limitations .. under the License. +.. _format: + +Specifications and Protocols +============================ + .. toctree:: :maxdepth: 2 - :caption: Specifications and Protocols - :hidden: Versioning Columnar diff --git a/docs/source/index.rst b/docs/source/index.rst index b348d3dab22b7..e8cdf50c5b1ec 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -15,6 +15,8 @@ .. specific language governing permissions and limitations .. under the License. +:html_theme.sidebar_secondary.remove: + Apache Arrow ============ @@ -35,11 +37,71 @@ such topics as: **To learn how to use Arrow refer to the documentation specific to your target environment.** +.. grid:: 2 + :gutter: 4 + :padding: 2 2 0 0 + :class-container: sd-text-center + + .. grid-item-card:: Specifications and Protocols + :class-card: contrib-card + :shadow: none + + Read about the Apache Arrow format + specifications and Protocols. + + +++ + + .. button-ref:: format + :ref-type: ref + :click-parent: + :color: primary + :expand: + + To the Specifications and Protocols + + .. grid-item-card:: Development + :class-card: contrib-card + :shadow: none + + Find the documentation on the topic of + contributions, reviews, building of the libraries + from source, building of the documentation, + continuous integration, benchmarks and the + release process. + + +++ + + .. button-ref:: developers + :ref-type: ref + :click-parent: + :color: primary + :expand: + + To the Development + +.. _toc.columnar: + +.. toctree:: + :maxdepth: 2 + :hidden: + + format/index + +.. _toc.development: + +.. toctree:: + :maxdepth: 2 + :hidden: + + developers/index + +Implementations +--------------- + .. _toc.usage: .. toctree:: :maxdepth: 1 - :caption: Supported Environments C/GLib C++ @@ -55,52 +117,15 @@ target environment.** Rust status +Examples +-------- + .. _toc.cookbook: .. toctree:: :maxdepth: 1 - :caption: Cookbooks - - C++ - Java - Python - R -.. _toc.columnar: - -.. toctree:: - :maxdepth: 2 - :caption: Specifications and Protocols - - format/Versioning - format/Columnar - format/CanonicalExtensions - format/Flight - format/FlightSql - format/Integration - format/CDataInterface - format/CStreamInterface - format/CDeviceDataInterface - format/ADBC - format/Other - format/Changing - format/Glossary - -.. _toc.development: - -.. toctree:: - :maxdepth: 2 - :caption: Development - - developers/contributing - developers/bug_reports - developers/guide/index - developers/overview - developers/reviewing - developers/cpp/index - developers/java/index - developers/python - developers/continuous_integration/index - developers/benchmarks - developers/documentation - developers/release + C++ cookbook + Java cookbook + Python cookbook + R cookbook diff --git a/docs/source/java/index.rst b/docs/source/java/index.rst index 9b555e297b0f9..cf93b0e897832 100644 --- a/docs/source/java/index.rst +++ b/docs/source/java/index.rst @@ -15,6 +15,8 @@ .. specific language governing permissions and limitations .. under the License. +.. _java: + Java Implementation =================== @@ -41,3 +43,4 @@ on the Arrow format and other language bindings see the :doc:`parent documentati cdata jdbc Reference (javadoc) + Java cookbook diff --git a/docs/source/js/index.rst b/docs/source/js/index.rst index 77813c1372dfe..2ab205a08b850 100644 --- a/docs/source/js/index.rst +++ b/docs/source/js/index.rst @@ -15,6 +15,8 @@ .. specific language governing permissions and limitations .. under the License. +.. _js: + JavaScript docs =============== diff --git a/docs/source/python/index.rst b/docs/source/python/index.rst index b80cbc7de594e..6a3de3d42b149 100644 --- a/docs/source/python/index.rst +++ b/docs/source/python/index.rst @@ -15,8 +15,13 @@ .. specific language governing permissions and limitations .. under the License. +.. _python: + +Python +====== + PyArrow - Apache Arrow Python bindings -====================================== +-------------------------------------- This is the documentation of the Python API of Apache Arrow. @@ -62,3 +67,4 @@ files into Arrow structures. api getting_involved benchmarks + Python cookbook diff --git a/docs/source/r/index.rst b/docs/source/r/index.rst index b799544bb6bb3..8ccbec132ad3d 100644 --- a/docs/source/r/index.rst +++ b/docs/source/r/index.rst @@ -15,6 +15,8 @@ .. specific language governing permissions and limitations .. under the License. +.. _r: + R docs ====== From 286487010b43da384dbeec941d2b49f66638a90a Mon Sep 17 00:00:00 2001 From: Danyaal Khan Date: Wed, 27 Sep 2023 16:42:22 +0100 Subject: [PATCH 06/56] GH-37377: [C#] Throw OverflowException on overflow in TimestampArray.ConvertTo() (#37388) Throw `OverflowException` on overflow in `TimestampArray.ConvertTo()` when `DataType.Unit` is `Nanosecond` and `ticks` is large, instead of silently overflowing and returning the wrong value. * Closes: #37377 Authored-by: Danyaal Khan Signed-off-by: Weston Pace --- csharp/src/Apache.Arrow/Arrays/TimestampArray.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/src/Apache.Arrow/Arrays/TimestampArray.cs b/csharp/src/Apache.Arrow/Arrays/TimestampArray.cs index 0269768f490bb..0dc5726d01734 100644 --- a/csharp/src/Apache.Arrow/Arrays/TimestampArray.cs +++ b/csharp/src/Apache.Arrow/Arrays/TimestampArray.cs @@ -76,7 +76,7 @@ protected override long ConvertTo(DateTimeOffset value) switch (DataType.Unit) { case TimeUnit.Nanosecond: - return ticks * 100; + return checked(ticks * 100); case TimeUnit.Microsecond: return ticks / 10; case TimeUnit.Millisecond: From aca1d3eeed3775c2f02e9f5d59d62478267950b1 Mon Sep 17 00:00:00 2001 From: ismail simsek Date: Wed, 27 Sep 2023 17:51:05 +0200 Subject: [PATCH 07/56] GH-35770: [Go][Documentation] Update TimestampType zero value as seconds in comment (#37905) ### Rationale for this change To clear the confusion around the zero value of `TimestampType` ### What changes are included in this PR? Just a comment change `nanosecond -> second` ### Are these changes tested? No need to test ### Are there any user-facing changes? No Closes: https://github.com/apache/arrow/issues/35770 * Closes: #35770 Authored-by: ismail simsek Signed-off-by: Matt Topol --- go/arrow/datatype_fixedwidth.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/arrow/datatype_fixedwidth.go b/go/arrow/datatype_fixedwidth.go index 7f62becdc2884..fc0b3aea56e70 100644 --- a/go/arrow/datatype_fixedwidth.go +++ b/go/arrow/datatype_fixedwidth.go @@ -347,7 +347,7 @@ type TemporalWithUnit interface { } // TimestampType is encoded as a 64-bit signed integer since the UNIX epoch (2017-01-01T00:00:00Z). -// The zero-value is a nanosecond and time zone neutral. Time zone neutral can be +// The zero-value is a second and time zone neutral. Time zone neutral can be // considered UTC without having "UTC" as a time zone. type TimestampType struct { Unit TimeUnit From c9674bcc16411d7ecfd3b5587f544758b9fc7062 Mon Sep 17 00:00:00 2001 From: h-vetinari Date: Thu, 28 Sep 2023 22:18:07 +1100 Subject: [PATCH 08/56] GH-37621: [Packaging][Conda] Sync conda recipes with feedstocks (#37624) Syncing after the release of 13.0.0 + a couple of migrations (state as of https://github.com/conda-forge/arrow-cpp-feedstock/pull/1168 & https://github.com/conda-forge/r-arrow-feedstock/pull/68) Relevant updates: * we're not building twice for different protobuf versions anymore * new abseil version (fixes #36908) * we've finally upgraded the aws-sdk to 1.11 * the default R versions (on unix) are now 4.2 & 4.3. Also some further hardening of the activation scripts & clean-ups for dependencies & test skips. * Closes: #37621 Lead-authored-by: H. Vetinari Co-authored-by: h-vetinari Signed-off-by: Joris Van den Bossche --- .../linux_64_cuda_compiler_version11.2.yaml | 20 +++--- .../linux_64_cuda_compiler_versionNone.yaml | 20 +++--- ...nux_aarch64_cuda_compiler_version11.2.yaml | 20 +++--- ...nux_aarch64_cuda_compiler_versionNone.yaml | 20 +++--- ...nux_ppc64le_cuda_compiler_version11.2.yaml | 20 +++--- ...nux_ppc64le_cuda_compiler_versionNone.yaml | 20 +++--- .../conda-recipes/.ci_support/osx_64_.yaml | 22 +++---- .../conda-recipes/.ci_support/osx_arm64_.yaml | 20 +++--- ...r_base4.1.yaml => linux_64_r_base4.3.yaml} | 2 +- ...e4.1.yaml => linux_aarch64_r_base4.3.yaml} | 2 +- ...4_r_base4.1.yaml => osx_64_r_base4.3.yaml} | 2 +- ..._base4.1.yaml => osx_arm64_r_base4.3.yaml} | 2 +- .../win_64_cuda_compiler_version11.2.yaml | 22 +++---- .../win_64_cuda_compiler_versionNone.yaml | 22 +++---- dev/tasks/conda-recipes/arrow-cpp/activate.sh | 17 +++-- .../conda-recipes/arrow-cpp/build-arrow.sh | 4 +- .../conda-recipes/arrow-cpp/build-pyarrow.sh | 4 ++ dev/tasks/conda-recipes/arrow-cpp/meta.yaml | 65 ++++++++----------- dev/tasks/tasks.yml | 24 +++---- 19 files changed, 151 insertions(+), 177 deletions(-) rename dev/tasks/conda-recipes/.ci_support/r/{linux_64_r_base4.1.yaml => linux_64_r_base4.3.yaml} (98%) rename dev/tasks/conda-recipes/.ci_support/r/{linux_aarch64_r_base4.1.yaml => linux_aarch64_r_base4.3.yaml} (98%) rename dev/tasks/conda-recipes/.ci_support/r/{osx_64_r_base4.1.yaml => osx_64_r_base4.3.yaml} (98%) rename dev/tasks/conda-recipes/.ci_support/r/{osx_arm64_r_base4.1.yaml => osx_arm64_r_base4.3.yaml} (98%) diff --git a/dev/tasks/conda-recipes/.ci_support/linux_64_cuda_compiler_version11.2.yaml b/dev/tasks/conda-recipes/.ci_support/linux_64_cuda_compiler_version11.2.yaml index 1cdcec199e7ba..042e2364d1c49 100644 --- a/dev/tasks/conda-recipes/.ci_support/linux_64_cuda_compiler_version11.2.yaml +++ b/dev/tasks/conda-recipes/.ci_support/linux_64_cuda_compiler_version11.2.yaml @@ -1,7 +1,7 @@ aws_crt_cpp: -- 0.20.3 +- 0.23.1 aws_sdk_cpp: -- 1.10.57 +- 1.11.156 bzip2: - '1' c_compiler: @@ -33,20 +33,18 @@ glog: google_cloud_cpp: - '2.12' libabseil: -- '20230125' +- '20230802' libgrpc: -- '1.54' -- '1.56' +- '1.57' libprotobuf: -- '3.21' -- 4.23.3 +- 4.23.4 lz4_c: - 1.9.3 numpy: -- '1.21' +- '1.22' - '1.23' -- '1.21' -- '1.21' +- '1.22' +- '1.22' openssl: - '3' orc: @@ -67,7 +65,7 @@ snappy: target_platform: - linux-64 thrift_cpp: -- 0.18.1 +- 0.19.0 ucx: - 1.14.0 zip_keys: diff --git a/dev/tasks/conda-recipes/.ci_support/linux_64_cuda_compiler_versionNone.yaml b/dev/tasks/conda-recipes/.ci_support/linux_64_cuda_compiler_versionNone.yaml index 5be5b58a73932..9885e6db38cd7 100644 --- a/dev/tasks/conda-recipes/.ci_support/linux_64_cuda_compiler_versionNone.yaml +++ b/dev/tasks/conda-recipes/.ci_support/linux_64_cuda_compiler_versionNone.yaml @@ -1,7 +1,7 @@ aws_crt_cpp: -- 0.20.3 +- 0.23.1 aws_sdk_cpp: -- 1.10.57 +- 1.11.156 bzip2: - '1' c_compiler: @@ -33,20 +33,18 @@ glog: google_cloud_cpp: - '2.12' libabseil: -- '20230125' +- '20230802' libgrpc: -- '1.54' -- '1.56' +- '1.57' libprotobuf: -- '3.21' -- 4.23.3 +- 4.23.4 lz4_c: - 1.9.3 numpy: -- '1.21' +- '1.22' - '1.23' -- '1.21' -- '1.21' +- '1.22' +- '1.22' openssl: - '3' orc: @@ -67,7 +65,7 @@ snappy: target_platform: - linux-64 thrift_cpp: -- 0.18.1 +- 0.19.0 ucx: - 1.14.0 zip_keys: diff --git a/dev/tasks/conda-recipes/.ci_support/linux_aarch64_cuda_compiler_version11.2.yaml b/dev/tasks/conda-recipes/.ci_support/linux_aarch64_cuda_compiler_version11.2.yaml index 1677b03564c08..788b584504ec4 100644 --- a/dev/tasks/conda-recipes/.ci_support/linux_aarch64_cuda_compiler_version11.2.yaml +++ b/dev/tasks/conda-recipes/.ci_support/linux_aarch64_cuda_compiler_version11.2.yaml @@ -1,9 +1,9 @@ BUILD: - aarch64-conda_cos7-linux-gnu aws_crt_cpp: -- 0.20.3 +- 0.23.1 aws_sdk_cpp: -- 1.10.57 +- 1.11.156 bzip2: - '1' c_compiler: @@ -37,20 +37,18 @@ glog: google_cloud_cpp: - '2.12' libabseil: -- '20230125' +- '20230802' libgrpc: -- '1.54' -- '1.56' +- '1.57' libprotobuf: -- '3.21' -- 4.23.3 +- 4.23.4 lz4_c: - 1.9.3 numpy: -- '1.21' +- '1.22' - '1.23' -- '1.21' -- '1.21' +- '1.22' +- '1.22' openssl: - '3' orc: @@ -71,7 +69,7 @@ snappy: target_platform: - linux-aarch64 thrift_cpp: -- 0.18.1 +- 0.19.0 ucx: - 1.14.0 zip_keys: diff --git a/dev/tasks/conda-recipes/.ci_support/linux_aarch64_cuda_compiler_versionNone.yaml b/dev/tasks/conda-recipes/.ci_support/linux_aarch64_cuda_compiler_versionNone.yaml index 88fdf1254e661..a1e4b8571abaf 100644 --- a/dev/tasks/conda-recipes/.ci_support/linux_aarch64_cuda_compiler_versionNone.yaml +++ b/dev/tasks/conda-recipes/.ci_support/linux_aarch64_cuda_compiler_versionNone.yaml @@ -1,9 +1,9 @@ BUILD: - aarch64-conda_cos7-linux-gnu aws_crt_cpp: -- 0.20.3 +- 0.23.1 aws_sdk_cpp: -- 1.10.57 +- 1.11.156 bzip2: - '1' c_compiler: @@ -37,20 +37,18 @@ glog: google_cloud_cpp: - '2.12' libabseil: -- '20230125' +- '20230802' libgrpc: -- '1.54' -- '1.56' +- '1.57' libprotobuf: -- '3.21' -- 4.23.3 +- 4.23.4 lz4_c: - 1.9.3 numpy: -- '1.21' +- '1.22' - '1.23' -- '1.21' -- '1.21' +- '1.22' +- '1.22' openssl: - '3' orc: @@ -71,7 +69,7 @@ snappy: target_platform: - linux-aarch64 thrift_cpp: -- 0.18.1 +- 0.19.0 ucx: - 1.14.0 zip_keys: diff --git a/dev/tasks/conda-recipes/.ci_support/linux_ppc64le_cuda_compiler_version11.2.yaml b/dev/tasks/conda-recipes/.ci_support/linux_ppc64le_cuda_compiler_version11.2.yaml index 3585db7b99baa..e21c4cbe853f8 100644 --- a/dev/tasks/conda-recipes/.ci_support/linux_ppc64le_cuda_compiler_version11.2.yaml +++ b/dev/tasks/conda-recipes/.ci_support/linux_ppc64le_cuda_compiler_version11.2.yaml @@ -1,7 +1,7 @@ aws_crt_cpp: -- 0.20.3 +- 0.23.1 aws_sdk_cpp: -- 1.10.57 +- 1.11.156 bzip2: - '1' c_compiler: @@ -33,20 +33,18 @@ glog: google_cloud_cpp: - '2.12' libabseil: -- '20230125' +- '20230802' libgrpc: -- '1.54' -- '1.56' +- '1.57' libprotobuf: -- '3.21' -- 4.23.3 +- 4.23.4 lz4_c: - 1.9.3 numpy: -- '1.21' +- '1.22' - '1.23' -- '1.21' -- '1.21' +- '1.22' +- '1.22' openssl: - '3' orc: @@ -67,7 +65,7 @@ snappy: target_platform: - linux-ppc64le thrift_cpp: -- 0.18.1 +- 0.19.0 ucx: - 1.14.0 zip_keys: diff --git a/dev/tasks/conda-recipes/.ci_support/linux_ppc64le_cuda_compiler_versionNone.yaml b/dev/tasks/conda-recipes/.ci_support/linux_ppc64le_cuda_compiler_versionNone.yaml index c13a522254286..89f1049ebdd84 100644 --- a/dev/tasks/conda-recipes/.ci_support/linux_ppc64le_cuda_compiler_versionNone.yaml +++ b/dev/tasks/conda-recipes/.ci_support/linux_ppc64le_cuda_compiler_versionNone.yaml @@ -1,7 +1,7 @@ aws_crt_cpp: -- 0.20.3 +- 0.23.1 aws_sdk_cpp: -- 1.10.57 +- 1.11.156 bzip2: - '1' c_compiler: @@ -33,20 +33,18 @@ glog: google_cloud_cpp: - '2.12' libabseil: -- '20230125' +- '20230802' libgrpc: -- '1.54' -- '1.56' +- '1.57' libprotobuf: -- '3.21' -- 4.23.3 +- 4.23.4 lz4_c: - 1.9.3 numpy: -- '1.21' +- '1.22' - '1.23' -- '1.21' -- '1.21' +- '1.22' +- '1.22' openssl: - '3' orc: @@ -67,7 +65,7 @@ snappy: target_platform: - linux-ppc64le thrift_cpp: -- 0.18.1 +- 0.19.0 ucx: - 1.14.0 zip_keys: diff --git a/dev/tasks/conda-recipes/.ci_support/osx_64_.yaml b/dev/tasks/conda-recipes/.ci_support/osx_64_.yaml index dd4a230760ef2..2a5f8c5b36bd3 100644 --- a/dev/tasks/conda-recipes/.ci_support/osx_64_.yaml +++ b/dev/tasks/conda-recipes/.ci_support/osx_64_.yaml @@ -1,9 +1,9 @@ MACOSX_DEPLOYMENT_TARGET: -- '10.9' +- '10.13' aws_crt_cpp: -- 0.20.3 +- 0.23.1 aws_sdk_cpp: -- 1.10.57 +- 1.11.156 bzip2: - '1' c_compiler: @@ -27,22 +27,20 @@ glog: google_cloud_cpp: - '2.12' libabseil: -- '20230125' +- '20230802' libgrpc: -- '1.54' -- '1.56' +- '1.57' libprotobuf: -- '3.21' -- 4.23.3 +- 4.23.4 lz4_c: - 1.9.3 macos_machine: - x86_64-apple-darwin13.4.0 numpy: -- '1.21' +- '1.22' - '1.23' -- '1.21' -- '1.21' +- '1.22' +- '1.22' openssl: - '3' orc: @@ -63,7 +61,7 @@ snappy: target_platform: - osx-64 thrift_cpp: -- 0.18.1 +- 0.19.0 zip_keys: - - c_compiler_version - cxx_compiler_version diff --git a/dev/tasks/conda-recipes/.ci_support/osx_arm64_.yaml b/dev/tasks/conda-recipes/.ci_support/osx_arm64_.yaml index 6a6713a54fe86..211b71226cae8 100644 --- a/dev/tasks/conda-recipes/.ci_support/osx_arm64_.yaml +++ b/dev/tasks/conda-recipes/.ci_support/osx_arm64_.yaml @@ -1,9 +1,9 @@ MACOSX_DEPLOYMENT_TARGET: - '11.0' aws_crt_cpp: -- 0.20.3 +- 0.23.1 aws_sdk_cpp: -- 1.10.57 +- 1.11.156 bzip2: - '1' c_compiler: @@ -27,22 +27,20 @@ glog: google_cloud_cpp: - '2.12' libabseil: -- '20230125' +- '20230802' libgrpc: -- '1.54' -- '1.56' +- '1.57' libprotobuf: -- '3.21' -- 4.23.3 +- 4.23.4 lz4_c: - 1.9.3 macos_machine: - arm64-apple-darwin20.0.0 numpy: -- '1.21' +- '1.22' - '1.23' -- '1.21' -- '1.21' +- '1.22' +- '1.22' openssl: - '3' orc: @@ -63,7 +61,7 @@ snappy: target_platform: - osx-arm64 thrift_cpp: -- 0.18.1 +- 0.19.0 zip_keys: - - c_compiler_version - cxx_compiler_version diff --git a/dev/tasks/conda-recipes/.ci_support/r/linux_64_r_base4.1.yaml b/dev/tasks/conda-recipes/.ci_support/r/linux_64_r_base4.3.yaml similarity index 98% rename from dev/tasks/conda-recipes/.ci_support/r/linux_64_r_base4.1.yaml rename to dev/tasks/conda-recipes/.ci_support/r/linux_64_r_base4.3.yaml index e63767cbe9771..a4d06c9f20cdd 100644 --- a/dev/tasks/conda-recipes/.ci_support/r/linux_64_r_base4.1.yaml +++ b/dev/tasks/conda-recipes/.ci_support/r/linux_64_r_base4.3.yaml @@ -19,7 +19,7 @@ pin_run_as_build: min_pin: x.x max_pin: x.x r_base: -- '4.1' +- '4.3' target_platform: - linux-64 zip_keys: diff --git a/dev/tasks/conda-recipes/.ci_support/r/linux_aarch64_r_base4.1.yaml b/dev/tasks/conda-recipes/.ci_support/r/linux_aarch64_r_base4.3.yaml similarity index 98% rename from dev/tasks/conda-recipes/.ci_support/r/linux_aarch64_r_base4.1.yaml rename to dev/tasks/conda-recipes/.ci_support/r/linux_aarch64_r_base4.3.yaml index 2b80b020fdc0b..028b190bb1ef5 100644 --- a/dev/tasks/conda-recipes/.ci_support/r/linux_aarch64_r_base4.1.yaml +++ b/dev/tasks/conda-recipes/.ci_support/r/linux_aarch64_r_base4.3.yaml @@ -23,7 +23,7 @@ pin_run_as_build: min_pin: x.x max_pin: x.x r_base: -- '4.1' +- '4.3' target_platform: - linux-aarch64 zip_keys: diff --git a/dev/tasks/conda-recipes/.ci_support/r/osx_64_r_base4.1.yaml b/dev/tasks/conda-recipes/.ci_support/r/osx_64_r_base4.3.yaml similarity index 98% rename from dev/tasks/conda-recipes/.ci_support/r/osx_64_r_base4.1.yaml rename to dev/tasks/conda-recipes/.ci_support/r/osx_64_r_base4.3.yaml index 6be6c2f5462c5..7b8b62d8e00bb 100644 --- a/dev/tasks/conda-recipes/.ci_support/r/osx_64_r_base4.1.yaml +++ b/dev/tasks/conda-recipes/.ci_support/r/osx_64_r_base4.3.yaml @@ -19,7 +19,7 @@ pin_run_as_build: min_pin: x.x max_pin: x.x r_base: -- '4.1' +- '4.3' target_platform: - osx-64 zip_keys: diff --git a/dev/tasks/conda-recipes/.ci_support/r/osx_arm64_r_base4.1.yaml b/dev/tasks/conda-recipes/.ci_support/r/osx_arm64_r_base4.3.yaml similarity index 98% rename from dev/tasks/conda-recipes/.ci_support/r/osx_arm64_r_base4.1.yaml rename to dev/tasks/conda-recipes/.ci_support/r/osx_arm64_r_base4.3.yaml index 0ce856fcccf5c..a8e8aab83d598 100644 --- a/dev/tasks/conda-recipes/.ci_support/r/osx_arm64_r_base4.1.yaml +++ b/dev/tasks/conda-recipes/.ci_support/r/osx_arm64_r_base4.3.yaml @@ -19,7 +19,7 @@ pin_run_as_build: min_pin: x.x max_pin: x.x r_base: -- '4.1' +- '4.3' target_platform: - osx-arm64 zip_keys: diff --git a/dev/tasks/conda-recipes/.ci_support/win_64_cuda_compiler_version11.2.yaml b/dev/tasks/conda-recipes/.ci_support/win_64_cuda_compiler_version11.2.yaml index f75d92e276d9e..32da33c072019 100644 --- a/dev/tasks/conda-recipes/.ci_support/win_64_cuda_compiler_version11.2.yaml +++ b/dev/tasks/conda-recipes/.ci_support/win_64_cuda_compiler_version11.2.yaml @@ -1,11 +1,9 @@ aws_crt_cpp: -- 0.20.3 +- 0.23.1 aws_sdk_cpp: -- 1.10.57 +- 1.11.156 bzip2: - '1' -c_ares: -- '1' c_compiler: - vs2019 channel_sources: @@ -27,24 +25,22 @@ glog: google_cloud_cpp: - '2.12' libabseil: -- '20230125' +- '20230802' libcrc32c: - '1.1' libcurl: - '8' libgrpc: -- '1.54' -- '1.56' +- '1.57' libprotobuf: -- '3.21' -- 4.23.3 +- 4.23.4 lz4_c: - 1.9.3 numpy: -- '1.21' +- '1.22' - '1.23' -- '1.21' -- '1.21' +- '1.22' +- '1.22' openssl: - '3' orc: @@ -65,7 +61,7 @@ snappy: target_platform: - win-64 thrift_cpp: -- 0.18.1 +- 0.19.0 zip_keys: - - cuda_compiler - cuda_compiler_version diff --git a/dev/tasks/conda-recipes/.ci_support/win_64_cuda_compiler_versionNone.yaml b/dev/tasks/conda-recipes/.ci_support/win_64_cuda_compiler_versionNone.yaml index 6d8fb15b15a2a..6a33b86b9d65e 100644 --- a/dev/tasks/conda-recipes/.ci_support/win_64_cuda_compiler_versionNone.yaml +++ b/dev/tasks/conda-recipes/.ci_support/win_64_cuda_compiler_versionNone.yaml @@ -1,11 +1,9 @@ aws_crt_cpp: -- 0.20.3 +- 0.23.1 aws_sdk_cpp: -- 1.10.57 +- 1.11.156 bzip2: - '1' -c_ares: -- '1' c_compiler: - vs2019 channel_sources: @@ -27,24 +25,22 @@ glog: google_cloud_cpp: - '2.12' libabseil: -- '20230125' +- '20230802' libcrc32c: - '1.1' libcurl: - '8' libgrpc: -- '1.54' -- '1.56' +- '1.57' libprotobuf: -- '3.21' -- 4.23.3 +- 4.23.4 lz4_c: - 1.9.3 numpy: -- '1.21' +- '1.22' - '1.23' -- '1.21' -- '1.21' +- '1.22' +- '1.22' openssl: - '3' orc: @@ -65,7 +61,7 @@ snappy: target_platform: - win-64 thrift_cpp: -- 0.18.1 +- 0.19.0 zip_keys: - - cuda_compiler - cuda_compiler_version diff --git a/dev/tasks/conda-recipes/arrow-cpp/activate.sh b/dev/tasks/conda-recipes/arrow-cpp/activate.sh index 8757612781bbe..19d037ff4127a 100644 --- a/dev/tasks/conda-recipes/arrow-cpp/activate.sh +++ b/dev/tasks/conda-recipes/arrow-cpp/activate.sh @@ -23,6 +23,13 @@ _la_log "Beginning libarrow activation." # where the GDB wrappers get installed _la_gdb_prefix="$CONDA_PREFIX/share/gdb/auto-load" +# If the directory is not writable, nothing can be done +if [ ! -w "$_la_gdb_prefix" ]; then + _la_log 'No rights to modify $_la_gdb_prefix, cannot create symlink!' + _la_log 'Unless you plan to use the GDB debugger with libarrow, this warning can be safely ignored.' + return +fi + # this needs to be in sync with ARROW_GDB_INSTALL_DIR in build.sh _la_placeholder="replace_this_section_with_absolute_slashed_path_to_CONDA_PREFIX" # the paths here are intentionally stacked, see #935, resp. @@ -44,7 +51,7 @@ for _la_target in "$_la_orig_install_dir/"*.py; do # If the file doesn't exist, skip this iteration of the loop. # (This happens when no files are found, in which case the # loop runs with target equal to the pattern itself.) - _la_log 'Folder $_la_orig_install_dir seems to not contain .py files, skipping' + _la_log 'Folder $_la_orig_install_dir seems to not contain .py files, skipping.' continue fi _la_symlink="$_la_symlink_dir/$(basename "$_la_target")" @@ -54,13 +61,13 @@ for _la_target in "$_la_orig_install_dir/"*.py; do _la_log 'symlink $_la_symlink already exists and points to $_la_target, skipping.' continue fi - _la_log 'Creating symlink $_la_symlink pointing to $_la_target' + _la_log 'Creating symlink $_la_symlink pointing to $_la_target.' mkdir -p "$_la_symlink_dir" || true # this check also creates the symlink; if it fails, we enter the if-branch. if ! ln -sf "$_la_target" "$_la_symlink"; then - echo -n "${BASH_SOURCE[0]} ERROR: Failed to create symlink from " - echo -n "'$_la_target' to '$_la_symlink'" - echo + echo -n "${BASH_SOURCE[0]} WARNING: Failed to create symlink from " + echo "'$_la_target' to '$_la_symlink'!" + echo "Unless you plan to use the GDB debugger with libarrow, this warning can be safely ignored." continue fi done diff --git a/dev/tasks/conda-recipes/arrow-cpp/build-arrow.sh b/dev/tasks/conda-recipes/arrow-cpp/build-arrow.sh index dc588f9473870..ef0b038812a01 100755 --- a/dev/tasks/conda-recipes/arrow-cpp/build-arrow.sh +++ b/dev/tasks/conda-recipes/arrow-cpp/build-arrow.sh @@ -30,7 +30,7 @@ fi # Enable CUDA support if [[ ! -z "${cuda_compiler_version+x}" && "${cuda_compiler_version}" != "None" ]] then - EXTRA_CMAKE_ARGS=" ${EXTRA_CMAKE_ARGS} -DARROW_CUDA=ON -DCUDA_TOOLKIT_ROOT_DIR=${CUDA_HOME} -DCMAKE_LIBRARY_PATH=${CONDA_BUILD_SYSROOT}/lib" + EXTRA_CMAKE_ARGS=" ${EXTRA_CMAKE_ARGS} -DARROW_CUDA=ON -DCUDAToolkit_ROOT=${CUDA_HOME} -DCMAKE_LIBRARY_PATH=${CONDA_BUILD_SYSROOT}/lib" else EXTRA_CMAKE_ARGS=" ${EXTRA_CMAKE_ARGS} -DARROW_CUDA=OFF" fi @@ -43,8 +43,8 @@ if [[ "${build_platform}" != "${target_platform}" ]]; then fi EXTRA_CMAKE_ARGS="${EXTRA_CMAKE_ARGS} -DCLANG_EXECUTABLE=${BUILD_PREFIX}/bin/${CONDA_TOOLCHAIN_HOST}-clang" EXTRA_CMAKE_ARGS="${EXTRA_CMAKE_ARGS} -DLLVM_LINK_EXECUTABLE=${BUILD_PREFIX}/bin/llvm-link" + EXTRA_CMAKE_ARGS="${EXTRA_CMAKE_ARGS} -DARROW_JEMALLOC_LG_PAGE=16" sed -ie "s;protoc-gen-grpc.*$;protoc-gen-grpc=${BUILD_PREFIX}/bin/grpc_cpp_plugin\";g" ../src/arrow/flight/CMakeLists.txt - sed -ie 's;"--with-jemalloc-prefix\=je_arrow_";"--with-jemalloc-prefix\=je_arrow_" "--with-lg-page\=16";g' ../cmake_modules/ThirdpartyToolchain.cmake fi # disable -fno-plt, which causes problems with GCC on PPC diff --git a/dev/tasks/conda-recipes/arrow-cpp/build-pyarrow.sh b/dev/tasks/conda-recipes/arrow-cpp/build-pyarrow.sh index 9c12321a1c115..f39e06874ca0e 100755 --- a/dev/tasks/conda-recipes/arrow-cpp/build-pyarrow.sh +++ b/dev/tasks/conda-recipes/arrow-cpp/build-pyarrow.sh @@ -24,6 +24,10 @@ BUILD_EXT_FLAGS="" # Enable CUDA support if [[ ! -z "${cuda_compiler_version+x}" && "${cuda_compiler_version}" != "None" ]]; then export PYARROW_WITH_CUDA=1 + if [[ "${build_platform}" != "${target_platform}" ]]; then + export CUDAToolkit_ROOT=${CUDA_HOME} + export CMAKE_LIBRARY_PATH=${CONDA_BUILD_SYSROOT}/lib + fi else export PYARROW_WITH_CUDA=0 fi diff --git a/dev/tasks/conda-recipes/arrow-cpp/meta.yaml b/dev/tasks/conda-recipes/arrow-cpp/meta.yaml index fbe40af3dae01..371b62245bb72 100644 --- a/dev/tasks/conda-recipes/arrow-cpp/meta.yaml +++ b/dev/tasks/conda-recipes/arrow-cpp/meta.yaml @@ -61,7 +61,7 @@ outputs: build: string: h{{ PKG_HASH }}_{{ PKG_BUILDNUM }}_{{ build_ext }} run_exports: - - {{ pin_subpackage("libarrow", max_pin="x.x.x") }} + - {{ pin_subpackage("libarrow", max_pin="x") }} ignore_run_exports_from: - {{ compiler("cuda") }} # [cuda_compiler_version != "None"] # arrow only uses headers, apparently @@ -114,6 +114,8 @@ outputs: - libgrpc - libprotobuf - libutf8proc + # gandiva requires shared libllvm + - llvm # [unix] - lz4-c - nlohmann_json # gandiva depends on openssl @@ -133,8 +135,6 @@ outputs: # its host deps (which aren't yet covered above) leak into the build here - libcrc32c # [win] - libcurl # [win] - # same for libgrpc (before 1.55.0, which is coupled with libprotobuf 4.23.x) - - c-ares # [win and libprotobuf == "3.21"] run_constrained: - apache-arrow-proc =*={{ build_ext }} # make sure we don't co-install with old version of old package name @@ -198,8 +198,6 @@ outputs: requirements: host: - {{ pin_subpackage('libarrow', exact=True) }} - # avoid wrappers for different builds colliding due to identical hashes - - libprotobuf run: - {{ pin_subpackage('libarrow', exact=True) }} test: @@ -235,9 +233,7 @@ outputs: - cmake - ninja host: - # we're building for two protobuf versions, cannot pin exactly - # - {{ pin_subpackage('libarrow', exact=True) }} - - libarrow ={{ version }}=*_{{ PKG_BUILDNUM }}_{{ build_ext }} + - {{ pin_subpackage('libarrow', exact=True) }} - clangdev {{ llvm_version }} - llvmdev {{ llvm_version }} - cython <3 @@ -246,8 +242,7 @@ outputs: - setuptools - setuptools_scm <8.0.0 run: - # - {{ pin_subpackage('libarrow', exact=True) }} - - libarrow ={{ version }}=*_{{ PKG_BUILDNUM }}_{{ build_ext }} + - {{ pin_subpackage('libarrow', exact=True) }} - {{ pin_compatible('numpy') }} - python run_constrained: @@ -336,28 +331,28 @@ outputs: # crossbow CI: reduce to one python version, except on (unemulated) linux, where it's fast enough {% if linux64 or py == 311 %} - # {% if not (aarch64 or ppc64le) or py in (310, 311) %} - # only run the full test suite for one python version when in emulation (each run takes ~45min); - # there's essentially zero divergence in behaviour across python versions anyway, and otherwise - # CUDA builds for aarch/ppc consistently run out of disk space on azure for some reason + # {% if not (aarch64 or ppc64le) or py == 311 %} + # only run the full test suite for one python version when in emulation + # (each run can take up to ~45min); there's essentially zero divergence + # in behaviour across python versions anyway test: requires: - # vary protobuf version in test suite (historically, test failures only have a very - # weak dependency on python version, so we don't lose coverage by doing half & half) - - libprotobuf <4 # [py % 2 == 0] # test_cpp_extension_in_python requires a compiler - {{ compiler("cxx") }} # [linux] - # temporary pin due to missing fixture - - pytest <7.4.0 + - pytest - pytest-lazy-fixture - backports.zoneinfo # [py<39] + - boto3 - cffi - cloudpickle - cython <3 - fastparquet - fsspec - hypothesis + # currently disabled due to GH-37692 + # - minio-server - pandas + - s3fs >=2023 - scipy # these are generally (far) behind on migrating abseil/grpc/protobuf, # and using them as test dependencies blocks the migrator unnecessarily @@ -372,8 +367,8 @@ outputs: source_files: - testing/data commands: - - cd ${SP_DIR}/pyarrow/tests # [unix] - - cd %SP_DIR%\pyarrow\tests # [win] + - cd ${SP_DIR} # [unix] + - cd %SP_DIR% # [win] - export ARROW_TEST_DATA="${SRC_DIR}/testing/data" # [unix] - set "ARROW_TEST_DATA=%SRC_DIR%\testing\data" # [win] @@ -382,34 +377,26 @@ outputs: {% set tests_to_skip = tests_to_skip + " or test_cuda" %} # skip tests that raise SIGINT and crash the test suite {% set tests_to_skip = tests_to_skip + " or (test_csv and test_cancellation)" %} # [linux] - {% set tests_to_skip = tests_to_skip + " or (test_flight and test_interrupt)" %} # [linux] - # tests that may crash the agent due to out-of-bound memory writes or other risky stuff - {% set tests_to_skip = tests_to_skip + " or test_debug_memory_pool" %} # [aarch64 or ppc64le] - # cannot pass -D_LIBCPP_DISABLE_AVAILABILITY to test suite for our older macos sdk - {% set tests_to_skip = tests_to_skip + " or test_cpp_extension_in_python" %} # [osx] + # skip test that intentionally writes out of bounds and then expects no error message + {% set tests_to_skip = tests_to_skip + " or test_debug_memory_pool_disabled[system_memory_pool]" %} # [osx] # skip tests that make invalid(-for-conda) assumptions about the compilers setup {% set tests_to_skip = tests_to_skip + " or test_cython_api" %} # [unix] {% set tests_to_skip = tests_to_skip + " or test_visit_strings" %} # [unix] # skip tests that cannot succeed in emulation {% set tests_to_skip = tests_to_skip + " or test_debug_memory_pool_disabled" %} # [aarch64 or ppc64le] {% set tests_to_skip = tests_to_skip + " or test_env_var_io_thread_count" %} # [aarch64 or ppc64le] + # XMinioInvalidObjectName on osx/win: "Object name contains unsupported characters" + {% set tests_to_skip = tests_to_skip + " or test_write_to_dataset_with_partitions_s3fs" %} # [osx or win] # vvvvvvv TESTS THAT SHOULDN'T HAVE TO BE SKIPPED vvvvvvv - {% set tests_to_skip = tests_to_skip + " or test_extension_to_pandas_storage_type" %} - # segfaults on OSX: to investigate ASAP - {% set tests_to_skip = tests_to_skip + " or test_flight" %} # [osx] + # currently broken + {% set tests_to_skip = tests_to_skip + " or test_fastparquet_cross_compatibility" %} # gandiva tests are segfaulting on ppc - {% set tests_to_skip = tests_to_skip + " or test_gandiva" %} # [ppc64le] - # test failures on ppc + {% set tests_to_skip = tests_to_skip + " or test_gandiva" %} # [ppc64le] + # test failures on ppc (both failing with: Float value was truncated converting to int32) {% set tests_to_skip = tests_to_skip + " or test_safe_cast_from_float_with_nans_to_int" %} # [ppc64le] - # gandiva tests are segfaulting on ppc - {% set tests_to_skip = tests_to_skip + " or test_float_with_null_as_integer" %} # [ppc64le] - # test is broken; header is in $PREFIX, not $SP_DIR - {% set tests_to_skip = tests_to_skip + " or (test_misc and test_get_include)" %} # [unix] - # flaky tests that fail occasionally - {% set tests_to_skip = tests_to_skip + " or test_total_bytes_allocated " %} # [linux] - {% set tests_to_skip = tests_to_skip + " or test_feather_format " %} # [linux] + {% set tests_to_skip = tests_to_skip + " or test_float_with_null_as_integer" %} # [ppc64le] # ^^^^^^^ TESTS THAT SHOULDN'T HAVE TO BE SKIPPED ^^^^^^^ - - pytest -rfEs -k "not ({{ tests_to_skip }})" + - pytest pyarrow/ -rfEs -k "not ({{ tests_to_skip }})" {% endif %} about: diff --git a/dev/tasks/tasks.yml b/dev/tasks/tasks.yml index 29e038a922412..859ff8ddb5b44 100644 --- a/dev/tasks/tasks.yml +++ b/dev/tasks/tasks.yml @@ -246,15 +246,15 @@ tasks: # generated and to be synced regularly from the feedstock. We have no way # yet to generate them inside the arrow repository automatically. - conda-linux-x64-cpu-r41: + conda-linux-x64-cpu-r43: ci: azure template: conda-recipes/azure.linux.yml params: config: linux_64_cuda_compiler_versionNone - r_config: linux_64_r_base4.1 + r_config: linux_64_r_base4.3 artifacts: - libarrow-{no_rc_version}-(h[a-z0-9]+)_0_cpu.conda - - r-arrow-{no_rc_version}-r41(h[a-z0-9]+)_0.conda + - r-arrow-{no_rc_version}-r43(h[a-z0-9]+)_0.conda conda-linux-x64-cpu-r42: ci: azure @@ -292,15 +292,15 @@ tasks: ########################### Conda Linux (aarch64) ########################### - conda-linux-aarch64-cpu-r41: + conda-linux-aarch64-cpu-r43: ci: azure template: conda-recipes/azure.linux.yml params: config: linux_aarch64_cuda_compiler_versionNone - r_config: linux_aarch64_r_base4.1 + r_config: linux_aarch64_r_base4.3 artifacts: - libarrow-{no_rc_version}-(h[a-z0-9]+)_0_cpu.conda - - r-arrow-{no_rc_version}-r41(h[a-z0-9]+)_0.conda + - r-arrow-{no_rc_version}-r43(h[a-z0-9]+)_0.conda conda-linux-aarch64-cpu-r42: ci: azure @@ -364,15 +364,15 @@ tasks: ############################## Conda OSX (x64) ############################## - conda-osx-x64-cpu-r41: + conda-osx-x64-cpu-r43: ci: azure template: conda-recipes/azure.osx.yml params: config: osx_64_ - r_config: osx_64_r_base4.1 + r_config: osx_64_r_base4.3 artifacts: - libarrow-{no_rc_version}-(h[a-z0-9]+)_0_cpu.conda - - r-arrow-{no_rc_version}-r41(h[a-z0-9]+)_0.conda + - r-arrow-{no_rc_version}-r43(h[a-z0-9]+)_0.conda conda-osx-x64-cpu-r42: ci: azure @@ -398,15 +398,15 @@ tasks: ############################# Conda OSX (arm64) ############################# - conda-osx-arm64-cpu-r41: + conda-osx-arm64-cpu-r43: ci: azure template: conda-recipes/azure.osx.yml params: config: osx_arm64_ - r_config: osx_arm64_r_base4.1 + r_config: osx_arm64_r_base4.3 artifacts: - libarrow-{no_rc_version}-(h[a-z0-9]+)_0_cpu.conda - - r-arrow-{no_rc_version}-r41(h[a-z0-9]+)_0.conda + - r-arrow-{no_rc_version}-r43(h[a-z0-9]+)_0.conda conda-osx-arm64-cpu-r42: ci: azure From 284dddd129fae072ec3e7ae269520b54c8decdb4 Mon Sep 17 00:00:00 2001 From: James Duong Date: Thu, 28 Sep 2023 06:22:26 -0700 Subject: [PATCH 09/56] GH-37863: [Java] Add typed getters for StructVector (#37916) ### Rationale for this change Add methods for getting child vectors as specific vector subtypes for convenience. ### What changes are included in this PR? Add child getters which let the caller specify the target vector type to StructVector. ### Are these changes tested? Yes. ### Are there any user-facing changes? No. * Closes: #37863 Authored-by: James Duong Signed-off-by: David Li --- .../vector/complex/NonNullableStructVector.java | 12 ++++++++++++ .../org/apache/arrow/vector/TestStructVector.java | 8 ++++++++ 2 files changed, 20 insertions(+) diff --git a/java/vector/src/main/java/org/apache/arrow/vector/complex/NonNullableStructVector.java b/java/vector/src/main/java/org/apache/arrow/vector/complex/NonNullableStructVector.java index 4da2668121af6..7d724656cdab7 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/complex/NonNullableStructVector.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/complex/NonNullableStructVector.java @@ -374,6 +374,18 @@ public ValueVector getVectorById(int id) { return getChildByOrdinal(id); } + /** + * Gets a child vector by ordinal position and casts to the specified class. + */ + public V getVectorById(int id, Class clazz) { + ValueVector untyped = getVectorById(id); + if (clazz.isInstance(untyped)) { + return clazz.cast(untyped); + } + throw new ClassCastException("Id " + id + " had the wrong type. Expected " + clazz.getCanonicalName() + + " but was " + untyped.getClass().getCanonicalName()); + } + @Override public void setValueCount(int valueCount) { for (final ValueVector v : getChildren()) { diff --git a/java/vector/src/test/java/org/apache/arrow/vector/TestStructVector.java b/java/vector/src/test/java/org/apache/arrow/vector/TestStructVector.java index b4c30480000c8..552d5752f236f 100644 --- a/java/vector/src/test/java/org/apache/arrow/vector/TestStructVector.java +++ b/java/vector/src/test/java/org/apache/arrow/vector/TestStructVector.java @@ -282,4 +282,12 @@ public void testAddChildVectorsWithDuplicatedFieldNamesForConflictPolicyReplace( } } + @Test + public void testTypedGetters() { + try (final StructVector s1 = StructVector.empty("s1", allocator)) { + s1.addOrGet("struct_child", FieldType.nullable(MinorType.INT.getType()), IntVector.class); + assertEquals(IntVector.class, s1.getChild("struct_child", IntVector.class).getClass()); + assertEquals(IntVector.class, s1.getVectorById(0, IntVector.class).getClass()); + } + } } From 26667340f2e72c84107c9be28e68aa88dcb064ff Mon Sep 17 00:00:00 2001 From: James Duong Date: Thu, 28 Sep 2023 06:22:45 -0700 Subject: [PATCH 10/56] GH-37864: [Java] Remove unnecessary throws from OrcReader (#37913) ### Rationale for this change Make OrcReader more friendly to use with try-with-resources blocks and AutoCloseables by removing an unnecessary throws modifier on close(). ### What changes are included in this PR? Removes an unused throws specifier on OrcReader#close(). ### Are these changes tested? Yes. ### Are there any user-facing changes? No. * Closes: #37864 Authored-by: James Duong Signed-off-by: David Li --- .../src/main/java/org/apache/arrow/adapter/orc/OrcReader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/adapter/orc/src/main/java/org/apache/arrow/adapter/orc/OrcReader.java b/java/adapter/orc/src/main/java/org/apache/arrow/adapter/orc/OrcReader.java index b42ddb48433b5..648e17e9c374c 100644 --- a/java/adapter/orc/src/main/java/org/apache/arrow/adapter/orc/OrcReader.java +++ b/java/adapter/orc/src/main/java/org/apache/arrow/adapter/orc/OrcReader.java @@ -84,7 +84,7 @@ public int getNumberOfStripes() throws IllegalArgumentException { } @Override - public void close() throws Exception { + public void close() { jniWrapper.close(nativeInstanceId); } } From 019d06df56ba3215148465554948a4d93fd9c707 Mon Sep 17 00:00:00 2001 From: Laurent Goujon Date: Thu, 28 Sep 2023 07:50:51 -0700 Subject: [PATCH 11/56] GH-37893: [Java] Move Types.proto in a subfolder (#37894) ### Rationale for this change Types.proto is a Gandiva protobuf definition used by Gandiva to exchange data between Java and C++. This file is packaged automatically within arrow-gandiva jar but because of its generic name, it may cause conflicts in others' people project. ### What changes are included in this PR? Move `Types.proto` into `gandiva/types.proto` (also matching convention of using lowercase filename) so that it become less likely to cause a conflict. ### Are these changes tested? Change should have no impact on the feature itself. Manually check the resulting jar to confirm that `types.proto` is not located at the root of the archive. ### Are there any user-facing changes? No user-facing. Developers who were actually referencing Gandiva `Types.proto` in their project may have to change their `import` directive. **This PR includes breaking changes to public APIs.** * Closes: #37893 Authored-by: Laurent Goujon Signed-off-by: David Li --- java/gandiva/CMakeLists.txt | 10 +- .../{Types.proto => gandiva/types.proto} | 4 +- .../main/cpp/expression_registry_helper.cc | 87 +++++----- java/gandiva/src/main/cpp/jni_common.cc | 152 +++++++++--------- 4 files changed, 126 insertions(+), 127 deletions(-) rename java/gandiva/proto/{Types.proto => gandiva/types.proto} (99%) diff --git a/java/gandiva/CMakeLists.txt b/java/gandiva/CMakeLists.txt index 629ab2fb347d8..2aa8d92959e42 100644 --- a/java/gandiva/CMakeLists.txt +++ b/java/gandiva/CMakeLists.txt @@ -29,21 +29,21 @@ add_jar(arrow_java_jni_gandiva_jar arrow_java_jni_gandiva_headers) set(GANDIVA_PROTO_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) -set(GANDIVA_PROTO_OUTPUT_FILES "${GANDIVA_PROTO_OUTPUT_DIR}/Types.pb.cc" - "${GANDIVA_PROTO_OUTPUT_DIR}/Types.pb.h") +set(GANDIVA_PROTO_OUTPUT_FILES "${GANDIVA_PROTO_OUTPUT_DIR}/gandiva/types.pb.cc" + "${GANDIVA_PROTO_OUTPUT_DIR}/gandiva/types.pb.h") set_source_files_properties(${GANDIVA_PROTO_OUTPUT_FILES} PROPERTIES GENERATED TRUE) set(GANDIVA_PROTO_DIR ${CMAKE_CURRENT_SOURCE_DIR}/proto) -get_filename_component(GANDIVA_PROTO_FILE_ABSOLUTE ${GANDIVA_PROTO_DIR}/Types.proto - ABSOLUTE) +get_filename_component(GANDIVA_PROTO_FILE_ABSOLUTE + ${GANDIVA_PROTO_DIR}/gandiva/types.proto ABSOLUTE) find_package(Protobuf REQUIRED) add_custom_command(OUTPUT ${GANDIVA_PROTO_OUTPUT_FILES} COMMAND protobuf::protoc --proto_path ${GANDIVA_PROTO_DIR} --cpp_out ${GANDIVA_PROTO_OUTPUT_DIR} ${GANDIVA_PROTO_FILE_ABSOLUTE} DEPENDS ${GANDIVA_PROTO_FILE_ABSOLUTE} - COMMENT "Running Protobuf compiler on Types.proto" + COMMENT "Running Protobuf compiler on gandiva/types.proto" VERBATIM) add_custom_target(garrow_java_jni_gandiva_proto ALL DEPENDS ${GANDIVA_PROTO_OUTPUT_FILES}) diff --git a/java/gandiva/proto/Types.proto b/java/gandiva/proto/gandiva/types.proto similarity index 99% rename from java/gandiva/proto/Types.proto rename to java/gandiva/proto/gandiva/types.proto index eb0d996b92e63..4ce342681d614 100644 --- a/java/gandiva/proto/Types.proto +++ b/java/gandiva/proto/gandiva/types.proto @@ -15,8 +15,8 @@ // specific language governing permissions and limitations // under the License. -syntax = "proto2"; -package types; +syntax = "proto3"; +package gandiva.types; option java_package = "org.apache.arrow.gandiva.ipc"; option java_outer_classname = "GandivaTypes"; diff --git a/java/gandiva/src/main/cpp/expression_registry_helper.cc b/java/gandiva/src/main/cpp/expression_registry_helper.cc index 6765df3b9727f..66b97c8b9ef44 100644 --- a/java/gandiva/src/main/cpp/expression_registry_helper.cc +++ b/java/gandiva/src/main/cpp/expression_registry_helper.cc @@ -20,121 +20,120 @@ #include #include #include - -#include "Types.pb.h" -#include "org_apache_arrow_gandiva_evaluator_ExpressionRegistryJniHelper.h" +#include +#include using gandiva::DataTypePtr; using gandiva::ExpressionRegistry; -types::TimeUnit MapTimeUnit(arrow::TimeUnit::type& unit) { +gandiva::types::TimeUnit MapTimeUnit(arrow::TimeUnit::type& unit) { switch (unit) { case arrow::TimeUnit::MILLI: - return types::TimeUnit::MILLISEC; + return gandiva::types::TimeUnit::MILLISEC; case arrow::TimeUnit::SECOND: - return types::TimeUnit::SEC; + return gandiva::types::TimeUnit::SEC; case arrow::TimeUnit::MICRO: - return types::TimeUnit::MICROSEC; + return gandiva::types::TimeUnit::MICROSEC; case arrow::TimeUnit::NANO: - return types::TimeUnit::NANOSEC; + return gandiva::types::TimeUnit::NANOSEC; } // satisfy gcc. should be unreachable. - return types::TimeUnit::SEC; + return gandiva::types::TimeUnit::SEC; } -void ArrowToProtobuf(DataTypePtr type, types::ExtGandivaType* gandiva_data_type) { +void ArrowToProtobuf(DataTypePtr type, gandiva::types::ExtGandivaType* gandiva_data_type) { switch (type->id()) { case arrow::Type::BOOL: - gandiva_data_type->set_type(types::GandivaType::BOOL); + gandiva_data_type->set_type(gandiva::types::GandivaType::BOOL); break; case arrow::Type::UINT8: - gandiva_data_type->set_type(types::GandivaType::UINT8); + gandiva_data_type->set_type(gandiva::types::GandivaType::UINT8); break; case arrow::Type::INT8: - gandiva_data_type->set_type(types::GandivaType::INT8); + gandiva_data_type->set_type(gandiva::types::GandivaType::INT8); break; case arrow::Type::UINT16: - gandiva_data_type->set_type(types::GandivaType::UINT16); + gandiva_data_type->set_type(gandiva::types::GandivaType::UINT16); break; case arrow::Type::INT16: - gandiva_data_type->set_type(types::GandivaType::INT16); + gandiva_data_type->set_type(gandiva::types::GandivaType::INT16); break; case arrow::Type::UINT32: - gandiva_data_type->set_type(types::GandivaType::UINT32); + gandiva_data_type->set_type(gandiva::types::GandivaType::UINT32); break; case arrow::Type::INT32: - gandiva_data_type->set_type(types::GandivaType::INT32); + gandiva_data_type->set_type(gandiva::types::GandivaType::INT32); break; case arrow::Type::UINT64: - gandiva_data_type->set_type(types::GandivaType::UINT64); + gandiva_data_type->set_type(gandiva::types::GandivaType::UINT64); break; case arrow::Type::INT64: - gandiva_data_type->set_type(types::GandivaType::INT64); + gandiva_data_type->set_type(gandiva::types::GandivaType::INT64); break; case arrow::Type::HALF_FLOAT: - gandiva_data_type->set_type(types::GandivaType::HALF_FLOAT); + gandiva_data_type->set_type(gandiva::types::GandivaType::HALF_FLOAT); break; case arrow::Type::FLOAT: - gandiva_data_type->set_type(types::GandivaType::FLOAT); + gandiva_data_type->set_type(gandiva::types::GandivaType::FLOAT); break; case arrow::Type::DOUBLE: - gandiva_data_type->set_type(types::GandivaType::DOUBLE); + gandiva_data_type->set_type(gandiva::types::GandivaType::DOUBLE); break; case arrow::Type::STRING: - gandiva_data_type->set_type(types::GandivaType::UTF8); + gandiva_data_type->set_type(gandiva::types::GandivaType::UTF8); break; case arrow::Type::BINARY: - gandiva_data_type->set_type(types::GandivaType::BINARY); + gandiva_data_type->set_type(gandiva::types::GandivaType::BINARY); break; case arrow::Type::DATE32: - gandiva_data_type->set_type(types::GandivaType::DATE32); + gandiva_data_type->set_type(gandiva::types::GandivaType::DATE32); break; case arrow::Type::DATE64: - gandiva_data_type->set_type(types::GandivaType::DATE64); + gandiva_data_type->set_type(gandiva::types::GandivaType::DATE64); break; case arrow::Type::TIMESTAMP: { - gandiva_data_type->set_type(types::GandivaType::TIMESTAMP); + gandiva_data_type->set_type(gandiva::types::GandivaType::TIMESTAMP); std::shared_ptr cast_time_stamp_type = std::dynamic_pointer_cast(type); arrow::TimeUnit::type unit = cast_time_stamp_type->unit(); - types::TimeUnit time_unit = MapTimeUnit(unit); + gandiva::types::TimeUnit time_unit = MapTimeUnit(unit); gandiva_data_type->set_timeunit(time_unit); break; } case arrow::Type::TIME32: { - gandiva_data_type->set_type(types::GandivaType::TIME32); + gandiva_data_type->set_type(gandiva::types::GandivaType::TIME32); std::shared_ptr cast_time_32_type = std::dynamic_pointer_cast(type); arrow::TimeUnit::type unit = cast_time_32_type->unit(); - types::TimeUnit time_unit = MapTimeUnit(unit); + gandiva::types::TimeUnit time_unit = MapTimeUnit(unit); gandiva_data_type->set_timeunit(time_unit); break; } case arrow::Type::TIME64: { - gandiva_data_type->set_type(types::GandivaType::TIME32); + gandiva_data_type->set_type(gandiva::types::GandivaType::TIME32); std::shared_ptr cast_time_64_type = std::dynamic_pointer_cast(type); arrow::TimeUnit::type unit = cast_time_64_type->unit(); - types::TimeUnit time_unit = MapTimeUnit(unit); + gandiva::types::TimeUnit time_unit = MapTimeUnit(unit); gandiva_data_type->set_timeunit(time_unit); break; } case arrow::Type::NA: - gandiva_data_type->set_type(types::GandivaType::NONE); + gandiva_data_type->set_type(gandiva::types::GandivaType::NONE); break; case arrow::Type::DECIMAL: { - gandiva_data_type->set_type(types::GandivaType::DECIMAL); + gandiva_data_type->set_type(gandiva::types::GandivaType::DECIMAL); gandiva_data_type->set_precision(0); gandiva_data_type->set_scale(0); break; } case arrow::Type::INTERVAL_MONTHS: - gandiva_data_type->set_type(types::GandivaType::INTERVAL); - gandiva_data_type->set_intervaltype(types::IntervalType::YEAR_MONTH); + gandiva_data_type->set_type(gandiva::types::GandivaType::INTERVAL); + gandiva_data_type->set_intervaltype(gandiva::types::IntervalType::YEAR_MONTH); break; case arrow::Type::INTERVAL_DAY_TIME: - gandiva_data_type->set_type(types::GandivaType::INTERVAL); - gandiva_data_type->set_intervaltype(types::IntervalType::DAY_TIME); + gandiva_data_type->set_type(gandiva::types::GandivaType::INTERVAL); + gandiva_data_type->set_intervaltype(gandiva::types::IntervalType::DAY_TIME); break; default: // un-supported types. test ensures that @@ -146,10 +145,10 @@ void ArrowToProtobuf(DataTypePtr type, types::ExtGandivaType* gandiva_data_type) JNIEXPORT jbyteArray JNICALL Java_org_apache_arrow_gandiva_evaluator_ExpressionRegistryJniHelper_getGandivaSupportedDataTypes( // NOLINT JNIEnv* env, jobject types_helper) { - types::GandivaDataTypes gandiva_data_types; + gandiva::types::GandivaDataTypes gandiva_data_types; auto supported_types = ExpressionRegistry::supported_types(); for (auto const& type : supported_types) { - types::ExtGandivaType* gandiva_data_type = gandiva_data_types.add_datatype(); + gandiva::types::ExtGandivaType* gandiva_data_type = gandiva_data_types.add_datatype(); ArrowToProtobuf(type, gandiva_data_type); } auto size = static_cast(gandiva_data_types.ByteSizeLong()); @@ -169,15 +168,15 @@ JNIEXPORT jbyteArray JNICALL Java_org_apache_arrow_gandiva_evaluator_ExpressionRegistryJniHelper_getGandivaSupportedFunctions( // NOLINT JNIEnv* env, jobject types_helper) { ExpressionRegistry expr_registry; - types::GandivaFunctions gandiva_functions; + gandiva::types::GandivaFunctions gandiva_functions; for (auto function = expr_registry.function_signature_begin(); function != expr_registry.function_signature_end(); function++) { - types::FunctionSignature* function_signature = gandiva_functions.add_function(); + gandiva::types::FunctionSignature* function_signature = gandiva_functions.add_function(); function_signature->set_name((*function).base_name()); - types::ExtGandivaType* return_type = function_signature->mutable_returntype(); + gandiva::types::ExtGandivaType* return_type = function_signature->mutable_returntype(); ArrowToProtobuf((*function).ret_type(), return_type); for (auto& param_type : (*function).param_types()) { - types::ExtGandivaType* proto_param_type = function_signature->add_paramtypes(); + gandiva::types::ExtGandivaType* proto_param_type = function_signature->add_paramtypes(); ArrowToProtobuf(param_type, proto_param_type); } } diff --git a/java/gandiva/src/main/cpp/jni_common.cc b/java/gandiva/src/main/cpp/jni_common.cc index 43db266ff56f5..a5dff9981ce89 100644 --- a/java/gandiva/src/main/cpp/jni_common.cc +++ b/java/gandiva/src/main/cpp/jni_common.cc @@ -35,13 +35,13 @@ #include #include #include +#include +#include -#include "Types.pb.h" #include "config_holder.h" #include "env_helper.h" #include "id_to_module_map.h" #include "module_holder.h" -#include "org_apache_arrow_gandiva_evaluator_JniWrapper.h" using gandiva::ConditionPtr; using gandiva::DataTypePtr; @@ -65,7 +65,7 @@ using gandiva::FilterHolder; using gandiva::ProjectorHolder; // forward declarations -NodePtr ProtoTypeToNode(const types::TreeNode& node); +NodePtr ProtoTypeToNode(const gandiva::types::TreeNode& node); static jint JNI_VERSION = JNI_VERSION_1_6; @@ -131,11 +131,11 @@ void JNI_OnUnload(JavaVM* vm, void* reserved) { env->DeleteGlobalRef(vector_expander_ret_class_); } -DataTypePtr ProtoTypeToTime32(const types::ExtGandivaType& ext_type) { +DataTypePtr ProtoTypeToTime32(const gandiva::types::ExtGandivaType& ext_type) { switch (ext_type.timeunit()) { - case types::SEC: + case gandiva::types::SEC: return arrow::time32(arrow::TimeUnit::SECOND); - case types::MILLISEC: + case gandiva::types::MILLISEC: return arrow::time32(arrow::TimeUnit::MILLI); default: std::cerr << "Unknown time unit: " << ext_type.timeunit() << " for time32\n"; @@ -143,11 +143,11 @@ DataTypePtr ProtoTypeToTime32(const types::ExtGandivaType& ext_type) { } } -DataTypePtr ProtoTypeToTime64(const types::ExtGandivaType& ext_type) { +DataTypePtr ProtoTypeToTime64(const gandiva::types::ExtGandivaType& ext_type) { switch (ext_type.timeunit()) { - case types::MICROSEC: + case gandiva::types::MICROSEC: return arrow::time64(arrow::TimeUnit::MICRO); - case types::NANOSEC: + case gandiva::types::NANOSEC: return arrow::time64(arrow::TimeUnit::NANO); default: std::cerr << "Unknown time unit: " << ext_type.timeunit() << " for time64\n"; @@ -155,15 +155,15 @@ DataTypePtr ProtoTypeToTime64(const types::ExtGandivaType& ext_type) { } } -DataTypePtr ProtoTypeToTimestamp(const types::ExtGandivaType& ext_type) { +DataTypePtr ProtoTypeToTimestamp(const gandiva::types::ExtGandivaType& ext_type) { switch (ext_type.timeunit()) { - case types::SEC: + case gandiva::types::SEC: return arrow::timestamp(arrow::TimeUnit::SECOND); - case types::MILLISEC: + case gandiva::types::MILLISEC: return arrow::timestamp(arrow::TimeUnit::MILLI); - case types::MICROSEC: + case gandiva::types::MICROSEC: return arrow::timestamp(arrow::TimeUnit::MICRO); - case types::NANOSEC: + case gandiva::types::NANOSEC: return arrow::timestamp(arrow::TimeUnit::NANO); default: std::cerr << "Unknown time unit: " << ext_type.timeunit() << " for timestamp\n"; @@ -171,11 +171,11 @@ DataTypePtr ProtoTypeToTimestamp(const types::ExtGandivaType& ext_type) { } } -DataTypePtr ProtoTypeToInterval(const types::ExtGandivaType& ext_type) { +DataTypePtr ProtoTypeToInterval(const gandiva::types::ExtGandivaType& ext_type) { switch (ext_type.intervaltype()) { - case types::YEAR_MONTH: + case gandiva::types::YEAR_MONTH: return arrow::month_interval(); - case types::DAY_TIME: + case gandiva::types::DAY_TIME: return arrow::day_time_interval(); default: std::cerr << "Unknown interval type: " << ext_type.intervaltype() << "\n"; @@ -183,59 +183,59 @@ DataTypePtr ProtoTypeToInterval(const types::ExtGandivaType& ext_type) { } } -DataTypePtr ProtoTypeToDataType(const types::ExtGandivaType& ext_type) { +DataTypePtr ProtoTypeToDataType(const gandiva::types::ExtGandivaType& ext_type) { switch (ext_type.type()) { - case types::NONE: + case gandiva::types::NONE: return arrow::null(); - case types::BOOL: + case gandiva::types::BOOL: return arrow::boolean(); - case types::UINT8: + case gandiva::types::UINT8: return arrow::uint8(); - case types::INT8: + case gandiva::types::INT8: return arrow::int8(); - case types::UINT16: + case gandiva::types::UINT16: return arrow::uint16(); - case types::INT16: + case gandiva::types::INT16: return arrow::int16(); - case types::UINT32: + case gandiva::types::UINT32: return arrow::uint32(); - case types::INT32: + case gandiva::types::INT32: return arrow::int32(); - case types::UINT64: + case gandiva::types::UINT64: return arrow::uint64(); - case types::INT64: + case gandiva::types::INT64: return arrow::int64(); - case types::HALF_FLOAT: + case gandiva::types::HALF_FLOAT: return arrow::float16(); - case types::FLOAT: + case gandiva::types::FLOAT: return arrow::float32(); - case types::DOUBLE: + case gandiva::types::DOUBLE: return arrow::float64(); - case types::UTF8: + case gandiva::types::UTF8: return arrow::utf8(); - case types::BINARY: + case gandiva::types::BINARY: return arrow::binary(); - case types::DATE32: + case gandiva::types::DATE32: return arrow::date32(); - case types::DATE64: + case gandiva::types::DATE64: return arrow::date64(); - case types::DECIMAL: + case gandiva::types::DECIMAL: // TODO: error handling return arrow::decimal(ext_type.precision(), ext_type.scale()); - case types::TIME32: + case gandiva::types::TIME32: return ProtoTypeToTime32(ext_type); - case types::TIME64: + case gandiva::types::TIME64: return ProtoTypeToTime64(ext_type); - case types::TIMESTAMP: + case gandiva::types::TIMESTAMP: return ProtoTypeToTimestamp(ext_type); - case types::INTERVAL: + case gandiva::types::INTERVAL: return ProtoTypeToInterval(ext_type); - case types::FIXED_SIZE_BINARY: - case types::LIST: - case types::STRUCT: - case types::UNION: - case types::DICTIONARY: - case types::MAP: + case gandiva::types::FIXED_SIZE_BINARY: + case gandiva::types::LIST: + case gandiva::types::STRUCT: + case gandiva::types::UNION: + case gandiva::types::DICTIONARY: + case gandiva::types::MAP: std::cerr << "Unhandled data type: " << ext_type.type() << "\n"; return nullptr; @@ -245,7 +245,7 @@ DataTypePtr ProtoTypeToDataType(const types::ExtGandivaType& ext_type) { } } -FieldPtr ProtoTypeToField(const types::Field& f) { +FieldPtr ProtoTypeToField(const gandiva::types::Field& f) { const std::string& name = f.name(); DataTypePtr type = ProtoTypeToDataType(f.type()); bool nullable = true; @@ -256,7 +256,7 @@ FieldPtr ProtoTypeToField(const types::Field& f) { return field(name, type, nullable); } -NodePtr ProtoTypeToFieldNode(const types::FieldNode& node) { +NodePtr ProtoTypeToFieldNode(const gandiva::types::FieldNode& node) { FieldPtr field_ptr = ProtoTypeToField(node.field()); if (field_ptr == nullptr) { std::cerr << "Unable to create field node from protobuf\n"; @@ -266,12 +266,12 @@ NodePtr ProtoTypeToFieldNode(const types::FieldNode& node) { return TreeExprBuilder::MakeField(field_ptr); } -NodePtr ProtoTypeToFnNode(const types::FunctionNode& node) { +NodePtr ProtoTypeToFnNode(const gandiva::types::FunctionNode& node) { const std::string& name = node.functionname(); NodeVector children; for (int i = 0; i < node.inargs_size(); i++) { - const types::TreeNode& arg = node.inargs(i); + const gandiva::types::TreeNode& arg = node.inargs(i); NodePtr n = ProtoTypeToNode(arg); if (n == nullptr) { @@ -291,7 +291,7 @@ NodePtr ProtoTypeToFnNode(const types::FunctionNode& node) { return TreeExprBuilder::MakeFunction(name, children, return_type); } -NodePtr ProtoTypeToIfNode(const types::IfNode& node) { +NodePtr ProtoTypeToIfNode(const gandiva::types::IfNode& node) { NodePtr cond = ProtoTypeToNode(node.cond()); if (cond == nullptr) { std::cerr << "Unable to create cond node for if node\n"; @@ -319,11 +319,11 @@ NodePtr ProtoTypeToIfNode(const types::IfNode& node) { return TreeExprBuilder::MakeIf(cond, then_node, else_node, return_type); } -NodePtr ProtoTypeToAndNode(const types::AndNode& node) { +NodePtr ProtoTypeToAndNode(const gandiva::types::AndNode& node) { NodeVector children; for (int i = 0; i < node.args_size(); i++) { - const types::TreeNode& arg = node.args(i); + const gandiva::types::TreeNode& arg = node.args(i); NodePtr n = ProtoTypeToNode(arg); if (n == nullptr) { @@ -335,11 +335,11 @@ NodePtr ProtoTypeToAndNode(const types::AndNode& node) { return TreeExprBuilder::MakeAnd(children); } -NodePtr ProtoTypeToOrNode(const types::OrNode& node) { +NodePtr ProtoTypeToOrNode(const gandiva::types::OrNode& node) { NodeVector children; for (int i = 0; i < node.args_size(); i++) { - const types::TreeNode& arg = node.args(i); + const gandiva::types::TreeNode& arg = node.args(i); NodePtr n = ProtoTypeToNode(arg); if (n == nullptr) { @@ -351,7 +351,7 @@ NodePtr ProtoTypeToOrNode(const types::OrNode& node) { return TreeExprBuilder::MakeOr(children); } -NodePtr ProtoTypeToInNode(const types::InNode& node) { +NodePtr ProtoTypeToInNode(const gandiva::types::InNode& node) { NodePtr field = ProtoTypeToNode(node.node()); if (node.has_intvalues()) { @@ -417,7 +417,7 @@ NodePtr ProtoTypeToInNode(const types::InNode& node) { return nullptr; } -NodePtr ProtoTypeToNullNode(const types::NullNode& node) { +NodePtr ProtoTypeToNullNode(const gandiva::types::NullNode& node) { DataTypePtr data_type = ProtoTypeToDataType(node.type()); if (data_type == nullptr) { std::cerr << "Unknown type " << data_type->ToString() << " for null node\n"; @@ -427,7 +427,7 @@ NodePtr ProtoTypeToNullNode(const types::NullNode& node) { return TreeExprBuilder::MakeNull(data_type); } -NodePtr ProtoTypeToNode(const types::TreeNode& node) { +NodePtr ProtoTypeToNode(const gandiva::types::TreeNode& node) { if (node.has_fieldnode()) { return ProtoTypeToFieldNode(node.fieldnode()); } @@ -494,7 +494,7 @@ NodePtr ProtoTypeToNode(const types::TreeNode& node) { return nullptr; } -ExpressionPtr ProtoTypeToExpression(const types::ExpressionRoot& root) { +ExpressionPtr ProtoTypeToExpression(const gandiva::types::ExpressionRoot& root) { NodePtr root_node = ProtoTypeToNode(root.root()); if (root_node == nullptr) { std::cerr << "Unable to create expression node from expression protobuf\n"; @@ -510,7 +510,7 @@ ExpressionPtr ProtoTypeToExpression(const types::ExpressionRoot& root) { return TreeExprBuilder::MakeExpression(root_node, field); } -ConditionPtr ProtoTypeToCondition(const types::Condition& condition) { +ConditionPtr ProtoTypeToCondition(const gandiva::types::Condition& condition) { NodePtr root_node = ProtoTypeToNode(condition.root()); if (root_node == nullptr) { return nullptr; @@ -519,7 +519,7 @@ ConditionPtr ProtoTypeToCondition(const types::Condition& condition) { return TreeExprBuilder::MakeCondition(root_node); } -SchemaPtr ProtoTypeToSchema(const types::Schema& schema) { +SchemaPtr ProtoTypeToSchema(const gandiva::types::Schema& schema) { std::vector fields; for (int i = 0; i < schema.columns_size(); i++) { @@ -608,11 +608,11 @@ JNIEXPORT jlong JNICALL Java_org_apache_arrow_gandiva_evaluator_JniWrapper_build std::shared_ptr projector; std::shared_ptr holder; - types::Schema schema; + gandiva::types::Schema schema; jsize schema_len = env->GetArrayLength(schema_arr); jbyte* schema_bytes = env->GetByteArrayElements(schema_arr, 0); - types::ExpressionList exprs; + gandiva::types::ExpressionList exprs; jsize exprs_len = env->GetArrayLength(exprs_arr); jbyte* exprs_bytes = env->GetByteArrayElements(exprs_arr, 0); @@ -643,7 +643,7 @@ JNIEXPORT jlong JNICALL Java_org_apache_arrow_gandiva_evaluator_JniWrapper_build goto err_out; } - // convert types::Schema to arrow::Schema + // convert gandiva::types::Schema to arrow::Schema schema_ptr = ProtoTypeToSchema(schema); if (schema_ptr == nullptr) { ss << "Unable to construct arrow schema object from schema protobuf\n"; @@ -666,13 +666,13 @@ JNIEXPORT jlong JNICALL Java_org_apache_arrow_gandiva_evaluator_JniWrapper_build } switch (selection_vector_type) { - case types::SV_NONE: + case gandiva::types::SV_NONE: mode = gandiva::SelectionVector::MODE_NONE; break; - case types::SV_INT16: + case gandiva::types::SV_INT16: mode = gandiva::SelectionVector::MODE_UINT16; break; - case types::SV_INT32: + case gandiva::types::SV_INT32: mode = gandiva::SelectionVector::MODE_UINT32; break; } @@ -809,17 +809,17 @@ Java_org_apache_arrow_gandiva_evaluator_JniWrapper_evaluateProjector( reinterpret_cast(sel_vec_addr), sel_vec_size); int output_row_count = 0; switch (sel_vec_type) { - case types::SV_NONE: { + case gandiva::types::SV_NONE: { output_row_count = num_rows; break; } - case types::SV_INT16: { + case gandiva::types::SV_INT16: { status = gandiva::SelectionVector::MakeImmutableInt16( sel_vec_rows, selection_buffer, &selection_vector); output_row_count = sel_vec_rows; break; } - case types::SV_INT32: { + case gandiva::types::SV_INT32: { status = gandiva::SelectionVector::MakeImmutableInt32( sel_vec_rows, selection_buffer, &selection_vector); output_row_count = sel_vec_rows; @@ -909,11 +909,11 @@ JNIEXPORT jlong JNICALL Java_org_apache_arrow_gandiva_evaluator_JniWrapper_build std::shared_ptr filter; std::shared_ptr holder; - types::Schema schema; + gandiva::types::Schema schema; jsize schema_len = env->GetArrayLength(schema_arr); jbyte* schema_bytes = env->GetByteArrayElements(schema_arr, 0); - types::Condition condition; + gandiva::types::Condition condition; jsize condition_len = env->GetArrayLength(condition_arr); jbyte* condition_bytes = env->GetByteArrayElements(condition_arr, 0); @@ -943,7 +943,7 @@ JNIEXPORT jlong JNICALL Java_org_apache_arrow_gandiva_evaluator_JniWrapper_build goto err_out; } - // convert types::Schema to arrow::Schema + // convert gandiva::types::Schema to arrow::Schema schema_ptr = ProtoTypeToSchema(schema); if (schema_ptr == nullptr) { ss << "Unable to construct arrow schema object from schema protobuf\n"; @@ -1008,15 +1008,15 @@ JNIEXPORT jint JNICALL Java_org_apache_arrow_gandiva_evaluator_JniWrapper_evalua } auto selection_vector_type = - static_cast(jselection_vector_type); + static_cast(jselection_vector_type); auto out_buffer = std::make_shared( reinterpret_cast(out_buf_addr), out_buf_size); switch (selection_vector_type) { - case types::SV_INT16: + case gandiva::types::SV_INT16: status = gandiva::SelectionVector::MakeInt16(num_rows, out_buffer, &selection_vector); break; - case types::SV_INT32: + case gandiva::types::SV_INT32: status = gandiva::SelectionVector::MakeInt32(num_rows, out_buffer, &selection_vector); break; From 853d8491addff3a10fc40950823a2942bb9fbf98 Mon Sep 17 00:00:00 2001 From: Gang Wu Date: Fri, 29 Sep 2023 00:07:16 +0800 Subject: [PATCH 12/56] GH-34950: [C++][Parquet] Support encryption for page index (#36574) ### Rationale for this change Parquet modular encryption requires page index to be encrypted if the column chunk is encrypted. This feature is missing for now. ### What changes are included in this PR? Support both encryption and decryption for parquet page index. ### Are these changes tested? Added round trip tests in write_configurations_test.cc and read_configurations_test.cc. ### Are there any user-facing changes? NO. * Closes: #34950 Authored-by: Gang Wu Signed-off-by: Antoine Pitrou --- cpp/src/parquet/column_reader.cc | 8 +- cpp/src/parquet/column_writer.cc | 4 +- .../parquet/encryption/encryption_internal.h | 2 + .../encryption/internal_file_decryptor.cc | 55 ++++++ .../encryption/internal_file_decryptor.h | 13 ++ .../encryption/read_configurations_test.cc | 58 ++++-- .../encryption/test_encryption_util.cc | 178 +++++++++++++++++- .../parquet/encryption/test_encryption_util.h | 16 +- cpp/src/parquet/encryption/type_fwd.h | 28 +++ .../encryption/write_configurations_test.cc | 2 +- cpp/src/parquet/file_reader.cc | 34 +--- cpp/src/parquet/file_writer.cc | 6 +- cpp/src/parquet/metadata.cc | 7 +- cpp/src/parquet/metadata.h | 8 +- cpp/src/parquet/page_index.cc | 105 +++++++---- cpp/src/parquet/page_index.h | 26 +-- cpp/src/parquet/thrift_internal.h | 7 +- cpp/src/parquet/type_fwd.h | 3 + 18 files changed, 439 insertions(+), 121 deletions(-) create mode 100644 cpp/src/parquet/encryption/type_fwd.h diff --git a/cpp/src/parquet/column_reader.cc b/cpp/src/parquet/column_reader.cc index 6fe1ce9da60fe..fa013dd2ea583 100644 --- a/cpp/src/parquet/column_reader.cc +++ b/cpp/src/parquet/column_reader.cc @@ -363,10 +363,8 @@ void SerializedPageReader::UpdateDecryption(const std::shared_ptr& de int8_t module_type, std::string* page_aad) { ARROW_DCHECK(decryptor != nullptr); if (crypto_ctx_.start_decrypt_with_dictionary_page) { - std::string aad = encryption::CreateModuleAad( - decryptor->file_aad(), module_type, crypto_ctx_.row_group_ordinal, - crypto_ctx_.column_ordinal, kNonPageOrdinal); - decryptor->UpdateAad(aad); + UpdateDecryptor(decryptor, crypto_ctx_.row_group_ordinal, crypto_ctx_.column_ordinal, + module_type); } else { encryption::QuickUpdatePageAad(page_ordinal_, page_aad); decryptor->UpdateAad(*page_aad); @@ -449,7 +447,7 @@ std::shared_ptr SerializedPageReader::NextPage() { current_page_header_ = format::PageHeader(); deserializer.DeserializeMessage(reinterpret_cast(view.data()), &header_size, ¤t_page_header_, - crypto_ctx_.meta_decryptor); + crypto_ctx_.meta_decryptor.get()); break; } catch (std::exception& e) { // Failed to deserialize. Double the allowed page header size and try again diff --git a/cpp/src/parquet/column_writer.cc b/cpp/src/parquet/column_writer.cc index ae9216ba7c312..a0aedeee9e968 100644 --- a/cpp/src/parquet/column_writer.cc +++ b/cpp/src/parquet/column_writer.cc @@ -330,7 +330,7 @@ class SerializedPageWriter : public PageWriter { UpdateEncryption(encryption::kDictionaryPageHeader); } const int64_t header_size = - thrift_serializer_->Serialize(&page_header, sink_.get(), meta_encryptor_); + thrift_serializer_->Serialize(&page_header, sink_.get(), meta_encryptor_.get()); PARQUET_THROW_NOT_OK(sink_->Write(output_data_buffer, output_data_len)); @@ -422,7 +422,7 @@ class SerializedPageWriter : public PageWriter { UpdateEncryption(encryption::kDataPageHeader); } const int64_t header_size = - thrift_serializer_->Serialize(&page_header, sink_.get(), meta_encryptor_); + thrift_serializer_->Serialize(&page_header, sink_.get(), meta_encryptor_.get()); PARQUET_THROW_NOT_OK(sink_->Write(output_data_buffer, output_data_len)); /// Collect page index diff --git a/cpp/src/parquet/encryption/encryption_internal.h b/cpp/src/parquet/encryption/encryption_internal.h index 4ed5b5cf61243..77921d8731d25 100644 --- a/cpp/src/parquet/encryption/encryption_internal.h +++ b/cpp/src/parquet/encryption/encryption_internal.h @@ -40,6 +40,8 @@ constexpr int8_t kDataPageHeader = 4; constexpr int8_t kDictionaryPageHeader = 5; constexpr int8_t kColumnIndex = 6; constexpr int8_t kOffsetIndex = 7; +constexpr int8_t kBloomFilterHeader = 8; +constexpr int8_t kBloomFilterBitset = 9; /// Performs AES encryption operations with GCM or CTR ciphers. class AesEncryptor { diff --git a/cpp/src/parquet/encryption/internal_file_decryptor.cc b/cpp/src/parquet/encryption/internal_file_decryptor.cc index 87bfc2bd12047..19e4845c8732d 100644 --- a/cpp/src/parquet/encryption/internal_file_decryptor.cc +++ b/cpp/src/parquet/encryption/internal_file_decryptor.cc @@ -16,8 +16,10 @@ // under the License. #include "parquet/encryption/internal_file_decryptor.h" +#include "arrow/util/logging.h" #include "parquet/encryption/encryption.h" #include "parquet/encryption/encryption_internal.h" +#include "parquet/metadata.h" namespace parquet { @@ -215,4 +217,57 @@ std::shared_ptr InternalFileDecryptor::GetColumnDecryptor( return column_data_map_[column_path]; } +namespace { + +std::shared_ptr GetColumnDecryptor( + const ColumnCryptoMetaData* crypto_metadata, InternalFileDecryptor* file_decryptor, + const std::function( + InternalFileDecryptor* file_decryptor, const std::string& column_path, + const std::string& column_key_metadata, const std::string& aad)>& func, + bool metadata) { + if (crypto_metadata == nullptr) { + return nullptr; + } + + if (file_decryptor == nullptr) { + throw ParquetException("RowGroup is noted as encrypted but no file decryptor"); + } + + if (crypto_metadata->encrypted_with_footer_key()) { + return metadata ? file_decryptor->GetFooterDecryptorForColumnMeta() + : file_decryptor->GetFooterDecryptorForColumnData(); + } + + // The column is encrypted with its own key + const std::string& column_key_metadata = crypto_metadata->key_metadata(); + const std::string column_path = crypto_metadata->path_in_schema()->ToDotString(); + return func(file_decryptor, column_path, column_key_metadata, /*aad=*/""); +} + +} // namespace + +std::shared_ptr GetColumnMetaDecryptor( + const ColumnCryptoMetaData* crypto_metadata, InternalFileDecryptor* file_decryptor) { + return GetColumnDecryptor(crypto_metadata, file_decryptor, + &InternalFileDecryptor::GetColumnMetaDecryptor, + /*metadata=*/true); +} + +std::shared_ptr GetColumnDataDecryptor( + const ColumnCryptoMetaData* crypto_metadata, InternalFileDecryptor* file_decryptor) { + return GetColumnDecryptor(crypto_metadata, file_decryptor, + &InternalFileDecryptor::GetColumnDataDecryptor, + /*metadata=*/false); +} + +void UpdateDecryptor(const std::shared_ptr& decryptor, + int16_t row_group_ordinal, int16_t column_ordinal, + int8_t module_type) { + ARROW_DCHECK(!decryptor->file_aad().empty()); + const std::string aad = + encryption::CreateModuleAad(decryptor->file_aad(), module_type, row_group_ordinal, + column_ordinal, kNonPageOrdinal); + decryptor->UpdateAad(aad); +} + } // namespace parquet diff --git a/cpp/src/parquet/encryption/internal_file_decryptor.h b/cpp/src/parquet/encryption/internal_file_decryptor.h index 2f9c3952aff2d..0b27effda8822 100644 --- a/cpp/src/parquet/encryption/internal_file_decryptor.h +++ b/cpp/src/parquet/encryption/internal_file_decryptor.h @@ -31,6 +31,7 @@ class AesDecryptor; class AesEncryptor; } // namespace encryption +class ColumnCryptoMetaData; class FileDecryptionProperties; class PARQUET_EXPORT Decryptor { @@ -110,4 +111,16 @@ class InternalFileDecryptor { bool metadata = false); }; +/// Utility to get column meta decryptor of an encrypted column. +std::shared_ptr GetColumnMetaDecryptor( + const ColumnCryptoMetaData* crypto_metadata, InternalFileDecryptor* file_decryptor); + +/// Utility to get column data decryptor of an encrypted column. +std::shared_ptr GetColumnDataDecryptor( + const ColumnCryptoMetaData* crypto_metadata, InternalFileDecryptor* file_decryptor); + +void UpdateDecryptor(const std::shared_ptr& decryptor, + int16_t row_group_ordinal, int16_t column_ordinal, + int8_t module_type); + } // namespace parquet diff --git a/cpp/src/parquet/encryption/read_configurations_test.cc b/cpp/src/parquet/encryption/read_configurations_test.cc index 10de7198ac5ff..695696db293fb 100644 --- a/cpp/src/parquet/encryption/read_configurations_test.cc +++ b/cpp/src/parquet/encryption/read_configurations_test.cc @@ -36,7 +36,7 @@ * The unit-test is called multiple times, each time to decrypt parquet files using * different decryption configuration as described below. * In each call two encrypted files are read: one temporary file that was generated using - * encryption-write-configurations-test.cc test and will be deleted upon + * write_configurations_test.cc test and will be deleted upon * reading it, while the second resides in * parquet-testing/data repository. Those two encrypted files were encrypted using the * same encryption configuration. @@ -59,8 +59,8 @@ * read the footer + all non-encrypted columns. * (pairs with encryption configuration 3) * - * The encrypted parquet files that is read was encrypted using one of the configurations - * below: + * The encrypted parquet files that are read were encrypted using one of the + * configurations below: * * - Encryption configuration 1: Encrypt all columns and the footer with the same key. * (uniform encryption) @@ -166,7 +166,11 @@ class TestDecryptionConfiguration vector_of_decryption_configurations_.push_back(NULL); } - void DecryptFile(std::string file, int decryption_config_num) { + void DecryptFileInternal( + const std::string& file, int decryption_config_num, + std::function&)> + decrypt_func) { std::string exception_msg; std::shared_ptr file_decryption_properties; // if we get decryption_config_num = x then it means the actual number is x+1 @@ -176,18 +180,40 @@ class TestDecryptionConfiguration vector_of_decryption_configurations_[decryption_config_num]->DeepClone(); } - decryptor_.DecryptFile(file, file_decryption_properties); + decrypt_func(std::move(file), std::move(file_decryption_properties)); + } + + void DecryptFile(const std::string& file, int decryption_config_num) { + DecryptFileInternal( + file, decryption_config_num, + [&](const std::string& file, + const std::shared_ptr& file_decryption_properties) { + decryptor_.DecryptFile(file, file_decryption_properties); + }); + } + + void DecryptPageIndex(const std::string& file, int decryption_config_num) { + DecryptFileInternal( + file, decryption_config_num, + [&](const std::string& file, + const std::shared_ptr& file_decryption_properties) { + decryptor_.DecryptPageIndex(file, file_decryption_properties); + }); } // Check that the decryption result is as expected. - void CheckResults(const std::string file_name, unsigned decryption_config_num, - unsigned encryption_config_num) { + void CheckResults(const std::string& file_name, unsigned decryption_config_num, + unsigned encryption_config_num, bool file_has_page_index) { // Encryption_configuration number five contains aad_prefix and // disable_aad_prefix_storage. // An exception is expected to be thrown if the file is not decrypted with aad_prefix. if (encryption_config_num == 5) { if (decryption_config_num == 1 || decryption_config_num == 3) { EXPECT_THROW(DecryptFile(file_name, decryption_config_num - 1), ParquetException); + if (file_has_page_index) { + EXPECT_THROW(DecryptPageIndex(file_name, decryption_config_num - 1), + ParquetException); + } return; } } @@ -196,6 +222,10 @@ class TestDecryptionConfiguration if (decryption_config_num == 2) { if (encryption_config_num != 5 && encryption_config_num != 4) { EXPECT_THROW(DecryptFile(file_name, decryption_config_num - 1), ParquetException); + if (file_has_page_index) { + EXPECT_THROW(DecryptPageIndex(file_name, decryption_config_num - 1), + ParquetException); + } return; } } @@ -205,6 +235,9 @@ class TestDecryptionConfiguration return; } EXPECT_NO_THROW(DecryptFile(file_name, decryption_config_num - 1)); + if (file_has_page_index) { + EXPECT_NO_THROW(DecryptPageIndex(file_name, decryption_config_num - 1)); + } } // Returns true if file exists. Otherwise returns false. @@ -217,14 +250,13 @@ class TestDecryptionConfiguration // Read encrypted parquet file. // The test reads two parquet files that were encrypted using the same encryption // configuration: -// one was generated in encryption-write-configurations-test.cc tests and is deleted +// one was generated in write_configurations_test.cc tests and is deleted // once the file is read and the second exists in parquet-testing/data folder. // The name of the files are passed as parameters to the unit-test. TEST_P(TestDecryptionConfiguration, TestDecryption) { int encryption_config_num = std::get<0>(GetParam()); const char* param_file_name = std::get<1>(GetParam()); - // Decrypt parquet file that was generated in encryption-write-configurations-test.cc - // test. + // Decrypt parquet file that was generated in write_configurations_test.cc test. std::string tmp_file_name = "tmp_" + std::string(param_file_name); std::string file_name = temp_dir->path().ToString() + tmp_file_name; if (!fexists(file_name)) { @@ -237,7 +269,8 @@ TEST_P(TestDecryptionConfiguration, TestDecryption) { // parquet file. for (unsigned index = 0; index < vector_of_decryption_configurations_.size(); ++index) { unsigned decryption_config_num = index + 1; - CheckResults(file_name, decryption_config_num, encryption_config_num); + CheckResults(file_name, decryption_config_num, encryption_config_num, + /*file_has_page_index=*/true); } // Delete temporary test file. ASSERT_EQ(std::remove(file_name.c_str()), 0); @@ -255,7 +288,8 @@ TEST_P(TestDecryptionConfiguration, TestDecryption) { // parquet file. for (unsigned index = 0; index < vector_of_decryption_configurations_.size(); ++index) { unsigned decryption_config_num = index + 1; - CheckResults(file_name, decryption_config_num, encryption_config_num); + CheckResults(file_name, decryption_config_num, encryption_config_num, + /*file_has_page_index=*/false); } } diff --git a/cpp/src/parquet/encryption/test_encryption_util.cc b/cpp/src/parquet/encryption/test_encryption_util.cc index 694ed3cf42d9e..4fa215312f265 100644 --- a/cpp/src/parquet/encryption/test_encryption_util.cc +++ b/cpp/src/parquet/encryption/test_encryption_util.cc @@ -19,14 +19,17 @@ // Parquet column chunk within a row group. It could be extended in the future // to iterate through all data pages in all chunks in a file. +#include #include -#include - +#include "arrow/io/file.h" #include "arrow/testing/future_util.h" +#include "arrow/util/unreachable.h" + #include "parquet/encryption/test_encryption_util.h" #include "parquet/file_reader.h" #include "parquet/file_writer.h" +#include "parquet/page_index.h" #include "parquet/test_util.h" using ::arrow::io::FileOutputStream; @@ -206,6 +209,7 @@ void FileEncryptor::EncryptFile( WriterProperties::Builder prop_builder; prop_builder.compression(parquet::Compression::UNCOMPRESSED); prop_builder.encryption(encryption_configurations); + prop_builder.enable_write_page_index(); std::shared_ptr writer_properties = prop_builder.build(); PARQUET_ASSIGN_OR_THROW(auto out_file, FileOutputStream::Open(file)); @@ -340,8 +344,8 @@ void ReadAndVerifyColumn(RowGroupReader* rg_reader, RowGroupMetadata* rg_md, } void FileDecryptor::DecryptFile( - std::string file, - std::shared_ptr file_decryption_properties) { + const std::string& file, + const std::shared_ptr& file_decryption_properties) { std::string exception_msg; parquet::ReaderProperties reader_properties = parquet::default_reader_properties(); if (file_decryption_properties) { @@ -353,7 +357,7 @@ void FileDecryptor::DecryptFile( source, ::arrow::io::ReadableFile::Open(file, reader_properties.memory_pool())); auto file_reader = parquet::ParquetFileReader::Open(source, reader_properties); - CheckFile(file_reader.get(), file_decryption_properties.get()); + CheckFile(file_reader.get(), file_decryption_properties); if (file_decryption_properties) { reader_properties.file_decryption_properties(file_decryption_properties->DeepClone()); @@ -361,14 +365,15 @@ void FileDecryptor::DecryptFile( auto fut = parquet::ParquetFileReader::OpenAsync(source, reader_properties); ASSERT_FINISHES_OK(fut); ASSERT_OK_AND_ASSIGN(file_reader, fut.MoveResult()); - CheckFile(file_reader.get(), file_decryption_properties.get()); + CheckFile(file_reader.get(), file_decryption_properties); file_reader->Close(); PARQUET_THROW_NOT_OK(source->Close()); } -void FileDecryptor::CheckFile(parquet::ParquetFileReader* file_reader, - FileDecryptionProperties* file_decryption_properties) { +void FileDecryptor::CheckFile( + parquet::ParquetFileReader* file_reader, + const std::shared_ptr& file_decryption_properties) { // Get the File MetaData std::shared_ptr file_metadata = file_reader->metadata(); @@ -509,4 +514,161 @@ void FileDecryptor::CheckFile(parquet::ParquetFileReader* file_reader, } } +void FileDecryptor::DecryptPageIndex( + const std::string& file, + const std::shared_ptr& file_decryption_properties) { + std::string exception_msg; + parquet::ReaderProperties reader_properties = parquet::default_reader_properties(); + if (file_decryption_properties) { + reader_properties.file_decryption_properties(file_decryption_properties->DeepClone()); + } + + std::shared_ptr<::arrow::io::RandomAccessFile> source; + PARQUET_ASSIGN_OR_THROW( + source, ::arrow::io::ReadableFile::Open(file, reader_properties.memory_pool())); + + auto file_reader = parquet::ParquetFileReader::Open(source, reader_properties); + CheckPageIndex(file_reader.get(), file_decryption_properties); + + ASSERT_NO_FATAL_FAILURE(file_reader->Close()); + PARQUET_THROW_NOT_OK(source->Close()); +} + +template +void AssertColumnIndex(const std::shared_ptr& column_index, + const std::vector& expected_null_counts, + const std::vector& expected_min_values, + const std::vector& expected_max_values) { + auto typed_column_index = + std::dynamic_pointer_cast>(column_index); + ASSERT_NE(typed_column_index, nullptr); + ASSERT_EQ(typed_column_index->null_counts(), expected_null_counts); + if constexpr (std::is_same_v) { + ASSERT_EQ(typed_column_index->min_values().size(), expected_min_values.size()); + ASSERT_EQ(typed_column_index->max_values().size(), expected_max_values.size()); + for (size_t i = 0; i < expected_min_values.size(); ++i) { + ASSERT_EQ( + FixedLenByteArrayToString(typed_column_index->min_values()[i], kFixedLength), + FixedLenByteArrayToString(expected_min_values[i], kFixedLength)); + } + for (size_t i = 0; i < expected_max_values.size(); ++i) { + ASSERT_EQ( + FixedLenByteArrayToString(typed_column_index->max_values()[i], kFixedLength), + FixedLenByteArrayToString(expected_max_values[i], kFixedLength)); + } + } else { + ASSERT_EQ(typed_column_index->min_values(), expected_min_values); + ASSERT_EQ(typed_column_index->max_values(), expected_max_values); + } +} + +void FileDecryptor::CheckPageIndex( + parquet::ParquetFileReader* file_reader, + const std::shared_ptr& file_decryption_properties) { + std::shared_ptr page_index_reader = file_reader->GetPageIndexReader(); + ASSERT_NE(page_index_reader, nullptr); + + const std::shared_ptr file_metadata = file_reader->metadata(); + const int num_row_groups = file_metadata->num_row_groups(); + const int num_columns = file_metadata->num_columns(); + ASSERT_EQ(num_columns, 8); + + // We cannot read page index of encrypted columns in the plaintext mode + std::vector need_row_groups(num_row_groups); + std::iota(need_row_groups.begin(), need_row_groups.end(), 0); + std::vector need_columns; + if (file_decryption_properties == nullptr) { + need_columns = {0, 1, 2, 3, 6, 7}; + } else { + need_columns = {0, 1, 2, 3, 4, 5, 6, 7}; + } + + // Provide hint of requested columns to avoid accessing encrypted columns without + // decryption properties. + page_index_reader->WillNeed( + need_row_groups, need_columns, + PageIndexSelection{/*column_index=*/true, /*offset_index=*/true}); + + // Iterate over all the RowGroups in the file. + for (int r = 0; r < num_row_groups; ++r) { + auto row_group_page_index_reader = page_index_reader->RowGroup(r); + ASSERT_NE(row_group_page_index_reader, nullptr); + + for (int c = 0; c < num_columns; ++c) { + // Skip reading encrypted columns without decryption properties. + if (file_decryption_properties == nullptr && (c == 4 || c == 5)) { + continue; + } + + constexpr size_t kExpectedNumPages = 1; + + // Check offset index. + auto offset_index = row_group_page_index_reader->GetOffsetIndex(c); + ASSERT_NE(offset_index, nullptr); + ASSERT_EQ(offset_index->page_locations().size(), kExpectedNumPages); + const auto& first_page = offset_index->page_locations()[0]; + ASSERT_EQ(first_page.first_row_index, 0); + ASSERT_GT(first_page.compressed_page_size, 0); + + // Int96 column does not have column index. + if (c == 3) { + continue; + } + + // Check column index + auto column_index = row_group_page_index_reader->GetColumnIndex(c); + ASSERT_NE(column_index, nullptr); + ASSERT_EQ(column_index->null_pages().size(), kExpectedNumPages); + ASSERT_EQ(column_index->null_pages()[0], false); + ASSERT_EQ(column_index->encoded_min_values().size(), kExpectedNumPages); + ASSERT_EQ(column_index->encoded_max_values().size(), kExpectedNumPages); + ASSERT_TRUE(column_index->has_null_counts()); + + switch (c) { + case 0: { + AssertColumnIndex(column_index, /*expected_null_counts=*/{0}, + /*expected_min_values=*/{false}, + /*expected_max_values=*/{true}); + } break; + case 1: { + AssertColumnIndex(column_index, /*expected_null_counts=*/{0}, + /*expected_min_values=*/{0}, + /*expected_max_values=*/{49}); + } break; + case 2: { + AssertColumnIndex(column_index, /*expected_null_counts=*/{0}, + /*expected_min_values=*/{0}, + /*expected_max_values=*/{99000000000000}); + } break; + case 4: { + AssertColumnIndex(column_index, /*expected_null_counts=*/{0}, + /*expected_min_values=*/{0.0F}, + /*expected_max_values=*/{53.9F}); + } break; + case 5: { + AssertColumnIndex(column_index, /*expected_null_counts=*/{0}, + /*expected_min_values=*/{0.0}, + /*expected_max_values=*/{54.4444439}); + } break; + case 6: { + AssertColumnIndex( + column_index, /*expected_null_counts=*/{25}, + /*expected_min_values=*/{ByteArray("parquet000")}, + /*expected_max_values=*/{ByteArray("parquet048")}); + } break; + case 7: { + const std::vector kExpectedMinValue(kFixedLength, 0); + const std::vector kExpectedMaxValue(kFixedLength, 49); + AssertColumnIndex( + column_index, /*expected_null_counts=*/{0}, + /*expected_min_values=*/{FLBA(kExpectedMinValue.data())}, + /*expected_max_values=*/{FLBA(kExpectedMaxValue.data())}); + } break; + default: + ::arrow::Unreachable("Unexpected column index " + std::to_string(c)); + } + } + } +} + } // namespace parquet::encryption::test diff --git a/cpp/src/parquet/encryption/test_encryption_util.h b/cpp/src/parquet/encryption/test_encryption_util.h index 19c230ee5ff99..86aa0ff07cf84 100644 --- a/cpp/src/parquet/encryption/test_encryption_util.h +++ b/cpp/src/parquet/encryption/test_encryption_util.h @@ -113,12 +113,20 @@ class FileEncryptor { class FileDecryptor { public: - void DecryptFile(std::string file_name, - std::shared_ptr file_decryption_properties); + void DecryptFile( + const std::string& file_name, + const std::shared_ptr& file_decryption_properties); + void DecryptPageIndex( + const std::string& file_name, + const std::shared_ptr& file_decryption_properties); private: - void CheckFile(parquet::ParquetFileReader* file_reader, - FileDecryptionProperties* file_decryption_properties); + void CheckFile( + parquet::ParquetFileReader* file_reader, + const std::shared_ptr& file_decryption_properties); + void CheckPageIndex( + parquet::ParquetFileReader* file_reader, + const std::shared_ptr& file_decryption_properties); }; } // namespace encryption::test diff --git a/cpp/src/parquet/encryption/type_fwd.h b/cpp/src/parquet/encryption/type_fwd.h new file mode 100644 index 0000000000000..623811718482c --- /dev/null +++ b/cpp/src/parquet/encryption/type_fwd.h @@ -0,0 +1,28 @@ +// 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. + +#pragma once + +namespace parquet { + +class Decryptor; +class Encryptor; + +class InternalFileDecryptor; +class InternalFileEncryptor; + +} // namespace parquet diff --git a/cpp/src/parquet/encryption/write_configurations_test.cc b/cpp/src/parquet/encryption/write_configurations_test.cc index e262003db3e6a..f27da82694874 100644 --- a/cpp/src/parquet/encryption/write_configurations_test.cc +++ b/cpp/src/parquet/encryption/write_configurations_test.cc @@ -33,7 +33,7 @@ * This file contains unit-tests for writing encrypted Parquet files with * different encryption configurations. * The files are saved in temporary folder and will be deleted after reading - * them in encryption-read-configurations-test.cc test. + * them in read_configurations_test.cc test. * * A detailed description of the Parquet Modular Encryption specification can be found * here: diff --git a/cpp/src/parquet/file_reader.cc b/cpp/src/parquet/file_reader.cc index 08d493b0bca2f..5247b9d4b543d 100644 --- a/cpp/src/parquet/file_reader.cc +++ b/cpp/src/parquet/file_reader.cc @@ -227,37 +227,19 @@ class SerializedRowGroup : public RowGroupReader::Contents { always_compressed); } - if (file_decryptor_ == nullptr) { - throw ParquetException("RowGroup is noted as encrypted but no file decryptor"); - } + // The column is encrypted + std::shared_ptr meta_decryptor = + GetColumnMetaDecryptor(crypto_metadata.get(), file_decryptor_.get()); + std::shared_ptr data_decryptor = + GetColumnDataDecryptor(crypto_metadata.get(), file_decryptor_.get()); + ARROW_DCHECK_NE(meta_decryptor, nullptr); + ARROW_DCHECK_NE(data_decryptor, nullptr); constexpr auto kEncryptedRowGroupsLimit = 32767; if (i > kEncryptedRowGroupsLimit) { throw ParquetException("Encrypted files cannot contain more than 32767 row groups"); } - // The column is encrypted - std::shared_ptr meta_decryptor; - std::shared_ptr data_decryptor; - // The column is encrypted with footer key - if (crypto_metadata->encrypted_with_footer_key()) { - meta_decryptor = file_decryptor_->GetFooterDecryptorForColumnMeta(); - data_decryptor = file_decryptor_->GetFooterDecryptorForColumnData(); - CryptoContext ctx(col->has_dictionary_page(), row_group_ordinal_, - static_cast(i), meta_decryptor, data_decryptor); - return PageReader::Open(stream, col->num_values(), col->compression(), properties_, - always_compressed, &ctx); - } - - // The column is encrypted with its own key - std::string column_key_metadata = crypto_metadata->key_metadata(); - const std::string column_path = crypto_metadata->path_in_schema()->ToDotString(); - - meta_decryptor = - file_decryptor_->GetColumnMetaDecryptor(column_path, column_key_metadata); - data_decryptor = - file_decryptor_->GetColumnDataDecryptor(column_path, column_key_metadata); - CryptoContext ctx(col->has_dictionary_page(), row_group_ordinal_, static_cast(i), meta_decryptor, data_decryptor); return PageReader::Open(stream, col->num_values(), col->compression(), properties_, @@ -330,7 +312,7 @@ class SerializedFile : public ParquetFileReader::Contents { } if (!page_index_reader_) { page_index_reader_ = PageIndexReader::Make(source_.get(), file_metadata_, - properties_, file_decryptor_); + properties_, file_decryptor_.get()); } return page_index_reader_; } diff --git a/cpp/src/parquet/file_writer.cc b/cpp/src/parquet/file_writer.cc index 2a6a88df2dd0a..9a92d4525d23d 100644 --- a/cpp/src/parquet/file_writer.cc +++ b/cpp/src/parquet/file_writer.cc @@ -471,10 +471,6 @@ class FileSerializer : public ParquetFileWriter::Contents { void WritePageIndex() { if (page_index_builder_ != nullptr) { - if (properties_->file_encryption_properties()) { - throw ParquetException("Encryption is not supported with page index"); - } - // Serialize page index after all row groups have been written and report // location to the file metadata. PageIndexLocation page_index_location; @@ -533,7 +529,7 @@ class FileSerializer : public ParquetFileWriter::Contents { } if (properties_->page_index_enabled()) { - page_index_builder_ = PageIndexBuilder::Make(&schema_); + page_index_builder_ = PageIndexBuilder::Make(&schema_, file_encryptor_.get()); } } }; diff --git a/cpp/src/parquet/metadata.cc b/cpp/src/parquet/metadata.cc index 8aedf5b926add..4ef2151fee59d 100644 --- a/cpp/src/parquet/metadata.cc +++ b/cpp/src/parquet/metadata.cc @@ -211,7 +211,7 @@ class ColumnChunkMetaData::ColumnChunkMetaDataImpl { ThriftDeserializer deserializer(properties_); deserializer.DeserializeMessage( reinterpret_cast(column->encrypted_column_metadata.c_str()), - &len, &decrypted_metadata_, decryptor); + &len, &decrypted_metadata_, decryptor.get()); column_metadata_ = &decrypted_metadata_; } else { throw ParquetException( @@ -603,7 +603,8 @@ class FileMetaData::FileMetaDataImpl { ThriftDeserializer deserializer(properties_); deserializer.DeserializeMessage(reinterpret_cast(metadata), - metadata_len, metadata_.get(), footer_decryptor); + metadata_len, metadata_.get(), + footer_decryptor.get()); metadata_len_ = *metadata_len; if (metadata_->__isset.created_by) { @@ -705,7 +706,7 @@ class FileMetaData::FileMetaDataImpl { encryption::kGcmTagLength)); } else { // either plaintext file (when encryptor is null) // or encrypted file with encrypted footer - serializer.Serialize(metadata_.get(), dst, encryptor); + serializer.Serialize(metadata_.get(), dst, encryptor.get()); } } diff --git a/cpp/src/parquet/metadata.h b/cpp/src/parquet/metadata.h index e62b2d187a20b..6609cff48bac2 100644 --- a/cpp/src/parquet/metadata.h +++ b/cpp/src/parquet/metadata.h @@ -25,6 +25,7 @@ #include #include +#include "parquet/encryption/type_fwd.h" #include "parquet/platform.h" #include "parquet/properties.h" #include "parquet/schema.h" @@ -34,15 +35,10 @@ namespace parquet { class ColumnDescriptor; class EncodedStatistics; +class FileCryptoMetaData; class Statistics; class SchemaDescriptor; -class FileCryptoMetaData; -class InternalFileDecryptor; -class Decryptor; -class Encryptor; -class FooterSigningEncryptor; - namespace schema { class ColumnPath; diff --git a/cpp/src/parquet/page_index.cc b/cpp/src/parquet/page_index.cc index 9bae90e5540bd..ec99af17f05a1 100644 --- a/cpp/src/parquet/page_index.cc +++ b/cpp/src/parquet/page_index.cc @@ -17,6 +17,9 @@ #include "parquet/page_index.h" #include "parquet/encoding.h" +#include "parquet/encryption/encryption_internal.h" +#include "parquet/encryption/internal_file_decryptor.h" +#include "parquet/encryption/internal_file_encryptor.h" #include "parquet/exception.h" #include "parquet/metadata.h" #include "parquet/schema.h" @@ -192,13 +195,13 @@ class RowGroupPageIndexReaderImpl : public RowGroupPageIndexReader { const ReaderProperties& properties, int32_t row_group_ordinal, const RowGroupIndexReadRange& index_read_range, - std::shared_ptr file_decryptor) + InternalFileDecryptor* file_decryptor) : input_(input), row_group_metadata_(std::move(row_group_metadata)), properties_(properties), row_group_ordinal_(row_group_ordinal), index_read_range_(index_read_range), - file_decryptor_(std::move(file_decryptor)) {} + file_decryptor_(file_decryptor) {} /// Read column index of a column chunk. std::shared_ptr GetColumnIndex(int32_t i) override { @@ -207,11 +210,6 @@ class RowGroupPageIndexReaderImpl : public RowGroupPageIndexReader { } auto col_chunk = row_group_metadata_->ColumnChunk(i); - std::unique_ptr crypto_metadata = col_chunk->crypto_metadata(); - if (crypto_metadata != nullptr) { - ParquetException::NYI("Cannot read encrypted column index yet"); - } - auto column_index_location = col_chunk->GetColumnIndexLocation(); if (!column_index_location.has_value()) { return nullptr; @@ -232,8 +230,17 @@ class RowGroupPageIndexReaderImpl : public RowGroupPageIndexReader { // uint32_t uint32_t length = static_cast(column_index_location->length); auto descr = row_group_metadata_->schema()->Column(i); + + // Get decryptor of column index if encrypted. + std::shared_ptr decryptor = parquet::GetColumnMetaDecryptor( + col_chunk->crypto_metadata().get(), file_decryptor_); + if (decryptor != nullptr) { + UpdateDecryptor(decryptor, row_group_ordinal_, /*column_ordinal=*/i, + encryption::kColumnIndex); + } + return ColumnIndex::Make(*descr, column_index_buffer_->data() + buffer_offset, length, - properties_); + properties_, decryptor.get()); } /// Read offset index of a column chunk. @@ -243,11 +250,6 @@ class RowGroupPageIndexReaderImpl : public RowGroupPageIndexReader { } auto col_chunk = row_group_metadata_->ColumnChunk(i); - std::unique_ptr crypto_metadata = col_chunk->crypto_metadata(); - if (crypto_metadata != nullptr) { - ParquetException::NYI("Cannot read encrypted offset index yet"); - } - auto offset_index_location = col_chunk->GetOffsetIndexLocation(); if (!offset_index_location.has_value()) { return nullptr; @@ -267,8 +269,17 @@ class RowGroupPageIndexReaderImpl : public RowGroupPageIndexReader { // OffsetIndex::Make() requires the type of serialized thrift message to be // uint32_t uint32_t length = static_cast(offset_index_location->length); + + // Get decryptor of offset index if encrypted. + std::shared_ptr decryptor = + GetColumnMetaDecryptor(col_chunk->crypto_metadata().get(), file_decryptor_); + if (decryptor != nullptr) { + UpdateDecryptor(decryptor, row_group_ordinal_, /*column_ordinal=*/i, + encryption::kOffsetIndex); + } + return OffsetIndex::Make(offset_index_buffer_->data() + buffer_offset, length, - properties_); + properties_, decryptor.get()); } private: @@ -325,7 +336,7 @@ class RowGroupPageIndexReaderImpl : public RowGroupPageIndexReader { RowGroupIndexReadRange index_read_range_; /// File-level decryptor. - std::shared_ptr file_decryptor_; + InternalFileDecryptor* file_decryptor_; /// Buffer to hold the raw bytes of the page index. /// Will be set lazily when the corresponding page index is accessed for the 1st time. @@ -338,11 +349,11 @@ class PageIndexReaderImpl : public PageIndexReader { PageIndexReaderImpl(::arrow::io::RandomAccessFile* input, std::shared_ptr file_metadata, const ReaderProperties& properties, - std::shared_ptr file_decryptor) + InternalFileDecryptor* file_decryptor) : input_(input), file_metadata_(std::move(file_metadata)), properties_(properties), - file_decryptor_(std::move(file_decryptor)) {} + file_decryptor_(file_decryptor) {} std::shared_ptr RowGroup(int i) override { if (i < 0 || i >= file_metadata_->num_row_groups()) { @@ -418,7 +429,7 @@ class PageIndexReaderImpl : public PageIndexReader { const ReaderProperties& properties_; /// File-level decrypter. - std::shared_ptr file_decryptor_; + InternalFileDecryptor* file_decryptor_; /// Coalesced read ranges of page index of row groups that have been suggested by /// WillNeed(). Key is the row group ordinal. @@ -524,9 +535,9 @@ class ColumnIndexBuilderImpl final : public ColumnIndexBuilder { column_index_.__set_boundary_order(ToThrift(boundary_order)); } - void WriteTo(::arrow::io::OutputStream* sink) const override { + void WriteTo(::arrow::io::OutputStream* sink, Encryptor* encryptor) const override { if (state_ == BuilderState::kFinished) { - ThriftSerializer{}.Serialize(&column_index_, sink); + ThriftSerializer{}.Serialize(&column_index_, sink, encryptor); } } @@ -634,9 +645,9 @@ class OffsetIndexBuilderImpl final : public OffsetIndexBuilder { } } - void WriteTo(::arrow::io::OutputStream* sink) const override { + void WriteTo(::arrow::io::OutputStream* sink, Encryptor* encryptor) const override { if (state_ == BuilderState::kFinished) { - ThriftSerializer{}.Serialize(&offset_index_, sink); + ThriftSerializer{}.Serialize(&offset_index_, sink, encryptor); } } @@ -654,7 +665,9 @@ class OffsetIndexBuilderImpl final : public OffsetIndexBuilder { class PageIndexBuilderImpl final : public PageIndexBuilder { public: - explicit PageIndexBuilderImpl(const SchemaDescriptor* schema) : schema_(schema) {} + explicit PageIndexBuilderImpl(const SchemaDescriptor* schema, + InternalFileEncryptor* file_encryptor) + : schema_(schema), file_encryptor_(file_encryptor) {} void AppendRowGroup() override { if (finished_) { @@ -724,12 +737,31 @@ class PageIndexBuilderImpl final : public PageIndexBuilder { } } + std::shared_ptr GetColumnMetaEncryptor(int row_group_ordinal, + int column_ordinal, + int8_t module_type) const { + std::shared_ptr encryptor; + if (file_encryptor_ != nullptr) { + const auto column_path = schema_->Column(column_ordinal)->path()->ToDotString(); + encryptor = file_encryptor_->GetColumnMetaEncryptor(column_path); + if (encryptor != nullptr) { + encryptor->UpdateAad(encryption::CreateModuleAad( + encryptor->file_aad(), module_type, row_group_ordinal, column_ordinal, + kNonPageOrdinal)); + } + } + return encryptor; + } + template void SerializeIndex( const std::vector>>& page_index_builders, ::arrow::io::OutputStream* sink, std::map>>* location) const { const auto num_columns = static_cast(schema_->num_columns()); + constexpr int8_t module_type = std::is_same_v + ? encryption::kColumnIndex + : encryption::kOffsetIndex; /// Serialize the same kind of page index row group by row group. for (size_t row_group = 0; row_group < page_index_builders.size(); ++row_group) { @@ -743,9 +775,13 @@ class PageIndexBuilderImpl final : public PageIndexBuilder { for (size_t column = 0; column < num_columns; ++column) { const auto& column_page_index_builder = row_group_page_index_builders[column]; if (column_page_index_builder != nullptr) { + /// Get encryptor if encryption is enabled. + std::shared_ptr encryptor = GetColumnMetaEncryptor( + static_cast(row_group), static_cast(column), module_type); + /// Try serializing the page index. PARQUET_ASSIGN_OR_THROW(int64_t pos_before_write, sink->Tell()); - column_page_index_builder->WriteTo(sink); + column_page_index_builder->WriteTo(sink, encryptor.get()); PARQUET_ASSIGN_OR_THROW(int64_t pos_after_write, sink->Tell()); int64_t len = pos_after_write - pos_before_write; @@ -769,6 +805,7 @@ class PageIndexBuilderImpl final : public PageIndexBuilder { } const SchemaDescriptor* schema_; + InternalFileEncryptor* file_encryptor_; std::vector>> column_index_builders_; std::vector>> offset_index_builders_; bool finished_ = false; @@ -832,11 +869,12 @@ RowGroupIndexReadRange PageIndexReader::DeterminePageIndexRangesInRowGroup( std::unique_ptr ColumnIndex::Make(const ColumnDescriptor& descr, const void* serialized_index, uint32_t index_len, - const ReaderProperties& properties) { + const ReaderProperties& properties, + Decryptor* decryptor) { format::ColumnIndex column_index; ThriftDeserializer deserializer(properties); deserializer.DeserializeMessage(reinterpret_cast(serialized_index), - &index_len, &column_index); + &index_len, &column_index, decryptor); switch (descr.physical_type()) { case Type::BOOLEAN: return std::make_unique>(descr, @@ -871,20 +909,20 @@ std::unique_ptr ColumnIndex::Make(const ColumnDescriptor& descr, std::unique_ptr OffsetIndex::Make(const void* serialized_index, uint32_t index_len, - const ReaderProperties& properties) { + const ReaderProperties& properties, + Decryptor* decryptor) { format::OffsetIndex offset_index; ThriftDeserializer deserializer(properties); deserializer.DeserializeMessage(reinterpret_cast(serialized_index), - &index_len, &offset_index); + &index_len, &offset_index, decryptor); return std::make_unique(offset_index); } std::shared_ptr PageIndexReader::Make( ::arrow::io::RandomAccessFile* input, std::shared_ptr file_metadata, - const ReaderProperties& properties, - std::shared_ptr file_decryptor) { + const ReaderProperties& properties, InternalFileDecryptor* file_decryptor) { return std::make_shared(input, std::move(file_metadata), - properties, std::move(file_decryptor)); + properties, file_decryptor); } std::unique_ptr ColumnIndexBuilder::Make( @@ -917,8 +955,9 @@ std::unique_ptr OffsetIndexBuilder::Make() { return std::make_unique(); } -std::unique_ptr PageIndexBuilder::Make(const SchemaDescriptor* schema) { - return std::make_unique(schema); +std::unique_ptr PageIndexBuilder::Make( + const SchemaDescriptor* schema, InternalFileEncryptor* file_encryptor) { + return std::make_unique(schema, file_encryptor); } std::ostream& operator<<(std::ostream& out, const PageIndexSelection& selection) { diff --git a/cpp/src/parquet/page_index.h b/cpp/src/parquet/page_index.h index b6ea5fd6abc08..f2ed77cb97c3b 100644 --- a/cpp/src/parquet/page_index.h +++ b/cpp/src/parquet/page_index.h @@ -18,6 +18,7 @@ #pragma once #include "arrow/io/interfaces.h" +#include "parquet/encryption/type_fwd.h" #include "parquet/types.h" #include @@ -25,14 +26,8 @@ namespace parquet { -class ColumnDescriptor; class EncodedStatistics; -class FileMetaData; -class InternalFileDecryptor; struct PageIndexLocation; -class ReaderProperties; -class RowGroupMetaData; -class RowGroupPageIndexReader; /// \brief ColumnIndex is a proxy around format::ColumnIndex. class PARQUET_EXPORT ColumnIndex { @@ -41,7 +36,8 @@ class PARQUET_EXPORT ColumnIndex { static std::unique_ptr Make(const ColumnDescriptor& descr, const void* serialized_index, uint32_t index_len, - const ReaderProperties& properties); + const ReaderProperties& properties, + Decryptor* decryptor = NULLPTR); virtual ~ColumnIndex() = default; @@ -126,7 +122,8 @@ class PARQUET_EXPORT OffsetIndex { /// \brief Create a OffsetIndex from a serialized thrift message. static std::unique_ptr Make(const void* serialized_index, uint32_t index_len, - const ReaderProperties& properties); + const ReaderProperties& properties, + Decryptor* decryptor = NULLPTR); virtual ~OffsetIndex() = default; @@ -187,7 +184,7 @@ class PARQUET_EXPORT PageIndexReader { static std::shared_ptr Make( ::arrow::io::RandomAccessFile* input, std::shared_ptr file_metadata, const ReaderProperties& properties, - std::shared_ptr file_decryptor = NULLPTR); + InternalFileDecryptor* file_decryptor = NULLPTR); /// \brief Get the page index reader of a specific row group. /// \param[in] i row group ordinal to get page index reader. @@ -283,7 +280,9 @@ class PARQUET_EXPORT ColumnIndexBuilder { /// not write any data to the sink. /// /// \param[out] sink output stream to write the serialized message. - virtual void WriteTo(::arrow::io::OutputStream* sink) const = 0; + /// \param[in] encryptor encryptor to encrypt the serialized column index. + virtual void WriteTo(::arrow::io::OutputStream* sink, + Encryptor* encryptor = NULLPTR) const = 0; /// \brief Create a ColumnIndex directly. /// @@ -322,7 +321,9 @@ class PARQUET_EXPORT OffsetIndexBuilder { /// \brief Serialize the offset index thrift message. /// /// \param[out] sink output stream to write the serialized message. - virtual void WriteTo(::arrow::io::OutputStream* sink) const = 0; + /// \param[in] encryptor encryptor to encrypt the serialized offset index. + virtual void WriteTo(::arrow::io::OutputStream* sink, + Encryptor* encryptor = NULLPTR) const = 0; /// \brief Create an OffsetIndex directly. virtual std::unique_ptr Build() const = 0; @@ -332,7 +333,8 @@ class PARQUET_EXPORT OffsetIndexBuilder { class PARQUET_EXPORT PageIndexBuilder { public: /// \brief API convenience to create a PageIndexBuilder. - static std::unique_ptr Make(const SchemaDescriptor* schema); + static std::unique_ptr Make( + const SchemaDescriptor* schema, InternalFileEncryptor* file_encryptor = NULLPTR); virtual ~PageIndexBuilder() = default; diff --git a/cpp/src/parquet/thrift_internal.h b/cpp/src/parquet/thrift_internal.h index 5824a82d5b86d..7491f118d32a0 100644 --- a/cpp/src/parquet/thrift_internal.h +++ b/cpp/src/parquet/thrift_internal.h @@ -403,7 +403,7 @@ class ThriftDeserializer { // set to the actual length of the header. template void DeserializeMessage(const uint8_t* buf, uint32_t* len, T* deserialized_msg, - const std::shared_ptr& decryptor = NULLPTR) { + Decryptor* decryptor = NULLPTR) { if (decryptor == NULLPTR) { // thrift message is not encrypted DeserializeUnencryptedMessage(buf, len, deserialized_msg); @@ -495,7 +495,7 @@ class ThriftSerializer { template int64_t Serialize(const T* obj, ArrowOutputStream* out, - const std::shared_ptr& encryptor = NULLPTR) { + Encryptor* encryptor = NULLPTR) { uint8_t* out_buffer; uint32_t out_length; SerializeToBuffer(obj, &out_length, &out_buffer); @@ -523,8 +523,7 @@ class ThriftSerializer { } int64_t SerializeEncryptedObj(ArrowOutputStream* out, uint8_t* out_buffer, - uint32_t out_length, - const std::shared_ptr& encryptor) { + uint32_t out_length, Encryptor* encryptor) { auto cipher_buffer = std::static_pointer_cast(AllocateBuffer( encryptor->pool(), static_cast(encryptor->CiphertextSizeDelta() + out_length))); diff --git a/cpp/src/parquet/type_fwd.h b/cpp/src/parquet/type_fwd.h index 3e66f32fc0322..da0d0f7bdee96 100644 --- a/cpp/src/parquet/type_fwd.h +++ b/cpp/src/parquet/type_fwd.h @@ -69,6 +69,9 @@ struct ParquetVersion { }; class FileMetaData; +class RowGroupMetaData; + +class ColumnDescriptor; class SchemaDescriptor; class ReaderProperties; From e9730f5971480b942c7394846162c4dfa9145aa9 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Thu, 28 Sep 2023 18:24:26 +0200 Subject: [PATCH 13/56] GH-37934: [Doc][Integration] Document C Data Interface testing (#37935) ### Rationale for this change gh-37537 added integration testing for the C Data Interface, but the documentation was not updated. ### What changes are included in this PR? Add documentation for C Data Interface integration testing. ### Are these changes tested? N/A, only doc changes. ### Are there any user-facing changes? No. * Closes: #37934 Authored-by: Antoine Pitrou Signed-off-by: Antoine Pitrou --- docs/source/developers/java/development.rst | 10 +- docs/source/format/Integration.rst | 114 ++++++++++++++++---- 2 files changed, 97 insertions(+), 27 deletions(-) diff --git a/docs/source/developers/java/development.rst b/docs/source/developers/java/development.rst index 1094d02f1c140..ce7e1704f641c 100644 --- a/docs/source/developers/java/development.rst +++ b/docs/source/developers/java/development.rst @@ -84,11 +84,13 @@ UI Benchmark: Integration Testing =================== -Integration tests can be run via Archery: +Integration tests can be run :ref:`via Archery `. +For example, assuming you only built Arrow Java and want to run the IPC +integration tests, you would do: -.. code-block:: +.. code-block:: console - $ archery integration --with-java true --with-cpp false --with-js false --with-csharp false --with-go false --with-rust false + $ archery integration --run-ipc --with-java 1 Code Style ========== @@ -104,4 +106,4 @@ This checks the code style of all source code under the current directory or fro .. _benchmark: https://github.com/ursacomputing/benchmarks .. _archery: https://github.com/apache/arrow/blob/main/dev/conbench_envs/README.md#L188 .. _conbench: https://github.com/conbench/conbench -.. _checkstyle: https://github.com/apache/arrow/blob/main/java/dev/checkstyle/checkstyle.xml \ No newline at end of file +.. _checkstyle: https://github.com/apache/arrow/blob/main/java/dev/checkstyle/checkstyle.xml diff --git a/docs/source/format/Integration.rst b/docs/source/format/Integration.rst index 5f2341b9c469c..e1160b287e77c 100644 --- a/docs/source/format/Integration.rst +++ b/docs/source/format/Integration.rst @@ -20,32 +20,98 @@ Integration Testing =================== +To ensure Arrow implementations are interoperable between each other, +the Arrow project includes cross-language integration tests which are +regularly run as Continuous Integration tasks. + +The integration tests exercise compliance with several Arrow specifications: +the :ref:`IPC format `, the :ref:`Flight RPC ` protocol, +and the :ref:`C Data Interface `. + +Strategy +-------- + Our strategy for integration testing between Arrow implementations is: -* Test datasets are specified in a custom human-readable, JSON-based format - designed exclusively for Arrow's integration tests -* Each implementation provides a testing executable capable of converting - between the JSON and the binary Arrow file representation -* Each testing executable is used to generate binary Arrow file representations - from the JSON-based test datasets. These results are then used to call the - testing executable of each other implementation to validate the contents - against the corresponding JSON file. - - *ie.* the C++ testing executable generates binary arrow files from JSON - specified datasets. The resulting files are then used as input to the Java - testing executable for validation, confirming that the Java implementation - can correctly read what the C++ implementation wrote. +* Test datasets are specified in a custom human-readable, + :ref:`JSON-based format ` designed exclusively + for Arrow's integration tests. + +* The JSON files are generated by the integration test harness. Different + files are used to represent different data types and features, such as + numerics, lists, dictionary encoding, etc. This makes it easier to pinpoint + incompatibilities than if all data types were represented in a single file. + +* Each implementation provides entry points capable of converting + between the JSON and the Arrow in-memory representation, and of exposing + Arrow in-memory data using the desired format. + +* Each format (whether Arrow IPC, Flight or the C Data Interface) is tested for + all supported pairs of (producer, consumer) implementations. The producer + typically reads a JSON file, converts it to in-memory Arrow data, and exposes + this data using the format under test. The consumer reads the data in the + said format and converts it back to Arrow in-memory data; it also reads + the same JSON file as the producer, and validates that both datasets are + identical. + +Example: IPC format +~~~~~~~~~~~~~~~~~~~ + +Let's say we are testing Arrow C++ as a producer and Arrow Java as a consumer +of the Arrow IPC format. Testing a JSON file would go as follows: + +#. A C++ executable reads the JSON file, converts it into Arrow in-memory data + and writes an Arrow IPC file (the file paths are typically given on the command + line). + +#. A Java executable reads the JSON file, converts it into Arrow in-memory data; + it also reads the Arrow IPC file generated by C++. Finally, it validates that + both Arrow in-memory datasets are equal. + +Example: C Data Interface +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Now, let's say we are testing Arrow Go as a producer and Arrow C# as a consumer +of the Arrow C Data Interface. + +#. The integration testing harness allocates a C + :ref:`ArrowArray ` structure on the heap. + +#. A Go in-process entrypoint (for example a C-compatible function call) + reads a JSON file and exports one of its :term:`record batches ` + into the ``ArrowArray`` structure. + +#. A C# in-process entrypoint reads the same JSON file, converts the + same record batch into Arrow in-memory data; it also imports the + record batch exported by Arrow Go in the ``ArrowArray`` structure. + It validates that both record batches are equal, and then releases the + imported record batch. + +#. Depending on the implementation languages' abilities, the integration + testing harness may assert that memory consumption remained identical + (i.e., that the exported record batch didn't leak). + +#. At the end, the integration testing harness deallocates the ``ArrowArray`` + structure. + +.. _running_integration_tests: Running integration tests ------------------------- The integration test data generator and runner are implemented inside -the :ref:`Archery ` utility. +the :ref:`Archery ` utility. You need to install the ``integration`` +component of archery: + +.. code:: console + + $ pip install -e "dev/archery[integration]" The integration tests are run using the ``archery integration`` command. -.. code-block:: shell +.. code-block:: console - archery integration --help + $ archery integration --help In order to run integration tests, you'll first need to build each component you want to include. See the respective developer docs for C++, Java, etc. @@ -56,26 +122,26 @@ testing. For C++, for example, you need to add ``-DARROW_BUILD_INTEGRATION=ON`` to your cmake command. Depending on which components you have built, you can enable and add them to -the archery test run. For example, if you only have the C++ project built, run: +the archery test run. For example, if you only have the C++ project built +and want to run the Arrow IPC integration tests, run: .. code-block:: shell - archery integration --with-cpp=1 - + archery integration --run-ipc --with-cpp=1 For Java, it may look like: .. code-block:: shell - VERSION=0.11.0-SNAPSHOT + VERSION=14.0.0-SNAPSHOT export ARROW_JAVA_INTEGRATION_JAR=$JAVA_DIR/tools/target/arrow-tools-$VERSION-jar-with-dependencies.jar - archery integration --with-cpp=1 --with-java=1 + archery integration --run-ipc --with-cpp=1 --with-java=1 -To run all tests, including Flight integration tests, do: +To run all tests, including Flight and C Data Interface integration tests, do: .. code-block:: shell - archery integration --with-all --run-flight + archery integration --with-all --run-flight --run-ipc --run-c-data Note that we run these tests in continuous integration, and the CI job uses docker-compose. You may also run the docker-compose job locally, or at least @@ -85,6 +151,8 @@ certain tests. See :ref:`docker-builds` for more information about the project's ``docker-compose`` configuration. +.. _format_json_integration: + JSON test data format --------------------- @@ -415,7 +483,7 @@ will have count 28. For "null" type, ``BufferData`` does not contain any buffers. Archery Integration Test Cases --------------------------------------- +------------------------------ This list can make it easier to understand what manual testing may need to be done for any future Arrow Format changes by knowing what cases the automated From 79abb7362f671f484675b89f19566df861c45f6f Mon Sep 17 00:00:00 2001 From: Nic Crane Date: Thu, 28 Sep 2023 21:40:45 +0100 Subject: [PATCH 14/56] GH-37842: [R] Implement infer_schema.data.frame() (#37843) ### Rationale for this change Users will be able to easily see the schema which their `data.frame` object will have when it's converted into an Arrwo table. ### What changes are included in this PR? Implements `infer_schema()` method for `data.frame` objects. Before: ``` r library(arrow) schema(mtcars) #> Error in UseMethod("infer_schema"): no applicable method for 'infer_schema' applied to an object of class "data.frame" ``` After: ``` r library(arrow) schema(mtcars) #> Schema #> mpg: double #> cyl: double #> disp: double #> hp: double #> drat: double #> wt: double #> qsec: double #> vs: double #> am: double #> gear: double #> carb: double #> #> See $metadata for additional Schema metadata ``` ### Are these changes tested? Yes ### Are there any user-facing changes? Yes * Closes: #37842 Authored-by: Nic Crane Signed-off-by: Nic Crane --- r/NAMESPACE | 1 + r/R/schema.R | 3 +++ r/tests/testthat/test-schema.R | 5 +++++ 3 files changed, 9 insertions(+) diff --git a/r/NAMESPACE b/r/NAMESPACE index 21f88b4180d24..d49255f781f94 100644 --- a/r/NAMESPACE +++ b/r/NAMESPACE @@ -112,6 +112,7 @@ S3method(infer_schema,ArrowTabular) S3method(infer_schema,Dataset) S3method(infer_schema,RecordBatchReader) S3method(infer_schema,arrow_dplyr_query) +S3method(infer_schema,data.frame) S3method(infer_type,ArrowDatum) S3method(infer_type,Expression) S3method(infer_type,blob) diff --git a/r/R/schema.R b/r/R/schema.R index 1ad18e314191e..ac0604b2b345c 100644 --- a/r/R/schema.R +++ b/r/R/schema.R @@ -285,6 +285,9 @@ infer_schema.Dataset <- function(x) x$schema #' @export infer_schema.arrow_dplyr_query <- function(x) implicit_schema(x) +#' @export +infer_schema.data.frame <- function(x) schema(!!!lapply(x, infer_type)) + #' @export names.Schema <- function(x) x$names diff --git a/r/tests/testthat/test-schema.R b/r/tests/testthat/test-schema.R index db91cee330960..b1dc06592955e 100644 --- a/r/tests/testthat/test-schema.R +++ b/r/tests/testthat/test-schema.R @@ -295,9 +295,14 @@ test_that("schema name assignment", { test_that("schema extraction", { skip_if_not_available("dataset") + tbl <- arrow_table(example_data) + expect_equal(schema(example_data), tbl$schema) expect_equal(schema(tbl), tbl$schema) + expect_equal(schema(data.frame(a = 1, a = "x", check.names = FALSE)), schema(a = double(), a = string())) + expect_equal(schema(data.frame()), schema()) + ds <- InMemoryDataset$create(example_data) expect_equal(schema(ds), ds$schema) From 9d3806a27747241c5daf2ecc901986c16962ead2 Mon Sep 17 00:00:00 2001 From: Nic Crane Date: Thu, 28 Sep 2023 21:41:56 +0100 Subject: [PATCH 15/56] GH-34640: [R] Can't read in partitioning column in CSV datasets when both (non-hive) partition and schema supplied (#37658) ### Rationale for this change It wasn't possible to use the partitioning column in the dataset when reading in CSV datasets and supplying both a schema and a partition variable. ### What changes are included in this PR? This PR updates the code which creates the `CSVReadOptions` object and makes sure we don't pass in the partition variable column name as a column name there, as previously this was resulting in an error. ### Are these changes tested? Yes ### Are there any user-facing changes? Yes * Closes: #34640 Lead-authored-by: Nic Crane Co-authored-by: Dewey Dunnington Signed-off-by: Nic Crane --- r/R/dataset-factory.R | 2 +- r/R/dataset-format.R | 31 +++++++++++++++----------- r/tests/testthat/test-dataset-csv.R | 34 +++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 14 deletions(-) diff --git a/r/R/dataset-factory.R b/r/R/dataset-factory.R index adb7353a043b9..d3d4f639e3729 100644 --- a/r/R/dataset-factory.R +++ b/r/R/dataset-factory.R @@ -49,7 +49,7 @@ DatasetFactory$create <- function(x, } if (is.character(format)) { - format <- FileFormat$create(match.arg(format), ...) + format <- FileFormat$create(match.arg(format), partitioning = partitioning, ...) } else { assert_is(format, "FileFormat") } diff --git a/r/R/dataset-format.R b/r/R/dataset-format.R index e1f434d60cd50..5dd00b9344014 100644 --- a/r/R/dataset-format.R +++ b/r/R/dataset-format.R @@ -74,13 +74,14 @@ FileFormat <- R6Class("FileFormat", type = function() dataset___FileFormat__type_name(self) ) ) -FileFormat$create <- function(format, schema = NULL, ...) { + +FileFormat$create <- function(format, schema = NULL, partitioning = NULL, ...) { opt_names <- names(list(...)) if (format %in% c("csv", "text", "txt") || any(opt_names %in% c("delim", "delimiter"))) { - CsvFileFormat$create(schema = schema, ...) + CsvFileFormat$create(schema = schema, partitioning = partitioning, ...) } else if (format == "tsv") { # This delimiter argument is ignored. - CsvFileFormat$create(delimiter = "\t", schema = schema, ...) + CsvFileFormat$create(delimiter = "\t", schema = schema, partitioning = partitioning, ...) } else if (format == "parquet") { ParquetFileFormat$create(...) } else if (format %in% c("ipc", "arrow", "feather")) { # These are aliases for the same thing @@ -189,16 +190,19 @@ JsonFileFormat$create <- function(...) { #' #' @export CsvFileFormat <- R6Class("CsvFileFormat", inherit = FileFormat) -CsvFileFormat$create <- function(...) { +CsvFileFormat$create <- function(..., partitioning = NULL) { + dots <- list(...) - options <- check_csv_file_format_args(dots) - check_schema(options[["schema"]], options[["read_options"]]$column_names) + + options <- check_csv_file_format_args(dots, partitioning = partitioning) + check_schema(options[["schema"]], partitioning, options[["read_options"]]$column_names) dataset___CsvFileFormat__Make(options$parse_options, options$convert_options, options$read_options) } # Check all arguments are valid -check_csv_file_format_args <- function(args) { +check_csv_file_format_args <- function(args, partitioning = NULL) { + options <- list( parse_options = args$parse_options, convert_options = args$convert_options, @@ -223,7 +227,7 @@ check_csv_file_format_args <- function(args) { } if (is.null(args$read_options)) { - options$read_options <- do.call(csv_file_format_read_opts, args) + options$read_options <- do.call(csv_file_format_read_opts, c(args, list(partitioning = partitioning))) } else if (is.list(args$read_options)) { options$read_options <- do.call(CsvReadOptions$create, args$read_options) } @@ -339,7 +343,7 @@ check_ambiguous_options <- function(passed_opts, opts1, opts2) { } } -check_schema <- function(schema, column_names) { +check_schema <- function(schema, partitioning, column_names) { if (!is.null(schema) && !inherits(schema, "Schema")) { abort(paste0( "`schema` must be an object of class 'Schema' not '", @@ -348,7 +352,7 @@ check_schema <- function(schema, column_names) { )) } - schema_names <- names(schema) + schema_names <- setdiff(names(schema), names(partitioning)) if (!is.null(schema) && !identical(schema_names, column_names)) { missing_from_schema <- setdiff(column_names, schema_names) @@ -451,7 +455,8 @@ csv_file_format_convert_opts <- function(...) { do.call(CsvConvertOptions$create, opts) } -csv_file_format_read_opts <- function(schema = NULL, ...) { +csv_file_format_read_opts <- function(schema = NULL, partitioning = NULL, ...) { + opts <- list(...) # Filter out arguments meant for CsvParseOptions/CsvConvertOptions arrow_opts <- c(names(formals(CsvParseOptions$create)), "parse_options") @@ -477,9 +482,9 @@ csv_file_format_read_opts <- function(schema = NULL, ...) { if (!is.null(schema) && null_or_true(opts[["column_names"]]) && null_or_true(opts[["col_names"]])) { if (any(is_readr_opt)) { - opts[["col_names"]] <- names(schema) + opts[["col_names"]] <- setdiff(names(schema), names(partitioning)) } else { - opts[["column_names"]] <- names(schema) + opts[["column_names"]] <- setdiff(names(schema), names(partitioning)) } } diff --git a/r/tests/testthat/test-dataset-csv.R b/r/tests/testthat/test-dataset-csv.R index c83c30ff904ff..ff1712646a472 100644 --- a/r/tests/testthat/test-dataset-csv.R +++ b/r/tests/testthat/test-dataset-csv.R @@ -593,3 +593,37 @@ test_that("CSVReadOptions field access", { expect_equal(options$block_size, 1048576L) expect_equal(options$encoding, "UTF-8") }) + +test_that("GH-34640 - CSV datasets are read in correctly when both schema and partitioning supplied", { + target_schema <- schema( + int = int32(), dbl = float32(), lgl = bool(), chr = utf8(), + fct = utf8(), ts = timestamp(unit = "s"), part = int8() + ) + + ds <- open_dataset( + csv_dir, + partitioning = schema(part = int32()), + format = "csv", + schema = target_schema, + skip = 1 + ) + expect_r6_class(ds$format, "CsvFileFormat") + expect_r6_class(ds$filesystem, "LocalFileSystem") + expect_identical(names(ds), c(names(df1), "part")) + expect_identical(names(collect(ds)), c(names(df1), "part")) + + expect_identical(dim(ds), c(20L, 7L)) + expect_equal(schema(ds), target_schema) + + expect_equal( + ds %>% + select(string = chr, integer = int, part) %>% + filter(integer > 6 & part == 5) %>% + collect() %>% + summarize(mean = mean(as.numeric(integer))), + df1 %>% + select(string = chr, integer = int) %>% + filter(integer > 6) %>% + summarize(mean = mean(integer)) + ) +}) From 3ceb2f1ed871afbecfc481e5cabfd5e846dc5cd6 Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Thu, 28 Sep 2023 23:09:43 +0200 Subject: [PATCH 16/56] GH-37803: [Python][CI] Pin setuptools_scm to fix release verification scripts (#37930) Follow-up on https://github.com/apache/arrow/pull/37819, which missed one place to add a pin for the release verification scripts * Closes: #37803 Authored-by: Joris Van den Bossche Signed-off-by: Sutou Kouhei --- dev/release/verify-release-candidate.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/release/verify-release-candidate.sh b/dev/release/verify-release-candidate.sh index 77b996766f78c..ae28ebe792404 100755 --- a/dev/release/verify-release-candidate.sh +++ b/dev/release/verify-release-candidate.sh @@ -666,7 +666,7 @@ test_python() { show_header "Build and test Python libraries" # Build and test Python - maybe_setup_virtualenv "cython<3" numpy setuptools_scm setuptools || exit 1 + maybe_setup_virtualenv "cython<3" numpy "setuptools_scm<8.0.0" setuptools || exit 1 maybe_setup_conda --file ci/conda_env_python.txt || exit 1 if [ "${USE_CONDA}" -gt 0 ]; then From befcc90defcc6b2fc35e8b3226b1ee38851e0cdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Ne=C4=8Das?= Date: Thu, 28 Sep 2023 23:40:54 +0200 Subject: [PATCH 17/56] GH-21815: [JS] Add support for Duration type (#37341) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Rationale for this change The `Duration` type is currently not supported and trying to deserialize a Table containing the type (e.g. using `tableFromIPC`) fails with `Unrecognized type` error. This PR aims to fix that. ### What changes are included in this PR? - definition of the `Duration` data type - updates to the visitor classes so that things like parsing work correctly - test coverage for the type - documentation update ### Are these changes tested? Yes, I extended the data generator with the new type so that the type is tested by the existing tests. ### Are there any user-facing changes? Yes, I've updated the documentation status page. I also noticed that it was outdated for JavaScript, i.e. there is already support for `Decimal` type so I updated this as well. Closes: https://github.com/apache/arrow/issues/21815 Closes: https://github.com/apache/arrow/issues/35439 * Closes: #21815 Lead-authored-by: František Necas Co-authored-by: ptaylor Signed-off-by: Dominik Moritz --- dev/archery/archery/integration/datagen.py | 3 +- docs/source/status.rst | 4 +- js/src/Arrow.dom.ts | 2 + js/src/Arrow.ts | 2 + js/src/builder.ts | 6 +-- js/src/builder/duration.ts | 46 ++++++++++++++++++++++ js/src/data.ts | 11 ++++++ js/src/enum.ts | 7 +++- js/src/interfaces.ts | 16 ++++++++ js/src/ipc/metadata/json.ts | 6 ++- js/src/ipc/metadata/message.ts | 7 +++- js/src/type.ts | 34 ++++++++++++++++ js/src/visitor.ts | 27 ++++++++++++- js/src/visitor/builderctor.ts | 6 +++ js/src/visitor/bytelength.ts | 5 ++- js/src/visitor/get.ts | 30 ++++++++++++++ js/src/visitor/indexof.ts | 11 ++++++ js/src/visitor/iterator.ts | 11 ++++++ js/src/visitor/jsontypeassembler.ts | 3 ++ js/src/visitor/jsonvectorassembler.ts | 6 ++- js/src/visitor/set.ts | 31 +++++++++++++++ js/src/visitor/typeassembler.ts | 6 +++ js/src/visitor/typecomparator.ts | 18 +++++++++ js/src/visitor/typector.ts | 5 +++ js/src/visitor/vectorassembler.ts | 6 ++- js/src/visitor/vectorloader.ts | 5 ++- js/test/data/tables.ts | 3 +- js/test/generate-test-data.ts | 20 +++++++++- js/test/unit/builders/builder-tests.ts | 4 ++ js/test/unit/generated-data-tests.ts | 4 ++ js/test/unit/visitor-tests.ts | 11 ++++++ 31 files changed, 338 insertions(+), 18 deletions(-) create mode 100644 js/src/builder/duration.ts diff --git a/dev/archery/archery/integration/datagen.py b/dev/archery/archery/integration/datagen.py index 299881c4b613a..8d0cc6b0b01a8 100644 --- a/dev/archery/archery/integration/datagen.py +++ b/dev/archery/archery/integration/datagen.py @@ -1805,8 +1805,7 @@ def _temp_path(): generate_datetime_case(), generate_duration_case() - .skip_tester('C#') - .skip_tester('JS'), # TODO(ARROW-5239): Intervals + JS + .skip_tester('C#'), generate_interval_case() .skip_tester('C#') diff --git a/docs/source/status.rst b/docs/source/status.rst index 6314fd4c8d31f..e2b3852e2229f 100644 --- a/docs/source/status.rst +++ b/docs/source/status.rst @@ -46,7 +46,7 @@ Data Types +-------------------+-------+-------+-------+------------+-------+-------+-------+-------+ | Decimal128 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | +-------------------+-------+-------+-------+------------+-------+-------+-------+-------+ -| Decimal256 | ✓ | ✓ | ✓ | | ✓ | ✓ | ✓ | | +| Decimal256 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | +-------------------+-------+-------+-------+------------+-------+-------+-------+-------+ | Date32/64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +-------------------+-------+-------+-------+------------+-------+-------+-------+-------+ @@ -54,7 +54,7 @@ Data Types +-------------------+-------+-------+-------+------------+-------+-------+-------+-------+ | Timestamp | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | +-------------------+-------+-------+-------+------------+-------+-------+-------+-------+ -| Duration | ✓ | ✓ | ✓ | | | ✓ | ✓ | | +| Duration | ✓ | ✓ | ✓ | ✓ | | ✓ | ✓ | | +-------------------+-------+-------+-------+------------+-------+-------+-------+-------+ | Interval | ✓ | ✓ | ✓ | | | ✓ | ✓ | | +-------------------+-------+-------+-------+------------+-------+-------+-------+-------+ diff --git a/js/src/Arrow.dom.ts b/js/src/Arrow.dom.ts index 2fdef60c1fb55..451bf6acb6186 100644 --- a/js/src/Arrow.dom.ts +++ b/js/src/Arrow.dom.ts @@ -59,6 +59,7 @@ export { Union, DenseUnion, SparseUnion, Dictionary, Interval, IntervalDayTime, IntervalYearMonth, + Duration, DurationSecond, DurationMillisecond, DurationMicrosecond, DurationNanosecond, FixedSizeList, Map_, MapRow, Table, makeTable, tableFromArrays, @@ -86,6 +87,7 @@ export { FixedSizeListBuilder, FloatBuilder, Float16Builder, Float32Builder, Float64Builder, IntervalBuilder, IntervalDayTimeBuilder, IntervalYearMonthBuilder, + DurationBuilder, DurationSecondBuilder, DurationMillisecondBuilder, DurationMicrosecondBuilder, DurationNanosecondBuilder, IntBuilder, Int8Builder, Int16Builder, Int32Builder, Int64Builder, Uint8Builder, Uint16Builder, Uint32Builder, Uint64Builder, ListBuilder, MapBuilder, diff --git a/js/src/Arrow.ts b/js/src/Arrow.ts index 4a6394c266b1b..714861e764ccb 100644 --- a/js/src/Arrow.ts +++ b/js/src/Arrow.ts @@ -48,6 +48,7 @@ export { Union, DenseUnion, SparseUnion, Dictionary, Interval, IntervalDayTime, IntervalYearMonth, + Duration, DurationSecond, DurationMillisecond, DurationMicrosecond, DurationNanosecond, FixedSizeList, Map_ } from './type.js'; @@ -75,6 +76,7 @@ export { IntBuilder, Int8Builder, Int16Builder, Int32Builder, Int64Builder, Uint export { TimeBuilder, TimeSecondBuilder, TimeMillisecondBuilder, TimeMicrosecondBuilder, TimeNanosecondBuilder } from './builder/time.js'; export { TimestampBuilder, TimestampSecondBuilder, TimestampMillisecondBuilder, TimestampMicrosecondBuilder, TimestampNanosecondBuilder } from './builder/timestamp.js'; export { IntervalBuilder, IntervalDayTimeBuilder, IntervalYearMonthBuilder } from './builder/interval.js'; +export { DurationBuilder, DurationSecondBuilder, DurationMillisecondBuilder, DurationMicrosecondBuilder, DurationNanosecondBuilder } from './builder/duration.js'; export { Utf8Builder } from './builder/utf8.js'; export { BinaryBuilder } from './builder/binary.js'; export { ListBuilder } from './builder/list.js'; diff --git a/js/src/builder.ts b/js/src/builder.ts index 90fe3ddcc9477..93510eedf84ff 100644 --- a/js/src/builder.ts +++ b/js/src/builder.ts @@ -21,7 +21,7 @@ import { MapRow, kKeys } from './row/map.js'; import { DataType, strideForType, Float, Int, Decimal, FixedSizeBinary, - Date_, Time, Timestamp, Interval, + Date_, Time, Timestamp, Interval, Duration, Utf8, Binary, List, Map_, } from './type.js'; import { createIsValidFunction } from './builder/valid.js'; @@ -290,7 +290,7 @@ export abstract class Builder { } else if (valueOffsets = _offsets?.flush(length)) { // Variable-width primitives (Binary, Utf8), and Lists // Binary, Utf8 data = _values?.flush(_offsets.last()); - } else { // Fixed-width primitives (Int, Float, Decimal, Time, Timestamp, and Interval) + } else { // Fixed-width primitives (Int, Float, Decimal, Time, Timestamp, Duration and Interval) data = _values?.flush(length); } @@ -342,7 +342,7 @@ export abstract class Builder { (Builder.prototype as any)._isValid = () => true; /** @ignore */ -export abstract class FixedWidthBuilder extends Builder { +export abstract class FixedWidthBuilder extends Builder { constructor(opts: BuilderOptions) { super(opts); this._values = new DataBufferBuilder(new this.ArrayType(0), this.stride); diff --git a/js/src/builder/duration.ts b/js/src/builder/duration.ts new file mode 100644 index 0000000000000..968899ea55b91 --- /dev/null +++ b/js/src/builder/duration.ts @@ -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. + +import { FixedWidthBuilder } from '../builder.js'; +import { Duration, DurationSecond, DurationMillisecond, DurationMicrosecond, DurationNanosecond } from '../type.js'; +import { setDuration, setDurationSecond, setDurationMillisecond, setDurationMicrosecond, setDurationNanosecond } from '../visitor/set.js'; + +/** @ignore */ +export class DurationBuilder extends FixedWidthBuilder { } + +(DurationBuilder.prototype as any)._setValue = setDuration; + +/** @ignore */ +export class DurationSecondBuilder extends DurationBuilder { } + +(DurationSecondBuilder.prototype as any)._setValue = setDurationSecond; + +/** @ignore */ +export class DurationMillisecondBuilder extends DurationBuilder { } + +(DurationMillisecondBuilder.prototype as any)._setValue = setDurationMillisecond; + +/** @ignore */ +export class DurationMicrosecondBuilder extends DurationBuilder { } + +(DurationMicrosecondBuilder.prototype as any)._setValue = setDurationMicrosecond; + +/** @ignore */ +export class DurationNanosecondBuilder extends DurationBuilder { } + +(DurationNanosecondBuilder.prototype as any)._setValue = setDurationNanosecond; diff --git a/js/src/data.ts b/js/src/data.ts index dc423cdb01e1c..1e9df71cff8a7 100644 --- a/js/src/data.ts +++ b/js/src/data.ts @@ -257,6 +257,7 @@ import { Int, Date_, Interval, + Duration, Time, Timestamp, Union, DenseUnion, SparseUnion, @@ -390,6 +391,13 @@ class MakeDataVisitor extends Visitor { const { ['length']: length = data.length / strideForType(type), ['nullCount']: nullCount = props['nullBitmap'] ? -1 : 0, } = props; return new Data(type, offset, length, nullCount, [undefined, data, nullBitmap]); } + public visitDuration(props: DurationDataProps) { + const { ['type']: type, ['offset']: offset = 0 } = props; + const nullBitmap = toUint8Array(props['nullBitmap']); + const data = toArrayBufferView(type.ArrayType, props['data']); + const { ['length']: length = data.length, ['nullCount']: nullCount = props['nullBitmap'] ? -1 : 0, } = props; + return new Data(type, offset, length, nullCount, [undefined, data, nullBitmap]); + } public visitFixedSizeList(props: FixedSizeListDataProps) { const { ['type']: type, ['offset']: offset = 0, ['child']: child = new MakeDataVisitor().visit({ type: type.valueType }) } = props; const nullBitmap = toUint8Array(props['nullBitmap']); @@ -424,6 +432,7 @@ interface Date_DataProps extends DataProps_ { data?: DataBuf interface TimeDataProps extends DataProps_ { data?: DataBuffer } interface TimestampDataProps extends DataProps_ { data?: DataBuffer } interface IntervalDataProps extends DataProps_ { data?: DataBuffer } +interface DurationDataProps extends DataProps_ { data?: DataBuffer } interface FixedSizeBinaryDataProps extends DataProps_ { data?: DataBuffer } interface BinaryDataProps extends DataProps_ { valueOffsets: ValueOffsetsBuffer; data?: DataBuffer } interface Utf8DataProps extends DataProps_ { valueOffsets: ValueOffsetsBuffer; data?: DataBuffer } @@ -446,6 +455,7 @@ export type DataProps = ( T extends Time /* */ ? TimeDataProps : T extends Timestamp /* */ ? TimestampDataProps : T extends Interval /* */ ? IntervalDataProps : + T extends Duration /* */ ? DurationDataProps : T extends FixedSizeBinary /* */ ? FixedSizeBinaryDataProps : T extends Binary /* */ ? BinaryDataProps : T extends Utf8 /* */ ? Utf8DataProps : @@ -471,6 +481,7 @@ export function makeData(props: Date_DataProps): Data; export function makeData(props: TimeDataProps): Data; export function makeData(props: TimestampDataProps): Data; export function makeData(props: IntervalDataProps): Data; +export function makeData(props: DurationDataProps): Data; export function makeData(props: FixedSizeBinaryDataProps): Data; export function makeData(props: BinaryDataProps): Data; export function makeData(props: Utf8DataProps): Data; diff --git a/js/src/enum.ts b/js/src/enum.ts index f5856bc06afbe..4e207dd37cec1 100644 --- a/js/src/enum.ts +++ b/js/src/enum.ts @@ -137,7 +137,7 @@ export enum MessageHeader { * nested type consisting of other data types, or another data type (e.g. a * timestamp encoded as an int64). * - * **Note**: Only enum values 0-17 (NONE through Map) are written to an Arrow + * **Note**: Only enum values 0-18 (NONE through Duration) are written to an Arrow * IPC payload. * * The rest of the values are specified here so TypeScript can narrow the type @@ -174,6 +174,7 @@ export enum Type { FixedSizeBinary = 15, /** Fixed-size binary. Each value occupies the same number of bytes */ FixedSizeList = 16, /** Fixed-size list. Each value occupies the same number of bytes */ Map = 17, /** Map of named logical types */ + Duration = 18, /** Measure of elapsed time in either seconds, miliseconds, microseconds or nanoseconds. */ Dictionary = -1, /** Dictionary aka Category type */ Int8 = -2, @@ -201,6 +202,10 @@ export enum Type { SparseUnion = -24, IntervalDayTime = -25, IntervalYearMonth = -26, + DurationSecond = -27, + DurationMillisecond = -28, + DurationMicrosecond = -29, + DurationNanosecond = -30 } export enum BufferType { diff --git a/js/src/interfaces.ts b/js/src/interfaces.ts index 8d61295919046..95c5adbb2a25e 100644 --- a/js/src/interfaces.ts +++ b/js/src/interfaces.ts @@ -31,6 +31,7 @@ import type { IntBuilder, Int8Builder, Int16Builder, Int32Builder, Int64Builder, import type { TimeBuilder, TimeSecondBuilder, TimeMillisecondBuilder, TimeMicrosecondBuilder, TimeNanosecondBuilder } from './builder/time.js'; import type { TimestampBuilder, TimestampSecondBuilder, TimestampMillisecondBuilder, TimestampMicrosecondBuilder, TimestampNanosecondBuilder } from './builder/timestamp.js'; import type { IntervalBuilder, IntervalDayTimeBuilder, IntervalYearMonthBuilder } from './builder/interval.js'; +import type { DurationBuilder, DurationSecondBuilder, DurationMillisecondBuilder, DurationMicrosecondBuilder, DurationNanosecondBuilder } from './builder/duration.js'; import type { Utf8Builder } from './builder/utf8.js'; import type { BinaryBuilder } from './builder/binary.js'; import type { ListBuilder } from './builder/list.js'; @@ -222,6 +223,11 @@ export type TypeToDataType = { [Type.Interval]: type.Interval; [Type.IntervalDayTime]: type.IntervalDayTime; [Type.IntervalYearMonth]: type.IntervalYearMonth; + [Type.Duration]: type.Duration; + [Type.DurationSecond]: type.DurationSecond; + [Type.DurationMillisecond]: type.DurationMillisecond; + [Type.DurationMicrosecond]: type.DurationMicrosecond; + [Type.DurationNanosecond]: type.DurationNanosecond; [Type.Map]: type.Map_; [Type.List]: type.List; [Type.Struct]: type.Struct; @@ -270,6 +276,11 @@ type TypeToBuilder = { [Type.Interval]: IntervalBuilder; [Type.IntervalDayTime]: IntervalDayTimeBuilder; [Type.IntervalYearMonth]: IntervalYearMonthBuilder; + [Type.Duration]: DurationBuilder; + [Type.DurationSecond]: DurationBuilder; + [Type.DurationMillisecond]: DurationMillisecondBuilder; + [Type.DurationMicrosecond]: DurationMicrosecondBuilder; + [Type.DurationNanosecond]: DurationNanosecondBuilder; [Type.Map]: MapBuilder; [Type.List]: ListBuilder; [Type.Struct]: StructBuilder; @@ -318,6 +329,11 @@ type DataTypeToBuilder = { [Type.Interval]: T extends type.Interval ? IntervalBuilder : never; [Type.IntervalDayTime]: T extends type.IntervalDayTime ? IntervalDayTimeBuilder : never; [Type.IntervalYearMonth]: T extends type.IntervalYearMonth ? IntervalYearMonthBuilder : never; + [Type.Duration]: T extends type.Duration ? DurationBuilder: never; + [Type.DurationSecond]: T extends type.DurationSecond ? DurationSecondBuilder : never; + [Type.DurationMillisecond]: T extends type.DurationMillisecond ? DurationMillisecondBuilder : never; + [Type.DurationMicrosecond]: T extends type.DurationMicrosecond ? DurationMicrosecondBuilder: never; + [Type.DurationNanosecond]: T extends type.DurationNanosecond ? DurationNanosecondBuilder: never; [Type.Map]: T extends type.Map_ ? MapBuilder : never; [Type.List]: T extends type.List ? ListBuilder : never; [Type.Struct]: T extends type.Struct ? StructBuilder : never; diff --git a/js/src/ipc/metadata/json.ts b/js/src/ipc/metadata/json.ts index e5995110f084b..f1f306730ddba 100644 --- a/js/src/ipc/metadata/json.ts +++ b/js/src/ipc/metadata/json.ts @@ -22,7 +22,7 @@ import { DataType, Dictionary, TimeBitWidth, Utf8, Binary, Decimal, FixedSizeBinary, List, FixedSizeList, Map_, Struct, Union, - Bool, Null, Int, Float, Date_, Time, Interval, Timestamp, IntBitWidth, Int32, TKeys, + Bool, Null, Int, Float, Date_, Time, Interval, Timestamp, IntBitWidth, Int32, TKeys, Duration, } from '../../type.js'; import { DictionaryBatch, RecordBatch, FieldNode, BufferRegion } from './message.js'; @@ -185,6 +185,10 @@ function typeFromJSON(f: any, children?: Field[]): DataType { const t = f['type']; return new Interval(IntervalUnit[t['unit']] as any); } + case 'duration': { + const t = f['type']; + return new Duration(TimeUnit[t['unit']] as any); + } case 'union': { const t = f['type']; const [m, ...ms] = (t['mode'] + '').toLowerCase(); diff --git a/js/src/ipc/metadata/message.ts b/js/src/ipc/metadata/message.ts index 6465d3d064720..27c9b92d6897b 100644 --- a/js/src/ipc/metadata/message.ts +++ b/js/src/ipc/metadata/message.ts @@ -36,6 +36,7 @@ import { Date as _Date } from '../../fb/date.js'; import { Time as _Time } from '../../fb/time.js'; import { Timestamp as _Timestamp } from '../../fb/timestamp.js'; import { Interval as _Interval } from '../../fb/interval.js'; +import { Duration as _Duration } from '../../fb/duration.js'; import { Union as _Union } from '../../fb/union.js'; import { FixedSizeBinary as _FixedSizeBinary } from '../../fb/fixed-size-binary.js'; import { FixedSizeList as _FixedSizeList } from '../../fb/fixed-size-list.js'; @@ -57,7 +58,7 @@ import { DataType, Dictionary, TimeBitWidth, Utf8, Binary, Decimal, FixedSizeBinary, List, FixedSizeList, Map_, Struct, Union, - Bool, Null, Int, Float, Date_, Time, Interval, Timestamp, IntBitWidth, Int32, TKeys, + Bool, Null, Int, Float, Date_, Time, Interval, Timestamp, IntBitWidth, Int32, TKeys, Duration, } from '../../type.js'; /** @@ -466,6 +467,10 @@ function decodeFieldType(f: _Field, children?: Field[]): DataType { const t = f.type(new _Interval())!; return new Interval(t.unit()); } + case Type['Duration']: { + const t = f.type(new _Duration())!; + return new Duration(t.unit()); + } case Type['Union']: { const t = f.type(new _Union())!; return new Union(t.mode(), t.typeIdsArray() || [], children || []); diff --git a/js/src/type.ts b/js/src/type.ts index 1dc90c47cbd10..34bbf45bca728 100644 --- a/js/src/type.ts +++ b/js/src/type.ts @@ -63,6 +63,7 @@ export abstract class DataType { construct /** @ignore */ export class IntervalYearMonth extends Interval_ { constructor() { super(IntervalUnit.YEAR_MONTH); } } +/** @ignore */ +type Durations = Type.Duration | Type.DurationSecond | Type.DurationMillisecond | Type.DurationMicrosecond | Type.DurationNanosecond; +/** @ignore */ +export interface Duration extends DataType { + TArray: BigInt64Array; + TValue: bigint; + ArrayType: BigInt64Array; +} + +/** @ignore */ +export class Duration extends DataType { + constructor(public readonly unit: TimeUnit) { + super(); + } + public get typeId() { return Type.Duration as T; } + public toString() { return `Duration<${TimeUnit[this.unit]}>`; } + protected static [Symbol.toStringTag] = ((proto: Duration) => { + (proto).unit = null; + (proto).ArrayType = BigInt64Array; + return proto[Symbol.toStringTag] = 'Duration'; + })(Duration.prototype); +} + +/** @ignore */ +export class DurationSecond extends Duration { constructor() { super(TimeUnit.SECOND); }} +/** @ignore */ +export class DurationMillisecond extends Duration { constructor() { super(TimeUnit.MILLISECOND); }} +/** @ignore */ +export class DurationMicrosecond extends Duration { constructor() { super(TimeUnit.MICROSECOND); }} +/** @ignore */ +export class DurationNanosecond extends Duration { constructor() { super(TimeUnit.NANOSECOND); }} + + /** @ignore */ export interface List extends DataType { TArray: Array; diff --git a/js/src/visitor.ts b/js/src/visitor.ts index 3be50a6d3eacf..c63640b038e47 100644 --- a/js/src/visitor.ts +++ b/js/src/visitor.ts @@ -16,7 +16,7 @@ // under the License. import { Type, Precision, DateUnit, TimeUnit, IntervalUnit, UnionMode } from './enum.js'; -import { DataType, Float, Int, Date_, Interval, Time, Timestamp, Union, } from './type.js'; +import { DataType, Float, Int, Date_, Interval, Time, Timestamp, Union, Duration } from './type.js'; export abstract class Visitor { public visitMany(nodes: any[], ...args: any[][]) { @@ -47,6 +47,7 @@ export abstract class Visitor { public visitUnion(_node: any, ..._args: any[]): any { return null; } public visitDictionary(_node: any, ..._args: any[]): any { return null; } public visitInterval(_node: any, ..._args: any[]): any { return null; } + public visitDuration(_node: any, ... _args: any[]): any { return null; } public visitFixedSizeList(_node: any, ..._args: any[]): any { return null; } public visitMap(_node: any, ..._args: any[]): any { return null; } } @@ -113,6 +114,11 @@ function getVisitFnByTypeId(visitor: Visitor, dtype: Type, throwIfNotFound = tru case Type.Interval: fn = visitor.visitInterval; break; case Type.IntervalDayTime: fn = visitor.visitIntervalDayTime || visitor.visitInterval; break; case Type.IntervalYearMonth: fn = visitor.visitIntervalYearMonth || visitor.visitInterval; break; + case Type.Duration: fn = visitor.visitDuration; break; + case Type.DurationSecond: fn = visitor.visitDurationSecond || visitor.visitDuration; break; + case Type.DurationMillisecond: fn = visitor.visitDurationMillisecond || visitor.visitDuration; break; + case Type.DurationMicrosecond: fn = visitor.visitDurationMicrosecond || visitor.visitDuration; break; + case Type.DurationNanosecond: fn = visitor.visitDurationNanosecond || visitor.visitDuration; break; case Type.FixedSizeList: fn = visitor.visitFixedSizeList; break; case Type.Map: fn = visitor.visitMap; break; } @@ -180,6 +186,15 @@ function inferDType(type: T): Type { } // @ts-ignore return Type.Interval; + case Type.Duration: + switch ((type as any as Duration).unit) { + case TimeUnit.SECOND: return Type.DurationSecond; + case TimeUnit.MILLISECOND: return Type.DurationMillisecond; + case TimeUnit.MICROSECOND: return Type.DurationMicrosecond; + case TimeUnit.NANOSECOND: return Type.DurationNanosecond; + } + // @ts-ignore + return Type.Duration; case Type.Map: return Type.Map; case Type.List: return Type.List; case Type.Struct: return Type.Struct; @@ -239,6 +254,11 @@ export interface Visitor { visitInterval(node: any, ...args: any[]): any; visitIntervalDayTime?(node: any, ...args: any[]): any; visitIntervalYearMonth?(node: any, ...args: any[]): any; + visitDuration(node: any, ...args: any[]): any; + visitDurationSecond(node: any, ...args: any[]): any; + visitDurationMillisecond(node: any, ...args: any[]): any; + visitDurationMicrosecond(node: any, ...args: any[]): any; + visitDurationNanosecond(node: any, ...args: any[]): any; visitFixedSizeList(node: any, ...args: any[]): any; visitMap(node: any, ...args: any[]): any; } @@ -270,3 +290,8 @@ export interface Visitor { (Visitor.prototype as any).visitSparseUnion = null; (Visitor.prototype as any).visitIntervalDayTime = null; (Visitor.prototype as any).visitIntervalYearMonth = null; +(Visitor.prototype as any).visitDuration = null; +(Visitor.prototype as any).visitDurationSecond = null; +(Visitor.prototype as any).visitDurationMillisecond = null; +(Visitor.prototype as any).visitDurationMicrosecond = null; +(Visitor.prototype as any).visitDurationNanosecond = null; diff --git a/js/src/visitor/builderctor.ts b/js/src/visitor/builderctor.ts index 9ce9ae4d4a797..2d20f2a8efd5c 100644 --- a/js/src/visitor/builderctor.ts +++ b/js/src/visitor/builderctor.ts @@ -30,6 +30,7 @@ import { FixedSizeBinaryBuilder } from '../builder/fixedsizebinary.js'; import { FixedSizeListBuilder } from '../builder/fixedsizelist.js'; import { FloatBuilder, Float16Builder, Float32Builder, Float64Builder } from '../builder/float.js'; import { IntervalBuilder, IntervalDayTimeBuilder, IntervalYearMonthBuilder } from '../builder/interval.js'; +import { DurationBuilder, DurationSecondBuilder, DurationMillisecondBuilder, DurationMicrosecondBuilder, DurationNanosecondBuilder } from '../builder/duration.js'; import { IntBuilder, Int8Builder, Int16Builder, Int32Builder, Int64Builder, Uint8Builder, Uint16Builder, Uint32Builder, Uint64Builder } from '../builder/int.js'; import { ListBuilder } from '../builder/list.js'; import { MapBuilder } from '../builder/map.js'; @@ -91,6 +92,11 @@ export class GetBuilderCtor extends Visitor { public visitInterval() { return IntervalBuilder; } public visitIntervalDayTime() { return IntervalDayTimeBuilder; } public visitIntervalYearMonth() { return IntervalYearMonthBuilder; } + public visitDuration() { return DurationBuilder; } + public visitDurationSecond() { return DurationSecondBuilder; } + public visitDurationMillisecond() { return DurationMillisecondBuilder; } + public visitDurationMicrosecond() { return DurationMicrosecondBuilder; } + public visistDurationNanosecond() { return DurationNanosecondBuilder; } public visitFixedSizeList() { return FixedSizeListBuilder; } public visitMap() { return MapBuilder; } } diff --git a/js/src/visitor/bytelength.ts b/js/src/visitor/bytelength.ts index 862808ad54ee9..72d6148a52fd8 100644 --- a/js/src/visitor/bytelength.ts +++ b/js/src/visitor/bytelength.ts @@ -25,7 +25,7 @@ import { TypeToDataType } from '../interfaces.js'; import { Type, TimeUnit, UnionMode } from '../enum.js'; import { DataType, Dictionary, - Float, Int, Date_, Interval, Time, Timestamp, + Float, Int, Date_, Interval, Time, Timestamp, Duration, Bool, Null, Utf8, Binary, Decimal, FixedSizeBinary, List, FixedSizeList, Map_, Struct, Union, DenseUnion, SparseUnion, } from '../type.js'; @@ -75,6 +75,9 @@ export class GetByteLengthVisitor extends Visitor { public visitInterval(data: Data, _: number) { return (data.type.unit + 1) * 4; } + public visitDuration(____: Data, _: number) { + return 8; + } public visitStruct(data: Data, i: number) { return data.children.reduce((total, child) => total + instance.visit(child, i), 0); } diff --git a/js/src/visitor/get.ts b/js/src/visitor/get.ts index 12f8325470bac..5aaaedf51a37e 100644 --- a/js/src/visitor/get.ts +++ b/js/src/visitor/get.ts @@ -34,6 +34,7 @@ import { Interval, IntervalDayTime, IntervalYearMonth, Time, TimeSecond, TimeMillisecond, TimeMicrosecond, TimeNanosecond, Timestamp, TimestampSecond, TimestampMillisecond, TimestampMicrosecond, TimestampNanosecond, + Duration, DurationSecond, DurationMillisecond, DurationMicrosecond, DurationNanosecond, Union, DenseUnion, SparseUnion, } from '../type.js'; @@ -84,6 +85,11 @@ export interface GetVisitor extends Visitor { visitInterval(data: Data, index: number): T['TValue'] | null; visitIntervalDayTime(data: Data, index: number): T['TValue'] | null; visitIntervalYearMonth(data: Data, index: number): T['TValue'] | null; + visitDuration(data: Data, index: number): T['TValue'] | null; + visitDurationSecond(data: Data, index: number): T['TValue'] | null; + visitDurationMillisecond(data: Data, index: number): T['TValue'] | null; + visitDurationMicrosecond(data: Data, index: number): T['TValue'] | null; + visitDurationNanosecond(data: Data, index: number): T['TValue'] | null; visitFixedSizeList(data: Data, index: number): T['TValue'] | null; visitMap(data: Data, index: number): T['TValue'] | null; } @@ -279,6 +285,25 @@ const getIntervalYearMonth = ({ values }: Data, return int32s; }; +/** @ignore */ +const getDurationSecond = ({ values }: Data, index: number): T['TValue'] => values[index]; +/** @ignore */ +const getDurationMillisecond = ({ values }: Data, index: number): T['TValue'] => values[index]; +/** @ignore */ +const getDurationMicrosecond = ({ values }: Data, index: number): T['TValue'] => values[index]; +/** @ignore */ +const getDurationNanosecond = ({ values }: Data, index: number): T['TValue'] => values[index]; +/* istanbul ignore next */ +/** @ignore */ +const getDuration = (data: Data, index: number): T['TValue'] => { + switch (data.type.unit) { + case TimeUnit.SECOND: return getDurationSecond(data as Data, index); + case TimeUnit.MILLISECOND: return getDurationMillisecond(data as Data, index); + case TimeUnit.MICROSECOND: return getDurationMicrosecond(data as Data, index); + case TimeUnit.NANOSECOND: return getDurationNanosecond(data as Data, index); + } +}; + /** @ignore */ const getFixedSizeList = (data: Data, index: number): T['TValue'] => { const { stride, children } = data; @@ -328,6 +353,11 @@ GetVisitor.prototype.visitDictionary = wrapGet(getDictionary); GetVisitor.prototype.visitInterval = wrapGet(getInterval); GetVisitor.prototype.visitIntervalDayTime = wrapGet(getIntervalDayTime); GetVisitor.prototype.visitIntervalYearMonth = wrapGet(getIntervalYearMonth); +GetVisitor.prototype.visitDuration = wrapGet(getDuration); +GetVisitor.prototype.visitDurationSecond = wrapGet(getDurationSecond); +GetVisitor.prototype.visitDurationMillisecond = wrapGet(getDurationMillisecond); +GetVisitor.prototype.visitDurationMicrosecond = wrapGet(getDurationMicrosecond); +GetVisitor.prototype.visitDurationNanosecond = wrapGet(getDurationNanosecond); GetVisitor.prototype.visitFixedSizeList = wrapGet(getFixedSizeList); GetVisitor.prototype.visitMap = wrapGet(getMap); diff --git a/js/src/visitor/indexof.ts b/js/src/visitor/indexof.ts index 654134c6dff04..28dcff20d3bd3 100644 --- a/js/src/visitor/indexof.ts +++ b/js/src/visitor/indexof.ts @@ -31,6 +31,7 @@ import { Interval, IntervalDayTime, IntervalYearMonth, Time, TimeSecond, TimeMillisecond, TimeMicrosecond, TimeNanosecond, Timestamp, TimestampSecond, TimestampMillisecond, TimestampMicrosecond, TimestampNanosecond, + Duration, DurationSecond, DurationMillisecond, DurationMicrosecond, DurationNanosecond, Union, DenseUnion, SparseUnion, } from '../type.js'; @@ -81,6 +82,11 @@ export interface IndexOfVisitor extends Visitor { visitInterval(data: Data, value: T['TValue'] | null, index?: number): number; visitIntervalDayTime(data: Data, value: T['TValue'] | null, index?: number): number; visitIntervalYearMonth(data: Data, value: T['TValue'] | null, index?: number): number; + visitDuration(data: Data, value: T['TValue'] | null, index?: number): number; + visitDurationSecond(data: Data, value: T['TValue'] | null, index?: number): number; + visitDurationMillisecond(data: Data, value: T['TValue'] | null, index?: number): number; + visitDurationMicrosecond(data: Data, value: T['TValue'] | null, index?: number): number; + visitDurationNanosecond(data: Data, value: T['TValue'] | null, index?: number): number; visitFixedSizeList(data: Data, value: T['TValue'] | null, index?: number): number; visitMap(data: Data, value: T['TValue'] | null, index?: number): number; } @@ -191,6 +197,11 @@ IndexOfVisitor.prototype.visitDictionary = indexOfValue; IndexOfVisitor.prototype.visitInterval = indexOfValue; IndexOfVisitor.prototype.visitIntervalDayTime = indexOfValue; IndexOfVisitor.prototype.visitIntervalYearMonth = indexOfValue; +IndexOfVisitor.prototype.visitDuration = indexOfValue; +IndexOfVisitor.prototype.visitDurationSecond = indexOfValue; +IndexOfVisitor.prototype.visitDurationMillisecond = indexOfValue; +IndexOfVisitor.prototype.visitDurationMicrosecond = indexOfValue; +IndexOfVisitor.prototype.visitDurationNanosecond = indexOfValue; IndexOfVisitor.prototype.visitFixedSizeList = indexOfValue; IndexOfVisitor.prototype.visitMap = indexOfValue; diff --git a/js/src/visitor/iterator.ts b/js/src/visitor/iterator.ts index 48021a78e86f6..e38bb907695d0 100644 --- a/js/src/visitor/iterator.ts +++ b/js/src/visitor/iterator.ts @@ -28,6 +28,7 @@ import { Interval, IntervalDayTime, IntervalYearMonth, Time, TimeSecond, TimeMillisecond, TimeMicrosecond, TimeNanosecond, Timestamp, TimestampSecond, TimestampMillisecond, TimestampMicrosecond, TimestampNanosecond, + Duration, DurationSecond, DurationMillisecond, DurationMicrosecond, DurationNanosecond, Union, DenseUnion, SparseUnion, } from '../type.js'; import { ChunkedIterator } from '../util/chunk.js'; @@ -79,6 +80,11 @@ export interface IteratorVisitor extends Visitor { visitInterval(vector: Vector): IterableIterator; visitIntervalDayTime(vector: Vector): IterableIterator; visitIntervalYearMonth(vector: Vector): IterableIterator; + visitDuration(vector: Vector): IterableIterator; + visitDurationSecond(vector: Vector): IterableIterator; + visitDurationMillisecond(vector: Vector): IterableIterator; + visitDurationMicrosecond(vector: Vector): IterableIterator; + visitDurationNanosecond(vector: Vector): IterableIterator; visitFixedSizeList(vector: Vector): IterableIterator; visitMap(vector: Vector): IterableIterator; } @@ -177,6 +183,11 @@ IteratorVisitor.prototype.visitDictionary = vectorIterator; IteratorVisitor.prototype.visitInterval = vectorIterator; IteratorVisitor.prototype.visitIntervalDayTime = vectorIterator; IteratorVisitor.prototype.visitIntervalYearMonth = vectorIterator; +IteratorVisitor.prototype.visitDuration = vectorIterator; +IteratorVisitor.prototype.visitDurationSecond = vectorIterator; +IteratorVisitor.prototype.visitDurationMillisecond = vectorIterator; +IteratorVisitor.prototype.visitDurationMicrosecond = vectorIterator; +IteratorVisitor.prototype.visitDurationNanosecond = vectorIterator; IteratorVisitor.prototype.visitFixedSizeList = vectorIterator; IteratorVisitor.prototype.visitMap = vectorIterator; diff --git a/js/src/visitor/jsontypeassembler.ts b/js/src/visitor/jsontypeassembler.ts index d83edfc24fbd8..6e6cfb07413c3 100644 --- a/js/src/visitor/jsontypeassembler.ts +++ b/js/src/visitor/jsontypeassembler.ts @@ -63,6 +63,9 @@ export class JSONTypeAssembler extends Visitor { public visitInterval({ typeId, unit }: T) { return { 'name': ArrowType[typeId].toLowerCase(), 'unit': IntervalUnit[unit] }; } + public visitDuration({ typeId, unit }: T) { + return { 'name': ArrowType[typeId].toLocaleLowerCase(), 'unit': TimeUnit[unit]}; + } public visitList({ typeId }: T) { return { 'name': ArrowType[typeId].toLowerCase() }; } diff --git a/js/src/visitor/jsonvectorassembler.ts b/js/src/visitor/jsonvectorassembler.ts index 7a617f4afe2c4..55a6b4e2ea390 100644 --- a/js/src/visitor/jsonvectorassembler.ts +++ b/js/src/visitor/jsonvectorassembler.ts @@ -26,7 +26,7 @@ import { UnionMode, DateUnit, TimeUnit } from '../enum.js'; import { BitIterator, getBit, getBool } from '../util/bit.js'; import { DataType, - Float, Int, Date_, Interval, Time, Timestamp, Union, + Float, Int, Date_, Interval, Time, Timestamp, Union, Duration, Bool, Null, Utf8, Binary, Decimal, FixedSizeBinary, List, FixedSizeList, Map_, Struct, IntArray, } from '../type.js'; @@ -52,6 +52,7 @@ export interface JSONVectorAssembler extends Visitor { visitStruct(data: Data): { children: any[] }; visitUnion(data: Data): { children: any[]; TYPE_ID: number[] }; visitInterval(data: Data): { DATA: number[] }; + visitDuration(data: Data): { DATA: string[] }; visitFixedSizeList(data: Data): { children: any[] }; visitMap(data: Data): { children: any[] }; } @@ -146,6 +147,9 @@ export class JSONVectorAssembler extends Visitor { public visitInterval(data: Data) { return { 'DATA': [...data.values] }; } + public visitDuration(data: Data) { + return { 'DATA': [...bigNumsToStrings(data.values, 2)]}; + } public visitFixedSizeList(data: Data) { return { 'children': this.visitMany(data.type.children, data.children) diff --git a/js/src/visitor/set.ts b/js/src/visitor/set.ts index c2d4319911afe..1a0eddc556899 100644 --- a/js/src/visitor/set.ts +++ b/js/src/visitor/set.ts @@ -32,6 +32,7 @@ import { Interval, IntervalDayTime, IntervalYearMonth, Time, TimeSecond, TimeMillisecond, TimeMicrosecond, TimeNanosecond, Timestamp, TimestampSecond, TimestampMillisecond, TimestampMicrosecond, TimestampNanosecond, + Duration, DurationSecond, DurationMillisecond, DurationMicrosecond, DurationNanosecond, Union, DenseUnion, SparseUnion, } from '../type.js'; @@ -82,6 +83,11 @@ export interface SetVisitor extends Visitor { visitInterval(data: Data, index: number, value: T['TValue']): void; visitIntervalDayTime(data: Data, index: number, value: T['TValue']): void; visitIntervalYearMonth(data: Data, index: number, value: T['TValue']): void; + visitDuration(data: Data, index: number, value: T['TValue']): void; + visitDurationSecond(data: Data, index: number, value: T['TValue']): void; + visitDurationMillisecond(data: Data, index: number, value: T['TValue']): void; + visitDurationMicrosecond(data: Data, index: number, value: T['TValue']): void; + visitDurationNanosecond(data: Data, index: number, value: T['TValue']): void; visitFixedSizeList(data: Data, index: number, value: T['TValue']): void; visitMap(data: Data, index: number, value: T['TValue']): void; } @@ -308,6 +314,26 @@ export const setIntervalDayTime = ({ values }: Data({ values }: Data, index: number, value: T['TValue']): void => { values[index] = (value[0] * 12) + (value[1] % 12); }; +/** @ignore */ +export const setDurationSecond = ({ values }: Data, index: number, value: T['TValue']): void => { values[index] = value; }; +/** @ignore */ +export const setDurationMillisecond = ({ values }: Data, index: number, value: T['TValue']): void => { values[index] = value; }; +/** @ignore */ +export const setDurationMicrosecond = ({ values }: Data, index: number, value: T['TValue']): void => { values[index] = value; }; +/** @ignore */ +export const setDurationNanosecond = ({ values }: Data, index: number, value: T['TValue']): void => { values[index] = value; }; +/* istanbul ignore next */ +/** @ignore */ +export const setDuration = (data: Data, index: number, value: T['TValue']): void => { + switch (data.type.unit) { + case TimeUnit.SECOND: return setDurationSecond(data as Data, index, value as DurationSecond['TValue']); + case TimeUnit.MILLISECOND: return setDurationMillisecond(data as Data, index, value as DurationMillisecond['TValue']); + case TimeUnit.MICROSECOND: return setDurationMicrosecond(data as Data, index, value as DurationMicrosecond['TValue']); + case TimeUnit.NANOSECOND: return setDurationNanosecond(data as Data, index, value as DurationNanosecond['TValue']); + } +}; + + /** @ignore */ const setFixedSizeList = (data: Data, index: number, value: T['TValue']): void => { const { stride } = data; @@ -364,6 +390,11 @@ SetVisitor.prototype.visitDictionary = wrapSet(setDictionary); SetVisitor.prototype.visitInterval = wrapSet(setIntervalValue); SetVisitor.prototype.visitIntervalDayTime = wrapSet(setIntervalDayTime); SetVisitor.prototype.visitIntervalYearMonth = wrapSet(setIntervalYearMonth); +SetVisitor.prototype.visitDuration = wrapSet(setDuration); +SetVisitor.prototype.visitDurationSecond = wrapSet(setDurationSecond); +SetVisitor.prototype.visitDurationMillisecond = wrapSet(setDurationMillisecond); +SetVisitor.prototype.visitDurationMicrosecond = wrapSet(setDurationMicrosecond); +SetVisitor.prototype.visitDurationNanosecond = wrapSet(setDurationNanosecond); SetVisitor.prototype.visitFixedSizeList = wrapSet(setFixedSizeList); SetVisitor.prototype.visitMap = wrapSet(setMap); diff --git a/js/src/visitor/typeassembler.ts b/js/src/visitor/typeassembler.ts index c84e3930f64f5..c2262d20531b9 100644 --- a/js/src/visitor/typeassembler.ts +++ b/js/src/visitor/typeassembler.ts @@ -32,6 +32,7 @@ import { Date } from '../fb/date.js'; import { Time } from '../fb/time.js'; import { Timestamp } from '../fb/timestamp.js'; import { Interval } from '../fb/interval.js'; +import { Duration } from '../fb/duration.js'; import { List } from '../fb/list.js'; import { Struct_ as Struct } from '../fb/struct-.js'; import { Union } from '../fb/union.js'; @@ -109,6 +110,11 @@ export class TypeAssembler extends Visitor { Interval.addUnit(b, node.unit); return Interval.endInterval(b); } + public visitDuration(node: T, b: Builder) { + Duration.startDuration(b); + Duration.addUnit(b, node.unit); + return Duration.endDuration(b); + } public visitList(_node: T, b: Builder) { List.startList(b); return List.endList(b); diff --git a/js/src/visitor/typecomparator.ts b/js/src/visitor/typecomparator.ts index a77c4020961ce..1de8e218dae4f 100644 --- a/js/src/visitor/typecomparator.ts +++ b/js/src/visitor/typecomparator.ts @@ -28,6 +28,7 @@ import { Interval, IntervalDayTime, IntervalYearMonth, Time, TimeSecond, TimeMillisecond, TimeMicrosecond, TimeNanosecond, Timestamp, TimestampSecond, TimestampMillisecond, TimestampMicrosecond, TimestampNanosecond, + Duration, DurationSecond, DurationMillisecond, DurationMicrosecond, DurationNanosecond, Union, DenseUnion, SparseUnion, } from '../type.js'; @@ -77,6 +78,11 @@ export interface TypeComparator extends Visitor { visitInterval(type: T, other?: DataType | null): other is T; visitIntervalDayTime(type: T, other?: DataType | null): other is T; visitIntervalYearMonth(type: T, other?: DataType | null): other is T; + visitDuration(type: T, other?: DataType | null): other is T; + visitDurationSecond(type: T, other?: DataType | null): other is T; + visitDurationMillisecond(type: T, other?: DataType | null): other is T; + visitDurationMicrosecond(type: T, other?: DataType | null): other is T; + visitDurationNanosecond(type: T, other?: DataType | null): other is T; visitFixedSizeList(type: T, other?: DataType | null): other is T; visitMap(type: T, other?: DataType | null): other is T; } @@ -202,6 +208,13 @@ function compareInterval(type: T, other?: DataType | null): ); } +function compareDuration(type: T, other?: DataType | null): other is T { + return (type === other) || ( + compareConstructor(type, other) && + type.unit === other.unit + ); +} + function compareFixedSizeList(type: T, other?: DataType | null): other is T { return (type === other) || ( compareConstructor(type, other) && @@ -261,6 +274,11 @@ TypeComparator.prototype.visitDictionary = compareDictionary; TypeComparator.prototype.visitInterval = compareInterval; TypeComparator.prototype.visitIntervalDayTime = compareInterval; TypeComparator.prototype.visitIntervalYearMonth = compareInterval; +TypeComparator.prototype.visitDuration = compareDuration; +TypeComparator.prototype.visitDurationSecond = compareDuration; +TypeComparator.prototype.visitDurationMillisecond = compareDuration; +TypeComparator.prototype.visitDurationMicrosecond = compareDuration; +TypeComparator.prototype.visitDurationNanosecond = compareDuration; TypeComparator.prototype.visitFixedSizeList = compareFixedSizeList; TypeComparator.prototype.visitMap = compareMap; diff --git a/js/src/visitor/typector.ts b/js/src/visitor/typector.ts index c825a61dbadfb..077f66592fbfb 100644 --- a/js/src/visitor/typector.ts +++ b/js/src/visitor/typector.ts @@ -74,6 +74,11 @@ export class GetDataTypeConstructor extends Visitor { public visitInterval() { return type.Interval; } public visitIntervalDayTime() { return type.IntervalDayTime; } public visitIntervalYearMonth() { return type.IntervalYearMonth; } + public visitDuration() { return type.Duration; } + public visitDurationSecond() { return type.DurationSecond; } + public visitDurationMillisecond() { return type.DurationMillisecond; } + public visitDurationMicrosecond() { return type.DurationMicrosecond; } + public visitDurationNanosecond() { return type.DurationNanosecond; } public visitFixedSizeList() { return type.FixedSizeList; } public visitMap() { return type.Map_; } } diff --git a/js/src/visitor/vectorassembler.ts b/js/src/visitor/vectorassembler.ts index dbf778c4c3631..949463272e718 100644 --- a/js/src/visitor/vectorassembler.ts +++ b/js/src/visitor/vectorassembler.ts @@ -26,7 +26,7 @@ import { packBools, truncateBitmap } from '../util/bit.js'; import { BufferRegion, FieldNode } from '../ipc/metadata/message.js'; import { DataType, Dictionary, - Float, Int, Date_, Interval, Time, Timestamp, Union, + Float, Int, Date_, Interval, Time, Timestamp, Union, Duration, Bool, Null, Utf8, Binary, Decimal, FixedSizeBinary, List, FixedSizeList, Map_, Struct, } from '../type.js'; @@ -51,6 +51,7 @@ export interface VectorAssembler extends Visitor { visitStruct(data: Data): this; visitUnion(data: Data): this; visitInterval(data: Data): this; + visitDuration(data: Data): this; visitFixedSizeList(data: Data): this; visitMap(data: Data): this; } @@ -195,7 +196,7 @@ function assembleBoolVector(this: VectorAssembler, data: Data } /** @ignore */ -function assembleFlatVector(this: VectorAssembler, data: Data) { +function assembleFlatVector(this: VectorAssembler, data: Data) { return addBuffer.call(this, data.values.subarray(0, data.length * data.stride)); } @@ -243,5 +244,6 @@ VectorAssembler.prototype.visitList = assembleListVector; VectorAssembler.prototype.visitStruct = assembleNestedVector; VectorAssembler.prototype.visitUnion = assembleUnion; VectorAssembler.prototype.visitInterval = assembleFlatVector; +VectorAssembler.prototype.visitDuration = assembleFlatVector; VectorAssembler.prototype.visitFixedSizeList = assembleListVector; VectorAssembler.prototype.visitMap = assembleListVector; diff --git a/js/src/visitor/vectorloader.ts b/js/src/visitor/vectorloader.ts index cb4bc2829274f..db34edad9a1c1 100644 --- a/js/src/visitor/vectorloader.ts +++ b/js/src/visitor/vectorloader.ts @@ -115,6 +115,9 @@ export class VectorLoader extends Visitor { public visitInterval(type: T, { length, nullCount } = this.nextFieldNode()) { return makeData({ type, length, nullCount, nullBitmap: this.readNullBitmap(type, nullCount), data: this.readData(type) }); } + public visitDuration(type: T, { length, nullCount } = this.nextFieldNode()) { + return makeData({ type, length, nullCount, nullBitmap: this.readNullBitmap(type, nullCount), data: this.readData(type) }); + } public visitFixedSizeList(type: T, { length, nullCount } = this.nextFieldNode()) { return makeData({ type, length, nullCount, nullBitmap: this.readNullBitmap(type, nullCount), 'child': this.visit(type.children[0]) }); } @@ -157,7 +160,7 @@ export class JSONVectorLoader extends VectorLoader { const { sources } = this; if (DataType.isTimestamp(type)) { return toArrayBufferView(Uint8Array, Int64.convertArray(sources[offset] as string[])); - } else if ((DataType.isInt(type) || DataType.isTime(type)) && type.bitWidth === 64) { + } else if ((DataType.isInt(type) || DataType.isTime(type)) && type.bitWidth === 64 || DataType.isDuration(type)) { return toArrayBufferView(Uint8Array, Int64.convertArray(sources[offset] as string[])); } else if (DataType.isDate(type) && type.unit === DateUnit.MILLISECOND) { return toArrayBufferView(Uint8Array, Int64.convertArray(sources[offset] as string[])); diff --git a/js/test/data/tables.ts b/js/test/data/tables.ts index e4d859e0a69b7..28aed7e4feccf 100644 --- a/js/test/data/tables.ts +++ b/js/test/data/tables.ts @@ -30,7 +30,8 @@ const valueVectorGeneratorNames = [ 'float16', 'float32', 'float64', 'utf8', 'binary', 'fixedSizeBinary', 'dateDay', 'dateMillisecond', 'timestampSecond', 'timestampMillisecond', 'timestampMicrosecond', 'timestampNanosecond', 'timeSecond', 'timeMillisecond', 'timeMicrosecond', 'timeNanosecond', 'decimal', - 'dictionary', 'intervalDayTime', 'intervalYearMonth' + 'dictionary', 'intervalDayTime', 'intervalYearMonth', + 'durationSecond', 'durationMillisecond', 'durationMicrosecond', 'durationNanosecond', ]; const vectorGeneratorNames = [...valueVectorGeneratorNames, ...listVectorGeneratorNames, ...nestedVectorGeneratorNames]; diff --git a/js/test/generate-test-data.ts b/js/test/generate-test-data.ts index a03b22c54c770..15fb715a31f95 100644 --- a/js/test/generate-test-data.ts +++ b/js/test/generate-test-data.ts @@ -36,6 +36,7 @@ import { Union, DenseUnion, SparseUnion, Dictionary, Interval, IntervalDayTime, IntervalYearMonth, + Duration, DurationSecond, DurationMillisecond, DurationMicrosecond, DurationNanosecond, FixedSizeList, Map_, DateUnit, TimeUnit, UnionMode, @@ -58,6 +59,7 @@ interface TestDataVectorGenerator extends Visitor { visit(type: T, length?: number, nullCount?: number): GeneratedVector; visit(type: T, length?: number, nullCount?: number): GeneratedVector; visit(type: T, length?: number, nullCount?: number): GeneratedVector; + visit(type: T, length?: number, nullCount?: number): GeneratedVector; visit(type: T, length?: number, nullCount?: number, child?: Vector): GeneratedVector; visit(type: T, length?: number, nullCount?: number, child?: Vector): GeneratedVector; visit(type: T, length?: number, nullCount?: number, dictionary?: Vector): GeneratedVector; @@ -84,6 +86,7 @@ interface TestDataVectorGenerator extends Visitor { visitUnion: typeof generateUnion; visitDictionary: typeof generateDictionary; visitInterval: typeof generateInterval; + visitDuration: typeof generateDuration; visitFixedSizeList: typeof generateFixedSizeList; visitMap: typeof generateMap; } @@ -108,6 +111,7 @@ TestDataVectorGenerator.prototype.visitStruct = generateStruct; TestDataVectorGenerator.prototype.visitUnion = generateUnion; TestDataVectorGenerator.prototype.visitDictionary = generateDictionary; TestDataVectorGenerator.prototype.visitInterval = generateInterval; +TestDataVectorGenerator.prototype.visitDuration = generateDuration; TestDataVectorGenerator.prototype.visitFixedSizeList = generateFixedSizeList; TestDataVectorGenerator.prototype.visitMap = generateMap; @@ -230,11 +234,15 @@ export const sparseUnion = (length = 100, nullCount = Math.trunc(length * 0.2), export const dictionary = (length = 100, nullCount = Math.trunc(length * 0.2), dict: T = new Utf8(), keys: TKey = new Int32()) => vectorGenerator.visit(new Dictionary(dict, keys), length, nullCount); export const intervalDayTime = (length = 100, nullCount = Math.trunc(length * 0.2)) => vectorGenerator.visit(new IntervalDayTime(), length, nullCount); export const intervalYearMonth = (length = 100, nullCount = Math.trunc(length * 0.2)) => vectorGenerator.visit(new IntervalYearMonth(), length, nullCount); +export const durationSecond = (length = 100, nullCount = Math.trunc(length * 0.2)) => vectorGenerator.visit(new DurationSecond(), length, nullCount); +export const durationMillisecond = (length = 100, nullCount = Math.trunc(length * 0.2)) => vectorGenerator.visit(new DurationMillisecond(), length, nullCount); +export const durationMicrosecond = (length = 100, nullCount = Math.trunc(length * 0.2)) => vectorGenerator.visit(new DurationMicrosecond(), length, nullCount); +export const durationNanosecond = (length = 100, nullCount = Math.trunc(length * 0.2)) => vectorGenerator.visit(new DurationNanosecond(), length, nullCount); export const fixedSizeList = (length = 100, nullCount = Math.trunc(length * 0.2), listSize = 2, child = defaultListChild) => vectorGenerator.visit(new FixedSizeList(listSize, child), length, nullCount); export const map = (length = 100, nullCount = Math.trunc(length * 0.2), child: Field> = defaultMapChild()) => vectorGenerator.visit(new Map_(child), length, nullCount); export const vecs = { - null_, bool, int8, int16, int32, int64, uint8, uint16, uint32, uint64, float16, float32, float64, utf8, binary, fixedSizeBinary, dateDay, dateMillisecond, timestampSecond, timestampMillisecond, timestampMicrosecond, timestampNanosecond, timeSecond, timeMillisecond, timeMicrosecond, timeNanosecond, decimal, list, struct, denseUnion, sparseUnion, dictionary, intervalDayTime, intervalYearMonth, fixedSizeList, map + null_, bool, int8, int16, int32, int64, uint8, uint16, uint32, uint64, float16, float32, float64, utf8, binary, fixedSizeBinary, dateDay, dateMillisecond, timestampSecond, timestampMillisecond, timestampMicrosecond, timestampNanosecond, timeSecond, timeMillisecond, timeMicrosecond, timeNanosecond, decimal, list, struct, denseUnion, sparseUnion, dictionary, intervalDayTime, intervalYearMonth, fixedSizeList, map, durationSecond, durationMillisecond, durationMicrosecond, durationNanosecond } as { [k: string]: (...args: any[]) => any }; function generateNull(this: TestDataVectorGenerator, type: T, length = 100): GeneratedVector { @@ -421,6 +429,16 @@ function generateInterval(this: TestDataVectorGenerator, typ return { values, vector: new Vector([makeData({ type, length, nullCount, nullBitmap, data })]) }; } +function generateDuration(this: TestDataVectorGenerator, type: T, length = 100, nullCount = Math.trunc(length * 0.2)): GeneratedVector { + const nullBitmap = createBitmap(length, nullCount); + const multiple = type.unit === TimeUnit.NANOSECOND ? 1000000000 : + type.unit === TimeUnit.MICROSECOND ? 1000000 : + type.unit === TimeUnit.MILLISECOND ? 1000 : 1; + const values: bigint[] = []; + const data = createTime64(length, nullBitmap, multiple, values); + return { values: () => values, vector: new Vector([makeData({ type, length, nullCount, nullBitmap, data })]) }; +} + function generateList(this: TestDataVectorGenerator, type: T, length = 100, nullCount = Math.trunc(length * 0.2), child = this.visit(type.children[0].type, length * 3, nullCount * 3)): GeneratedVector { const childVec = child.vector; const nullBitmap = createBitmap(length, nullCount); diff --git a/js/test/unit/builders/builder-tests.ts b/js/test/unit/builders/builder-tests.ts index a73183a7a5d47..b261e4f815e3a 100644 --- a/js/test/unit/builders/builder-tests.ts +++ b/js/test/unit/builders/builder-tests.ts @@ -64,6 +64,10 @@ describe('Generated Test Data', () => { describe('DictionaryBuilder', () => { validateBuilder(generate.dictionary); }); describe('IntervalDayTimeBuilder', () => { validateBuilder(generate.intervalDayTime); }); describe('IntervalYearMonthBuilder', () => { validateBuilder(generate.intervalYearMonth); }); + describe('DurationSecondBuilder', () => { validateBuilder(generate.durationSecond); }); + describe('DurationMillisecondBuilder', () => { validateBuilder(generate.durationMillisecond); }); + describe('DurationMicrosecondBuilder', () => { validateBuilder(generate.durationMicrosecond); }); + describe('DurationNanosecondBuilder', () => { validateBuilder(generate.durationNanosecond); }); describe('FixedSizeListBuilder', () => { validateBuilder(generate.fixedSizeList); }); describe('MapBuilder', () => { validateBuilder(generate.map); }); }); diff --git a/js/test/unit/generated-data-tests.ts b/js/test/unit/generated-data-tests.ts index 90cf0d598aa6f..d64c7c188d3ed 100644 --- a/js/test/unit/generated-data-tests.ts +++ b/js/test/unit/generated-data-tests.ts @@ -58,6 +58,10 @@ describe('Generated Test Data', () => { describe('Dictionary', () => { validateVector(generate.dictionary()); }); describe('IntervalDayTime', () => { validateVector(generate.intervalDayTime()); }); describe('IntervalYearMonth', () => { validateVector(generate.intervalYearMonth()); }); + describe('DurationSecond', () => { validateVector(generate.durationSecond()); }); + describe('DurationMillisecond', () => { validateVector(generate.durationMillisecond()); }); + describe('DurationMicrosecond', () => { validateVector(generate.durationMicrosecond()); }); + describe('DurationNanosecond', () => { validateVector(generate.durationNanosecond()); }); describe('FixedSizeList', () => { validateVector(generate.fixedSizeList()); }); describe('Map', () => { validateVector(generate.map()); }); }); diff --git a/js/test/unit/visitor-tests.ts b/js/test/unit/visitor-tests.ts index 645fcc60f8d90..8a7ba1ed778aa 100644 --- a/js/test/unit/visitor-tests.ts +++ b/js/test/unit/visitor-tests.ts @@ -25,6 +25,7 @@ import { Interval, IntervalDayTime, IntervalYearMonth, Time, TimeSecond, TimeMillisecond, TimeMicrosecond, TimeNanosecond, Timestamp, TimestampSecond, TimestampMillisecond, TimestampMicrosecond, TimestampNanosecond, + Duration, DurationSecond, DurationMillisecond, DurationMicrosecond, DurationNanosecond, Union, DenseUnion, SparseUnion, } from 'apache-arrow'; @@ -46,6 +47,7 @@ class BasicVisitor extends Visitor { public visitUnion(type: T) { return (this.type = type); } public visitDictionary(type: T) { return (this.type = type); } public visitInterval(type: T) { return (this.type = type); } + public visitDuration(type: T) { return (this.type = type); } public visitFixedSizeList(type: T) { return (this.type = type); } public visitMap(type: T) { return (this.type = type); } } @@ -86,6 +88,10 @@ class FeatureVisitor extends Visitor { public visitDictionary(type: T) { return (this.type = type); } public visitIntervalDayTime(type: T) { return (this.type = type); } public visitIntervalYearMonth(type: T) { return (this.type = type); } + public visitDurationSecond(type: T) { return (this.type = type); } + public visitDurationMillisecond(type: T) { return (this.type = type); } + public visitDurationMicrosecond(type: T) { return (this.type = type); } + public visitDurationNanosecond(type: T) { return (this.type = type); } public visitFixedSizeList(type: T) { return (this.type = type); } public visitMap(type: T) { return (this.type = type); } } @@ -109,6 +115,7 @@ describe('Visitor', () => { test(`visits Union types`, () => validateBasicVisitor(new Union(0, [] as any[], [] as any[]))); test(`visits Dictionary types`, () => validateBasicVisitor(new Dictionary(null as any, null as any))); test(`visits Interval types`, () => validateBasicVisitor(new Interval(0))); + test(`visits Duration types`, () => validateBasicVisitor(new Duration(0))); test(`visits FixedSizeList types`, () => validateBasicVisitor(new FixedSizeList(2, null as any))); test(`visits Map types`, () => validateBasicVisitor(new Map_(new Field('', new Struct<{ key: Utf8; value: Int }>([ new Field('key', new Utf8()), new Field('value', new Int8()) @@ -158,6 +165,10 @@ describe('Visitor', () => { test(`visits IntervalDayTime types`, () => validateFeatureVisitor(new IntervalDayTime())); test(`visits IntervalYearMonth types`, () => validateFeatureVisitor(new IntervalYearMonth())); test(`visits FixedSizeList types`, () => validateFeatureVisitor(new FixedSizeList(2, null as any))); + test(`visits DurationSecond types`, () => validateFeatureVisitor(new DurationSecond())); + test(`visits DurationMillisecond types`, () => validateFeatureVisitor(new DurationMillisecond())); + test(`visits DurationMicrosecond types`, () => validateFeatureVisitor(new DurationMicrosecond())); + test(`visits DurationNanosecond types`, () => validateFeatureVisitor(new DurationNanosecond())); test(`visits Map types`, () => validateFeatureVisitor(new Map_(new Field('', new Struct<{ key: Utf8; value: Int }>([ new Field('key', new Utf8()), new Field('value', new Int8()) ] as any[]))))); From 80b351cc99881dc864c9dc8850a9e67379a3f657 Mon Sep 17 00:00:00 2001 From: Nic Crane Date: Fri, 29 Sep 2023 09:53:39 +0100 Subject: [PATCH 18/56] MINOR: [R] Bump versions file for navigating between docs versions (#37928) ### Rationale for this change Versions files needed bumping with the 13.0.01 release ### What changes are included in this PR? Increasing version numbers ### Are these changes tested? No ### Are there any user-facing changes? No Authored-by: Nic Crane Signed-off-by: Nic Crane --- r/pkgdown/assets/versions.html | 5 +++-- r/pkgdown/assets/versions.json | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/r/pkgdown/assets/versions.html b/r/pkgdown/assets/versions.html index 31f393a27785d..8ba513a98c85b 100644 --- a/r/pkgdown/assets/versions.html +++ b/r/pkgdown/assets/versions.html @@ -1,7 +1,8 @@ -

12.0.1.9000 (dev)

-

12.0.1.1 (release)

+

13.0.0.9000 (dev)

+

13.0.0.1 (release)

+

12.0.1.1

11.0.0.3

10.0.1

9.0.0

diff --git a/r/pkgdown/assets/versions.json b/r/pkgdown/assets/versions.json index 565f67b9730a4..b7c6984e3c660 100644 --- a/r/pkgdown/assets/versions.json +++ b/r/pkgdown/assets/versions.json @@ -4,7 +4,7 @@ "version": "dev/" }, { - "name": "13.0.0 (release)", + "name": "13.0.0.1 (release)", "version": "" }, { From c703b874417d1165b8afc0a42265d5513d5786d7 Mon Sep 17 00:00:00 2001 From: Jacob Wujciak-Jens Date: Fri, 29 Sep 2023 11:20:59 +0200 Subject: [PATCH 19/56] MINOR: [CI][Dev] Fix crossbow badge url (#37946) Github has changed the badge url so all crossbow badges where showing up as grey. Authored-by: Jacob Wujciak-Jens Signed-off-by: Sutou Kouhei --- dev/archery/archery/crossbow/reports.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/archery/archery/crossbow/reports.py b/dev/archery/archery/crossbow/reports.py index 1cf19841c6939..ea10e75ad3478 100644 --- a/dev/archery/archery/crossbow/reports.py +++ b/dev/archery/archery/crossbow/reports.py @@ -284,7 +284,7 @@ class CommentReport(Report): 'github': _markdown_badge.format( title='Github Actions', badge=( - 'https://github.com/{repo}/workflows/Crossbow/' + 'https://github.com/{repo}/actions/workflows/crossbow.yml/' 'badge.svg?branch={branch}' ), ), From 141559816eea8474ed96680a60eceae574d499c3 Mon Sep 17 00:00:00 2001 From: Nic Crane Date: Fri, 29 Sep 2023 13:31:38 +0100 Subject: [PATCH 20/56] GH-37950: [R] tests fail on R < 4.0 due to test calling data.frame() without specifying stringsAsFactors=FALSE (#37951) ### Rationale for this change Tests failing on R < 4.0 builds due to the default value of the the `data.frame()` parameter `stringsAsFactors` between older and newer versions of R ### What changes are included in this PR? Update a test using `data.frame()` to manually specify the value of `stringsAsFactors` as `FALSE`. ### Are these changes tested? No ### Are there any user-facing changes? No * Closes: #37950 Authored-by: Nic Crane Signed-off-by: Nic Crane --- r/tests/testthat/test-schema.R | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/r/tests/testthat/test-schema.R b/r/tests/testthat/test-schema.R index b1dc06592955e..15342add38fae 100644 --- a/r/tests/testthat/test-schema.R +++ b/r/tests/testthat/test-schema.R @@ -300,7 +300,11 @@ test_that("schema extraction", { expect_equal(schema(example_data), tbl$schema) expect_equal(schema(tbl), tbl$schema) - expect_equal(schema(data.frame(a = 1, a = "x", check.names = FALSE)), schema(a = double(), a = string())) + expect_equal( + schema(data.frame(a = 1, a = "x", check.names = FALSE, stringsAsFactors = FALSE)), + schema(a = double(), a = string()) + ) + expect_equal(schema(data.frame()), schema()) ds <- InMemoryDataset$create(example_data) From 72c6497dd02f1d0c3caeff54fdc7bf4c3b846a70 Mon Sep 17 00:00:00 2001 From: Nic Crane Date: Fri, 29 Sep 2023 13:32:41 +0100 Subject: [PATCH 21/56] GH-37813: [R] add quoted_na argument to open_delim_dataset() (#37828) ### Rationale for this change The `open_delim_dataset()` family of functions were implemented to have the same arguments as the `read_delim_arrow()` functions where possible, but `quoted_na` was missed. ### What changes are included in this PR? Adding `quoted_na` to those functions. ### Are these changes tested? Yes ### Are there any user-facing changes? Yes **This PR includes breaking changes to public APIs.** Empty strings in input datasets now default to being read in by `open_delim_dataset()` and its derivates as NAs and not empty string * Closes: #37813 Authored-by: Nic Crane Signed-off-by: Nic Crane --- r/R/dataset-format.R | 15 ++++++++++----- r/R/dataset.R | 13 ++++++++----- r/man/open_delim_dataset.Rd | 15 +++++++++++---- r/tests/testthat/test-dataset-csv.R | 14 ++++++++++++-- 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/r/R/dataset-format.R b/r/R/dataset-format.R index 5dd00b9344014..cdaaf08827bfd 100644 --- a/r/R/dataset-format.R +++ b/r/R/dataset-format.R @@ -239,7 +239,7 @@ check_unsupported_args <- function(args) { opt_names <- get_opt_names(args) # Filter out arguments meant for CsvConvertOptions/CsvReadOptions - supported_convert_opts <- c(names(formals(CsvConvertOptions$create)), "na") + supported_convert_opts <- c(names(formals(CsvConvertOptions$create)), "na", "quoted_na") supported_read_opts <- c( names(formals(CsvReadOptions$create)), @@ -312,7 +312,8 @@ check_unrecognised_args <- function(opts) { readr_opts <- c( names(formals(readr_to_csv_parse_options)), names(formals(readr_to_csv_read_options)), - "na" + "na", + "quoted_na" ) is_arrow_opt <- !is.na(pmatch(opt_names, arrow_opts)) @@ -394,7 +395,7 @@ check_schema <- function(schema, partitioning, column_names) { csv_file_format_parse_opts <- function(...) { opts <- list(...) # Filter out arguments meant for CsvConvertOptions/CsvReadOptions - convert_opts <- c(names(formals(CsvConvertOptions$create)), "na", "convert_options") + convert_opts <- c(names(formals(CsvConvertOptions$create)), "na", "quoted_na", "convert_options") read_opts <- c( names(formals(CsvReadOptions$create)), names(formals(readr_to_csv_read_options)), @@ -452,6 +453,11 @@ csv_file_format_convert_opts <- function(...) { opts[["na"]] <- NULL } + if ("quoted_na" %in% names(opts)) { + opts[["strings_can_be_null"]] <- opts[["quoted_na"]] + opts[["quoted_na"]] <- NULL + } + do.call(CsvConvertOptions$create, opts) } @@ -461,7 +467,7 @@ csv_file_format_read_opts <- function(schema = NULL, partitioning = NULL, ...) { # Filter out arguments meant for CsvParseOptions/CsvConvertOptions arrow_opts <- c(names(formals(CsvParseOptions$create)), "parse_options") readr_opts <- names(formals(readr_to_csv_parse_options)) - convert_opts <- c(names(formals(CsvConvertOptions$create)), "na", "convert_options") + convert_opts <- c(names(formals(CsvConvertOptions$create)), "na", "quoted_na", "convert_options") opts[arrow_opts] <- NULL opts[readr_opts] <- NULL opts[convert_opts] <- NULL @@ -473,7 +479,6 @@ csv_file_format_read_opts <- function(schema = NULL, partitioning = NULL, ...) { is_arrow_opt <- !is.na(match(opt_names, arrow_opts)) is_readr_opt <- !is.na(match(opt_names, readr_opts)) - check_ambiguous_options(opt_names, arrow_opts, readr_opts) null_or_true <- function(x) { diff --git a/r/R/dataset.R b/r/R/dataset.R index b7728ff897fff..9d91839c220bb 100644 --- a/r/R/dataset.R +++ b/r/R/dataset.R @@ -240,7 +240,6 @@ open_dataset <- function(sources, #' @section Options currently supported by [read_delim_arrow()] which are not supported here: #' * `file` (instead, please specify files in `sources`) #' * `col_select` (instead, subset columns after dataset creation) -#' * `quoted_na` #' * `as_data_frame` (instead, convert to data frame after dataset creation) #' * `parse_options` #' @@ -276,7 +275,8 @@ open_delim_dataset <- function(sources, skip = 0L, convert_options = NULL, read_options = NULL, - timestamp_parsers = NULL) { + timestamp_parsers = NULL, + quoted_na = TRUE) { open_dataset( sources = sources, schema = schema, @@ -296,7 +296,8 @@ open_delim_dataset <- function(sources, skip = skip, convert_options = convert_options, read_options = read_options, - timestamp_parsers = timestamp_parsers + timestamp_parsers = timestamp_parsers, + quoted_na = quoted_na ) } @@ -318,7 +319,8 @@ open_csv_dataset <- function(sources, skip = 0L, convert_options = NULL, read_options = NULL, - timestamp_parsers = NULL) { + timestamp_parsers = NULL, + quoted_na = TRUE) { mc <- match.call() mc$delim <- "," mc[[1]] <- get("open_delim_dataset", envir = asNamespace("arrow")) @@ -343,7 +345,8 @@ open_tsv_dataset <- function(sources, skip = 0L, convert_options = NULL, read_options = NULL, - timestamp_parsers = NULL) { + timestamp_parsers = NULL, + quoted_na = TRUE) { mc <- match.call() mc$delim <- "\t" mc[[1]] <- get("open_delim_dataset", envir = asNamespace("arrow")) diff --git a/r/man/open_delim_dataset.Rd b/r/man/open_delim_dataset.Rd index 2bfd047040a8b..cf08302cc6436 100644 --- a/r/man/open_delim_dataset.Rd +++ b/r/man/open_delim_dataset.Rd @@ -24,7 +24,8 @@ open_delim_dataset( skip = 0L, convert_options = NULL, read_options = NULL, - timestamp_parsers = NULL + timestamp_parsers = NULL, + quoted_na = TRUE ) open_csv_dataset( @@ -44,7 +45,8 @@ open_csv_dataset( skip = 0L, convert_options = NULL, read_options = NULL, - timestamp_parsers = NULL + timestamp_parsers = NULL, + quoted_na = TRUE ) open_tsv_dataset( @@ -64,7 +66,8 @@ open_tsv_dataset( skip = 0L, convert_options = NULL, read_options = NULL, - timestamp_parsers = NULL + timestamp_parsers = NULL, + quoted_na = TRUE ) } \arguments{ @@ -178,6 +181,11 @@ starting from the beginning of this vector. Possible values are: \item a character vector of \link[base:strptime]{strptime} parse strings \item a list of \link{TimestampParser} objects }} + +\item{quoted_na}{Should missing values inside quotes be treated as missing +values (the default) or strings. (Note that this is different from the +the Arrow C++ default for the corresponding convert option, +\code{strings_can_be_null}.)} } \description{ A wrapper around \link{open_dataset} which explicitly includes parameters mirroring \code{\link[=read_csv_arrow]{read_csv_arrow()}}, @@ -189,7 +197,6 @@ for opening single files and functions for opening datasets. \itemize{ \item \code{file} (instead, please specify files in \code{sources}) \item \code{col_select} (instead, subset columns after dataset creation) -\item \code{quoted_na} \item \code{as_data_frame} (instead, convert to data frame after dataset creation) \item \code{parse_options} } diff --git a/r/tests/testthat/test-dataset-csv.R b/r/tests/testthat/test-dataset-csv.R index ff1712646a472..e8e7c61fc8848 100644 --- a/r/tests/testthat/test-dataset-csv.R +++ b/r/tests/testthat/test-dataset-csv.R @@ -220,7 +220,7 @@ test_that("readr parse options", { # With not yet supported readr parse options expect_error( - open_dataset(tsv_dir, partitioning = "part", delim = "\t", quoted_na = TRUE), + open_dataset(tsv_dir, partitioning = "part", delim = "\t", col_select = "integer"), "supported" ) @@ -253,7 +253,7 @@ test_that("readr parse options", { tsv_dir, partitioning = "part", format = "text", - quo = "\"", + del = "," ), "Ambiguous" ) @@ -561,6 +561,16 @@ test_that("open_delim_dataset params passed through to open_dataset", { expect_named(ds, c("int", "dbl", "lgl", "chr", "fct", "ts")) + # quoted_na + dst_dir <- make_temp_dir() + dst_file <- file.path(dst_dir, "data.csv") + writeLines("text,num\none,1\ntwo,2\n,3\nfour,4", dst_file) + ds <- open_csv_dataset(dst_dir, quoted_na = TRUE) %>% collect() + expect_equal(ds$text, c("one", "two", NA, "four")) + + ds <- open_csv_dataset(dst_dir, quoted_na = FALSE) %>% collect() + expect_equal(ds$text, c("one", "two", "", "four")) + # timestamp_parsers skip("GH-33708: timestamp_parsers don't appear to be working properly") From a0041027902ac71f00572d5b31022ee98502ed6a Mon Sep 17 00:00:00 2001 From: James Duong Date: Fri, 29 Sep 2023 06:11:12 -0700 Subject: [PATCH 22/56] GH-37702: [Java] Add vector validation consistent with C++ (#37942) ### Rationale for this change Make vector validation code more consistent with C++. Add missing checks and have the entry point be the same so that the code is easier to read/write when working with both languages. ### What changes are included in this PR? Make vector validation more consistent with Array::Validate() in C++: * Add validate() and validateFull() instance methods to vectors. * Validate that VarCharVector and LargeVarCharVector contents are valid UTF-8. * Validate that DecimalVector and Decimal256Vector contents fit within the supplied precision and scale. * Validate that NullVectors contain only nulls. * Validate that FixedSizeBinaryVector values have the correct length. ### Are these changes tested? Yes. ### Are there any user-facing changes? No. * Closes: #37702 Authored-by: James Duong Signed-off-by: David Li --- .../arrow/vector/BaseFixedWidthVector.java | 7 ++ .../vector/BaseLargeVariableWidthVector.java | 7 ++ .../arrow/vector/BaseVariableWidthVector.java | 7 ++ .../apache/arrow/vector/Decimal256Vector.java | 13 ++++ .../apache/arrow/vector/DecimalVector.java | 13 ++++ .../arrow/vector/FixedSizeBinaryVector.java | 13 ++++ .../arrow/vector/LargeVarCharVector.java | 12 +++ .../org/apache/arrow/vector/ValueVector.java | 9 +++ .../apache/arrow/vector/VarCharVector.java | 12 +++ .../arrow/vector/util/DecimalUtility.java | 10 ++- .../org/apache/arrow/vector/util/Text.java | 50 ++++++++++--- .../validate/ValidateVectorDataVisitor.java | 5 ++ .../vector/validate/TestValidateVector.java | 14 ++++ .../validate/TestValidateVectorFull.java | 74 +++++++++++++++++++ 14 files changed, 233 insertions(+), 13 deletions(-) diff --git a/java/vector/src/main/java/org/apache/arrow/vector/BaseFixedWidthVector.java b/java/vector/src/main/java/org/apache/arrow/vector/BaseFixedWidthVector.java index 223ae9aa8cb1c..04a038a0b5dfd 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/BaseFixedWidthVector.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/BaseFixedWidthVector.java @@ -550,6 +550,13 @@ private void setReaderAndWriterIndex() { } } + /** + * Validate the scalar values held by this vector. + */ + public void validateScalars() { + // No validation by default. + } + /** * Construct a transfer pair of this vector and another vector of same type. * @param ref name of the target vector diff --git a/java/vector/src/main/java/org/apache/arrow/vector/BaseLargeVariableWidthVector.java b/java/vector/src/main/java/org/apache/arrow/vector/BaseLargeVariableWidthVector.java index 90694db830cd6..4d5a8a5119c53 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/BaseLargeVariableWidthVector.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/BaseLargeVariableWidthVector.java @@ -643,6 +643,13 @@ public ArrowBuf[] getBuffers(boolean clear) { return buffers; } + /** + * Validate the scalar values held by this vector. + */ + public void validateScalars() { + // No validation by default. + } + /** * Construct a transfer pair of this vector and another vector of same type. * @param ref name of the target vector diff --git a/java/vector/src/main/java/org/apache/arrow/vector/BaseVariableWidthVector.java b/java/vector/src/main/java/org/apache/arrow/vector/BaseVariableWidthVector.java index 2a89590bf8440..d7f5ff05a935d 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/BaseVariableWidthVector.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/BaseVariableWidthVector.java @@ -685,6 +685,13 @@ public ArrowBuf[] getBuffers(boolean clear) { return buffers; } + /** + * Validate the scalar values held by this vector. + */ + public void validateScalars() { + // No validation by default. + } + /** * Construct a transfer pair of this vector and another vector of same type. * @param ref name of the target vector diff --git a/java/vector/src/main/java/org/apache/arrow/vector/Decimal256Vector.java b/java/vector/src/main/java/org/apache/arrow/vector/Decimal256Vector.java index 70a895ff40496..79a9badc3955d 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/Decimal256Vector.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/Decimal256Vector.java @@ -35,6 +35,7 @@ import org.apache.arrow.vector.types.pojo.FieldType; import org.apache.arrow.vector.util.DecimalUtility; import org.apache.arrow.vector.util.TransferPair; +import org.apache.arrow.vector.validate.ValidateUtil; /** @@ -527,6 +528,18 @@ public void setSafe(int index, int isSet, long start, ArrowBuf buffer) { set(index, isSet, start, buffer); } + @Override + public void validateScalars() { + for (int i = 0; i < getValueCount(); ++i) { + BigDecimal value = getObject(i); + if (value != null) { + ValidateUtil.validateOrThrow(DecimalUtility.checkPrecisionAndScaleNoThrow(value, getPrecision(), getScale()), + "Invalid value for Decimal256Vector at position " + i + ". Value does not fit in precision " + + getPrecision() + " and scale " + getScale() + "."); + } + } + } + /*----------------------------------------------------------------* | | | vector transfer | diff --git a/java/vector/src/main/java/org/apache/arrow/vector/DecimalVector.java b/java/vector/src/main/java/org/apache/arrow/vector/DecimalVector.java index 6a3ec60afc52e..d1a3bfc3afb10 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/DecimalVector.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/DecimalVector.java @@ -35,6 +35,7 @@ import org.apache.arrow.vector.types.pojo.FieldType; import org.apache.arrow.vector.util.DecimalUtility; import org.apache.arrow.vector.util.TransferPair; +import org.apache.arrow.vector.validate.ValidateUtil; /** * DecimalVector implements a fixed width vector (16 bytes) of @@ -526,6 +527,18 @@ public void setSafe(int index, int isSet, long start, ArrowBuf buffer) { set(index, isSet, start, buffer); } + @Override + public void validateScalars() { + for (int i = 0; i < getValueCount(); ++i) { + BigDecimal value = getObject(i); + if (value != null) { + ValidateUtil.validateOrThrow(DecimalUtility.checkPrecisionAndScaleNoThrow(value, getPrecision(), getScale()), + "Invalid value for DecimalVector at position " + i + ". Value does not fit in precision " + + getPrecision() + " and scale " + getScale() + "."); + } + } + } + /*----------------------------------------------------------------* | | | vector transfer | diff --git a/java/vector/src/main/java/org/apache/arrow/vector/FixedSizeBinaryVector.java b/java/vector/src/main/java/org/apache/arrow/vector/FixedSizeBinaryVector.java index 3ce2bb77ccc55..967d560d78dea 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/FixedSizeBinaryVector.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/FixedSizeBinaryVector.java @@ -31,6 +31,7 @@ import org.apache.arrow.vector.types.pojo.Field; import org.apache.arrow.vector.types.pojo.FieldType; import org.apache.arrow.vector.util.TransferPair; +import org.apache.arrow.vector.validate.ValidateUtil; /** * FixedSizeBinaryVector implements a fixed width vector of @@ -320,6 +321,18 @@ public static byte[] get(final ArrowBuf buffer, final int index, final int byteW return dst; } + @Override + public void validateScalars() { + for (int i = 0; i < getValueCount(); ++i) { + byte[] value = get(i); + if (value != null) { + ValidateUtil.validateOrThrow(value.length == byteWidth, + "Invalid value for FixedSizeBinaryVector at position " + i + ". The length was " + + value.length + " but the length of each element should be " + byteWidth + "."); + } + } + } + /*----------------------------------------------------------------* | | | vector transfer | diff --git a/java/vector/src/main/java/org/apache/arrow/vector/LargeVarCharVector.java b/java/vector/src/main/java/org/apache/arrow/vector/LargeVarCharVector.java index 1f8d9b7d3a85c..e9472c9f2c71e 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/LargeVarCharVector.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/LargeVarCharVector.java @@ -27,6 +27,7 @@ import org.apache.arrow.vector.types.pojo.FieldType; import org.apache.arrow.vector.util.Text; import org.apache.arrow.vector.util.TransferPair; +import org.apache.arrow.vector.validate.ValidateUtil; /** * LargeVarCharVector implements a variable width vector of VARCHAR @@ -261,6 +262,17 @@ public void setSafe(int index, Text text) { setSafe(index, text.getBytes(), 0, text.getLength()); } + @Override + public void validateScalars() { + for (int i = 0; i < getValueCount(); ++i) { + byte[] value = get(i); + if (value != null) { + ValidateUtil.validateOrThrow(Text.validateUTF8NoThrow(value), + "Non-UTF-8 data in VarCharVector at position " + i + "."); + } + } + } + /*----------------------------------------------------------------* | | | vector transfer | diff --git a/java/vector/src/main/java/org/apache/arrow/vector/ValueVector.java b/java/vector/src/main/java/org/apache/arrow/vector/ValueVector.java index aa29c29314e33..462b512c65436 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/ValueVector.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/ValueVector.java @@ -29,6 +29,7 @@ import org.apache.arrow.vector.types.pojo.Field; import org.apache.arrow.vector.util.CallBack; import org.apache.arrow.vector.util.TransferPair; +import org.apache.arrow.vector.util.ValueVectorUtility; /** * An abstraction that is used to store a sequence of values in an individual column. @@ -282,4 +283,12 @@ public interface ValueVector extends Closeable, Iterable { * @return the name of the vector. */ String getName(); + + default void validate() { + ValueVectorUtility.validate(this); + } + + default void validateFull() { + ValueVectorUtility.validateFull(this); + } } diff --git a/java/vector/src/main/java/org/apache/arrow/vector/VarCharVector.java b/java/vector/src/main/java/org/apache/arrow/vector/VarCharVector.java index bc5c68b29f310..2c83893819a1e 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/VarCharVector.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/VarCharVector.java @@ -29,6 +29,7 @@ import org.apache.arrow.vector.types.pojo.FieldType; import org.apache.arrow.vector.util.Text; import org.apache.arrow.vector.util.TransferPair; +import org.apache.arrow.vector.validate.ValidateUtil; /** * VarCharVector implements a variable width vector of VARCHAR @@ -261,6 +262,17 @@ public void setSafe(int index, Text text) { setSafe(index, text.getBytes(), 0, text.getLength()); } + @Override + public void validateScalars() { + for (int i = 0; i < getValueCount(); ++i) { + byte[] value = get(i); + if (value != null) { + ValidateUtil.validateOrThrow(Text.validateUTF8NoThrow(value), + "Non-UTF-8 data in VarCharVector at position " + i + "."); + } + } + } + /*----------------------------------------------------------------* | | | vector transfer | diff --git a/java/vector/src/main/java/org/apache/arrow/vector/util/DecimalUtility.java b/java/vector/src/main/java/org/apache/arrow/vector/util/DecimalUtility.java index 137ac746f4aee..a81169b8f7d73 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/util/DecimalUtility.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/util/DecimalUtility.java @@ -95,11 +95,19 @@ public static boolean checkPrecisionAndScale(BigDecimal value, int vectorPrecisi } if (value.precision() > vectorPrecision) { throw new UnsupportedOperationException("BigDecimal precision can not be greater than that in the Arrow " + - "vector: " + value.precision() + " > " + vectorPrecision); + "vector: " + value.precision() + " > " + vectorPrecision); } return true; } + /** + * Check that the BigDecimal scale equals the vectorScale and that the BigDecimal precision is + * less than or equal to the vectorPrecision. Return true if so, otherwise return false. + */ + public static boolean checkPrecisionAndScaleNoThrow(BigDecimal value, int vectorPrecision, int vectorScale) { + return value.scale() == vectorScale && value.precision() < vectorPrecision; + } + /** * Check that the decimal scale equals the vectorScale and that the decimal precision is * less than or equal to the vectorPrecision. If not, then an UnsupportedOperationException is diff --git a/java/vector/src/main/java/org/apache/arrow/vector/util/Text.java b/java/vector/src/main/java/org/apache/arrow/vector/util/Text.java index b479305c6e39b..778af0ca956df 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/util/Text.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/util/Text.java @@ -30,6 +30,7 @@ import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.Arrays; +import java.util.Optional; import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.core.JsonGenerator; @@ -466,6 +467,16 @@ public static ByteBuffer encode(String string, boolean replace) private static final int TRAIL_BYTE = 2; + /** + * Check if a byte array contains valid utf-8. + * + * @param utf8 byte array + * @return true if the input is valid UTF-8. False otherwise. + */ + public static boolean validateUTF8NoThrow(byte[] utf8) { + return !validateUTF8Internal(utf8, 0, utf8.length).isPresent(); + } + /** * Check if a byte array contains valid utf-8. * @@ -484,8 +495,22 @@ public static void validateUTF8(byte[] utf8) throws MalformedInputException { * @param len the length of the byte sequence * @throws MalformedInputException if the byte array contains invalid bytes */ - public static void validateUTF8(byte[] utf8, int start, int len) - throws MalformedInputException { + public static void validateUTF8(byte[] utf8, int start, int len) throws MalformedInputException { + Optional result = validateUTF8Internal(utf8, start, len); + if (result.isPresent()) { + throw new MalformedInputException(result.get()); + } + } + + /** + * Check to see if a byte array is valid utf-8. + * + * @param utf8 the array of bytes + * @param start the offset of the first byte in the array + * @param len the length of the byte sequence + * @return the position where a malformed byte occurred or Optional.empty() if the byte array was valid UTF-8. + */ + private static Optional validateUTF8Internal(byte[] utf8, int start, int len) { int count = start; int leadByte = 0; int length = 0; @@ -501,51 +526,51 @@ public static void validateUTF8(byte[] utf8, int start, int len) switch (length) { case 0: // check for ASCII if (leadByte > 0x7F) { - throw new MalformedInputException(count); + return Optional.of(count); } break; case 1: if (leadByte < 0xC2 || leadByte > 0xDF) { - throw new MalformedInputException(count); + return Optional.of(count); } state = TRAIL_BYTE_1; break; case 2: if (leadByte < 0xE0 || leadByte > 0xEF) { - throw new MalformedInputException(count); + return Optional.of(count); } state = TRAIL_BYTE_1; break; case 3: if (leadByte < 0xF0 || leadByte > 0xF4) { - throw new MalformedInputException(count); + return Optional.of(count); } state = TRAIL_BYTE_1; break; default: // too long! Longest valid UTF-8 is 4 bytes (lead + three) // or if < 0 we got a trail byte in the lead byte position - throw new MalformedInputException(count); + return Optional.of(count); } // switch (length) break; case TRAIL_BYTE_1: if (leadByte == 0xF0 && aByte < 0x90) { - throw new MalformedInputException(count); + return Optional.of(count); } if (leadByte == 0xF4 && aByte > 0x8F) { - throw new MalformedInputException(count); + return Optional.of(count); } if (leadByte == 0xE0 && aByte < 0xA0) { - throw new MalformedInputException(count); + return Optional.of(count); } if (leadByte == 0xED && aByte > 0x9F) { - throw new MalformedInputException(count); + return Optional.of(count); } // falls through to regular trail-byte test!! case TRAIL_BYTE: if (aByte < 0x80 || aByte > 0xBF) { - throw new MalformedInputException(count); + return Optional.of(count); } if (--length == 0) { state = LEAD_BYTE; @@ -558,6 +583,7 @@ public static void validateUTF8(byte[] utf8, int start, int len) } // switch (state) count++; } + return Optional.empty(); } /** diff --git a/java/vector/src/main/java/org/apache/arrow/vector/validate/ValidateVectorDataVisitor.java b/java/vector/src/main/java/org/apache/arrow/vector/validate/ValidateVectorDataVisitor.java index cdeb4f1eaa1ca..6d33be7a0dbac 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/validate/ValidateVectorDataVisitor.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/validate/ValidateVectorDataVisitor.java @@ -85,18 +85,21 @@ private void validateTypeBuffer(ArrowBuf typeBuf, int valueCount) { @Override public Void visit(BaseFixedWidthVector vector, Void value) { + vector.validateScalars(); return null; } @Override public Void visit(BaseVariableWidthVector vector, Void value) { validateOffsetBuffer(vector, vector.getValueCount()); + vector.validateScalars(); return null; } @Override public Void visit(BaseLargeVariableWidthVector vector, Void value) { validateLargeOffsetBuffer(vector, vector.getValueCount()); + vector.validateScalars(); return null; } @@ -169,6 +172,8 @@ public Void visit(DenseUnionVector vector, Void value) { @Override public Void visit(NullVector vector, Void value) { + ValidateUtil.validateOrThrow(vector.getNullCount() == vector.getValueCount(), + "NullVector should have only null entries."); return null; } diff --git a/java/vector/src/test/java/org/apache/arrow/vector/validate/TestValidateVector.java b/java/vector/src/test/java/org/apache/arrow/vector/validate/TestValidateVector.java index 2354b281ed41d..20492036dab99 100644 --- a/java/vector/src/test/java/org/apache/arrow/vector/validate/TestValidateVector.java +++ b/java/vector/src/test/java/org/apache/arrow/vector/validate/TestValidateVector.java @@ -251,6 +251,20 @@ public void testDenseUnionVector() { } } + @Test + public void testBaseFixedWidthVectorInstanceMethod() { + try (final IntVector vector = new IntVector("v", allocator)) { + vector.validate(); + setVector(vector, 1, 2, 3); + vector.validate(); + + vector.getDataBuffer().capacity(0); + ValidateUtil.ValidateException e = assertThrows(ValidateUtil.ValidateException.class, + () -> vector.validate()); + assertTrue(e.getMessage().contains("Not enough capacity for fixed width data buffer")); + } + } + private void writeStructVector(NullableStructWriter writer, int value1, long value2) { writer.start(); writer.integer("f0").writeInt(value1); diff --git a/java/vector/src/test/java/org/apache/arrow/vector/validate/TestValidateVectorFull.java b/java/vector/src/test/java/org/apache/arrow/vector/validate/TestValidateVectorFull.java index 4241a0d9cff93..ca71a622bb8ea 100644 --- a/java/vector/src/test/java/org/apache/arrow/vector/validate/TestValidateVectorFull.java +++ b/java/vector/src/test/java/org/apache/arrow/vector/validate/TestValidateVectorFull.java @@ -23,11 +23,14 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import org.apache.arrow.memory.ArrowBuf; import org.apache.arrow.memory.BufferAllocator; import org.apache.arrow.memory.RootAllocator; +import org.apache.arrow.vector.Decimal256Vector; +import org.apache.arrow.vector.DecimalVector; import org.apache.arrow.vector.Float4Vector; import org.apache.arrow.vector.IntVector; import org.apache.arrow.vector.LargeVarCharVector; @@ -231,4 +234,75 @@ public void testDenseUnionVector() { assertTrue(e.getMessage().contains("Dense union vector offset exceeds sub-vector boundary")); } } + + @Test + public void testBaseVariableWidthVectorInstanceMethod() { + try (final VarCharVector vector = new VarCharVector("v", allocator)) { + vector.validateFull(); + setVector(vector, "aaa", "bbb", "ccc"); + vector.validateFull(); + + ArrowBuf offsetBuf = vector.getOffsetBuffer(); + offsetBuf.setInt(0, 100); + offsetBuf.setInt(4, 50); + + ValidateUtil.ValidateException e = assertThrows(ValidateUtil.ValidateException.class, + vector::validateFull); + assertTrue(e.getMessage().contains("The values in positions 0 and 1 of the offset buffer are decreasing")); + } + } + + @Test + public void testValidateVarCharUTF8() { + try (final VarCharVector vector = new VarCharVector("v", allocator)) { + vector.validateFull(); + setVector(vector, "aaa".getBytes(StandardCharsets.UTF_8), "bbb".getBytes(StandardCharsets.UTF_8), + new byte[] {(byte) 0xFF, (byte) 0xFE}); + ValidateUtil.ValidateException e = assertThrows(ValidateUtil.ValidateException.class, + vector::validateFull); + assertTrue(e.getMessage().contains("UTF")); + } + } + + @Test + public void testValidateLargeVarCharUTF8() { + try (final LargeVarCharVector vector = new LargeVarCharVector("v", allocator)) { + vector.validateFull(); + setVector(vector, "aaa".getBytes(StandardCharsets.UTF_8), "bbb".getBytes(StandardCharsets.UTF_8), + new byte[] {(byte) 0xFF, (byte) 0xFE}); + ValidateUtil.ValidateException e = assertThrows(ValidateUtil.ValidateException.class, + vector::validateFull); + assertTrue(e.getMessage().contains("UTF")); + } + } + + @Test + public void testValidateDecimal() { + try (final DecimalVector vector = new DecimalVector(Field.nullable("v", + new ArrowType.Decimal(2, 0, DecimalVector.TYPE_WIDTH * 8)), allocator)) { + vector.validateFull(); + setVector(vector, 1L); + vector.validateFull(); + vector.clear(); + setVector(vector, Long.MAX_VALUE); + ValidateUtil.ValidateException e = assertThrows(ValidateUtil.ValidateException.class, + vector::validateFull); + assertTrue(e.getMessage().contains("Decimal")); + } + } + + @Test + public void testValidateDecimal256() { + try (final Decimal256Vector vector = new Decimal256Vector(Field.nullable("v", + new ArrowType.Decimal(2, 0, DecimalVector.TYPE_WIDTH * 8)), allocator)) { + vector.validateFull(); + setVector(vector, 1L); + vector.validateFull(); + vector.clear(); + setVector(vector, Long.MAX_VALUE); + ValidateUtil.ValidateException e = assertThrows(ValidateUtil.ValidateException.class, + vector::validateFull); + assertTrue(e.getMessage().contains("Decimal")); + } + } } From 816eac4579775b45771fd0f462b73f5a68a87d4b Mon Sep 17 00:00:00 2001 From: mwish Date: Sat, 30 Sep 2023 01:11:33 +0800 Subject: [PATCH 23/56] GH-37851: [C++] IPC: ArrayLoader style enhancement (#37872) ### Rationale for this change Enhance the style of `arrow::ipc::ArrayLoader`'s `SkipField` ### What changes are included in this PR? Set `out_` to `nullptr` when `SkipField` is called. ### Are these changes tested? No ### Are there any user-facing changes? No * Closes: #37851 Authored-by: mwish Signed-off-by: Benjamin Kietzman --- cpp/src/arrow/ipc/reader.cc | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/cpp/src/arrow/ipc/reader.cc b/cpp/src/arrow/ipc/reader.cc index 0def0e036e3c1..6e801e1f8adb7 100644 --- a/cpp/src/arrow/ipc/reader.cc +++ b/cpp/src/arrow/ipc/reader.cc @@ -205,7 +205,10 @@ class ArrayLoader { } } - Status LoadType(const DataType& type) { return VisitTypeInline(type, this); } + Status LoadType(const DataType& type) { + DCHECK_NE(out_, nullptr); + return VisitTypeInline(type, this); + } Status Load(const Field* field, ArrayData* out) { if (max_recursion_depth_ <= 0) { @@ -223,6 +226,9 @@ class ArrayLoader { skip_io_ = true; Status status = Load(field, &dummy); skip_io_ = false; + // GH-37851: Reset state. Load will set `out_` to `&dummy`, which would + // be a dangling pointer. + out_ = nullptr; return status; } @@ -258,6 +264,7 @@ class ArrayLoader { } Status LoadCommon(Type::type type_id) { + DCHECK_NE(out_, nullptr); // This only contains the length and null count, which we need to figure // out what to do with the buffers. For example, if null_count == 0, then // we can skip that buffer without reading from shared memory @@ -276,6 +283,7 @@ class ArrayLoader { template Status LoadPrimitive(Type::type type_id) { + DCHECK_NE(out_, nullptr); out_->buffers.resize(2); RETURN_NOT_OK(LoadCommon(type_id)); @@ -290,6 +298,7 @@ class ArrayLoader { template Status LoadBinary(Type::type type_id) { + DCHECK_NE(out_, nullptr); out_->buffers.resize(3); RETURN_NOT_OK(LoadCommon(type_id)); @@ -299,6 +308,7 @@ class ArrayLoader { template Status LoadList(const TYPE& type) { + DCHECK_NE(out_, nullptr); out_->buffers.resize(2); RETURN_NOT_OK(LoadCommon(type.id())); @@ -313,6 +323,7 @@ class ArrayLoader { } Status LoadChildren(const std::vector>& child_fields) { + DCHECK_NE(out_, nullptr); ArrayData* parent = out_; parent->child_data.resize(child_fields.size()); @@ -2010,7 +2021,7 @@ class StreamDecoder::StreamDecoderImpl : public StreamDecoderInternal { }; StreamDecoder::StreamDecoder(std::shared_ptr listener, IpcReadOptions options) { - impl_.reset(new StreamDecoderImpl(std::move(listener), options)); + impl_ = std::make_unique(std::move(listener), options); } StreamDecoder::~StreamDecoder() {} From 1bd3cba84a1187e594655b2ba4880214dcc73e63 Mon Sep 17 00:00:00 2001 From: Angela Li Date: Fri, 29 Sep 2023 15:37:39 -0400 Subject: [PATCH 24/56] MINOR: [R][Documentation] Add default descriptions in CsvParseOptions$create() docs (#37909) ### Rationale for this change Add more function documentation for folks who want to manually change `quote_char` or `escape_char` options in `CsvParseOptions$create()`, as I did in #37908. I had to go through the source code to arrow/r/R/csv.R - [line 587](https://github.com/apache/arrow/blob/7dc9f69a8a77345d0ec7920af9224ef96d7f5f78/r/R/csv.R#L587) to find the default argument, which was a pain. ### What changes are included in this PR? Documentation changes ### Are these changes tested? No - not changing underlying code. Maintainers might need to rebuild package to include these changes in man/ folder ### Are there any user-facing changes? Yes, on documentation of methods. Lead-authored-by: Angela Li Co-authored-by: Nic Crane Signed-off-by: Nic Crane --- r/R/csv.R | 4 ++-- r/man/CsvReadOptions.Rd | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/r/R/csv.R b/r/R/csv.R index b119d16a84c06..116c620f83490 100644 --- a/r/R/csv.R +++ b/r/R/csv.R @@ -404,10 +404,10 @@ CsvTableReader$create <- function(file, #' #' - `delimiter` Field delimiting character (default `","`) #' - `quoting` Logical: are strings quoted? (default `TRUE`) -#' - `quote_char` Quoting character, if `quoting` is `TRUE` +#' - `quote_char` Quoting character, if `quoting` is `TRUE` (default `'"'`) #' - `double_quote` Logical: are quotes inside values double-quoted? (default `TRUE`) #' - `escaping` Logical: whether escaping is used (default `FALSE`) -#' - `escape_char` Escaping character, if `escaping` is `TRUE` +#' - `escape_char` Escaping character, if `escaping` is `TRUE` (default `"\\"`) #' - `newlines_in_values` Logical: are values allowed to contain CR (`0x0d`) #' and LF (`0x0a`) characters? (default `FALSE`) #' - `ignore_empty_lines` Logical: should empty lines be ignored (default) or diff --git a/r/man/CsvReadOptions.Rd b/r/man/CsvReadOptions.Rd index a18ff959ce7e5..6ebb2355184c1 100644 --- a/r/man/CsvReadOptions.Rd +++ b/r/man/CsvReadOptions.Rd @@ -52,10 +52,10 @@ The order of application is as follows: \itemize{ \item \code{delimiter} Field delimiting character (default \code{","}) \item \code{quoting} Logical: are strings quoted? (default \code{TRUE}) -\item \code{quote_char} Quoting character, if \code{quoting} is \code{TRUE} +\item \code{quote_char} Quoting character, if \code{quoting} is \code{TRUE} (default \code{'"'}) \item \code{double_quote} Logical: are quotes inside values double-quoted? (default \code{TRUE}) \item \code{escaping} Logical: whether escaping is used (default \code{FALSE}) -\item \code{escape_char} Escaping character, if \code{escaping} is \code{TRUE} +\item \code{escape_char} Escaping character, if \code{escaping} is \code{TRUE} (default \code{"\\\\"}) \item \code{newlines_in_values} Logical: are values allowed to contain CR (\code{0x0d}) and LF (\code{0x0a}) characters? (default \code{FALSE}) \item \code{ignore_empty_lines} Logical: should empty lines be ignored (default) or From 00efb06dc0de9c40907576811ebb546198b7f528 Mon Sep 17 00:00:00 2001 From: sgilmore10 <74676073+sgilmore10@users.noreply.github.com> Date: Fri, 29 Sep 2023 16:16:50 -0400 Subject: [PATCH 25/56] GH-37835: [MATLAB] Improve `arrow.tabular.Schema` display (#37836) ### Rationale for this change We would like to change how `arrow.tabular.Schema`s are displayed in the Command Window. Below is the current display: ```matlab >> field1 = arrow.field("A", arrow.time32()); >> field2 = arrow.field("B", arrow.boolean()); >>s = arrow.schema([field1 field2]) s = A: time32[s] B: bool ``` This display is not very MATLAB-like. ### What changes are included in this PR? 1. Updated the display of `arrow.tabular.Schema`. Below is the new display: ```matlab >> field1 = arrow.field("A", arrow.time32()); >> field2 = arrow.field("B", arrow.boolean()); >> s = arrow.schema([field1 field2]) s = Arrow Schema with 2 fields: A: Time32 | B: Boolean ``` When MATLAB is opened in desktop mode, `Schema`, `Time32`, and `Boolean` are hyperlinks users can click on to view the help text for the different class types. ### Are these changes tested? Yes. Added three new test cases to `tSchema.m`: 1. `TestDisplaySchemaZeroFields` 2. `TestDisplaySchemaOneField` 3. `TestDisplaySchemaMultipleFields` ### Are there any user-facing changes? Yes. `arrow.tabular.Schema`s will be displayed differently in the Command Window. ### Notes Once #37826 is merged, I will rebase my changes and mark this PR as ready for review. * Closes: #37835 Authored-by: Sarah Gilmore Signed-off-by: Kevin Gurney --- .../cpp/arrow/matlab/tabular/proxy/schema.cc | 11 ---- .../cpp/arrow/matlab/tabular/proxy/schema.h | 1 - .../+arrow/+tabular/+internal/displaySchema.m | 50 +++++++++++++++ matlab/src/matlab/+arrow/+tabular/Schema.m | 25 +++++--- matlab/test/arrow/tabular/tSchema.m | 63 +++++++++++++++++++ 5 files changed, 131 insertions(+), 19 deletions(-) create mode 100644 matlab/src/matlab/+arrow/+tabular/+internal/displaySchema.m diff --git a/matlab/src/cpp/arrow/matlab/tabular/proxy/schema.cc b/matlab/src/cpp/arrow/matlab/tabular/proxy/schema.cc index ec1ac1eecb2fd..023381e005969 100644 --- a/matlab/src/cpp/arrow/matlab/tabular/proxy/schema.cc +++ b/matlab/src/cpp/arrow/matlab/tabular/proxy/schema.cc @@ -34,7 +34,6 @@ namespace arrow::matlab::tabular::proxy { REGISTER_METHOD(Schema, getFieldByName); REGISTER_METHOD(Schema, getNumFields); REGISTER_METHOD(Schema, getFieldNames); - REGISTER_METHOD(Schema, toString); } libmexclass::proxy::MakeResult Schema::make(const libmexclass::proxy::FunctionArguments& constructor_arguments) { @@ -141,14 +140,4 @@ namespace arrow::matlab::tabular::proxy { context.outputs[0] = field_names_mda; } - void Schema::toString(libmexclass::proxy::method::Context& context) { - namespace mda = ::matlab::data; - mda::ArrayFactory factory; - - const auto str_utf8 = schema->ToString(); - MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(const auto str_utf16, arrow::util::UTF8StringToUTF16(str_utf8), context, error::UNICODE_CONVERSION_ERROR_ID); - auto str_mda = factory.createScalar(str_utf16); - context.outputs[0] = str_mda; - } - } diff --git a/matlab/src/cpp/arrow/matlab/tabular/proxy/schema.h b/matlab/src/cpp/arrow/matlab/tabular/proxy/schema.h index 30883bc2a85ac..9ca4a94e53071 100644 --- a/matlab/src/cpp/arrow/matlab/tabular/proxy/schema.h +++ b/matlab/src/cpp/arrow/matlab/tabular/proxy/schema.h @@ -39,7 +39,6 @@ namespace arrow::matlab::tabular::proxy { void getFieldByName(libmexclass::proxy::method::Context& context); void getNumFields(libmexclass::proxy::method::Context& context); void getFieldNames(libmexclass::proxy::method::Context& context); - void toString(libmexclass::proxy::method::Context& context); std::shared_ptr schema; }; diff --git a/matlab/src/matlab/+arrow/+tabular/+internal/displaySchema.m b/matlab/src/matlab/+arrow/+tabular/+internal/displaySchema.m new file mode 100644 index 0000000000000..8d6740b195abc --- /dev/null +++ b/matlab/src/matlab/+arrow/+tabular/+internal/displaySchema.m @@ -0,0 +1,50 @@ +%DISPLAYSCHEMA Generates arrow.tabular.Schema display text. + +% 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. + +function text = displaySchema(schema) + fields = schema.Fields; + names = [fields.Name]; + types = [fields.Type]; + typeIDs = string([types.ID]); + + % Use as the sentinel for field names with zero characters. + idx = strlength(names) == 0; + names(idx) = ""; + + if usejava("desktop") + % When in desktop mode, the Command Window can interpret HTML tags + % to display bold font and hyperlinks. + names = compose("%s", names); + classNames = arrayfun(@(type) string(class(type)), types); + + % Creates a string array with the following form: + % + % ["arrow.type.BooleanType" "Boolean" "arrow.type.StringType" "String" ...] + % + % This string array is passed to the compose call below. The + % format specifier operator supplied to compose contains two + % formatting operators (%s), so compose uses two elements from the + % string array (classNameAndIDs) at a time. + classNameAndIDs = strings([1 numel(typeIDs) * 2]); + classNameAndIDs(1:2:end-1) = classNames; + classNameAndIDs(2:2:end) = typeIDs; + typeIDs = compose("%s", classNameAndIDs); + end + + text = names + ": " + typeIDs; + text = " " + strjoin(text, " | "); +end \ No newline at end of file diff --git a/matlab/src/matlab/+arrow/+tabular/Schema.m b/matlab/src/matlab/+arrow/+tabular/Schema.m index f679b1e0bc22c..3ee40f0e14293 100644 --- a/matlab/src/matlab/+arrow/+tabular/Schema.m +++ b/matlab/src/matlab/+arrow/+tabular/Schema.m @@ -97,18 +97,29 @@ end end - methods (Access = private) + methods (Access=protected) - function str = toString(obj) - str = obj.Proxy.toString(); + function header = getHeader(obj) + name = matlab.mixin.CustomDisplay.getClassNameForHeader(obj); + numFields = obj.NumFields; + if numFields == 0 + header = compose(" Arrow %s with 0 fields" + newline, name); + elseif numFields == 1 + header = compose(" Arrow %s with %d field:" + newline, name, numFields); + else + header = compose(" Arrow %s with %d fields:" + newline, name, numFields); + end end - end + function displayScalarObject(obj) + disp(getHeader(obj)); + numFields = obj.NumFields; - methods (Access=protected) + if numFields > 0 + text = arrow.tabular.internal.displaySchema(obj); + disp(text + newline); + end - function displayScalarObject(obj) - disp(obj.toString()); end end diff --git a/matlab/test/arrow/tabular/tSchema.m b/matlab/test/arrow/tabular/tSchema.m index e4c706d9a3d6c..bb95c1823b9fc 100644 --- a/matlab/test/arrow/tabular/tSchema.m +++ b/matlab/test/arrow/tabular/tSchema.m @@ -526,7 +526,70 @@ function TestIsEqualFalse(testCase) % Compare schema to double testCase.verifyFalse(isequal(schema4, 5)); + end + + function TestDisplaySchemaZeroFields(testCase) + import arrow.internal.test.display.makeLinkString + + schema = arrow.schema(arrow.type.Field.empty(0, 0)); %#ok + classnameLink = makeLinkString(FullClassName="arrow.tabular.Schema",... + ClassName="Schema", BoldFont=true); + expectedDisplay = " Arrow " + classnameLink + " with 0 fields" + newline; + expectedDisplay = char(expectedDisplay + newline); + actualDisplay = evalc('disp(schema)'); + testCase.verifyEqual(actualDisplay, char(expectedDisplay)); + end + + function TestDisplaySchemaOneField(testCase) + import arrow.internal.test.display.makeLinkString + + schema = arrow.schema(arrow.field("TestField", arrow.boolean())); %#ok + classnameLink = makeLinkString(FullClassName="arrow.tabular.Schema",... + ClassName="Schema", BoldFont=true); + header = " Arrow " + classnameLink + " with 1 field:" + newline; + indent = " "; + + if usejava("desktop") + type = makeLinkString(FullClassName="arrow.type.BooleanType", ... + ClassName="Boolean", BoldFont=true); + name = "TestField: "; + fieldLine = indent + name + type + newline; + else + fieldLine = indent + "TestField: Boolean" + newline; + end + expectedDisplay = join([header, fieldLine], newline); + expectedDisplay = char(expectedDisplay + newline); + actualDisplay = evalc('disp(schema)'); + testCase.verifyEqual(actualDisplay, char(expectedDisplay)); + end + function TestDisplaySchemaField(testCase) + import arrow.internal.test.display.makeLinkString + + field1 = arrow.field("Field1", arrow.timestamp()); + field2 = arrow.field("Field2", arrow.string()); + schema = arrow.schema([field1, field2]); %#ok + classnameLink = makeLinkString(FullClassName="arrow.tabular.Schema",... + ClassName="Schema", BoldFont=true); + header = " Arrow " + classnameLink + " with 2 fields:" + newline; + + indent = " "; + if usejava("desktop") + type1 = makeLinkString(FullClassName="arrow.type.TimestampType", ... + ClassName="Timestamp", BoldFont=true); + field1String = "Field1: " + type1; + type2 = makeLinkString(FullClassName="arrow.type.StringType", ... + ClassName="String", BoldFont=true); + field2String = "Field2: " + type2; + fieldLine = indent + field1String + " | " + field2String + newline; + else + fieldLine = indent + "Field1: Timestamp | Field2: String" + newline; + end + + expectedDisplay = join([header, fieldLine], newline); + expectedDisplay = char(expectedDisplay + newline); + actualDisplay = evalc('disp(schema)'); + testCase.verifyEqual(actualDisplay, char(expectedDisplay)); end end From ffdb9274abb7401289a671274b52ae10ce830b00 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 04:42:13 +0900 Subject: [PATCH 26/56] MINOR: [JS] Bump eslint-plugin-jest from 27.2.3 to 27.4.2 in /js (#37963) Bumps [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) from 27.2.3 to 27.4.2.
Release notes

Sourced from eslint-plugin-jest's releases.

v27.4.2

27.4.2 (2023-09-29)

Bug Fixes

  • make rule message punctuation consistent (#1444) (84121ee)

v27.4.1

27.4.1 (2023-09-29)

Bug Fixes

  • no-focused-tests: make reporting location consistent (#1443) (a871775)

v27.4.0

27.4.0 (2023-09-15)

Features

  • valid-title: support ignoring leading and trailing whitespace (#1433) (bc96473)

v27.3.0

27.3.0 (2023-09-15)

Features

Changelog

Sourced from eslint-plugin-jest's changelog.

27.4.2 (2023-09-29)

Bug Fixes

  • make rule message punctuation consistent (#1444) (84121ee)

27.4.1 (2023-09-29)

Bug Fixes

  • no-focused-tests: make reporting location consistent (#1443) (a871775)

27.4.0 (2023-09-15)

Features

  • valid-title: support ignoring leading and trailing whitespace (#1433) (bc96473)

27.3.0 (2023-09-15)

Features

Commits
  • 094ac10 chore(release): 27.4.2 [skip ci]
  • 0ec155a chore(deps): update dependency semantic-release to v22 (#1434)
  • 84121ee fix: make rule message punctuation consistent (#1444)
  • 90488de chore(release): 27.4.1 [skip ci]
  • a871775 fix(no-focused-tests): make reporting location consistent (#1443)
  • 1ee0087 refactor(max-nested-describe): simplify implementation (#1442)
  • c846f7f chore(deps): lock file maintenance
  • e790193 chore(deps): update danger/danger-js action to v11.3.0 (#1437)
  • 225c3cf chore(deps): lock file maintenance
  • 42fec48 chore(release): 27.4.0 [skip ci]
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=eslint-plugin-jest&package-manager=npm_and_yarn&previous-version=27.2.3&new-version=27.4.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@ dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@ dependabot rebase` will rebase this PR - `@ dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@ dependabot merge` will merge this PR after your CI passes on it - `@ dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@ dependabot cancel merge` will cancel a previously requested merge and block automerging - `@ dependabot reopen` will reopen this PR if it is closed - `@ dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@ dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@ dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@ dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@ dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Sutou Kouhei --- js/package.json | 2 +- js/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/js/package.json b/js/package.json index 11bbe24f0244c..d3b06ae43f23f 100644 --- a/js/package.json +++ b/js/package.json @@ -82,7 +82,7 @@ "esbuild": "0.19.2", "esbuild-plugin-alias": "0.2.1", "eslint": "8.42.0", - "eslint-plugin-jest": "27.2.3", + "eslint-plugin-jest": "27.4.2", "eslint-plugin-unicorn": "47.0.0", "esm": "https://github.com/jsg2021/esm/releases/download/v3.x.x-pr883/esm-3.x.x-pr883.tgz", "glob": "10.2.7", diff --git a/js/yarn.lock b/js/yarn.lock index 66ede59a598b1..9805f706946f2 100644 --- a/js/yarn.lock +++ b/js/yarn.lock @@ -2766,10 +2766,10 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -eslint-plugin-jest@27.2.3: - version "27.2.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.2.3.tgz#6f8a4bb2ca82c0c5d481d1b3be256ab001f5a3ec" - integrity sha512-sRLlSCpICzWuje66Gl9zvdF6mwD5X86I4u55hJyFBsxYOsBCmT5+kSUjf+fkFWVMMgpzNEupjW8WzUqi83hJAQ== +eslint-plugin-jest@27.4.2: + version "27.4.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.4.2.tgz#181d999ac67a9b6040db1d27935887cf5a2882ed" + integrity sha512-3Nfvv3wbq2+PZlRTf2oaAWXWwbdBejFRBR2O8tAO67o+P8zno+QGbcDYaAXODlreXVg+9gvWhKKmG2rgfb8GEg== dependencies: "@typescript-eslint/utils" "^5.10.0" From ff98e7d43de44caa6650a5cfbc395986809900f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 04:43:07 +0900 Subject: [PATCH 27/56] MINOR: [JS] Bump memfs from 4.2.1 to 4.5.0 in /js (#37964) Bumps [memfs](https://github.com/streamich/memfs) from 4.2.1 to 4.5.0.
Release notes

Sourced from memfs's releases.

v4.5.0

4.5.0 (2023-09-25)

Features

  • volume: fromJSON now accepts Buffer as volume content (#880) (9c0a6ff)

v4.4.0

4.4.0 (2023-09-22)

Features

  • volume: toJSON now accepts the asBuffer parameter (#952) (91a3742)
  • volume: implement readv and writev (#946) (966e17e)

v4.3.0

4.3.0 (2023-09-15)

Features

v4.2.3

4.2.3 (2023-09-15)

Bug Fixes

  • add missing nanosecond-precision properties to Stats (#943) (b9d4c6d)

v4.2.2

4.2.2 (2023-09-15)

Bug Fixes

Changelog

Sourced from memfs's changelog.

4.5.0 (2023-09-25)

Features

  • volume: fromJSON now accepts Buffer as volume content (#880) (9c0a6ff)

4.4.0 (2023-09-22)

Features

  • volume: toJSON now accepts the asBuffer parameter (#952) (91a3742)
  • volume: implement readv and writev (#946) (966e17e)

4.3.0 (2023-09-15)

Features

4.2.3 (2023-09-15)

Bug Fixes

  • add missing nanosecond-precision properties to Stats (#943) (b9d4c6d)

4.2.2 (2023-09-15)

Bug Fixes

Commits
  • 7fc1f7e chore(release): 4.5.0 [skip ci]
  • 9c0a6ff feat(volume): fromJSON now accepts Buffer as volume content (#880)
  • d1d66f6 chore(release): 4.4.0 [skip ci]
  • 91a3742 feat(volume): toJSON now accepts the asBuffer parameter (#952)
  • 966e17e feat(volume): implement readv and writev (#946)
  • 125a996 chore: sort package.json (#950)
  • 539a78d chore(deps): update jest monorepo to v29 (major) (#844)
  • b15a80e chore(release): 4.3.0 [skip ci]
  • 96cbce4 feat: add support for O_SYMLINK (#944)
  • f6d988d chore(release): 4.2.3 [skip ci]
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=memfs&package-manager=npm_and_yarn&previous-version=4.2.1&new-version=4.5.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@ dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@ dependabot rebase` will rebase this PR - `@ dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@ dependabot merge` will merge this PR after your CI passes on it - `@ dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@ dependabot cancel merge` will cancel a previously requested merge and block automerging - `@ dependabot reopen` will reopen this PR if it is closed - `@ dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@ dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@ dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@ dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@ dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Sutou Kouhei --- js/package.json | 2 +- js/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/js/package.json b/js/package.json index d3b06ae43f23f..e3c3b946a0b12 100644 --- a/js/package.json +++ b/js/package.json @@ -99,7 +99,7 @@ "ix": "5.0.0", "jest": "29.6.2", "jest-silent-reporter": "0.5.0", - "memfs": "4.2.1", + "memfs": "4.5.0", "mkdirp": "3.0.1", "multistream": "4.1.0", "randomatic": "3.1.1", diff --git a/js/yarn.lock b/js/yarn.lock index 9805f706946f2..d16bcf191e9d6 100644 --- a/js/yarn.lock +++ b/js/yarn.lock @@ -4931,10 +4931,10 @@ math-random@^1.0.1: resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== -memfs@4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-4.2.1.tgz#8c5a48707a460dde8e734b15e405e8377db2bec5" - integrity sha512-CINEB6cNAAhLUfRGrB4lj2Pj47ygerEmw3jxPb6R1gkD6Jfp484gJLteQ6MzqIjGWtFWuVzDl+KN7HiipMuKSw== +memfs@4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-4.5.0.tgz#03082709987760022275e0d3bc0f24545b7fe279" + integrity sha512-8QePW5iXi/ZCySFTo39h3ujKGT0rYVnZywuSo5AzR7POAuy4uBEFZKziYkkrlGdWuxACUxKAJ0L/sry3DSG+TA== dependencies: json-joy "^9.2.0" thingies "^1.11.1" From a381c05d596cddd341437de6b277520345f9bb8e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 04:44:34 +0900 Subject: [PATCH 28/56] MINOR: [JS] Bump del from 7.0.0 to 7.1.0 in /js (#37967) Bumps [del](https://github.com/sindresorhus/del) from 7.0.0 to 7.1.0.
Release notes

Sourced from del's releases.

v7.1.0

  • Add path to onProgress event (#155) f5d31e6

https://github.com/sindresorhus/del/compare/v7.0.0...v7.1.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=del&package-manager=npm_and_yarn&previous-version=7.0.0&new-version=7.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@ dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@ dependabot rebase` will rebase this PR - `@ dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@ dependabot merge` will merge this PR after your CI passes on it - `@ dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@ dependabot cancel merge` will cancel a previously requested merge and block automerging - `@ dependabot reopen` will reopen this PR if it is closed - `@ dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@ dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@ dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@ dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@ dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Sutou Kouhei --- js/package.json | 2 +- js/yarn.lock | 16 +--------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/js/package.json b/js/package.json index e3c3b946a0b12..dfb17d24c2f41 100644 --- a/js/package.json +++ b/js/package.json @@ -77,7 +77,7 @@ "async-done": "2.0.0", "benny": "3.7.1", "cross-env": "7.0.3", - "del": "7.0.0", + "del": "7.1.0", "del-cli": "5.1.0", "esbuild": "0.19.2", "esbuild-plugin-alias": "0.2.1", diff --git a/js/yarn.lock b/js/yarn.lock index d16bcf191e9d6..647b696931bb0 100644 --- a/js/yarn.lock +++ b/js/yarn.lock @@ -2495,21 +2495,7 @@ del-cli@5.1.0: del "^7.1.0" meow "^10.1.3" -del@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/del/-/del-7.0.0.tgz#79db048bec96f83f344b46c1a66e35d9c09fe8ac" - integrity sha512-tQbV/4u5WVB8HMJr08pgw0b6nG4RGt/tj+7Numvq+zqcvUFeMaIWWOUFltiU+6go8BSO2/ogsB4EasDaj0y68Q== - dependencies: - globby "^13.1.2" - graceful-fs "^4.2.10" - is-glob "^4.0.3" - is-path-cwd "^3.0.0" - is-path-inside "^4.0.0" - p-map "^5.5.0" - rimraf "^3.0.2" - slash "^4.0.0" - -del@^7.1.0: +del@7.1.0, del@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/del/-/del-7.1.0.tgz#0de0044d556b649ff05387f1fa7c885e155fd1b6" integrity sha512-v2KyNk7efxhlyHpjEvfyxaAihKKK0nWCuf6ZtqZcFFpQRG0bJ12Qsr0RpvsICMjAAZ8DOVCxrlqpxISlMHC4Kg== From b0eb0216be3ac365e31ba34151cdaaf193c96244 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 06:46:59 +0900 Subject: [PATCH 29/56] MINOR: [JS] Bump google-closure-compiler from 20230502.0.0 to 20230802.0.0 in /js (#37965) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [google-closure-compiler](https://github.com/google/closure-compiler-npm) from 20230502.0.0 to 20230802.0.0.
Release notes

Sourced from google-closure-compiler's releases.

20230802.0.0

Closure-compiler 20230802 release

What's Changed

New Contributors

Full Changelog: https://github.com/google/closure-compiler-npm/compare/v20230502.0.0...v20230802.0.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google-closure-compiler&package-manager=npm_and_yarn&previous-version=20230502.0.0&new-version=20230802.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@ dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@ dependabot rebase` will rebase this PR - `@ dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@ dependabot merge` will merge this PR after your CI passes on it - `@ dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@ dependabot cancel merge` will cancel a previously requested merge and block automerging - `@ dependabot reopen` will reopen this PR if it is closed - `@ dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@ dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@ dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@ dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@ dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Sutou Kouhei --- js/package.json | 2 +- js/yarn.lock | 56 ++++++++++++++++++++++++------------------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/js/package.json b/js/package.json index dfb17d24c2f41..14f26c74d29f3 100644 --- a/js/package.json +++ b/js/package.json @@ -86,7 +86,7 @@ "eslint-plugin-unicorn": "47.0.0", "esm": "https://github.com/jsg2021/esm/releases/download/v3.x.x-pr883/esm-3.x.x-pr883.tgz", "glob": "10.2.7", - "google-closure-compiler": "20230502.0.0", + "google-closure-compiler": "20230802.0.0", "gulp": "4.0.2", "gulp-esbuild": "0.11.1", "gulp-json-transform": "0.4.8", diff --git a/js/yarn.lock b/js/yarn.lock index 647b696931bb0..f027be218245f 100644 --- a/js/yarn.lock +++ b/js/yarn.lock @@ -3447,40 +3447,40 @@ glogg@^1.0.0: dependencies: sparkles "^1.0.0" -google-closure-compiler-java@^20230502.0.0: - version "20230502.0.0" - resolved "https://registry.yarnpkg.com/google-closure-compiler-java/-/google-closure-compiler-java-20230502.0.0.tgz#111240655adf9d64a0ac7eb16f73e896f3f9cefd" - integrity sha512-2nMQPQz2ppU9jvHhz2zpUP5jBDAqZp4gFVOEvirEyfUuLLkHwAvU2Tl1c7xaKX+Z4uMxpxttxcwdIjQhV2g8eQ== - -google-closure-compiler-linux@^20230502.0.0: - version "20230502.0.0" - resolved "https://registry.yarnpkg.com/google-closure-compiler-linux/-/google-closure-compiler-linux-20230502.0.0.tgz#c71114611b7ca47febd6feb1289ae152ca020b92" - integrity sha512-4NDgPKJXQHUxEyJoVFPVMQPJs5at7ThOXa9u3+9UeYk2K+vtW5wVZlmW07VOy8Mk/O/n2dp+Vl+wuE35BIiHAA== - -google-closure-compiler-osx@^20230502.0.0: - version "20230502.0.0" - resolved "https://registry.yarnpkg.com/google-closure-compiler-osx/-/google-closure-compiler-osx-20230502.0.0.tgz#9ea082f0c6ad40b829802f0993f2e5b4b0e079e8" - integrity sha512-jB13dcbu8O02cG3JcCCVZku1oI0ZirJc/Sr9xcGHY5MMyw3qEMlXb3IU97W6UXLcg2wCRawMWadOwL9K4L9lfQ== - -google-closure-compiler-windows@^20230502.0.0: - version "20230502.0.0" - resolved "https://registry.yarnpkg.com/google-closure-compiler-windows/-/google-closure-compiler-windows-20230502.0.0.tgz#81eef5de8b86364716b77a2d8068afba8b0e8244" - integrity sha512-wW5/liBxejvUViiBNo8/C9Vnhw+Lm+n3RdfE4spNkmdH9bcpKM+KQBLrPPakW17P3HbAPOPZ0L1RsrmyLYA5Cg== - -google-closure-compiler@20230502.0.0: - version "20230502.0.0" - resolved "https://registry.yarnpkg.com/google-closure-compiler/-/google-closure-compiler-20230502.0.0.tgz#65b19e673255b4b4dad4271724932e0970b11a97" - integrity sha512-C2WZkuRnXpNjU2nc0W/Cgxm6t2VlwEyUJOTaGHaLr6qZCXK0L1uhOneKWN2X7AORKdzyLW6Tq8ONxRc7eODGJg== +google-closure-compiler-java@^20230802.0.0: + version "20230802.0.0" + resolved "https://registry.yarnpkg.com/google-closure-compiler-java/-/google-closure-compiler-java-20230802.0.0.tgz#5de4679f3d014b6b66471a48fb82c2772db4c872" + integrity sha512-PWKLMLwj7pR/U0yYbiy649LLqAscu+F1gyY4Y/jK6CmSLb8cIJbL8BTJd00828TzTNfWnYwxbkcQw0y9C2YsGw== + +google-closure-compiler-linux@^20230802.0.0: + version "20230802.0.0" + resolved "https://registry.yarnpkg.com/google-closure-compiler-linux/-/google-closure-compiler-linux-20230802.0.0.tgz#1acaf12ef386e5c1dcb5ff5796d4ae9f48ebce46" + integrity sha512-F13U4iSXiWeGtHOFS25LVem1s6zI+pJvXVPVR7zSib5ppoUJ0JXnABJQezUR3FnpxmnkALG4oIGW0syH9zPLZA== + +google-closure-compiler-osx@^20230802.0.0: + version "20230802.0.0" + resolved "https://registry.yarnpkg.com/google-closure-compiler-osx/-/google-closure-compiler-osx-20230802.0.0.tgz#10746ecfa81ad6eecc4d42d4ce9d0ed3ca8071e7" + integrity sha512-ANAi/ux92Tt+Na7vFDLeK2hRzotjC5j+nxoPtE0OcuNcbjji5dREKoJxkq7r0YwRTCzAFZszK5ip/NPdTOdCEg== + +google-closure-compiler-windows@^20230802.0.0: + version "20230802.0.0" + resolved "https://registry.yarnpkg.com/google-closure-compiler-windows/-/google-closure-compiler-windows-20230802.0.0.tgz#d57968dc24d5e0d538840b4313e1bec7c71b18d6" + integrity sha512-ZQPujoNiiUyTGl8zEGR/0yAygWnbMtX/NQ/S/EHVgq5nmYkvDEVuiVbgpPAmO9lzBTq0hvUTRRATZbTU2ISxgA== + +google-closure-compiler@20230802.0.0: + version "20230802.0.0" + resolved "https://registry.yarnpkg.com/google-closure-compiler/-/google-closure-compiler-20230802.0.0.tgz#849181359823f8c9130faec9a1597377680823d6" + integrity sha512-o2fYoc8lqOBdhm95Ick0vWrtwH2Icd5yLZhbTcQ0T7NfGiBepYvx1BB63hR8ebgzEZemz9Fh+O6Kg/3Mjm28ww== dependencies: chalk "4.x" - google-closure-compiler-java "^20230502.0.0" + google-closure-compiler-java "^20230802.0.0" minimist "1.x" vinyl "2.x" vinyl-sourcemaps-apply "^0.2.0" optionalDependencies: - google-closure-compiler-linux "^20230502.0.0" - google-closure-compiler-osx "^20230502.0.0" - google-closure-compiler-windows "^20230502.0.0" + google-closure-compiler-linux "^20230802.0.0" + google-closure-compiler-osx "^20230802.0.0" + google-closure-compiler-windows "^20230802.0.0" graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.4, graceful-fs@^4.2.9: version "4.2.11" From 22df70a0caf888084ae13d7f3e0178a477d1e7d7 Mon Sep 17 00:00:00 2001 From: mwish Date: Mon, 2 Oct 2023 22:51:50 +0800 Subject: [PATCH 30/56] GH-37799: [C++] Compute: CommonTemporal support time32 and time64 casting (#37949) ### Rationale for this change The original problem in mentioned in https://github.com/apache/arrow/issues/37799 1. `SECOND` in Parquet would always cast to `MILLS` 2. `eq` not support `eq(time32[s], time32[ms)` This patch is as advice in https://github.com/apache/arrow/issues/37799#issuecomment-1737747352 . We tent to add time32 and time64 in `CommonTemporal`. ### What changes are included in this PR? Support time32 and time64 with different time unit in `arrow::compute::internal::CommonTemporal`. ### Are these changes tested? Yes ### Are there any user-facing changes? bugfix * Closes: #37799 Authored-by: mwish Signed-off-by: Benjamin Kietzman --- .../arrow/compute/kernels/codegen_internal.cc | 49 +++++++++++++++---- .../compute/kernels/codegen_internal_test.cc | 12 +++++ cpp/src/arrow/dataset/file_parquet_test.cc | 25 ++++++++++ 3 files changed, 77 insertions(+), 9 deletions(-) diff --git a/cpp/src/arrow/compute/kernels/codegen_internal.cc b/cpp/src/arrow/compute/kernels/codegen_internal.cc index 8e2669bd3dfb9..00a833742f957 100644 --- a/cpp/src/arrow/compute/kernels/codegen_internal.cc +++ b/cpp/src/arrow/compute/kernels/codegen_internal.cc @@ -251,6 +251,7 @@ TypeHolder CommonTemporal(const TypeHolder* begin, size_t count) { bool saw_date32 = false; bool saw_date64 = false; bool saw_duration = false; + bool saw_time_since_midnight = false; const TypeHolder* end = begin + count; for (auto it = begin; it != end; it++) { auto id = it->type->id(); @@ -271,6 +272,18 @@ TypeHolder CommonTemporal(const TypeHolder* begin, size_t count) { finest_unit = std::max(finest_unit, ty.unit()); continue; } + case Type::TIME32: { + const auto& type = checked_cast(*it->type); + finest_unit = std::max(finest_unit, type.unit()); + saw_time_since_midnight = true; + continue; + } + case Type::TIME64: { + const auto& type = checked_cast(*it->type); + finest_unit = std::max(finest_unit, type.unit()); + saw_time_since_midnight = true; + continue; + } case Type::DURATION: { const auto& ty = checked_cast(*it->type); finest_unit = std::max(finest_unit, ty.unit()); @@ -282,15 +295,33 @@ TypeHolder CommonTemporal(const TypeHolder* begin, size_t count) { } } - if (timezone) { - // At least one timestamp seen - return timestamp(finest_unit, *timezone); - } else if (saw_date64) { - return date64(); - } else if (saw_date32) { - return date32(); - } else if (saw_duration) { - return duration(finest_unit); + bool saw_timestamp_or_date = timezone || saw_date64 || saw_date32 || saw_duration; + + if (saw_time_since_midnight && saw_timestamp_or_date) { + // Cannot find common type + return TypeHolder(nullptr); + } + if (saw_timestamp_or_date) { + if (timezone) { + // At least one timestamp seen + return timestamp(finest_unit, *timezone); + } else if (saw_date64) { + return date64(); + } else if (saw_date32) { + return date32(); + } else if (saw_duration) { + return duration(finest_unit); + } + } + if (saw_time_since_midnight) { + switch (finest_unit) { + case TimeUnit::SECOND: + case TimeUnit::MILLI: + return time32(finest_unit); + case TimeUnit::MICRO: + case TimeUnit::NANO: + return time64(finest_unit); + } } return TypeHolder(nullptr); } diff --git a/cpp/src/arrow/compute/kernels/codegen_internal_test.cc b/cpp/src/arrow/compute/kernels/codegen_internal_test.cc index af024fb8d6e08..6bb5568d2ff38 100644 --- a/cpp/src/arrow/compute/kernels/codegen_internal_test.cc +++ b/cpp/src/arrow/compute/kernels/codegen_internal_test.cc @@ -159,6 +159,18 @@ TEST(TestDispatchBest, CommonTemporal) { args = {timestamp(TimeUnit::SECOND, "America/Phoenix"), timestamp(TimeUnit::SECOND, "UTC")}; ASSERT_EQ(CommonTemporal(args.data(), args.size()), nullptr); + + args = {time32(TimeUnit::SECOND), time32(TimeUnit::MILLI)}; + AssertTypeEqual(*time32(TimeUnit::MILLI), *CommonTemporal(args.data(), args.size())); + + args = {time32(TimeUnit::SECOND), time64(TimeUnit::NANO)}; + AssertTypeEqual(*time64(TimeUnit::NANO), *CommonTemporal(args.data(), args.size())); + + args = {date32(), time32(TimeUnit::SECOND)}; + ASSERT_EQ(CommonTemporal(args.data(), args.size()), nullptr); + + args = {timestamp(TimeUnit::SECOND), time32(TimeUnit::SECOND)}; + ASSERT_EQ(CommonTemporal(args.data(), args.size()), nullptr); } TEST(TestDispatchBest, CommonTemporalResolution) { diff --git a/cpp/src/arrow/dataset/file_parquet_test.cc b/cpp/src/arrow/dataset/file_parquet_test.cc index 177ca824179a8..dc9e085df3c4c 100644 --- a/cpp/src/arrow/dataset/file_parquet_test.cc +++ b/cpp/src/arrow/dataset/file_parquet_test.cc @@ -730,6 +730,31 @@ TEST_P(TestParquetFileFormatScan, PredicatePushdownRowGroupFragmentsUsingDuratio CountRowGroupsInFragment(fragment, {0}, expr); } +TEST_P(TestParquetFileFormatScan, + PredicatePushdownRowGroupFragmentsUsingTimestampColumn) { + // GH-37799: Parquet arrow will change TimeUnit::SECOND to TimeUnit::MILLI + // because parquet LogicalType doesn't support SECOND. + for (auto time_unit : {TimeUnit::MILLI, TimeUnit::SECOND}) { + auto table = TableFromJSON(schema({field("t", time32(time_unit))}), + { + R"([{"t": 1}])", + R"([{"t": 2}, {"t": 3}])", + }); + TableBatchReader table_reader(*table); + ARROW_SCOPED_TRACE("time_unit=", time_unit); + ASSERT_OK_AND_ASSIGN( + auto source, + ParquetFormatHelper::Write( + &table_reader, ArrowWriterProperties::Builder().store_schema()->build()) + .As()); + SetSchema({field("t", time32(time_unit))}); + ASSERT_OK_AND_ASSIGN(auto fragment, format_->MakeFragment(source)); + + auto expr = equal(field_ref("t"), literal(::arrow::Time32Scalar(1, time_unit))); + CountRowGroupsInFragment(fragment, {0}, expr); + } +} + // Tests projection with nested/indexed FieldRefs. // https://github.com/apache/arrow/issues/35579 TEST_P(TestParquetFileFormatScan, ProjectWithNonNamedFieldRefs) { From 7667b81bffcb5b361fab6d61c42ce396d98cc6e1 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Mon, 2 Oct 2023 18:07:59 +0200 Subject: [PATCH 31/56] GH-37906: [Integration][C#] Implement C Data Interface integration testing for C# (#37904) ### Rationale for this change All Arrow implementations supporting the C Data Interface should also implement integration testing, to ensure proper interoperability. ### What changes are included in this PR? * Implement C Data Interface integration testing for C# * Fix bugs in the C Data Interface implementation for C# ### Are these changes tested? Yes, by construction. ### Are there any user-facing changes? No. * Closes: #37906 Authored-by: Antoine Pitrou Signed-off-by: Antoine Pitrou --- ci/scripts/integration_arrow.sh | 5 + csharp/src/Apache.Arrow/ArrowBuffer.cs | 3 +- csharp/src/Apache.Arrow/C/CArrowArray.cs | 13 +- .../src/Apache.Arrow/C/CArrowArrayExporter.cs | 53 +- .../Apache.Arrow/C/CArrowSchemaImporter.cs | 10 +- .../Memory/ExportedAllocationOwner.cs | 22 + .../Apache.Arrow.IntegrationTest.csproj | 3 +- .../CDataInterface.cs | 77 +++ .../IntegrationCommand.cs | 606 +---------------- .../Apache.Arrow.IntegrationTest/JsonFile.cs | 640 +++++++++++++++++- .../CDataInterfacePythonTests.cs | 4 +- dev/archery/archery/integration/runner.py | 11 +- dev/archery/archery/integration/tester.py | 6 +- dev/archery/archery/integration/tester_cpp.py | 6 +- .../archery/integration/tester_csharp.py | 138 +++- dev/archery/archery/integration/tester_go.py | 6 +- 16 files changed, 958 insertions(+), 645 deletions(-) create mode 100644 csharp/test/Apache.Arrow.IntegrationTest/CDataInterface.cs diff --git a/ci/scripts/integration_arrow.sh b/ci/scripts/integration_arrow.sh index a165f8027bf8f..289d376a4db9b 100755 --- a/ci/scripts/integration_arrow.sh +++ b/ci/scripts/integration_arrow.sh @@ -23,6 +23,11 @@ arrow_dir=${1} gold_dir=$arrow_dir/testing/data/arrow-ipc-stream/integration pip install -e $arrow_dir/dev/archery[integration] +# For C# C Data Interface testing +pip install pythonnet + +# Get more detailed context on crashes +export PYTHONFAULTHANDLER=1 # Rust can be enabled by exporting ARCHERY_INTEGRATION_WITH_RUST=1 time archery integration \ diff --git a/csharp/src/Apache.Arrow/ArrowBuffer.cs b/csharp/src/Apache.Arrow/ArrowBuffer.cs index dbd97fc3aec9e..ef98bdc853b88 100644 --- a/csharp/src/Apache.Arrow/ArrowBuffer.cs +++ b/csharp/src/Apache.Arrow/ArrowBuffer.cs @@ -75,8 +75,9 @@ public void Dispose() internal bool TryExport(ExportedAllocationOwner newOwner, out IntPtr ptr) { - if (_memoryOwner == null && IsEmpty) + if (IsEmpty) { + // _memoryOwner could be anything (for example null or a NullMemoryOwner), but it doesn't matter here ptr = IntPtr.Zero; return true; } diff --git a/csharp/src/Apache.Arrow/C/CArrowArray.cs b/csharp/src/Apache.Arrow/C/CArrowArray.cs index fc609f10fdfa5..882ca8caa503d 100644 --- a/csharp/src/Apache.Arrow/C/CArrowArray.cs +++ b/csharp/src/Apache.Arrow/C/CArrowArray.cs @@ -16,6 +16,7 @@ // under the License. using System; +using System.Diagnostics; using System.Runtime.InteropServices; namespace Apache.Arrow.C @@ -67,6 +68,15 @@ public unsafe struct CArrowArray /// Do not call this on a pointer that was allocated elsewhere. /// public static void Free(CArrowArray* array) + { + CallReleaseFunc(array); + Marshal.FreeHGlobal((IntPtr)array); + } + + /// + /// Call the array's release func, if set. + /// + public static void CallReleaseFunc(CArrowArray* array) { if (array->release != default) { @@ -76,8 +86,9 @@ public static void Free(CArrowArray* array) #else Marshal.GetDelegateForFunctionPointer(array->release)(array); #endif + Debug.Assert(array->release == default, + "Calling the CArrowArray release func should have set it to NULL"); } - Marshal.FreeHGlobal((IntPtr)array); } } } diff --git a/csharp/src/Apache.Arrow/C/CArrowArrayExporter.cs b/csharp/src/Apache.Arrow/C/CArrowArrayExporter.cs index 16aaa3874b370..2d9febea33f54 100644 --- a/csharp/src/Apache.Arrow/C/CArrowArrayExporter.cs +++ b/csharp/src/Apache.Arrow/C/CArrowArrayExporter.cs @@ -15,6 +15,7 @@ using System; +using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Apache.Arrow.Memory; @@ -59,8 +60,6 @@ public static unsafe void ExportArray(IArrowArray array, CArrowArray* cArray) try { ConvertArray(allocationOwner, array.Data, cArray); - cArray->release = ReleaseArrayPtr; - cArray->private_data = FromDisposable(allocationOwner); allocationOwner = null; } finally @@ -102,8 +101,6 @@ public static unsafe void ExportRecordBatch(RecordBatch batch, CArrowArray* cArr try { ConvertRecordBatch(allocationOwner, batch, cArray); - cArray->release = ReleaseArrayPtr; - cArray->private_data = FromDisposable(allocationOwner); allocationOwner = null; } finally @@ -118,7 +115,7 @@ private unsafe static void ConvertArray(ExportedAllocationOwner sharedOwner, Arr cArray->offset = array.Offset; cArray->null_count = array.NullCount; cArray->release = ReleaseArrayPtr; - cArray->private_data = null; + cArray->private_data = MakePrivateData(sharedOwner); cArray->n_buffers = array.Buffers?.Length ?? 0; cArray->buffers = null; @@ -131,7 +128,7 @@ private unsafe static void ConvertArray(ExportedAllocationOwner sharedOwner, Arr IntPtr ptr; if (!buffer.TryExport(sharedOwner, out ptr)) { - throw new NotSupportedException($"An ArrowArray of type {array.DataType.TypeId} could not be exported"); + throw new NotSupportedException($"An ArrowArray of type {array.DataType.TypeId} could not be exported: failed on buffer #{i}"); } cArray->buffers[i] = (byte*)ptr; } @@ -144,7 +141,7 @@ private unsafe static void ConvertArray(ExportedAllocationOwner sharedOwner, Arr cArray->children = (CArrowArray**)sharedOwner.Allocate(IntPtr.Size * array.Children.Length); for (int i = 0; i < array.Children.Length; i++) { - cArray->children[i] = CArrowArray.Create(); + cArray->children[i] = MakeArray(sharedOwner); ConvertArray(sharedOwner, array.Children[i], cArray->children[i]); } } @@ -152,7 +149,7 @@ private unsafe static void ConvertArray(ExportedAllocationOwner sharedOwner, Arr cArray->dictionary = null; if (array.Dictionary != null) { - cArray->dictionary = CArrowArray.Create(); + cArray->dictionary = MakeArray(sharedOwner); ConvertArray(sharedOwner, array.Dictionary, cArray->dictionary); } } @@ -163,20 +160,24 @@ private unsafe static void ConvertRecordBatch(ExportedAllocationOwner sharedOwne cArray->offset = 0; cArray->null_count = 0; cArray->release = ReleaseArrayPtr; - cArray->private_data = null; + cArray->private_data = MakePrivateData(sharedOwner); cArray->n_buffers = 1; cArray->buffers = (byte**)sharedOwner.Allocate(IntPtr.Size); cArray->n_children = batch.ColumnCount; cArray->children = null; + // XXX sharing the same ExportedAllocationOwner for all columns + // and child arrays makes memory tracking inflexible. + // If the consumer keeps only a single record batch column, + // the entire record batch memory is nevertheless kept alive. if (cArray->n_children > 0) { cArray->children = (CArrowArray**)sharedOwner.Allocate(IntPtr.Size * batch.ColumnCount); int i = 0; foreach (IArrowArray child in batch.Arrays) { - cArray->children[i] = CArrowArray.Create(); + cArray->children[i] = MakeArray(sharedOwner); ConvertArray(sharedOwner, child.Data, cArray->children[i]); i++; } @@ -190,26 +191,44 @@ private unsafe static void ConvertRecordBatch(ExportedAllocationOwner sharedOwne #endif private unsafe static void ReleaseArray(CArrowArray* cArray) { - Dispose(&cArray->private_data); + for (long i = 0; i < cArray->n_children; i++) + { + CArrowArray.CallReleaseFunc(cArray->children[i]); + } + if (cArray->dictionary != null) + { + CArrowArray.CallReleaseFunc(cArray->dictionary); + } + DisposePrivateData(&cArray->private_data); cArray->release = default; } - private unsafe static void* FromDisposable(IDisposable disposable) + private unsafe static CArrowArray* MakeArray(ExportedAllocationOwner sharedOwner) + { + var array = (CArrowArray*)sharedOwner.Allocate(sizeof(CArrowArray)); + *array = default; + return array; + } + + private unsafe static void* MakePrivateData(ExportedAllocationOwner sharedOwner) { - GCHandle gch = GCHandle.Alloc(disposable); + GCHandle gch = GCHandle.Alloc(sharedOwner); + sharedOwner.IncRef(); return (void*)GCHandle.ToIntPtr(gch); } - private unsafe static void Dispose(void** ptr) + private unsafe static void DisposePrivateData(void** ptr) { - GCHandle gch = GCHandle.FromIntPtr((IntPtr)(*ptr)); + GCHandle gch = GCHandle.FromIntPtr((IntPtr) (*ptr)); if (!gch.IsAllocated) { return; } - ((IDisposable)gch.Target).Dispose(); + // We can't call IDisposable.Dispose() here as we create multiple + // GCHandles to the same object. Instead, refcounting ensures + // timely memory deallocation when all GCHandles are freed. + ((ExportedAllocationOwner) gch.Target).DecRef(); gch.Free(); - *ptr = null; } } } diff --git a/csharp/src/Apache.Arrow/C/CArrowSchemaImporter.cs b/csharp/src/Apache.Arrow/C/CArrowSchemaImporter.cs index 42c8cdd5ef548..f7216df869abd 100644 --- a/csharp/src/Apache.Arrow/C/CArrowSchemaImporter.cs +++ b/csharp/src/Apache.Arrow/C/CArrowSchemaImporter.cs @@ -37,7 +37,7 @@ public static class CArrowSchemaImporter /// Typically, you will allocate an uninitialized CArrowSchema pointer, /// pass that to external function, and then use this method to import /// the result. - /// + /// /// /// CArrowSchema* importedPtr = CArrowSchema.Create(); /// foreign_export_function(importedPtr); @@ -62,7 +62,7 @@ public static unsafe ArrowType ImportType(CArrowSchema* ptr) /// Typically, you will allocate an uninitialized CArrowSchema pointer, /// pass that to external function, and then use this method to import /// the result. - /// + /// /// /// CArrowSchema* importedPtr = CArrowSchema.Create(); /// foreign_export_function(importedPtr); @@ -87,7 +87,7 @@ public static unsafe Field ImportField(CArrowSchema* ptr) /// Typically, you will allocate an uninitialized CArrowSchema pointer, /// pass that to external function, and then use this method to import /// the result. - /// + /// /// /// CArrowSchema* importedPtr = CArrowSchema.Create(); /// foreign_export_function(importedPtr); @@ -241,6 +241,10 @@ public ArrowType GetAsType() }; string timezone = format.Substring(format.IndexOf(':') + 1); + if (timezone.Length == 0) + { + timezone = null; + } return new TimestampType(timeUnit, timezone); } diff --git a/csharp/src/Apache.Arrow/Memory/ExportedAllocationOwner.cs b/csharp/src/Apache.Arrow/Memory/ExportedAllocationOwner.cs index e872dc5425e06..05529899e410c 100644 --- a/csharp/src/Apache.Arrow/Memory/ExportedAllocationOwner.cs +++ b/csharp/src/Apache.Arrow/Memory/ExportedAllocationOwner.cs @@ -14,8 +14,10 @@ // limitations under the License. using System; +using System.Diagnostics; using System.Collections.Generic; using System.Runtime.InteropServices; +using System.Threading; namespace Apache.Arrow.Memory { @@ -23,6 +25,8 @@ internal sealed class ExportedAllocationOwner : INativeAllocationOwner, IDisposa { private readonly List _pointers = new List(); private int _allocationSize; + private long _referenceCount; + private bool _disposed; ~ExportedAllocationOwner() { @@ -47,8 +51,25 @@ public void Release(IntPtr ptr, int offset, int length) throw new InvalidOperationException(); } + public void IncRef() + { + Interlocked.Increment(ref _referenceCount); + } + + public void DecRef() + { + if (Interlocked.Decrement(ref _referenceCount) == 0) + { + Dispose(); + } + } + public void Dispose() { + if (_disposed) + { + return; + } for (int i = 0; i < _pointers.Count; i++) { if (_pointers[i] != IntPtr.Zero) @@ -59,6 +80,7 @@ public void Dispose() } GC.RemoveMemoryPressure(_allocationSize); GC.SuppressFinalize(this); + _disposed = true; } } } diff --git a/csharp/test/Apache.Arrow.IntegrationTest/Apache.Arrow.IntegrationTest.csproj b/csharp/test/Apache.Arrow.IntegrationTest/Apache.Arrow.IntegrationTest.csproj index a6c635a79a45f..cb7f7ae896ee2 100644 --- a/csharp/test/Apache.Arrow.IntegrationTest/Apache.Arrow.IntegrationTest.csproj +++ b/csharp/test/Apache.Arrow.IntegrationTest/Apache.Arrow.IntegrationTest.csproj @@ -3,6 +3,7 @@ Exe + true net7.0 @@ -13,4 +14,4 @@ - \ No newline at end of file + diff --git a/csharp/test/Apache.Arrow.IntegrationTest/CDataInterface.cs b/csharp/test/Apache.Arrow.IntegrationTest/CDataInterface.cs new file mode 100644 index 0000000000000..2fabae1a2a3b3 --- /dev/null +++ b/csharp/test/Apache.Arrow.IntegrationTest/CDataInterface.cs @@ -0,0 +1,77 @@ +// 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 System; +using System.Collections.Generic; +using System.Data; +using System.Diagnostics; +using System.IO; +using Apache.Arrow.C; +using Apache.Arrow.Arrays; +using Apache.Arrow.Types; + +namespace Apache.Arrow.IntegrationTest +{ + /// + /// Bridge for C Data Interface integration testing. + /// These methods are called from the Python integration testing + /// harness provided by Archery. + /// + public static class CDataInterface + { + // Archery uses the `pythonnet` library (*) to invoke .Net DLLs. + // `pythonnet` is only able to marshal simple types such as int and + // str, which is why we provide trivial wrappers around other APIs. + // + // (*) https://pythonnet.github.io/ + + public static void Initialize() + { + // Allow debugging using Debug.WriteLine() + Trace.Listeners.Add(new ConsoleTraceListener()); + } + + public static unsafe Schema ImportSchema(long ptr) + { + return CArrowSchemaImporter.ImportSchema((CArrowSchema*) ptr); + } + + public static unsafe void ExportSchema(Schema schema, long ptr) + { + CArrowSchemaExporter.ExportSchema(schema, (CArrowSchema*) ptr); + } + + public static unsafe RecordBatch ImportRecordBatch(long ptr, Schema schema) + { + return CArrowArrayImporter.ImportRecordBatch((CArrowArray*) ptr, schema); + } + + public static unsafe void ExportRecordBatch(RecordBatch batch, long ptr) + { + CArrowArrayExporter.ExportRecordBatch(batch, (CArrowArray*) ptr); + } + + public static JsonFile ParseJsonFile(string jsonPath) + { + return JsonFile.Parse(new FileInfo(jsonPath)); + } + + public static void RunGC() + { + GC.Collect(); + GC.WaitForPendingFinalizers(); + } + } +} diff --git a/csharp/test/Apache.Arrow.IntegrationTest/IntegrationCommand.cs b/csharp/test/Apache.Arrow.IntegrationTest/IntegrationCommand.cs index 1e76ee505a516..d19d19f1ce7c1 100644 --- a/csharp/test/Apache.Arrow.IntegrationTest/IntegrationCommand.cs +++ b/csharp/test/Apache.Arrow.IntegrationTest/IntegrationCommand.cs @@ -72,7 +72,7 @@ private async Task Validate() return -1; } - Schema jsonFileSchema = CreateSchema(jsonFile.Schema); + Schema jsonFileSchema = jsonFile.Schema.ToArrow(); Schema arrowFileSchema = reader.Schema; SchemaComparer.Compare(jsonFileSchema, arrowFileSchema); @@ -80,7 +80,7 @@ private async Task Validate() for (int i = 0; i < batchCount; i++) { RecordBatch arrowFileRecordBatch = reader.ReadNextRecordBatch(); - RecordBatch jsonFileRecordBatch = CreateRecordBatch(jsonFileSchema, jsonFile.Batches[i]); + RecordBatch jsonFileRecordBatch = jsonFile.Batches[i].ToArrow(jsonFileSchema); ArrowReaderVerifier.CompareBatches(jsonFileRecordBatch, arrowFileRecordBatch, strictCompare: false); } @@ -98,7 +98,7 @@ private async Task Validate() private async Task JsonToArrow() { JsonFile jsonFile = await ParseJsonFile(); - Schema schema = CreateSchema(jsonFile.Schema); + Schema schema = jsonFile.Schema.ToArrow(); using (FileStream fs = ArrowFileInfo.Create()) { @@ -107,7 +107,7 @@ private async Task JsonToArrow() foreach (var jsonRecordBatch in jsonFile.Batches) { - RecordBatch batch = CreateRecordBatch(schema, jsonRecordBatch); + RecordBatch batch = jsonRecordBatch.ToArrow(schema); await writer.WriteRecordBatchAsync(batch); } await writer.WriteEndAsync(); @@ -117,595 +117,6 @@ private async Task JsonToArrow() return 0; } - private RecordBatch CreateRecordBatch(Schema schema, JsonRecordBatch jsonRecordBatch) - { - if (schema.FieldsList.Count != jsonRecordBatch.Columns.Count) - { - throw new NotSupportedException($"jsonRecordBatch.Columns.Count '{jsonRecordBatch.Columns.Count}' doesn't match schema field count '{schema.FieldsList.Count}'"); - } - - List arrays = new List(jsonRecordBatch.Columns.Count); - for (int i = 0; i < jsonRecordBatch.Columns.Count; i++) - { - JsonFieldData data = jsonRecordBatch.Columns[i]; - Field field = schema.FieldsList[i]; - ArrayCreator creator = new ArrayCreator(data); - field.DataType.Accept(creator); - arrays.Add(creator.Array); - } - - return new RecordBatch(schema, arrays, jsonRecordBatch.Count); - } - - private static Schema CreateSchema(JsonSchema jsonSchema) - { - Schema.Builder builder = new Schema.Builder(); - for (int i = 0; i < jsonSchema.Fields.Count; i++) - { - builder.Field(f => CreateField(f, jsonSchema.Fields[i])); - } - return builder.Build(); - } - - private static void CreateField(Field.Builder builder, JsonField jsonField) - { - Field[] children = null; - if (jsonField.Children?.Count > 0) - { - children = new Field[jsonField.Children.Count]; - for (int i = 0; i < jsonField.Children.Count; i++) - { - Field.Builder field = new Field.Builder(); - CreateField(field, jsonField.Children[i]); - children[i] = field.Build(); - } - } - - builder.Name(jsonField.Name) - .DataType(ToArrowType(jsonField.Type, children)) - .Nullable(jsonField.Nullable); - - if (jsonField.Metadata != null) - { - builder.Metadata(jsonField.Metadata); - } - } - - private static IArrowType ToArrowType(JsonArrowType type, Field[] children) - { - return type.Name switch - { - "bool" => BooleanType.Default, - "int" => ToIntArrowType(type), - "floatingpoint" => ToFloatingPointArrowType(type), - "decimal" => ToDecimalArrowType(type), - "binary" => BinaryType.Default, - "utf8" => StringType.Default, - "fixedsizebinary" => new FixedSizeBinaryType(type.ByteWidth), - "date" => ToDateArrowType(type), - "time" => ToTimeArrowType(type), - "timestamp" => ToTimestampArrowType(type), - "list" => ToListArrowType(type, children), - "fixedsizelist" => ToFixedSizeListArrowType(type, children), - "struct" => ToStructArrowType(type, children), - "union" => ToUnionArrowType(type, children), - "null" => NullType.Default, - _ => throw new NotSupportedException($"JsonArrowType not supported: {type.Name}") - }; - } - - private static IArrowType ToIntArrowType(JsonArrowType type) - { - return (type.BitWidth, type.IsSigned) switch - { - (8, true) => Int8Type.Default, - (8, false) => UInt8Type.Default, - (16, true) => Int16Type.Default, - (16, false) => UInt16Type.Default, - (32, true) => Int32Type.Default, - (32, false) => UInt32Type.Default, - (64, true) => Int64Type.Default, - (64, false) => UInt64Type.Default, - _ => throw new NotSupportedException($"Int type not supported: {type.BitWidth}, {type.IsSigned}") - }; - } - - private static IArrowType ToFloatingPointArrowType(JsonArrowType type) - { - return type.FloatingPointPrecision switch - { - "SINGLE" => FloatType.Default, - "DOUBLE" => DoubleType.Default, - _ => throw new NotSupportedException($"FloatingPoint type not supported: {type.FloatingPointPrecision}") - }; - } - - private static IArrowType ToDecimalArrowType(JsonArrowType type) - { - return type.BitWidth switch - { - 256 => new Decimal256Type(type.DecimalPrecision, type.Scale), - _ => new Decimal128Type(type.DecimalPrecision, type.Scale), - }; - } - - private static IArrowType ToDateArrowType(JsonArrowType type) - { - return type.Unit switch - { - "DAY" => Date32Type.Default, - "MILLISECOND" => Date64Type.Default, - _ => throw new NotSupportedException($"Date type not supported: {type.Unit}") - }; - } - - private static IArrowType ToTimeArrowType(JsonArrowType type) - { - return (type.Unit, type.BitWidth) switch - { - ("SECOND", 32) => new Time32Type(TimeUnit.Second), - ("SECOND", 64) => new Time64Type(TimeUnit.Second), - ("MILLISECOND", 32) => new Time32Type(TimeUnit.Millisecond), - ("MILLISECOND", 64) => new Time64Type(TimeUnit.Millisecond), - ("MICROSECOND", 32) => new Time32Type(TimeUnit.Microsecond), - ("MICROSECOND", 64) => new Time64Type(TimeUnit.Microsecond), - ("NANOSECOND", 32) => new Time32Type(TimeUnit.Nanosecond), - ("NANOSECOND", 64) => new Time64Type(TimeUnit.Nanosecond), - _ => throw new NotSupportedException($"Time type not supported: {type.Unit}, {type.BitWidth}") - }; - } - - private static IArrowType ToTimestampArrowType(JsonArrowType type) - { - return type.Unit switch - { - "SECOND" => new TimestampType(TimeUnit.Second, type.Timezone), - "MILLISECOND" => new TimestampType(TimeUnit.Millisecond, type.Timezone), - "MICROSECOND" => new TimestampType(TimeUnit.Microsecond, type.Timezone), - "NANOSECOND" => new TimestampType(TimeUnit.Nanosecond, type.Timezone), - _ => throw new NotSupportedException($"Time type not supported: {type.Unit}, {type.BitWidth}") - }; - } - - private static IArrowType ToListArrowType(JsonArrowType type, Field[] children) - { - return new ListType(children[0]); - } - - private static IArrowType ToFixedSizeListArrowType(JsonArrowType type, Field[] children) - { - return new FixedSizeListType(children[0], type.ListSize); - } - - private static IArrowType ToStructArrowType(JsonArrowType type, Field[] children) - { - return new StructType(children); - } - - private static IArrowType ToUnionArrowType(JsonArrowType type, Field[] children) - { - UnionMode mode = type.Mode switch - { - "SPARSE" => UnionMode.Sparse, - "DENSE" => UnionMode.Dense, - _ => throw new NotSupportedException($"Union mode not supported: {type.Mode}"), - }; - return new UnionType(children, type.TypeIds, mode); - } - - private class ArrayCreator : - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor, - IArrowTypeVisitor - { - private JsonFieldData JsonFieldData { get; set; } - public IArrowArray Array { get; private set; } - - public ArrayCreator(JsonFieldData jsonFieldData) - { - JsonFieldData = jsonFieldData; - } - - public void Visit(BooleanType type) - { - ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); - ArrowBuffer.BitmapBuilder valueBuilder = new ArrowBuffer.BitmapBuilder(validityBuffer.Length); - - var json = JsonFieldData.Data.GetRawText(); - bool[] values = JsonSerializer.Deserialize(json); - - foreach (bool value in values) - { - valueBuilder.Append(value); - } - ArrowBuffer valueBuffer = valueBuilder.Build(); - - Array = new BooleanArray( - valueBuffer, validityBuffer, - JsonFieldData.Count, nullCount, 0); - } - - public void Visit(Int8Type type) => GenerateArray((v, n, c, nc, o) => new Int8Array(v, n, c, nc, o)); - public void Visit(Int16Type type) => GenerateArray((v, n, c, nc, o) => new Int16Array(v, n, c, nc, o)); - public void Visit(Int32Type type) => GenerateArray((v, n, c, nc, o) => new Int32Array(v, n, c, nc, o)); - public void Visit(Int64Type type) => GenerateLongArray((v, n, c, nc, o) => new Int64Array(v, n, c, nc, o), s => long.Parse(s)); - public void Visit(UInt8Type type) => GenerateArray((v, n, c, nc, o) => new UInt8Array(v, n, c, nc, o)); - public void Visit(UInt16Type type) => GenerateArray((v, n, c, nc, o) => new UInt16Array(v, n, c, nc, o)); - public void Visit(UInt32Type type) => GenerateArray((v, n, c, nc, o) => new UInt32Array(v, n, c, nc, o)); - public void Visit(UInt64Type type) => GenerateLongArray((v, n, c, nc, o) => new UInt64Array(v, n, c, nc, o), s => ulong.Parse(s)); - public void Visit(FloatType type) => GenerateArray((v, n, c, nc, o) => new FloatArray(v, n, c, nc, o)); - public void Visit(DoubleType type) => GenerateArray((v, n, c, nc, o) => new DoubleArray(v, n, c, nc, o)); - public void Visit(Time32Type type) => GenerateArray((v, n, c, nc, o) => new Time32Array(type, v, n, c, nc, o)); - public void Visit(Time64Type type) => GenerateLongArray((v, n, c, nc, o) => new Time64Array(type, v, n, c, nc, o), s => long.Parse(s)); - - public void Visit(Decimal128Type type) - { - Array = new Decimal128Array(GetDecimalArrayData(type)); - } - - public void Visit(Decimal256Type type) - { - Array = new Decimal256Array(GetDecimalArrayData(type)); - } - - public void Visit(NullType type) - { - Array = new NullArray(JsonFieldData.Count); - } - - private ArrayData GetDecimalArrayData(FixedSizeBinaryType type) - { - ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); - - var json = JsonFieldData.Data.GetRawText(); - string[] values = JsonSerializer.Deserialize(json, s_options); - - Span buffer = stackalloc byte[type.ByteWidth]; - - ArrowBuffer.Builder valueBuilder = new ArrowBuffer.Builder(); - foreach (string value in values) - { - buffer.Fill(0); - - BigInteger bigInteger = BigInteger.Parse(value); - if (!bigInteger.TryWriteBytes(buffer, out int bytesWritten, false, !BitConverter.IsLittleEndian)) - { - throw new InvalidDataException($"Decimal data was too big to fit into {type.BitWidth} bits."); - } - - if (bigInteger.Sign == -1) - { - buffer.Slice(bytesWritten).Fill(255); - } - - valueBuilder.Append(buffer); - } - ArrowBuffer valueBuffer = valueBuilder.Build(default); - - return new ArrayData(type, JsonFieldData.Count, nullCount, 0, new[] { validityBuffer, valueBuffer }); - } - - public void Visit(Date32Type type) - { - ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); - - ArrowBuffer.Builder valueBuilder = new ArrowBuffer.Builder(JsonFieldData.Count); - var json = JsonFieldData.Data.GetRawText(); - int[] values = JsonSerializer.Deserialize(json, s_options); - - foreach (int value in values) - { - valueBuilder.Append(value); - } - ArrowBuffer valueBuffer = valueBuilder.Build(); - - Array = new Date32Array( - valueBuffer, validityBuffer, - JsonFieldData.Count, nullCount, 0); - } - - public void Visit(Date64Type type) - { - ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); - - ArrowBuffer.Builder valueBuilder = new ArrowBuffer.Builder(JsonFieldData.Count); - var json = JsonFieldData.Data.GetRawText(); - string[] values = JsonSerializer.Deserialize(json, s_options); - - foreach (string value in values) - { - valueBuilder.Append(long.Parse(value)); - } - ArrowBuffer valueBuffer = valueBuilder.Build(); - - Array = new Date64Array( - valueBuffer, validityBuffer, - JsonFieldData.Count, nullCount, 0); - } - - public void Visit(TimestampType type) - { - ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); - - ArrowBuffer.Builder valueBuilder = new ArrowBuffer.Builder(JsonFieldData.Count); - var json = JsonFieldData.Data.GetRawText(); - string[] values = JsonSerializer.Deserialize(json, s_options); - - foreach (string value in values) - { - valueBuilder.Append(long.Parse(value)); - } - ArrowBuffer valueBuffer = valueBuilder.Build(); - - Array = new TimestampArray( - type, valueBuffer, validityBuffer, - JsonFieldData.Count, nullCount, 0); - } - - public void Visit(StringType type) - { - ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); - ArrowBuffer offsetBuffer = GetOffsetBuffer(); - - var json = JsonFieldData.Data.GetRawText(); - string[] values = JsonSerializer.Deserialize(json, s_options); - - ArrowBuffer.Builder valueBuilder = new ArrowBuffer.Builder(); - foreach (string value in values) - { - valueBuilder.Append(Encoding.UTF8.GetBytes(value)); - } - ArrowBuffer valueBuffer = valueBuilder.Build(default); - - Array = new StringArray(JsonFieldData.Count, offsetBuffer, valueBuffer, validityBuffer, nullCount); - } - - public void Visit(BinaryType type) - { - ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); - ArrowBuffer offsetBuffer = GetOffsetBuffer(); - - var json = JsonFieldData.Data.GetRawText(); - string[] values = JsonSerializer.Deserialize(json, s_options); - - ArrowBuffer.Builder valueBuilder = new ArrowBuffer.Builder(); - foreach (string value in values) - { - valueBuilder.Append(ConvertHexStringToByteArray(value)); - } - ArrowBuffer valueBuffer = valueBuilder.Build(default); - - ArrayData arrayData = new ArrayData(type, JsonFieldData.Count, nullCount, 0, new[] { validityBuffer, offsetBuffer, valueBuffer }); - Array = new BinaryArray(arrayData); - } - - public void Visit(FixedSizeBinaryType type) - { - ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); - - var json = JsonFieldData.Data.GetRawText(); - string[] values = JsonSerializer.Deserialize(json, s_options); - - ArrowBuffer.Builder valueBuilder = new ArrowBuffer.Builder(); - foreach (string value in values) - { - valueBuilder.Append(ConvertHexStringToByteArray(value)); - } - ArrowBuffer valueBuffer = valueBuilder.Build(default); - - ArrayData arrayData = new ArrayData(type, JsonFieldData.Count, nullCount, 0, new[] { validityBuffer, valueBuffer }); - Array = new FixedSizeBinaryArray(arrayData); - } - - public void Visit(ListType type) - { - ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); - ArrowBuffer offsetBuffer = GetOffsetBuffer(); - - var data = JsonFieldData; - JsonFieldData = data.Children[0]; - type.ValueDataType.Accept(this); - JsonFieldData = data; - - ArrayData arrayData = new ArrayData(type, JsonFieldData.Count, nullCount, 0, - new[] { validityBuffer, offsetBuffer }, new[] { Array.Data }); - Array = new ListArray(arrayData); - } - - public void Visit(FixedSizeListType type) - { - ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); - - var data = JsonFieldData; - JsonFieldData = data.Children[0]; - type.ValueDataType.Accept(this); - JsonFieldData = data; - - ArrayData arrayData = new ArrayData(type, JsonFieldData.Count, nullCount, 0, - new[] { validityBuffer }, new[] { Array.Data }); - Array = new FixedSizeListArray(arrayData); - } - - public void Visit(StructType type) - { - ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); - - ArrayData[] children = new ArrayData[type.Fields.Count]; - - var data = JsonFieldData; - for (int i = 0; i < children.Length; i++) - { - JsonFieldData = data.Children[i]; - type.Fields[i].DataType.Accept(this); - children[i] = Array.Data; - } - JsonFieldData = data; - - ArrayData arrayData = new ArrayData(type, JsonFieldData.Count, nullCount, 0, - new[] { validityBuffer }, children); - Array = new StructArray(arrayData); - } - - public void Visit(UnionType type) - { - ArrowBuffer[] buffers; - if (type.Mode == UnionMode.Dense) - { - buffers = new ArrowBuffer[2]; - buffers[1] = GetOffsetBuffer(); - } - else - { - buffers = new ArrowBuffer[1]; - } - buffers[0] = GetTypeIdBuffer(); - - ArrayData[] children = GetChildren(type); - - int nullCount = 0; - ArrayData arrayData = new ArrayData(type, JsonFieldData.Count, nullCount, 0, buffers, children); - Array = UnionArray.Create(arrayData); - } - - private ArrayData[] GetChildren(NestedType type) - { - ArrayData[] children = new ArrayData[type.Fields.Count]; - - var data = JsonFieldData; - for (int i = 0; i < children.Length; i++) - { - JsonFieldData = data.Children[i]; - type.Fields[i].DataType.Accept(this); - children[i] = Array.Data; - } - JsonFieldData = data; - - return children; - } - - private static byte[] ConvertHexStringToByteArray(string hexString) - { - byte[] data = new byte[hexString.Length / 2]; - for (int index = 0; index < data.Length; index++) - { - data[index] = byte.Parse(hexString.AsSpan(index * 2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture); - } - - return data; - } - - private static readonly JsonSerializerOptions s_options = new JsonSerializerOptions() - { - Converters = - { - new ByteArrayConverter() - } - }; - - private void GenerateArray(Func createArray) - where TArray : PrimitiveArray - where T : struct - { - ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); - - ArrowBuffer.Builder valueBuilder = new ArrowBuffer.Builder(JsonFieldData.Count); - var json = JsonFieldData.Data.GetRawText(); - T[] values = JsonSerializer.Deserialize(json, s_options); - - foreach (T value in values) - { - valueBuilder.Append(value); - } - ArrowBuffer valueBuffer = valueBuilder.Build(); - - Array = createArray( - valueBuffer, validityBuffer, - JsonFieldData.Count, nullCount, 0); - } - - private void GenerateLongArray(Func createArray, Func parse) - where TArray : PrimitiveArray - where T : struct - { - ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); - - ArrowBuffer.Builder valueBuilder = new ArrowBuffer.Builder(JsonFieldData.Count); - var json = JsonFieldData.Data.GetRawText(); - string[] values = JsonSerializer.Deserialize(json); - - foreach (string value in values) - { - valueBuilder.Append(parse(value)); - } - ArrowBuffer valueBuffer = valueBuilder.Build(); - - Array = createArray( - valueBuffer, validityBuffer, - JsonFieldData.Count, nullCount, 0); - } - - private ArrowBuffer GetOffsetBuffer() - { - if (JsonFieldData.Count == 0) { return ArrowBuffer.Empty; } - ArrowBuffer.Builder valueOffsets = new ArrowBuffer.Builder(JsonFieldData.Offset.Length); - valueOffsets.AppendRange(JsonFieldData.Offset); - return valueOffsets.Build(default); - } - - private ArrowBuffer GetTypeIdBuffer() - { - ArrowBuffer.Builder typeIds = new ArrowBuffer.Builder(JsonFieldData.TypeId.Length); - for (int i = 0; i < JsonFieldData.TypeId.Length; i++) - { - typeIds.Append(checked((byte)JsonFieldData.TypeId[i])); - } - return typeIds.Build(default); - } - - private ArrowBuffer GetValidityBuffer(out int nullCount) - { - if (JsonFieldData.Validity == null) - { - nullCount = 0; - return ArrowBuffer.Empty; - } - - ArrowBuffer.BitmapBuilder validityBuilder = new ArrowBuffer.BitmapBuilder(JsonFieldData.Validity.Length); - validityBuilder.AppendRange(JsonFieldData.Validity); - - nullCount = validityBuilder.UnsetBitCount; - return validityBuilder.Build(); - } - - public void Visit(IArrowType type) - { - throw new NotImplementedException($"{type.Name} not implemented"); - } - } - private async Task StreamToFile() { using ArrowStreamReader reader = new ArrowStreamReader(Console.OpenStandardInput()); @@ -752,14 +163,7 @@ private async Task FileToStream() private async ValueTask ParseJsonFile() { - using var fileStream = JsonFileInfo.OpenRead(); - JsonSerializerOptions options = new JsonSerializerOptions() - { - PropertyNamingPolicy = JsonFileNamingPolicy.Instance, - }; - options.Converters.Add(new ValidityConverter()); - - return await JsonSerializer.DeserializeAsync(fileStream, options); + return await JsonFile.ParseAsync(JsonFileInfo); } } } diff --git a/csharp/test/Apache.Arrow.IntegrationTest/JsonFile.cs b/csharp/test/Apache.Arrow.IntegrationTest/JsonFile.cs index 112eeabcb9931..85f66890edf47 100644 --- a/csharp/test/Apache.Arrow.IntegrationTest/JsonFile.cs +++ b/csharp/test/Apache.Arrow.IntegrationTest/JsonFile.cs @@ -15,8 +15,16 @@ using System; using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Numerics; +using System.Text; using System.Text.Json; using System.Text.Json.Serialization; +using System.Threading.Tasks; +using Apache.Arrow.Arrays; +using Apache.Arrow.Types; namespace Apache.Arrow.IntegrationTest { @@ -25,12 +33,200 @@ public class JsonFile public JsonSchema Schema { get; set; } public List Batches { get; set; } //public List Dictionaries {get;set;} + + public static async ValueTask ParseAsync(FileInfo fileInfo) + { + using var fileStream = fileInfo.OpenRead(); + var options = GetJsonOptions(); + return await JsonSerializer.DeserializeAsync(fileStream, options); + } + + public static JsonFile Parse(FileInfo fileInfo) + { + using var fileStream = fileInfo.OpenRead(); + var options = GetJsonOptions(); + return JsonSerializer.Deserialize(fileStream, options); + } + + private static JsonSerializerOptions GetJsonOptions() + { + JsonSerializerOptions options = new JsonSerializerOptions() + { + PropertyNamingPolicy = JsonFileNamingPolicy.Instance, + }; + options.Converters.Add(new ValidityConverter()); + return options; + } } public class JsonSchema { public List Fields { get; set; } public JsonMetadata Metadata { get; set; } + + /// + /// Decode this JSON schema as a Schema instance. + /// + public Schema ToArrow() + { + return CreateSchema(this); + } + + private static Schema CreateSchema(JsonSchema jsonSchema) + { + Schema.Builder builder = new Schema.Builder(); + for (int i = 0; i < jsonSchema.Fields.Count; i++) + { + builder.Field(f => CreateField(f, jsonSchema.Fields[i])); + } + return builder.Build(); + } + + private static void CreateField(Field.Builder builder, JsonField jsonField) + { + Field[] children = null; + if (jsonField.Children?.Count > 0) + { + children = new Field[jsonField.Children.Count]; + for (int i = 0; i < jsonField.Children.Count; i++) + { + Field.Builder field = new Field.Builder(); + CreateField(field, jsonField.Children[i]); + children[i] = field.Build(); + } + } + + builder.Name(jsonField.Name) + .DataType(ToArrowType(jsonField.Type, children)) + .Nullable(jsonField.Nullable); + + if (jsonField.Metadata != null) + { + builder.Metadata(jsonField.Metadata); + } + } + + private static IArrowType ToArrowType(JsonArrowType type, Field[] children) + { + return type.Name switch + { + "bool" => BooleanType.Default, + "int" => ToIntArrowType(type), + "floatingpoint" => ToFloatingPointArrowType(type), + "decimal" => ToDecimalArrowType(type), + "binary" => BinaryType.Default, + "utf8" => StringType.Default, + "fixedsizebinary" => new FixedSizeBinaryType(type.ByteWidth), + "date" => ToDateArrowType(type), + "time" => ToTimeArrowType(type), + "timestamp" => ToTimestampArrowType(type), + "list" => ToListArrowType(type, children), + "fixedsizelist" => ToFixedSizeListArrowType(type, children), + "struct" => ToStructArrowType(type, children), + "union" => ToUnionArrowType(type, children), + "null" => NullType.Default, + _ => throw new NotSupportedException($"JsonArrowType not supported: {type.Name}") + }; + } + + private static IArrowType ToIntArrowType(JsonArrowType type) + { + return (type.BitWidth, type.IsSigned) switch + { + (8, true) => Int8Type.Default, + (8, false) => UInt8Type.Default, + (16, true) => Int16Type.Default, + (16, false) => UInt16Type.Default, + (32, true) => Int32Type.Default, + (32, false) => UInt32Type.Default, + (64, true) => Int64Type.Default, + (64, false) => UInt64Type.Default, + _ => throw new NotSupportedException($"Int type not supported: {type.BitWidth}, {type.IsSigned}") + }; + } + + private static IArrowType ToFloatingPointArrowType(JsonArrowType type) + { + return type.FloatingPointPrecision switch + { + "SINGLE" => FloatType.Default, + "DOUBLE" => DoubleType.Default, + _ => throw new NotSupportedException($"FloatingPoint type not supported: {type.FloatingPointPrecision}") + }; + } + + private static IArrowType ToDecimalArrowType(JsonArrowType type) + { + return type.BitWidth switch + { + 256 => new Decimal256Type(type.DecimalPrecision, type.Scale), + _ => new Decimal128Type(type.DecimalPrecision, type.Scale), + }; + } + + private static IArrowType ToDateArrowType(JsonArrowType type) + { + return type.Unit switch + { + "DAY" => Date32Type.Default, + "MILLISECOND" => Date64Type.Default, + _ => throw new NotSupportedException($"Date type not supported: {type.Unit}") + }; + } + + private static IArrowType ToTimeArrowType(JsonArrowType type) + { + return (type.Unit, type.BitWidth) switch + { + ("SECOND", 32) => new Time32Type(TimeUnit.Second), + ("SECOND", 64) => new Time64Type(TimeUnit.Second), + ("MILLISECOND", 32) => new Time32Type(TimeUnit.Millisecond), + ("MILLISECOND", 64) => new Time64Type(TimeUnit.Millisecond), + ("MICROSECOND", 32) => new Time32Type(TimeUnit.Microsecond), + ("MICROSECOND", 64) => new Time64Type(TimeUnit.Microsecond), + ("NANOSECOND", 32) => new Time32Type(TimeUnit.Nanosecond), + ("NANOSECOND", 64) => new Time64Type(TimeUnit.Nanosecond), + _ => throw new NotSupportedException($"Time type not supported: {type.Unit}, {type.BitWidth}") + }; + } + + private static IArrowType ToTimestampArrowType(JsonArrowType type) + { + return type.Unit switch + { + "SECOND" => new TimestampType(TimeUnit.Second, type.Timezone), + "MILLISECOND" => new TimestampType(TimeUnit.Millisecond, type.Timezone), + "MICROSECOND" => new TimestampType(TimeUnit.Microsecond, type.Timezone), + "NANOSECOND" => new TimestampType(TimeUnit.Nanosecond, type.Timezone), + _ => throw new NotSupportedException($"Time type not supported: {type.Unit}, {type.BitWidth}") + }; + } + + private static IArrowType ToListArrowType(JsonArrowType type, Field[] children) + { + return new ListType(children[0]); + } + + private static IArrowType ToFixedSizeListArrowType(JsonArrowType type, Field[] children) + { + return new FixedSizeListType(children[0], type.ListSize); + } + + private static IArrowType ToStructArrowType(JsonArrowType type, Field[] children) + { + return new StructType(children); + } + + private static IArrowType ToUnionArrowType(JsonArrowType type, Field[] children) + { + UnionMode mode = type.Mode switch + { + "SPARSE" => UnionMode.Sparse, + "DENSE" => UnionMode.Dense, + _ => throw new NotSupportedException($"Union mode not supported: {type.Mode}"), + }; + return new UnionType(children, type.TypeIds, mode); + } } public class JsonField @@ -60,7 +256,7 @@ public class JsonArrowType public int DecimalPrecision => ExtensionData["precision"].GetInt32(); public int Scale { get; set; } - // date and time fields + // date and time fields public string Unit { get; set; } // timestamp fields public string Timezone { get; set; } @@ -74,7 +270,7 @@ public class JsonArrowType // union fields public string Mode { get; set; } public int[] TypeIds { get; set; } - + [JsonExtensionData] public Dictionary ExtensionData { get; set; } } @@ -94,6 +290,446 @@ public class JsonRecordBatch { public int Count { get; set; } public List Columns { get; set; } + + /// + /// Decode this JSON record batch as a RecordBatch instance. + /// + public RecordBatch ToArrow(Schema schema) + { + return CreateRecordBatch(schema, this); + } + + private RecordBatch CreateRecordBatch(Schema schema, JsonRecordBatch jsonRecordBatch) + { + if (schema.FieldsList.Count != jsonRecordBatch.Columns.Count) + { + throw new NotSupportedException($"jsonRecordBatch.Columns.Count '{jsonRecordBatch.Columns.Count}' doesn't match schema field count '{schema.FieldsList.Count}'"); + } + + List arrays = new List(jsonRecordBatch.Columns.Count); + for (int i = 0; i < jsonRecordBatch.Columns.Count; i++) + { + JsonFieldData data = jsonRecordBatch.Columns[i]; + Field field = schema.FieldsList[i]; + ArrayCreator creator = new ArrayCreator(data); + field.DataType.Accept(creator); + arrays.Add(creator.Array); + } + + return new RecordBatch(schema, arrays, jsonRecordBatch.Count); + } + + private class ArrayCreator : + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor, + IArrowTypeVisitor + { + private JsonFieldData JsonFieldData { get; set; } + public IArrowArray Array { get; private set; } + + public ArrayCreator(JsonFieldData jsonFieldData) + { + JsonFieldData = jsonFieldData; + } + + public void Visit(BooleanType type) + { + ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); + ArrowBuffer.BitmapBuilder valueBuilder = new ArrowBuffer.BitmapBuilder(validityBuffer.Length); + + var json = JsonFieldData.Data.GetRawText(); + bool[] values = JsonSerializer.Deserialize(json); + + foreach (bool value in values) + { + valueBuilder.Append(value); + } + ArrowBuffer valueBuffer = valueBuilder.Build(); + + Array = new BooleanArray( + valueBuffer, validityBuffer, + JsonFieldData.Count, nullCount, 0); + } + + public void Visit(Int8Type type) => GenerateArray((v, n, c, nc, o) => new Int8Array(v, n, c, nc, o)); + public void Visit(Int16Type type) => GenerateArray((v, n, c, nc, o) => new Int16Array(v, n, c, nc, o)); + public void Visit(Int32Type type) => GenerateArray((v, n, c, nc, o) => new Int32Array(v, n, c, nc, o)); + public void Visit(Int64Type type) => GenerateLongArray((v, n, c, nc, o) => new Int64Array(v, n, c, nc, o), s => long.Parse(s)); + public void Visit(UInt8Type type) => GenerateArray((v, n, c, nc, o) => new UInt8Array(v, n, c, nc, o)); + public void Visit(UInt16Type type) => GenerateArray((v, n, c, nc, o) => new UInt16Array(v, n, c, nc, o)); + public void Visit(UInt32Type type) => GenerateArray((v, n, c, nc, o) => new UInt32Array(v, n, c, nc, o)); + public void Visit(UInt64Type type) => GenerateLongArray((v, n, c, nc, o) => new UInt64Array(v, n, c, nc, o), s => ulong.Parse(s)); + public void Visit(FloatType type) => GenerateArray((v, n, c, nc, o) => new FloatArray(v, n, c, nc, o)); + public void Visit(DoubleType type) => GenerateArray((v, n, c, nc, o) => new DoubleArray(v, n, c, nc, o)); + public void Visit(Time32Type type) => GenerateArray((v, n, c, nc, o) => new Time32Array(type, v, n, c, nc, o)); + public void Visit(Time64Type type) => GenerateLongArray((v, n, c, nc, o) => new Time64Array(type, v, n, c, nc, o), s => long.Parse(s)); + + public void Visit(Decimal128Type type) + { + Array = new Decimal128Array(GetDecimalArrayData(type)); + } + + public void Visit(Decimal256Type type) + { + Array = new Decimal256Array(GetDecimalArrayData(type)); + } + + public void Visit(NullType type) + { + Array = new NullArray(JsonFieldData.Count); + } + + private ArrayData GetDecimalArrayData(FixedSizeBinaryType type) + { + ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); + + var json = JsonFieldData.Data.GetRawText(); + string[] values = JsonSerializer.Deserialize(json, s_options); + + Span buffer = stackalloc byte[type.ByteWidth]; + + ArrowBuffer.Builder valueBuilder = new ArrowBuffer.Builder(); + foreach (string value in values) + { + buffer.Fill(0); + + BigInteger bigInteger = BigInteger.Parse(value); + if (!bigInteger.TryWriteBytes(buffer, out int bytesWritten, false, !BitConverter.IsLittleEndian)) + { + throw new InvalidDataException($"Decimal data was too big to fit into {type.BitWidth} bits."); + } + + if (bigInteger.Sign == -1) + { + buffer.Slice(bytesWritten).Fill(255); + } + + valueBuilder.Append(buffer); + } + ArrowBuffer valueBuffer = valueBuilder.Build(default); + + return new ArrayData(type, JsonFieldData.Count, nullCount, 0, new[] { validityBuffer, valueBuffer }); + } + + public void Visit(Date32Type type) + { + ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); + + ArrowBuffer.Builder valueBuilder = new ArrowBuffer.Builder(JsonFieldData.Count); + var json = JsonFieldData.Data.GetRawText(); + int[] values = JsonSerializer.Deserialize(json, s_options); + + foreach (int value in values) + { + valueBuilder.Append(value); + } + ArrowBuffer valueBuffer = valueBuilder.Build(); + + Array = new Date32Array( + valueBuffer, validityBuffer, + JsonFieldData.Count, nullCount, 0); + } + + public void Visit(Date64Type type) + { + ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); + + ArrowBuffer.Builder valueBuilder = new ArrowBuffer.Builder(JsonFieldData.Count); + var json = JsonFieldData.Data.GetRawText(); + string[] values = JsonSerializer.Deserialize(json, s_options); + + foreach (string value in values) + { + valueBuilder.Append(long.Parse(value)); + } + ArrowBuffer valueBuffer = valueBuilder.Build(); + + Array = new Date64Array( + valueBuffer, validityBuffer, + JsonFieldData.Count, nullCount, 0); + } + + public void Visit(TimestampType type) + { + ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); + + ArrowBuffer.Builder valueBuilder = new ArrowBuffer.Builder(JsonFieldData.Count); + var json = JsonFieldData.Data.GetRawText(); + string[] values = JsonSerializer.Deserialize(json, s_options); + + foreach (string value in values) + { + valueBuilder.Append(long.Parse(value)); + } + ArrowBuffer valueBuffer = valueBuilder.Build(); + + Array = new TimestampArray( + type, valueBuffer, validityBuffer, + JsonFieldData.Count, nullCount, 0); + } + + public void Visit(StringType type) + { + ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); + ArrowBuffer offsetBuffer = GetOffsetBuffer(); + + var json = JsonFieldData.Data.GetRawText(); + string[] values = JsonSerializer.Deserialize(json, s_options); + + ArrowBuffer.Builder valueBuilder = new ArrowBuffer.Builder(); + foreach (string value in values) + { + valueBuilder.Append(Encoding.UTF8.GetBytes(value)); + } + ArrowBuffer valueBuffer = valueBuilder.Build(default); + + Array = new StringArray(JsonFieldData.Count, offsetBuffer, valueBuffer, validityBuffer, nullCount); + } + + public void Visit(BinaryType type) + { + ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); + ArrowBuffer offsetBuffer = GetOffsetBuffer(); + + var json = JsonFieldData.Data.GetRawText(); + string[] values = JsonSerializer.Deserialize(json, s_options); + + ArrowBuffer.Builder valueBuilder = new ArrowBuffer.Builder(); + foreach (string value in values) + { + valueBuilder.Append(ConvertHexStringToByteArray(value)); + } + ArrowBuffer valueBuffer = valueBuilder.Build(default); + + ArrayData arrayData = new ArrayData(type, JsonFieldData.Count, nullCount, 0, new[] { validityBuffer, offsetBuffer, valueBuffer }); + Array = new BinaryArray(arrayData); + } + + public void Visit(FixedSizeBinaryType type) + { + ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); + + var json = JsonFieldData.Data.GetRawText(); + string[] values = JsonSerializer.Deserialize(json, s_options); + + ArrowBuffer.Builder valueBuilder = new ArrowBuffer.Builder(); + foreach (string value in values) + { + valueBuilder.Append(ConvertHexStringToByteArray(value)); + } + ArrowBuffer valueBuffer = valueBuilder.Build(default); + + ArrayData arrayData = new ArrayData(type, JsonFieldData.Count, nullCount, 0, new[] { validityBuffer, valueBuffer }); + Array = new FixedSizeBinaryArray(arrayData); + } + + public void Visit(ListType type) + { + ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); + ArrowBuffer offsetBuffer = GetOffsetBuffer(); + + var data = JsonFieldData; + JsonFieldData = data.Children[0]; + type.ValueDataType.Accept(this); + JsonFieldData = data; + + ArrayData arrayData = new ArrayData(type, JsonFieldData.Count, nullCount, 0, + new[] { validityBuffer, offsetBuffer }, new[] { Array.Data }); + Array = new ListArray(arrayData); + } + + public void Visit(FixedSizeListType type) + { + ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); + + var data = JsonFieldData; + JsonFieldData = data.Children[0]; + type.ValueDataType.Accept(this); + JsonFieldData = data; + + ArrayData arrayData = new ArrayData(type, JsonFieldData.Count, nullCount, 0, + new[] { validityBuffer }, new[] { Array.Data }); + Array = new FixedSizeListArray(arrayData); + } + + public void Visit(StructType type) + { + ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); + + ArrayData[] children = new ArrayData[type.Fields.Count]; + + var data = JsonFieldData; + for (int i = 0; i < children.Length; i++) + { + JsonFieldData = data.Children[i]; + type.Fields[i].DataType.Accept(this); + children[i] = Array.Data; + } + JsonFieldData = data; + + ArrayData arrayData = new ArrayData(type, JsonFieldData.Count, nullCount, 0, + new[] { validityBuffer }, children); + Array = new StructArray(arrayData); + } + + public void Visit(UnionType type) + { + ArrowBuffer[] buffers; + if (type.Mode == UnionMode.Dense) + { + buffers = new ArrowBuffer[2]; + buffers[1] = GetOffsetBuffer(); + } + else + { + buffers = new ArrowBuffer[1]; + } + buffers[0] = GetTypeIdBuffer(); + + ArrayData[] children = GetChildren(type); + + int nullCount = 0; + ArrayData arrayData = new ArrayData(type, JsonFieldData.Count, nullCount, 0, buffers, children); + Array = UnionArray.Create(arrayData); + } + + private ArrayData[] GetChildren(NestedType type) + { + ArrayData[] children = new ArrayData[type.Fields.Count]; + + var data = JsonFieldData; + for (int i = 0; i < children.Length; i++) + { + JsonFieldData = data.Children[i]; + type.Fields[i].DataType.Accept(this); + children[i] = Array.Data; + } + JsonFieldData = data; + + return children; + } + + private static byte[] ConvertHexStringToByteArray(string hexString) + { + byte[] data = new byte[hexString.Length / 2]; + for (int index = 0; index < data.Length; index++) + { + data[index] = byte.Parse(hexString.AsSpan(index * 2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture); + } + + return data; + } + + private static readonly JsonSerializerOptions s_options = new JsonSerializerOptions() + { + Converters = + { + new ByteArrayConverter() + } + }; + + private void GenerateArray(Func createArray) + where TArray : PrimitiveArray + where T : struct + { + ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); + + ArrowBuffer.Builder valueBuilder = new ArrowBuffer.Builder(JsonFieldData.Count); + var json = JsonFieldData.Data.GetRawText(); + T[] values = JsonSerializer.Deserialize(json, s_options); + + foreach (T value in values) + { + valueBuilder.Append(value); + } + ArrowBuffer valueBuffer = valueBuilder.Build(); + + Array = createArray( + valueBuffer, validityBuffer, + JsonFieldData.Count, nullCount, 0); + } + + private void GenerateLongArray(Func createArray, Func parse) + where TArray : PrimitiveArray + where T : struct + { + ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); + + ArrowBuffer.Builder valueBuilder = new ArrowBuffer.Builder(JsonFieldData.Count); + var json = JsonFieldData.Data.GetRawText(); + string[] values = JsonSerializer.Deserialize(json); + + foreach (string value in values) + { + valueBuilder.Append(parse(value)); + } + ArrowBuffer valueBuffer = valueBuilder.Build(); + + Array = createArray( + valueBuffer, validityBuffer, + JsonFieldData.Count, nullCount, 0); + } + + private ArrowBuffer GetOffsetBuffer() + { + ArrowBuffer.Builder valueOffsets = new ArrowBuffer.Builder(JsonFieldData.Offset.Length); + valueOffsets.AppendRange(JsonFieldData.Offset); + return valueOffsets.Build(default); + } + + private ArrowBuffer GetTypeIdBuffer() + { + ArrowBuffer.Builder typeIds = new ArrowBuffer.Builder(JsonFieldData.TypeId.Length); + for (int i = 0; i < JsonFieldData.TypeId.Length; i++) + { + typeIds.Append(checked((byte)JsonFieldData.TypeId[i])); + } + return typeIds.Build(default); + } + + private ArrowBuffer GetValidityBuffer(out int nullCount) + { + if (JsonFieldData.Validity == null) + { + nullCount = 0; + return ArrowBuffer.Empty; + } + + ArrowBuffer.BitmapBuilder validityBuilder = new ArrowBuffer.BitmapBuilder(JsonFieldData.Validity.Length); + validityBuilder.AppendRange(JsonFieldData.Validity); + + nullCount = validityBuilder.UnsetBitCount; + return validityBuilder.Build(); + } + + public void Visit(IArrowType type) + { + throw new NotImplementedException($"{type.Name} not implemented"); + } + } } public class JsonFieldData diff --git a/csharp/test/Apache.Arrow.Tests/CDataInterfacePythonTests.cs b/csharp/test/Apache.Arrow.Tests/CDataInterfacePythonTests.cs index f28b89a9cd17e..b6b65a582d953 100644 --- a/csharp/test/Apache.Arrow.Tests/CDataInterfacePythonTests.cs +++ b/csharp/test/Apache.Arrow.Tests/CDataInterfacePythonTests.cs @@ -99,8 +99,8 @@ private static Schema GetTestSchema() .Field(f => f.Name("time64_us").DataType(new Time64Type(TimeUnit.Microsecond)).Nullable(false)) .Field(f => f.Name("time64_ns").DataType(new Time64Type(TimeUnit.Nanosecond)).Nullable(false)) - .Field(f => f.Name("timestamp_ns").DataType(new TimestampType(TimeUnit.Nanosecond, "")).Nullable(false)) - .Field(f => f.Name("timestamp_us").DataType(new TimestampType(TimeUnit.Microsecond, "")).Nullable(false)) + .Field(f => f.Name("timestamp_ns").DataType(new TimestampType(TimeUnit.Nanosecond, (string) null)).Nullable(false)) + .Field(f => f.Name("timestamp_us").DataType(new TimestampType(TimeUnit.Microsecond, (string) null)).Nullable(false)) .Field(f => f.Name("timestamp_us_paris").DataType(new TimestampType(TimeUnit.Microsecond, "Europe/Paris")).Nullable(true)) .Field(f => f.Name("list_string").DataType(new ListType(StringType.Default)).Nullable(false)) diff --git a/dev/archery/archery/integration/runner.py b/dev/archery/archery/integration/runner.py index a780d33cbf323..67f0693df14aa 100644 --- a/dev/archery/archery/integration/runner.py +++ b/dev/archery/archery/integration/runner.py @@ -124,8 +124,8 @@ def run_c_data(self): enabled implementations. """ for producer, consumer in itertools.product( - filter(lambda t: t.C_DATA_EXPORTER, self.testers), - filter(lambda t: t.C_DATA_IMPORTER, self.testers)): + filter(lambda t: t.C_DATA_SCHEMA_EXPORTER, self.testers), + filter(lambda t: t.C_DATA_SCHEMA_IMPORTER, self.testers)): self._compare_c_data_implementations(producer, consumer) log('\n') @@ -428,9 +428,10 @@ def _compare_c_data_implementations( exporter, importer) self._run_test_cases(case_runner, self.json_files, serial=serial) - case_runner = partial(self._run_c_array_test_cases, producer, consumer, - exporter, importer) - self._run_test_cases(case_runner, self.json_files, serial=serial) + if producer.C_DATA_ARRAY_EXPORTER and consumer.C_DATA_ARRAY_IMPORTER: + case_runner = partial(self._run_c_array_test_cases, producer, consumer, + exporter, importer) + self._run_test_cases(case_runner, self.json_files, serial=serial) def _run_c_schema_test_case(self, producer: Tester, consumer: Tester, diff --git a/dev/archery/archery/integration/tester.py b/dev/archery/archery/integration/tester.py index 6a3061992d006..6cde20e61b321 100644 --- a/dev/archery/archery/integration/tester.py +++ b/dev/archery/archery/integration/tester.py @@ -204,9 +204,11 @@ class Tester: # whether the language supports receiving Flight FLIGHT_CLIENT = False # whether the language supports the C Data Interface as an exporter - C_DATA_EXPORTER = False + C_DATA_SCHEMA_EXPORTER = False + C_DATA_ARRAY_EXPORTER = False # whether the language supports the C Data Interface as an importer - C_DATA_IMPORTER = False + C_DATA_SCHEMA_IMPORTER = False + C_DATA_ARRAY_IMPORTER = False # the name used for skipping and shown in the logs name = "unknown" diff --git a/dev/archery/archery/integration/tester_cpp.py b/dev/archery/archery/integration/tester_cpp.py index 9ddc3c480002a..ab642c31aacc6 100644 --- a/dev/archery/archery/integration/tester_cpp.py +++ b/dev/archery/archery/integration/tester_cpp.py @@ -52,8 +52,10 @@ class CppTester(Tester): CONSUMER = True FLIGHT_SERVER = True FLIGHT_CLIENT = True - C_DATA_EXPORTER = True - C_DATA_IMPORTER = True + C_DATA_SCHEMA_EXPORTER = True + C_DATA_ARRAY_EXPORTER = True + C_DATA_SCHEMA_IMPORTER = True + C_DATA_ARRAY_IMPORTER = True name = 'C++' diff --git a/dev/archery/archery/integration/tester_csharp.py b/dev/archery/archery/integration/tester_csharp.py index 018731d573cac..83b07495f9907 100644 --- a/dev/archery/archery/integration/tester_csharp.py +++ b/dev/archery/archery/integration/tester_csharp.py @@ -15,23 +15,143 @@ # specific language governing permissions and limitations # under the License. +from contextlib import contextmanager +import gc import os -from .tester import Tester +from . import cdata +from .tester import Tester, CDataExporter, CDataImporter from .util import run_cmd, log from ..utils.source import ARROW_ROOT_DEFAULT -_EXE_PATH = os.path.join( - ARROW_ROOT_DEFAULT, - "csharp/artifacts/Apache.Arrow.IntegrationTest", - "Debug/net7.0/Apache.Arrow.IntegrationTest", -) +_ARTIFACTS_PATH = os.path.join(ARROW_ROOT_DEFAULT, "csharp/artifacts") + +_EXE_PATH = os.path.join(_ARTIFACTS_PATH, + "Apache.Arrow.IntegrationTest", + "Debug/net7.0/Apache.Arrow.IntegrationTest", + ) + +_clr_loaded = False + + +def _load_clr(): + global _clr_loaded + if not _clr_loaded: + _clr_loaded = True + import pythonnet + pythonnet.load("coreclr") + import clr + clr.AddReference( + f"{_ARTIFACTS_PATH}/Apache.Arrow.IntegrationTest/" + f"Debug/net7.0/Apache.Arrow.IntegrationTest.dll") + clr.AddReference( + f"{_ARTIFACTS_PATH}/Apache.Arrow.Tests/" + f"Debug/net7.0/Apache.Arrow.Tests.dll") + + from Apache.Arrow.IntegrationTest import CDataInterface + CDataInterface.Initialize() + + +@contextmanager +def _disposing(disposable): + """ + Ensure the IDisposable object is disposed of when the enclosed block exits. + """ + try: + yield disposable + finally: + disposable.Dispose() + + +class _CDataBase: + + def __init__(self, debug, args): + self.debug = debug + self.args = args + self.ffi = cdata.ffi() + _load_clr() + + def _pointer_to_int(self, c_ptr): + return int(self.ffi.cast('uintptr_t', c_ptr)) + + def _read_batch_from_json(self, json_path, num_batch): + from Apache.Arrow.IntegrationTest import CDataInterface + + jf = CDataInterface.ParseJsonFile(json_path) + schema = jf.Schema.ToArrow() + return schema, jf.Batches[num_batch].ToArrow(schema) + + +class CSharpCDataExporter(CDataExporter, _CDataBase): + + def export_schema_from_json(self, json_path, c_schema_ptr): + from Apache.Arrow.IntegrationTest import CDataInterface + + jf = CDataInterface.ParseJsonFile(json_path) + CDataInterface.ExportSchema(jf.Schema.ToArrow(), + self._pointer_to_int(c_schema_ptr)) + + def export_batch_from_json(self, json_path, num_batch, c_array_ptr): + from Apache.Arrow.IntegrationTest import CDataInterface + + _, batch = self._read_batch_from_json(json_path, num_batch) + with _disposing(batch): + CDataInterface.ExportRecordBatch(batch, + self._pointer_to_int(c_array_ptr)) + + @property + def supports_releasing_memory(self): + # XXX the C# GC doesn't give reliable allocation measurements + return False + + +class CSharpCDataImporter(CDataImporter, _CDataBase): + + def import_schema_and_compare_to_json(self, json_path, c_schema_ptr): + from Apache.Arrow.IntegrationTest import CDataInterface + from Apache.Arrow.Tests import SchemaComparer + + jf = CDataInterface.ParseJsonFile(json_path) + imported_schema = CDataInterface.ImportSchema( + self._pointer_to_int(c_schema_ptr)) + SchemaComparer.Compare(jf.Schema.ToArrow(), imported_schema) + + def import_batch_and_compare_to_json(self, json_path, num_batch, + c_array_ptr): + from Apache.Arrow.IntegrationTest import CDataInterface + from Apache.Arrow.Tests import ArrowReaderVerifier + + schema, batch = self._read_batch_from_json(json_path, num_batch) + with _disposing(batch): + imported_batch = CDataInterface.ImportRecordBatch( + self._pointer_to_int(c_array_ptr), schema) + with _disposing(imported_batch): + ArrowReaderVerifier.CompareBatches(batch, imported_batch, + strictCompare=False) + + @property + def supports_releasing_memory(self): + return True + + def gc_until(self, predicate): + from Apache.Arrow.IntegrationTest import CDataInterface + for i in range(3): + if predicate(): + return True + # Collect any C# objects hanging around through Python + gc.collect() + CDataInterface.RunGC() + return predicate() class CSharpTester(Tester): PRODUCER = True CONSUMER = True + C_DATA_SCHEMA_EXPORTER = True + C_DATA_SCHEMA_IMPORTER = True + C_DATA_ARRAY_EXPORTER = True + C_DATA_ARRAY_IMPORTER = True name = 'C#' @@ -68,3 +188,9 @@ def file_to_stream(self, file_path, stream_path): cmd.extend(['--mode', 'file-to-stream']) cmd.extend(['-a', file_path, '>', stream_path]) self.run_shell_command(cmd) + + def make_c_data_exporter(self): + return CSharpCDataExporter(self.debug, self.args) + + def make_c_data_importer(self): + return CSharpCDataImporter(self.debug, self.args) diff --git a/dev/archery/archery/integration/tester_go.py b/dev/archery/archery/integration/tester_go.py index 6fa26ea02b8e7..75333db8d66d5 100644 --- a/dev/archery/archery/integration/tester_go.py +++ b/dev/archery/archery/integration/tester_go.py @@ -55,8 +55,10 @@ class GoTester(Tester): CONSUMER = True FLIGHT_SERVER = True FLIGHT_CLIENT = True - C_DATA_EXPORTER = True - C_DATA_IMPORTER = True + C_DATA_SCHEMA_EXPORTER = True + C_DATA_ARRAY_EXPORTER = True + C_DATA_SCHEMA_IMPORTER = True + C_DATA_ARRAY_IMPORTER = True name = 'Go' From 50de296b0b62e54ee3a67401f277afba9b9d0433 Mon Sep 17 00:00:00 2001 From: Sutou Kouhei Date: Tue, 3 Oct 2023 10:13:45 +0900 Subject: [PATCH 32/56] GH-37971: [CI][Java] Don't use cache for nightly upload (#37980) ### Rationale for this change It's too large (8.6 GB) and it's always re-created because it uses github.run_id for key. It expires other caches soon. ### What changes are included in this PR? Remove actions/cache. ### Are these changes tested? No. ### Are there any user-facing changes? No. * Closes: #37971 Authored-by: Sutou Kouhei Signed-off-by: Sutou Kouhei --- .github/workflows/java_nightly.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/java_nightly.yml b/.github/workflows/java_nightly.yml index 4440d36d18f73..41843d663051a 100644 --- a/.github/workflows/java_nightly.yml +++ b/.github/workflows/java_nightly.yml @@ -73,12 +73,6 @@ jobs: fi echo $PREFIX archery crossbow download-artifacts -f java-jars -t binaries $PREFIX - - name: Cache Repo - uses: actions/cache@v3 - with: - path: repo - key: java-nightly-${{ github.run_id }} - restore-keys: java-nightly - name: Sync from Remote uses: ./arrow/.github/actions/sync-nightlies with: From d428ef4682d3a9ce4cfc2b1ab4653deeafd92a3e Mon Sep 17 00:00:00 2001 From: Yue Date: Tue, 3 Oct 2023 15:21:45 +0800 Subject: [PATCH 33/56] GH-37834: [Gandiva] Migrate to new LLVM PassManager API (#37867) ### Rationale for this change In https://github.com/apache/arrow/issues/37834, to support LLVM 17, we need to migrate to use the new LLVM PassManager API. ### What changes are included in this PR? This PR tries to migrate the legacy PassManager to the new PassManager. ### Are these changes tested? It should be covered by existing unit tests. But more performance tests may be needed to verify this change. ### Are there any user-facing changes? No * Closes: #37834 Lead-authored-by: Yue Ni Co-authored-by: Sutou Kouhei Co-authored-by: Sutou Kouhei Signed-off-by: Sutou Kouhei --- cpp/CMakeLists.txt | 1 + cpp/cmake_modules/FindLLVMAlt.cmake | 24 ++--- cpp/src/gandiva/CMakeLists.txt | 2 - cpp/src/gandiva/engine.cc | 130 +++++++++++++++++++++------- 4 files changed, 115 insertions(+), 42 deletions(-) diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index f2906b960eba6..f0acab0389b19 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -152,6 +152,7 @@ set(ARROW_DOC_DIR "share/doc/${PROJECT_NAME}") set(BUILD_SUPPORT_DIR "${CMAKE_SOURCE_DIR}/build-support") set(ARROW_LLVM_VERSIONS + "17.0" "16.0" "15.0" "14.0" diff --git a/cpp/cmake_modules/FindLLVMAlt.cmake b/cpp/cmake_modules/FindLLVMAlt.cmake index e980f53fd3407..69f680824b082 100644 --- a/cpp/cmake_modules/FindLLVMAlt.cmake +++ b/cpp/cmake_modules/FindLLVMAlt.cmake @@ -86,16 +86,20 @@ if(LLVM_FOUND) target_link_libraries(LLVM::LLVM_LIBS INTERFACE LLVM) else() # Find the libraries that correspond to the LLVM components - llvm_map_components_to_libnames(LLVM_LIBS - core - mcjit - native - ipo - bitreader - target - linker - analysis - debuginfodwarf) + set(LLVM_TARGET_COMPONENTS + analysis + bitreader + core + debuginfodwarf + ipo + linker + mcjit + native + target) + if(LLVM_VERSION_MAJOR GREATER_EQUAL 14) + list(APPEND LLVM_TARGET_COMPONENTS passes) + endif() + llvm_map_components_to_libnames(LLVM_LIBS ${LLVM_TARGET_COMPONENTS}) target_link_libraries(LLVM::LLVM_LIBS INTERFACE ${LLVM_LIBS}) if(TARGET LLVMSupport AND NOT ARROW_ZSTD_USE_SHARED) diff --git a/cpp/src/gandiva/CMakeLists.txt b/cpp/src/gandiva/CMakeLists.txt index db260b5acc933..d2810c39f723c 100644 --- a/cpp/src/gandiva/CMakeLists.txt +++ b/cpp/src/gandiva/CMakeLists.txt @@ -31,8 +31,6 @@ if(ARROW_WITH_ZSTD AND "${zstd_SOURCE}" STREQUAL "SYSTEM") provide_find_module(zstdAlt "Gandiva") endif() -add_definitions(-DGANDIVA_LLVM_VERSION=${LLVM_VERSION_MAJOR}) - # Set the path where the bitcode file generated, see precompiled/CMakeLists.txt set(GANDIVA_PRECOMPILED_BC_PATH "${CMAKE_CURRENT_BINARY_DIR}/irhelpers.bc") set(GANDIVA_PRECOMPILED_CC_PATH "${CMAKE_CURRENT_BINARY_DIR}/precompiled_bitcode.cc") diff --git a/cpp/src/gandiva/engine.cc b/cpp/src/gandiva/engine.cc index 7d75793a3e9e7..b6c78da89d575 100644 --- a/cpp/src/gandiva/engine.cc +++ b/cpp/src/gandiva/engine.cc @@ -53,18 +53,33 @@ #include #include #include +#if LLVM_VERSION_MAJOR >= 17 +#include +#else #include +#endif +#include #include #include +#include +#include #if LLVM_VERSION_MAJOR >= 14 +#include #include +#include +#include +#include +#include +#include +#include +#include #else #include +#include #endif #include #include #include -#include #include #include #include @@ -268,49 +283,104 @@ Status Engine::LoadPreCompiledIR() { // a pass for dead code elimination. Status Engine::RemoveUnusedFunctions() { // Setup an optimiser pipeline - std::unique_ptr pass_manager( - new llvm::legacy::PassManager()); + llvm::PassBuilder pass_builder; + llvm::ModuleAnalysisManager module_am; + + pass_builder.registerModuleAnalyses(module_am); + llvm::ModulePassManager module_pm; std::unordered_set used_functions; used_functions.insert(functions_to_compile_.begin(), functions_to_compile_.end()); - pass_manager->add( - llvm::createInternalizePass([&used_functions](const llvm::GlobalValue& func) { - return (used_functions.find(func.getName().str()) != used_functions.end()); + module_pm.addPass( + llvm::InternalizePass([&used_functions](const llvm::GlobalValue& variable) -> bool { + return used_functions.find(variable.getName().str()) != used_functions.end(); })); - pass_manager->add(llvm::createGlobalDCEPass()); - pass_manager->run(*module_); + module_pm.addPass(llvm::GlobalDCEPass()); + + module_pm.run(*module_, module_am); return Status::OK(); } +// several passes requiring LLVM 14+ that are not available in the legacy pass manager +#if LLVM_VERSION_MAJOR >= 14 +static void OptimizeModuleWithNewPassManager(llvm::Module& module, + llvm::TargetIRAnalysis target_analysis) { + // Setup an optimiser pipeline + llvm::PassBuilder pass_builder; + llvm::LoopAnalysisManager loop_am; + llvm::FunctionAnalysisManager function_am; + llvm::CGSCCAnalysisManager cgscc_am; + llvm::ModuleAnalysisManager module_am; + + function_am.registerPass([&] { return target_analysis; }); + + // Register required analysis managers + pass_builder.registerModuleAnalyses(module_am); + pass_builder.registerCGSCCAnalyses(cgscc_am); + pass_builder.registerFunctionAnalyses(function_am); + pass_builder.registerLoopAnalyses(loop_am); + pass_builder.crossRegisterProxies(loop_am, function_am, cgscc_am, module_am); + + pass_builder.registerPipelineStartEPCallback([&](llvm::ModulePassManager& module_pm, + llvm::OptimizationLevel Level) { + module_pm.addPass(llvm::ModuleInlinerPass()); + + llvm::FunctionPassManager function_pm; + function_pm.addPass(llvm::InstCombinePass()); + function_pm.addPass(llvm::PromotePass()); + function_pm.addPass(llvm::GVNPass()); + function_pm.addPass(llvm::NewGVNPass()); + function_pm.addPass(llvm::SimplifyCFGPass()); + function_pm.addPass(llvm::LoopVectorizePass()); + function_pm.addPass(llvm::SLPVectorizerPass()); + module_pm.addPass(llvm::createModuleToFunctionPassAdaptor(std::move(function_pm))); + + module_pm.addPass(llvm::GlobalOptPass()); + }); + + pass_builder.buildPerModuleDefaultPipeline(llvm::OptimizationLevel::O3) + .run(module, module_am); +} +#else +static void OptimizeModuleWithLegacyPassManager(llvm::Module& module, + llvm::TargetIRAnalysis target_analysis) { + std::unique_ptr pass_manager( + new llvm::legacy::PassManager()); + + pass_manager->add(llvm::createTargetTransformInfoWrapperPass(target_analysis)); + pass_manager->add(llvm::createFunctionInliningPass()); + pass_manager->add(llvm::createInstructionCombiningPass()); + pass_manager->add(llvm::createPromoteMemoryToRegisterPass()); + pass_manager->add(llvm::createGVNPass()); + pass_manager->add(llvm::createNewGVNPass()); + pass_manager->add(llvm::createCFGSimplificationPass()); + pass_manager->add(llvm::createLoopVectorizePass()); + pass_manager->add(llvm::createSLPVectorizerPass()); + pass_manager->add(llvm::createGlobalOptimizerPass()); + + // run the optimiser + llvm::PassManagerBuilder pass_builder; + pass_builder.OptLevel = 3; + pass_builder.populateModulePassManager(*pass_manager); + pass_manager->run(module); +} +#endif + // Optimise and compile the module. Status Engine::FinalizeModule() { if (!cached_) { ARROW_RETURN_NOT_OK(RemoveUnusedFunctions()); if (optimize_) { - // misc passes to allow for inlining, vectorization, .. - std::unique_ptr pass_manager( - new llvm::legacy::PassManager()); - - llvm::TargetIRAnalysis target_analysis = - execution_engine_->getTargetMachine()->getTargetIRAnalysis(); - pass_manager->add(llvm::createTargetTransformInfoWrapperPass(target_analysis)); - pass_manager->add(llvm::createFunctionInliningPass()); - pass_manager->add(llvm::createInstructionCombiningPass()); - pass_manager->add(llvm::createPromoteMemoryToRegisterPass()); - pass_manager->add(llvm::createGVNPass()); - pass_manager->add(llvm::createNewGVNPass()); - pass_manager->add(llvm::createCFGSimplificationPass()); - pass_manager->add(llvm::createLoopVectorizePass()); - pass_manager->add(llvm::createSLPVectorizerPass()); - pass_manager->add(llvm::createGlobalOptimizerPass()); - - // run the optimiser - llvm::PassManagerBuilder pass_builder; - pass_builder.OptLevel = 3; - pass_builder.populateModulePassManager(*pass_manager); - pass_manager->run(*module_); + auto target_analysis = execution_engine_->getTargetMachine()->getTargetIRAnalysis(); + +// misc passes to allow for inlining, vectorization, .. +#if LLVM_VERSION_MAJOR >= 14 + OptimizeModuleWithNewPassManager(*module_, target_analysis); +#else + OptimizeModuleWithLegacyPassManager(*module_, target_analysis); +#endif } ARROW_RETURN_IF(llvm::verifyModule(*module_, &llvm::errs()), From 14a433aa65dc684e68dfa3a8d3f73cfce313d0eb Mon Sep 17 00:00:00 2001 From: mwish Date: Tue, 3 Oct 2023 21:43:16 +0800 Subject: [PATCH 34/56] GH-37873: [C++][Parquet] DELTA_BYTE_ARRAY: avoid copying data when possible (#37874) ### Rationale for this change When decoding DELTA_BYTE_ARRAY data, if the prefix (respectively suffix) is empty, we don't need to recreate the original string by copying the data into a new buffer, we can just point to the existing suffix (respectively suffix). ### What changes are included in this PR? Avoid spurious memory copies in the DELTA_BYTE_ARRAY decoder (also reducing the memory footprint when decoding). Benchmark numbers show that decoding can be up to 2x faster. ### Are these changes tested? Yes, already tested. ### Are there any user-facing changes? No. * Closes: #37873 Lead-authored-by: mwish Co-authored-by: Antoine Pitrou Signed-off-by: Antoine Pitrou --- cpp/src/parquet/encoding.cc | 66 ++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 11 deletions(-) diff --git a/cpp/src/parquet/encoding.cc b/cpp/src/parquet/encoding.cc index 0564ea2b93f3f..9f705768e4eff 100644 --- a/cpp/src/parquet/encoding.cc +++ b/cpp/src/parquet/encoding.cc @@ -3346,6 +3346,43 @@ class DeltaByteArrayDecoderImpl : public DecoderImpl, virtual public TypedDecode } protected: + template + static void BuildBufferInternal(const int32_t* prefix_len_ptr, int i, ByteArray* buffer, + std::string_view* prefix, uint8_t** data_ptr) { + if (ARROW_PREDICT_FALSE(static_cast(prefix_len_ptr[i]) > prefix->length())) { + throw ParquetException("prefix length too large in DELTA_BYTE_ARRAY"); + } + // For now, `buffer` points to string suffixes, and the suffix decoder + // ensures that the suffix data has sufficient lifetime. + if (prefix_len_ptr[i] == 0) { + // prefix is empty: buffer[i] already points to the suffix. + *prefix = std::string_view{buffer[i]}; + return; + } + DCHECK_EQ(is_first_run, i == 0); + if constexpr (!is_first_run) { + if (buffer[i].len == 0) { + // suffix is empty: buffer[i] can simply point to the prefix. + // This is not possible for the first run since the prefix + // would point to the mutable `last_value_`. + *prefix = prefix->substr(0, prefix_len_ptr[i]); + buffer[i] = ByteArray(*prefix); + return; + } + } + // Both prefix and suffix are non-empty, so we need to decode the string + // into `data_ptr`. + // 1. Copy the prefix + memcpy(*data_ptr, prefix->data(), prefix_len_ptr[i]); + // 2. Copy the suffix. + memcpy(*data_ptr + prefix_len_ptr[i], buffer[i].ptr, buffer[i].len); + // 3. Point buffer[i] to the decoded string. + buffer[i].ptr = *data_ptr; + buffer[i].len += prefix_len_ptr[i]; + *data_ptr += buffer[i].len; + *prefix = std::string_view{buffer[i]}; + } + int GetInternal(ByteArray* buffer, int max_values) { // Decode up to `max_values` strings into an internal buffer // and reference them into `buffer`. @@ -3366,9 +3403,19 @@ class DeltaByteArrayDecoderImpl : public DecoderImpl, virtual public TypedDecode reinterpret_cast(buffered_prefix_length_->data()) + prefix_len_offset_; for (int i = 0; i < max_values; ++i) { + if (prefix_len_ptr[i] == 0) { + // We don't need to copy the suffix if the prefix length is 0. + continue; + } if (ARROW_PREDICT_FALSE(prefix_len_ptr[i] < 0)) { throw ParquetException("negative prefix length in DELTA_BYTE_ARRAY"); } + if (buffer[i].len == 0 && i != 0) { + // We don't need to copy the prefix if the suffix length is 0 + // and this is not the first run (that is, the prefix doesn't point + // to the mutable `last_value_`). + continue; + } if (ARROW_PREDICT_FALSE(AddWithOverflow(data_size, prefix_len_ptr[i], &data_size) || AddWithOverflow(data_size, buffer[i].len, &data_size))) { throw ParquetException("excess expansion in DELTA_BYTE_ARRAY"); @@ -3378,18 +3425,15 @@ class DeltaByteArrayDecoderImpl : public DecoderImpl, virtual public TypedDecode string_view prefix{last_value_}; uint8_t* data_ptr = buffered_data_->mutable_data(); - for (int i = 0; i < max_values; ++i) { - if (ARROW_PREDICT_FALSE(static_cast(prefix_len_ptr[i]) > prefix.length())) { - throw ParquetException("prefix length too large in DELTA_BYTE_ARRAY"); - } - memcpy(data_ptr, prefix.data(), prefix_len_ptr[i]); - // buffer[i] currently points to the string suffix - memcpy(data_ptr + prefix_len_ptr[i], buffer[i].ptr, buffer[i].len); - buffer[i].ptr = data_ptr; - buffer[i].len += prefix_len_ptr[i]; - data_ptr += buffer[i].len; - prefix = std::string_view{buffer[i]}; + if (max_values > 0) { + BuildBufferInternal(prefix_len_ptr, 0, buffer, &prefix, + &data_ptr); + } + for (int i = 1; i < max_values; ++i) { + BuildBufferInternal(prefix_len_ptr, i, buffer, &prefix, + &data_ptr); } + DCHECK_EQ(data_ptr - buffered_data_->mutable_data(), data_size); prefix_len_offset_ += max_values; this->num_values_ -= max_values; num_valid_values_ -= max_values; From f6afc33a9e1b4cbd336982bf99b330ccacbf8566 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Tue, 3 Oct 2023 17:12:02 +0200 Subject: [PATCH 35/56] GH-37993: [CI] Fix conda-integration build (#37990) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Rationale for this change The conda-integration build has recently started failing: https://github.com/apache/arrow/actions/runs/6393852866/job/17353952453 Apparently this is because conda-forge is now providing Python 3.12 by default, and pythonnet [does not support it yet](https://github.com/pythonnet/pythonnet/pull/2249). ### What changes are included in this PR? Avoid using Python 3.12 for Archery in conda-integration build. ### Are these changes tested? Yes, by construction. ### Are there any user-facing changes? No. * Closes: #37993 Authored-by: Antoine Pitrou Signed-off-by: Raúl Cumplido --- ci/docker/conda-integration.dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ci/docker/conda-integration.dockerfile b/ci/docker/conda-integration.dockerfile index a306790b5cb6d..074021677d6fd 100644 --- a/ci/docker/conda-integration.dockerfile +++ b/ci/docker/conda-integration.dockerfile @@ -29,9 +29,11 @@ ARG go=1.19.13 # Install Archery and integration dependencies COPY ci/conda_env_archery.txt /arrow/ci/ +# Pin Python until pythonnet is made compatible with 3.12 +# (https://github.com/pythonnet/pythonnet/pull/2249) RUN mamba install -q -y \ --file arrow/ci/conda_env_archery.txt \ - "python>=3.7" \ + "python < 3.12" \ numpy \ compilers \ maven=${maven} \ From 92de9a3028fdfb76e0ca1e216845e09bf68ab4ac Mon Sep 17 00:00:00 2001 From: Matt Topol Date: Tue, 3 Oct 2023 13:49:50 -0400 Subject: [PATCH 36/56] GH-37635: [Format][C++][Go] Add app_metadata to FlightInfo and FlightEndpoint (#37679) ### Rationale for this change As suggested here: https://github.com/apache/arrow/issues/37635#issuecomment-1712146541 this just adds an `app_metadata` field to FlightInfo and FlightEndpoint ### What changes are included in this PR? Just the updated proto file and the generated Go code from the proto ### Are there any user-facing changes? Yes. **This PR includes breaking changes to public APIs.** * Closes: #37635 Lead-authored-by: Matt Topol Co-authored-by: Sutou Kouhei Signed-off-by: Matt Topol --- cpp/src/arrow/flight/flight_internals_test.cc | 69 ++- .../flight_integration_test.cc | 4 + .../integration_tests/test_integration.cc | 61 ++ cpp/src/arrow/flight/perf_server.cc | 2 +- .../arrow/flight/serialization_internal.cc | 4 + cpp/src/arrow/flight/sql/server.cc | 2 +- cpp/src/arrow/flight/test_util.cc | 26 +- cpp/src/arrow/flight/test_util.h | 3 +- cpp/src/arrow/flight/types.cc | 11 +- cpp/src/arrow/flight/types.h | 10 +- dev/archery/archery/integration/runner.py | 5 + format/Flight.proto | 22 + go/arrow/array/numericbuilder.gen.go | 28 +- go/arrow/flight/gen.go | 2 +- go/arrow/flight/gen/flight/Flight.pb.go | 328 +++++----- go/arrow/flight/gen/flight/FlightSql.pb.go | 564 ++++++++++-------- go/arrow/flight/gen/flight/Flight_grpc.pb.go | 48 +- .../internal/flight_integration/scenario.go | 64 +- 18 files changed, 803 insertions(+), 450 deletions(-) diff --git a/cpp/src/arrow/flight/flight_internals_test.cc b/cpp/src/arrow/flight/flight_internals_test.cc index b32036a2c973f..5feb310fc14a2 100644 --- a/cpp/src/arrow/flight/flight_internals_test.cc +++ b/cpp/src/arrow/flight/flight_internals_test.cc @@ -191,33 +191,33 @@ TEST(FlightTypes, FlightEndpoint) { Timestamp expiration_time( std::chrono::duration_cast(expiration_time_duration)); std::vector values = { - {{""}, {}, std::nullopt}, - {{"foo"}, {}, std::nullopt}, - {{"bar"}, {}, std::nullopt}, - {{"foo"}, {}, expiration_time}, - {{"foo"}, {location1}, std::nullopt}, - {{"bar"}, {location1}, std::nullopt}, - {{"foo"}, {location2}, std::nullopt}, - {{"foo"}, {location1, location2}, std::nullopt}, + {{""}, {}, std::nullopt, {}}, + {{"foo"}, {}, std::nullopt, {}}, + {{"bar"}, {}, std::nullopt, {"\xDE\xAD\xBE\xEF"}}, + {{"foo"}, {}, expiration_time, {}}, + {{"foo"}, {location1}, std::nullopt, {}}, + {{"bar"}, {location1}, std::nullopt, {}}, + {{"foo"}, {location2}, std::nullopt, {}}, + {{"foo"}, {location1, location2}, std::nullopt, {"\xba\xdd\xca\xfe"}}, }; std::vector reprs = { " locations=[] " - "expiration_time=null>", + "expiration_time=null app_metadata=''>", " locations=[] " - "expiration_time=null>", + "expiration_time=null app_metadata=''>", " locations=[] " - "expiration_time=null>", + "expiration_time=null app_metadata='DEADBEEF'>", " locations=[] " - "expiration_time=2023-06-19 03:14:06.004339000>", + "expiration_time=2023-06-19 03:14:06.004339000 app_metadata=''>", " locations=" - "[grpc+tcp://localhost:1024] expiration_time=null>", + "[grpc+tcp://localhost:1024] expiration_time=null app_metadata=''>", " locations=" - "[grpc+tcp://localhost:1024] expiration_time=null>", + "[grpc+tcp://localhost:1024] expiration_time=null app_metadata=''>", " locations=" - "[grpc+tls://localhost:1024] expiration_time=null>", + "[grpc+tls://localhost:1024] expiration_time=null app_metadata=''>", " locations=" "[grpc+tcp://localhost:1024, grpc+tls://localhost:1024] " - "expiration_time=null>", + "expiration_time=null app_metadata='BADDCAFE'>", }; ASSERT_NO_FATAL_FAILURE(TestRoundtrip(values, reprs)); @@ -229,30 +229,35 @@ TEST(FlightTypes, FlightInfo) { Schema schema2({}); auto desc1 = FlightDescriptor::Command("foo"); auto desc2 = FlightDescriptor::Command("bar"); - auto endpoint1 = FlightEndpoint{Ticket{"foo"}, {}, std::nullopt}; - auto endpoint2 = FlightEndpoint{Ticket{"foo"}, {location}, std::nullopt}; + auto endpoint1 = FlightEndpoint{Ticket{"foo"}, {}, std::nullopt, ""}; + auto endpoint2 = + FlightEndpoint{Ticket{"foo"}, {location}, std::nullopt, "\xCA\xFE\xD0\x0D"}; std::vector values = { - MakeFlightInfo(schema1, desc1, {}, -1, -1, false), - MakeFlightInfo(schema1, desc2, {}, -1, -1, true), - MakeFlightInfo(schema2, desc1, {}, -1, -1, false), - MakeFlightInfo(schema1, desc1, {endpoint1}, -1, 42, true), - MakeFlightInfo(schema1, desc2, {endpoint1, endpoint2}, 64, -1, false), + MakeFlightInfo(schema1, desc1, {}, -1, -1, false, ""), + MakeFlightInfo(schema1, desc2, {}, -1, -1, true, ""), + MakeFlightInfo(schema2, desc1, {}, -1, -1, false, ""), + MakeFlightInfo(schema1, desc1, {endpoint1}, -1, 42, true, ""), + MakeFlightInfo(schema1, desc2, {endpoint1, endpoint2}, 64, -1, false, + "\xDE\xAD\xC0\xDE"), }; std::vector reprs = { " " - "endpoints=[] total_records=-1 total_bytes=-1 ordered=false>", + "endpoints=[] total_records=-1 total_bytes=-1 ordered=false app_metadata=''>", " " - "endpoints=[] total_records=-1 total_bytes=-1 ordered=true>", + "endpoints=[] total_records=-1 total_bytes=-1 ordered=true app_metadata=''>", " " - "endpoints=[] total_records=-1 total_bytes=-1 ordered=false>", + "endpoints=[] total_records=-1 total_bytes=-1 ordered=false app_metadata=''>", " " "endpoints=[ locations=[] " - "expiration_time=null>] total_records=-1 total_bytes=42 ordered=true>", + "expiration_time=null app_metadata=''>] total_records=-1 total_bytes=42 " + "ordered=true app_metadata=''>", " " "endpoints=[ locations=[] " - "expiration_time=null>, " - "locations=[grpc+tcp://localhost:1234] expiration_time=null>] " - "total_records=64 total_bytes=-1 ordered=false>", + "expiration_time=null app_metadata=''>, " + "locations=[grpc+tcp://localhost:1234] expiration_time=null " + "app_metadata='CAFED00D'>] " + "total_records=64 total_bytes=-1 ordered=false app_metadata='DEADC0DE'>", }; ASSERT_NO_FATAL_FAILURE(TestRoundtrip(values, reprs)); @@ -262,8 +267,8 @@ TEST(FlightTypes, PollInfo) { ASSERT_OK_AND_ASSIGN(auto location, Location::ForGrpcTcp("localhost", 1234)); Schema schema({field("ints", int64())}); auto desc = FlightDescriptor::Command("foo"); - auto endpoint = FlightEndpoint{Ticket{"foo"}, {}, std::nullopt}; - auto info = MakeFlightInfo(schema, desc, {endpoint}, -1, 42, true); + auto endpoint = FlightEndpoint{Ticket{"foo"}, {}, std::nullopt, ""}; + auto info = MakeFlightInfo(schema, desc, {endpoint}, -1, 42, true, ""); // 2023-06-19 03:14:06.004330100 // We must use microsecond resolution here for portability. // std::chrono::system_clock::time_point may not provide nanosecond diff --git a/cpp/src/arrow/flight/integration_tests/flight_integration_test.cc b/cpp/src/arrow/flight/integration_tests/flight_integration_test.cc index 4a49dea31b99d..67c7ee85f59d3 100644 --- a/cpp/src/arrow/flight/integration_tests/flight_integration_test.cc +++ b/cpp/src/arrow/flight/integration_tests/flight_integration_test.cc @@ -73,6 +73,10 @@ TEST(FlightIntegration, ExpirationTimeRenewFlightEndpoint) { TEST(FlightIntegration, PollFlightInfo) { ASSERT_OK(RunScenario("poll_flight_info")); } +TEST(FlightIntegration, AppMetadataFlightInfoEndpoint) { + ASSERT_OK(RunScenario("app_metadata_flight_info_endpoint")); +} + TEST(FlightIntegration, FlightSql) { ASSERT_OK(RunScenario("flight_sql")); } TEST(FlightIntegration, FlightSqlExtension) { diff --git a/cpp/src/arrow/flight/integration_tests/test_integration.cc b/cpp/src/arrow/flight/integration_tests/test_integration.cc index 03e352ffa6770..31bffd7704474 100644 --- a/cpp/src/arrow/flight/integration_tests/test_integration.cc +++ b/cpp/src/arrow/flight/integration_tests/test_integration.cc @@ -815,6 +815,64 @@ class PollFlightInfoScenario : public Scenario { } }; +/// \brief The server used for testing app_metadata in FlightInfo and FlightEndpoint +class AppMetadataFlightInfoEndpointServer : public FlightServerBase { + public: + AppMetadataFlightInfoEndpointServer() : FlightServerBase() {} + + Status GetFlightInfo(const ServerCallContext& context, const FlightDescriptor& request, + std::unique_ptr* info) override { + if (request.type != FlightDescriptor::CMD) { + return Status::Invalid("request descriptor should be of type CMD"); + } + + auto schema = arrow::schema({arrow::field("number", arrow::uint32(), false)}); + std::vector endpoints = { + FlightEndpoint{{}, {}, std::nullopt, request.cmd}}; + ARROW_ASSIGN_OR_RAISE(auto result, FlightInfo::Make(*schema, request, endpoints, -1, + -1, false, request.cmd)); + *info = std::make_unique(std::move(result)); + return Status::OK(); + } +}; + +/// \brief The AppMetadataFlightInfoEndpoint scenario. +/// +/// This tests that the client can receive and use the `app_metadata` field in +/// the FlightInfo and FlightEndpoint messages. +/// +/// The server only implements GetFlightInfo and will return a FlightInfo with a non- +/// empty app_metadata value that should match the app_metadata field in the +/// included FlightEndpoint. The value should be the same as the cmd bytes passed +/// in the call to GetFlightInfo by the client. +class AppMetadataFlightInfoEndpointScenario : public Scenario { + Status MakeServer(std::unique_ptr* server, + FlightServerOptions* options) override { + *server = std::make_unique(); + return Status::OK(); + } + + Status MakeClient(FlightClientOptions* options) override { return Status::OK(); } + + Status RunClient(std::unique_ptr client) override { + ARROW_ASSIGN_OR_RAISE(auto info, + client->GetFlightInfo(FlightDescriptor::Command("foobar"))); + if (info->app_metadata() != "foobar") { + return Status::Invalid("app_metadata should have been 'foobar', got: ", + info->app_metadata()); + } + if (info->endpoints().size() != 1) { + return Status::Invalid("should have gotten exactly one FlightEndpoint back, got: ", + info->endpoints().size()); + } + if (info->endpoints()[0].app_metadata != "foobar") { + return Status::Invalid("FlightEndpoint app_metadata should be 'foobar', got: ", + info->endpoints()[0].app_metadata); + } + return Status::OK(); + } +}; + /// \brief Schema to be returned for mocking the statement/prepared statement results. /// /// Must be the same across all languages. @@ -1897,6 +1955,9 @@ Status GetScenario(const std::string& scenario_name, std::shared_ptr* } else if (scenario_name == "poll_flight_info") { *out = std::make_shared(); return Status::OK(); + } else if (scenario_name == "app_metadata_flight_info_endpoint") { + *out = std::make_shared(); + return Status::OK(); } else if (scenario_name == "flight_sql") { *out = std::make_shared(); return Status::OK(); diff --git a/cpp/src/arrow/flight/perf_server.cc b/cpp/src/arrow/flight/perf_server.cc index a768840c0295d..40f6cbcbf0d82 100644 --- a/cpp/src/arrow/flight/perf_server.cc +++ b/cpp/src/arrow/flight/perf_server.cc @@ -196,7 +196,7 @@ class FlightPerfServer : public FlightServerBase { perf_request.stream_count() * perf_request.records_per_stream(); *info = std::make_unique( - MakeFlightInfo(*perf_schema_, request, endpoints, total_records, -1, false)); + MakeFlightInfo(*perf_schema_, request, endpoints, total_records, -1, false, "")); return Status::OK(); } diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index f85b451dccec3..64a40564afd72 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -177,6 +177,7 @@ Status FromProto(const pb::FlightEndpoint& pb_endpoint, FlightEndpoint* endpoint RETURN_NOT_OK(FromProto(pb_endpoint.expiration_time(), &expiration_time)); endpoint->expiration_time = std::move(expiration_time); } + endpoint->app_metadata = pb_endpoint.app_metadata(); return Status::OK(); } @@ -190,6 +191,7 @@ Status ToProto(const FlightEndpoint& endpoint, pb::FlightEndpoint* pb_endpoint) RETURN_NOT_OK(ToProto(endpoint.expiration_time.value(), pb_endpoint->mutable_expiration_time())); } + pb_endpoint->set_app_metadata(endpoint.app_metadata); return Status::OK(); } @@ -255,6 +257,7 @@ arrow::Result FromProto(const pb::FlightInfo& pb_info) { info.total_records = pb_info.total_records(); info.total_bytes = pb_info.total_bytes(); info.ordered = pb_info.ordered(); + info.app_metadata = pb_info.app_metadata(); return FlightInfo(std::move(info)); } @@ -296,6 +299,7 @@ Status ToProto(const FlightInfo& info, pb::FlightInfo* pb_info) { pb_info->set_total_records(info.total_records()); pb_info->set_total_bytes(info.total_bytes()); pb_info->set_ordered(info.ordered()); + pb_info->set_app_metadata(info.app_metadata()); return Status::OK(); } diff --git a/cpp/src/arrow/flight/sql/server.cc b/cpp/src/arrow/flight/sql/server.cc index 7a1c394fb413b..a6d197d15b2c0 100644 --- a/cpp/src/arrow/flight/sql/server.cc +++ b/cpp/src/arrow/flight/sql/server.cc @@ -930,7 +930,7 @@ arrow::Result> FlightSqlServerBase::GetFlightInfoSql } std::vector endpoints{ - FlightEndpoint{{descriptor.cmd}, {}, std::nullopt}}; + FlightEndpoint{{descriptor.cmd}, {}, std::nullopt, {}}}; ARROW_ASSIGN_OR_RAISE( auto result, FlightInfo::Make(*SqlSchema::GetSqlInfoSchema(), descriptor, endpoints, -1, -1, false)) diff --git a/cpp/src/arrow/flight/test_util.cc b/cpp/src/arrow/flight/test_util.cc index fed2b59abf56d..bf2f4c2b4effc 100644 --- a/cpp/src/arrow/flight/test_util.cc +++ b/cpp/src/arrow/flight/test_util.cc @@ -531,9 +531,11 @@ std::unique_ptr ExampleTestServer() { FlightInfo MakeFlightInfo(const Schema& schema, const FlightDescriptor& descriptor, const std::vector& endpoints, - int64_t total_records, int64_t total_bytes, bool ordered) { - EXPECT_OK_AND_ASSIGN(auto info, FlightInfo::Make(schema, descriptor, endpoints, - total_records, total_bytes, ordered)); + int64_t total_records, int64_t total_bytes, bool ordered, + std::string app_metadata) { + EXPECT_OK_AND_ASSIGN(auto info, + FlightInfo::Make(schema, descriptor, endpoints, total_records, + total_bytes, ordered, std::move(app_metadata))); return info; } @@ -602,11 +604,11 @@ std::vector ExampleFlightInfo() { Location location4 = *Location::ForGrpcTcp("foo4.bar.com", 12345); Location location5 = *Location::ForGrpcTcp("foo5.bar.com", 12345); - FlightEndpoint endpoint1({{"ticket-ints-1"}, {location1}, std::nullopt}); - FlightEndpoint endpoint2({{"ticket-ints-2"}, {location2}, std::nullopt}); - FlightEndpoint endpoint3({{"ticket-cmd"}, {location3}, std::nullopt}); - FlightEndpoint endpoint4({{"ticket-dicts-1"}, {location4}, std::nullopt}); - FlightEndpoint endpoint5({{"ticket-floats-1"}, {location5}, std::nullopt}); + FlightEndpoint endpoint1({{"ticket-ints-1"}, {location1}, std::nullopt, {}}); + FlightEndpoint endpoint2({{"ticket-ints-2"}, {location2}, std::nullopt, {}}); + FlightEndpoint endpoint3({{"ticket-cmd"}, {location3}, std::nullopt, {}}); + FlightEndpoint endpoint4({{"ticket-dicts-1"}, {location4}, std::nullopt, {}}); + FlightEndpoint endpoint5({{"ticket-floats-1"}, {location5}, std::nullopt, {}}); FlightDescriptor descr1{FlightDescriptor::PATH, "", {"examples", "ints"}}; FlightDescriptor descr2{FlightDescriptor::CMD, "my_command", {}}; @@ -619,10 +621,10 @@ std::vector ExampleFlightInfo() { auto schema4 = ExampleFloatSchema(); return { - MakeFlightInfo(*schema1, descr1, {endpoint1, endpoint2}, 1000, 100000, false), - MakeFlightInfo(*schema2, descr2, {endpoint3}, 1000, 100000, false), - MakeFlightInfo(*schema3, descr3, {endpoint4}, -1, -1, false), - MakeFlightInfo(*schema4, descr4, {endpoint5}, 1000, 100000, false), + MakeFlightInfo(*schema1, descr1, {endpoint1, endpoint2}, 1000, 100000, false, ""), + MakeFlightInfo(*schema2, descr2, {endpoint3}, 1000, 100000, false, ""), + MakeFlightInfo(*schema3, descr3, {endpoint4}, -1, -1, false, ""), + MakeFlightInfo(*schema4, descr4, {endpoint5}, 1000, 100000, false, ""), }; } diff --git a/cpp/src/arrow/flight/test_util.h b/cpp/src/arrow/flight/test_util.h index f299d358c539e..c0b42d9b90c5a 100644 --- a/cpp/src/arrow/flight/test_util.h +++ b/cpp/src/arrow/flight/test_util.h @@ -192,7 +192,8 @@ std::vector ExampleActionTypes(); ARROW_FLIGHT_EXPORT FlightInfo MakeFlightInfo(const Schema& schema, const FlightDescriptor& descriptor, const std::vector& endpoints, - int64_t total_records, int64_t total_bytes, bool ordered); + int64_t total_records, int64_t total_bytes, bool ordered, + std::string app_metadata); // ---------------------------------------------------------------------- // A pair of authentication handlers that check for a predefined password diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index a24a9ef8758ab..9da83fa8a11f2 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -260,13 +260,14 @@ arrow::Result FlightInfo::Make(const Schema& schema, const FlightDescriptor& descriptor, const std::vector& endpoints, int64_t total_records, int64_t total_bytes, - bool ordered) { + bool ordered, std::string app_metadata) { FlightInfo::Data data; data.descriptor = descriptor; data.endpoints = endpoints; data.total_records = total_records; data.total_bytes = total_bytes; data.ordered = ordered; + data.app_metadata = std::move(app_metadata); RETURN_NOT_OK(internal::SchemaToString(schema, &data.schema)); return FlightInfo(data); } @@ -328,6 +329,7 @@ std::string FlightInfo::ToString() const { ss << "] total_records=" << data_.total_records; ss << " total_bytes=" << data_.total_bytes; ss << " ordered=" << (data_.ordered ? "true" : "false"); + ss << " app_metadata='" << HexEncode(data_.app_metadata) << "'"; ss << '>'; return ss.str(); } @@ -338,7 +340,8 @@ bool FlightInfo::Equals(const FlightInfo& other) const { data_.endpoints == other.data_.endpoints && data_.total_records == other.data_.total_records && data_.total_bytes == other.data_.total_bytes && - data_.ordered == other.data_.ordered; + data_.ordered == other.data_.ordered && + data_.app_metadata == other.data_.app_metadata; } arrow::Result PollInfo::SerializeToString() const { @@ -535,6 +538,7 @@ std::string FlightEndpoint::ToString() const { } else { ss << "null"; } + ss << " app_metadata='" << HexEncode(app_metadata) << "'"; ss << ">"; return ss.str(); } @@ -554,6 +558,9 @@ bool FlightEndpoint::Equals(const FlightEndpoint& other) const { return false; } } + if (app_metadata != other.app_metadata) { + return false; + } return true; } diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index 70e7c90676b73..40a0787d14a7a 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -481,6 +481,9 @@ struct ARROW_FLIGHT_EXPORT FlightEndpoint { /// retrying DoGet requests. std::optional expiration_time; + /// Opaque Application-defined metadata + std::string app_metadata; + std::string ToString() const; bool Equals(const FlightEndpoint& other) const; @@ -583,6 +586,7 @@ class ARROW_FLIGHT_EXPORT FlightInfo { int64_t total_records = -1; int64_t total_bytes = -1; bool ordered = false; + std::string app_metadata; }; explicit FlightInfo(Data data) : data_(std::move(data)), reconstructed_schema_(false) {} @@ -592,7 +596,8 @@ class ARROW_FLIGHT_EXPORT FlightInfo { const FlightDescriptor& descriptor, const std::vector& endpoints, int64_t total_records, int64_t total_bytes, - bool ordered = false); + bool ordered = false, + std::string app_metadata = ""); /// \brief Deserialize the Arrow schema of the dataset. Populate any /// dictionary encoded fields into a DictionaryMemo for @@ -621,6 +626,9 @@ class ARROW_FLIGHT_EXPORT FlightInfo { /// Whether endpoints are in the same order as the data. bool ordered() const { return data_.ordered; } + /// Application-defined opaque metadata + const std::string& app_metadata() const { return data_.app_metadata; } + /// \brief Get the wire-format representation of this type. /// /// Useful when interoperating with non-Flight systems (e.g. REST diff --git a/dev/archery/archery/integration/runner.py b/dev/archery/archery/integration/runner.py index 67f0693df14aa..eb2e26951cd88 100644 --- a/dev/archery/archery/integration/runner.py +++ b/dev/archery/archery/integration/runner.py @@ -611,6 +611,11 @@ def run_all_tests(with_cpp=True, with_java=True, with_js=True, description="Ensure PollFlightInfo is supported.", skip_testers={"JS", "C#", "Rust"} ), + Scenario( + "app_metadata_flight_info_endpoint", + description="Ensure support FlightInfo and Endpoint app_metadata", + skip_testers={"JS", "C#", "Rust", "Java"} + ), Scenario( "flight_sql", description="Ensure Flight SQL protocol is working as expected.", diff --git a/format/Flight.proto b/format/Flight.proto index baf2733d81048..de3794f05ba83 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -366,6 +366,17 @@ message FlightInfo { * FlightEndpoints are in the same order as the data. */ bool ordered = 6; + + /* + * Application-defined metadata. + * + * There is no inherent or required relationship between this + * and the app_metadata fields in the FlightEndpoints or resulting + * FlightData messages. Since this metadata is application-defined, + * a given application could define there to be a relationship, + * but there is none required by the spec. + */ + bytes app_metadata = 7; } /* @@ -446,6 +457,17 @@ message FlightEndpoint { * application-defined whether DoGet requests may be retried. */ google.protobuf.Timestamp expiration_time = 3; + + /* + * Application-defined metadata. + * + * There is no inherent or required relationship between this + * and the app_metadata fields in the FlightInfo or resulting + * FlightData messages. Since this metadata is application-defined, + * a given application could define there to be a relationship, + * but there is none required by the spec. + */ + bytes app_metadata = 4; } /* diff --git a/go/arrow/array/numericbuilder.gen.go b/go/arrow/array/numericbuilder.gen.go index d3648f0b1fbc4..7f01180f55957 100644 --- a/go/arrow/array/numericbuilder.gen.go +++ b/go/arrow/array/numericbuilder.gen.go @@ -86,7 +86,7 @@ func (b *Int64Builder) AppendEmptyValue() { } func (b *Int64Builder) AppendEmptyValues(n int) { - for i := 0; i < n; i ++ { + for i := 0; i < n; i++ { b.AppendEmptyValue() } } @@ -564,7 +564,7 @@ func (b *Float64Builder) AppendEmptyValue() { } func (b *Float64Builder) AppendEmptyValues(n int) { - for i := 0; i < n; i ++ { + for i := 0; i < n; i++ { b.AppendEmptyValue() } } @@ -803,7 +803,7 @@ func (b *Int32Builder) AppendEmptyValue() { } func (b *Int32Builder) AppendEmptyValues(n int) { - for i := 0; i < n; i ++ { + for i := 0; i < n; i++ { b.AppendEmptyValue() } } @@ -1042,7 +1042,7 @@ func (b *Uint32Builder) AppendEmptyValue() { } func (b *Uint32Builder) AppendEmptyValues(n int) { - for i := 0; i < n; i ++ { + for i := 0; i < n; i++ { b.AppendEmptyValue() } } @@ -1281,7 +1281,7 @@ func (b *Float32Builder) AppendEmptyValue() { } func (b *Float32Builder) AppendEmptyValues(n int) { - for i := 0; i < n; i ++ { + for i := 0; i < n; i++ { b.AppendEmptyValue() } } @@ -1520,7 +1520,7 @@ func (b *Int16Builder) AppendEmptyValue() { } func (b *Int16Builder) AppendEmptyValues(n int) { - for i := 0; i < n; i ++ { + for i := 0; i < n; i++ { b.AppendEmptyValue() } } @@ -1759,7 +1759,7 @@ func (b *Uint16Builder) AppendEmptyValue() { } func (b *Uint16Builder) AppendEmptyValues(n int) { - for i := 0; i < n; i ++ { + for i := 0; i < n; i++ { b.AppendEmptyValue() } } @@ -1998,7 +1998,7 @@ func (b *Int8Builder) AppendEmptyValue() { } func (b *Int8Builder) AppendEmptyValues(n int) { - for i := 0; i < n; i ++ { + for i := 0; i < n; i++ { b.AppendEmptyValue() } } @@ -2237,7 +2237,7 @@ func (b *Uint8Builder) AppendEmptyValue() { } func (b *Uint8Builder) AppendEmptyValues(n int) { - for i := 0; i < n; i ++ { + for i := 0; i < n; i++ { b.AppendEmptyValue() } } @@ -2477,7 +2477,7 @@ func (b *Time32Builder) AppendEmptyValue() { } func (b *Time32Builder) AppendEmptyValues(n int) { - for i := 0; i < n; i ++ { + for i := 0; i < n; i++ { b.AppendEmptyValue() } } @@ -2717,7 +2717,7 @@ func (b *Time64Builder) AppendEmptyValue() { } func (b *Time64Builder) AppendEmptyValues(n int) { - for i := 0; i < n; i ++ { + for i := 0; i < n; i++ { b.AppendEmptyValue() } } @@ -2956,7 +2956,7 @@ func (b *Date32Builder) AppendEmptyValue() { } func (b *Date32Builder) AppendEmptyValues(n int) { - for i := 0; i < n; i ++ { + for i := 0; i < n; i++ { b.AppendEmptyValue() } } @@ -3195,7 +3195,7 @@ func (b *Date64Builder) AppendEmptyValue() { } func (b *Date64Builder) AppendEmptyValues(n int) { - for i := 0; i < n; i ++ { + for i := 0; i < n; i++ { b.AppendEmptyValue() } } @@ -3435,7 +3435,7 @@ func (b *DurationBuilder) AppendEmptyValue() { } func (b *DurationBuilder) AppendEmptyValues(n int) { - for i := 0; i < n; i ++ { + for i := 0; i < n; i++ { b.AppendEmptyValue() } } diff --git a/go/arrow/flight/gen.go b/go/arrow/flight/gen.go index cfdd0e036703a..29ae54b38f427 100644 --- a/go/arrow/flight/gen.go +++ b/go/arrow/flight/gen.go @@ -16,5 +16,5 @@ package flight -//go:generate protoc -I../../../format --go_out=./gen/flight --go-grpc_out=./gen/flight --go_opt=paths=source_relative --go-grpc_opt=paths=source_relative Flight.proto +//go:generate protoc --experimental_allow_proto3_optional -I../../../format --go_out=./gen/flight --go-grpc_out=./gen/flight --go_opt=paths=source_relative --go-grpc_opt=paths=source_relative Flight.proto //go:generate protoc --experimental_allow_proto3_optional -I../../../format --go_out=./gen/flight --go-grpc_out=./gen/flight --go_opt=paths=source_relative --go-grpc_opt=paths=source_relative FlightSql.proto diff --git a/go/arrow/flight/gen/flight/Flight.pb.go b/go/arrow/flight/gen/flight/Flight.pb.go index 861b37d90d088..0438bca28be50 100644 --- a/go/arrow/flight/gen/flight/Flight.pb.go +++ b/go/arrow/flight/gen/flight/Flight.pb.go @@ -18,7 +18,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v3.21.12 +// protoc v4.23.4 // source: Flight.proto package flight @@ -38,6 +38,7 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +// // The result of a cancel operation. // // This is used by CancelFlightInfoResult.status. @@ -102,17 +103,19 @@ func (CancelStatus) EnumDescriptor() ([]byte, []int) { return file_Flight_proto_rawDescGZIP(), []int{0} } +// // Describes what type of descriptor is defined. type FlightDescriptor_DescriptorType int32 const ( // Protobuf pattern, not used. FlightDescriptor_UNKNOWN FlightDescriptor_DescriptorType = 0 + // // A named path that identifies a dataset. A path is composed of a string // or list of strings describing a particular dataset. This is conceptually - // - // similar to a path inside a filesystem. + // similar to a path inside a filesystem. FlightDescriptor_PATH FlightDescriptor_DescriptorType = 1 + // // An opaque command to generate a dataset. FlightDescriptor_CMD FlightDescriptor_DescriptorType = 2 ) @@ -158,14 +161,17 @@ func (FlightDescriptor_DescriptorType) EnumDescriptor() ([]byte, []int) { return file_Flight_proto_rawDescGZIP(), []int{12, 0} } +// // The request that a client provides to a server on handshake. type HandshakeRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // // A defined protocol version ProtocolVersion uint64 `protobuf:"varint,1,opt,name=protocol_version,json=protocolVersion,proto3" json:"protocol_version,omitempty"` + // // Arbitrary auth/handshake info. Payload []byte `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"` } @@ -221,8 +227,10 @@ type HandshakeResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // // A defined protocol version ProtocolVersion uint64 `protobuf:"varint,1,opt,name=protocol_version,json=protocolVersion,proto3" json:"protocol_version,omitempty"` + // // Arbitrary auth/handshake info. Payload []byte `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"` } @@ -273,6 +281,7 @@ func (x *HandshakeResponse) GetPayload() []byte { return nil } +// // A message for doing simple auth. type BasicAuth struct { state protoimpl.MessageState @@ -367,6 +376,7 @@ func (*Empty) Descriptor() ([]byte, []int) { return file_Flight_proto_rawDescGZIP(), []int{3} } +// // Describes an available action, including both the name used for execution // along with a short description of the purpose of the action. type ActionType struct { @@ -424,6 +434,7 @@ func (x *ActionType) GetDescription() string { return "" } +// // A service specific expression that can be used to return a limited set // of available Arrow Flight streams. type Criteria struct { @@ -473,6 +484,7 @@ func (x *Criteria) GetExpression() []byte { return nil } +// // An opaque action specific for the service. type Action struct { state protoimpl.MessageState @@ -529,6 +541,7 @@ func (x *Action) GetBody() []byte { return nil } +// // The request of the CancelFlightInfo action. // // The request should be stored in Action.body. @@ -579,6 +592,7 @@ func (x *CancelFlightInfoRequest) GetInfo() *FlightInfo { return nil } +// // The request of the RenewFlightEndpoint action. // // The request should be stored in Action.body. @@ -629,6 +643,7 @@ func (x *RenewFlightEndpointRequest) GetEndpoint() *FlightEndpoint { return nil } +// // An opaque result returned after executing an action. type Result struct { state protoimpl.MessageState @@ -677,6 +692,7 @@ func (x *Result) GetBody() []byte { return nil } +// // The result of the CancelFlightInfo action. // // The result should be stored in Result.body. @@ -727,6 +743,7 @@ func (x *CancelFlightInfoResult) GetStatus() CancelStatus { return CancelStatus_CANCEL_STATUS_UNSPECIFIED } +// // Wrap the result of a getSchema call type SchemaResult struct { state protoimpl.MessageState @@ -734,10 +751,9 @@ type SchemaResult struct { unknownFields protoimpl.UnknownFields // The schema of the dataset in its IPC form: - // - // 4 bytes - an optional IPC_CONTINUATION_TOKEN prefix - // 4 bytes - the byte length of the payload - // a flatbuffer Message whose header is the Schema + // 4 bytes - an optional IPC_CONTINUATION_TOKEN prefix + // 4 bytes - the byte length of the payload + // a flatbuffer Message whose header is the Schema Schema []byte `protobuf:"bytes,1,opt,name=schema,proto3" json:"schema,omitempty"` } @@ -780,6 +796,7 @@ func (x *SchemaResult) GetSchema() []byte { return nil } +// // The name or tag for a Flight. May be used as a way to retrieve or generate // a flight or be used to expose a set of previously defined flights. type FlightDescriptor struct { @@ -788,9 +805,11 @@ type FlightDescriptor struct { unknownFields protoimpl.UnknownFields Type FlightDescriptor_DescriptorType `protobuf:"varint,1,opt,name=type,proto3,enum=arrow.flight.protocol.FlightDescriptor_DescriptorType" json:"type,omitempty"` + // // Opaque value used to express a command. Should only be defined when // type = CMD. Cmd []byte `protobuf:"bytes,2,opt,name=cmd,proto3" json:"cmd,omitempty"` + // // List of strings identifying a particular dataset. Should only be defined // when type = PATH. Path []string `protobuf:"bytes,3,rep,name=path,proto3" json:"path,omitempty"` @@ -849,6 +868,7 @@ func (x *FlightDescriptor) GetPath() []string { return nil } +// // The access coordinates for retrieval of a dataset. With a FlightInfo, a // consumer is able to determine how to retrieve a dataset. type FlightInfo struct { @@ -857,13 +877,14 @@ type FlightInfo struct { unknownFields protoimpl.UnknownFields // The schema of the dataset in its IPC form: - // - // 4 bytes - an optional IPC_CONTINUATION_TOKEN prefix - // 4 bytes - the byte length of the payload - // a flatbuffer Message whose header is the Schema + // 4 bytes - an optional IPC_CONTINUATION_TOKEN prefix + // 4 bytes - the byte length of the payload + // a flatbuffer Message whose header is the Schema Schema []byte `protobuf:"bytes,1,opt,name=schema,proto3" json:"schema,omitempty"` + // // The descriptor associated with this info. FlightDescriptor *FlightDescriptor `protobuf:"bytes,2,opt,name=flight_descriptor,json=flightDescriptor,proto3" json:"flight_descriptor,omitempty"` + // // A list of endpoints associated with the flight. To consume the // whole flight, all endpoints (and hence all Tickets) must be // consumed. Endpoints can be consumed in any order. @@ -883,15 +904,19 @@ type FlightInfo struct { // ordering is important for an application, an application must // choose one of them: // - // - An application requires that all clients must read data in - // returned endpoints order. - // - An application must return the all data in a single endpoint. + // * An application requires that all clients must read data in + // returned endpoints order. + // * An application must return the all data in a single endpoint. Endpoint []*FlightEndpoint `protobuf:"bytes,3,rep,name=endpoint,proto3" json:"endpoint,omitempty"` // Set these to -1 if unknown. TotalRecords int64 `protobuf:"varint,4,opt,name=total_records,json=totalRecords,proto3" json:"total_records,omitempty"` TotalBytes int64 `protobuf:"varint,5,opt,name=total_bytes,json=totalBytes,proto3" json:"total_bytes,omitempty"` + // // FlightEndpoints are in the same order as the data. Ordered bool `protobuf:"varint,6,opt,name=ordered,proto3" json:"ordered,omitempty"` + // + // Application-defined metadata. + AppMetadata []byte `protobuf:"bytes,7,opt,name=app_metadata,json=appMetadata,proto3" json:"app_metadata,omitempty"` } func (x *FlightInfo) Reset() { @@ -968,12 +993,21 @@ func (x *FlightInfo) GetOrdered() bool { return false } +func (x *FlightInfo) GetAppMetadata() []byte { + if x != nil { + return x.AppMetadata + } + return nil +} + +// // The information to process a long-running query. type PollInfo struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // // The currently available results. // // If "flight_descriptor" is not specified, the query is complete @@ -991,12 +1025,15 @@ type PollInfo struct { // ticket in the info before the query is // completed. FlightInfo.ordered is also valid. Info *FlightInfo `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"` + // // The descriptor the client should use on the next try. // If unset, the query is complete. FlightDescriptor *FlightDescriptor `protobuf:"bytes,2,opt,name=flight_descriptor,json=flightDescriptor,proto3" json:"flight_descriptor,omitempty"` + // // Query progress. If known, must be in [0.0, 1.0] but need not be // monotonic or nondecreasing. If unknown, do not set. Progress *float64 `protobuf:"fixed64,3,opt,name=progress,proto3,oneof" json:"progress,omitempty"` + // // Expiration time for this request. After this passes, the server // might not accept the retry descriptor anymore (and the query may // be cancelled). This may be updated on a call to PollFlightInfo. @@ -1063,14 +1100,17 @@ func (x *PollInfo) GetExpirationTime() *timestamppb.Timestamp { return nil } +// // A particular stream or split associated with a flight. type FlightEndpoint struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // // Token used to retrieve this stream. Ticket *Ticket `protobuf:"bytes,1,opt,name=ticket,proto3" json:"ticket,omitempty"` + // // A list of URIs where this ticket can be redeemed via DoGet(). // // If the list is empty, the expectation is that the ticket can only @@ -1086,10 +1126,14 @@ type FlightEndpoint struct { // In other words, an application can use multiple locations to // represent redundant and/or load balanced services. Location []*Location `protobuf:"bytes,2,rep,name=location,proto3" json:"location,omitempty"` + // // Expiration time of this stream. If present, clients may assume // they can retry DoGet requests. Otherwise, it is // application-defined whether DoGet requests may be retried. ExpirationTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=expiration_time,json=expirationTime,proto3" json:"expiration_time,omitempty"` + // + // Application-defined metadata. + AppMetadata []byte `protobuf:"bytes,4,opt,name=app_metadata,json=appMetadata,proto3" json:"app_metadata,omitempty"` } func (x *FlightEndpoint) Reset() { @@ -1145,6 +1189,14 @@ func (x *FlightEndpoint) GetExpirationTime() *timestamppb.Timestamp { return nil } +func (x *FlightEndpoint) GetAppMetadata() []byte { + if x != nil { + return x.AppMetadata + } + return nil +} + +// // A location where a Flight service will accept retrieval of a particular // stream given a ticket. type Location struct { @@ -1194,6 +1246,7 @@ func (x *Location) GetUri() string { return "" } +// // An opaque identifier that the service can use to retrieve a particular // portion of a stream. // @@ -1246,19 +1299,24 @@ func (x *Ticket) GetTicket() []byte { return nil } +// // A batch of Arrow data as part of a stream of batches. type FlightData struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // // The descriptor of the data. This is only relevant when a client is // starting a new DoPut stream. FlightDescriptor *FlightDescriptor `protobuf:"bytes,1,opt,name=flight_descriptor,json=flightDescriptor,proto3" json:"flight_descriptor,omitempty"` + // // Header for message data as described in Message.fbs::Message. DataHeader []byte `protobuf:"bytes,2,opt,name=data_header,json=dataHeader,proto3" json:"data_header,omitempty"` + // // Application-defined metadata. AppMetadata []byte `protobuf:"bytes,3,opt,name=app_metadata,json=appMetadata,proto3" json:"app_metadata,omitempty"` + // // The actual batch of Arrow data. Preferably handled with minimal-copies // coming last in the definition to help with sidecar patterns (it is // expected that some implementations will fetch this field off the wire @@ -1326,7 +1384,7 @@ func (x *FlightData) GetDataBody() []byte { return nil } -// * +//* // The response message associated with the submission of a DoPut. type PutResult struct { state protoimpl.MessageState @@ -1441,7 +1499,7 @@ var file_Flight_proto_rawDesc = []byte{ 0x22, 0x30, 0x0a, 0x0e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x41, 0x54, 0x48, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x43, 0x4d, 0x44, - 0x10, 0x02, 0x22, 0x9d, 0x02, 0x0a, 0x0a, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x49, 0x6e, 0x66, + 0x10, 0x02, 0x22, 0xc0, 0x02, 0x0a, 0x0a, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x54, 0x0a, 0x11, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x18, 0x02, @@ -1459,129 +1517,133 @@ var file_Flight_proto_rawDesc = []byte{ 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, - 0x65, 0x64, 0x22, 0x8a, 0x02, 0x0a, 0x08, 0x50, 0x6f, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x12, - 0x35, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, - 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x49, 0x6e, 0x66, 0x6f, - 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x54, 0x0a, 0x11, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, - 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x27, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, - 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x10, 0x66, 0x6c, 0x69, 0x67, - 0x68, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x08, - 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, - 0x52, 0x08, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x88, 0x01, 0x01, 0x12, 0x43, 0x0a, - 0x0f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x0e, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, - 0x6d, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x22, - 0xc9, 0x01, 0x0a, 0x0e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x12, 0x35, 0x0a, 0x06, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, - 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, - 0x74, 0x52, 0x06, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x3b, 0x0a, 0x08, 0x6c, 0x6f, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x61, 0x72, + 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x70, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x61, 0x70, 0x70, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x8a, 0x02, 0x0a, 0x08, 0x50, 0x6f, 0x6c, 0x6c, 0x49, 0x6e, + 0x66, 0x6f, 0x12, 0x35, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x21, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x54, 0x0a, 0x11, 0x66, 0x6c, 0x69, + 0x67, 0x68, 0x74, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, + 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, + 0x67, 0x68, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x10, 0x66, + 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, + 0x1f, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x01, 0x48, 0x00, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x88, 0x01, 0x01, + 0x12, 0x43, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0e, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, + 0x73, 0x73, 0x22, 0xec, 0x01, 0x0a, 0x0e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x45, 0x6e, 0x64, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x35, 0x0a, 0x06, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, + 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x54, 0x69, + 0x63, 0x6b, 0x65, 0x74, 0x52, 0x06, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x3b, 0x0a, 0x08, + 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, + 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x0a, 0x0f, 0x65, 0x78, 0x70, + 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0e, + 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21, + 0x0a, 0x0c, 0x61, 0x70, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x61, 0x70, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x22, 0x1c, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, + 0x03, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x22, + 0x20, 0x0a, 0x06, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x69, 0x63, + 0x6b, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x74, 0x69, 0x63, 0x6b, 0x65, + 0x74, 0x22, 0xc4, 0x01, 0x0a, 0x0a, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x61, 0x74, 0x61, + 0x12, 0x54, 0x0a, 0x11, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x63, 0x6f, 0x6c, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c, 0x6f, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0e, 0x65, 0x78, 0x70, - 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x1c, 0x0a, 0x08, 0x4c, - 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x22, 0x20, 0x0a, 0x06, 0x54, 0x69, 0x63, - 0x6b, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x06, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x22, 0xc4, 0x01, 0x0a, 0x0a, - 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x54, 0x0a, 0x11, 0x66, 0x6c, - 0x69, 0x67, 0x68, 0x74, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, - 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, - 0x69, 0x67, 0x68, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x10, - 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, - 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x70, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x61, 0x70, 0x70, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x62, 0x6f, 0x64, - 0x79, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x64, 0x61, 0x74, 0x61, 0x42, 0x6f, - 0x64, 0x79, 0x22, 0x2e, 0x0a, 0x09, 0x50, 0x75, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, - 0x21, 0x0a, 0x0c, 0x61, 0x70, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x61, 0x70, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x2a, 0x8b, 0x01, 0x0a, 0x0c, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x19, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x5f, 0x53, 0x54, - 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x5f, 0x53, 0x54, 0x41, - 0x54, 0x55, 0x53, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, - 0x1c, 0x0a, 0x18, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, - 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x4c, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x21, 0x0a, - 0x1d, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x4e, - 0x4f, 0x54, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x4c, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x03, - 0x32, 0x85, 0x07, 0x0a, 0x0d, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x12, 0x64, 0x0a, 0x09, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x12, + 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x6f, 0x72, 0x52, 0x10, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x68, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x64, 0x61, 0x74, + 0x61, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x70, 0x70, 0x5f, 0x6d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x61, + 0x70, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x61, + 0x74, 0x61, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, + 0x64, 0x61, 0x74, 0x61, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x2e, 0x0a, 0x09, 0x50, 0x75, 0x74, 0x52, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x70, 0x70, 0x5f, 0x6d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x61, 0x70, 0x70, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2a, 0x8b, 0x01, 0x0a, 0x0c, 0x43, 0x61, 0x6e, + 0x63, 0x65, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x19, 0x43, 0x41, 0x4e, + 0x43, 0x45, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x43, 0x41, 0x4e, 0x43, + 0x45, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, + 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x5f, + 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x4c, 0x49, 0x4e, + 0x47, 0x10, 0x02, 0x12, 0x21, 0x0a, 0x1d, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x5f, 0x53, 0x54, + 0x41, 0x54, 0x55, 0x53, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x4c, + 0x41, 0x42, 0x4c, 0x45, 0x10, 0x03, 0x32, 0x85, 0x07, 0x0a, 0x0d, 0x46, 0x6c, 0x69, 0x67, 0x68, + 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x64, 0x0a, 0x09, 0x48, 0x61, 0x6e, 0x64, + 0x73, 0x68, 0x61, 0x6b, 0x65, 0x12, 0x27, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, + 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x48, 0x61, + 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, + 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x12, 0x55, + 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x12, 0x1f, 0x2e, + 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x1a, 0x21, + 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x49, 0x6e, 0x66, + 0x6f, 0x22, 0x00, 0x30, 0x01, 0x12, 0x5d, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x46, 0x6c, 0x69, 0x67, + 0x68, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x27, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, + 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, + 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x1a, + 0x21, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x49, 0x6e, + 0x66, 0x6f, 0x22, 0x00, 0x12, 0x5c, 0x0a, 0x0e, 0x50, 0x6f, 0x6c, 0x6c, 0x46, 0x6c, 0x69, 0x67, + 0x68, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x27, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, + 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, + 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x1a, + 0x1f, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x50, 0x6f, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, + 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x27, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x1a, 0x23, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, - 0x2e, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x12, 0x55, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, - 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x12, 0x1f, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, - 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, - 0x43, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x1a, 0x21, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, + 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, + 0x4d, 0x0a, 0x05, 0x44, 0x6f, 0x47, 0x65, 0x74, 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, - 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x00, 0x30, 0x01, 0x12, - 0x5d, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x49, 0x6e, 0x66, 0x6f, - 0x12, 0x27, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x1a, 0x21, 0x2e, 0x61, 0x72, 0x72, 0x6f, - 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x00, 0x12, 0x5c, - 0x0a, 0x0e, 0x50, 0x6f, 0x6c, 0x6c, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x49, 0x6e, 0x66, 0x6f, - 0x12, 0x27, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, + 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x1a, 0x21, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, + 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, + 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x61, 0x74, 0x61, 0x22, 0x00, 0x30, 0x01, 0x12, 0x52, + 0x0a, 0x05, 0x44, 0x6f, 0x50, 0x75, 0x74, 0x12, 0x21, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, + 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, + 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x61, 0x74, 0x61, 0x1a, 0x20, 0x2e, 0x61, 0x72, 0x72, + 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6c, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x28, 0x01, + 0x30, 0x01, 0x12, 0x58, 0x0a, 0x0a, 0x44, 0x6f, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x12, 0x21, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x1a, 0x1f, 0x2e, 0x61, 0x72, 0x72, 0x6f, - 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x2e, 0x50, 0x6f, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x09, - 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x27, 0x2e, 0x61, 0x72, 0x72, 0x6f, + 0x61, 0x74, 0x61, 0x1a, 0x21, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, + 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, + 0x68, 0x74, 0x44, 0x61, 0x74, 0x61, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x12, 0x4c, 0x0a, 0x08, + 0x44, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, + 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, + 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x1d, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, + 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, + 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x0b, 0x4c, 0x69, + 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1c, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x6f, 0x72, 0x1a, 0x23, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, - 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, - 0x61, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, 0x4d, 0x0a, 0x05, 0x44, 0x6f, 0x47, - 0x65, 0x74, 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, - 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, - 0x74, 0x1a, 0x21, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, - 0x44, 0x61, 0x74, 0x61, 0x22, 0x00, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x05, 0x44, 0x6f, 0x50, 0x75, - 0x74, 0x12, 0x21, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, - 0x44, 0x61, 0x74, 0x61, 0x1a, 0x20, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, - 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x50, 0x75, 0x74, - 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x12, 0x58, 0x0a, 0x0a, - 0x44, 0x6f, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x21, 0x2e, 0x61, 0x72, 0x72, - 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x61, 0x74, 0x61, 0x1a, 0x21, 0x2e, - 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x44, 0x61, 0x74, 0x61, - 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x12, 0x4c, 0x0a, 0x08, 0x44, 0x6f, 0x41, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, - 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x1a, 0x1d, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x22, 0x00, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x1c, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, - 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x1a, 0x21, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x54, 0x79, 0x70, 0x65, 0x22, 0x00, 0x30, 0x01, 0x42, 0x71, 0x0a, 0x1c, 0x6f, 0x72, 0x67, 0x2e, - 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, - 0x67, 0x68, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6c, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2f, 0x61, 0x72, 0x72, 0x6f, - 0x77, 0x2f, 0x67, 0x6f, 0x2f, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2f, 0x66, 0x6c, 0x69, 0x67, 0x68, - 0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0xaa, 0x02, 0x1c, 0x41, - 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x41, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x46, 0x6c, 0x69, 0x67, - 0x68, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x6c, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x21, 0x2e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, + 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, + 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x22, 0x00, 0x30, 0x01, 0x42, 0x71, + 0x0a, 0x1c, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x61, 0x72, 0x72, + 0x6f, 0x77, 0x2e, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6c, 0x5a, 0x32, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x70, 0x61, 0x63, 0x68, + 0x65, 0x2f, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2f, 0x67, 0x6f, 0x2f, 0x61, 0x72, 0x72, 0x6f, 0x77, + 0x2f, 0x66, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x66, 0x6c, 0x69, 0x67, + 0x68, 0x74, 0xaa, 0x02, 0x1c, 0x41, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x41, 0x72, 0x72, 0x6f, + 0x77, 0x2e, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/go/arrow/flight/gen/flight/FlightSql.pb.go b/go/arrow/flight/gen/flight/FlightSql.pb.go index 95faa719a9488..494bf8bcca115 100644 --- a/go/arrow/flight/gen/flight/FlightSql.pb.go +++ b/go/arrow/flight/gen/flight/FlightSql.pb.go @@ -18,7 +18,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v3.21.12 +// protoc v4.23.4 // source: FlightSql.proto package flight @@ -48,27 +48,33 @@ const ( SqlInfo_FLIGHT_SQL_SERVER_VERSION SqlInfo = 1 // Retrieves a UTF-8 string with the Arrow format version of the Flight SQL Server. SqlInfo_FLIGHT_SQL_SERVER_ARROW_VERSION SqlInfo = 2 + // // Retrieves a boolean value indicating whether the Flight SQL Server is read only. // // Returns: // - false: if read-write // - true: if read only SqlInfo_FLIGHT_SQL_SERVER_READ_ONLY SqlInfo = 3 + // // Retrieves a boolean value indicating whether the Flight SQL Server supports executing // SQL queries. // // Note that the absence of this info (as opposed to a false value) does not necessarily // mean that SQL is not supported, as this property was not originally defined. SqlInfo_FLIGHT_SQL_SERVER_SQL SqlInfo = 4 + // // Retrieves a boolean value indicating whether the Flight SQL Server supports executing // Substrait plans. SqlInfo_FLIGHT_SQL_SERVER_SUBSTRAIT SqlInfo = 5 + // // Retrieves a string value indicating the minimum supported Substrait version, or null // if Substrait is not supported. SqlInfo_FLIGHT_SQL_SERVER_SUBSTRAIT_MIN_VERSION SqlInfo = 6 + // // Retrieves a string value indicating the maximum supported Substrait version, or null // if Substrait is not supported. SqlInfo_FLIGHT_SQL_SERVER_SUBSTRAIT_MAX_VERSION SqlInfo = 7 + // // Retrieves an int32 indicating whether the Flight SQL Server supports the // BeginTransaction/EndTransaction/BeginSavepoint/EndSavepoint actions. // @@ -78,51 +84,61 @@ const ( // // The possible values are listed in `SqlSupportedTransaction`. SqlInfo_FLIGHT_SQL_SERVER_TRANSACTION SqlInfo = 8 + // // Retrieves a boolean value indicating whether the Flight SQL Server supports explicit // query cancellation (the CancelQuery action). SqlInfo_FLIGHT_SQL_SERVER_CANCEL SqlInfo = 9 + // // Retrieves an int32 indicating the timeout (in milliseconds) for prepared statement handles. // // If 0, there is no timeout. Servers should reset the timeout when the handle is used in a command. SqlInfo_FLIGHT_SQL_SERVER_STATEMENT_TIMEOUT SqlInfo = 100 + // // Retrieves an int32 indicating the timeout (in milliseconds) for transactions, since transactions are not tied to a connection. // // If 0, there is no timeout. Servers should reset the timeout when the handle is used in a command. SqlInfo_FLIGHT_SQL_SERVER_TRANSACTION_TIMEOUT SqlInfo = 101 + // // Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of catalogs. // // Returns: // - false: if it doesn't support CREATE and DROP of catalogs. // - true: if it supports CREATE and DROP of catalogs. SqlInfo_SQL_DDL_CATALOG SqlInfo = 500 + // // Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of schemas. // // Returns: // - false: if it doesn't support CREATE and DROP of schemas. // - true: if it supports CREATE and DROP of schemas. SqlInfo_SQL_DDL_SCHEMA SqlInfo = 501 + // // Indicates whether the Flight SQL Server supports CREATE and DROP of tables. // // Returns: // - false: if it doesn't support CREATE and DROP of tables. // - true: if it supports CREATE and DROP of tables. SqlInfo_SQL_DDL_TABLE SqlInfo = 502 + // // Retrieves a int32 ordinal representing the case sensitivity of catalog, table, schema and table names. // // The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`. SqlInfo_SQL_IDENTIFIER_CASE SqlInfo = 503 // Retrieves a UTF-8 string with the supported character(s) used to surround a delimited identifier. SqlInfo_SQL_IDENTIFIER_QUOTE_CHAR SqlInfo = 504 + // // Retrieves a int32 describing the case sensitivity of quoted identifiers. // // The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`. SqlInfo_SQL_QUOTED_IDENTIFIER_CASE SqlInfo = 505 + // // Retrieves a boolean value indicating whether all tables are selectable. // // Returns: // - false: if not all tables are selectable or if none are; // - true: if all tables are selectable. SqlInfo_SQL_ALL_TABLES_ARE_SELECTABLE SqlInfo = 506 + // // Retrieves the null ordering. // // Returns a int32 ordinal for the null ordering being used, as described in @@ -138,15 +154,18 @@ const ( SqlInfo_SQL_SYSTEM_FUNCTIONS SqlInfo = 511 // Retrieves a UTF-8 string list with values of the supported datetime functions. SqlInfo_SQL_DATETIME_FUNCTIONS SqlInfo = 512 + // // Retrieves the UTF-8 string that can be used to escape wildcard characters. // This is the string that can be used to escape '_' or '%' in the catalog search parameters that are a pattern // (and therefore use one of the wildcard characters). // The '_' character represents any single character; the '%' character represents any sequence of zero or more // characters. SqlInfo_SQL_SEARCH_STRING_ESCAPE SqlInfo = 513 + // // Retrieves a UTF-8 string with all the "extra" characters that can be used in unquoted identifier names // (those beyond a-z, A-Z, 0-9 and _). SqlInfo_SQL_EXTRA_NAME_CHARACTERS SqlInfo = 514 + // // Retrieves a boolean value indicating whether column aliasing is supported. // If so, the SQL AS clause can be used to provide names for computed columns or to provide alias names for columns // as required. @@ -155,6 +174,7 @@ const ( // - false: if column aliasing is unsupported; // - true: if column aliasing is supported. SqlInfo_SQL_SUPPORTS_COLUMN_ALIASING SqlInfo = 515 + // // Retrieves a boolean value indicating whether concatenations between null and non-null values being // null are supported. // @@ -162,11 +182,13 @@ const ( // - false: if concatenations between null and non-null values being null are unsupported; // - true: if concatenations between null and non-null values being null are supported. SqlInfo_SQL_NULL_PLUS_NULL_IS_NULL SqlInfo = 516 + // // Retrieves a map where the key is the type to convert from and the value is a list with the types to convert to, // indicating the supported conversions. Each key and each item on the list value is a value to a predefined type on // SqlSupportsConvert enum. // The returned map will be: map> SqlInfo_SQL_SUPPORTS_CONVERT SqlInfo = 517 + // // Retrieves a boolean value indicating whether, when table correlation names are supported, // they are restricted to being different from the names of the tables. // @@ -174,6 +196,7 @@ const ( // - false: if table correlation names are unsupported; // - true: if table correlation names are supported. SqlInfo_SQL_SUPPORTS_TABLE_CORRELATION_NAMES SqlInfo = 518 + // // Retrieves a boolean value indicating whether, when table correlation names are supported, // they are restricted to being different from the names of the tables. // @@ -181,12 +204,14 @@ const ( // - false: if different table correlation names are unsupported; // - true: if different table correlation names are supported SqlInfo_SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES SqlInfo = 519 + // // Retrieves a boolean value indicating whether expressions in ORDER BY lists are supported. // // Returns: // - false: if expressions in ORDER BY are unsupported; // - true: if expressions in ORDER BY are supported; SqlInfo_SQL_SUPPORTS_EXPRESSIONS_IN_ORDER_BY SqlInfo = 520 + // // Retrieves a boolean value indicating whether using a column that is not in the SELECT statement in a GROUP BY // clause is supported. // @@ -194,6 +219,7 @@ const ( // - false: if using a column that is not in the SELECT statement in a GROUP BY clause is unsupported; // - true: if using a column that is not in the SELECT statement in a GROUP BY clause is supported. SqlInfo_SQL_SUPPORTS_ORDER_BY_UNRELATED SqlInfo = 521 + // // Retrieves the supported GROUP BY commands; // // Returns an int32 bitmask value representing the supported commands. @@ -206,18 +232,21 @@ const ( // - return 3 (\b11) => [SQL_GROUP_BY_UNRELATED, SQL_GROUP_BY_BEYOND_SELECT]. // Valid GROUP BY types are described under `arrow.flight.protocol.sql.SqlSupportedGroupBy`. SqlInfo_SQL_SUPPORTED_GROUP_BY SqlInfo = 522 + // // Retrieves a boolean value indicating whether specifying a LIKE escape clause is supported. // // Returns: // - false: if specifying a LIKE escape clause is unsupported; // - true: if specifying a LIKE escape clause is supported. SqlInfo_SQL_SUPPORTS_LIKE_ESCAPE_CLAUSE SqlInfo = 523 + // // Retrieves a boolean value indicating whether columns may be defined as non-nullable. // // Returns: // - false: if columns cannot be defined as non-nullable; // - true: if columns may be defined as non-nullable. SqlInfo_SQL_SUPPORTS_NON_NULLABLE_COLUMNS SqlInfo = 524 + // // Retrieves the supported SQL grammar level as per the ODBC specification. // // Returns an int32 bitmask value representing the supported SQL grammar level. @@ -234,6 +263,7 @@ const ( // - return 7 (\b111) => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR]. // Valid SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedSqlGrammar`. SqlInfo_SQL_SUPPORTED_GRAMMAR SqlInfo = 525 + // // Retrieves the supported ANSI92 SQL grammar level. // // Returns an int32 bitmask value representing the supported ANSI92 SQL grammar level. @@ -250,12 +280,14 @@ const ( // - return 7 (\b111) => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL]. // Valid ANSI92 SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedAnsi92SqlGrammarLevel`. SqlInfo_SQL_ANSI92_SUPPORTED_LEVEL SqlInfo = 526 + // // Retrieves a boolean value indicating whether the SQL Integrity Enhancement Facility is supported. // // Returns: // - false: if the SQL Integrity Enhancement Facility is supported; // - true: if the SQL Integrity Enhancement Facility is supported. SqlInfo_SQL_SUPPORTS_INTEGRITY_ENHANCEMENT_FACILITY SqlInfo = 527 + // // Retrieves the support level for SQL OUTER JOINs. // // Returns a int32 ordinal for the SQL ordering being used, as described in @@ -265,14 +297,17 @@ const ( SqlInfo_SQL_SCHEMA_TERM SqlInfo = 529 // Retrieves a UTF-8 string with the preferred term for "procedure". SqlInfo_SQL_PROCEDURE_TERM SqlInfo = 530 + // // Retrieves a UTF-8 string with the preferred term for "catalog". // If a empty string is returned its assumed that the server does NOT supports catalogs. SqlInfo_SQL_CATALOG_TERM SqlInfo = 531 + // // Retrieves a boolean value indicating whether a catalog appears at the start of a fully qualified table name. // // - false: if a catalog does not appear at the start of a fully qualified table name; // - true: if a catalog appears at the start of a fully qualified table name. SqlInfo_SQL_CATALOG_AT_START SqlInfo = 532 + // // Retrieves the supported actions for a SQL schema. // // Returns an int32 bitmask value representing the supported actions for a SQL schema. @@ -289,6 +324,7 @@ const ( // - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS]. // Valid actions for a SQL schema described under `arrow.flight.protocol.sql.SqlSupportedElementActions`. SqlInfo_SQL_SCHEMAS_SUPPORTED_ACTIONS SqlInfo = 533 + // // Retrieves the supported actions for a SQL schema. // // Returns an int32 bitmask value representing the supported actions for a SQL catalog. @@ -305,6 +341,7 @@ const ( // - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS]. // Valid actions for a SQL catalog are described under `arrow.flight.protocol.sql.SqlSupportedElementActions`. SqlInfo_SQL_CATALOGS_SUPPORTED_ACTIONS SqlInfo = 534 + // // Retrieves the supported SQL positioned commands. // // Returns an int32 bitmask value representing the supported SQL positioned commands. @@ -317,12 +354,14 @@ const ( // - return 3 (\b11) => [SQL_POSITIONED_DELETE, SQL_POSITIONED_UPDATE]. // Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedPositionedCommands`. SqlInfo_SQL_SUPPORTED_POSITIONED_COMMANDS SqlInfo = 535 + // // Retrieves a boolean value indicating whether SELECT FOR UPDATE statements are supported. // // Returns: // - false: if SELECT FOR UPDATE statements are unsupported; // - true: if SELECT FOR UPDATE statements are supported. SqlInfo_SQL_SELECT_FOR_UPDATE_SUPPORTED SqlInfo = 536 + // // Retrieves a boolean value indicating whether stored procedure calls that use the stored procedure escape syntax // are supported. // @@ -330,6 +369,7 @@ const ( // - false: if stored procedure calls that use the stored procedure escape syntax are unsupported; // - true: if stored procedure calls that use the stored procedure escape syntax are supported. SqlInfo_SQL_STORED_PROCEDURES_SUPPORTED SqlInfo = 537 + // // Retrieves the supported SQL subqueries. // // Returns an int32 bitmask value representing the supported SQL subqueries. @@ -355,12 +395,14 @@ const ( // - ... // Valid SQL subqueries are described under `arrow.flight.protocol.sql.SqlSupportedSubqueries`. SqlInfo_SQL_SUPPORTED_SUBQUERIES SqlInfo = 538 + // // Retrieves a boolean value indicating whether correlated subqueries are supported. // // Returns: // - false: if correlated subqueries are unsupported; // - true: if correlated subqueries are supported. SqlInfo_SQL_CORRELATED_SUBQUERIES_SUPPORTED SqlInfo = 539 + // // Retrieves the supported SQL UNIONs. // // Returns an int32 bitmask value representing the supported SQL UNIONs. @@ -393,6 +435,7 @@ const ( SqlInfo_SQL_MAX_CONNECTIONS SqlInfo = 549 // Retrieves a int64 value the maximum number of characters allowed in a cursor name. SqlInfo_SQL_MAX_CURSOR_NAME_LENGTH SqlInfo = 550 + // // Retrieves a int64 value representing the maximum number of bytes allowed for an index, // including all of the parts of the index. SqlInfo_SQL_MAX_INDEX_LENGTH SqlInfo = 551 @@ -404,15 +447,17 @@ const ( SqlInfo_SQL_MAX_CATALOG_NAME_LENGTH SqlInfo = 554 // Retrieves a int64 value representing the maximum number of bytes allowed in a single row. SqlInfo_SQL_MAX_ROW_SIZE SqlInfo = 555 + // // Retrieves a boolean indicating whether the return value for the JDBC method getMaxRowSize includes the SQL // data types LONGVARCHAR and LONGVARBINARY. // // Returns: - // - false: if return value for the JDBC method getMaxRowSize does - // not include the SQL data types LONGVARCHAR and LONGVARBINARY; - // - true: if return value for the JDBC method getMaxRowSize includes - // the SQL data types LONGVARCHAR and LONGVARBINARY. + // - false: if return value for the JDBC method getMaxRowSize does + // not include the SQL data types LONGVARCHAR and LONGVARBINARY; + // - true: if return value for the JDBC method getMaxRowSize includes + // the SQL data types LONGVARCHAR and LONGVARBINARY. SqlInfo_SQL_MAX_ROW_SIZE_INCLUDES_BLOBS SqlInfo = 556 + // // Retrieves a int64 value representing the maximum number of characters allowed for an SQL statement; // a result of 0 (zero) means that there is no limit or the limit is not known. SqlInfo_SQL_MAX_STATEMENT_LENGTH SqlInfo = 557 @@ -424,11 +469,13 @@ const ( SqlInfo_SQL_MAX_TABLES_IN_SELECT SqlInfo = 560 // Retrieves a int64 value representing the maximum number of characters allowed in a user name. SqlInfo_SQL_MAX_USERNAME_LENGTH SqlInfo = 561 + // // Retrieves this database's default transaction isolation level as described in // `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`. // // Returns a int32 ordinal for the SQL transaction isolation level. SqlInfo_SQL_DEFAULT_TRANSACTION_ISOLATION SqlInfo = 562 + // // Retrieves a boolean value indicating whether transactions are supported. If not, invoking the method commit is a // noop, and the isolation level is `arrow.flight.protocol.sql.SqlTransactionIsolationLevel.TRANSACTION_NONE`. // @@ -436,6 +483,7 @@ const ( // - false: if transactions are unsupported; // - true: if transactions are supported. SqlInfo_SQL_TRANSACTIONS_SUPPORTED SqlInfo = 563 + // // Retrieves the supported transactions isolation levels. // // Returns an int32 bitmask value representing the supported transactions isolation levels. @@ -462,6 +510,7 @@ const ( // - ... // Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`. SqlInfo_SQL_SUPPORTED_TRANSACTIONS_ISOLATION_LEVELS SqlInfo = 564 + // // Retrieves a boolean value indicating whether a data definition statement within a transaction forces // the transaction to commit. // @@ -469,12 +518,14 @@ const ( // - false: if a data definition statement within a transaction does not force the transaction to commit; // - true: if a data definition statement within a transaction forces the transaction to commit. SqlInfo_SQL_DATA_DEFINITION_CAUSES_TRANSACTION_COMMIT SqlInfo = 565 + // // Retrieves a boolean value indicating whether a data definition statement within a transaction is ignored. // // Returns: // - false: if a data definition statement within a transaction is taken into account; // - true: a data definition statement within a transaction is ignored. SqlInfo_SQL_DATA_DEFINITIONS_IN_TRANSACTIONS_IGNORED SqlInfo = 566 + // // Retrieves an int32 bitmask value representing the supported result set types. // The returned bitmask should be parsed in order to retrieve the supported result set types. // @@ -491,6 +542,7 @@ const ( // - ... // Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetType`. SqlInfo_SQL_SUPPORTED_RESULT_SET_TYPES SqlInfo = 567 + // // Returns an int32 bitmask value concurrency types supported for // `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_UNSPECIFIED`. // @@ -505,6 +557,7 @@ const ( // - return 7 (\b111) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE] // Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`. SqlInfo_SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_UNSPECIFIED SqlInfo = 568 + // // Returns an int32 bitmask value concurrency types supported for // `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_FORWARD_ONLY`. // @@ -519,6 +572,7 @@ const ( // - return 7 (\b111) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE] // Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`. SqlInfo_SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_FORWARD_ONLY SqlInfo = 569 + // // Returns an int32 bitmask value concurrency types supported for // `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE`. // @@ -533,6 +587,7 @@ const ( // - return 7 (\b111) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE] // Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`. SqlInfo_SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_SENSITIVE SqlInfo = 570 + // // Returns an int32 bitmask value concurrency types supported for // `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE`. // @@ -547,29 +602,34 @@ const ( // - return 7 (\b111) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE] // Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`. SqlInfo_SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_INSENSITIVE SqlInfo = 571 + // // Retrieves a boolean value indicating whether this database supports batch updates. // // - false: if this database does not support batch updates; // - true: if this database supports batch updates. SqlInfo_SQL_BATCH_UPDATES_SUPPORTED SqlInfo = 572 + // // Retrieves a boolean value indicating whether this database supports savepoints. // // Returns: // - false: if this database does not support savepoints; // - true: if this database supports savepoints. SqlInfo_SQL_SAVEPOINTS_SUPPORTED SqlInfo = 573 + // // Retrieves a boolean value indicating whether named parameters are supported in callable statements. // // Returns: // - false: if named parameters in callable statements are unsupported; // - true: if named parameters in callable statements are supported. SqlInfo_SQL_NAMED_PARAMETERS_SUPPORTED SqlInfo = 574 + // // Retrieves a boolean value indicating whether updates made to a LOB are made on a copy or directly to the LOB. // // Returns: // - false: if updates made to a LOB are made directly to the LOB; // - true: if updates made to a LOB are made on a copy. SqlInfo_SQL_LOCATORS_UPDATE_COPY SqlInfo = 575 + // // Retrieves a boolean value indicating whether invoking user-defined or vendor functions // using the stored procedure escape syntax is supported. // @@ -1642,7 +1702,7 @@ func (SqlSupportsConvert) EnumDescriptor() ([]byte, []int) { return file_FlightSql_proto_rawDescGZIP(), []int{16} } -// * +//* // The JDBC/ODBC-defined type of any object. // All the values here are the sames as in the JDBC and ODBC specs. type XdbcDataType int32 @@ -1757,7 +1817,7 @@ func (XdbcDataType) EnumDescriptor() ([]byte, []int) { return file_FlightSql_proto_rawDescGZIP(), []int{17} } -// * +//* // Detailed subtype information for XDBC_TYPE_DATETIME and XDBC_TYPE_INTERVAL. type XdbcDatetimeSubcode int32 @@ -1898,13 +1958,13 @@ func (XdbcDatetimeSubcode) EnumDescriptor() ([]byte, []int) { type Nullable int32 const ( - // * + //* // Indicates that the fields does not allow the use of null values. Nullable_NULLABILITY_NO_NULLS Nullable = 0 - // * + //* // Indicates that the fields allow the use of null values. Nullable_NULLABILITY_NULLABLE Nullable = 1 - // * + //* // Indicates that nullability of the fields can not be determined. Nullable_NULLABILITY_UNKNOWN Nullable = 2 ) @@ -1953,21 +2013,21 @@ func (Nullable) EnumDescriptor() ([]byte, []int) { type Searchable int32 const ( - // * + //* // Indicates that column can not be used in a WHERE clause. Searchable_SEARCHABLE_NONE Searchable = 0 - // * + //* // Indicates that the column can be used in a WHERE clause if it is using a // LIKE operator. Searchable_SEARCHABLE_CHAR Searchable = 1 - // * + //* // Indicates that the column can be used In a WHERE clause with any // operator other than LIKE. // - // - Allowed operators: comparison, quantified comparison, BETWEEN, - // DISTINCT, IN, MATCH, and UNIQUE. + // - Allowed operators: comparison, quantified comparison, BETWEEN, + // DISTINCT, IN, MATCH, and UNIQUE. Searchable_SEARCHABLE_BASIC Searchable = 2 - // * + //* // Indicates that the column can be used in a WHERE clause using any operator. Searchable_SEARCHABLE_FULL Searchable = 3 ) @@ -2233,23 +2293,22 @@ func (ActionCancelQueryResult_CancelResult) EnumDescriptor() ([]byte, []int) { return file_FlightSql_proto_rawDescGZIP(), []int{29, 0} } +// // Represents a metadata request. Used in the command member of FlightDescriptor // for the following RPC calls: -// - GetSchema: return the Arrow schema of the query. -// - GetFlightInfo: execute the metadata request. +// - GetSchema: return the Arrow schema of the query. +// - GetFlightInfo: execute the metadata request. // // The returned Arrow schema will be: // < -// -// info_name: uint32 not null, -// value: dense_union< -// string_value: utf8, -// bool_value: bool, -// bigint_value: int64, -// int32_bitmask: int32, -// string_list: list -// int32_to_int32_list_map: map> -// +// info_name: uint32 not null, +// value: dense_union< +// string_value: utf8, +// bool_value: bool, +// bigint_value: int64, +// int32_bitmask: int32, +// string_list: list +// int32_to_int32_list_map: map> // > // where there is one row per requested piece of metadata information. type CommandGetSqlInfo struct { @@ -2257,6 +2316,7 @@ type CommandGetSqlInfo struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // // Values are modelled after ODBC's SQLGetInfo() function. This information is intended to provide // Flight SQL clients with basic, SQL syntax and SQL functions related information. // More information types can be added in future releases. @@ -2316,62 +2376,61 @@ func (x *CommandGetSqlInfo) GetInfo() []uint32 { return nil } +// // Represents a request to retrieve information about data type supported on a Flight SQL enabled backend. // Used in the command member of FlightDescriptor for the following RPC calls: -// - GetSchema: return the schema of the query. -// - GetFlightInfo: execute the catalog metadata request. +// - GetSchema: return the schema of the query. +// - GetFlightInfo: execute the catalog metadata request. // // The returned schema will be: // < -// -// type_name: utf8 not null (The name of the data type, for example: VARCHAR, INTEGER, etc), -// data_type: int32 not null (The SQL data type), -// column_size: int32 (The maximum size supported by that column. -// In case of exact numeric types, this represents the maximum precision. -// In case of string types, this represents the character length. -// In case of datetime data types, this represents the length in characters of the string representation. -// NULL is returned for data types where column size is not applicable.), -// literal_prefix: utf8 (Character or characters used to prefix a literal, NULL is returned for -// data types where a literal prefix is not applicable.), -// literal_suffix: utf8 (Character or characters used to terminate a literal, -// NULL is returned for data types where a literal suffix is not applicable.), -// create_params: list -// (A list of keywords corresponding to which parameters can be used when creating -// a column for that specific type. -// NULL is returned if there are no parameters for the data type definition.), -// nullable: int32 not null (Shows if the data type accepts a NULL value. The possible values can be seen in the -// Nullable enum.), -// case_sensitive: bool not null (Shows if a character data type is case-sensitive in collations and comparisons), -// searchable: int32 not null (Shows how the data type is used in a WHERE clause. The possible values can be seen in the -// Searchable enum.), -// unsigned_attribute: bool (Shows if the data type is unsigned. NULL is returned if the attribute is -// not applicable to the data type or the data type is not numeric.), -// fixed_prec_scale: bool not null (Shows if the data type has predefined fixed precision and scale.), -// auto_increment: bool (Shows if the data type is auto incremental. NULL is returned if the attribute -// is not applicable to the data type or the data type is not numeric.), -// local_type_name: utf8 (Localized version of the data source-dependent name of the data type. NULL -// is returned if a localized name is not supported by the data source), -// minimum_scale: int32 (The minimum scale of the data type on the data source. -// If a data type has a fixed scale, the MINIMUM_SCALE and MAXIMUM_SCALE -// columns both contain this value. NULL is returned if scale is not applicable.), -// maximum_scale: int32 (The maximum scale of the data type on the data source. -// NULL is returned if scale is not applicable.), -// sql_data_type: int32 not null (The value of the SQL DATA TYPE which has the same values -// as data_type value. Except for interval and datetime, which -// uses generic values. More info about those types can be -// obtained through datetime_subcode. The possible values can be seen -// in the XdbcDataType enum.), -// datetime_subcode: int32 (Only used when the SQL DATA TYPE is interval or datetime. It contains -// its sub types. For type different from interval and datetime, this value -// is NULL. The possible values can be seen in the XdbcDatetimeSubcode enum.), -// num_prec_radix: int32 (If the data type is an approximate numeric type, this column contains -// the value 2 to indicate that COLUMN_SIZE specifies a number of bits. For -// exact numeric types, this column contains the value 10 to indicate that -// column size specifies a number of decimal digits. Otherwise, this column is NULL.), -// interval_precision: int32 (If the data type is an interval data type, then this column contains the value -// of the interval leading precision. Otherwise, this column is NULL. This fields -// is only relevant to be used by ODBC). -// +// type_name: utf8 not null (The name of the data type, for example: VARCHAR, INTEGER, etc), +// data_type: int32 not null (The SQL data type), +// column_size: int32 (The maximum size supported by that column. +// In case of exact numeric types, this represents the maximum precision. +// In case of string types, this represents the character length. +// In case of datetime data types, this represents the length in characters of the string representation. +// NULL is returned for data types where column size is not applicable.), +// literal_prefix: utf8 (Character or characters used to prefix a literal, NULL is returned for +// data types where a literal prefix is not applicable.), +// literal_suffix: utf8 (Character or characters used to terminate a literal, +// NULL is returned for data types where a literal suffix is not applicable.), +// create_params: list +// (A list of keywords corresponding to which parameters can be used when creating +// a column for that specific type. +// NULL is returned if there are no parameters for the data type definition.), +// nullable: int32 not null (Shows if the data type accepts a NULL value. The possible values can be seen in the +// Nullable enum.), +// case_sensitive: bool not null (Shows if a character data type is case-sensitive in collations and comparisons), +// searchable: int32 not null (Shows how the data type is used in a WHERE clause. The possible values can be seen in the +// Searchable enum.), +// unsigned_attribute: bool (Shows if the data type is unsigned. NULL is returned if the attribute is +// not applicable to the data type or the data type is not numeric.), +// fixed_prec_scale: bool not null (Shows if the data type has predefined fixed precision and scale.), +// auto_increment: bool (Shows if the data type is auto incremental. NULL is returned if the attribute +// is not applicable to the data type or the data type is not numeric.), +// local_type_name: utf8 (Localized version of the data source-dependent name of the data type. NULL +// is returned if a localized name is not supported by the data source), +// minimum_scale: int32 (The minimum scale of the data type on the data source. +// If a data type has a fixed scale, the MINIMUM_SCALE and MAXIMUM_SCALE +// columns both contain this value. NULL is returned if scale is not applicable.), +// maximum_scale: int32 (The maximum scale of the data type on the data source. +// NULL is returned if scale is not applicable.), +// sql_data_type: int32 not null (The value of the SQL DATA TYPE which has the same values +// as data_type value. Except for interval and datetime, which +// uses generic values. More info about those types can be +// obtained through datetime_subcode. The possible values can be seen +// in the XdbcDataType enum.), +// datetime_subcode: int32 (Only used when the SQL DATA TYPE is interval or datetime. It contains +// its sub types. For type different from interval and datetime, this value +// is NULL. The possible values can be seen in the XdbcDatetimeSubcode enum.), +// num_prec_radix: int32 (If the data type is an approximate numeric type, this column contains +// the value 2 to indicate that COLUMN_SIZE specifies a number of bits. For +// exact numeric types, this column contains the value 10 to indicate that +// column size specifies a number of decimal digits. Otherwise, this column is NULL.), +// interval_precision: int32 (If the data type is an interval data type, then this column contains the value +// of the interval leading precision. Otherwise, this column is NULL. This fields +// is only relevant to be used by ODBC). // > // The returned data should be ordered by data_type and then by type_name. type CommandGetXdbcTypeInfo struct { @@ -2379,6 +2438,7 @@ type CommandGetXdbcTypeInfo struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // // Specifies the data type to search for the info. DataType *int32 `protobuf:"varint,1,opt,name=data_type,json=dataType,proto3,oneof" json:"data_type,omitempty"` } @@ -2422,17 +2482,16 @@ func (x *CommandGetXdbcTypeInfo) GetDataType() int32 { return 0 } +// // Represents a request to retrieve the list of catalogs on a Flight SQL enabled backend. // The definition of a catalog depends on vendor/implementation. It is usually the database itself // Used in the command member of FlightDescriptor for the following RPC calls: -// - GetSchema: return the Arrow schema of the query. -// - GetFlightInfo: execute the catalog metadata request. +// - GetSchema: return the Arrow schema of the query. +// - GetFlightInfo: execute the catalog metadata request. // // The returned Arrow schema will be: // < -// -// catalog_name: utf8 not null -// +// catalog_name: utf8 not null // > // The returned data should be ordered by catalog_name. type CommandGetCatalogs struct { @@ -2473,18 +2532,17 @@ func (*CommandGetCatalogs) Descriptor() ([]byte, []int) { return file_FlightSql_proto_rawDescGZIP(), []int{2} } +// // Represents a request to retrieve the list of database schemas on a Flight SQL enabled backend. // The definition of a database schema depends on vendor/implementation. It is usually a collection of tables. // Used in the command member of FlightDescriptor for the following RPC calls: -// - GetSchema: return the Arrow schema of the query. -// - GetFlightInfo: execute the catalog metadata request. +// - GetSchema: return the Arrow schema of the query. +// - GetFlightInfo: execute the catalog metadata request. // // The returned Arrow schema will be: // < -// -// catalog_name: utf8, -// db_schema_name: utf8 not null -// +// catalog_name: utf8, +// db_schema_name: utf8 not null // > // The returned data should be ordered by catalog_name, then db_schema_name. type CommandGetDbSchemas struct { @@ -2492,15 +2550,17 @@ type CommandGetDbSchemas struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // // Specifies the Catalog to search for the tables. // An empty string retrieves those without a catalog. // If omitted the catalog name should not be used to narrow the search. Catalog *string `protobuf:"bytes,1,opt,name=catalog,proto3,oneof" json:"catalog,omitempty"` + // // Specifies a filter pattern for schemas to search for. // When no db_schema_filter_pattern is provided, the pattern will not be used to narrow the search. // In the pattern string, two special characters can be used to denote matching rules: - // - "%" means to match any substring with 0 or more characters. - // - "_" means to match any one character. + // - "%" means to match any substring with 0 or more characters. + // - "_" means to match any one character. DbSchemaFilterPattern *string `protobuf:"bytes,2,opt,name=db_schema_filter_pattern,json=dbSchemaFilterPattern,proto3,oneof" json:"db_schema_filter_pattern,omitempty"` } @@ -2550,56 +2610,58 @@ func (x *CommandGetDbSchemas) GetDbSchemaFilterPattern() string { return "" } +// // Represents a request to retrieve the list of tables, and optionally their schemas, on a Flight SQL enabled backend. // Used in the command member of FlightDescriptor for the following RPC calls: -// - GetSchema: return the Arrow schema of the query. -// - GetFlightInfo: execute the catalog metadata request. +// - GetSchema: return the Arrow schema of the query. +// - GetFlightInfo: execute the catalog metadata request. // // The returned Arrow schema will be: // < -// -// catalog_name: utf8, -// db_schema_name: utf8, -// table_name: utf8 not null, -// table_type: utf8 not null, -// [optional] table_schema: bytes not null (schema of the table as described in Schema.fbs::Schema, -// it is serialized as an IPC message.) -// +// catalog_name: utf8, +// db_schema_name: utf8, +// table_name: utf8 not null, +// table_type: utf8 not null, +// [optional] table_schema: bytes not null (schema of the table as described in Schema.fbs::Schema, +// it is serialized as an IPC message.) // > // Fields on table_schema may contain the following metadata: -// - ARROW:FLIGHT:SQL:CATALOG_NAME - Table's catalog name -// - ARROW:FLIGHT:SQL:DB_SCHEMA_NAME - Database schema name -// - ARROW:FLIGHT:SQL:TABLE_NAME - Table name -// - ARROW:FLIGHT:SQL:TYPE_NAME - The data source-specific name for the data type of the column. -// - ARROW:FLIGHT:SQL:PRECISION - Column precision/size -// - ARROW:FLIGHT:SQL:SCALE - Column scale/decimal digits if applicable -// - ARROW:FLIGHT:SQL:IS_AUTO_INCREMENT - "1" indicates if the column is auto incremented, "0" otherwise. -// - ARROW:FLIGHT:SQL:IS_CASE_SENSITIVE - "1" indicates if the column is case sensitive, "0" otherwise. -// - ARROW:FLIGHT:SQL:IS_READ_ONLY - "1" indicates if the column is read only, "0" otherwise. -// - ARROW:FLIGHT:SQL:IS_SEARCHABLE - "1" indicates if the column is searchable via WHERE clause, "0" otherwise. -// +// - ARROW:FLIGHT:SQL:CATALOG_NAME - Table's catalog name +// - ARROW:FLIGHT:SQL:DB_SCHEMA_NAME - Database schema name +// - ARROW:FLIGHT:SQL:TABLE_NAME - Table name +// - ARROW:FLIGHT:SQL:TYPE_NAME - The data source-specific name for the data type of the column. +// - ARROW:FLIGHT:SQL:PRECISION - Column precision/size +// - ARROW:FLIGHT:SQL:SCALE - Column scale/decimal digits if applicable +// - ARROW:FLIGHT:SQL:IS_AUTO_INCREMENT - "1" indicates if the column is auto incremented, "0" otherwise. +// - ARROW:FLIGHT:SQL:IS_CASE_SENSITIVE - "1" indicates if the column is case sensitive, "0" otherwise. +// - ARROW:FLIGHT:SQL:IS_READ_ONLY - "1" indicates if the column is read only, "0" otherwise. +// - ARROW:FLIGHT:SQL:IS_SEARCHABLE - "1" indicates if the column is searchable via WHERE clause, "0" otherwise. // The returned data should be ordered by catalog_name, db_schema_name, table_name, then table_type, followed by table_schema if requested. type CommandGetTables struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // // Specifies the Catalog to search for the tables. // An empty string retrieves those without a catalog. // If omitted the catalog name should not be used to narrow the search. Catalog *string `protobuf:"bytes,1,opt,name=catalog,proto3,oneof" json:"catalog,omitempty"` + // // Specifies a filter pattern for schemas to search for. // When no db_schema_filter_pattern is provided, all schemas matching other filters are searched. // In the pattern string, two special characters can be used to denote matching rules: - // - "%" means to match any substring with 0 or more characters. - // - "_" means to match any one character. + // - "%" means to match any substring with 0 or more characters. + // - "_" means to match any one character. DbSchemaFilterPattern *string `protobuf:"bytes,2,opt,name=db_schema_filter_pattern,json=dbSchemaFilterPattern,proto3,oneof" json:"db_schema_filter_pattern,omitempty"` + // // Specifies a filter pattern for tables to search for. // When no table_name_filter_pattern is provided, all tables matching other filters are searched. // In the pattern string, two special characters can be used to denote matching rules: - // - "%" means to match any substring with 0 or more characters. - // - "_" means to match any one character. + // - "%" means to match any substring with 0 or more characters. + // - "_" means to match any one character. TableNameFilterPattern *string `protobuf:"bytes,3,opt,name=table_name_filter_pattern,json=tableNameFilterPattern,proto3,oneof" json:"table_name_filter_pattern,omitempty"` + // // Specifies a filter of table types which must match. // The table types depend on vendor/implementation. It is usually used to separate tables from views or system tables. // TABLE, VIEW, and SYSTEM TABLE are commonly supported. @@ -2675,18 +2737,17 @@ func (x *CommandGetTables) GetIncludeSchema() bool { return false } +// // Represents a request to retrieve the list of table types on a Flight SQL enabled backend. // The table types depend on vendor/implementation. It is usually used to separate tables from views or system tables. // TABLE, VIEW, and SYSTEM TABLE are commonly supported. // Used in the command member of FlightDescriptor for the following RPC calls: -// - GetSchema: return the Arrow schema of the query. -// - GetFlightInfo: execute the catalog metadata request. +// - GetSchema: return the Arrow schema of the query. +// - GetFlightInfo: execute the catalog metadata request. // // The returned Arrow schema will be: // < -// -// table_type: utf8 not null -// +// table_type: utf8 not null // > // The returned data should be ordered by table_type. type CommandGetTableTypes struct { @@ -2727,21 +2788,20 @@ func (*CommandGetTableTypes) Descriptor() ([]byte, []int) { return file_FlightSql_proto_rawDescGZIP(), []int{5} } +// // Represents a request to retrieve the primary keys of a table on a Flight SQL enabled backend. // Used in the command member of FlightDescriptor for the following RPC calls: -// - GetSchema: return the Arrow schema of the query. -// - GetFlightInfo: execute the catalog metadata request. +// - GetSchema: return the Arrow schema of the query. +// - GetFlightInfo: execute the catalog metadata request. // // The returned Arrow schema will be: // < -// -// catalog_name: utf8, -// db_schema_name: utf8, -// table_name: utf8 not null, -// column_name: utf8 not null, -// key_name: utf8, -// key_sequence: int32 not null -// +// catalog_name: utf8, +// db_schema_name: utf8, +// table_name: utf8 not null, +// column_name: utf8 not null, +// key_name: utf8, +// key_sequence: int32 not null // > // The returned data should be ordered by catalog_name, db_schema_name, table_name, key_name, then key_sequence. type CommandGetPrimaryKeys struct { @@ -2749,10 +2809,12 @@ type CommandGetPrimaryKeys struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // // Specifies the catalog to search for the table. // An empty string retrieves those without a catalog. // If omitted the catalog name should not be used to narrow the search. Catalog *string `protobuf:"bytes,1,opt,name=catalog,proto3,oneof" json:"catalog,omitempty"` + // // Specifies the schema to search for the table. // An empty string retrieves those without a schema. // If omitted the schema name should not be used to narrow the search. @@ -2814,29 +2876,28 @@ func (x *CommandGetPrimaryKeys) GetTable() string { return "" } +// // Represents a request to retrieve a description of the foreign key columns that reference the given table's // primary key columns (the foreign keys exported by a table) of a table on a Flight SQL enabled backend. // Used in the command member of FlightDescriptor for the following RPC calls: -// - GetSchema: return the Arrow schema of the query. -// - GetFlightInfo: execute the catalog metadata request. +// - GetSchema: return the Arrow schema of the query. +// - GetFlightInfo: execute the catalog metadata request. // // The returned Arrow schema will be: // < -// -// pk_catalog_name: utf8, -// pk_db_schema_name: utf8, -// pk_table_name: utf8 not null, -// pk_column_name: utf8 not null, -// fk_catalog_name: utf8, -// fk_db_schema_name: utf8, -// fk_table_name: utf8 not null, -// fk_column_name: utf8 not null, -// key_sequence: int32 not null, -// fk_key_name: utf8, -// pk_key_name: utf8, -// update_rule: uint8 not null, -// delete_rule: uint8 not null -// +// pk_catalog_name: utf8, +// pk_db_schema_name: utf8, +// pk_table_name: utf8 not null, +// pk_column_name: utf8 not null, +// fk_catalog_name: utf8, +// fk_db_schema_name: utf8, +// fk_table_name: utf8 not null, +// fk_column_name: utf8 not null, +// key_sequence: int32 not null, +// fk_key_name: utf8, +// pk_key_name: utf8, +// update_rule: uint8 not null, +// delete_rule: uint8 not null // > // The returned data should be ordered by fk_catalog_name, fk_db_schema_name, fk_table_name, fk_key_name, then key_sequence. // update_rule and delete_rule returns a byte that is equivalent to actions declared on UpdateDeleteRules enum. @@ -2845,10 +2906,12 @@ type CommandGetExportedKeys struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // // Specifies the catalog to search for the foreign key table. // An empty string retrieves those without a catalog. // If omitted the catalog name should not be used to narrow the search. Catalog *string `protobuf:"bytes,1,opt,name=catalog,proto3,oneof" json:"catalog,omitempty"` + // // Specifies the schema to search for the foreign key table. // An empty string retrieves those without a schema. // If omitted the schema name should not be used to narrow the search. @@ -2910,45 +2973,46 @@ func (x *CommandGetExportedKeys) GetTable() string { return "" } +// // Represents a request to retrieve the foreign keys of a table on a Flight SQL enabled backend. // Used in the command member of FlightDescriptor for the following RPC calls: -// - GetSchema: return the Arrow schema of the query. -// - GetFlightInfo: execute the catalog metadata request. +// - GetSchema: return the Arrow schema of the query. +// - GetFlightInfo: execute the catalog metadata request. // // The returned Arrow schema will be: // < -// -// pk_catalog_name: utf8, -// pk_db_schema_name: utf8, -// pk_table_name: utf8 not null, -// pk_column_name: utf8 not null, -// fk_catalog_name: utf8, -// fk_db_schema_name: utf8, -// fk_table_name: utf8 not null, -// fk_column_name: utf8 not null, -// key_sequence: int32 not null, -// fk_key_name: utf8, -// pk_key_name: utf8, -// update_rule: uint8 not null, -// delete_rule: uint8 not null -// +// pk_catalog_name: utf8, +// pk_db_schema_name: utf8, +// pk_table_name: utf8 not null, +// pk_column_name: utf8 not null, +// fk_catalog_name: utf8, +// fk_db_schema_name: utf8, +// fk_table_name: utf8 not null, +// fk_column_name: utf8 not null, +// key_sequence: int32 not null, +// fk_key_name: utf8, +// pk_key_name: utf8, +// update_rule: uint8 not null, +// delete_rule: uint8 not null // > // The returned data should be ordered by pk_catalog_name, pk_db_schema_name, pk_table_name, pk_key_name, then key_sequence. // update_rule and delete_rule returns a byte that is equivalent to actions: -// - 0 = CASCADE -// - 1 = RESTRICT -// - 2 = SET NULL -// - 3 = NO ACTION -// - 4 = SET DEFAULT +// - 0 = CASCADE +// - 1 = RESTRICT +// - 2 = SET NULL +// - 3 = NO ACTION +// - 4 = SET DEFAULT type CommandGetImportedKeys struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // // Specifies the catalog to search for the primary key table. // An empty string retrieves those without a catalog. // If omitted the catalog name should not be used to narrow the search. Catalog *string `protobuf:"bytes,1,opt,name=catalog,proto3,oneof" json:"catalog,omitempty"` + // // Specifies the schema to search for the primary key table. // An empty string retrieves those without a schema. // If omitted the schema name should not be used to narrow the search. @@ -3010,67 +3074,66 @@ func (x *CommandGetImportedKeys) GetTable() string { return "" } +// // Represents a request to retrieve a description of the foreign key columns in the given foreign key table that // reference the primary key or the columns representing a unique constraint of the parent table (could be the same // or a different table) on a Flight SQL enabled backend. // Used in the command member of FlightDescriptor for the following RPC calls: -// - GetSchema: return the Arrow schema of the query. -// - GetFlightInfo: execute the catalog metadata request. +// - GetSchema: return the Arrow schema of the query. +// - GetFlightInfo: execute the catalog metadata request. // // The returned Arrow schema will be: // < -// -// pk_catalog_name: utf8, -// pk_db_schema_name: utf8, -// pk_table_name: utf8 not null, -// pk_column_name: utf8 not null, -// fk_catalog_name: utf8, -// fk_db_schema_name: utf8, -// fk_table_name: utf8 not null, -// fk_column_name: utf8 not null, -// key_sequence: int32 not null, -// fk_key_name: utf8, -// pk_key_name: utf8, -// update_rule: uint8 not null, -// delete_rule: uint8 not null -// +// pk_catalog_name: utf8, +// pk_db_schema_name: utf8, +// pk_table_name: utf8 not null, +// pk_column_name: utf8 not null, +// fk_catalog_name: utf8, +// fk_db_schema_name: utf8, +// fk_table_name: utf8 not null, +// fk_column_name: utf8 not null, +// key_sequence: int32 not null, +// fk_key_name: utf8, +// pk_key_name: utf8, +// update_rule: uint8 not null, +// delete_rule: uint8 not null // > // The returned data should be ordered by pk_catalog_name, pk_db_schema_name, pk_table_name, pk_key_name, then key_sequence. // update_rule and delete_rule returns a byte that is equivalent to actions: -// - 0 = CASCADE -// - 1 = RESTRICT -// - 2 = SET NULL -// - 3 = NO ACTION -// - 4 = SET DEFAULT +// - 0 = CASCADE +// - 1 = RESTRICT +// - 2 = SET NULL +// - 3 = NO ACTION +// - 4 = SET DEFAULT type CommandGetCrossReference struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // * + //* // The catalog name where the parent table is. // An empty string retrieves those without a catalog. // If omitted the catalog name should not be used to narrow the search. PkCatalog *string `protobuf:"bytes,1,opt,name=pk_catalog,json=pkCatalog,proto3,oneof" json:"pk_catalog,omitempty"` - // * + //* // The Schema name where the parent table is. // An empty string retrieves those without a schema. // If omitted the schema name should not be used to narrow the search. PkDbSchema *string `protobuf:"bytes,2,opt,name=pk_db_schema,json=pkDbSchema,proto3,oneof" json:"pk_db_schema,omitempty"` - // * + //* // The parent table name. It cannot be null. PkTable string `protobuf:"bytes,3,opt,name=pk_table,json=pkTable,proto3" json:"pk_table,omitempty"` - // * + //* // The catalog name where the foreign table is. // An empty string retrieves those without a catalog. // If omitted the catalog name should not be used to narrow the search. FkCatalog *string `protobuf:"bytes,4,opt,name=fk_catalog,json=fkCatalog,proto3,oneof" json:"fk_catalog,omitempty"` - // * + //* // The schema name where the foreign table is. // An empty string retrieves those without a schema. // If omitted the schema name should not be used to narrow the search. FkDbSchema *string `protobuf:"bytes,5,opt,name=fk_db_schema,json=fkDbSchema,proto3,oneof" json:"fk_db_schema,omitempty"` - // * + //* // The foreign table name. It cannot be null. FkTable string `protobuf:"bytes,6,opt,name=fk_table,json=fkTable,proto3" json:"fk_table,omitempty"` } @@ -3149,6 +3212,7 @@ func (x *CommandGetCrossReference) GetFkTable() string { return "" } +// // Request message for the "CreatePreparedStatement" action on a Flight SQL enabled backend. type ActionCreatePreparedStatementRequest struct { state protoimpl.MessageState @@ -3208,6 +3272,7 @@ func (x *ActionCreatePreparedStatementRequest) GetTransactionId() []byte { return nil } +// // An embedded message describing a Substrait plan to execute. type SubstraitPlan struct { state protoimpl.MessageState @@ -3271,6 +3336,7 @@ func (x *SubstraitPlan) GetVersion() string { return "" } +// // Request message for the "CreatePreparedSubstraitPlan" action on a Flight SQL enabled backend. type ActionCreatePreparedSubstraitPlanRequest struct { state protoimpl.MessageState @@ -3330,6 +3396,7 @@ func (x *ActionCreatePreparedSubstraitPlanRequest) GetTransactionId() []byte { return nil } +// // Wrap the result of a "CreatePreparedStatement" or "CreatePreparedSubstraitPlan" action. // // The resultant PreparedStatement can be closed either: @@ -3405,6 +3472,7 @@ func (x *ActionCreatePreparedStatementResult) GetParameterSchema() []byte { return nil } +// // Request message for the "ClosePreparedStatement" action on a Flight SQL enabled backend. // Closes server resources associated with the prepared statement handle. type ActionClosePreparedStatementRequest struct { @@ -3455,6 +3523,7 @@ func (x *ActionClosePreparedStatementRequest) GetPreparedStatementHandle() []byt return nil } +// // Request message for the "BeginTransaction" action. // Begins a transaction. type ActionBeginTransactionRequest struct { @@ -3495,6 +3564,7 @@ func (*ActionBeginTransactionRequest) Descriptor() ([]byte, []int) { return file_FlightSql_proto_rawDescGZIP(), []int{15} } +// // Request message for the "BeginSavepoint" action. // Creates a savepoint within a transaction. // @@ -3557,6 +3627,7 @@ func (x *ActionBeginSavepointRequest) GetName() string { return "" } +// // The result of a "BeginTransaction" action. // // The transaction can be manipulated with the "EndTransaction" action, or @@ -3612,6 +3683,7 @@ func (x *ActionBeginTransactionResult) GetTransactionId() []byte { return nil } +// // The result of a "BeginSavepoint" action. // // The transaction can be manipulated with the "EndSavepoint" action. @@ -3667,6 +3739,7 @@ func (x *ActionBeginSavepointResult) GetSavepointId() []byte { return nil } +// // Request message for the "EndTransaction" action. // // Commit (COMMIT) or rollback (ROLLBACK) the transaction. @@ -3730,6 +3803,7 @@ func (x *ActionEndTransactionRequest) GetAction() ActionEndTransactionRequest_En return ActionEndTransactionRequest_END_TRANSACTION_UNSPECIFIED } +// // Request message for the "EndSavepoint" action. // // Release (RELEASE) the savepoint or rollback (ROLLBACK) to the @@ -3795,21 +3869,22 @@ func (x *ActionEndSavepointRequest) GetAction() ActionEndSavepointRequest_EndSav return ActionEndSavepointRequest_END_SAVEPOINT_UNSPECIFIED } +// // Represents a SQL query. Used in the command member of FlightDescriptor // for the following RPC calls: -// - GetSchema: return the Arrow schema of the query. -// Fields on this schema may contain the following metadata: -// - ARROW:FLIGHT:SQL:CATALOG_NAME - Table's catalog name -// - ARROW:FLIGHT:SQL:DB_SCHEMA_NAME - Database schema name -// - ARROW:FLIGHT:SQL:TABLE_NAME - Table name -// - ARROW:FLIGHT:SQL:TYPE_NAME - The data source-specific name for the data type of the column. -// - ARROW:FLIGHT:SQL:PRECISION - Column precision/size -// - ARROW:FLIGHT:SQL:SCALE - Column scale/decimal digits if applicable -// - ARROW:FLIGHT:SQL:IS_AUTO_INCREMENT - "1" indicates if the column is auto incremented, "0" otherwise. -// - ARROW:FLIGHT:SQL:IS_CASE_SENSITIVE - "1" indicates if the column is case sensitive, "0" otherwise. -// - ARROW:FLIGHT:SQL:IS_READ_ONLY - "1" indicates if the column is read only, "0" otherwise. -// - ARROW:FLIGHT:SQL:IS_SEARCHABLE - "1" indicates if the column is searchable via WHERE clause, "0" otherwise. -// - GetFlightInfo: execute the query. +// - GetSchema: return the Arrow schema of the query. +// Fields on this schema may contain the following metadata: +// - ARROW:FLIGHT:SQL:CATALOG_NAME - Table's catalog name +// - ARROW:FLIGHT:SQL:DB_SCHEMA_NAME - Database schema name +// - ARROW:FLIGHT:SQL:TABLE_NAME - Table name +// - ARROW:FLIGHT:SQL:TYPE_NAME - The data source-specific name for the data type of the column. +// - ARROW:FLIGHT:SQL:PRECISION - Column precision/size +// - ARROW:FLIGHT:SQL:SCALE - Column scale/decimal digits if applicable +// - ARROW:FLIGHT:SQL:IS_AUTO_INCREMENT - "1" indicates if the column is auto incremented, "0" otherwise. +// - ARROW:FLIGHT:SQL:IS_CASE_SENSITIVE - "1" indicates if the column is case sensitive, "0" otherwise. +// - ARROW:FLIGHT:SQL:IS_READ_ONLY - "1" indicates if the column is read only, "0" otherwise. +// - ARROW:FLIGHT:SQL:IS_SEARCHABLE - "1" indicates if the column is searchable via WHERE clause, "0" otherwise. +// - GetFlightInfo: execute the query. type CommandStatementQuery struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3867,22 +3942,23 @@ func (x *CommandStatementQuery) GetTransactionId() []byte { return nil } +// // Represents a Substrait plan. Used in the command member of FlightDescriptor // for the following RPC calls: -// - GetSchema: return the Arrow schema of the query. -// Fields on this schema may contain the following metadata: -// - ARROW:FLIGHT:SQL:CATALOG_NAME - Table's catalog name -// - ARROW:FLIGHT:SQL:DB_SCHEMA_NAME - Database schema name -// - ARROW:FLIGHT:SQL:TABLE_NAME - Table name -// - ARROW:FLIGHT:SQL:TYPE_NAME - The data source-specific name for the data type of the column. -// - ARROW:FLIGHT:SQL:PRECISION - Column precision/size -// - ARROW:FLIGHT:SQL:SCALE - Column scale/decimal digits if applicable -// - ARROW:FLIGHT:SQL:IS_AUTO_INCREMENT - "1" indicates if the column is auto incremented, "0" otherwise. -// - ARROW:FLIGHT:SQL:IS_CASE_SENSITIVE - "1" indicates if the column is case sensitive, "0" otherwise. -// - ARROW:FLIGHT:SQL:IS_READ_ONLY - "1" indicates if the column is read only, "0" otherwise. -// - ARROW:FLIGHT:SQL:IS_SEARCHABLE - "1" indicates if the column is searchable via WHERE clause, "0" otherwise. -// - GetFlightInfo: execute the query. -// - DoPut: execute the query. +// - GetSchema: return the Arrow schema of the query. +// Fields on this schema may contain the following metadata: +// - ARROW:FLIGHT:SQL:CATALOG_NAME - Table's catalog name +// - ARROW:FLIGHT:SQL:DB_SCHEMA_NAME - Database schema name +// - ARROW:FLIGHT:SQL:TABLE_NAME - Table name +// - ARROW:FLIGHT:SQL:TYPE_NAME - The data source-specific name for the data type of the column. +// - ARROW:FLIGHT:SQL:PRECISION - Column precision/size +// - ARROW:FLIGHT:SQL:SCALE - Column scale/decimal digits if applicable +// - ARROW:FLIGHT:SQL:IS_AUTO_INCREMENT - "1" indicates if the column is auto incremented, "0" otherwise. +// - ARROW:FLIGHT:SQL:IS_CASE_SENSITIVE - "1" indicates if the column is case sensitive, "0" otherwise. +// - ARROW:FLIGHT:SQL:IS_READ_ONLY - "1" indicates if the column is read only, "0" otherwise. +// - ARROW:FLIGHT:SQL:IS_SEARCHABLE - "1" indicates if the column is searchable via WHERE clause, "0" otherwise. +// - GetFlightInfo: execute the query. +// - DoPut: execute the query. type CommandStatementSubstraitPlan struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3940,7 +4016,7 @@ func (x *CommandStatementSubstraitPlan) GetTransactionId() []byte { return nil } -// * +//* // Represents a ticket resulting from GetFlightInfo with a CommandStatementQuery. // This should be used only once and treated as an opaque value, that is, clients should not attempt to parse this. type TicketStatementQuery struct { @@ -3991,22 +4067,23 @@ func (x *TicketStatementQuery) GetStatementHandle() []byte { return nil } +// // Represents an instance of executing a prepared statement. Used in the command member of FlightDescriptor for // the following RPC calls: -// - GetSchema: return the Arrow schema of the query. -// Fields on this schema may contain the following metadata: -// - ARROW:FLIGHT:SQL:CATALOG_NAME - Table's catalog name -// - ARROW:FLIGHT:SQL:DB_SCHEMA_NAME - Database schema name -// - ARROW:FLIGHT:SQL:TABLE_NAME - Table name -// - ARROW:FLIGHT:SQL:TYPE_NAME - The data source-specific name for the data type of the column. -// - ARROW:FLIGHT:SQL:PRECISION - Column precision/size -// - ARROW:FLIGHT:SQL:SCALE - Column scale/decimal digits if applicable -// - ARROW:FLIGHT:SQL:IS_AUTO_INCREMENT - "1" indicates if the column is auto incremented, "0" otherwise. -// - ARROW:FLIGHT:SQL:IS_CASE_SENSITIVE - "1" indicates if the column is case sensitive, "0" otherwise. -// - ARROW:FLIGHT:SQL:IS_READ_ONLY - "1" indicates if the column is read only, "0" otherwise. -// - ARROW:FLIGHT:SQL:IS_SEARCHABLE - "1" indicates if the column is searchable via WHERE clause, "0" otherwise. -// - DoPut: bind parameter values. All of the bound parameter sets will be executed as a single atomic execution. -// - GetFlightInfo: execute the prepared statement instance. +// - GetSchema: return the Arrow schema of the query. +// Fields on this schema may contain the following metadata: +// - ARROW:FLIGHT:SQL:CATALOG_NAME - Table's catalog name +// - ARROW:FLIGHT:SQL:DB_SCHEMA_NAME - Database schema name +// - ARROW:FLIGHT:SQL:TABLE_NAME - Table name +// - ARROW:FLIGHT:SQL:TYPE_NAME - The data source-specific name for the data type of the column. +// - ARROW:FLIGHT:SQL:PRECISION - Column precision/size +// - ARROW:FLIGHT:SQL:SCALE - Column scale/decimal digits if applicable +// - ARROW:FLIGHT:SQL:IS_AUTO_INCREMENT - "1" indicates if the column is auto incremented, "0" otherwise. +// - ARROW:FLIGHT:SQL:IS_CASE_SENSITIVE - "1" indicates if the column is case sensitive, "0" otherwise. +// - ARROW:FLIGHT:SQL:IS_READ_ONLY - "1" indicates if the column is read only, "0" otherwise. +// - ARROW:FLIGHT:SQL:IS_SEARCHABLE - "1" indicates if the column is searchable via WHERE clause, "0" otherwise. +// - DoPut: bind parameter values. All of the bound parameter sets will be executed as a single atomic execution. +// - GetFlightInfo: execute the prepared statement instance. type CommandPreparedStatementQuery struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -4055,6 +4132,7 @@ func (x *CommandPreparedStatementQuery) GetPreparedStatementHandle() []byte { return nil } +// // Represents a SQL update query. Used in the command member of FlightDescriptor // for the the RPC call DoPut to cause the server to execute the included SQL update. type CommandStatementUpdate struct { @@ -4114,6 +4192,7 @@ func (x *CommandStatementUpdate) GetTransactionId() []byte { return nil } +// // Represents a SQL update query. Used in the command member of FlightDescriptor // for the the RPC call DoPut to cause the server to execute the included // prepared statement handle as an update. @@ -4165,6 +4244,7 @@ func (x *CommandPreparedStatementUpdate) GetPreparedStatementHandle() []byte { return nil } +// // Returned from the RPC call DoPut when a CommandStatementUpdate // CommandPreparedStatementUpdate was in the request, containing // results from the update. @@ -4217,6 +4297,7 @@ func (x *DoPutUpdateResult) GetRecordCount() int64 { return 0 } +// // Request message for the "CancelQuery" action. // // Explicitly cancel a running query. @@ -4285,6 +4366,7 @@ func (x *ActionCancelQueryRequest) GetInfo() []byte { return nil } +// // The result of cancelling a query. // // The result should be wrapped in a google.protobuf.Any message. diff --git a/go/arrow/flight/gen/flight/Flight_grpc.pb.go b/go/arrow/flight/gen/flight/Flight_grpc.pb.go index 150de71a1113b..87d9abc5926eb 100644 --- a/go/arrow/flight/gen/flight/Flight_grpc.pb.go +++ b/go/arrow/flight/gen/flight/Flight_grpc.pb.go @@ -1,4 +1,8 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v4.23.4 +// source: Flight.proto package flight @@ -11,17 +15,20 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. const _ = grpc.SupportPackageIsVersion7 // FlightServiceClient is the client API for FlightService service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type FlightServiceClient interface { + // // Handshake between client and server. Depending on the server, the // handshake may be required to determine the token that should be used for // future operations. Both request and response are streams to allow multiple // round-trips depending on auth mechanism. Handshake(ctx context.Context, opts ...grpc.CallOption) (FlightService_HandshakeClient, error) + // // Get a list of available streams given a particular criteria. Most flight // services will expose one or more streams that are readily available for // retrieval. This api allows listing the streams available for @@ -29,6 +36,7 @@ type FlightServiceClient interface { // the subset of streams that can be listed via this interface. Each flight // service allows its own definition of how to consume criteria. ListFlights(ctx context.Context, in *Criteria, opts ...grpc.CallOption) (FlightService_ListFlightsClient, error) + // // For a given FlightDescriptor, get information about how the flight can be // consumed. This is a useful interface if the consumer of the interface // already can identify the specific flight to consume. This interface can @@ -40,6 +48,7 @@ type FlightServiceClient interface { // available for consumption for the duration defined by the specific flight // service. GetFlightInfo(ctx context.Context, in *FlightDescriptor, opts ...grpc.CallOption) (*FlightInfo, error) + // // For a given FlightDescriptor, start a query and get information // to poll its execution status. This is a useful interface if the // query may be a long-running query. The first PollFlightInfo call @@ -63,16 +72,19 @@ type FlightServiceClient interface { // A client may use the CancelFlightInfo action with // PollInfo.info to cancel the running query. PollFlightInfo(ctx context.Context, in *FlightDescriptor, opts ...grpc.CallOption) (*PollInfo, error) + // // For a given FlightDescriptor, get the Schema as described in Schema.fbs::Schema // This is used when a consumer needs the Schema of flight stream. Similar to // GetFlightInfo this interface may generate a new flight that was not previously // available in ListFlights. GetSchema(ctx context.Context, in *FlightDescriptor, opts ...grpc.CallOption) (*SchemaResult, error) + // // Retrieve a single stream associated with a particular descriptor // associated with the referenced ticket. A Flight can be composed of one or // more streams where each stream can be retrieved using a separate opaque // ticket that the flight service uses for managing a collection of streams. DoGet(ctx context.Context, in *Ticket, opts ...grpc.CallOption) (FlightService_DoGetClient, error) + // // Push a stream to the flight service associated with a particular // flight stream. This allows a client of a flight service to upload a stream // of data. Depending on the particular flight service, a client consumer @@ -80,12 +92,14 @@ type FlightServiceClient interface { // number. In the latter, the service might implement a 'seal' action that // can be applied to a descriptor once all streams are uploaded. DoPut(ctx context.Context, opts ...grpc.CallOption) (FlightService_DoPutClient, error) + // // Open a bidirectional data channel for a given descriptor. This // allows clients to send and receive arbitrary Arrow data and // application-specific metadata in a single logical stream. In // contrast to DoGet/DoPut, this is more suited for clients // offloading computation (rather than storage) to a Flight service. DoExchange(ctx context.Context, opts ...grpc.CallOption) (FlightService_DoExchangeClient, error) + // // Flight services can support an arbitrary number of simple actions in // addition to the possible ListFlights, GetFlightInfo, DoGet, DoPut // operations that are potentially available. DoAction allows a flight client @@ -93,6 +107,7 @@ type FlightServiceClient interface { // opaque request and response objects that are specific to the type action // being undertaken. DoAction(ctx context.Context, in *Action, opts ...grpc.CallOption) (FlightService_DoActionClient, error) + // // A flight service exposes all of the available action types that it has // along with descriptions. This allows different flight consumers to // understand the capabilities of the flight service. @@ -108,7 +123,7 @@ func NewFlightServiceClient(cc grpc.ClientConnInterface) FlightServiceClient { } func (c *flightServiceClient) Handshake(ctx context.Context, opts ...grpc.CallOption) (FlightService_HandshakeClient, error) { - stream, err := c.cc.NewStream(ctx, &_FlightService_serviceDesc.Streams[0], "/arrow.flight.protocol.FlightService/Handshake", opts...) + stream, err := c.cc.NewStream(ctx, &FlightService_ServiceDesc.Streams[0], "/arrow.flight.protocol.FlightService/Handshake", opts...) if err != nil { return nil, err } @@ -139,7 +154,7 @@ func (x *flightServiceHandshakeClient) Recv() (*HandshakeResponse, error) { } func (c *flightServiceClient) ListFlights(ctx context.Context, in *Criteria, opts ...grpc.CallOption) (FlightService_ListFlightsClient, error) { - stream, err := c.cc.NewStream(ctx, &_FlightService_serviceDesc.Streams[1], "/arrow.flight.protocol.FlightService/ListFlights", opts...) + stream, err := c.cc.NewStream(ctx, &FlightService_ServiceDesc.Streams[1], "/arrow.flight.protocol.FlightService/ListFlights", opts...) if err != nil { return nil, err } @@ -198,7 +213,7 @@ func (c *flightServiceClient) GetSchema(ctx context.Context, in *FlightDescripto } func (c *flightServiceClient) DoGet(ctx context.Context, in *Ticket, opts ...grpc.CallOption) (FlightService_DoGetClient, error) { - stream, err := c.cc.NewStream(ctx, &_FlightService_serviceDesc.Streams[2], "/arrow.flight.protocol.FlightService/DoGet", opts...) + stream, err := c.cc.NewStream(ctx, &FlightService_ServiceDesc.Streams[2], "/arrow.flight.protocol.FlightService/DoGet", opts...) if err != nil { return nil, err } @@ -230,7 +245,7 @@ func (x *flightServiceDoGetClient) Recv() (*FlightData, error) { } func (c *flightServiceClient) DoPut(ctx context.Context, opts ...grpc.CallOption) (FlightService_DoPutClient, error) { - stream, err := c.cc.NewStream(ctx, &_FlightService_serviceDesc.Streams[3], "/arrow.flight.protocol.FlightService/DoPut", opts...) + stream, err := c.cc.NewStream(ctx, &FlightService_ServiceDesc.Streams[3], "/arrow.flight.protocol.FlightService/DoPut", opts...) if err != nil { return nil, err } @@ -261,7 +276,7 @@ func (x *flightServiceDoPutClient) Recv() (*PutResult, error) { } func (c *flightServiceClient) DoExchange(ctx context.Context, opts ...grpc.CallOption) (FlightService_DoExchangeClient, error) { - stream, err := c.cc.NewStream(ctx, &_FlightService_serviceDesc.Streams[4], "/arrow.flight.protocol.FlightService/DoExchange", opts...) + stream, err := c.cc.NewStream(ctx, &FlightService_ServiceDesc.Streams[4], "/arrow.flight.protocol.FlightService/DoExchange", opts...) if err != nil { return nil, err } @@ -292,7 +307,7 @@ func (x *flightServiceDoExchangeClient) Recv() (*FlightData, error) { } func (c *flightServiceClient) DoAction(ctx context.Context, in *Action, opts ...grpc.CallOption) (FlightService_DoActionClient, error) { - stream, err := c.cc.NewStream(ctx, &_FlightService_serviceDesc.Streams[5], "/arrow.flight.protocol.FlightService/DoAction", opts...) + stream, err := c.cc.NewStream(ctx, &FlightService_ServiceDesc.Streams[5], "/arrow.flight.protocol.FlightService/DoAction", opts...) if err != nil { return nil, err } @@ -324,7 +339,7 @@ func (x *flightServiceDoActionClient) Recv() (*Result, error) { } func (c *flightServiceClient) ListActions(ctx context.Context, in *Empty, opts ...grpc.CallOption) (FlightService_ListActionsClient, error) { - stream, err := c.cc.NewStream(ctx, &_FlightService_serviceDesc.Streams[6], "/arrow.flight.protocol.FlightService/ListActions", opts...) + stream, err := c.cc.NewStream(ctx, &FlightService_ServiceDesc.Streams[6], "/arrow.flight.protocol.FlightService/ListActions", opts...) if err != nil { return nil, err } @@ -359,11 +374,13 @@ func (x *flightServiceListActionsClient) Recv() (*ActionType, error) { // All implementations must embed UnimplementedFlightServiceServer // for forward compatibility type FlightServiceServer interface { + // // Handshake between client and server. Depending on the server, the // handshake may be required to determine the token that should be used for // future operations. Both request and response are streams to allow multiple // round-trips depending on auth mechanism. Handshake(FlightService_HandshakeServer) error + // // Get a list of available streams given a particular criteria. Most flight // services will expose one or more streams that are readily available for // retrieval. This api allows listing the streams available for @@ -371,6 +388,7 @@ type FlightServiceServer interface { // the subset of streams that can be listed via this interface. Each flight // service allows its own definition of how to consume criteria. ListFlights(*Criteria, FlightService_ListFlightsServer) error + // // For a given FlightDescriptor, get information about how the flight can be // consumed. This is a useful interface if the consumer of the interface // already can identify the specific flight to consume. This interface can @@ -382,6 +400,7 @@ type FlightServiceServer interface { // available for consumption for the duration defined by the specific flight // service. GetFlightInfo(context.Context, *FlightDescriptor) (*FlightInfo, error) + // // For a given FlightDescriptor, start a query and get information // to poll its execution status. This is a useful interface if the // query may be a long-running query. The first PollFlightInfo call @@ -405,16 +424,19 @@ type FlightServiceServer interface { // A client may use the CancelFlightInfo action with // PollInfo.info to cancel the running query. PollFlightInfo(context.Context, *FlightDescriptor) (*PollInfo, error) + // // For a given FlightDescriptor, get the Schema as described in Schema.fbs::Schema // This is used when a consumer needs the Schema of flight stream. Similar to // GetFlightInfo this interface may generate a new flight that was not previously // available in ListFlights. GetSchema(context.Context, *FlightDescriptor) (*SchemaResult, error) + // // Retrieve a single stream associated with a particular descriptor // associated with the referenced ticket. A Flight can be composed of one or // more streams where each stream can be retrieved using a separate opaque // ticket that the flight service uses for managing a collection of streams. DoGet(*Ticket, FlightService_DoGetServer) error + // // Push a stream to the flight service associated with a particular // flight stream. This allows a client of a flight service to upload a stream // of data. Depending on the particular flight service, a client consumer @@ -422,12 +444,14 @@ type FlightServiceServer interface { // number. In the latter, the service might implement a 'seal' action that // can be applied to a descriptor once all streams are uploaded. DoPut(FlightService_DoPutServer) error + // // Open a bidirectional data channel for a given descriptor. This // allows clients to send and receive arbitrary Arrow data and // application-specific metadata in a single logical stream. In // contrast to DoGet/DoPut, this is more suited for clients // offloading computation (rather than storage) to a Flight service. DoExchange(FlightService_DoExchangeServer) error + // // Flight services can support an arbitrary number of simple actions in // addition to the possible ListFlights, GetFlightInfo, DoGet, DoPut // operations that are potentially available. DoAction allows a flight client @@ -435,6 +459,7 @@ type FlightServiceServer interface { // opaque request and response objects that are specific to the type action // being undertaken. DoAction(*Action, FlightService_DoActionServer) error + // // A flight service exposes all of the available action types that it has // along with descriptions. This allows different flight consumers to // understand the capabilities of the flight service. @@ -485,8 +510,8 @@ type UnsafeFlightServiceServer interface { mustEmbedUnimplementedFlightServiceServer() } -func RegisterFlightServiceServer(s *grpc.Server, srv FlightServiceServer) { - s.RegisterService(&_FlightService_serviceDesc, srv) +func RegisterFlightServiceServer(s grpc.ServiceRegistrar, srv FlightServiceServer) { + s.RegisterService(&FlightService_ServiceDesc, srv) } func _FlightService_Handshake_Handler(srv interface{}, stream grpc.ServerStream) error { @@ -705,7 +730,10 @@ func (x *flightServiceListActionsServer) Send(m *ActionType) error { return x.ServerStream.SendMsg(m) } -var _FlightService_serviceDesc = grpc.ServiceDesc{ +// FlightService_ServiceDesc is the grpc.ServiceDesc for FlightService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var FlightService_ServiceDesc = grpc.ServiceDesc{ ServiceName: "arrow.flight.protocol.FlightService", HandlerType: (*FlightServiceServer)(nil), Methods: []grpc.MethodDesc{ diff --git a/go/arrow/internal/flight_integration/scenario.go b/go/arrow/internal/flight_integration/scenario.go index 4108cf8124245..4f47d7fd506ee 100644 --- a/go/arrow/internal/flight_integration/scenario.go +++ b/go/arrow/internal/flight_integration/scenario.go @@ -71,6 +71,8 @@ func GetScenario(name string, args ...string) Scenario { return &expirationTimeRenewFlightEndpointScenarioTester{} case "poll_flight_info": return &pollFlightInfoScenarioTester{} + case "app_metadata_flight_info_endpoint": + return &appMetadataFlightInfoEndpointScenarioTester{} case "flight_sql": return &flightSqlScenarioTester{} case "flight_sql:extension": @@ -1153,7 +1155,7 @@ func (tester *pollFlightInfoScenarioTester) PollFlightInfo(ctx context.Context, nil, ) endpoints := []*flight.FlightEndpoint{ - &flight.FlightEndpoint{ + { Ticket: &flight.Ticket{Ticket: []byte("long-running query")}, Location: []*flight.Location{}, }, @@ -1236,6 +1238,66 @@ func (tester *pollFlightInfoScenarioTester) RunClient(addr string, opts ...grpc. return nil } +type appMetadataFlightInfoEndpointScenarioTester struct { + flight.BaseFlightServer +} + +func (tester *appMetadataFlightInfoEndpointScenarioTester) MakeServer(port int) flight.Server { + srv := flight.NewServerWithMiddleware(nil) + srv.RegisterFlightService(tester) + initServer(port, srv) + return srv +} + +func (tester *appMetadataFlightInfoEndpointScenarioTester) GetFlightInfo(ctx context.Context, desc *flight.FlightDescriptor) (*flight.FlightInfo, error) { + schema := arrow.NewSchema( + []arrow.Field{ + {Name: "number", Type: arrow.PrimitiveTypes.Uint32}, + }, + nil, + ) + + if desc.Type != flight.DescriptorCMD { + return nil, fmt.Errorf("%w: should have received CMD descriptor", arrow.ErrInvalid) + } + endpoints := []*flight.FlightEndpoint{{AppMetadata: desc.Cmd}} + return &flight.FlightInfo{ + Schema: flight.SerializeSchema(schema, memory.DefaultAllocator), + FlightDescriptor: desc, + Endpoint: endpoints, + TotalRecords: -1, + TotalBytes: -1, + AppMetadata: desc.Cmd, + }, nil +} + +func (tester *appMetadataFlightInfoEndpointScenarioTester) RunClient(addr string, opts ...grpc.DialOption) error { + client, err := flight.NewClientWithMiddleware(addr, nil, nil, opts...) + if err != nil { + return err + } + defer client.Close() + + ctx := context.Background() + desc := flight.FlightDescriptor{ + Type: flight.DescriptorCMD, + Cmd: []byte("foobar"), + } + info, err := client.GetFlightInfo(ctx, &desc) + if err != nil { + return err + } + switch { + case !bytes.Equal(desc.Cmd, info.AppMetadata): + return fmt.Errorf("invalid flight info app_metadata: %s, expected: %s", info.AppMetadata, desc.Cmd) + case len(info.Endpoint) != 1: + return fmt.Errorf("expected exactly 1 flight endpoint, got: %d", len(info.Endpoint)) + case !bytes.Equal(desc.Cmd, info.Endpoint[0].AppMetadata): + return fmt.Errorf("invalid flight endpoint app_metadata: %s, expected: %s", info.Endpoint[0].AppMetadata, desc.Cmd) + } + return nil +} + const ( updateStatementExpectedRows int64 = 10000 updateStatementWithTransactionExpectedRows int64 = 15000 From 5514b223ebc1345c7bbd501fe3cc57dcac668e86 Mon Sep 17 00:00:00 2001 From: Ed Seidl Date: Tue, 3 Oct 2023 12:14:50 -0700 Subject: [PATCH 37/56] GH-37939: [C++] Use signed arithmetic for frame of reference when encoding DELTA_BINARY_PACKED (#37940) Closes #37939. ### What changes are included in this PR? This PR changes values used in the `DELTA_BINARY_PACKED` encoder to signed types. To gracefully handle overflow, arithmetic is still performed in the unsigned domain, but other operations such as computing the min and max deltas are done in the signed domain. Using signed types ensures the optimal number of bits is used when encoding the deltas, which was not the case before if any negative deltas were encountered (which is obviously common). ### Are these changes tested? I've included two tests that result in overflow. ### Are there any user-facing changes? No * Closes: #37939 Authored-by: seidl Signed-off-by: Antoine Pitrou --- cpp/src/parquet/encoding.cc | 27 ++++++++------ cpp/src/parquet/encoding_test.cc | 64 ++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 12 deletions(-) diff --git a/cpp/src/parquet/encoding.cc b/cpp/src/parquet/encoding.cc index 9f705768e4eff..931b9fd10729f 100644 --- a/cpp/src/parquet/encoding.cc +++ b/cpp/src/parquet/encoding.cc @@ -57,6 +57,7 @@ using arrow::VisitNullBitmapInline; using arrow::internal::AddWithOverflow; using arrow::internal::checked_cast; using arrow::internal::MultiplyWithOverflow; +using arrow::internal::SafeSignedSubtract; using arrow::internal::SubtractWithOverflow; using arrow::util::SafeLoad; using arrow::util::SafeLoadAs; @@ -2189,9 +2190,9 @@ class DeltaBitPackEncoder : public EncoderImpl, virtual public TypedEncoder deltas_; + T first_value_{0}; + T current_value_{0}; + ArrowPoolVector deltas_; std::shared_ptr bits_buffer_; ::arrow::BufferBuilder sink_; ::arrow::bit_util::BitWriter bit_writer_; @@ -2212,12 +2213,12 @@ void DeltaBitPackEncoder::Put(const T* src, int num_values) { total_value_count_ += num_values; while (idx < num_values) { - UT value = static_cast(src[idx]); + T value = src[idx]; // Calculate deltas. The possible overflow is handled by use of unsigned integers // making subtraction operations well-defined and correct even in case of overflow. // Encoded integers will wrap back around on decoding. // See http://en.wikipedia.org/wiki/Modular_arithmetic#Integers_modulo_n - deltas_[values_current_block_] = value - current_value_; + deltas_[values_current_block_] = SafeSignedSubtract(value, current_value_); current_value_ = value; idx++; values_current_block_++; @@ -2233,9 +2234,11 @@ void DeltaBitPackEncoder::FlushBlock() { return; } - const UT min_delta = + // Calculate the frame of reference for this miniblock. This value will be subtracted + // from all deltas to guarantee all deltas are positive for encoding. + const T min_delta = *std::min_element(deltas_.begin(), deltas_.begin() + values_current_block_); - bit_writer_.PutZigZagVlqInt(static_cast(min_delta)); + bit_writer_.PutZigZagVlqInt(min_delta); // Call to GetNextBytePtr reserves mini_blocks_per_block_ bytes of space to write // bit widths of miniblocks as they become known during the encoding. @@ -2250,17 +2253,17 @@ void DeltaBitPackEncoder::FlushBlock() { std::min(values_per_mini_block_, values_current_block_); const uint32_t start = i * values_per_mini_block_; - const UT max_delta = *std::max_element( + const T max_delta = *std::max_element( deltas_.begin() + start, deltas_.begin() + start + values_current_mini_block); // The minimum number of bits required to write any of values in deltas_ vector. // See overflow comment above. - const auto bit_width = bit_width_data[i] = - bit_util::NumRequiredBits(max_delta - min_delta); + const auto bit_width = bit_width_data[i] = bit_util::NumRequiredBits( + static_cast(max_delta) - static_cast(min_delta)); for (uint32_t j = start; j < start + values_current_mini_block; j++) { - // See overflow comment above. - const UT value = deltas_[j] - min_delta; + // Convert delta to frame of reference. See overflow comment above. + const UT value = static_cast(deltas_[j]) - static_cast(min_delta); bit_writer_.PutValue(value, bit_width); } // If there are not enough values to fill the last mini block, we pad the mini block diff --git a/cpp/src/parquet/encoding_test.cc b/cpp/src/parquet/encoding_test.cc index 71dc40d33ac47..9861c317c80d9 100644 --- a/cpp/src/parquet/encoding_test.cc +++ b/cpp/src/parquet/encoding_test.cc @@ -1634,6 +1634,70 @@ TYPED_TEST(TestDeltaBitPackEncoding, NonZeroPaddedMiniblockBitWidth) { } } +// Test that the DELTA_BINARY_PACKED encoding works properply in the presence of values +// that will cause integer overflow (see GH-37939). +TYPED_TEST(TestDeltaBitPackEncoding, DeltaBitPackedWrapping) { + using T = typename TypeParam::c_type; + + // Values that should wrap when converted to deltas, and then when converted to the + // frame of reference. + std::vector int_values = {std::numeric_limits::min(), + std::numeric_limits::max(), + std::numeric_limits::min(), + std::numeric_limits::max(), + 0, + -1, + 0, + 1, + -1, + 1}; + const int num_values = static_cast(int_values.size()); + + auto const encoder = MakeTypedEncoder( + Encoding::DELTA_BINARY_PACKED, /*use_dictionary=*/false, this->descr_.get()); + encoder->Put(int_values, num_values); + auto const encoded = encoder->FlushValues(); + + auto const decoder = + MakeTypedDecoder(Encoding::DELTA_BINARY_PACKED, this->descr_.get()); + + std::vector decoded(num_values); + decoder->SetData(num_values, encoded->data(), static_cast(encoded->size())); + + const int values_decoded = decoder->Decode(decoded.data(), num_values); + + ASSERT_EQ(num_values, values_decoded); + ASSERT_NO_FATAL_FAILURE( + VerifyResults(decoded.data(), int_values.data(), num_values)); +} + +// Test that the DELTA_BINARY_PACKED encoding does not use more bits to encode than +// necessary (see GH-37939). +TYPED_TEST(TestDeltaBitPackEncoding, DeltaBitPackedSize) { + using T = typename TypeParam::c_type; + constexpr int num_values = 128; + // 128 values should be <= 1 block of values encoded with 2 bits + // delta header should be 0x8001|0x8002 0x04 0x8001 0x02 (6 bytes) + // mini-block header should be 0x01 0x02020202 (5 bytes) + constexpr int encoded_size = 2 * num_values / 8 + 6 + 5; + + // Create a run of {1, 0, -1, 0, 1, 0, ...}. + // min_delta is -1, max_delta is 1, max_delta - min_delta is 2, so this requires 2 bits + // to encode. + std::vector int_values(num_values); + std::iota(int_values.begin(), int_values.end(), 0); + std::transform(int_values.begin(), int_values.end(), int_values.begin(), [](T idx) { + return (idx % 2) == 1 ? 0 : (idx % 4) == 0 ? 1 : -1; + }); + + auto const encoder = MakeTypedEncoder( + Encoding::DELTA_BINARY_PACKED, /*use_dictionary=*/false, this->descr_.get()); + encoder->Put(int_values, num_values); + auto const encoded = encoder->FlushValues(); + + ASSERT_EQ(encoded->size(), encoded_size); +} + // ---------------------------------------------------------------------- // Rle for Boolean encode/decode tests. From 45588a77af3548720dc64fc8ae917e469e6f106a Mon Sep 17 00:00:00 2001 From: Sutou Kouhei Date: Wed, 4 Oct 2023 05:32:13 +0900 Subject: [PATCH 38/56] GH-37984: [Release] Use ISO 8601 format for YAML date value (#37985) ### Rationale for this change If we use ISO 8601 format for date value, we can use the value as a `Date` object in Jekyll. It's easy to reuse. Use case: https://github.com/apache/arrow-site/pull/408 ### What changes are included in this PR? Use ISO 8601 format. ### Are these changes tested? No. ### Are there any user-facing changes? No. * Closes: #37984 Authored-by: Sutou Kouhei Signed-off-by: Sutou Kouhei --- dev/release/post-03-website.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dev/release/post-03-website.sh b/dev/release/post-03-website.sh index faf79625952cc..cb605aee83523 100755 --- a/dev/release/post-03-website.sh +++ b/dev/release/post-03-website.sh @@ -58,6 +58,7 @@ fi export TZ=UTC release_date=$(LC_TIME=C date "+%-d %B %Y") +release_date_iso8601=$(LC_TIME=C date "+%Y-%m-%d") previous_tag_date=$(git log -n 1 --pretty=%aI apache-arrow-${previous_version}) rough_previous_release_date=$(date --date "${previous_tag_date}" +%s) rough_release_date=$(date +%s) @@ -257,7 +258,7 @@ current: number: '${version}' pinned_number: '${pinned_version}' major_number: '${major_version}' - date: '${release_date}' + date: '${release_date_iso8601}' git-tag: '${git_tag_hash}' github-tag-link: 'https://github.com/apache/arrow/releases/tag/${git_tag}' release-notes: 'https://arrow.apache.org/release/${version}.html' From 081e354e6fc9ded8f7d3d19d8a785cff31fa5cfb Mon Sep 17 00:00:00 2001 From: sgilmore10 <74676073+sgilmore10@users.noreply.github.com> Date: Tue, 3 Oct 2023 16:35:43 -0400 Subject: [PATCH 39/56] GH-37996: [MATLAB] Add a static constructor method named `fromMATLAB` to `arrow.array.StructArray` (#37998) ### Rationale for this change Right now, the only way to construct an `arrow.array.StructArray` is to call its static method `fromArrays` method. Doing so requires users to first construct the individual field arrays before creating the `StructArray`. ```matlab >> a1 = arrow.array([1 2 3 4]); >> a2 = arrow.array(["A" "B" "C" "D"]); >> s1 = arrow.array.StructArray.fromArrays(a1, a2, FieldNames=["Number" "String"]); >> class(s1) ans = 'arrow.array.StructArray' ``` It would be nice if users could construct `StructArray`s from MATLAB `table`s by either calling `arrow.array.StructArray.fromMATLAB()` or by passing a `table` to `arrow.array()`: ```matlab >> t = table([1 2 3 4]', ["A1" "A2" "A3" "A4"]', VariableNames=["Number", "String"]) % Call fromMATLAB method >> s1 = arrow.array.StructArray.fromMATLAB(t); >> class(s1) ans = 'arrow.array.StructArray' % Pass table to arrow.array() >> class(s2) ans = 'arrow.array.StructArray' ``` ### What changes are included in this PR? 1. Added static constructor method `fromMATLAB` to `arrow.array.StructArray`. It accepts a `table` as input and optionally two name-value pairs: `FieldNames` and `Valid`. 2. Set the `ArrayStaticConstructor` property of `arrow.type.traits.StructTraits` to `@ arrow.array.StructArray.fromMATLAB`. Previously, it was set to `missing`. 3. Updated `arrow.type.traits.traits(className)` to return `StructTraits` if `className` is the string `"table"`. 4. Updated `arrow.array` to accept a MATLAB `table` as input and return an `arrow.array.StructArray` if given a `table`. 5. Changed the signature of `arrow.array()` to accept `varargin` instead of pre-determined name-value pairs. The name-value pairs accepted depends on the type of array being constructed. For example, you can supply `TimeUnit` when constructing an `arrow.array.TimestampArray`, but `TimeUnit` will not be accepted when creating an `arrow.array.Int8Array`. ### Are these changes tested? Yes. Added new tests cases to `tArray.m`, `tStructArray.m`, `ttraits.m`, and `tStructTraits.m`. ### Are there any user-facing changes? Yes, users can now create `StructArray`s directly from MATLAB `table`s by calling either `arrow.array()` or `arrow.array.StructArray.fromMATLAB`. * Closes: #37996 Authored-by: Sarah Gilmore Signed-off-by: Kevin Gurney --- matlab/src/matlab/+arrow/+array/StructArray.m | 33 +++++++ .../+arrow/+type/+traits/StructTraits.m | 5 +- .../src/matlab/+arrow/+type/+traits/traits.m | 2 + matlab/src/matlab/+arrow/array.m | 38 ++++---- matlab/test/arrow/array/tArray.m | 5 +- matlab/test/arrow/array/tStructArray.m | 86 +++++++++++++++++++ matlab/test/arrow/type/traits/tStructTraits.m | 2 +- matlab/test/arrow/type/traits/ttraits.m | 11 +++ 8 files changed, 154 insertions(+), 28 deletions(-) diff --git a/matlab/src/matlab/+arrow/+array/StructArray.m b/matlab/src/matlab/+arrow/+array/StructArray.m index 589e39fecd015..800e34fe746ec 100644 --- a/matlab/src/matlab/+arrow/+array/StructArray.m +++ b/matlab/src/matlab/+arrow/+array/StructArray.m @@ -142,5 +142,38 @@ proxy = arrow.internal.proxy.create(proxyName, args); array = arrow.array.StructArray(proxy); end + + function array = fromMATLAB(T, opts) + arguments + T table + opts.FieldNames(1, :) string {mustBeNonmissing} = T.Properties.VariableNames + opts.Valid + end + + import arrow.tabular.internal.decompose + import arrow.tabular.internal.validateColumnNames + import arrow.array.internal.getArrayProxyIDs + import arrow.internal.validate.parseValid + + if width(T) == 0 + % StructArrays require at least one field + error("arrow:struct:ZeroVariables", ... + "Input table T must have at least one variable."); + end + + % If FieldNames was provided, make sure the number of field + % names is equal to the width of the table. + validateColumnNames(opts.FieldNames, width(T)); + + arrowArrays = decompose(T); + arrayProxyIDs = getArrayProxyIDs(arrowArrays); + validElements = parseValid(opts, height(T)); + + args = struct(ArrayProxyIDs=arrayProxyIDs, ... + FieldNames=opts.FieldNames, Valid=validElements); + proxyName = "arrow.array.proxy.StructArray"; + proxy = arrow.internal.proxy.create(proxyName, args); + array = arrow.array.StructArray(proxy); + end end end \ No newline at end of file diff --git a/matlab/src/matlab/+arrow/+type/+traits/StructTraits.m b/matlab/src/matlab/+arrow/+type/+traits/StructTraits.m index 0f8b7b3a2a663..adab036f27855 100644 --- a/matlab/src/matlab/+arrow/+type/+traits/StructTraits.m +++ b/matlab/src/matlab/+arrow/+type/+traits/StructTraits.m @@ -19,10 +19,7 @@ ArrayConstructor = @arrow.array.StructArray ArrayClassName = "arrow.array.StructArray" ArrayProxyClassName = "arrow.array.proxy.StructArray" - - % TODO: Implement fromMATLAB - ArrayStaticConstructor = missing - + ArrayStaticConstructor = @arrow.array.StructArray.fromMATLAB TypeConstructor = @arrow.type.StructType TypeClassName = "arrow.type.StructType" TypeProxyClassName = "arrow.type.proxy.StructType" diff --git a/matlab/src/matlab/+arrow/+type/+traits/traits.m b/matlab/src/matlab/+arrow/+type/+traits/traits.m index f737108ce5f76..9badf63eebb81 100644 --- a/matlab/src/matlab/+arrow/+type/+traits/traits.m +++ b/matlab/src/matlab/+arrow/+type/+traits/traits.m @@ -91,6 +91,8 @@ typeTraits = TimestampTraits(); case "duration" typeTraits = Time64Traits(); + case "table" + typeTraits = StructTraits(); otherwise error("arrow:type:traits:UnsupportedMatlabClass", "Unsupported MATLAB class: " + type); end diff --git a/matlab/src/matlab/+arrow/array.m b/matlab/src/matlab/+arrow/array.m index 983b3c88680c4..e34eb8b3fcc6c 100644 --- a/matlab/src/matlab/+arrow/array.m +++ b/matlab/src/matlab/+arrow/array.m @@ -13,46 +13,42 @@ % implied. See the License for the specific language governing % permissions and limitations under the License. -function arrowArray = array(data, opts) - arguments - data - opts.InferNulls(1, 1) logical = true - opts.Valid - end +function arrowArray = array(data, varargin) data = convertCellstrToString(data); classname = string(class(data)); - args = namedargs2cell(opts); switch (classname) case "logical" - arrowArray = arrow.array.BooleanArray.fromMATLAB(data, args{:}); + arrowArray = arrow.array.BooleanArray.fromMATLAB(data, varargin{:}); case "uint8" - arrowArray = arrow.array.UInt8Array.fromMATLAB(data, args{:}); + arrowArray = arrow.array.UInt8Array.fromMATLAB(data, varargin{:}); case "uint16" - arrowArray = arrow.array.UInt16Array.fromMATLAB(data, args{:}); + arrowArray = arrow.array.UInt16Array.fromMATLAB(data, varargin{:}); case "uint32" - arrowArray = arrow.array.UInt32Array.fromMATLAB(data, args{:}); + arrowArray = arrow.array.UInt32Array.fromMATLAB(data, varargin{:}); case "uint64" - arrowArray = arrow.array.UInt64Array.fromMATLAB(data, args{:}); + arrowArray = arrow.array.UInt64Array.fromMATLAB(data, varargin{:}); case "int8" - arrowArray = arrow.array.Int8Array.fromMATLAB(data, args{:}); + arrowArray = arrow.array.Int8Array.fromMATLAB(data, varargin{:}); case "int16" - arrowArray = arrow.array.Int16Array.fromMATLAB(data, args{:}); + arrowArray = arrow.array.Int16Array.fromMATLAB(data, varargin{:}); case "int32" - arrowArray = arrow.array.Int32Array.fromMATLAB(data, args{:}); + arrowArray = arrow.array.Int32Array.fromMATLAB(data, varargin{:}); case "int64" - arrowArray = arrow.array.Int64Array.fromMATLAB(data, args{:}); + arrowArray = arrow.array.Int64Array.fromMATLAB(data, varargin{:}); case "single" - arrowArray = arrow.array.Float32Array.fromMATLAB(data, args{:}); + arrowArray = arrow.array.Float32Array.fromMATLAB(data, varargin{:}); case "double" - arrowArray = arrow.array.Float64Array.fromMATLAB(data, args{:}); + arrowArray = arrow.array.Float64Array.fromMATLAB(data, varargin{:}); case "string" - arrowArray = arrow.array.StringArray.fromMATLAB(data, args{:}); + arrowArray = arrow.array.StringArray.fromMATLAB(data, varargin{:}); case "datetime" - arrowArray = arrow.array.TimestampArray.fromMATLAB(data, args{:}); + arrowArray = arrow.array.TimestampArray.fromMATLAB(data, varargin{:}); case "duration" - arrowArray = arrow.array.Time64Array.fromMATLAB(data, args{:}); + arrowArray = arrow.array.Time64Array.fromMATLAB(data, varargin{:}); + case "table" + arrowArray = arrow.array.StructArray.fromMATLAB(data, varargin{:}); otherwise errid = "arrow:array:UnsupportedMATLABType"; msg = join(["Unable to convert MATLAB type" classname "to arrow array."]); diff --git a/matlab/test/arrow/array/tArray.m b/matlab/test/arrow/array/tArray.m index 54b31270b25d2..545d382ddf7f4 100644 --- a/matlab/test/arrow/array/tArray.m +++ b/matlab/test/arrow/array/tArray.m @@ -32,7 +32,8 @@ {[1 2], "arrow.array.Float64Array"}, ... {datetime(2022, 1, 1), "arrow.array.TimestampArray"}, ... {seconds([1 2]), "arrow.array.Time64Array"}, ... - {["A" "B"], "arrow.array.StringArray"}}; + {["A" "B"], "arrow.array.StringArray"}, ... + {table(["A" "B"]'), "arrow.array.StructArray"}}; end methods(Test) @@ -50,7 +51,7 @@ function UnsupportedMATLABTypeError(testCase) % Verify arrow.array throws an error with the identifier % "arrow:array:UnsupportedMATLABType" if the input array is not one % we support converting into an Arrow array. - matlabArray = table; + matlabArray = {table}; fcn = @() arrow.array(matlabArray); errID = "arrow:array:UnsupportedMATLABType"; testCase.verifyError(fcn, errID); diff --git a/matlab/test/arrow/array/tStructArray.m b/matlab/test/arrow/array/tStructArray.m index 639df65befbf5..83e902ee2fa23 100644 --- a/matlab/test/arrow/array/tStructArray.m +++ b/matlab/test/arrow/array/tStructArray.m @@ -273,5 +273,91 @@ function IsEqualFalse(tc) tc.verifyFalse(isequal(array1, array3)); end + function FromMATLABBasic(tc) + % Verify StructArray.fromMATLAB returns the expected + % StructArray. + import arrow.array.StructArray + + T = table([1 2]', ["A1" "A2"]', VariableNames=["Number" "String"]); + array = StructArray.fromMATLAB(T); + tc.verifyEqual(array.Length, int64(2)); + tc.verifyEqual(array.NumFields, int32(2)); + tc.verifyEqual(array.FieldNames, ["Number" "String"]); + + field1 = arrow.array([1 2]'); + field2 = arrow.array(["A1" "A2"]'); + + tc.verifyEqual(field1, array.field(1)); + tc.verifyEqual(field2, array.field(2)); + end + + function FromMATLABFieldNames(tc) + % Verify StructArray.fromMATLAB returns the expected + % StructArray when the FieldNames nv-pair is supplied. + import arrow.array.StructArray + + T = table([1 2]', ["A1" "A2"]', VariableNames=["Number" "String"]); + array = StructArray.fromMATLAB(T, FieldNames=["Custom" "Name"]); + tc.verifyEqual(array.Length, int64(2)); + tc.verifyEqual(array.NumFields, int32(2)); + tc.verifyEqual(array.FieldNames, ["Custom" "Name"]); + tc.verifyEqual(array.Valid, [true; true]); + + field1 = arrow.array([1 2]'); + field2 = arrow.array(["A1" "A2"]'); + + tc.verifyEqual(field1, array.field(1)); + tc.verifyEqual(field2, array.field(2)); + end + + function FromMATLABValid(tc) + % Verify StructArray.fromMATLAB returns the expected + % StructArray when the Valid nv-pair is supplied. + + import arrow.array.StructArray + + T = table([1 2]', ["A1" "A2"]', VariableNames=["Number" "String"]); + array = StructArray.fromMATLAB(T, Valid=2); + tc.verifyEqual(array.Length, int64(2)); + tc.verifyEqual(array.NumFields, int32(2)); + tc.verifyEqual(array.FieldNames, ["Number" "String"]); + tc.verifyEqual(array.Valid, [false; true]); + + field1 = arrow.array([1 2]'); + field2 = arrow.array(["A1" "A2"]'); + + tc.verifyEqual(field1, array.field(1)); + tc.verifyEqual(field2, array.field(2)); + end + + function FromMATLABZeroVariablesError(tc) + % Verify StructArray.fromMATLAB throws an error when the input + % table T has zero variables. + import arrow.array.StructArray + + fcn = @() StructArray.fromMATLAB(table); + tc.verifyError(fcn, "arrow:struct:ZeroVariables"); + end + + function FromMATLABWrongNumberFieldNames(tc) + % Verify StructArray.fromMATLAB throws an error when the + % FieldNames nv-pair is provided and its number of elements + % does not equal the number of variables in the input table T. + + import arrow.array.StructArray + + fcn = @() StructArray.fromMATLAB(table(1), FieldNames=["A" "B"]); + tc.verifyError(fcn, "arrow:tabular:WrongNumberColumnNames"); + end + + function FromMATLABValidNVPairBadIndex(tc) + % Verify StructArray.fromMATLAB throws an error when the + % Valid nv-pair is provided and it contains an invalid index. + + import arrow.array.StructArray + + fcn = @() StructArray.fromMATLAB(table(1), Valid=2); + tc.verifyError(fcn, "MATLAB:notLessEqual"); + end end end \ No newline at end of file diff --git a/matlab/test/arrow/type/traits/tStructTraits.m b/matlab/test/arrow/type/traits/tStructTraits.m index 07833aca162b5..dad9ec012f3e5 100644 --- a/matlab/test/arrow/type/traits/tStructTraits.m +++ b/matlab/test/arrow/type/traits/tStructTraits.m @@ -20,7 +20,7 @@ ArrayConstructor = @arrow.array.StructArray ArrayClassName = "arrow.array.StructArray" ArrayProxyClassName = "arrow.array.proxy.StructArray" - ArrayStaticConstructor = missing + ArrayStaticConstructor = @arrow.array.StructArray.fromMATLAB TypeConstructor = @arrow.type.StructType TypeClassName = "arrow.type.StructType" TypeProxyClassName = "arrow.type.proxy.StructType" diff --git a/matlab/test/arrow/type/traits/ttraits.m b/matlab/test/arrow/type/traits/ttraits.m index 2880645f2957c..d2d80b3f8f8f5 100644 --- a/matlab/test/arrow/type/traits/ttraits.m +++ b/matlab/test/arrow/type/traits/ttraits.m @@ -365,6 +365,17 @@ function TestMatlabDuration(testCase) testCase.verifyEqual(actualTraits, expectedTraits); end + function TestMatlabTable(testCase) + import arrow.type.traits.* + + type = "table"; + expectedTraits = StructTraits(); + + actualTraits = traits(type); + + testCase.verifyEqual(actualTraits, expectedTraits); + end + function TestErrorIfUnsupportedMatlabClass(testCase) import arrow.type.traits.* From 57e9386d4a3a18dfa3c5269c49efaee93aabea2b Mon Sep 17 00:00:00 2001 From: Erik McKelvey Date: Tue, 3 Oct 2023 17:43:21 -0700 Subject: [PATCH 40/56] MINOR: [Python][Docs] Fix two typos in data.rst (#37997) ### What changes are included in this PR? Fixed two minor typos in data.rst Authored-by: Erik McKelvey Signed-off-by: Sutou Kouhei --- docs/source/python/data.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/python/data.rst b/docs/source/python/data.rst index 75d1e88970c29..0ce2ddd698414 100644 --- a/docs/source/python/data.rst +++ b/docs/source/python/data.rst @@ -216,7 +216,7 @@ value during the conversion. If an integer input is supplied to To handle better compatibility with Pandas, we support interpreting NaN values as null elements. This is enabled automatically on all ``from_pandas`` function and -can be enable on the other conversion functions by passing ``from_pandas=True`` +can be enabled on the other conversion functions by passing ``from_pandas=True`` as a function parameter. List arrays @@ -510,7 +510,7 @@ a new schema and cast the data to this schema: t2.schema.field("f1").metadata t2.schema.metadata -Metadata key and value pair are ``std::string`` objects in the C++ implementation +Metadata key and value pairs are ``std::string`` objects in the C++ implementation and so they are bytes objects (``b'...'``) in Python. Record Batch Readers From 532ab464db39da0e6b03e4b046355e7bf499730a Mon Sep 17 00:00:00 2001 From: Nic Crane Date: Wed, 4 Oct 2023 11:00:50 +0100 Subject: [PATCH 41/56] MINOR: [R] Skip tests which use with_language() on CRAN (#37810) ### Rationale for this change Tests which use `with_language()` are failing on CRAN ### What changes are included in this PR? Skip those tests on CRAN for now until we find the source of the problem ### Are these changes tested? No ### Are there any user-facing changes? No Authored-by: Nic Crane Signed-off-by: Nic Crane --- r/tests/testthat/helper-arrow.R | 1 + 1 file changed, 1 insertion(+) diff --git a/r/tests/testthat/helper-arrow.R b/r/tests/testthat/helper-arrow.R index 6812a3eec0a4e..8d39f7252ee21 100644 --- a/r/tests/testthat/helper-arrow.R +++ b/r/tests/testthat/helper-arrow.R @@ -34,6 +34,7 @@ Sys.setenv(LANGUAGE = "en") options(arrow.pull_as_vector = FALSE) with_language <- function(lang, expr) { + skip_on_cran() old <- Sys.getenv("LANGUAGE") # Check what this message is before changing languages; this will # trigger caching the transations if the OS does that (some do). From 0abb672a23a8de520154e7b8d25f9eda96e217da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Cumplido?= Date: Wed, 4 Oct 2023 16:39:59 +0200 Subject: [PATCH 42/56] GH-37999: [CI][Archery] Install python3-dev on ARM jobs to have access to Python.h (#38009) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Rationale for this change Currently CI on ARM is failing due to ruamel.yaml requiring Python.h ### What changes are included in this PR? Install python3-dev ### Are these changes tested? Yes, CI ### Are there any user-facing changes? No * Closes: #37999 Authored-by: Raúl Cumplido Signed-off-by: Jacob Wujciak-Jens --- .github/workflows/cpp.yml | 3 ++- .github/workflows/go.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cpp.yml b/.github/workflows/cpp.yml index fc8d0bad58e9f..5451cbe064b59 100644 --- a/.github/workflows/cpp.yml +++ b/.github/workflows/cpp.yml @@ -108,7 +108,8 @@ jobs: restore-keys: ${{ matrix.image }}- - name: Setup Python run: | - sudo apt install -y --no-install-recommends python3 python3-pip + sudo apt update + sudo apt install -y --no-install-recommends python3 python3-dev python3-pip - name: Setup Archery run: python3 -m pip install -e dev/archery[docker] - name: Execute Docker Build diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index ad8fedb9bd9e4..a0dfb9fea1673 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -79,7 +79,8 @@ jobs: submodules: recursive - name: Setup Python run: | - sudo apt install -y --no-install-recommends python3 python3-pip + sudo apt update + sudo apt install -y --no-install-recommends python3 python3-dev python3-pip - name: Setup Archery run: python3 -m pip install -e dev/archery[docker] - name: Execute Docker Build From 02de3c1789460304e958936b78d60f824921c250 Mon Sep 17 00:00:00 2001 From: Eero Lihavainen Date: Wed, 4 Oct 2023 17:52:04 +0300 Subject: [PATCH 43/56] GH-37917: [Parquet] Add OpenAsync for FileSource (#37918) ### Rationale for this change Improves performance of file reads with an expensive Open operation. ### What changes are included in this PR? ### Are these changes tested? ### Are there any user-facing changes? No * Closes: #37917 Authored-by: Eero Lihavainen Signed-off-by: Benjamin Kietzman --- cpp/src/arrow/dataset/file_base.cc | 14 ++++++++ cpp/src/arrow/dataset/file_base.h | 1 + cpp/src/arrow/dataset/file_parquet.cc | 50 +++++++++++++++------------ 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/cpp/src/arrow/dataset/file_base.cc b/cpp/src/arrow/dataset/file_base.cc index 2fcd57d2f3622..6a97b51cf2815 100644 --- a/cpp/src/arrow/dataset/file_base.cc +++ b/cpp/src/arrow/dataset/file_base.cc @@ -81,6 +81,20 @@ Result> FileSource::Open() const { return custom_open_(); } +Future> FileSource::OpenAsync() const { + if (filesystem_) { + return filesystem_->OpenInputFileAsync(file_info_); + } + + if (buffer_) { + return Future>::MakeFinished( + std::make_shared(buffer_)); + } + + // TODO(GH-37962): custom_open_ should not block + return Future>::MakeFinished(custom_open_()); +} + int64_t FileSource::Size() const { if (filesystem_) { return file_info_.size(); diff --git a/cpp/src/arrow/dataset/file_base.h b/cpp/src/arrow/dataset/file_base.h index d33d88e9966fe..46fc8ebc40db0 100644 --- a/cpp/src/arrow/dataset/file_base.h +++ b/cpp/src/arrow/dataset/file_base.h @@ -115,6 +115,7 @@ class ARROW_DS_EXPORT FileSource : public util::EqualityComparable { /// \brief Get a RandomAccessFile which views this file source Result> Open() const; + Future> OpenAsync() const; /// \brief Get the size (in bytes) of the file or buffer /// If the file is compressed this should be the compressed (on-disk) size. diff --git a/cpp/src/arrow/dataset/file_parquet.cc b/cpp/src/arrow/dataset/file_parquet.cc index 751937e93b937..3cad1ddd8321f 100644 --- a/cpp/src/arrow/dataset/file_parquet.cc +++ b/cpp/src/arrow/dataset/file_parquet.cc @@ -479,29 +479,35 @@ Future> ParquetFileFormat::GetReader default_fragment_scan_options)); auto properties = MakeReaderProperties(*this, parquet_scan_options.get(), options->pool); - ARROW_ASSIGN_OR_RAISE(auto input, source.Open()); - // TODO(ARROW-12259): workaround since we have Future<(move-only type)> - auto reader_fut = parquet::ParquetFileReader::OpenAsync( - std::move(input), std::move(properties), metadata); - auto path = source.path(); + auto self = checked_pointer_cast(shared_from_this()); - return reader_fut.Then( - [=](const std::unique_ptr&) mutable - -> Result> { - ARROW_ASSIGN_OR_RAISE(std::unique_ptr reader, - reader_fut.MoveResult()); - std::shared_ptr metadata = reader->metadata(); - auto arrow_properties = - MakeArrowReaderProperties(*this, *metadata, *options, *parquet_scan_options); - std::unique_ptr arrow_reader; - RETURN_NOT_OK(parquet::arrow::FileReader::Make(options->pool, std::move(reader), - std::move(arrow_properties), - &arrow_reader)); - return std::move(arrow_reader); - }, - [path]( - const Status& status) -> Result> { - return WrapSourceError(status, path); + + return source.OpenAsync().Then( + [=](const std::shared_ptr& input) mutable { + return parquet::ParquetFileReader::OpenAsync(input, std::move(properties), + metadata) + .Then( + [=](const std::unique_ptr& reader) mutable + -> Result> { + auto arrow_properties = MakeArrowReaderProperties( + *self, *reader->metadata(), *options, *parquet_scan_options); + + std::unique_ptr arrow_reader; + RETURN_NOT_OK(parquet::arrow::FileReader::Make( + options->pool, + // TODO(ARROW-12259): workaround since we have Future<(move-only + // type)> It *wouldn't* be safe to const_cast reader except that + // here we know there are no other waiters on the reader. + std::move(const_cast&>( + reader)), + std::move(arrow_properties), &arrow_reader)); + + return std::move(arrow_reader); + }, + [path = source.path()](const Status& status) + -> Result> { + return WrapSourceError(status, path); + }); }); } From 7d834d65c37c17d1c19bfb497eadb983893c9ea0 Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Thu, 5 Oct 2023 09:21:56 +0200 Subject: [PATCH 44/56] GH-36709: [Python] Allow to specify use_threads=False in Table.group_by to have stable ordering (#36768) ### Rationale for this change Add a `use_threads` keyword to the `group_by` method on Table, and passes this through to the Declaration.to_table call. This also allows to specify `use_threads=False` to get stable ordering of the output, and which is also required to specify for certain aggregations (eg `"first"` will fail with the default of `use_threads=True`) ### Are these changes tested? Yes, added a test (similar to the one we have for this for `filter`), that would fail (>50% of the times) if the output was no longer ordered. * Closes: #36709 Authored-by: Joris Van den Bossche Signed-off-by: Joris Van den Bossche --- python/pyarrow/acero.py | 4 ++-- python/pyarrow/table.pxi | 20 +++++++++++++++----- python/pyarrow/tests/test_exec_plan.py | 14 ++++++++++++++ python/pyarrow/tests/test_table.py | 15 +++++++++++++++ 4 files changed, 46 insertions(+), 7 deletions(-) diff --git a/python/pyarrow/acero.py b/python/pyarrow/acero.py index 63da0a37864b2..0609e45753f0d 100644 --- a/python/pyarrow/acero.py +++ b/python/pyarrow/acero.py @@ -299,10 +299,10 @@ def _sort_source(table_or_dataset, sort_keys, output_type=Table, **kwargs): raise TypeError("Unsupported output type") -def _group_by(table, aggregates, keys): +def _group_by(table, aggregates, keys, use_threads=True): decl = Declaration.from_sequence([ Declaration("table_source", TableSourceNodeOptions(table)), Declaration("aggregate", AggregateNodeOptions(aggregates, keys=keys)) ]) - return decl.to_table(use_threads=True) + return decl.to_table(use_threads=use_threads) diff --git a/python/pyarrow/table.pxi b/python/pyarrow/table.pxi index 2eae38485dca4..36601130b3f12 100644 --- a/python/pyarrow/table.pxi +++ b/python/pyarrow/table.pxi @@ -4599,8 +4599,9 @@ cdef class Table(_Tabular): """ return self.drop_columns(columns) - def group_by(self, keys): - """Declare a grouping over the columns of the table. + def group_by(self, keys, use_threads=True): + """ + Declare a grouping over the columns of the table. Resulting grouping can then be used to perform aggregations with a subsequent ``aggregate()`` method. @@ -4609,6 +4610,9 @@ cdef class Table(_Tabular): ---------- keys : str or list[str] Name of the columns that should be used as the grouping key. + use_threads : bool, default True + Whether to use multithreading or not. When set to True (the + default), no stable ordering of the output is guaranteed. Returns ------- @@ -4635,7 +4639,7 @@ cdef class Table(_Tabular): year: [[2020,2022,2021,2019]] n_legs_sum: [[2,6,104,5]] """ - return TableGroupBy(self, keys) + return TableGroupBy(self, keys, use_threads=use_threads) def join(self, right_table, keys, right_keys=None, join_type="left outer", left_suffix=None, right_suffix=None, coalesce_keys=True, @@ -5183,6 +5187,9 @@ class TableGroupBy: Input table to execute the aggregation on. keys : str or list[str] Name of the grouped columns. + use_threads : bool, default True + Whether to use multithreading or not. When set to True (the default), + no stable ordering of the output is guaranteed. Examples -------- @@ -5208,12 +5215,13 @@ class TableGroupBy: values_sum: [[3,7,5]] """ - def __init__(self, table, keys): + def __init__(self, table, keys, use_threads=True): if isinstance(keys, str): keys = [keys] self._table = table self.keys = keys + self._use_threads = use_threads def aggregate(self, aggregations): """ @@ -5328,4 +5336,6 @@ list[tuple(str, str, FunctionOptions)] aggr_name = "_".join(target) + "_" + func_nohash group_by_aggrs.append((target, func, opt, aggr_name)) - return _pac()._group_by(self._table, group_by_aggrs, self.keys) + return _pac()._group_by( + self._table, group_by_aggrs, self.keys, use_threads=self._use_threads + ) diff --git a/python/pyarrow/tests/test_exec_plan.py b/python/pyarrow/tests/test_exec_plan.py index 58c618179b601..d85a2c2152481 100644 --- a/python/pyarrow/tests/test_exec_plan.py +++ b/python/pyarrow/tests/test_exec_plan.py @@ -321,3 +321,17 @@ def test_join_extension_array_column(): result = _perform_join( "left outer", t1, ["colB"], t3, ["colC"]) assert result["colB"] == pa.chunked_array(ext_array) + + +def test_group_by_ordering(): + # GH-36709 - preserve ordering in groupby by setting use_threads=False + table1 = pa.table({'a': [1, 2, 3, 4], 'b': ['a'] * 4}) + table2 = pa.table({'a': [1, 2, 3, 4], 'b': ['b'] * 4}) + table = pa.concat_tables([table1, table2]) + + for _ in range(50): + # 50 seems to consistently cause errors when order is not preserved. + # If the order problem is reintroduced this test will become flaky + # which is still a signal that the order is not preserved. + result = table.group_by("b", use_threads=False).aggregate([]) + assert result["b"] == pa.chunked_array([["a"], ["b"]]) diff --git a/python/pyarrow/tests/test_table.py b/python/pyarrow/tests/test_table.py index f93c6bbc2c204..b9e0d692196fb 100644 --- a/python/pyarrow/tests/test_table.py +++ b/python/pyarrow/tests/test_table.py @@ -2175,6 +2175,21 @@ def sorted_by_keys(d): } +@pytest.mark.acero +def test_table_group_by_first(): + # "first" is an ordered aggregation -> requires to specify use_threads=False + table1 = pa.table({'a': [1, 2, 3, 4], 'b': ['a', 'b'] * 2}) + table2 = pa.table({'a': [1, 2, 3, 4], 'b': ['b', 'a'] * 2}) + table = pa.concat_tables([table1, table2]) + + with pytest.raises(NotImplementedError): + table.group_by("b").aggregate([("a", "first")]) + + result = table.group_by("b", use_threads=False).aggregate([("a", "first")]) + expected = pa.table({"b": ["a", "b"], "a_first": [1, 2]}) + assert result.equals(expected) + + def test_table_to_recordbatchreader(): table = pa.Table.from_pydict({'x': [1, 2, 3]}) reader = table.to_reader() From 41705f9eca36e667fe66607a470b31e3c5c03ffe Mon Sep 17 00:00:00 2001 From: Alenka Frim Date: Thu, 5 Oct 2023 10:00:48 +0200 Subject: [PATCH 45/56] GH-35600: [Python] Allow setting path to timezone db through python API (#37436) ### Rationale for this change Add a function to change the path where timezone db should be found as a small wrapper around the setting of a C++ option `GlobalOptions`. ### What changes are included in this PR? New function `configure_tzdb`. ### Are these changes tested? ### Are there any user-facing changes? No. * Closes: #35600 Lead-authored-by: AlenkaF Co-authored-by: Antoine Pitrou Co-authored-by: Alenka Frim Co-authored-by: Sutou Kouhei Signed-off-by: Joris Van den Bossche --- ci/appveyor-cpp-build.bat | 13 +++++++++++++ python/pyarrow/__init__.py | 8 ++++---- python/pyarrow/config.pxi | 19 +++++++++++++++++++ python/pyarrow/includes/libarrow.pxd | 5 +++++ python/pyarrow/tests/conftest.py | 7 +++++++ python/pyarrow/tests/test_misc.py | 12 ++++++++++++ python/pyarrow/tests/util.py | 10 ++++++++-- 7 files changed, 68 insertions(+), 6 deletions(-) diff --git a/ci/appveyor-cpp-build.bat b/ci/appveyor-cpp-build.bat index e69c7bf2516d9..5e561a0461ea3 100644 --- a/ci/appveyor-cpp-build.bat +++ b/ci/appveyor-cpp-build.bat @@ -132,6 +132,19 @@ set ARROW_HOME=%CONDA_PREFIX%\Library @rem ARROW-3075; pkgconfig is broken for Parquet for now set PARQUET_HOME=%CONDA_PREFIX%\Library +@rem Download IANA Timezone Database to a non-standard location to +@rem test the configurability of the timezone database path +curl https://data.iana.org/time-zones/releases/tzdata2021e.tar.gz --output tzdata.tar.gz || exit /B +mkdir %USERPROFILE%\Downloads\test\tzdata +tar --extract --file tzdata.tar.gz --directory %USERPROFILE%\Downloads\test\tzdata +curl https://raw.githubusercontent.com/unicode-org/cldr/master/common/supplemental/windowsZones.xml ^ + --output %USERPROFILE%\Downloads\test\tzdata\windowsZones.xml || exit /B +@rem Remove the database from the default location +rmdir /s /q %USERPROFILE%\Downloads\tzdata +@rem Set the env var for the non-standard location of the database +@rem (only needed for testing purposes) +set PYARROW_TZDATA_PATH=%USERPROFILE%\Downloads\test\tzdata + python setup.py develop -q || exit /B set PYTHONDEVMODE=1 diff --git a/python/pyarrow/__init__.py b/python/pyarrow/__init__.py index ee0d07bb2c811..cd66abcb44840 100644 --- a/python/pyarrow/__init__.py +++ b/python/pyarrow/__init__.py @@ -66,10 +66,10 @@ def parse_git(root, **kwargs): if _gc_enabled: _gc.enable() -from pyarrow.lib import (BuildInfo, RuntimeInfo, MonthDayNano, - VersionInfo, cpp_build_info, cpp_version, - cpp_version_info, runtime_info, cpu_count, - set_cpu_count, enable_signal_handlers, +from pyarrow.lib import (BuildInfo, RuntimeInfo, set_timezone_db_path, + MonthDayNano, VersionInfo, cpp_build_info, + cpp_version, cpp_version_info, runtime_info, + cpu_count, set_cpu_count, enable_signal_handlers, io_thread_count, set_io_thread_count) diff --git a/python/pyarrow/config.pxi b/python/pyarrow/config.pxi index fb9526ba89735..cf751b810cad1 100644 --- a/python/pyarrow/config.pxi +++ b/python/pyarrow/config.pxi @@ -18,6 +18,7 @@ from pyarrow.includes.libarrow cimport GetBuildInfo from collections import namedtuple +import os VersionInfo = namedtuple('VersionInfo', ('major', 'minor', 'patch')) @@ -74,3 +75,21 @@ def runtime_info(): return RuntimeInfo( simd_level=frombytes(c_info.simd_level), detected_simd_level=frombytes(c_info.detected_simd_level)) + + +def set_timezone_db_path(path): + """ + Configure the path to text timezone database on Windows. + + Parameters + ---------- + path : str + Path to text timezone database. + """ + cdef: + CGlobalOptions options + + if path is not None: + options.timezone_db_path = tobytes(path) + + check_status(Initialize(options)) diff --git a/python/pyarrow/includes/libarrow.pxd b/python/pyarrow/includes/libarrow.pxd index f4d6541fa724c..482a6e91ba929 100644 --- a/python/pyarrow/includes/libarrow.pxd +++ b/python/pyarrow/includes/libarrow.pxd @@ -80,6 +80,11 @@ cdef extern from "arrow/config.h" namespace "arrow" nogil: CRuntimeInfo GetRuntimeInfo() + cdef cppclass CGlobalOptions" arrow::GlobalOptions": + optional[c_string] timezone_db_path + + CStatus Initialize(const CGlobalOptions& options) + cdef extern from "arrow/util/future.h" namespace "arrow" nogil: cdef cppclass CFuture_Void" arrow::Future<>": diff --git a/python/pyarrow/tests/conftest.py b/python/pyarrow/tests/conftest.py index 241ae4814a5ae..a5941e8c8d1a8 100644 --- a/python/pyarrow/tests/conftest.py +++ b/python/pyarrow/tests/conftest.py @@ -28,6 +28,7 @@ import hypothesis as h from ..conftest import groups, defaults +from pyarrow import set_timezone_db_path from pyarrow.util import find_free_port @@ -48,6 +49,12 @@ os.environ['AWS_CONFIG_FILE'] = "/dev/null" +if sys.platform == 'win32': + tzdata_set_path = os.environ.get('PYARROW_TZDATA_PATH', None) + if tzdata_set_path: + set_timezone_db_path(tzdata_set_path) + + def pytest_addoption(parser): # Create options to selectively enable test groups def bool_env(name, default=None): diff --git a/python/pyarrow/tests/test_misc.py b/python/pyarrow/tests/test_misc.py index 86cbf013cd5b4..9b9dfdd554806 100644 --- a/python/pyarrow/tests/test_misc.py +++ b/python/pyarrow/tests/test_misc.py @@ -22,6 +22,7 @@ import pytest import pyarrow as pa +from pyarrow.lib import ArrowInvalid def test_get_include(): @@ -116,6 +117,17 @@ def test_runtime_info(): subprocess.check_call([sys.executable, "-c", code], env=env) +@pytest.mark.skipif(sys.platform == "win32", + reason="Path to timezone database is not configurable " + "on non-Windows platforms") +def test_set_timezone_db_path_non_windows(): + # set_timezone_db_path raises an error on non-Windows platforms + with pytest.raises(ArrowInvalid, + match="Arrow was set to use OS timezone " + "database at compile time"): + pa.set_timezone_db_path("path") + + @pytest.mark.parametrize('klass', [ pa.Field, pa.Schema, diff --git a/python/pyarrow/tests/util.py b/python/pyarrow/tests/util.py index 0b69deb73ba28..638eee9807335 100644 --- a/python/pyarrow/tests/util.py +++ b/python/pyarrow/tests/util.py @@ -455,5 +455,11 @@ def windows_has_tzdata(): This is the default location where tz.cpp will look for (until we make this configurable at run-time) """ - tzdata_path = os.path.expandvars(r"%USERPROFILE%\Downloads\tzdata") - return os.path.exists(tzdata_path) + tzdata_bool = False + if "PYARROW_TZDATA_PATH" in os.environ: + tzdata_bool = os.path.exists(os.environ['PYARROW_TZDATA_PATH']) + if not tzdata_bool: + tzdata_path = os.path.expandvars(r"%USERPROFILE%\Downloads\tzdata") + tzdata_bool = os.path.exists(tzdata_path) + + return tzdata_bool From 334c93726f3c9d9e69eb51136c7f354974c739fd Mon Sep 17 00:00:00 2001 From: Alenka Frim Date: Thu, 5 Oct 2023 11:02:23 +0200 Subject: [PATCH 46/56] GH-37598: [Python][Interchange Protocol] Fix the from_dataframe implementation to use the column dtype (#37986) ### Rationale for this change We have been defining buffer dtypes for string and timestamp types incorrectly in the DataFrame Interchange Protocol implementation. This PR is the first step to fix the error and is dealing with the `from_dataframe` part. The next two steps to solve the connected issue are: 2. Make sure other libraries have also updated their `from_dataframe` implementation 3. Fix the data buffer dtypes for strings and timestamps. ### What changes are included in this PR? Fix the `from_dataframe` implementation to use the column dtype rather than the data buffer dtype to interpret the buffers. Only for the indices of the categorical column we still use buffer data type in order to convert the indices when constructing the `DictionaryArray`. ### Are these changes tested? No new tests are added but all the existing tests should pass and with that the stability of the change is tested. ### Are there any user-facing changes? No. * Closes: #37598 Lead-authored-by: AlenkaF Co-authored-by: Alenka Frim Co-authored-by: Joris Van den Bossche Signed-off-by: Joris Van den Bossche --- python/pyarrow/interchange/from_dataframe.py | 23 +++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/python/pyarrow/interchange/from_dataframe.py b/python/pyarrow/interchange/from_dataframe.py index 1d41aa8d7eef3..d653054e910a6 100644 --- a/python/pyarrow/interchange/from_dataframe.py +++ b/python/pyarrow/interchange/from_dataframe.py @@ -19,6 +19,7 @@ from typing import ( Any, + Tuple, ) from pyarrow.interchange.column import ( @@ -204,7 +205,9 @@ def column_to_array( pa.Array """ buffers = col.get_buffers() - data = buffers_to_array(buffers, col.size(), + data_type = col.dtype + data = buffers_to_array(buffers, data_type, + col.size(), col.describe_null, col.offset, allow_copy) @@ -236,7 +239,9 @@ def bool_column_to_array( ) buffers = col.get_buffers() - data = buffers_to_array(buffers, col.size(), + data_type = col.dtype + data = buffers_to_array(buffers, data_type, + col.size(), col.describe_null, col.offset) data = pc.cast(data, pa.bool_()) @@ -274,11 +279,15 @@ def categorical_column_to_dictionary( raise NotImplementedError( "Non-dictionary categoricals not supported yet") + # We need to first convert the dictionary column cat_column = categorical["categories"] dictionary = column_to_array(cat_column) - + # Then we need to convert the indices + # Here we need to use the buffer data type! buffers = col.get_buffers() - indices = buffers_to_array(buffers, col.size(), + _, data_type = buffers["data"] + indices = buffers_to_array(buffers, data_type, + col.size(), col.describe_null, col.offset) @@ -326,6 +335,7 @@ def map_date_type(data_type): def buffers_to_array( buffers: ColumnBuffers, + data_type: Tuple[DtypeKind, int, str, str], length: int, describe_null: ColumnNullType, offset: int = 0, @@ -339,6 +349,9 @@ def buffers_to_array( buffer : ColumnBuffers Dictionary containing tuples of underlying buffers and their associated dtype. + data_type : Tuple[DtypeKind, int, str, str], + Dtype description of the column as a tuple ``(kind, bit-width, format string, + endianness)``. length : int The number of values in the array. describe_null: ColumnNullType @@ -360,7 +373,7 @@ def buffers_to_array( is responsible for keeping the memory owner object alive as long as the returned PyArrow array is being used. """ - data_buff, data_type = buffers["data"] + data_buff, _ = buffers["data"] try: validity_buff, validity_dtype = buffers["validity"] except TypeError: From 2360cb92e71c88a66a2808c7b4cc50dc6660cb10 Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Thu, 5 Oct 2023 13:56:15 +0200 Subject: [PATCH 47/56] GH-32483: [Docs][Python] Clarify you need to use conda-forge for installing nightly conda package (#37948) ### Rationale for this change Our nightly packages don't work with the defaults channel from Anaconda. * Closes: #32483 Authored-by: Joris Van den Bossche Signed-off-by: Joris Van den Bossche --- docs/source/developers/python.rst | 3 +++ docs/source/python/install.rst | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/source/developers/python.rst b/docs/source/developers/python.rst index 23bbb835a3044..e4699a65e211e 100644 --- a/docs/source/developers/python.rst +++ b/docs/source/developers/python.rst @@ -717,6 +717,9 @@ Install the development version of PyArrow from `arrow-nightlies conda install -c arrow-nightlies pyarrow +Note that this requires to use the ``conda-forge`` channel for all other +packages (``conda config --add channels conda-forge``). + Install the development version from an `alternative PyPI `_ index: diff --git a/docs/source/python/install.rst b/docs/source/python/install.rst index ef4353415fa21..99d1c43b024aa 100644 --- a/docs/source/python/install.rst +++ b/docs/source/python/install.rst @@ -56,8 +56,8 @@ need to install the `Visual C++ Redistributable for Visual Studio 2015 .. warning:: On Linux, you will need pip >= 19.0 to detect the prebuilt binary packages. -Installing from source ----------------------- +Installing nightly packages or from source +------------------------------------------ See :ref:`python-development`. From 0fbfffbf42a42577c4855cfdd232cf069e76ae87 Mon Sep 17 00:00:00 2001 From: Adam Reeve Date: Fri, 6 Oct 2023 01:44:17 +1300 Subject: [PATCH 48/56] GH-38039: [C++][Parquet] Fix segfault getting compression level for a Parquet column (#38025) ### Rationale for this change After the changes in #35886, getting the compression level for a Parquet column segfaults if the compression level or other options weren't previously set ### What changes are included in this PR? Adds a null check on the codec options of the column properties before trying to access the compression level. ### Are these changes tested? Yes, I added a unit test. ### Are there any user-facing changes? This fixes a regression added after 13.0.0 so isn't a user-facing fix * Closes: #38039 Authored-by: Adam Reeve Signed-off-by: Antoine Pitrou --- cpp/src/parquet/properties.h | 7 ++++++- cpp/src/parquet/properties_test.cc | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/cpp/src/parquet/properties.h b/cpp/src/parquet/properties.h index bdc5b15332d09..9344181d3f82f 100644 --- a/cpp/src/parquet/properties.h +++ b/cpp/src/parquet/properties.h @@ -196,7 +196,12 @@ class PARQUET_EXPORT ColumnProperties { size_t max_statistics_size() const { return max_stats_size_; } - int compression_level() const { return codec_options_->compression_level; } + int compression_level() const { + if (!codec_options_) { + return ::arrow::util::kUseDefaultCompressionLevel; + } + return codec_options_->compression_level; + } const std::shared_ptr& codec_options() const { return codec_options_; } diff --git a/cpp/src/parquet/properties_test.cc b/cpp/src/parquet/properties_test.cc index 96c3a63b831eb..b2c574413abf7 100644 --- a/cpp/src/parquet/properties_test.cc +++ b/cpp/src/parquet/properties_test.cc @@ -49,6 +49,15 @@ TEST(TestWriterProperties, Basics) { ASSERT_FALSE(props->page_checksum_enabled()); } +TEST(TestWriterProperties, DefaultCompression) { + std::shared_ptr props = WriterProperties::Builder().build(); + + ASSERT_EQ(props->compression(ColumnPath::FromDotString("any")), + Compression::UNCOMPRESSED); + ASSERT_EQ(props->compression_level(ColumnPath::FromDotString("any")), + ::arrow::util::kUseDefaultCompressionLevel); +} + TEST(TestWriterProperties, AdvancedHandling) { WriterProperties::Builder builder; builder.compression("gzip", Compression::GZIP); From dd8734dc8ff21e7f8463b239e800aeac0ddcb764 Mon Sep 17 00:00:00 2001 From: Jacob Wujciak-Jens Date: Thu, 5 Oct 2023 14:48:44 +0200 Subject: [PATCH 49/56] GH-37923: [R] Move macOS build system to nixlibs.R (#37684) This PR modifies the build system of the R package to no longer rely on auto/homebrew. Instead this PR adds the infrastructure and code paths to use the same type of pre-compiled libarrow binaries as we use for Linux. The main difference is the use of the binaries even on CRAN (as we previously also used binaries in form of brew bottles). The addition of the new artifacts to tasks.yml should ensure that they get uploaded to the nightly repo as well as to the artifactory during the release (@ kou please confirm). A summary of the changes in this PR: - update `r/configure` and `r/tools/nixlibs.R` to enable the source build on macOS and usage of precompiled binaries using the existing mechanism to test compile a program to detect the exisitng openssl version - added tests for the changes in nixlibs.R - update the binary allow-list - Add the build jobs for libarrow binaries for arm64 and x86_64 macos with openssl 1.1 and 3.0 to the `r-binary-packages` job - Use the binaries to build the nightly packages - bump snappy version to 1.1.10 (and patch it on 10.13) due to build issues with the current version. This also touches on a number of issues in regards to a sanitizer issue we have had for a long time: #32562 #31766 - Disable the centos binary test step: #37922 Follow up issues: - #37921 - #37941 - #37945 * Closes: #37923 Lead-authored-by: Jacob Wujciak-Jens Co-authored-by: Jonathan Keane Co-authored-by: Sutou Kouhei Signed-off-by: Dewey Dunnington --- cpp/Brewfile | 6 ++ cpp/cmake_modules/SetupCxxFlags.cmake | 15 +++- cpp/cmake_modules/ThirdpartyToolchain.cmake | 21 ++++++ cpp/cmake_modules/snappy.diff | 12 +++ cpp/thirdparty/versions.txt | 5 +- dev/release/rat_exclude_files.txt | 1 + dev/tasks/macros.jinja | 14 +++- dev/tasks/r/github.packages.yml | 83 +++++++++++++++++--- dev/tasks/tasks.yml | 4 + r/configure | 55 ++------------ r/tools/nixlibs-allowlist.txt | 1 + r/tools/nixlibs.R | 84 ++++++++++++++++----- r/tools/test-nixlibs.R | 64 +++++++++++++--- 13 files changed, 268 insertions(+), 97 deletions(-) create mode 100644 cpp/cmake_modules/snappy.diff diff --git a/cpp/Brewfile b/cpp/Brewfile index 58015d2121b5b..0f5527985364c 100644 --- a/cpp/Brewfile +++ b/cpp/Brewfile @@ -19,7 +19,9 @@ brew "aws-sdk-cpp" brew "bash" brew "boost" brew "brotli" +brew "bzip2" brew "c-ares" +brew "curl" brew "ccache" brew "cmake" brew "flatbuffers" @@ -29,14 +31,18 @@ brew "googletest" brew "grpc" brew "llvm@14" brew "lz4" +brew "mimalloc" brew "ninja" brew "node" brew "openssl@3" +brew "pkg-config" brew "protobuf" brew "python" brew "rapidjson" +brew "re2" brew "snappy" brew "thrift" +brew "utf8proc" brew "wget" brew "xsimd" brew "zstd" diff --git a/cpp/cmake_modules/SetupCxxFlags.cmake b/cpp/cmake_modules/SetupCxxFlags.cmake index 5531415ac2277..e90c00612caa3 100644 --- a/cpp/cmake_modules/SetupCxxFlags.cmake +++ b/cpp/cmake_modules/SetupCxxFlags.cmake @@ -456,11 +456,18 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STRE # Don't complain about optimization passes that were not possible set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -Wno-pass-failed") - # Avoid clang / libc++ error about C++17 aligned allocation on macOS. - # See https://chromium.googlesource.com/chromium/src/+/eee44569858fc650b635779c4e34be5cb0c73186%5E%21/#F0 - # for details. if(APPLE) - set(CXX_ONLY_FLAGS "${CXX_ONLY_FLAGS} -fno-aligned-new") + # Avoid clang / libc++ error about C++17 aligned allocation on macOS. + # See https://chromium.googlesource.com/chromium/src/+/eee44569858fc650b635779c4e34be5cb0c73186%5E%21/#F0 + # for details. + string(APPEND CXX_ONLY_FLAGS " -fno-aligned-new") + + if(CMAKE_HOST_SYSTEM_VERSION VERSION_LESS 20) + # Avoid C++17 std::get 'not available' issue on macOS 10.13 + # This will be required until atleast R 4.4 is released and + # CRAN (hopefully) stops checking on 10.13 + string(APPEND CXX_ONLY_FLAGS " -D_LIBCPP_DISABLE_AVAILABILITY") + endif() endif() endif() diff --git a/cpp/cmake_modules/ThirdpartyToolchain.cmake b/cpp/cmake_modules/ThirdpartyToolchain.cmake index 85c0337d108be..6d6a2bf7751ee 100644 --- a/cpp/cmake_modules/ThirdpartyToolchain.cmake +++ b/cpp/cmake_modules/ThirdpartyToolchain.cmake @@ -1308,6 +1308,26 @@ macro(build_snappy) set(SNAPPY_CMAKE_ARGS ${EP_COMMON_CMAKE_ARGS} -DSNAPPY_BUILD_TESTS=OFF -DSNAPPY_BUILD_BENCHMARKS=OFF "-DCMAKE_INSTALL_PREFIX=${SNAPPY_PREFIX}") + # Snappy unconditionaly enables Werror when building with clang this can lead + # to build failues by way of new compiler warnings. This adds a flag to disable + # Werror to the very end of the invocation to override the snappy internal setting. + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + foreach(CONFIG DEBUG MINSIZEREL RELEASE RELWITHDEBINFO) + list(APPEND + SNAPPY_CMAKE_ARGS + "-DCMAKE_CXX_FLAGS_${UPPERCASE_BUILD_TYPE}=${EP_CXX_FLAGS_${CONFIG}} -Wno-error" + ) + endforeach() + endif() + + if(APPLE AND CMAKE_HOST_SYSTEM_VERSION VERSION_LESS 20) + # On macOS 10.13 we need to explicitly add to avoid a missing include error + # This can be removed once CRAN no longer checks on macOS 10.13 + find_program(PATCH patch REQUIRED) + set(SNAPPY_PATCH_COMMAND ${PATCH} -p1 -i ${CMAKE_CURRENT_LIST_DIR}/snappy.diff) + else() + set(SNAPPY_PATCH_COMMAND) + endif() externalproject_add(snappy_ep ${EP_COMMON_OPTIONS} @@ -1315,6 +1335,7 @@ macro(build_snappy) INSTALL_DIR ${SNAPPY_PREFIX} URL ${SNAPPY_SOURCE_URL} URL_HASH "SHA256=${ARROW_SNAPPY_BUILD_SHA256_CHECKSUM}" + PATCH_COMMAND ${SNAPPY_PATCH_COMMAND} CMAKE_ARGS ${SNAPPY_CMAKE_ARGS} BUILD_BYPRODUCTS "${SNAPPY_STATIC_LIB}") diff --git a/cpp/cmake_modules/snappy.diff b/cpp/cmake_modules/snappy.diff new file mode 100644 index 0000000000000..f86e2bb19780c --- /dev/null +++ b/cpp/cmake_modules/snappy.diff @@ -0,0 +1,12 @@ +diff --git a/snappy.cc b/snappy.cc +index d414718..5b0d0d6 100644 +--- a/snappy.cc ++++ b/snappy.cc +@@ -83,6 +83,7 @@ + #include + #include + #include ++#include + + namespace snappy { + diff --git a/cpp/thirdparty/versions.txt b/cpp/thirdparty/versions.txt index 52d302592b55c..56163f35d2499 100644 --- a/cpp/thirdparty/versions.txt +++ b/cpp/thirdparty/versions.txt @@ -101,9 +101,8 @@ ARROW_RAPIDJSON_BUILD_VERSION=232389d4f1012dddec4ef84861face2d2ba85709 ARROW_RAPIDJSON_BUILD_SHA256_CHECKSUM=b9290a9a6d444c8e049bd589ab804e0ccf2b05dc5984a19ed5ae75d090064806 ARROW_RE2_BUILD_VERSION=2022-06-01 ARROW_RE2_BUILD_SHA256_CHECKSUM=f89c61410a072e5cbcf8c27e3a778da7d6fd2f2b5b1445cd4f4508bee946ab0f -# 1.1.9 is patched to implement https://github.com/google/snappy/pull/148 if this is bumped, remove the patch -ARROW_SNAPPY_BUILD_VERSION=1.1.9 -ARROW_SNAPPY_BUILD_SHA256_CHECKSUM=75c1fbb3d618dd3a0483bff0e26d0a92b495bbe5059c8b4f1c962b478b6e06e7 +ARROW_SNAPPY_BUILD_VERSION=1.1.10 +ARROW_SNAPPY_BUILD_SHA256_CHECKSUM=49d831bffcc5f3d01482340fe5af59852ca2fe76c3e05df0e67203ebbe0f1d90 ARROW_SUBSTRAIT_BUILD_VERSION=v0.27.0 ARROW_SUBSTRAIT_BUILD_SHA256_CHECKSUM=4ed375f69d972a57fdc5ec406c17003a111831d8640d3f1733eccd4b3ff45628 ARROW_S2N_TLS_BUILD_VERSION=v1.3.35 diff --git a/dev/release/rat_exclude_files.txt b/dev/release/rat_exclude_files.txt index aebe321d613ab..af084ea215621 100644 --- a/dev/release/rat_exclude_files.txt +++ b/dev/release/rat_exclude_files.txt @@ -24,6 +24,7 @@ cpp/build-support/iwyu/* cpp/cmake_modules/FindPythonLibsNew.cmake cpp/cmake_modules/SnappyCMakeLists.txt cpp/cmake_modules/SnappyConfig.h +cpp/cmake_modules/snappy.diff cpp/examples/parquet/parquet-arrow/cmake_modules/FindArrow.cmake cpp/src/parquet/.parquetcppversion cpp/src/generated/parquet_constants.cpp diff --git a/dev/tasks/macros.jinja b/dev/tasks/macros.jinja index faf77a1168d1b..54f676fd49cd9 100644 --- a/dev/tasks/macros.jinja +++ b/dev/tasks/macros.jinja @@ -307,7 +307,8 @@ on: stopifnot(packageVersion("arrow") == {{ '"${{needs.source.outputs.pkg_version}}"' }}) {% endmacro %} -{%- macro github_setup_local_r_repo(get_nix, get_win) -%} +{%- macro github_setup_local_r_repo(get_nix, get_win, get_mac=False) -%} +# TODO: improve arg handling - name: Setup local repo shell: bash run: mkdir repo @@ -327,6 +328,17 @@ on: path: repo/libarrow/bin/linux-openssl-{{ openssl_version }} {% endfor %} {% endif %} + {% if get_mac %} + {% for openssl_version in ["1.1", "3.0"] %} + {% for arch in ["x86_64", "arm64"] %} + - name: Get macOS {{ arch }} OpenSSL {{ openssl_version }} binary + uses: actions/download-artifact@v3 + with: + name: r-lib__libarrow__bin__darwin-{{arch}}-openssl-{{ openssl_version }} + path: repo/libarrow/bin/darwin-{{ arch }}-openssl-{{ openssl_version }} + {% endfor %} + {% endfor %} + {% endif %} - name: Get src pkg uses: actions/download-artifact@v3 with: diff --git a/dev/tasks/r/github.packages.yml b/dev/tasks/r/github.packages.yml index dbe21ffb6b160..760e3b6da448d 100644 --- a/dev/tasks/r/github.packages.yml +++ b/dev/tasks/r/github.packages.yml @@ -56,6 +56,59 @@ jobs: name: r-pkg__src__contrib path: arrow/r/arrow_*.tar.gz + macos-cpp: + name: C++ Binary macOS OpenSSL {{ '${{ matrix.openssl }}' }} {{ '${{ matrix.platform.arch }}' }} + + runs-on: {{ '${{ matrix.platform.runs_on }}' }} + + needs: source + strategy: + fail-fast: false + matrix: + platform: + - { runs_on: ["self-hosted", "macos-10.13"], arch: "x86_64" } + + - { runs_on: ["self-hosted", "macOS", "arm64", "devops-managed"], arch: "arm64" } + openssl: ['3.0', '1.1'] + + steps: + {{ macros.github_checkout_arrow(action_v="3")|indent }} + {{ macros.github_change_r_pkg_version(is_fork, '${{ needs.source.outputs.pkg_version }}')|indent }} + - name: Install Deps + if: {{ "${{ !contains(matrix.platform.runs_on, 'macos-10.13') }}" }} + run: | + brew install sccache ninja + brew install openssl@{{ '${{ matrix.openssl }}' }} + - name: Build libarrow + shell: bash + env: + {{ macros.github_set_sccache_envvars()|indent(8) }} + MACOSX_DEPLOYMENT_TARGET: "10.13" + ARROW_S3: ON + ARROW_GCS: ON + ARROW_DEPENDENCY_SOURCE: BUNDLED + CMAKE_GENERATOR: Ninja + LIBARROW_MINIMAL: false + run: | + sccache --start-server + export EXTRA_CMAKE_FLAGS="-DOPENSSL_ROOT_DIR=$(brew --prefix openssl@{{ '${{ matrix.openssl }}' }})" + cd arrow + r/inst/build_arrow_static.sh + - name: Bundle libarrow + shell: bash + env: + PKG_FILE: arrow-{{ '${{ needs.source.outputs.pkg_version }}' }}.zip + VERSION: {{ '${{ needs.source.outputs.pkg_version }}' }} + run: | + cd arrow/r/libarrow/dist + zip -r $PKG_FILE lib/ include/ + + - name: Upload binary artifact + uses: actions/upload-artifact@v3 + with: + name: r-lib__libarrow__bin__darwin-{{ '${{ matrix.platform.arch }}' }}-openssl-{{ '${{ matrix.openssl }}' }} + path: arrow/r/libarrow/dist/arrow-*.zip + linux-cpp: name: C++ Binary Linux OpenSSL {{ '${{ matrix.openssl }}' }} runs-on: ubuntu-latest @@ -135,7 +188,7 @@ jobs: path: build/arrow-*.zip r-packages: - needs: [source, windows-cpp] + needs: [source, windows-cpp, macos-cpp] name: {{ '${{ matrix.platform.name }} ${{ matrix.r_version.r }}' }} runs-on: {{ '${{ matrix.platform.runs_on }}' }} strategy: @@ -167,7 +220,7 @@ jobs: rig system setup-user-lib rig system add-pak - {{ macros.github_setup_local_r_repo(false, true)|indent }} + {{ macros.github_setup_local_r_repo(false, true, true)|indent }} - name: Prepare Dependency Installation shell: bash @@ -178,18 +231,19 @@ jobs: with: working-directory: 'arrow' extra-packages: cpp11 - - name: Install sccache - if: startsWith(matrix.platform, 'macos') - run: brew install sccache + - name: Set CRAN like openssl + if: contains(matrix.platform.runs_on, 'arm64') + run: | + # The arm64 runners contain openssl 1.1.1t in this path that is always included first so we need to override the + # default setting of the brew --prefix as root dir to avoid version conflicts. + echo "OPENSSL_ROOT_DIR=/opt/R/arm64" >> $GITHUB_ENV - name: Build Binary id: build shell: Rscript {0} env: - NOT_CRAN: "true" # actions/setup-r sets this implicitly + NOT_CRAN: "false" # actions/setup-r sets this implicitly ARROW_R_DEV: "true" - FORCE_AUTOBREW: "true" # this is ignored on windows - # sccache for macos - {{ macros.github_set_sccache_envvars()|indent(8) }} + LIBARROW_BINARY: "true" # has to be set as long as allowlist not updated run: | on_windows <- tolower(Sys.info()[["sysname"]]) == "windows" @@ -213,8 +267,10 @@ jobs: INSTALL_opts = INSTALL_opts ) + # Test library(arrow) + arrow_info() read_parquet(system.file("v0.7.1.parquet", package = "arrow")) # encode contrib.url for artifact name @@ -233,7 +289,6 @@ jobs: with: name: r-pkg{{ '${{ steps.build.outputs.path }}' }} path: arrow_* - test-linux-binary: needs: [source, linux-cpp] name: Test binary {{ '${{ matrix.config.image }}' }} @@ -291,7 +346,10 @@ jobs: with: name: r-pkg_centos7 path: arrow_* + test-centos-binary: + # arrow binary package not on ppm currently see #37922 + if: false needs: test-linux-binary runs-on: ubuntu-latest container: "rstudio/r-base:4.2-centos7" @@ -317,7 +375,8 @@ jobs: read_parquet(system.file("v0.7.1.parquet", package = "arrow")) print(arrow_info()) - test-source: + #TODO test macos source build? + test-linux-source: needs: source name: Test linux source build runs-on: ubuntu-latest @@ -367,7 +426,7 @@ jobs: upload-binaries: # Only upload binaries if all tests pass. - needs: [r-packages, test-source, test-linux-binary, test-centos-binary] + needs: [r-packages, test-linux-source, test-linux-binary] name: Upload artifacts runs-on: ubuntu-latest steps: diff --git a/dev/tasks/tasks.yml b/dev/tasks/tasks.yml index 859ff8ddb5b44..798932db23323 100644 --- a/dev/tasks/tasks.yml +++ b/dev/tasks/tasks.yml @@ -994,6 +994,10 @@ tasks: - r-lib__libarrow__bin__linux-openssl-1.0__arrow-{no_rc_r_version}\.zip - r-lib__libarrow__bin__linux-openssl-1.1__arrow-{no_rc_r_version}\.zip - r-lib__libarrow__bin__linux-openssl-3.0__arrow-{no_rc_r_version}\.zip + - r-lib__libarrow__bin__darwin-arm64-openssl-1.1__arrow-{no_rc_r_version}\.zip + - r-lib__libarrow__bin__darwin-arm64-openssl-3.0__arrow-{no_rc_r_version}\.zip + - r-lib__libarrow__bin__darwin-x86_64-openssl-1.1__arrow-{no_rc_r_version}\.zip + - r-lib__libarrow__bin__darwin-x86_64-openssl-3.0__arrow-{no_rc_r_version}\.zip - r-pkg__bin__windows__contrib__4.1__arrow_{no_rc_r_version}\.zip - r-pkg__bin__windows__contrib__4.2__arrow_{no_rc_r_version}\.zip - r-pkg__bin__macosx__contrib__4.1__arrow_{no_rc_r_version}\.tgz diff --git a/r/configure b/r/configure index 593f60bbddad9..d244b1a7c148f 100755 --- a/r/configure +++ b/r/configure @@ -39,8 +39,8 @@ # # * Installing a released version from source, as from CRAN, with # no other prior setup -# * On macOS, autobrew is used to retrieve libarrow and dependencies -# * On Linux, the nixlibs.R build script will download or build +# * On macOS and Linux, the nixlibs.R build script will download +# or build libarrow and dependencies # * Installing a released version but first installing libarrow. # It will use pkg-config and brew to search for libraries. # * Installing a development version from source as a user. @@ -65,8 +65,6 @@ PKG_TEST_HEADER="" # Some env vars that control the build (all logical, case insensitive) # Development mode, also increases verbosity in the bundled build ARROW_R_DEV=`echo $ARROW_R_DEV | tr '[:upper:]' '[:lower:]'` -# autobrew is how mac binaries are built on CRAN; FORCE ensures we use it here -FORCE_AUTOBREW=`echo $FORCE_AUTOBREW | tr '[:upper:]' '[:lower:]'` # The bundled build compiles arrow C++ from source; FORCE ensures we don't pick up # any other packages that may be found on the system FORCE_BUNDLED_BUILD=`echo $FORCE_BUNDLED_BUILD | tr '[:upper:]' '[:lower:]'` @@ -141,19 +139,11 @@ fi find_or_build_libarrow () { if [ "$FORCE_BUNDLED_BUILD" = "true" ]; then do_bundled_build - elif [ "$FORCE_AUTOBREW" = "true" ]; then - do_autobrew else find_arrow if [ "$_LIBARROW_FOUND" = "false" ]; then # If we haven't found a suitable version of libarrow, build it - if [ "$UNAME" = "Darwin" ] && ! echo $VERSION | grep -q "000"; then - # Only autobrew on release version (for testing, use FORCE_AUTOBREW above) - # (dev versions end in .9000, and nightly gets something like .10000xxx) - do_autobrew - else - do_bundled_build - fi + do_bundled_build fi fi } @@ -175,12 +165,6 @@ find_arrow () { # 2. Use pkg-config to find arrow on the system _LIBARROW_FOUND="`${PKG_CONFIG} --variable=prefix --silence-errors ${PKG_CONFIG_NAME}`" echo "*** Trying Arrow C++ found by pkg-config: $_LIBARROW_FOUND" - elif brew --prefix ${PKG_BREW_NAME} > /dev/null 2>&1; then - # 3. On macOS, look for Homebrew apache-arrow - # (note that if you have pkg-config, homebrew arrow may have already been found) - _LIBARROW_FOUND=`brew --prefix ${PKG_BREW_NAME}` - echo "*** Trying Arrow C++ found by Homebrew: ${_LIBARROW_FOUND}" - export PKG_CONFIG_PATH="${_LIBARROW_FOUND}/lib/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}}" else _LIBARROW_FOUND="false" fi @@ -247,34 +231,6 @@ do_bundled_build () { fi } -do_autobrew () { - echo "*** Downloading ${PKG_BREW_NAME}" - - # Setup for local autobrew testing - if [ -f "tools/apache-arrow.rb" ]; then - # If you want to use a local apache-arrow.rb formula, do - # $ cp ../dev/tasks/homebrew-formulae/autobrew/apache-arrow*.rb tools - # before R CMD build or INSTALL (assuming a local checkout of the apache/arrow repository). - # If you have this, you should use the local autobrew script so they match. - cp tools/autobrew . - fi - - if [ -f "autobrew" ]; then - echo "**** Using local manifest for ${PKG_BREW_NAME}" - else - if ! curl -sfL "https://autobrew.github.io/scripts/$PKG_BREW_NAME" > autobrew; then - echo "Failed to download manifest for ${PKG_BREW_NAME}" - # Fall back to the local copy - cp tools/autobrew . - fi - fi - if ! . autobrew; then - echo "Failed to retrieve binary for ${PKG_BREW_NAME}" - fi - # autobrew sets `PKG_LIBS`, `PKG_DIRS`, and `PKG_CFLAGS` - # TODO: move PKG_LIBS and PKG_CFLAGS out of autobrew and use set_pkg_vars -} - # Once libarrow is obtained, this function sets `PKG_LIBS`, `PKG_DIRS`, and `PKG_CFLAGS` # either from pkg-config or by inferring things about the directory in $1 set_pkg_vars () { @@ -298,6 +254,11 @@ set_pkg_vars () { if [ "$ARROW_R_CXXFLAGS" ]; then PKG_CFLAGS="$PKG_CFLAGS $ARROW_R_CXXFLAGS" fi + + if [ "$UNAME" = "Darwin" ] && expr $(sw_vers -productVersion) : '10\.13'; then + # avoid C++17 availability warnings on macOS < 11 + PKG_CFLAGS="$PKG_CFLAGS -D_LIBCPP_DISABLE_AVAILABILITY" + fi } # If we have pkg-config, it will tell us what libarrow needs diff --git a/r/tools/nixlibs-allowlist.txt b/r/tools/nixlibs-allowlist.txt index bd9f0c1b2c084..9c368e6ed15a2 100644 --- a/r/tools/nixlibs-allowlist.txt +++ b/r/tools/nixlibs-allowlist.txt @@ -2,3 +2,4 @@ ubuntu centos redhat rhel +darwin diff --git a/r/tools/nixlibs.R b/r/tools/nixlibs.R index 3d908c05cab07..60deca05cd172 100644 --- a/r/tools/nixlibs.R +++ b/r/tools/nixlibs.R @@ -28,6 +28,8 @@ if (test_mode && is.na(VERSION)) { } dev_version <- package_version(VERSION)[1, 4] +on_macos <- tolower(Sys.info()[["sysname"]]) == "darwin" + # Small dev versions are added for R-only changes during CRAN submission. if (is.na(dev_version) || dev_version < "100") { @@ -94,8 +96,10 @@ download_binary <- function(lib) { } } else { if (!quietly) { - cat(sprintf("*** Downloading libarrow binary failed for version %s (%s)\n at %s\n", - VERSION, lib, binary_url)) + cat(sprintf( + "*** Downloading libarrow binary failed for version %s (%s)\n at %s\n", + VERSION, lib, binary_url + )) } libfile <- NULL } @@ -114,6 +118,10 @@ download_binary <- function(lib) { # * "linux-openssl-1.0" (OpenSSL 1.0) # * "linux-openssl-1.1" (OpenSSL 1.1) # * "linux-openssl-3.0" (OpenSSL 3.0) +# * "macos-amd64-openssl-1.1" (OpenSSL 1.1) +# * "macos-amd64-openssl-3.0" (OpenSSL 3.0) +# * "macos-arm64-openssl-1.1" (OpenSSL 1.1) +# * "macos-arm64-openssl-3.0" (OpenSSL 3.0) # These string values, along with `NULL`, are the potential return values of # this function. identify_binary <- function(lib = Sys.getenv("LIBARROW_BINARY"), info = distro()) { @@ -142,7 +150,7 @@ check_allowlist <- function(os, allowed = "https://raw.githubusercontent.com/apa # Try a remote allowlist so that we can add/remove without a release suppressWarnings(readLines(allowed)), # Fallback to default: allowed only on Ubuntu and CentOS/RHEL - error = function(e) c("ubuntu", "centos", "redhat", "rhel") + error = function(e) c("ubuntu", "centos", "redhat", "rhel", "darwin") ) # allowlist should contain valid regular expressions (plain strings ok too) any(grepl(paste(allowlist, collapse = "|"), os)) @@ -151,14 +159,16 @@ check_allowlist <- function(os, allowed = "https://raw.githubusercontent.com/apa select_binary <- function(os = tolower(Sys.info()[["sysname"]]), arch = tolower(Sys.info()[["machine"]]), test_program = test_for_curl_and_openssl) { - if (identical(os, "linux") && identical(arch, "x86_64")) { - # We only host x86 linux binaries today - tryCatch( + if (identical(os, "darwin") || (identical(os, "linux") && identical(arch, "x86_64"))) { + # We only host x86 linux binaries and x86 & arm64 macos today + binary <- tryCatch( # Somehow the test program system2 call errors on the sanitizer builds # so globally handle the possibility that this could fail { errs <- compile_test_program(test_program) - determine_binary_from_stderr(errs) + openssl_version <- determine_binary_from_stderr(errs) + arch <- ifelse(identical(os, "darwin"), paste0("-", arch, "-"), "-") + ifelse(is.null(openssl_version), NULL, paste0(os, arch, openssl_version)) }, error = function(e) { cat("*** Unable to find libcurl and openssl\n") @@ -168,17 +178,20 @@ select_binary <- function(os = tolower(Sys.info()[["sysname"]]), } else { # No binary available for arch cat(sprintf("*** Building on %s %s\n", os, arch)) - NULL + binary <- NULL } + return(binary) } # This tests that curl and OpenSSL are present (bc we can include their headers) # and it checks for other versions/features and raises errors that we grep for test_for_curl_and_openssl <- " +#ifndef __APPLE__ #include #ifdef _LIBCPP_VERSION #error Using libc++ #endif +#endif #include #include @@ -194,11 +207,14 @@ test_for_curl_and_openssl <- " " compile_test_program <- function(code) { - # Note: if we wanted to check for openssl on macOS, we'd have to set the brew - # path as a -I directory. But since we (currently) only run this code to - # determine whether we can download a Linux binary, it's not relevant. + openssl_dir <- "" + if (on_macos) { + openssl_root_dir <- get_macos_openssl_dir() + openssl_dir <- paste0("-I", openssl_root_dir, "/include") + } runner <- paste( R_CMD_config("CXX17"), + openssl_dir, R_CMD_config("CPPFLAGS"), R_CMD_config("CXX17FLAGS"), R_CMD_config("CXX17STD"), @@ -208,17 +224,34 @@ compile_test_program <- function(code) { suppressWarnings(system2("echo", sprintf('"%s" | %s -', code, runner), stdout = FALSE, stderr = TRUE)) } +get_macos_openssl_dir <- function() { + openssl_root_dir <- Sys.getenv("OPENSSL_ROOT_DIR", NA) + header <- "openssl/opensslv.h" + if (is.na(openssl_root_dir) || !file.exists(file.path(openssl_root_dir, "include", header))) { + # try to guess default openssl include dir based on CRAN's build script + # https://github.com/R-macos/recipes/blob/master/build.sh#L35 + if (identical(Sys.info()["machine"], "arm64") && file.exists(file.path("/opt/R/arm64/include", header))) { + openssl_root_dir <- "/opt/R/arm64" + } else if (identical(Sys.info()["machine"], "x86_64") && file.exists(file.path("/opt/R/x86_64/include", header))) { + openssl_root_dir <- "/opt/R/x86_64" + } else { + openssl_root_dir <- "/usr/local" + } + } + return(openssl_root_dir) +} + # (built with newer devtoolset but older glibc (2.17) for broader compatibility,# like manylinux2014) determine_binary_from_stderr <- function(errs) { if (is.null(attr(errs, "status"))) { # There was no error in compiling: so we found libcurl and OpenSSL >= 1.1, # openssl is < 3.0 cat("*** Found libcurl and OpenSSL >= 1.1\n") - return("linux-openssl-1.1") + return("openssl-1.1") # Else, check for dealbreakers: - } else if (any(grepl("Using libc++", errs, fixed = TRUE))) { - # Our binaries are all built with GNU stdlib so they fail with libc++ - cat("*** Found libc++\n") + } else if (!on_macos && any(grepl("Using libc++", errs, fixed = TRUE))) { + # Our linux binaries are all built with GNU stdlib so they fail with libc++ + cat("*** Linux binaries incompatible with libc++\n") return(NULL) } else if (header_not_found("curl/curl", errs)) { cat("*** libcurl not found\n") @@ -231,11 +264,15 @@ determine_binary_from_stderr <- function(errs) { return(NULL) # Else, determine which other binary will work } else if (any(grepl("Using OpenSSL version 1.0", errs))) { + if (on_macos) { + cat("*** OpenSSL 1.0 is not supported on macOS\n") + return(NULL) + } cat("*** Found libcurl and OpenSSL < 1.1\n") - return("linux-openssl-1.0") + return("openssl-1.0") } else if (any(grepl("Using OpenSSL version 3", errs))) { cat("*** Found libcurl and OpenSSL >= 3.0.0\n") - return("linux-openssl-3.0") + return("openssl-3.0") } NULL } @@ -248,6 +285,11 @@ header_not_found <- function(header, errs) { #### start distro #### distro <- function() { + # This is not part of distro but needed to enable prebuilt binaries on macos + if (on_macos) { + return(list(id = "darwin", arch = tolower(Sys.info()[["machine"]]))) + } + # The code in this script is a (potentially stale) copy of the distro package if (requireNamespace("distro", quietly = TRUE)) { # Use the version from the package, which may be updated from this @@ -487,8 +529,10 @@ build_libarrow <- function(src_dir, dst_dir) { # It failed :( cat("**** Error building Arrow C++.", "\n") if (quietly) { - cat("**** Printing contents of build log because the build failed", - "while ARROW_R_DEV was set to FALSE\n") + cat( + "**** Printing contents of build log because the build failed", + "while ARROW_R_DEV was set to FALSE\n" + ) cat(readLines(build_log_path), sep = "\n") cat("**** Complete build log may still be present at", build_log_path, "\n") } @@ -503,7 +547,7 @@ ensure_cmake <- function(cmake_minimum_required = "3.16") { # If not found, download it cat("**** cmake\n") CMAKE_VERSION <- Sys.getenv("CMAKE_VERSION", "3.26.4") - if (tolower(Sys.info()[["sysname"]]) %in% "darwin") { + if (on_macos) { postfix <- "-macos-universal.tar.gz" } else if (tolower(Sys.info()[["machine"]]) %in% c("arm64", "aarch64")) { postfix <- "-linux-aarch64.tar.gz" diff --git a/r/tools/test-nixlibs.R b/r/tools/test-nixlibs.R index e099dcdad4acf..c9571b58b7bbf 100644 --- a/r/tools/test-nixlibs.R +++ b/r/tools/test-nixlibs.R @@ -21,8 +21,10 @@ # Flag so that we just load the functions and don't evaluate them like we do # when called from configure.R TESTING <- TRUE - -source("nixlibs.R", local = TRUE) +# The functions use `on_macos` from the env they were sourced in, so we need tool +# explicitly set it in that environment. +nixlibs_env <- environment() +source("nixlibs.R", local = nixlibs_env) test_that("identify_binary() based on LIBARROW_BINARY", { expect_null(identify_binary("FALSE")) @@ -31,10 +33,6 @@ test_that("identify_binary() based on LIBARROW_BINARY", { }) test_that("select_binary() based on system", { - expect_output( - expect_null(select_binary("darwin", "x86_64")), # Not built today - "Building on darwin x86_64" - ) expect_output( expect_null(select_binary("linux", arch = "aarch64")), # Not built today "Building on linux aarch64" @@ -52,21 +50,30 @@ test_that("determine_binary_from_stderr", { expect_output( expect_identical( determine_binary_from_stderr(compile_test_program("int a;")), - "linux-openssl-1.1" + "openssl-1.1" ), "Found libcurl and OpenSSL >= 1.1" ) + + nixlibs_env$on_macos <- FALSE expect_output( expect_identical( determine_binary_from_stderr(compile_test_program("#error Using OpenSSL version 1.0")), - "linux-openssl-1.0" + "openssl-1.0" ), "Found libcurl and OpenSSL < 1.1" ) + nixlibs_env$on_macos <- TRUE + expect_output( + expect_null( + determine_binary_from_stderr(compile_test_program("#error Using OpenSSL version 1.0")) + ), + "OpenSSL 1.0 is not supported on macOS" + ) expect_output( expect_identical( determine_binary_from_stderr(compile_test_program("#error Using OpenSSL version 3")), - "linux-openssl-3.0" + "openssl-3.0" ), "Found libcurl and OpenSSL >= 3.0.0" ) @@ -79,6 +86,7 @@ test_that("determine_binary_from_stderr", { }) test_that("select_binary() with test program", { + nixlibs_env$on_macos <- FALSE expect_output( expect_identical( select_binary("linux", "x86_64", "int a;"), @@ -100,13 +108,49 @@ test_that("select_binary() with test program", { ), "Found libcurl and OpenSSL >= 3.0.0" ) + nixlibs_env$on_macos <- TRUE + expect_output( + expect_identical( + select_binary("darwin", "x86_64", "int a;"), + "darwin-x86_64-openssl-1.1" + ), + "Found libcurl and OpenSSL >= 1.1" + ) + expect_output( + expect_identical( + select_binary("darwin", "x86_64", "#error Using OpenSSL version 3"), + "darwin-x86_64-openssl-3.0" + ), + "Found libcurl and OpenSSL >= 3.0.0" + ) + expect_output( + expect_identical( + select_binary("darwin", "arm64", "int a;"), + "darwin-arm64-openssl-1.1" + ), + "Found libcurl and OpenSSL >= 1.1" + ) + expect_output( + expect_identical( + select_binary("darwin", "arm64", "#error Using OpenSSL version 3"), + "darwin-arm64-openssl-3.0" + ), + "Found libcurl and OpenSSL >= 3.0.0" + ) + expect_output( + expect_null( + select_binary("darwin", "x86_64", "#error Using OpenSSL version 1.0") + ), + "OpenSSL 1.0 is not supported on macOS" + ) }) test_that("check_allowlist", { tf <- tempfile() - cat("tu$\n^cent\n", file = tf) + cat("tu$\n^cent\n^dar\n", file = tf) expect_true(check_allowlist("ubuntu", tf)) expect_true(check_allowlist("centos", tf)) + expect_true(check_allowlist("darwin", tf)) expect_false(check_allowlist("redhat", tf)) # remote allowlist doesn't have this expect_true(check_allowlist("redhat", tempfile())) # remote allowlist doesn't exist, so we fall back to the default list, which contains redhat expect_false(check_allowlist("debian", tempfile())) From f7530de9fe20f8a3731b465af07a79a56640fe79 Mon Sep 17 00:00:00 2001 From: Matt Topol Date: Thu, 5 Oct 2023 10:26:13 -0400 Subject: [PATCH 50/56] GH-37712: [Go][Parquet] Fix ARM64 assembly for bitmap extract bits (#37785) ### Rationale for this change The linked issue discovered a problem with the ARM64 implementation of the extractBits functionality which was being hidden because until `go1.21`, it looks like `golang.org/x/sys/cpu` wasn't properly detecting the ASIMD bit flag on the ARM processors and so it was using the pure go implementation. So we fix the assembly and add a test which was able to reproduce the failure without the fix on an ARM64 machine. ### What changes are included in this PR? There was a problem with the assembly as it existed as the short circuit case where the selection bitmap is 0 wasn't actually setting the 0 value back onto the stack as a return. The assembly which initialized that register to 0 only occurred AFTER the `CBZ` instruction which would jump to the bottom and return. This means that we *actually* returned whatever happened to be on the stack at that location (i.e. garbage!). This only occurred if you were using the ARM64-specific assembly implementation, not the amd64 or pure go versions. We also include a test to ensure we get the correct values for a variety of bitmaps and selections, along with this ensuring there's enough data on the stack so that if this problem re-occured we would catch it in this test. ### Are these changes tested? Test is added. * Closes: #37712 Lead-authored-by: Matt Topol Co-authored-by: Antoine Pitrou Signed-off-by: Matt Topol --- go/parquet/internal/bmi/_lib/bitmap_bmi2.c | 6 + go/parquet/internal/bmi/_lib/bitmap_neon.s | 32 - go/parquet/internal/bmi/bitmap_neon_arm64.go | 10 +- go/parquet/internal/bmi/bitmap_neon_arm64.s | 30 - go/parquet/internal/bmi/bmi_arm64.go | 49 +- go/parquet/internal/bmi/bmi_test.go | 47 + go/parquet/internal/utils/Makefile | 18 +- go/parquet/internal/utils/_lib/README.md | 154 + .../internal/utils/_lib/bit_packing_neon.c | 28 +- go/parquet/internal/utils/_lib/script.sed | 22 + .../internal/utils/bit_packing_arm64.go | 29 +- .../internal/utils/bit_packing_neon_arm64.s | 10229 +++++++++++----- go/parquet/internal/utils/clib_amd64.s | 18 + 13 files changed, 7209 insertions(+), 3463 deletions(-) create mode 100644 go/parquet/internal/bmi/bmi_test.go create mode 100644 go/parquet/internal/utils/_lib/README.md create mode 100644 go/parquet/internal/utils/_lib/script.sed mode change 100755 => 100644 go/parquet/internal/utils/bit_packing_neon_arm64.s diff --git a/go/parquet/internal/bmi/_lib/bitmap_bmi2.c b/go/parquet/internal/bmi/_lib/bitmap_bmi2.c index cc345d5798b8c..a020294fd6a38 100644 --- a/go/parquet/internal/bmi/_lib/bitmap_bmi2.c +++ b/go/parquet/internal/bmi/_lib/bitmap_bmi2.c @@ -17,6 +17,10 @@ #include #include +#if !defined(__ARM_NEON) && !defined(__ARM_NEON__) +// don't compile this for ARM, the pure go lookup table version +// is more performant anyways since ARM doesn't have a BMI2/pext_u64 +// instruction we can call directly. uint64_t FULL_NAME(extract_bits)(uint64_t bitmap, uint64_t select_bitmap) { #if defined(__BMI2__) return (uint64_t)(_pext_u64(bitmap, select_bitmap)); @@ -32,6 +36,8 @@ uint64_t FULL_NAME(extract_bits)(uint64_t bitmap, uint64_t select_bitmap) { #endif } +#endif + uint64_t FULL_NAME(levels_to_bitmap)(const int16_t* levels, const int num_levels, const int16_t rhs) { uint64_t mask = 0; for (int x = 0; x < num_levels; x++) { diff --git a/go/parquet/internal/bmi/_lib/bitmap_neon.s b/go/parquet/internal/bmi/_lib/bitmap_neon.s index f6d4e751be63a..d1d146f55cfab 100644 --- a/go/parquet/internal/bmi/_lib/bitmap_neon.s +++ b/go/parquet/internal/bmi/_lib/bitmap_neon.s @@ -1,37 +1,5 @@ .text .file "bitmap_bmi2.c" - .globl extract_bits_neon // -- Begin function extract_bits_neon - .p2align 2 - .type extract_bits_neon,@function -extract_bits_neon: // @extract_bits_neon -// %bb.0: - stp x29, x30, [sp, #-16]! // 16-byte Folded Spill - mov x29, sp - cbz x1, .LBB0_4 -// %bb.1: - mov x8, x0 - mov x0, xzr - mov w9, #1 -.LBB0_2: // =>This Inner Loop Header: Depth=1 - and x10, x1, x8 - neg x11, x1 - tst x10, x11 - sub x12, x1, #1 // =1 - csel x10, xzr, x9, eq - ands x1, x12, x1 - orr x0, x10, x0 - lsl x9, x9, #1 - b.ne .LBB0_2 -// %bb.3: - ldp x29, x30, [sp], #16 // 16-byte Folded Reload - ret -.LBB0_4: - mov x0, xzr - ldp x29, x30, [sp], #16 // 16-byte Folded Reload - ret -.Lfunc_end0: - .size extract_bits_neon, .Lfunc_end0-extract_bits_neon - // -- End function .section .rodata.cst16,"aM",@progbits,16 .p2align 4 // -- Begin function levels_to_bitmap_neon .LCPI1_0: diff --git a/go/parquet/internal/bmi/bitmap_neon_arm64.go b/go/parquet/internal/bmi/bitmap_neon_arm64.go index b3b0b093734be..65471d35288c3 100755 --- a/go/parquet/internal/bmi/bitmap_neon_arm64.go +++ b/go/parquet/internal/bmi/bitmap_neon_arm64.go @@ -14,21 +14,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !noasm // +build !noasm package bmi import "unsafe" -//go:noescape -func _extract_bits_neon(bitmap, selectBitmap uint64) (res uint64) - -// There is no single instruction similar with 'pext' on Arm64. -// The equivalent of 'pext' was implemented with Arm64 Neon for Parallel Bits Extract -func extractBitsNEON(bitmap, selectBitmap uint64) uint64 { - return _extract_bits_neon(bitmap, selectBitmap) -} - //go:noescape func _levels_to_bitmap_neon(levels unsafe.Pointer, numLevels int, rhs int16) (res uint64) diff --git a/go/parquet/internal/bmi/bitmap_neon_arm64.s b/go/parquet/internal/bmi/bitmap_neon_arm64.s index 019aaef5d99b8..abde5843c68e2 100755 --- a/go/parquet/internal/bmi/bitmap_neon_arm64.s +++ b/go/parquet/internal/bmi/bitmap_neon_arm64.s @@ -1,36 +1,6 @@ //+build !noasm !appengine // (C2GOASM doesn't work correctly for Arm64) -// func _extract_bits_neon(bitmap, selectBitmap uint64) (res uint64) -TEXT ·_extract_bits_neon(SB), $0-24 - - MOVD bitmap+0(FP), R0 - MOVD selectBitmap+8(FP), R1 - - WORD $0xa9bf7bfd // stp x29, x30, [sp, #-16]! - WORD $0x910003fd // mov x29, sp - CBZ R1, LBB0_4 - WORD $0xaa0003e8 // mov x8, x0 - WORD $0xaa1f03e0 // mov x0, xzr - WORD $0x52800029 // mov w9, #1 -LBB0_2: - WORD $0x8a08002a // and x10, x1, x8 - WORD $0xcb0103eb // neg x11, x1 - WORD $0xea0b015f // tst x10, x11 - WORD $0xd100042c // sub x12, x1, #1 - WORD $0x9a8903ea // csel x10, xzr, x9, eq - WORD $0xea010181 // ands x1, x12, x1 - WORD $0xaa000140 // orr x0, x10, x0 - WORD $0xd37ff929 // lsl x9, x9, #1 - BNE LBB0_2 - WORD $0xa8c17bfd // ldp x29, x30, [sp], #16 - MOVD R0, res+16(FP) - RET -LBB0_4: - WORD $0xaa1f03e0 // mov x0, xzr - WORD $0xa8c17bfd // ldp x29, x30, [sp], #16 - RET - // func _levels_to_bitmap_neon(levels unsafe.Pointer, numLevels int, rhs int16) (res uint64) TEXT ·_levels_to_bitmap_neon(SB), $0-32 diff --git a/go/parquet/internal/bmi/bmi_arm64.go b/go/parquet/internal/bmi/bmi_arm64.go index a436fadf72651..4174f6d06d989 100755 --- a/go/parquet/internal/bmi/bmi_arm64.go +++ b/go/parquet/internal/bmi/bmi_arm64.go @@ -14,44 +14,51 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !noasm // +build !noasm package bmi import ( + "fmt" "os" "strings" -) -import ( - "golang.org/x/sys/cpu" + + "github.com/klauspost/cpuid/v2" ) func init() { - // Added ability to enable extension via environment: + // Added ability to enable extension via environment: // ARM_ENABLE_EXT=NEON go test if ext, ok := os.LookupEnv("ARM_ENABLE_EXT"); ok { - exts := strings.Split(ext, ",") - - for _, x := range exts { - switch x { - case "NEON": - cpu.ARM64.HasASIMD = true - case "AES": - cpu.ARM64.HasAES = true - case "PMULL": - cpu.ARM64.HasPMULL = true - default: - cpu.ARM64.HasASIMD = false - cpu.ARM64.HasAES = false - cpu.ARM64.HasPMULL = false + if ext == "DISABLE" { + cpuid.CPU.Disable(cpuid.ASIMD, cpuid.AESARM, cpuid.PMULL) + } else { + exts := strings.Split(ext, ",") + + for _, x := range exts { + switch x { + case "NEON": + cpuid.CPU.Enable(cpuid.ASIMD) + case "AES": + cpuid.CPU.Enable(cpuid.AESARM) + case "PMULL": + cpuid.CPU.Enable(cpuid.PMULL) + default: + fmt.Fprintln(os.Stderr, "unrecognized value for ARM_ENABLE_EXT:", x) + } } } } - if cpu.ARM64.HasASIMD { - funclist.extractBits = extractBitsNEON + + // after benchmarking, turns out the pure go lookup table version + // is nearly twice as fast as the non-lookup table assembly + // because arm doesn't have a PEXT instruction. + funclist.extractBits = extractBitsGo + + if cpuid.CPU.Has(cpuid.ASIMD) { funclist.gtbitmap = greaterThanBitmapNEON } else { - funclist.extractBits = extractBitsGo funclist.gtbitmap = greaterThanBitmapGo } } diff --git a/go/parquet/internal/bmi/bmi_test.go b/go/parquet/internal/bmi/bmi_test.go new file mode 100644 index 0000000000000..460c6ec4e24c6 --- /dev/null +++ b/go/parquet/internal/bmi/bmi_test.go @@ -0,0 +1,47 @@ +// 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. + +package bmi_test + +import ( + "fmt" + "testing" + + "github.com/apache/arrow/go/v14/parquet/internal/bmi" + "github.com/stretchr/testify/assert" +) + +// Testing the issue in GH-37712 +func TestBasicExtractBits(t *testing.T) { + tests := []struct { + bitmap, selection uint64 + expected uint64 + }{ + {0, 0, 0}, + {0xFF, 0, 0}, + {0xFF, ^uint64(0), 0xFF}, + {0xFF00FF, 0xAAAA, 0x000F}, + {0xFF0AFF, 0xAFAA, 0x00AF}, + {0xFFAAFF, 0xAFAA, 0x03AF}, + {0xFECBDA9876543210, 0xF00FF00FF00FF00F, 0xFBD87430}, + } + + for _, tt := range tests { + t.Run(fmt.Sprintf("%d-%d=>%d", tt.bitmap, tt.selection, tt.expected), func(t *testing.T) { + assert.Equal(t, tt.expected, bmi.ExtractBits(tt.bitmap, tt.selection)) + }) + } +} diff --git a/go/parquet/internal/utils/Makefile b/go/parquet/internal/utils/Makefile index 58643223876ea..f6dce46197fef 100644 --- a/go/parquet/internal/utils/Makefile +++ b/go/parquet/internal/utils/Makefile @@ -32,11 +32,14 @@ C_FLAGS_NEON=-O3 -fvectorize -mllvm -force-vector-width=16 -fno-asynchronous-unw GO_SOURCES := $(shell find . -path ./_lib -prune -o -name '*.go' -not -name '*_test.go') ALL_SOURCES := $(shell find . -path ./_lib -prune -o -name '*.go' -name '*.s' -not -name '*_test.go') -.PHONEY: assembly +.PHONY: assembly INTEL_SOURCES := \ - bit_packing_avx2.s \ - unpack_bool_avx2.s unpack_bool_sse4.s + bit_packing_avx2_amd64.s \ + unpack_bool_avx2_amd64.s unpack_bool_sse4_amd64.s + +ARM_SOURCES := \ + bit_packing_neon_arm64.s unpack_bool_neon_arm64.s # # ARROW-15336: DO NOT add the assembly target for Arm64 (ARM_SOURCES) until c2goasm added the Arm64 support. @@ -58,13 +61,16 @@ _lib/unpack_bool_sse4.s: _lib/unpack_bool.c _lib/unpack_bool_neon.s: _lib/unpack_bool.c $(CC) -S $(C_FLAGS_NEON) $^ -o $@ ; $(PERL_FIXUP_ROTATE) $@ -bit_packing_avx2.s: _lib/bit_packing_avx2.s +_lib/bit_packing_neon.s: _lib/bit_packing_neon.c + $(CC) -S $(C_FLAGS_NEON) $^ -o $@ + +bit_packing_avx2_amd64.s: _lib/bit_packing_avx2.s $(C2GOASM) -a -f $^ $@ -unpack_bool_avx2.s: _lib/unpack_bool_avx2.s +unpack_bool_avx2_amd64.s: _lib/unpack_bool_avx2.s $(C2GOASM) -a -f $^ $@ -unpack_bool_sse4.s: _lib/unpack_bool_sse4.s +unpack_bool_sse4_amd64.s: _lib/unpack_bool_sse4.s $(C2GOASM) -a -f $^ $@ clean: diff --git a/go/parquet/internal/utils/_lib/README.md b/go/parquet/internal/utils/_lib/README.md new file mode 100644 index 0000000000000..10cc9a257e055 --- /dev/null +++ b/go/parquet/internal/utils/_lib/README.md @@ -0,0 +1,154 @@ + + +# SIMD Bit Packing Implementation + +Go doesn't have any SIMD intrinsics so for some low-level optimizations we can +leverage auto-vectorization by C++ compilers and the fact that Go lets you specify the body of a +function in assembly to benefit from SIMD. + +In here we have implementations using SIMD intrinsics for AVX (amd64) and NEON (arm64). + +## Generating the Go assembly + +c2goasm and asm2plan9s are two projects which can be used in conjunction to generate +compatible Go assembly from C assembly. + +First the tools need to be installed: + +```bash +go install github.com/klauspost/asmfmt/cmd/asmfmt@latest +go install github.com/minio/asm2plan9s@latest +go install github.com/minio/c2goasm@latest +``` + +### Generating for amd64 + +The Makefile in the directory above will work for amd64. `make assembly` will compile +the c sources and then call `c2goasm` to generate the Go assembly for amd64 +architectures. + +### Generating for arm64 + +Unfortunately there are some caveats for arm64. c2goasm / asm2plan9s doesn't fully +support arm64 correctly. However, proper assembly can be created with some slight +manipulation of the result. + +The Makefile has the NEON flags for compiling the assembly by using +`make _lib/bit_packing_neon.s` and `make _lib/unpack_bool_neon.s` to generate the +raw assembly sources. + +Before calling `c2goasm` there's a few things that need to be modified in the assembly: + +* x86-64 assembly uses `#` for comments while arm64 assembly uses `//` for comments. + `c2goasm` assumes `#` for comments and splits lines based on them. For most lines + this isn't an issue, but for any constants this is important and will need to have + the comment character converted from `//` to `#`. +* A `word` for x86-64 is 16 bits, a `double` word is 32 bits, and a `quad` is 64 bits. + For arm64, a `word` is 32 bits. This means that constants in the assembly need to be + modified. `c2goasm` and `asm2plan9s` expect the x86-64 meaning for the sizes, so + usage of `.word ######` needs to be converted to `.long #####` before running + `c2goasm`. In addition, `.xword` is an 8-byte value and as such should be changed to + `.quad` before running `c2goasm`. +* Because of this change in bits, `MOVQ` instructions will also be converted to + `MOVD` instructions. + +After running `c2goasm` there will still need to be modifications made to the +resulting assembly. + +* Most of the ARM instructions will be converted to using the Go assembly construction + of `WORD $0x########` to provide an instruction directly to the processor rather than + going through the Go assembler. Some of the instructions, however, aren't recognized + by `c2goasm` and will need to added. If you look at the assembly, you'll see these + as assembly that is commented out without any `WORD` instruction. For example: + ```asm + // stp x29, x30, [sp, #-48]! + WORD $0x11007c48 // add w8, w2, #31 + ``` + The `stp` instruction needs to be added. This can be done in one of two ways: + 1. Many instructions are properly handled by the Go assembler correctly. You can + find the arm-specific caveats to Go's assembly [here](https://pkg.go.dev/cmd/internal/obj/arm64). In this case, the instruction would be `STP.W (R29, R30), -48(RSP)`. + 2. Assuming that the GNU assembler is installed, you can use it to generate the + correct byte sequence. Create a file named `neon.asm` with a single line + (the instruction) and call `as -o neon.o neon.asm`. Then you can run + `objdump -S neon.o` to get the value to use. The output should look something + like: + ``` + Disassembly of section .text: + + 0000000000000000 <.text>: + 0: 11 00 7c 48 add w8, w2, #31 + ``` + And then update the assembly as `WORD $0x11007c48 // add w8, w2, #31` +* Labels used in instructions won't work when using the `WORD $0x#########` syntax. + They need to be the actual instructions for the labels. So all lines that have a + label will need to be converted. This is two-fold: + 1. Any lines for branching such as those which end with `// b.le LBB0_10` are updated + to be `BLE LBB0_10`. The same is true for `b.gt`, `b.ge`, `b.ne`, and `b.eq`. `b` + instructions are instead converted to `JMP` calls. + 2. References to constants need to be updated, for example `LCPI0_192`. By default, + these will get converted to global data instructions like + `DATA LCDATA1<>+0xc68(SB)/8, $0x0000000000000000`. Unfortunately, these seem to + have issues with being referenced by the assembler. The pattern to look for in + the assembly is an `adrp x9, .LCPI0_192` instruction that is later followed by + an instruction that looks like `str d4, [x9, 0:lo12:.LCPI0_192]`. These will + need to be converted to a macro and a `VMOV` instruction. + * In the original assembly, you'll see blocks like: + ```asm + .LCPI0_0 + .word 1 // 0x00000001 + .word 2 // 0x00000002 + .LCPI0_1 + .word 4294967265 // 0xffffffe1 + .word 4294967266 // 0xffffffe2 + ``` + which were converted to the `DATA LCDATA1`.... lines. Instead they should get + converted to a macro and a vector instruction: + ```asm + #define LCPI0_0 $0x0000000200000001 + #define LCPI0_1 $0xffffffe2ffffffe1 + ``` + Notice the lower/higher bits! + Then replace the `str`/`ldr`/`mov` instruction as `VMOVD LCPI0_0, v4`. Because + the original instruction storing the value in `d4`, we use `VMOVD` and `V4`. + Alternately we might find a prefix of `q` instead of `d`, in which case it we + need to use `VMOVQ` and pass the lower bytes followed by the higher bytes. + ```asm + #define LCPI0_48L $0x0000000d00000008 + #define LCPI0_48H $0x0000001700000012 + ... + VMOVQ LCPI0_48L, LCPI0_48H, V4 + ``` + After replacing the instructions, both the `adrp` and the `str`/`ldr`/`mov` + instructions should be removed/commented out. + There might also be a `LEAQ LCDATA1<>(SB), BP` instruction at the top of the + function. That should be removed/commented out as we are replacing the constants + with macros. +* Finally, if the function has a return value, make sure that at the end of the + function, ends with something akin to `MOVD R0, num+32(FP)`. Where `num` is the + local variable name of the return value, and `32` is the byte size of the arguments. + +To faciliate some automation, a `script.sed` file is provided in this directory which +can be run against the generated assembly from `c2goasm` as +`sed -f _lib/script.sed -i bit_packing_neon_arm64.s` which will perform several of +these steps on the generated assembly such as convering `b.le`/etc calls with labels +to proper `BLE LBB0_....` lines, and converting `adrp`/`ldr` pairs to `VMOVD` and +`VMOVQ` instructions. + +This should be sufficient to ensuring the assembly is generated and works properly! \ No newline at end of file diff --git a/go/parquet/internal/utils/_lib/bit_packing_neon.c b/go/parquet/internal/utils/_lib/bit_packing_neon.c index c333a346c3ac9..c8dd97c2a36a2 100755 --- a/go/parquet/internal/utils/_lib/bit_packing_neon.c +++ b/go/parquet/internal/utils/_lib/bit_packing_neon.c @@ -20,8 +20,9 @@ #include "arm_neon.h" inline const uint32_t* unpack0_32_neon(const uint32_t* in, uint32_t* out) { - memset(out, 0x0, 32 * sizeof(*out)); - out += 32; + for (const uint32_t* end = out + 32; out != end; out++) { + *out = 0; + } return in; } @@ -647,7 +648,7 @@ inline static const uint32_t* unpack7_32_neon(const uint32_t* in, uint32_t* out) out += 4; // shift the 2nd 4 outs - ind[2] = (in[0] >> 28 | in[1] << 4) >> shifts_2nd[0]; + ind[0] = (in[0] >> 28 | in[1] << 4) >> shifts_2nd[0]; ind[1] = in[1] >> shifts_2nd[1]; ind[2] = in[1] >> shifts_2nd[2]; ind[3] = in[1] >> shifts_2nd[3]; @@ -842,7 +843,7 @@ inline static const uint32_t* unpack9_32_neon(const uint32_t* in, uint32_t* out) out += 4; // shift the 2nd 4 outs - ind[2] = in[1] >> shifts_2nd[0]; + ind[0] = in[1] >> shifts_2nd[0]; ind[1] = in[1] >> shifts_2nd[1]; ind[2] = in[1] >> shifts_2nd[2]; ind[3] = (in[1] >> 31 | in[2] << 1) >> shifts_2nd[3]; @@ -939,7 +940,7 @@ inline static const uint32_t* unpack10_32_neon(const uint32_t* in, uint32_t* out out += 4; // shift the 2nd 4 outs - ind[2] = in[1] >> shifts_2nd[0]; + ind[0] = in[1] >> shifts_2nd[0]; ind[1] = in[1] >> shifts_2nd[1]; ind[2] = (in[1] >> 28 | in[2] << 4) >> shifts_2nd[2]; ind[3] = in[2] >> shifts_2nd[3]; @@ -1040,7 +1041,7 @@ inline static const uint32_t* unpack11_32_neon(const uint32_t* in, uint32_t* out out += 4; // shift the 2nd 4 outs - ind[2] = in[1] >> shifts_2nd[0]; + ind[0] = in[1] >> shifts_2nd[0]; ind[1] = (in[1] >> 23 | in[2] << 9) >> shifts_2nd[1]; ind[2] = in[2] >> shifts_2nd[2]; ind[3] = in[2] >> shifts_2nd[3]; @@ -1135,7 +1136,7 @@ inline static const uint32_t* unpack12_32_neon(const uint32_t* in, uint32_t* out out += 4; // shift the 2nd 4 outs - ind[2] = in[1] >> shifts_2nd[0]; + ind[0] = in[1] >> shifts_2nd[0]; ind[1] = (in[1] >> 28 | in[2] << 4) >> shifts_2nd[1]; ind[2] = in[2] >> shifts_2nd[2]; ind[3] = in[2] >> shifts_2nd[3]; @@ -1236,7 +1237,7 @@ inline static const uint32_t* unpack13_32_neon(const uint32_t* in, uint32_t* out out += 4; // shift the 2nd 4 outs - ind[2] = (in[1] >> 20 | in[2] << 12) >> shifts_2nd[0]; + ind[0] = (in[1] >> 20 | in[2] << 12) >> shifts_2nd[0]; ind[1] = in[2] >> shifts_2nd[1]; ind[2] = in[2] >> shifts_2nd[2]; ind[3] = (in[2] >> 27 | in[3] << 5) >> shifts_2nd[3]; @@ -1698,7 +1699,6 @@ inline static const uint32_t* unpack17_32_neon(const uint32_t* in, uint32_t* out vst1q_u32(out, results); out += 4; - in += 17; return in; @@ -1908,7 +1908,7 @@ inline static const uint32_t* unpack20_32_neon(const uint32_t* in, uint32_t* out uint32_t shifts_1st[4] = {0, 0, 8, 0}; uint32_t shifts_2nd[4] = {0, 4, 0, 12}; uint32x4_t reg_shft, reg_masks; - uint32x4_t results; + uint32x4_t results; reg_masks = vdupq_n_u32(mask); @@ -2093,7 +2093,6 @@ inline static const uint32_t* unpack21_32_neon(const uint32_t* in, uint32_t* out vst1q_u32(out, results); out += 4; - in += 21; return in; @@ -3079,9 +3078,10 @@ inline static const uint32_t* unpack31_32_neon(const uint32_t* in, uint32_t* out } inline const uint32_t* unpack32_32_neon(const uint32_t* in, uint32_t* out) { - memcpy(out, in, 32 * sizeof(*out)); - in += 32; - out += 32; + for (const uint32_t* end = out + 32; out != end; out++) { + *out = *in; + in++; + } return in; } diff --git a/go/parquet/internal/utils/_lib/script.sed b/go/parquet/internal/utils/_lib/script.sed new file mode 100644 index 0000000000000..908cce695a5ba --- /dev/null +++ b/go/parquet/internal/utils/_lib/script.sed @@ -0,0 +1,22 @@ +# 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. + +s|WORD $0x54[0-9a-f]\+[[:space:]]\+//[[:space:]]\+b.\([leqgtnso]\+\)[[:space:]]\+.\(LBB0_[0-9]\+\)|B\U\1 \2| +s|WORD $0x14000000[[:space:]]\+//[[:space:]]\+b[[:space:]]\+.\(LBB0_[0-9]\+\)|JMP \1| +s|\(WORD $0x9[0-9a-f]\+ // adrp.*\)|// \1| +s|WORD $0x[0-9a-f]\+ // ldr[[:space:]]\+d\([0-9]\+\), \[x[0-9]\+, :lo[0-9]\+:.\(LCPI0_[0-9]\+\)\]|VMOVD \2, V\1| +s|WORD $0x[0-9a-f]\+ // ldr[[:space:]]\+q\([0-9]\+\), \[x[0-9]\+, :lo[0-9]\+:.\(LCPI0_[0-9]\+\)\]|VMOVQ \2L, \2H, V\1| diff --git a/go/parquet/internal/utils/bit_packing_arm64.go b/go/parquet/internal/utils/bit_packing_arm64.go index 61eead02633ca..92fe0f97b77c3 100644 --- a/go/parquet/internal/utils/bit_packing_arm64.go +++ b/go/parquet/internal/utils/bit_packing_arm64.go @@ -20,33 +20,14 @@ package utils import ( - "os" - "strings" - - "golang.org/x/sys/cpu" + "github.com/klauspost/cpuid/v2" + // import for side effect of initializing feature flags + // based on ARM_ENABLE_EXT env var + _ "github.com/apache/arrow/go/v14/parquet/internal/bmi" ) func init() { - cpu.ARM64.HasASIMD = false - cpu.ARM64.HasAES = false - cpu.ARM64.HasPMULL = false - // Added ability to enable extension via environment: - if ext, ok := os.LookupEnv("ARM_ENABLE_EXT"); ok { - exts := strings.Split(ext, ",") - - for _, x := range exts { - switch x { - case "NEON": - cpu.ARM64.HasASIMD = true - case "AES": - cpu.ARM64.HasAES = true - case "PMULL": - cpu.ARM64.HasPMULL = true - default: - } - } - } - if cpu.ARM64.HasASIMD { + if cpuid.CPU.Has(cpuid.ASIMD) { unpack32 = unpack32NEON } else { // default to the pure go implementation if no avx2 available unpack32 = unpack32Default diff --git a/go/parquet/internal/utils/bit_packing_neon_arm64.s b/go/parquet/internal/utils/bit_packing_neon_arm64.s old mode 100755 new mode 100644 index 047e5b720e4a0..2d18dccdb573b --- a/go/parquet/internal/utils/bit_packing_neon_arm64.s +++ b/go/parquet/internal/utils/bit_packing_neon_arm64.s @@ -1,3351 +1,6926 @@ //+build !noasm !appengine +// AUTO-GENERATED BY C2GOASM -- DO NOT EDIT + +#include "go_asm.h" +#include "textflag.h" + +#define LCPI0_0L $0x000000000000000e +#define LCPI0_0H $0x000000000000000f +#define LCPI0_1L $0x000000000000000c +#define LCPI0_1H $0x000000000000000d +#define LCPI0_2L $0x000000000000000a +#define LCPI0_2H $0x000000000000000b +#define LCPI0_3L $0x0000000000000008 +#define LCPI0_3H $0x0000000000000009 +#define LCPI0_4L $0x0000000000000006 +#define LCPI0_4H $0x0000000000000007 +#define LCPI0_5L $0x0000000000000004 +#define LCPI0_5H $0x0000000000000005 +#define LCPI0_6L $0x0000000000000002 +#define LCPI0_6H $0x0000000000000003 +#define LCPI0_7L $0x0000000000000000 +#define LCPI0_7H $0x0000000000000001 + +#define LCPI0_10L $0x0000000500000004 +#define LCPI0_10H $0x0000000700000006 +#define LCPI0_11L $0xffffffe5ffffffe4 +#define LCPI0_11H $0xffffffe7ffffffe6 +#define LCPI0_12L $0x0000000900000008 +#define LCPI0_12H $0x0000000b0000000a +#define LCPI0_13L $0xffffffe9ffffffe8 +#define LCPI0_13H $0xffffffebffffffea +#define LCPI0_14L $0x0000000d0000000c +#define LCPI0_14H $0x0000000f0000000e +#define LCPI0_15L $0xffffffedffffffec +#define LCPI0_15H $0xffffffefffffffee +#define LCPI0_16L $0x0000001100000010 +#define LCPI0_16H $0x0000001300000012 +#define LCPI0_17L $0xfffffff1fffffff0 +#define LCPI0_17H $0xfffffff3fffffff2 +#define LCPI0_18L $0x0000001500000014 +#define LCPI0_18H $0x0000001700000016 +#define LCPI0_19L $0xfffffff5fffffff4 +#define LCPI0_19H $0xfffffff7fffffff6 +#define LCPI0_20L $0x0000001900000018 +#define LCPI0_20H $0x0000001b0000001a +#define LCPI0_21L $0xfffffff9fffffff8 +#define LCPI0_21H $0xfffffffbfffffffa +#define LCPI0_26L $0x0000000a00000008 +#define LCPI0_26H $0x0000000e0000000c +#define LCPI0_27L $0xffffffeaffffffe8 +#define LCPI0_27H $0xffffffeeffffffec +#define LCPI0_28L $0x0000001200000010 +#define LCPI0_28H $0x0000001600000014 +#define LCPI0_29L $0xfffffff2fffffff0 +#define LCPI0_29H $0xfffffff6fffffff4 +#define LCPI0_34L $0x0000000f0000000c +#define LCPI0_34H $0x0000001500000012 +#define LCPI0_35L $0xffffffefffffffec +#define LCPI0_35H $0xfffffff5fffffff2 +#define LCPI0_38L $0x0000000700000004 +#define LCPI0_38H $0x0000000d0000000a +#define LCPI0_39L $0xffffffe7ffffffe4 +#define LCPI0_39H $0xffffffedffffffea +#define LCPI0_40L $0x0000001300000010 +#define LCPI0_40H $0x0000001900000016 +#define LCPI0_41L $0xfffffff3fffffff0 +#define LCPI0_41H $0xfffffff9fffffff6 +#define LCPI0_44L $0x0000000b00000008 +#define LCPI0_44H $0x000000110000000e +#define LCPI0_45L $0xffffffebffffffe8 +#define LCPI0_45H $0xfffffff1ffffffee +#define LCPI0_56L $0x0000000d00000008 +#define LCPI0_56H $0x0000001700000012 +#define LCPI0_57L $0xffffffedffffffe8 +#define LCPI0_57H $0xfffffff7fffffff2 +#define LCPI0_62L $0x0000000900000004 +#define LCPI0_62H $0x000000130000000e +#define LCPI0_63L $0xffffffe9ffffffe4 +#define LCPI0_63H $0xfffffff3ffffffee +#define LCPI0_173L $0xfffffff5fffffffc +#define LCPI0_173H $0xffffffe7ffffffee +#define LCPI0_177L $0xfffffff2fffffff8 +#define LCPI0_177H $0xffffffe6ffffffec +#define LCPI0_180L $0xfffffff3fffffff8 +#define LCPI0_180H $0xffffffe9ffffffee +#define LCPI0_183L $0xfffffff7fffffffc +#define LCPI0_183H $0xffffffedfffffff2 +#define LCPI0_185L $0xffffffeffffffff4 +#define LCPI0_185H $0xffffffe5ffffffea +#define LCPI0_187L $0xffffffecfffffff0 +#define LCPI0_187H $0xffffffe4ffffffe8 +#define LCPI0_189L $0xfffffff1fffffff4 +#define LCPI0_189H $0xffffffebffffffee +#define LCPI0_191L $0xfffffff9fffffffc +#define LCPI0_191H $0xfffffff3fffffff6 +#define LCPI0_192L $0xffffffedfffffff0 +#define LCPI0_192H $0xffffffe7ffffffea +#define LCPI0_194L $0xfffffff5fffffff8 +#define LCPI0_194H $0xffffffeffffffff2 +#define LCPI0_195L $0xffffffe9ffffffec +#define LCPI0_195H $0xffffffe3ffffffe6 +#define LCPI0_197L $0xfffffff6fffffff8 +#define LCPI0_197H $0xfffffff2fffffff4 +#define LCPI0_198L $0xffffffeefffffff0 +#define LCPI0_198H $0xffffffeaffffffec +#define LCPI0_199L $0xffffffe6ffffffe8 +#define LCPI0_199H $0xffffffe2ffffffe4 +#define LCPI0_201L $0xfffffffbfffffffc +#define LCPI0_201H $0xfffffff9fffffffa +#define LCPI0_202L $0xfffffff7fffffff8 +#define LCPI0_202H $0xfffffff5fffffff6 +#define LCPI0_203L $0xfffffff3fffffff4 +#define LCPI0_203H $0xfffffff1fffffff2 +#define LCPI0_204L $0xffffffeffffffff0 +#define LCPI0_204H $0xffffffedffffffee +#define LCPI0_205L $0xffffffebffffffec +#define LCPI0_205H $0xffffffe9ffffffea +#define LCPI0_206L $0xffffffe7ffffffe8 +#define LCPI0_206H $0xffffffe5ffffffe6 +#define LCPI0_207L $0xffffffe3ffffffe4 +#define LCPI0_207H $0xffffffe1ffffffe2 + +#define LCPI0_8 $0x0000000200000001 +#define LCPI0_9 $0xffffffe2ffffffe1 +#define LCPI0_22 $0x0000001d0000001c +#define LCPI0_23 $0xfffffffdfffffffc +#define LCPI0_24 $0x0000000400000002 +#define LCPI0_25 $0xffffffe4ffffffe2 +#define LCPI0_30 $0x0000001a00000018 +#define LCPI0_31 $0xfffffffafffffff8 +#define LCPI0_32 $0x0000000600000003 +#define LCPI0_33 $0xffffffe6ffffffe3 +#define LCPI0_36 $0x0000001b00000018 +#define LCPI0_37 $0xfffffffbfffffff8 +#define LCPI0_42 $0x0000000500000002 +#define LCPI0_43 $0xffffffe5ffffffe2 +#define LCPI0_46 $0x0000001700000014 +#define LCPI0_47 $0xfffffff7fffffff4 +#define LCPI0_48 $0x0000000800000004 +#define LCPI0_49 $0xffffffe8ffffffe4 +#define LCPI0_50 $0x0000001400000010 +#define LCPI0_51 $0xfffffff4fffffff0 +#define LCPI0_52 $0x0000000a00000005 +#define LCPI0_53 $0xffffffeaffffffe5 +#define LCPI0_54 $0x0000001900000014 +#define LCPI0_55 $0xfffffff9fffffff4 +#define LCPI0_58 $0x0000000600000001 +#define LCPI0_59 $0xffffffe6ffffffe1 +#define LCPI0_60 $0x0000001500000010 +#define LCPI0_61 $0xfffffff5fffffff0 +#define LCPI0_64 $0x0000000700000002 +#define LCPI0_65 $0xffffffe7ffffffe2 +#define LCPI0_66 $0x000000110000000c +#define LCPI0_67 $0xfffffff1ffffffec +#define LCPI0_68 $0x0000000c00000006 +#define LCPI0_69 $0xffffffecffffffe6 +#define LCPI0_70 $0x0000000a00000004 +#define LCPI0_71 $0xffffffeaffffffe4 +#define LCPI0_72 $0x0000001600000010 +#define LCPI0_73 $0xfffffff6fffffff0 +#define LCPI0_74 $0x0000000e00000008 +#define LCPI0_75 $0xffffffeeffffffe8 +#define LCPI0_76 $0x0000000e00000007 +#define LCPI0_77 $0xffffffeeffffffe7 +#define LCPI0_78 $0x0000000a00000003 +#define LCPI0_79 $0xffffffeaffffffe3 +#define LCPI0_80 $0x0000000d00000006 +#define LCPI0_81 $0xffffffedffffffe6 +#define LCPI0_82 $0x0000000900000002 +#define LCPI0_83 $0xffffffe9ffffffe2 +#define LCPI0_84 $0x0000001700000010 +#define LCPI0_85 $0xfffffff7fffffff0 +#define LCPI0_86 $0x000000130000000c +#define LCPI0_87 $0xfffffff3ffffffec +#define LCPI0_88 $0x0000000f00000008 +#define LCPI0_89 $0xffffffefffffffe8 +#define LCPI0_90 $0x0000000b00000004 +#define LCPI0_91 $0xffffffebffffffe4 +#define LCPI0_92 $0x0000001000000008 +#define LCPI0_93 $0xfffffff0ffffffe8 +#define LCPI0_94 $0x0000001200000009 +#define LCPI0_95 $0xfffffff2ffffffe9 +#define LCPI0_96 $0x0000000d00000004 +#define LCPI0_97 $0xffffffedffffffe4 +#define LCPI0_98 $0x0000001100000008 +#define LCPI0_99 $0xfffffff1ffffffe8 +#define LCPI0_100 $0x000000150000000c +#define LCPI0_101 $0xfffffff5ffffffec +#define LCPI0_102 $0x0000000b00000002 +#define LCPI0_103 $0xffffffebffffffe2 +#define LCPI0_104 $0x0000000f00000006 +#define LCPI0_105 $0xffffffefffffffe6 +#define LCPI0_106 $0x0000000a00000001 +#define LCPI0_107 $0xffffffeaffffffe1 +#define LCPI0_108 $0x0000000e00000005 +#define LCPI0_109 $0xffffffeeffffffe5 +#define LCPI0_110 $0x000000140000000a +#define LCPI0_111 $0xfffffff4ffffffea +#define LCPI0_112 $0x0000001200000008 +#define LCPI0_113 $0xfffffff2ffffffe8 +#define LCPI0_114 $0x0000000e00000004 +#define LCPI0_115 $0xffffffeeffffffe4 +#define LCPI0_116 $0x0000000c00000002 +#define LCPI0_117 $0xffffffecffffffe2 +#define LCPI0_118 $0x0000000d00000002 +#define LCPI0_119 $0xffffffedffffffe2 +#define LCPI0_120 $0x0000000e00000003 +#define LCPI0_121 $0xffffffeeffffffe3 +#define LCPI0_122 $0x0000000f00000004 +#define LCPI0_123 $0xffffffefffffffe4 +#define LCPI0_124 $0x0000001100000006 +#define LCPI0_125 $0xfffffff1ffffffe6 +#define LCPI0_126 $0x0000001200000007 +#define LCPI0_127 $0xfffffff2ffffffe7 +#define LCPI0_128 $0x0000001300000008 +#define LCPI0_129 $0xfffffff3ffffffe8 +#define LCPI0_130 $0x0000000e00000001 +#define LCPI0_131 $0xffffffeeffffffe1 +#define LCPI0_132 $0x0000000f00000002 +#define LCPI0_133 $0xffffffefffffffe2 +#define LCPI0_134 $0x0000001100000004 +#define LCPI0_135 $0xfffffff1ffffffe4 +#define LCPI0_136 $0x0000001200000005 +#define LCPI0_137 $0xfffffff2ffffffe5 +#define LCPI0_138 $0xffffffeffffffffe +#define LCPI0_139 $0xffffffeefffffffc +#define LCPI0_140 $0xfffffff2ffffffff +#define LCPI0_141 $0xfffffff1fffffffe +#define LCPI0_142 $0xffffffeffffffffc +#define LCPI0_143 $0xffffffeefffffffb +#define LCPI0_144 $0xffffffedfffffffa +#define LCPI0_145 $0xffffffecfffffff8 +#define LCPI0_146 $0xfffffff3fffffffe +#define LCPI0_147 $0xfffffff2fffffffd +#define LCPI0_148 $0xfffffff1fffffffc +#define LCPI0_149 $0xffffffeffffffffa +#define LCPI0_150 $0xffffffeefffffff9 +#define LCPI0_151 $0xffffffedfffffff8 +#define LCPI0_152 $0xffffffebfffffff6 +#define LCPI0_153 $0xffffffecfffffff6 +#define LCPI0_154 $0xffffffeefffffff8 +#define LCPI0_155 $0xfffffff2fffffffc +#define LCPI0_156 $0xfffffff4fffffffe +#define LCPI0_157 $0xffffffeefffffff7 +#define LCPI0_158 $0xfffffff3fffffffc +#define LCPI0_159 $0xffffffeffffffff8 +#define LCPI0_160 $0xffffffebfffffff4 +#define LCPI0_161 $0xfffffff5fffffffe +#define LCPI0_162 $0xfffffff1fffffffa +#define LCPI0_163 $0xfffffff6ffffffff +#define LCPI0_164 $0xfffffff2fffffffb +#define LCPI0_165 $0xfffffff0fffffff8 +#define LCPI0_166 $0xfffffff2fffffff9 +#define LCPI0_167 $0xfffffff6fffffffd +#define LCPI0_168 $0xfffffff3fffffffa +#define LCPI0_169 $0xfffffff7fffffffe +#define LCPI0_170 $0xffffffe9fffffff0 +#define LCPI0_171 $0xffffffedfffffff4 +#define LCPI0_172 $0xfffffff1fffffff8 +#define LCPI0_174 $0xfffffff4fffffffa +#define LCPI0_175 $0xfffffff6fffffffc +#define LCPI0_176 $0xffffffeafffffff0 +#define LCPI0_178 $0xfffffff6fffffffb +#define LCPI0_179 $0xffffffe7ffffffec +#define LCPI0_181 $0xfffffffaffffffff +#define LCPI0_182 $0xffffffebfffffff0 +#define LCPI0_184 $0xfffffff9fffffffe +#define LCPI0_186 $0xfffffff8fffffffc +#define LCPI0_188 $0xfffffffafffffffd +#define LCPI0_190 $0xffffffe5ffffffe8 +#define LCPI0_193 $0xfffffffbfffffffe +#define LCPI0_196 $0xfffffffcfffffffe +#define LCPI0_200 $0xfffffffeffffffff + +TEXT ·_unpack32_neon(SB), $0-40 + + MOVD in+0(FP), R0 + MOVD out+8(FP), R1 + MOVD batchSize+16(FP), R2 + MOVD nbits+24(FP), R3 + // LEAQ LCDATA1<>(SB), BP + + // %bb.0: + WORD $0xa9ba7bfd // stp x29, x30, [sp, #-96]! + WORD $0xd10643e9 // sub x9, sp, #400 + WORD $0xa9016ffc // stp x28, x27, [sp, #16] + WORD $0xa90267fa // stp x26, x25, [sp, #32] + WORD $0x910003fd // mov x29, sp + WORD $0xa9035ff8 // stp x24, x23, [sp, #48] + WORD $0xa90457f6 // stp x22, x21, [sp, #64] + WORD $0xa9054ff4 // stp x20, x19, [sp, #80] + WORD $0x927df13f // and sp, x9, #0xfffffffffffffff8 + WORD $0x11007c48 // add w8, w2, #31 + WORD $0x7100005f // cmp w2, #0 + WORD $0x1a82b108 // csel w8, w8, w2, lt + WORD $0xaa0103fa // mov x26, x1 + WORD $0x13057d13 // asr w19, w8, #5 + WORD $0x71003c7f // cmp w3, #15 + BLE LBB0_14 + + // %bb.1: + WORD $0x71005c7f // cmp w3, #23 + BLE LBB0_22 + + // %bb.2: + WORD $0x71006c7f // cmp w3, #27 + BLE LBB0_36 + + // %bb.3: + WORD $0x7100747f // cmp w3, #29 + BLE LBB0_60 + + // %bb.4: + WORD $0x7100787f // cmp w3, #30 + BEQ LBB0_148 + + // %bb.5: + WORD $0x71007c7f // cmp w3, #31 + BEQ LBB0_100 + + // %bb.6: + WORD $0x7100807f // cmp w3, #32 + BNE LBB0_156 + + // %bb.7: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.8: + WORD $0x7100427f // cmp w19, #16 + BLO LBB0_11 + + // %bb.9: + WORD $0xd379e268 // lsl x8, x19, #7 + WORD $0x8b080009 // add x9, x0, x8 + WORD $0xeb1a013f // cmp x9, x26 + BLS LBB0_157 + + // %bb.10: + WORD $0x8b080348 // add x8, x26, x8 + WORD $0xeb00011f // cmp x8, x0 + BLS LBB0_157 + +LBB0_11: + WORD $0xf9000fff // str xzr, [sp, #24] -// ARROW-15336 -// (C2GOASM doesn't work correctly for Arm64) -// Partly GENERATED BY asm2plan9s. - -DATA LJTI<>+0x000(SB)/2, $0 -DATA LJTI<>+0x002(SB)/2, $9 -DATA LJTI<>+0x004(SB)/2, $72 -DATA LJTI<>+0x006(SB)/2, $133 -DATA LJTI<>+0x008(SB)/2, $210 -DATA LJTI<>+0x00a(SB)/2, $291 -DATA LJTI<>+0x00c(SB)/2, $390 -DATA LJTI<>+0x00e(SB)/2, $474 -DATA LJTI<>+0x010(SB)/2, $567 -DATA LJTI<>+0x012(SB)/2, $657 -DATA LJTI<>+0x014(SB)/2, $758 -DATA LJTI<>+0x016(SB)/2, $854 -DATA LJTI<>+0x018(SB)/2, $957 -DATA LJTI<>+0x01a(SB)/2, $1048 -DATA LJTI<>+0x01c(SB)/2, $4601 -DATA LJTI<>+0x01e(SB)/2, $1250 -DATA LJTI<>+0x020(SB)/2, $1354 -DATA LJTI<>+0x022(SB)/2, $1436 -DATA LJTI<>+0x024(SB)/2, $1541 -DATA LJTI<>+0x026(SB)/2, $1645 -DATA LJTI<>+0x028(SB)/2, $1773 -DATA LJTI<>+0x02a(SB)/2, $1875 -DATA LJTI<>+0x02c(SB)/2, $2015 -DATA LJTI<>+0x02e(SB)/2, $2145 -DATA LJTI<>+0x030(SB)/2, $2292 -DATA LJTI<>+0x032(SB)/2, $2390 -DATA LJTI<>+0x034(SB)/2, $3140 -DATA LJTI<>+0x036(SB)/2, $2533 -DATA LJTI<>+0x038(SB)/2, $2667 -DATA LJTI<>+0x03a(SB)/2, $2781 -DATA LJTI<>+0x03c(SB)/2, $2902 -DATA LJTI<>+0x03e(SB)/2, $3008 -DATA LJTI<>+0x040(SB)/2, $3117 -GLOBL LJTI<>+0(SB), 8, $66 - - -// func _unpack32_neon(in, out unsafe.Pointer, batchSize, nbits int) (num int) -TEXT ·_unpack32_neon(SB), $24-40 - - MOVD in+0(FP), R0 - MOVD out+8(FP), R1 - MOVD batchSize+16(FP), R2 - MOVD nbits+24(FP), R3 - - WORD $0xa9be7bfd // stp x29, x30, [sp, #-32]! - WORD $0x11007c48 // add w8, w2, #31 - WORD $0x7100005f // cmp w2, #0 - WORD $0x1a82b108 // csel w8, w8, w2, lt - WORD $0xf9000bf3 // str x19, [sp, #16] - WORD $0x7100807f // cmp w3, #32 - WORD $0x121b6913 // and w19, w8, #0xffffffe0 - WORD $0x910003fd // mov x29, sp - BHI LBB0_99 - WORD $0x2a0303e9 // mov w9, w3 - MOVD LJTI<>+0x00(SB), R10 - WORD $0x1000000b // adr x11, LBB0_2 - WORD $0x7869794c // ldrh w12, [x10, x9, lsl #1] - WORD $0x8b0c096b // add x11, x11, x12, lsl #2 - WORD $0x13057d08 // asr w8, w8, #5 - WORD $0xd61f0160 // br x11 -LBB0_2: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - WORD $0x51000508 // sub w8, w8, #1 - WORD $0xd379e108 // lsl x8, x8, #7 - WORD $0x91020102 // add x2, x8, #128 - WORD $0xaa0103e0 // mov x0, x1 - WORD $0x2a1f03e1 // mov w1, wzr - WORD $0x94000000 // bl memset - JMP LBB0_99 -LBB0_4: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - VMOVQ $0x0000000500000004, $0x0000000700000006, V1 // LCPI0_1 - VMOVQ $0x0000000900000008, $0x0000000b0000000a, V2 // LCPI0_3 - VMOVQ $0x0000000d0000000c, $0x0000000f0000000e, V3 // LCPI0_5 - VMOVQ $0x0000001100000010, $0x0000001300000012, V4 // LCPI0_7 - VMOVQ $0x0000001500000014, $0x0000001700000016, V5 // LCPI0_9 - VMOVQ $0x0000001900000018, $0x0000001b0000001a, V6 // LCPI0_11 - VMOVQ $0x0000001d0000001c, $0x0000001f0000001e, V7 // LCPI0_121 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f000420 // movi v0.4s, #1 - WORD $0x6ea0b821 // neg v1.4s, v1.4s - WORD $0x6ea0b842 // neg v2.4s, v2.4s - WORD $0x6ea0b863 // neg v3.4s, v3.4s - WORD $0x6ea0b884 // neg v4.4s, v4.4s - WORD $0x6ea0b8a5 // neg v5.4s, v5.4s - WORD $0x6ea0b8c6 // neg v6.4s, v6.4s - WORD $0x6ea0b8e7 // neg v7.4s, v7.4s - WORD $0xaa0003ea // mov x10, x0 -LBB0_6: - WORD $0xb940000b // ldr w11, [x0] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x53017d6c // lsr w12, w11, #1 - WORD $0x1e270170 // fmov s16, w11 - WORD $0x53027d6d // lsr w13, w11, #2 - WORD $0x4e0c1d90 // mov v16.s[1], w12 - WORD $0x53037d6e // lsr w14, w11, #3 - WORD $0x4e141db0 // mov v16.s[2], w13 - WORD $0x4e1c1dd0 // mov v16.s[3], w14 - WORD $0x4e201e10 // and v16.16b, v16.16b, v0.16b - WORD $0x3c9c0130 // stur q16, [x9, #-64] - WORD $0x4ddfc950 // ld1r { v16.4s }, [x10], #4 - WORD $0x6ea14610 // ushl v16.4s, v16.4s, v1.4s - WORD $0x4e201e10 // and v16.16b, v16.16b, v0.16b - WORD $0x3c9d0130 // stur q16, [x9, #-48] - WORD $0x4d40c810 // ld1r { v16.4s }, [x0] - WORD $0x6ea24610 // ushl v16.4s, v16.4s, v2.4s - WORD $0x4e201e10 // and v16.16b, v16.16b, v0.16b - WORD $0x3c9e0130 // stur q16, [x9, #-32] - WORD $0x4d40c810 // ld1r { v16.4s }, [x0] - WORD $0x6ea34610 // ushl v16.4s, v16.4s, v3.4s - WORD $0x4e201e10 // and v16.16b, v16.16b, v0.16b - WORD $0x3c9f0130 // stur q16, [x9, #-16] - WORD $0x4d40c810 // ld1r { v16.4s }, [x0] - WORD $0x6ea44610 // ushl v16.4s, v16.4s, v4.4s - WORD $0x4e201e10 // and v16.16b, v16.16b, v0.16b - WORD $0x3d800130 // str q16, [x9] - WORD $0x4d40c810 // ld1r { v16.4s }, [x0] - WORD $0x6ea54610 // ushl v16.4s, v16.4s, v5.4s - WORD $0x4e201e10 // and v16.16b, v16.16b, v0.16b - WORD $0x3d800530 // str q16, [x9, #16] - WORD $0x4d40c810 // ld1r { v16.4s }, [x0] - WORD $0x6ea64610 // ushl v16.4s, v16.4s, v6.4s - WORD $0x4e201e10 // and v16.16b, v16.16b, v0.16b - WORD $0x3d800930 // str q16, [x9, #32] - WORD $0x4d40c810 // ld1r { v16.4s }, [x0] - WORD $0xaa0a03e0 // mov x0, x10 - WORD $0x6ea74610 // ushl v16.4s, v16.4s, v7.4s - WORD $0x4e201e10 // and v16.16b, v16.16b, v0.16b - WORD $0x3d800d30 // str q16, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - BNE LBB0_6 - JMP LBB0_99 -LBB0_7: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - VMOVQ $0x0000000a00000008, $0x0000000e0000000c, V1 // LCPI0_15 - VMOVQ $0x0000001200000010, $0x0000001600000014, V2 // LCPI0_17 - VMOVQ $0x0000001a00000018, $0x0000001e0000001c, V3 // LCPI0_120 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f000460 // movi v0.4s, #3 - WORD $0x6ea0b821 // neg v1.4s, v1.4s - WORD $0x6ea0b842 // neg v2.4s, v2.4s - WORD $0x6ea0b863 // neg v3.4s, v3.4s -LBB0_9: - WORD $0xb940000a // ldr w10, [x0] - WORD $0xaa0003eb // mov x11, x0 - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x53027d4c // lsr w12, w10, #2 - WORD $0x1e270144 // fmov s4, w10 - WORD $0x53047d4d // lsr w13, w10, #4 - WORD $0x4e0c1d84 // mov v4.s[1], w12 - WORD $0x53067d4e // lsr w14, w10, #6 - WORD $0x4e141da4 // mov v4.s[2], w13 - WORD $0x4e1c1dc4 // mov v4.s[3], w14 - WORD $0x4e201c84 // and v4.16b, v4.16b, v0.16b - WORD $0x3c9c0124 // stur q4, [x9, #-64] - WORD $0x4ddfc964 // ld1r { v4.4s }, [x11], #4 - WORD $0x6ea14484 // ushl v4.4s, v4.4s, v1.4s - WORD $0x4e201c84 // and v4.16b, v4.16b, v0.16b - WORD $0x3c9d0124 // stur q4, [x9, #-48] - WORD $0x4d40c804 // ld1r { v4.4s }, [x0] - WORD $0x6ea24484 // ushl v4.4s, v4.4s, v2.4s - WORD $0x4e201c84 // and v4.16b, v4.16b, v0.16b - WORD $0x3c9e0124 // stur q4, [x9, #-32] - WORD $0xb840840a // ldr w10, [x0], #8 - WORD $0x4e040d44 // dup v4.4s, w10 - WORD $0x6ea34484 // ushl v4.4s, v4.4s, v3.4s - WORD $0x4e201c84 // and v4.16b, v4.16b, v0.16b - WORD $0x3c9f0124 // stur q4, [x9, #-16] - WORD $0xb940016a // ldr w10, [x11] - WORD $0x53027d4c // lsr w12, w10, #2 - WORD $0x1e270144 // fmov s4, w10 - WORD $0x53047d4d // lsr w13, w10, #4 - WORD $0x4e0c1d84 // mov v4.s[1], w12 - WORD $0x53067d4e // lsr w14, w10, #6 - WORD $0x4e141da4 // mov v4.s[2], w13 - WORD $0x4e1c1dc4 // mov v4.s[3], w14 - WORD $0x4e201c84 // and v4.16b, v4.16b, v0.16b - WORD $0x3d800124 // str q4, [x9] - WORD $0x4d40c964 // ld1r { v4.4s }, [x11] - WORD $0x6ea14484 // ushl v4.4s, v4.4s, v1.4s - WORD $0x4e201c84 // and v4.16b, v4.16b, v0.16b - WORD $0x3d800524 // str q4, [x9, #16] - WORD $0x4d40c964 // ld1r { v4.4s }, [x11] - WORD $0x6ea24484 // ushl v4.4s, v4.4s, v2.4s - WORD $0x4e201c84 // and v4.16b, v4.16b, v0.16b - WORD $0x3d800924 // str q4, [x9, #32] - WORD $0x4d40c964 // ld1r { v4.4s }, [x11] - WORD $0x6ea34484 // ushl v4.4s, v4.4s, v3.4s - WORD $0x4e201c84 // and v4.16b, v4.16b, v0.16b - WORD $0x3d800d24 // str q4, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - BNE LBB0_9 - JMP LBB0_99 -LBB0_10: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - VMOVQ $0x0000000f0000000c, $0x0000001500000012, V1 // LCPI0_21 - MOVD $0x0000001b00000018, R2 // LCPI0_23 - VMOVQ $0x0000000700000004, $0x0000000d0000000a, V3 // LCPI0_25 - VMOVQ $0x0000001300000010, $0x0000001900000016, V4 // LCPI0_27 - MOVD $0x0000000500000002, R5 // LCPI0_29 - VMOVQ $0x0000000b00000008, $0x000000110000000e, V6 // LCPI0_31 - VMOVQ $0x0000001700000014, $0x0000001d0000001a, V7 // LCPI0_119 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f0004e0 // movi v0.4s, #7 - WORD $0x6ea0b821 // neg v1.4s, v1.4s - WORD $0x2ea0b842 // neg v2.2s, v2.2s - WORD $0x6ea0b863 // neg v3.4s, v3.4s - WORD $0x6ea0b884 // neg v4.4s, v4.4s - WORD $0x2ea0b8a5 // neg v5.2s, v5.2s - WORD $0x6ea0b8c6 // neg v6.4s, v6.4s - WORD $0x6ea0b8e7 // neg v7.4s, v7.4s LBB0_12: - WORD $0xb940000a // ldr w10, [x0] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x53037d4b // lsr w11, w10, #3 - WORD $0x1e270150 // fmov s16, w10 - WORD $0x53067d4c // lsr w12, w10, #6 - WORD $0x4e0c1d70 // mov v16.s[1], w11 - WORD $0x53097d4d // lsr w13, w10, #9 - WORD $0x4e141d90 // mov v16.s[2], w12 - WORD $0x4e1c1db0 // mov v16.s[3], w13 - WORD $0x4e201e10 // and v16.16b, v16.16b, v0.16b - WORD $0xaa0003ea // mov x10, x0 - WORD $0x3c9c0130 // stur q16, [x9, #-64] - WORD $0x4ddfc950 // ld1r { v16.4s }, [x10], #4 - WORD $0x6ea14610 // ushl v16.4s, v16.4s, v1.4s - WORD $0x4e201e10 // and v16.16b, v16.16b, v0.16b - WORD $0x3c9d0130 // stur q16, [x9, #-48] - WORD $0xb940000b // ldr w11, [x0] - WORD $0xb940014c // ldr w12, [x10] - WORD $0x0e040d70 // dup v16.2s, w11 - WORD $0x138b798b // extr w11, w12, w11, #30 - WORD $0x2ea24610 // ushl v16.2s, v16.2s, v2.2s - WORD $0x53017d8c // lsr w12, w12, #1 - WORD $0x4e141d70 // mov v16.s[2], w11 - WORD $0x4e1c1d90 // mov v16.s[3], w12 - WORD $0x4e201e10 // and v16.16b, v16.16b, v0.16b - WORD $0x3c9e0130 // stur q16, [x9, #-32] - WORD $0x4d40c950 // ld1r { v16.4s }, [x10] - WORD $0x9100200c // add x12, x0, #8 - WORD $0x6ea34610 // ushl v16.4s, v16.4s, v3.4s - WORD $0x4e201e10 // and v16.16b, v16.16b, v0.16b - WORD $0x3c9f0130 // stur q16, [x9, #-16] - WORD $0x4d40c950 // ld1r { v16.4s }, [x10] - WORD $0x6ea44610 // ushl v16.4s, v16.4s, v4.4s - WORD $0x4e201e10 // and v16.16b, v16.16b, v0.16b - WORD $0x3d800130 // str q16, [x9] - WORD $0xb940014a // ldr w10, [x10] - WORD $0xb940080b // ldr w11, [x0, #8] - WORD $0x91003000 // add x0, x0, #12 - WORD $0x531c7d4d // lsr w13, w10, #28 - WORD $0x138a7d6a // extr w10, w11, w10, #31 - WORD $0x0e040d70 // dup v16.2s, w11 - WORD $0x1e2701b1 // fmov s17, w13 - WORD $0x2ea54610 // ushl v16.2s, v16.2s, v5.2s - WORD $0x4e0c1d51 // mov v17.s[1], w10 - WORD $0x6e180611 // mov v17.d[1], v16.d[0] - WORD $0x4e201e30 // and v16.16b, v17.16b, v0.16b - WORD $0x3d800530 // str q16, [x9, #16] - WORD $0x4d40c990 // ld1r { v16.4s }, [x12] - WORD $0x6ea64610 // ushl v16.4s, v16.4s, v6.4s - WORD $0x4e201e10 // and v16.16b, v16.16b, v0.16b - WORD $0x3d800930 // str q16, [x9, #32] - WORD $0x4d40c990 // ld1r { v16.4s }, [x12] - WORD $0x6ea74610 // ushl v16.4s, v16.4s, v7.4s - WORD $0x4e201e10 // and v16.16b, v16.16b, v0.16b - WORD $0x3d800d30 // str q16, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - BNE LBB0_12 - JMP LBB0_99 + WORD $0xf9400fe8 // ldr x8, [sp, #24] + WORD $0x8b081f4a // add x10, x26, x8, lsl #7 + WORD $0xcb080268 // sub x8, x19, x8 + WORD $0x9101014a // add x10, x10, #64 + LBB0_13: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - VMOVQ $0x0000001400000010, $0x0000001c00000018, V1 // LCPI0_118 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f0005e0 // movi v0.4s, #15 - WORD $0x6ea0b821 // neg v1.4s, v1.4s -LBB0_15: - WORD $0xb940000a // ldr w10, [x0] - WORD $0xaa0003eb // mov x11, x0 - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x53047d4c // lsr w12, w10, #4 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x53087d4d // lsr w13, w10, #8 - WORD $0x4e0c1d82 // mov v2.s[1], w12 - WORD $0x530c7d4e // lsr w14, w10, #12 - WORD $0x4e141da2 // mov v2.s[2], w13 - WORD $0x4e1c1dc2 // mov v2.s[3], w14 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3c9c0122 // stur q2, [x9, #-64] - WORD $0x4ddfc962 // ld1r { v2.4s }, [x11], #4 - WORD $0x6ea14442 // ushl v2.4s, v2.4s, v1.4s - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3c9d0122 // stur q2, [x9, #-48] - WORD $0xb940016a // ldr w10, [x11] - WORD $0x53047d4c // lsr w12, w10, #4 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x53087d4d // lsr w13, w10, #8 - WORD $0x4e0c1d82 // mov v2.s[1], w12 - WORD $0x530c7d4e // lsr w14, w10, #12 - WORD $0x4e141da2 // mov v2.s[2], w13 - WORD $0x4e1c1dc2 // mov v2.s[3], w14 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3c9e0122 // stur q2, [x9, #-32] - WORD $0x4d40c962 // ld1r { v2.4s }, [x11] - WORD $0x9100200b // add x11, x0, #8 - WORD $0x6ea14442 // ushl v2.4s, v2.4s, v1.4s - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3c9f0122 // stur q2, [x9, #-16] - WORD $0xb940080a // ldr w10, [x0, #8] - WORD $0x53047d4c // lsr w12, w10, #4 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x53087d4d // lsr w13, w10, #8 - WORD $0x4e0c1d82 // mov v2.s[1], w12 - WORD $0x530c7d4e // lsr w14, w10, #12 - WORD $0x4e141da2 // mov v2.s[2], w13 - WORD $0x4e1c1dc2 // mov v2.s[3], w14 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3c9f0122 // stur q2, [x9, #-16] - WORD $0xb940080a // ldr w10, [x0, #8] - WORD $0x53047d4c // lsr w12, w10, #4 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x53087d4d // lsr w13, w10, #8 - WORD $0x4e0c1d82 // mov v2.s[1], w12 - WORD $0x530c7d4e // lsr w14, w10, #12 - WORD $0x4e141da2 // mov v2.s[2], w13 - WORD $0x4e1c1dc2 // mov v2.s[3], w14 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3d800122 // str q2, [x9] - WORD $0x4d40c962 // ld1r { v2.4s }, [x11] - WORD $0x9100300b // add x11, x0, #12 - WORD $0x6ea14442 // ushl v2.4s, v2.4s, v1.4s - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3d800522 // str q2, [x9, #16] - WORD $0xb9400c0a // ldr w10, [x0, #12] - WORD $0x91004000 // add x0, x0, #16 - WORD $0x53047d4c // lsr w12, w10, #4 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x53087d4d // lsr w13, w10, #8 - WORD $0x4e0c1d82 // mov v2.s[1], w12 - WORD $0x530c7d4e // lsr w14, w10, #12 - WORD $0x4e141da2 // mov v2.s[2], w13 - WORD $0x4e1c1dc2 // mov v2.s[3], w14 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3d800922 // str q2, [x9, #32] - WORD $0x4d40c962 // ld1r { v2.4s }, [x11] - WORD $0x6ea14442 // ushl v2.4s, v2.4s, v1.4s - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3d800d22 // str q2, [x9, #48] - WORD $0x91020129 //add x9, x9, #128 - BNE LBB0_15 - JMP LBB0_99 -LBB0_16: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - MOVD $0x0000001900000014, R1 // LCPI0_37 - VMOVQ $0x0000000d00000008, $0x0000001700000012, V2 // LCPI0_39 - MOVD $0x0000000600000001, R3 // LCPI0_41 - MOVD $0x0000001500000010, R4 // LCPI0_43 - VMOVQ $0x0000000900000004, $0x000000130000000e, V5 // LCPI0_45 - MOVD $0x0000000700000002, R6 // LCPI0_47 - VMOVQ $0x000000110000000c, $0x0000001b00000016, V7 // LCPI0_117 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f0007e0 // movi v0.4s, #31 - WORD $0x2ea0b821 //neg v1.2s, v1.2s - WORD $0x6ea0b842 //neg v2.4s, v2.4s - WORD $0x2ea0b863 //neg v3.2s, v3.2s - WORD $0x2ea0b884 //neg v4.2s, v4.2s - WORD $0x6ea0b8a5 //neg v5.4s, v5.4s - WORD $0x2ea0b8c6 //neg v6.2s, v6.2s - WORD $0x6ea0b8e7 //neg v7.4s, v7.4s -LBB0_18: - WORD $0xb940000a //ldr w10, [x0] - WORD $0xf1000508 //subs x8, x8, #1 - WORD $0x53057d4b //lsr w11, w10, #5 - WORD $0x1e270150 //fmov s16, w10 - WORD $0x530a7d4c //lsr w12, w10, #10 - WORD $0x4e0c1d70 //mov v16.s[1], w11 - WORD $0x530f7d4d //lsr w13, w10, #15 - WORD $0x4e141d90 //mov v16.s[2], w12 - WORD $0x4e1c1db0 //mov v16.s[3], w13 - WORD $0x4e201e10 //and v16.16b, v16.16b, v0.16b - WORD $0x3c9c0130 // stur q16, [x9, #-64] - WORD $0x29402c0a //ldp w10, w11, [x0] - WORD $0x9100100c //add x12, x0, #4 - WORD $0x0e040d50 // dup v16.2s, w10 - WORD $0x138a796a // extr w10, w11, w10, #30 - WORD $0x2ea14610 // ushl v16.2s, v16.2s, v1.2s - WORD $0x53037d6b // lsr w11, w11, #3 - WORD $0x4e141d50 // mov v16.s[2], w10 - WORD $0x4e1c1d70 // mov v16.s[3], w11 - WORD $0x4e201e10 // and v16.16b, v16.16b, v0.16b - WORD $0x3c9d0130 // stur q16, [x9, #-48] - WORD $0x4d40c990 // ld1r { v16.4s }, [x12] - WORD $0x9100300c // add x12, x0, #12 - WORD $0x6ea24610 // ushl v16.4s, v16.4s, v2.4s - WORD $0x4e201e10 // and v16.16b, v16.16b, v0.16b - WORD $0x3c9e0130 // stur q16, [x9, #-32] - WORD $0x2940ac0a // ldp w10, w11, [x0, #4] - WORD $0x138a716a // extr w10, w11, w10, #28 - WORD $0x0e040d70 // dup v16.2s, w11 - WORD $0x2ea34610 // ushl v16.2s, v16.2s, v3.2s - WORD $0x1e270151 // fmov s17, w10 - WORD $0x6e0c0611 // mov v17.s[1], v16.s[0] - WORD $0x530b7d6b // lsr w11, w11, #11 - WORD $0x6e142611 // mov v17.s[2], v16.s[1] - WORD $0x4e1c1d71 // mov v17.s[3], w11 - WORD $0x4e201e30 // and v16.16b, v17.16b, v0.16b - WORD $0x3c9f0130 // stur q16, [x9, #-16] - WORD $0x29412c0a // ldp w10, w11, [x0, #8] - WORD $0x0e040d50 // dup v16.2s, w10 - WORD $0x531a7d4d // lsr w13, w10, #26 - WORD $0x2ea44610 // ushl v16.2s, v16.2s, v4.2s - WORD $0x138a7d6a // extr w10, w11, w10, #31 - WORD $0x4e141db0 // mov v16.s[2], w13 - WORD $0x4e1c1d50 // mov v16.s[3], w10 - WORD $0x4e201e10 // and v16.16b, v16.16b, v0.16b - WORD $0x3d800130 // str q16, [x9] - WORD $0x4d40c990 // ld1r { v16.4s }, [x12] - WORD $0x9100400c // add x12, x0, #16 - WORD $0x6ea54610 // ushl v16.4s, v16.4s, v5.4s - WORD $0x4e201e10 // and v16.16b, v16.16b, v0.16b - WORD $0x3d800530 // str q16, [x9, #16] - WORD $0x2941ac0a // ldp w10, w11, [x0, #12] - WORD $0x91005000 // add x0, x0, #20 - WORD $0x53187d4d // lsr w13, w10, #24 - WORD $0x138a756a // extr w10, w11, w10, #29 - WORD $0x0e040d70 // dup v16.2s, w11 - WORD $0x1e2701b1 // fmov s17, w13 - WORD $0x2ea64610 // ushl v16.2s, v16.2s, v6.2s - WORD $0x4e0c1d51 // mov v17.s[1], w10 - WORD $0x6e180611 // mov v17.d[1], v16.d[0] - WORD $0x4e201e30 // and v16.16b, v17.16b, v0.16b - WORD $0x3d800930 // str q16, [x9, #32] - WORD $0x4d40c990 // ld1r { v16.4s }, [x12] - WORD $0x6ea74610 // ushl v16.4s, v16.4s, v7.4s - WORD $0x4e201e10 // and v16.16b, v16.16b, v0.16b - WORD $0x3d800d30 // str q16, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - BNE LBB0_18 - JMP LBB0_99 -LBB0_19: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - MOVD $0x0000000a00000004, R1 // LCPI0_51 - MOVD $0x0000001600000010, R2 // LCPI0_53 - VMOVQ $0x0000000e00000008, $0x0000001a00000014, V3 // LCPI0_116 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f0107e0 // movi v0.4s, #63 - WORD $0x2ea0b821 // neg v1.2s, v1.2s - WORD $0x2ea0b842 // neg v2.2s, v2.2s - WORD $0x6ea0b863 // neg v3.4s, v3.4s + WORD $0xb940000b // ldr w11, [x0] + WORD $0xf1000508 // subs x8, x8, #1 + WORD $0xb81c014b // stur w11, [x10, #-64] + WORD $0xb940040b // ldr w11, [x0, #4] + WORD $0xb81c414b // stur w11, [x10, #-60] + WORD $0xb940080b // ldr w11, [x0, #8] + WORD $0xb81c814b // stur w11, [x10, #-56] + WORD $0xb9400c0b // ldr w11, [x0, #12] + WORD $0xb81cc14b // stur w11, [x10, #-52] + WORD $0xb940100b // ldr w11, [x0, #16] + WORD $0xb81d014b // stur w11, [x10, #-48] + WORD $0xb940140b // ldr w11, [x0, #20] + WORD $0xb81d414b // stur w11, [x10, #-44] + WORD $0xb940180b // ldr w11, [x0, #24] + WORD $0xb81d814b // stur w11, [x10, #-40] + WORD $0xb9401c0b // ldr w11, [x0, #28] + WORD $0xb81dc14b // stur w11, [x10, #-36] + WORD $0xb940200b // ldr w11, [x0, #32] + WORD $0xb81e014b // stur w11, [x10, #-32] + WORD $0xb940240b // ldr w11, [x0, #36] + WORD $0xb81e414b // stur w11, [x10, #-28] + WORD $0xb940280b // ldr w11, [x0, #40] + WORD $0xb81e814b // stur w11, [x10, #-24] + WORD $0xb9402c0b // ldr w11, [x0, #44] + WORD $0xb81ec14b // stur w11, [x10, #-20] + WORD $0xb940300b // ldr w11, [x0, #48] + WORD $0xb81f014b // stur w11, [x10, #-16] + WORD $0xb940340b // ldr w11, [x0, #52] + WORD $0xb81f414b // stur w11, [x10, #-12] + WORD $0xb940380b // ldr w11, [x0, #56] + WORD $0xb81f814b // stur w11, [x10, #-8] + WORD $0xb9403c0b // ldr w11, [x0, #60] + WORD $0xb81fc14b // stur w11, [x10, #-4] + WORD $0xb940400b // ldr w11, [x0, #64] + WORD $0xb900014b // str w11, [x10] + WORD $0xb940440b // ldr w11, [x0, #68] + WORD $0xb900054b // str w11, [x10, #4] + WORD $0xb940480b // ldr w11, [x0, #72] + WORD $0xb900094b // str w11, [x10, #8] + WORD $0xb9404c0b // ldr w11, [x0, #76] + WORD $0xb9000d4b // str w11, [x10, #12] + WORD $0xb940500b // ldr w11, [x0, #80] + WORD $0xb900114b // str w11, [x10, #16] + WORD $0xb940540b // ldr w11, [x0, #84] + WORD $0xb900154b // str w11, [x10, #20] + WORD $0xb940580b // ldr w11, [x0, #88] + WORD $0xb900194b // str w11, [x10, #24] + WORD $0xb9405c0b // ldr w11, [x0, #92] + WORD $0xb9001d4b // str w11, [x10, #28] + WORD $0xb940600b // ldr w11, [x0, #96] + WORD $0xb900214b // str w11, [x10, #32] + WORD $0xb940640b // ldr w11, [x0, #100] + WORD $0xb900254b // str w11, [x10, #36] + WORD $0xb940680b // ldr w11, [x0, #104] + WORD $0xb900294b // str w11, [x10, #40] + WORD $0xb9406c0b // ldr w11, [x0, #108] + WORD $0xb9002d4b // str w11, [x10, #44] + WORD $0xb940700b // ldr w11, [x0, #112] + WORD $0xb900314b // str w11, [x10, #48] + WORD $0xb940740b // ldr w11, [x0, #116] + WORD $0xb900354b // str w11, [x10, #52] + WORD $0xb940780b // ldr w11, [x0, #120] + WORD $0xb900394b // str w11, [x10, #56] + WORD $0xb9407c0b // ldr w11, [x0, #124] + WORD $0x91020000 // add x0, x0, #128 + WORD $0xb9003d4b // str w11, [x10, #60] + WORD $0x9102014a // add x10, x10, #128 + BNE LBB0_13 + JMP LBB0_156 + +LBB0_14: + WORD $0x71001c7f // cmp w3, #7 + BGT LBB0_29 + + // %bb.15: + WORD $0x71000c7f // cmp w3, #3 + BGT LBB0_42 + + // %bb.16: + WORD $0x7100047f // cmp w3, #1 + BGT LBB0_65 + + // %bb.17: + WORD $0x34000003 // cbz w3, .LBB0_103 + + // %bb.18: + WORD $0x7100047f // cmp w3, #1 + BNE LBB0_156 + + // %bb.19: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.20: + // WORD $0x90000009 // adrp x9, .LCPI0_201 + // WORD $0x90000008 // adrp x8, .LCPI0_200 + // WORD $0x9000000a // adrp x10, .LCPI0_202 + // WORD $0x9000000b // adrp x11, .LCPI0_206 + WORD $0x4f000427 // movi v7.4s, #1 + VMOVQ LCPI0_201L, LCPI0_201H, V1 + // WORD $0x90000009 // adrp x9, .LCPI0_204 + VMOVD LCPI0_200, V0 + // WORD $0x90000008 // adrp x8, .LCPI0_203 + VMOVQ LCPI0_202L, LCPI0_202H, V2 + // WORD $0x9000000a // adrp x10, .LCPI0_205 + VMOVQ LCPI0_204L, LCPI0_204H, V4 + // WORD $0x90000009 // adrp x9, .LCPI0_207 + VMOVQ LCPI0_203L, LCPI0_203H, V3 + WORD $0x91010348 // add x8, x26, #64 + VMOVQ LCPI0_205L, LCPI0_205H, V5 + WORD $0xaa0003ea // mov x10, x0 + VMOVQ LCPI0_206L, LCPI0_206H, V6 + VMOVQ LCPI0_207L, LCPI0_207H, V16 + WORD $0xaa1303e9 // mov x9, x19 + LBB0_21: - WORD $0xb940000a // ldr w10, [x0] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x53067d4b // lsr w11, w10, #6 - WORD $0x1e270144 // fmov s4, w10 - WORD $0x530c7d4c // lsr w12, w10, #12 - WORD $0x4e0c1d64 // mov v4.s[1], w11 - WORD $0x53127d4d // lsr w13, w10, #18 - WORD $0x4e141d84 // mov v4.s[2], w12 - WORD $0x4e1c1da4 // mov v4.s[3], w13 - WORD $0x4e201c84 // and v4.16b, v4.16b, v0.16b - WORD $0x3c9c0124 // stur q4, [x9, #-64] - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0x53187d4c // lsr w12, w10, #24 - WORD $0x138a796a // extr w10, w11, w10, #30 - WORD $0x0e040d64 // dup v4.2s, w11 - WORD $0x1e270185 // fmov s5, w12 - WORD $0x2ea14484 // ushl v4.2s, v4.2s, v1.2s - WORD $0x4e0c1d45 // mov v5.s[1], w10 - WORD $0x6e180485 // mov v5.d[1], v4.d[0] - WORD $0x4e201ca4 // and v4.16b, v5.16b, v0.16b - WORD $0x3c9d0124 // stur q4, [x9, #-48] - WORD $0x2940ac0a // ldp w10, w11, [x0, #4] - WORD $0x9100200c // add x12, x0, #8 - WORD $0x0e040d44 // dup v4.2s, w10 - WORD $0x138a716a // extr w10, w11, w10, #28 - WORD $0x2ea24484 // ushl v4.2s, v4.2s, v2.2s - WORD $0x53027d6b // lsr w11, w11, #2 - WORD $0x4e141d44 // mov v4.s[2], w10 - WORD $0x4e1c1d64 // mov v4.s[3], w11 - WORD $0x4e201c84 // and v4.16b, v4.16b, v0.16b - WORD $0x3c9e0124 // stur q4, [x9, #-32] - WORD $0x4d40c984 // ld1r { v4.4s }, [x12] - WORD $0x6ea34484 // ushl v4.4s, v4.4s, v3.4s - WORD $0x4e201c84 // and v4.16b, v4.16b, v0.16b - WORD $0x3c9f0124 // stur q4, [x9, #-16] - WORD $0xb9400c0a // ldr w10, [x0, #12] - WORD $0x53067d4b // lsr w11, w10, #6 - WORD $0x1e270144 // fmov s4, w10 - WORD $0x530c7d4c // lsr w12, w10, #12 - WORD $0x4e0c1d64 // mov v4.s[1], w11 - WORD $0x53127d4d // lsr w13, w10, #18 - WORD $0x4e141d84 // mov v4.s[2], w12 - WORD $0x4e1c1da4 // mov v4.s[3], w13 - WORD $0x4e201c84 // and v4.16b, v4.16b, v0.16b - WORD $0x3d800124 // str q4, [x9] - WORD $0x2941ac0a // ldp w10, w11, [x0, #12] - WORD $0x53187d4c // lsr w12, w10, #24 - WORD $0x138a796a // extr w10, w11, w10, #30 - WORD $0x0e040d64 // dup v4.2s, w11 - WORD $0x1e270185 // fmov s5, w12 - WORD $0x2ea14484 // ushl v4.2s, v4.2s, v1.2s - WORD $0x4e0c1d45 // mov v5.s[1], w10 - WORD $0x6e180485 // mov v5.d[1], v4.d[0] - WORD $0x4e201ca4 // and v4.16b, v5.16b, v0.16b - WORD $0x3d800524 // str q4, [x9, #16] - WORD $0x29422c0a // ldp w10, w11, [x0, #16] - WORD $0x9100500c // add x12, x0, #20 - WORD $0x91006000 // add x0, x0, #24 - WORD $0x0e040d44 // dup v4.2s, w10 - WORD $0x138a716a // extr w10, w11, w10, #28 - WORD $0x2ea24484 // ushl v4.2s, v4.2s, v2.2s - WORD $0x53027d6b // lsr w11, w11, #2 - WORD $0x4e141d44 // mov v4.s[2], w10 - WORD $0x4e1c1d64 // mov v4.s[3], w11 - WORD $0x4e201c84 // and v4.16b, v4.16b, v0.16b - WORD $0x3d800924 // str q4, [x9, #32] - WORD $0x4d40c984 // ld1r { v4.4s }, [x12] - WORD $0x6ea34484 // ushl v4.4s, v4.4s, v3.4s - WORD $0x4e201c84 // and v4.16b, v4.16b, v0.16b - WORD $0x3d800d24 // str q4, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - BNE LBB0_21 - JMP LBB0_99 + WORD $0xb940000b // ldr w11, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x0e040d71 // dup v17.2s, w11 + WORD $0x1e270172 // fmov s18, w11 + WORD $0x53037d6b // lsr w11, w11, #3 + WORD $0x6e122252 // ext v18.16b, v18.16b, v18.16b, #4 + WORD $0x2ea04631 // ushl v17.2s, v17.2s, v0.2s + WORD $0x6e116251 // ext v17.16b, v18.16b, v17.16b, #12 + WORD $0x4e1c1d71 // mov v17.s[3], w11 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9c0111 // stur q17, [x8, #-64] + WORD $0x4ddfc951 // ld1r { v17.4s }, [x10], #4 + WORD $0x6ea14631 // ushl v17.4s, v17.4s, v1.4s + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9d0111 // stur q17, [x8, #-48] + WORD $0x4d40c811 // ld1r { v17.4s }, [x0] + WORD $0x6ea24631 // ushl v17.4s, v17.4s, v2.4s + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9e0111 // stur q17, [x8, #-32] + WORD $0x4d40c811 // ld1r { v17.4s }, [x0] + WORD $0x6ea34631 // ushl v17.4s, v17.4s, v3.4s + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9f0111 // stur q17, [x8, #-16] + WORD $0x4d40c811 // ld1r { v17.4s }, [x0] + WORD $0x6ea44631 // ushl v17.4s, v17.4s, v4.4s + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800111 // str q17, [x8] + WORD $0x4d40c811 // ld1r { v17.4s }, [x0] + WORD $0x6ea54631 // ushl v17.4s, v17.4s, v5.4s + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800511 // str q17, [x8, #16] + WORD $0x4d40c811 // ld1r { v17.4s }, [x0] + WORD $0x6ea64631 // ushl v17.4s, v17.4s, v6.4s + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800911 // str q17, [x8, #32] + WORD $0x4d40c811 // ld1r { v17.4s }, [x0] + WORD $0xaa0a03e0 // mov x0, x10 + WORD $0x6eb04631 // ushl v17.4s, v17.4s, v16.4s + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800d11 // str q17, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_21 + JMP LBB0_156 + LBB0_22: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - MOVD $0x0000000d00000006, R1 // LCPI0_59 - MOVD $0x0000000900000002, R2 // LCPI0_61 - MOVD $0x0000001700000010, R3 // LCPI0_63 - MOVD $0x000000130000000c, R4 // LCPI0_65 - MOVD $0x0000000f00000008, R5 // LCPI0_67 - VMOVQ $0x0000000b00000004, $0x0000001900000012, V6 // LCPI0_115 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f0307e0 // movi v0.4s, #127 - WORD $0x2ea0b821 // neg v1.2s, v1.2s - WORD $0x2ea0b842 // neg v2.2s, v2.2s - WORD $0x2ea0b863 // neg v3.2s, v3.2s - WORD $0x2ea0b884 // neg v4.2s, v4.2s - WORD $0x2ea0b8a5 // neg v5.2s, v5.2s - WORD $0x6ea0b8c6 // neg v6.4s, v6.4s -LBB0_24: - WORD $0xb940000a // ldr w10, [x0] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x53077d4b // lsr w11, w10, #7 - WORD $0x1e270147 // fmov s7, w10 - WORD $0x530e7d4c // lsr w12, w10, #14 - WORD $0x4e0c1d67 // mov v7.s[1], w11 - WORD $0x53157d4d // lsr w13, w10, #21 - WORD $0x4e141d87 // mov v7.s[2], w12 - WORD $0x4e1c1da7 // mov v7.s[3], w13 - WORD $0x4e201cf0 // and v16.16b, v7.16b, v0.16b - WORD $0x3c9c0130 // stur q16, [x9, #-64] - WORD $0xb940040a // ldr w10, [x0, #4] - WORD $0x53037d4b // lsr w11, w10, #3 - WORD $0x530a7d4c // lsr w12, w10, #10 - WORD $0x4e0c1d67 // mov v7.s[1], w11 - WORD $0x53117d4a // lsr w10, w10, #17 - WORD $0x4e141d87 // mov v7.s[2], w12 - WORD $0x4e1c1d47 // mov v7.s[3], w10 - WORD $0x4e201ce7 // and v7.16b, v7.16b, v0.16b - WORD $0x3c9d0127 // stur q7, [x9, #-48] - WORD $0x2940ac0a // ldp w10, w11, [x0, #4] - WORD $0x53187d4c // lsr w12, w10, #24 - WORD $0x138a7d6a // extr w10, w11, w10, #31 - WORD $0x0e040d67 // dup v7.2s, w11 - WORD $0x1e270190 // fmov s16, w12 - WORD $0x2ea144e7 // ushl v7.2s, v7.2s, v1.2s - WORD $0x4e0c1d50 // mov v16.s[1], w10 - WORD $0x6e1804f0 // mov v16.d[1], v7.d[0] - WORD $0x4e201e07 // and v7.16b, v16.16b, v0.16b - WORD $0x3c9e0127 // stur q7, [x9, #-32] - WORD $0x29412c0a // ldp w10, w11, [x0, #8] - WORD $0x53147d4c // lsr w12, w10, #20 - WORD $0x138a6d6a // extr w10, w11, w10, #27 - WORD $0x0e040d67 // dup v7.2s, w11 - WORD $0x1e270190 // fmov s16, w12 - WORD $0x2ea244e7 // ushl v7.2s, v7.2s, v2.2s - WORD $0x4e0c1d50 // mov v16.s[1], w10 - WORD $0x6e1804f0 // mov v16.d[1], v7.d[0] - WORD $0x4e201e07 // and v7.16b, v16.16b, v0.16b - WORD $0x3c9f0127 // stur q7, [x9, #-16] - WORD $0x2941ac0a // ldp w10, w11, [x0, #12] - WORD $0x9100600c // add x12, x0, #24 - WORD $0x0e040d47 // dup v7.2s, w10 - WORD $0x138a796a // extr w10, w11, w10, #30 - WORD $0x2ea344e7 // ushl v7.2s, v7.2s, v3.2s - WORD $0x53057d6b // lsr w11, w11, #5 - WORD $0x4e141d47 // mov v7.s[2], w10 - WORD $0x4e1c1d67 // mov v7.s[3], w11 - WORD $0x4e201ce7 // and v7.16b, v7.16b, v0.16b - WORD $0x3d800127 // str q7, [x9] - WORD $0x29422c0a // ldp w10, w11, [x0, #16] - WORD $0x0e040d47 // dup v7.2s, w10 - WORD $0x138a696a // extr w10, w11, w10, #26 - WORD $0x2ea444e7 // ushl v7.2s, v7.2s, v4.2s - WORD $0x53017d6b // lsr w11, w11, #1 - WORD $0x4e141d47 // mov v7.s[2], w10 - WORD $0x4e1c1d67 // mov v7.s[3], w11 - WORD $0x4e201ce7 // and v7.16b, v7.16b, v0.16b - WORD $0x3d800527 // str q7, [x9, #16] - WORD $0x2942ac0a // ldp w10, w11, [x0, #20] - WORD $0x91007000 // add x0, x0, #28 - WORD $0x0e040d47 // dup v7.2s, w10 - WORD $0x53167d4d // lsr w13, w10, #22 - WORD $0x2ea544e7 // ushl v7.2s, v7.2s, v5.2s - WORD $0x138a756a // extr w10, w11, w10, #29 - WORD $0x4e141da7 // mov v7.s[2], w13 - WORD $0x4e1c1d47 // mov v7.s[3], w10 - WORD $0x4e201ce7 // and v7.16b, v7.16b, v0.16b - WORD $0x3d800927 // str q7, [x9, #32] - WORD $0x4d40c987 // ld1r { v7.4s }, [x12] - WORD $0x6ea644e7 // ushl v7.4s, v7.4s, v6.4s - WORD $0x4e201ce7 // and v7.16b, v7.16b, v0.16b - WORD $0x3d800d27 // str q7, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - BNE LBB0_24 - JMP LBB0_99 -LBB0_25: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x6f00e620 // movi v0.2d, #0x0000ff000000ff -LBB0_27: - WORD $0xb940000a // ldr w10, [x0] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x53087d4b // lsr w11, w10, #8 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x4e0c1d61 // mov v1.s[1], w11 - WORD $0x53187d4d // lsr w13, w10, #24 - WORD $0x4e141d81 // mov v1.s[2], w12 - WORD $0x4e1c1da1 // mov v1.s[3], w13 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3c9c0121 // stur q1, [x9, #-64] - WORD $0xb940040a // ldr w10, [x0, #4] - WORD $0x53087d4b // lsr w11, w10, #8 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x4e0c1d61 // mov v1.s[1], w11 - WORD $0x53187d4d // lsr w13, w10, #24 - WORD $0x4e141d81 // mov v1.s[2], w12 - WORD $0x4e1c1da1 // mov v1.s[3], w13 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3c9d0121 // stur q1, [x9, #-48] - WORD $0xb940080a // ldr w10, [x0, #8] - WORD $0x53087d4b // lsr w11, w10, #8 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x4e0c1d61 // mov v1.s[1], w11 - WORD $0x53187d4d // lsr w13, w10, #24 - WORD $0x4e141d81 // mov v1.s[2], w12 - WORD $0x4e1c1da1 // mov v1.s[3], w13 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3c9e0121 // stur q1, [x9, #-32] - WORD $0xb9400c0a // ldr w10, [x0, #12] - WORD $0x53087d4b // lsr w11, w10, #8 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x4e0c1d61 // mov v1.s[1], w11 - WORD $0x53187d4d // lsr w13, w10, #24 - WORD $0x4e141d81 // mov v1.s[2], w12 - WORD $0x4e1c1da1 // mov v1.s[3], w13 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3c9f0121 // stur q1, [x9, #-16] - WORD $0xb940100a // ldr w10, [x0, #16] - WORD $0x53087d4b // lsr w11, w10, #8 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x4e0c1d61 // mov v1.s[1], w11 - WORD $0x53187d4d // lsr w13, w10, #24 - WORD $0x4e141d81 // mov v1.s[2], w12 - WORD $0x4e1c1da1 // mov v1.s[3], w13 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3d800121 // str q1, [x9] - WORD $0xb940140a // ldr w10, [x0, #20] - WORD $0x53087d4b // lsr w11, w10, #8 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x4e0c1d61 // mov v1.s[1], w11 - WORD $0x53187d4d // lsr w13, w10, #24 - WORD $0x4e141d81 // mov v1.s[2], w12 - WORD $0x4e1c1da1 // mov v1.s[3], w13 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3d800521 // str q1, [x9, #16] - WORD $0xb940180a // ldr w10, [x0, #24] - WORD $0x53087d4b // lsr w11, w10, #8 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x4e0c1d61 // mov v1.s[1], w11 - WORD $0x53187d4d // lsr w13, w10, #24 - WORD $0x4e141d81 // mov v1.s[2], w12 - WORD $0x4e1c1da1 // mov v1.s[3], w13 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3d800921 // str q1, [x9, #32] - WORD $0xb9401c0a // ldr w10, [x0, #28] - WORD $0x91008000 // add x0, x0, #32 - WORD $0x53087d4b // lsr w11, w10, #8 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x4e0c1d61 // mov v1.s[1], w11 - WORD $0x53187d4d // lsr w13, w10, #24 - WORD $0x4e141d81 // mov v1.s[2], w12 - WORD $0x4e1c1da1 // mov v1.s[3], w13 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3d800d21 // str q1, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - BNE LBB0_27 - JMP LBB0_99 + WORD $0x71004c7f // cmp w3, #19 + BGT LBB0_48 + + // %bb.23: + WORD $0x7100447f // cmp w3, #17 + BGT LBB0_70 + + // %bb.24: + WORD $0x7100407f // cmp w3, #16 + BEQ LBB0_106 + + // %bb.25: + WORD $0x7100447f // cmp w3, #17 + BNE LBB0_156 + + // %bb.26: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.27: + WORD $0x4f00d420 // movi v0.4s, #1, msl #16 + WORD $0x91010348 // add x8, x26, #64 + WORD $0xaa1303e9 // mov x9, x19 + LBB0_28: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - MOVD $0x0000001100000008, R1 // LCPI0_73 - MOVD $0x000000150000000C, R2 // LCPI0_75 - MOVD $0x0000000b00000002, R3 // LCPI0_77 - MOVD $0x0000000f00000006, R4 // LCPI0_79 - MOVD $0x0000000a00000001, R5 // LCPI0_81 - MOVD $0x0000000e00000005, R6 // LCPI0_83 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f00c420 // movi v0.4s, #1, msl #8 - WORD $0x2ea0b821 // neg v1.2s, v1.2s - WORD $0x2ea0b842 // neg v2.2s, v2.2s - WORD $0x2ea0b863 // neg v3.2s, v3.2s - WORD $0x2ea0b884 // neg v4.2s, v4.2s - WORD $0x2ea0b8a5 // neg v5.2s, v5.2s - WORD $0x2ea0b8c6 // neg v6.2s, v6.2s -LBB0_30: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x53097d4c // lsr w12, w10, #9 - WORD $0x1e270147 // fmov s7, w10 - WORD $0x53127d4d // lsr w13, w10, #18 - WORD $0x4e0c1d87 // mov v7.s[1], w12 - WORD $0x138a6d6b // extr w11, w11, w10, #27 - WORD $0x4e141da7 // mov v7.s[2], w13 - WORD $0x4e1c1d67 // mov v7.s[3], w11 - WORD $0x4e201cf0 // and v16.16b, v7.16b, v0.16b - WORD $0x3c9c0130 // stur q16, [x9, #-64] - WORD $0x2940ac0a // ldp w10, w11, [x0, #4] - WORD $0x530d7d4c // lsr w12, w10, #13 - WORD $0x53167d4d // lsr w13, w10, #22 - WORD $0x4e0c1d87 // mov v7.s[1], w12 - WORD $0x138a7d6a // extr w10, w11, w10, #31 - WORD $0x4e141da7 // mov v7.s[2], w13 - WORD $0x4e1c1d47 // mov v7.s[3], w10 - WORD $0x4e201ce7 // and v7.16b, v7.16b, v0.16b - WORD $0x3c9d0127 // stur q7, [x9, #-48] - WORD $0x29412c0a // ldp w10, w11, [x0, #8] - WORD $0x0e040d47 // dup v7.2s, w10 - WORD $0x138a696a // extr w10, w11, w10, #26 - WORD $0x2ea144e7 // ushl v7.2s, v7.2s, v1.2s - WORD $0x53037d6b // lsr w11, w11, #3 - WORD $0x4e141d47 // mov v7.s[2], w10 - WORD $0x4e1c1d67 // mov v7.s[3], w11 - WORD $0x4e201ce7 // and v7.16b, v7.16b, v0.16b - WORD $0x3c9e0127 // stur q7, [x9, #-32] - WORD $0x2941ac0a // ldp w10, w11, [x0, #12] - WORD $0x0e040d47 // dup v7.2s, w10 - WORD $0x138a796a // extr w10, w11, w10, #30 - WORD $0x2ea244e7 // ushl v7.2s, v7.2s, v2.2s - WORD $0x53077d6b // lsr w11, w11, #7 - WORD $0x4e141d47 // mov v7.s[2], w10 - WORD $0x4e1c1d67 // mov v7.s[3], w11 - WORD $0x4e201ce7 // and v7.16b, v7.16b, v0.16b - WORD $0x3c9f0127 // stur q7, [x9, #-16] - WORD $0x29422c0a // ldp w10, w11, [x0, #16] - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x138a656a // extr w10, w11, w10, #25 - WORD $0x0e040d67 // dup v7.2s, w11 - WORD $0x1e270190 // fmov s16, w12 - WORD $0x2ea344e7 // ushl v7.2s, v7.2s, v3.2s - WORD $0x4e0c1d50 // mov v16.s[1], w10 - WORD $0x6e1804f0 // mov v16.d[1], v7.d[0] - WORD $0x4e201e07 // and v7.16b, v16.16b, v0.16b - WORD $0x3d800127 // str q7, [x9] - WORD $0x2942ac0a // ldp w10, w11, [x0, #20] - WORD $0x53147d4c // lsr w12, w10, #20 - WORD $0x138a756a // extr w10, w11, w10, #29 - WORD $0x0e040d67 // dup v7.2s, w11 - WORD $0x1e270190 // fmov s16, w12 - WORD $0x2ea444e7 // ushl v7.2s, v7.2s, v4.2s - WORD $0x4e0c1d50 // mov v16.s[1], w10 - WORD $0x6e1804f0 // mov v16.d[1], v7.d[0] - WORD $0x4e201e07 // and v7.16b, v16.16b, v0.16b - WORD $0x3d800527 // str q7, [x9, #16] - WORD $0x29432c0a // ldp w10, w11, [x0, #24] - WORD $0x138a616a // extr w10, w11, w10, #24 - WORD $0x0e040d67 // dup v7.2s, w11 - WORD $0x2ea544e7 // ushl v7.2s, v7.2s, v5.2s - WORD $0x1e270150 // fmov s16, w10 - WORD $0x6e0c04f0 // mov v16.s[1], v7.s[0] - WORD $0x53137d6b // lsr w11, w11, #19 - WORD $0x6e1424f0 // mov v16.s[2], v7.s[1] - WORD $0x4e1c1d70 // mov v16.s[3], w11 - WORD $0x4e201e07 // and v7.16b, v16.16b, v0.16b - WORD $0x3d800927 // str q7, [x9, #32] - WORD $0x2943ac0a // ldp w10, w11, [x0, #28] - WORD $0x91009000 // add x0, x0, #36 - WORD $0x138a716a // extr w10, w11, w10, #28 - WORD $0x0e040d67 // dup v7.2s, w11 - WORD $0x2ea644e7 // ushl v7.2s, v7.2s, v6.2s - WORD $0x1e270150 // fmov s16, w10 - WORD $0x6e0c04f0 // mov v16.s[1], v7.s[0] - WORD $0x53177d6b // lsr w11, w11, #23 - WORD $0x6e1424f0 // mov v16.s[2], v7.s[1] - WORD $0x4e1c1d70 // mov v16.s[3], w11 - WORD $0x4e201e07 // and v7.16b, v16.16b, v0.16b - WORD $0x3d800d27 // str q7, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - BNE LBB0_30 - JMP LBB0_99 -LBB0_31: - WORD $0x7100805f //cmp w2, #32 - BLT LBB0_99 - MOVD $0x0000000e00000004, R1 // LCPI0_87 - MOVD $0x0000000c00000002, R2 // LCPI0_89 - MOVD $0x0000001200000008, R3 // LCPI0_85 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f00c460 // movi v0.4s, #3, msl #8 - WORD $0x2ea0b821 // neg v1.2s, v1.2s - WORD $0x2ea0b842 // neg v2.2s, v2.2s - WORD $0x2ea0b863 // neg v3.2s, v3.2s -LBB0_33: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x530a7d4c // lsr w12, w10, #10 - WORD $0x1e270144 // fmov s4, w10 - WORD $0x53147d4d // lsr w13, w10, #20 - WORD $0x4e0c1d84 // mov v4.s[1], w12 - WORD $0x138a796b // extr w11, w11, w10, #30 - WORD $0x4e141da4 // mov v4.s[2], w13 - WORD $0x4e1c1d64 // mov v4.s[3], w11 - WORD $0x4e201c85 // and v5.16b, v4.16b, v0.16b - WORD $0x3c9c0125 // stur q5, [x9, #-64] - WORD $0x2940ac0a // ldp w10, w11, [x0, #4] - WORD $0x53127d4c // lsr w12, w10, #18 - WORD $0x138a716a // extr w10, w11, w10, #28 - WORD $0x4e0c1d84 // mov v4.s[1], w12 - WORD $0x53067d6b // lsr w11, w11, #6 - WORD $0x4e141d44 // mov v4.s[2], w10 - WORD $0x4e1c1d64 // mov v4.s[3], w11 - WORD $0x4e201c84 // and v4.16b, v4.16b, v0.16b - WORD $0x3c9d0124 // stur q4, [x9, #-48] - WORD $0x29412c0a // ldp w10, w11, [x0, #8] - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x138a696a // extr w10, w11, w10, #26 - WORD $0x0e040d64 // dup v4.2s, w11 - WORD $0x1e270185 // fmov s5, w12 - WORD $0x2ea14484 // ushl v4.2s, v4.2s, v1.2s - WORD $0x4e0c1d45 // mov v5.s[1], w10 - WORD $0x6e180485 // mov v5.d[1], v4.d[0] - WORD $0x4e201ca4 // and v4.16b, v5.16b, v0.16b - WORD $0x3c9e0124 // stur q4, [x9, #-32] - WORD $0x2941ac0a // ldp w10, w11, [x0, #12] - WORD $0x138a616a // extr w10, w11, w10, #24 - WORD $0x0e040d64 // dup v4.2s, w11 - WORD $0x2ea24484 // ushl v4.2s, v4.2s, v2.2s - WORD $0x1e270145 // fmov s5, w10 - WORD $0x6e0c0485 // mov v5.s[1], v4.s[0] - WORD $0x53167d6b // lsr w11, w11, #22 - WORD $0x6e142485 // mov v5.s[2], v4.s[1] - WORD $0x4e1c1d65 // mov v5.s[3], w11 - WORD $0x4e201ca4 // and v4.16b, v5.16b, v0.16b - WORD $0x3c9f0124 // stur q4, [x9, #-16] - WORD $0x2942ac0a // ldp w10, w11, [x0, #20] - WORD $0x530a7d4c // lsr w12, w10, #10 - WORD $0x1e270144 // fmov s4, w10 - WORD $0x53147d4d // lsr w13, w10, #20 - WORD $0x4e0c1d84 // mov v4.s[1], w12 - WORD $0x138a796b // extr w11, w11, w10, #30 - WORD $0x4e141da4 // mov v4.s[2], w13 - WORD $0x4e1c1d64 // mov v4.s[3], w11 - WORD $0x4e201c84 // and v4.16b, v4.16b, v0.16b - WORD $0x3d800124 // str q4, [x9] - WORD $0x29432c0a // ldp w10, w11, [x0, #24] - WORD $0x0e040d44 // dup v4.2s, w10 - WORD $0x138a716a // extr w10, w11, w10, #28 - WORD $0x2ea34484 // ushl v4.2s, v4.2s, v3.2s - WORD $0x53067d6b // lsr w11, w11, #6 - WORD $0x4e141d44 // mov v4.s[2], w10 - WORD $0x4e1c1d64 // mov v4.s[3], w11 - WORD $0x4e201c84 // and v4.16b, v4.16b, v0.16b - WORD $0x3d800524 // str q4, [x9, #16] - WORD $0x2943ac0a // ldp w10, w11, [x0, #28] - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x138a696a // extr w10, w11, w10, #26 - WORD $0x0e040d64 // dup v4.2s, w11 - WORD $0x1e270185 // fmov s5, w12 - WORD $0x2ea14484 // ushl v4.2s, v4.2s, v1.2s - WORD $0x4e0c1d45 // mov v5.s[1], w10 - WORD $0x6e180485 // mov v5.d[1], v4.d[0] - WORD $0x4e201ca4 // and v4.16b, v5.16b, v0.16b - WORD $0x3d800924 // str q4, [x9, #32] - WORD $0x29442c0a // ldp w10, w11, [x0, #32] - WORD $0x9100a000 // add x0, x0, #40 - WORD $0x138a616a // extr w10, w11, w10, #24 - WORD $0x0e040d64 // dup v4.2s, w11 - WORD $0x2ea24484 // ushl v4.2s, v4.2s, v2.2s - WORD $0x1e270145 // fmov s5, w10 - WORD $0x6e0c0485 // mov v5.s[1], v4.s[0] - WORD $0x53167d6b // lsr w11, w11, #22 - WORD $0x6e142485 // mov v5.s[2], v4.s[1] - WORD $0x4e1c1d65 // mov v5.s[3], w11 - WORD $0x4e201ca4 // and v4.16b, v5.16b, v0.16b - WORD $0x3d800d24 // str q4, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - BNE LBB0_33 - JMP LBB0_99 -LBB0_34: - WORD $0x7100805f // cmp w2, #32 - BL LBB0_99 - MOVD $0x0000000e00000003, R1 // LCPI0_93 - MOVD $0x0000000f00000004, R2 // LCPI0_95 - MOVD $0x0000001100000006, R3 // LCPI0_97 - MOVD $0x0000001200000007, R4 // LCPI0_99 - MOVD $0x0000001300000008, R5 // LCPI0_101 - MOVD $0x000000150000000a, R6 // LCPI0_114 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f00c4e0 // movi v0.4s, #7, msl #8 - WORD $0x2ea0b821 // neg v1.2s, v1.2s - WORD $0x2ea0b842 // neg v2.2s, v2.2s - WORD $0x2ea0b863 // neg v3.2s, v3.2s - WORD $0x2ea0b884 // neg v4.2s, v4.2s - WORD $0x2ea0b8a5 // neg v5.2s, v5.2s - WORD $0x2ea0b8c6 // neg v6.2s, v6.2s + WORD $0x29402c0a // ldp w10, w11, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x138a456c // extr w12, w11, w10, #17 + WORD $0x1e270141 // fmov s1, w10 + WORD $0x53027d6a // lsr w10, w11, #2 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0xb940080c // ldr w12, [x0, #8] + WORD $0x4e141d41 // mov v1.s[2], w10 + WORD $0x138b4d8a // extr w10, w12, w11, #19 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3c9c0101 // stur q1, [x8, #-64] + WORD $0x29412c0a // ldp w10, w11, [x0, #8] + WORD $0x53047d4c // lsr w12, w10, #4 + WORD $0x138a556a // extr w10, w11, w10, #21 + WORD $0x1e270181 // fmov s1, w12 + WORD $0xb940100c // ldr w12, [x0, #16] + WORD $0x4e0c1d41 // mov v1.s[1], w10 + WORD $0x53067d6a // lsr w10, w11, #6 + WORD $0x4e141d41 // mov v1.s[2], w10 + WORD $0x138b5d8a // extr w10, w12, w11, #23 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3c9d0101 // stur q1, [x8, #-48] + WORD $0x29422c0a // ldp w10, w11, [x0, #16] + WORD $0x53087d4c // lsr w12, w10, #8 + WORD $0x138a656a // extr w10, w11, w10, #25 + WORD $0x1e270181 // fmov s1, w12 + WORD $0xb940180c // ldr w12, [x0, #24] + WORD $0x4e0c1d41 // mov v1.s[1], w10 + WORD $0x530a7d6a // lsr w10, w11, #10 + WORD $0x4e141d41 // mov v1.s[2], w10 + WORD $0x138b6d8a // extr w10, w12, w11, #27 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3c9e0101 // stur q1, [x8, #-32] + WORD $0x29432c0a // ldp w10, w11, [x0, #24] + WORD $0x530c7d4c // lsr w12, w10, #12 + WORD $0x138a756a // extr w10, w11, w10, #29 + WORD $0x1e270181 // fmov s1, w12 + WORD $0xb940200c // ldr w12, [x0, #32] + WORD $0x4e0c1d41 // mov v1.s[1], w10 + WORD $0x530e7d6a // lsr w10, w11, #14 + WORD $0x4e141d41 // mov v1.s[2], w10 + WORD $0x138b7d8a // extr w10, w12, w11, #31 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3c9f0101 // stur q1, [x8, #-16] + WORD $0x29442c0a // ldp w10, w11, [x0, #32] + WORD $0x138a416a // extr w10, w11, w10, #16 + WORD $0x53017d6c // lsr w12, w11, #1 + WORD $0x1e270141 // fmov s1, w10 + WORD $0xb940280a // ldr w10, [x0, #40] + WORD $0x138b494b // extr w11, w10, w11, #18 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0x53037d4a // lsr w10, w10, #3 + WORD $0x4e141d61 // mov v1.s[2], w11 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3d800101 // str q1, [x8] + WORD $0x29452c0a // ldp w10, w11, [x0, #40] + WORD $0x138a516a // extr w10, w11, w10, #20 + WORD $0x53057d6c // lsr w12, w11, #5 + WORD $0x1e270141 // fmov s1, w10 + WORD $0xb940300a // ldr w10, [x0, #48] + WORD $0x138b594b // extr w11, w10, w11, #22 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0x53077d4a // lsr w10, w10, #7 + WORD $0x4e141d61 // mov v1.s[2], w11 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3d800501 // str q1, [x8, #16] + WORD $0x29462c0a // ldp w10, w11, [x0, #48] + WORD $0x138a616a // extr w10, w11, w10, #24 + WORD $0x53097d6c // lsr w12, w11, #9 + WORD $0x1e270141 // fmov s1, w10 + WORD $0xb940380a // ldr w10, [x0, #56] + WORD $0x138b694b // extr w11, w10, w11, #26 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0x530b7d4a // lsr w10, w10, #11 + WORD $0x4e141d61 // mov v1.s[2], w11 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3d800901 // str q1, [x8, #32] + WORD $0x29472c0a // ldp w10, w11, [x0, #56] + WORD $0x138a716a // extr w10, w11, w10, #28 + WORD $0x530d7d6c // lsr w12, w11, #13 + WORD $0x1e270141 // fmov s1, w10 + WORD $0xb940400a // ldr w10, [x0, #64] + WORD $0x91011000 // add x0, x0, #68 + WORD $0x138b794b // extr w11, w10, w11, #30 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0x530f7d4a // lsr w10, w10, #15 + WORD $0x4e141d61 // mov v1.s[2], w11 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3d800d01 // str q1, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_28 + JMP LBB0_156 + +LBB0_29: + WORD $0x71002c7f // cmp w3, #11 + BGT LBB0_54 + + // %bb.30: + WORD $0x7100247f // cmp w3, #9 + BGT LBB0_75 + + // %bb.31: + WORD $0x7100207f // cmp w3, #8 + BEQ LBB0_109 + + // %bb.32: + WORD $0x7100247f // cmp w3, #9 + BNE LBB0_156 + + // %bb.33: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.34: + // WORD $0x90000008 // adrp x8, .LCPI0_157 + // WORD $0x90000009 // adrp x9, .LCPI0_158 + // WORD $0x9000000a // adrp x10, .LCPI0_159 + WORD $0x4f00c427 // movi v7.4s, #1, msl #8 + VMOVD LCPI0_157, V0 + // WORD $0x90000008 // adrp x8, .LCPI0_160 + VMOVD LCPI0_158, V1 + // WORD $0x90000009 // adrp x9, .LCPI0_161 + VMOVD LCPI0_159, V2 + // WORD $0x9000000a // adrp x10, .LCPI0_162 + VMOVD LCPI0_160, V3 + // WORD $0x90000008 // adrp x8, .LCPI0_163 + VMOVD LCPI0_161, V4 + // WORD $0x90000009 // adrp x9, .LCPI0_164 + VMOVD LCPI0_162, V5 + VMOVD LCPI0_163, V6 + WORD $0x91010348 // add x8, x26, #64 + VMOVD LCPI0_164, V16 + WORD $0xaa1303e9 // mov x9, x19 + +LBB0_35: + WORD $0x29402c0a // ldp w10, w11, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x0e040d51 // dup v17.2s, w10 + WORD $0x1e270152 // fmov s18, w10 + WORD $0x138a6d6a // extr w10, w11, w10, #27 + WORD $0x6e122252 // ext v18.16b, v18.16b, v18.16b, #4 + WORD $0x2ea04631 // ushl v17.2s, v17.2s, v0.2s + WORD $0x6e116251 // ext v17.16b, v18.16b, v17.16b, #12 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9c0111 // stur q17, [x8, #-64] + WORD $0x2940ac0a // ldp w10, w11, [x0, #4] + WORD $0x0e040d51 // dup v17.2s, w10 + WORD $0x53167d4c // lsr w12, w10, #22 + WORD $0x138a7d6a // extr w10, w11, w10, #31 + WORD $0x2ea14631 // ushl v17.2s, v17.2s, v1.2s + WORD $0x4e141d91 // mov v17.s[2], w12 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9d0111 // stur q17, [x8, #-48] + WORD $0x29412c0a // ldp w10, w11, [x0, #8] + WORD $0x0e040d51 // dup v17.2s, w10 + WORD $0x138a696a // extr w10, w11, w10, #26 + WORD $0x2ea24631 // ushl v17.2s, v17.2s, v2.2s + WORD $0x4e141d51 // mov v17.s[2], w10 + WORD $0x53037d6a // lsr w10, w11, #3 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9e0111 // stur q17, [x8, #-32] + WORD $0x2941ac0a // ldp w10, w11, [x0, #12] + WORD $0x0e040d51 // dup v17.2s, w10 + WORD $0x138a796a // extr w10, w11, w10, #30 + WORD $0x2ea34631 // ushl v17.2s, v17.2s, v3.2s + WORD $0x4e141d51 // mov v17.s[2], w10 + WORD $0x53077d6a // lsr w10, w11, #7 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9f0111 // stur q17, [x8, #-16] + WORD $0x29422c0a // ldp w10, w11, [x0, #16] + WORD $0x53107d4c // lsr w12, w10, #16 + WORD $0x0e040d71 // dup v17.2s, w11 + WORD $0x138a656a // extr w10, w11, w10, #25 + WORD $0x1e270192 // fmov s18, w12 + WORD $0x2ea44631 // ushl v17.2s, v17.2s, v4.2s + WORD $0x4e0c1d52 // mov v18.s[1], w10 + WORD $0x6e180632 // mov v18.d[1], v17.d[0] + WORD $0x4e271e51 // and v17.16b, v18.16b, v7.16b + WORD $0x3d800111 // str q17, [x8] + WORD $0x2942ac0a // ldp w10, w11, [x0, #20] + WORD $0x53147d4c // lsr w12, w10, #20 + WORD $0x0e040d71 // dup v17.2s, w11 + WORD $0x138a756a // extr w10, w11, w10, #29 + WORD $0x1e270192 // fmov s18, w12 + WORD $0x2ea54631 // ushl v17.2s, v17.2s, v5.2s + WORD $0x4e0c1d52 // mov v18.s[1], w10 + WORD $0x6e180632 // mov v18.d[1], v17.d[0] + WORD $0x4e271e51 // and v17.16b, v18.16b, v7.16b + WORD $0x3d800511 // str q17, [x8, #16] + WORD $0x29432c0a // ldp w10, w11, [x0, #24] + WORD $0x138a616a // extr w10, w11, w10, #24 + WORD $0x0e040d71 // dup v17.2s, w11 + WORD $0x1e270152 // fmov s18, w10 + WORD $0x53137d6a // lsr w10, w11, #19 + WORD $0x2ea64631 // ushl v17.2s, v17.2s, v6.2s + WORD $0x6e122252 // ext v18.16b, v18.16b, v18.16b, #4 + WORD $0x6e116251 // ext v17.16b, v18.16b, v17.16b, #12 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800911 // str q17, [x8, #32] + WORD $0x2943ac0a // ldp w10, w11, [x0, #28] + WORD $0x91009000 // add x0, x0, #36 + WORD $0x138a716a // extr w10, w11, w10, #28 + WORD $0x0e040d71 // dup v17.2s, w11 + WORD $0x1e270152 // fmov s18, w10 + WORD $0x53177d6a // lsr w10, w11, #23 + WORD $0x2eb04631 // ushl v17.2s, v17.2s, v16.2s + WORD $0x6e122252 // ext v18.16b, v18.16b, v18.16b, #4 + WORD $0x6e116251 // ext v17.16b, v18.16b, v17.16b, #12 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800d11 // str q17, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_35 + JMP LBB0_156 + LBB0_36: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x530b7d4c // lsr w12, w10, #11 - WORD $0x1e270147 // fmov s7, w10 - WORD $0x138a596d // extr w13, w11, w10, #22 - WORD $0x4e0c1d87 // mov v7.s[1], w12 - WORD $0x53017d6b // lsr w11, w11, #1 - WORD $0x4e141da7 // mov v7.s[2], w13 - WORD $0x4e1c1d67 // mov v7.s[3], w11 - WORD $0x4e201cf0 // and v16.16b, v7.16b, v0.16b - WORD $0x3c9c0130 // stur q16, [x9, #-64] - WORD $0x2940ac0a // ldp w10, w11, [x0, #4] - WORD $0x138a5d6a // extr w10, w11, w10, #23 - WORD $0x53027d6c // lsr w12, w11, #2 - WORD $0x4e0c1d47 // mov v7.s[1], w10 - WORD $0x530d7d6b // lsr w11, w11, #13 - WORD $0x4e141d87 // mov v7.s[2], w12 - WORD $0x4e1c1d67 // mov v7.s[3], w11 - WORD $0x4e201ce7 // and v7.16b, v7.16b, v0.16b - WORD $0x3c9d0127 // stur q7, [x9, #-48] - WORD $0x29412c0a // ldp w10, w11, [x0, #8] - WORD $0xb940100c // ldr w12, [x0, #16] - WORD $0x138a616a // extr w10, w11, w10, #24 - WORD $0x0e040d67 // dup v7.2s, w11 - WORD $0x2ea144e7 // ushl v7.2s, v7.2s, v1.2s - WORD $0x1e270150 // fmov s16, w10 - WORD $0x6e0c04f0 // mov v16.s[1], v7.s[0] - WORD $0x138b658b // extr w11, w12, w11, #25 - WORD $0x6e1424f0 // mov v16.s[2], v7.s[1] - WORD $0x4e1c1d70 // mov v16.s[3], w11 - WORD $0x4e201e07 // and v7.16b, v16.16b, v0.16b - WORD $0x3c9e0127 // stur q7, [x9, #-32] - WORD $0x29422c0a // ldp w10, w11, [x0, #16] - WORD $0x0e040d47 // dup v7.2s, w10 - WORD $0x138a696a // extr w10, w11, w10, #26 - WORD $0x2ea244e7 // ushl v7.2s, v7.2s, v2.2s - WORD $0x53057d6b // lsr w11, w11, #5 - WORD $0x4e141d47 // mov v7.s[2], w10 - WORD $0x4e1c1d67 // mov v7.s[3], w11 - WORD $0x4e201ce7 // and v7.16b, v7.16b, v0.16b - WORD $0x3c9f0127 // stur q7, [x9, #-16] - WORD $0x2942ac0a // ldp w10, w11, [x0, #20] - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x138a6d6a // extr w10, w11, w10, #27 - WORD $0x0e040d67 // dup v7.2s, w11 - WORD $0x1e270190 // fmov s16, w12 - WORD $0x2ea344e7 // ushl v7.2s, v7.2s, v3.2s - WORD $0x4e0c1d50 // mov v16.s[1], w10 - WORD $0x6e1804f0 // mov v16.d[1], v7.d[0] - WORD $0x4e201e07 // and v7.16b, v16.16b, v0.16b - WORD $0x3d800127 // str q7, [x9] - WORD $0x29432c0a // ldp w10, w11, [x0, #24] - WORD $0xb940200c // ldr w12, [x0, #32] - WORD $0x138a716a // extr w10, w11, w10, #28 - WORD $0x0e040d67 // dup v7.2s, w11 - WORD $0x2ea444e7 // ushl v7.2s, v7.2s, v4.2s - WORD $0x1e270150 // fmov s16, w10 - WORD $0x6e0c04f0 // mov v16.s[1], v7.s[0] - WORD $0x138b758b // extr w11, w12, w11, #29 - WORD $0x6e1424f0 // mov v16.s[2], v7.s[1] - WORD $0x4e1c1d70 // mov v16.s[3], w11 - WORD $0x4e201e07 // and v7.16b, v16.16b, v0.16b - WORD $0x3d800527 // str q7, [x9, #16] - WORD $0x29442c0a // ldp w10, w11, [x0, #32] - WORD $0x0e040d47 // dup v7.2s, w10 - WORD $0x138a796a // extr w10, w11, w10, #30 - WORD $0x2ea544e7 // ushl v7.2s, v7.2s, v5.2s - WORD $0x53097d6b // lsr w11, w11, #9 - WORD $0x4e141d47 // mov v7.s[2], w10 - WORD $0x4e1c1d67 // mov v7.s[3], w11 - WORD $0x4e201ce7 // and v7.16b, v7.16b, v0.16b - WORD $0x3d800927 // str q7, [x9, #32] - WORD $0x2944ac0a // ldp w10, w11, [x0, #36] - WORD $0x9100b000 // add x0, x0, #44 - WORD $0x53147d4c // lsr w12, w10, #20 - WORD $0x138a7d6a // extr w10, w11, w10, #31 - WORD $0x0e040d67 // dup v7.2s, w11 - WORD $0x1e270190 // fmov s16, w12 - WORD $0x2ea644e7 // ushl v7.2s, v7.2s, v6.2s - WORD $0x4e0c1d50 // mov v16.s[1], w10 - WORD $0x6e1804f0 // mov v16.d[1], v7.d[0] - WORD $0x4e201e07 // and v7.16b, v16.16b, v0.16b - WORD $0x3d800d27 // str q7, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - BNE LBB0_36 - JMP LBB0_99 -LBB0_37: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - MOVD $0x0000000e00000003, R1 // LCPI0_113 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f00c5e0 // movi v0.4s, #15, msl #8 - WORD $0x2ea0b821 // neg v1.2s, v1.2s -LBB0_39: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x530c7d4c // lsr w12, w10, #12 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x138a616d // extr w13, w11, w10, #24 - WORD $0x4e0c1d82 // mov v2.s[1], w12 - WORD $0x53047d6b // lsr w11, w11, #4 - WORD $0x4e141da2 // mov v2.s[2], w13 - WORD $0x4e1c1d62 // mov v2.s[3], w11 - WORD $0x4e201c43 // and v3.16b, v2.16b, v0.16b - WORD $0x3c9c0123 // stur q3, [x9, #-64] - WORD $0x2940ac0a // ldp w10, w11, [x0, #4] - WORD $0x138a716a // extr w10, w11, w10, #28 - WORD $0x53087d6c // lsr w12, w11, #8 - WORD $0x4e0c1d42 // mov v2.s[1], w10 - WORD $0x53147d6b // lsr w11, w11, #20 - WORD $0x4e141d82 // mov v2.s[2], w12 - WORD $0x4e1c1d62 // mov v2.s[3], w11 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3c9d0122 // stur q2, [x9, #-48] - WORD $0x2941ac0a // ldp w10, w11, [x0, #12] - WORD $0x530c7d4c // lsr w12, w10, #12 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x138a616d // extr w13, w11, w10, #24 - WORD $0x4e0c1d82 // mov v2.s[1], w12 - WORD $0x53047d6b // lsr w11, w11, #4 - WORD $0x4e141da2 // mov v2.s[2], w13 - WORD $0x4e1c1d62 // mov v2.s[3], w11 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3c9e0122 // stur q2, [x9, #-32] - WORD $0x29422c0a // ldp w10, w11, [x0, #16] - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x138a716a // extr w10, w11, w10, #28 - WORD $0x0e040d62 // dup v2.2s, w11 - WORD $0x1e270183 // fmov s3, w12 - WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s - WORD $0x4e0c1d43 // mov v3.s[1], w10 - WORD $0x6e180443 // mov v3.d[1], v2.d[0] - WORD $0x4e201c62 // and v2.16b, v3.16b, v0.16b - WORD $0x3c9f0122 // stur q2, [x9, #-16] - WORD $0x29432c0a // ldp w10, w11, [x0, #24] - WORD $0x530c7d4c // lsr w12, w10, #12 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x138a616d // extr w13, w11, w10, #24 - WORD $0x4e0c1d82 // mov v2.s[1], w12 - WORD $0x53047d6b // lsr w11, w11, #4 - WORD $0x4e141da2 // mov v2.s[2], w13 - WORD $0x4e1c1d62 // mov v2.s[3], w11 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3d800122 // str q2, [x9] - WORD $0x2943ac0a // ldp w10, w11, [x0, #28] - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x138a716a // extr w10, w11, w10, #28 - WORD $0x0e040d62 // dup v2.2s, w11 - WORD $0x1e270183 // fmov s3, w12 - WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s - WORD $0x4e0c1d43 // mov v3.s[1], w10 - WORD $0x6e180443 // mov v3.d[1], v2.d[0] - WORD $0x4e201c62 // and v2.16b, v3.16b, v0.16b - WORD $0x3d800522 // str q2, [x9, #16] - WORD $0x2944ac0a // ldp w10, w11, [x0, #36] - WORD $0x530c7d4c // lsr w12, w10, #12 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x138a616d // extr w13, w11, w10, #24 - WORD $0x4e0c1d82 // mov v2.s[1], w12 - WORD $0x53047d6b // lsr w11, w11, #4 - WORD $0x4e141da2 // mov v2.s[2], w13 - WORD $0x4e1c1d62 // mov v2.s[3], w11 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3d800922 // str q2, [x9, #32] - WORD $0x29452c0a // ldp w10, w11, [x0, #40] - WORD $0x9100c000 // add x0, x0, #48 - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x138a716a // extr w10, w11, w10, #28 - WORD $0x0e040d62 // dup v2.2s, w11 - WORD $0x1e270183 // fmov s3, w12 - WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s - WORD $0x4e0c1d43 // mov v3.s[1], w10 - WORD $0x6e180443 // mov v3.d[1], v2.d[0] - WORD $0x4e201c62 // and v2.16b, v3.16b, v0.16b - WORD $0x3d800d22 // str q2, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - BNE LBB0_39 - JMP LBB0_99 -LBB0_40: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - MOVD $0x0000000f00000002, R1 // LCPI0_105 - MOVD $0x0000001100000004, R2 // LCPI0_107 - MOVD $0x0000001200000005, R3 // LCPI0_109 - MOVD $0x0000001300000006, R4 // LCPI0_112 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f00c7e0 // movi v0.4s, #31, msl #8 - WORD $0x2ea0b821 // neg v1.2s, v1.2s - WORD $0x2ea0b842 // neg v2.2s, v2.2s - WORD $0x2ea0b863 // neg v3.2s, v3.2s - WORD $0x2ea0b884 // neg v4.2s, v4.2s + WORD $0x7100647f // cmp w3, #25 + BGT LBB0_80 + + // %bb.37: + WORD $0x7100607f // cmp w3, #24 + BEQ LBB0_112 + + // %bb.38: + WORD $0x7100647f // cmp w3, #25 + BNE LBB0_156 + + // %bb.39: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.40: + // WORD $0x90000008 // adrp x8, .LCPI0_76 + // WORD $0x90000009 // adrp x9, .LCPI0_77 + // WORD $0x9000000a // adrp x10, .LCPI0_78 + // WORD $0x9000000b // adrp x11, .LCPI0_91 + VMOVD LCPI0_76, V0 + // WORD $0x90000008 // adrp x8, .LCPI0_79 + VMOVD LCPI0_77, V1 + // WORD $0x90000009 // adrp x9, .LCPI0_80 + VMOVD LCPI0_78, V2 + // WORD $0x9000000a // adrp x10, .LCPI0_81 + VMOVD LCPI0_79, V3 + // WORD $0x90000008 // adrp x8, .LCPI0_82 + VMOVD LCPI0_80, V4 + // WORD $0x90000009 // adrp x9, .LCPI0_83 + VMOVD LCPI0_81, V5 + // WORD $0x9000000a // adrp x10, .LCPI0_84 + VMOVD LCPI0_82, V6 + // WORD $0x90000008 // adrp x8, .LCPI0_85 + VMOVD LCPI0_83, V7 + // WORD $0x90000009 // adrp x9, .LCPI0_86 + VMOVD LCPI0_84, V16 + // WORD $0x9000000a // adrp x10, .LCPI0_87 + VMOVD LCPI0_85, V17 + // WORD $0x90000008 // adrp x8, .LCPI0_88 + VMOVD LCPI0_86, V18 + // WORD $0x90000009 // adrp x9, .LCPI0_89 + VMOVD LCPI0_87, V19 + // WORD $0x9000000a // adrp x10, .LCPI0_90 + VMOVD LCPI0_88, V20 + WORD $0x91010348 // add x8, x26, #64 + VMOVD LCPI0_89, V21 + WORD $0xaa1303e9 // mov x9, x19 + VMOVD LCPI0_90, V22 + VMOVD LCPI0_91, V23 + +LBB0_41: + WORD $0xb940000a // ldr w10, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0xfc404018 // ldur d24, [x0, #4] + WORD $0xb9400c0b // ldr w11, [x0, #12] + WORD $0x1e270159 // fmov s25, w10 + WORD $0x1e27015a // fmov s26, w10 + WORD $0x2ea0471b // ushl v27.2s, v24.2s, v0.2s + WORD $0x0e0c3f0a // mov w10, v24.s[1] + WORD $0x0e983b39 // zip1 v25.2s, v25.2s, v24.2s + WORD $0x6e1a235a // ext v26.16b, v26.16b, v26.16b, #4 + WORD $0x138a2d6a // extr w10, w11, w10, #11 + WORD $0x2ea14739 // ushl v25.2s, v25.2s, v1.2s + WORD $0x0eb91f79 // orr v25.8b, v27.8b, v25.8b + WORD $0x6e196358 // ext v24.16b, v26.16b, v25.16b, #12 + WORD $0x4e1c1d58 // mov v24.s[3], w10 + WORD $0x6f0777d8 // bic v24.4s, #254, lsl #24 + WORD $0x3c9c0118 // stur q24, [x8, #-64] + WORD $0xb9400c0a // ldr w10, [x0, #12] + WORD $0xfd400818 // ldr d24, [x0, #16] + WORD $0xb940180b // ldr w11, [x0, #24] + WORD $0x1e270159 // fmov s25, w10 + WORD $0x53047d4a // lsr w10, w10, #4 + WORD $0x2ea2471a // ushl v26.2s, v24.2s, v2.2s + WORD $0x0e983b39 // zip1 v25.2s, v25.2s, v24.2s + WORD $0x1e27015b // fmov s27, w10 + WORD $0x0e0c3f0a // mov w10, v24.s[1] + WORD $0x6e1b237b // ext v27.16b, v27.16b, v27.16b, #4 + WORD $0x2ea34739 // ushl v25.2s, v25.2s, v3.2s + WORD $0x138a3d6a // extr w10, w11, w10, #15 + WORD $0x0eb91f59 // orr v25.8b, v26.8b, v25.8b + WORD $0x6e196378 // ext v24.16b, v27.16b, v25.16b, #12 + WORD $0x4e1c1d58 // mov v24.s[3], w10 + WORD $0x6f0777d8 // bic v24.4s, #254, lsl #24 + WORD $0x3c9d0118 // stur q24, [x8, #-48] + WORD $0x2943280b // ldp w11, w10, [x0, #24] + WORD $0xfd401018 // ldr d24, [x0, #32] + WORD $0x1e270159 // fmov s25, w10 + WORD $0x138b214b // extr w11, w10, w11, #8 + WORD $0x53017d4a // lsr w10, w10, #1 + WORD $0x0e983b39 // zip1 v25.2s, v25.2s, v24.2s + WORD $0x2ea44718 // ushl v24.2s, v24.2s, v4.2s + WORD $0x1e27017a // fmov s26, w11 + WORD $0x2ea54739 // ushl v25.2s, v25.2s, v5.2s + WORD $0x4e0c1d5a // mov v26.s[1], w10 + WORD $0x0eb91f18 // orr v24.8b, v24.8b, v25.8b + WORD $0x6e18071a // mov v26.d[1], v24.d[0] + WORD $0x6f0777da // bic v26.4s, #254, lsl #24 + WORD $0x3c9e011a // stur q26, [x8, #-32] + WORD $0x2944a80b // ldp w11, w10, [x0, #36] + WORD $0xfc42c018 // ldur d24, [x0, #44] + WORD $0x1e270159 // fmov s25, w10 + WORD $0x138b314b // extr w11, w10, w11, #12 + WORD $0x53057d4a // lsr w10, w10, #5 + WORD $0x0e983b39 // zip1 v25.2s, v25.2s, v24.2s + WORD $0x2ea64718 // ushl v24.2s, v24.2s, v6.2s + WORD $0x1e27017a // fmov s26, w11 + WORD $0x2ea74739 // ushl v25.2s, v25.2s, v7.2s + WORD $0x4e0c1d5a // mov v26.s[1], w10 + WORD $0x0eb91f18 // orr v24.8b, v24.8b, v25.8b + WORD $0x6e18071a // mov v26.d[1], v24.d[0] + WORD $0x6f0777da // bic v26.4s, #254, lsl #24 + WORD $0x3c9f011a // stur q26, [x8, #-16] + WORD $0xfc434018 // ldur d24, [x0, #52] + WORD $0xbd403019 // ldr s25, [x0, #48] + WORD $0xb9403c0c // ldr w12, [x0, #60] + WORD $0x2eb0471a // ushl v26.2s, v24.2s, v16.2s + WORD $0x0e0c3f0a // mov w10, v24.s[1] + WORD $0x0e983b39 // zip1 v25.2s, v25.2s, v24.2s + WORD $0x53027d4b // lsr w11, w10, #2 + WORD $0x138a6d8a // extr w10, w12, w10, #27 + WORD $0x2eb14739 // ushl v25.2s, v25.2s, v17.2s + WORD $0x0eb91f58 // orr v24.8b, v26.8b, v25.8b + WORD $0x4e141d78 // mov v24.s[2], w11 + WORD $0x4e1c1d58 // mov v24.s[3], w10 + WORD $0x6f0777d8 // bic v24.4s, #254, lsl #24 + WORD $0x3d800118 // str q24, [x8] + WORD $0xfd402018 // ldr d24, [x0, #64] + WORD $0xbd403c19 // ldr s25, [x0, #60] + WORD $0xb940480c // ldr w12, [x0, #72] + WORD $0x2eb2471a // ushl v26.2s, v24.2s, v18.2s + WORD $0x0e0c3f0a // mov w10, v24.s[1] + WORD $0x0e983b39 // zip1 v25.2s, v25.2s, v24.2s + WORD $0x53067d4b // lsr w11, w10, #6 + WORD $0x138a7d8a // extr w10, w12, w10, #31 + WORD $0x2eb34739 // ushl v25.2s, v25.2s, v19.2s + WORD $0x0eb91f58 // orr v24.8b, v26.8b, v25.8b + WORD $0x4e141d78 // mov v24.s[2], w11 + WORD $0x4e1c1d58 // mov v24.s[3], w10 + WORD $0x6f0777d8 // bic v24.4s, #254, lsl #24 + WORD $0x3d800518 // str q24, [x8, #16] + WORD $0xfc44c018 // ldur d24, [x0, #76] + WORD $0xbd404819 // ldr s25, [x0, #72] + WORD $0xb940540b // ldr w11, [x0, #84] + WORD $0x2eb4471a // ushl v26.2s, v24.2s, v20.2s + WORD $0x0e0c3f0a // mov w10, v24.s[1] + WORD $0x0e983b39 // zip1 v25.2s, v25.2s, v24.2s + WORD $0x138a296a // extr w10, w11, w10, #10 + WORD $0x2eb54739 // ushl v25.2s, v25.2s, v21.2s + WORD $0x0eb91f58 // orr v24.8b, v26.8b, v25.8b + WORD $0x4e141d58 // mov v24.s[2], w10 + WORD $0x53037d6a // lsr w10, w11, #3 + WORD $0x4e1c1d58 // mov v24.s[3], w10 + WORD $0x6f0777d8 // bic v24.4s, #254, lsl #24 + WORD $0x3d800918 // str q24, [x8, #32] + WORD $0xfd402c18 // ldr d24, [x0, #88] + WORD $0xbd405419 // ldr s25, [x0, #84] + WORD $0xb940600b // ldr w11, [x0, #96] + WORD $0x91019000 // add x0, x0, #100 + WORD $0x2eb6471a // ushl v26.2s, v24.2s, v22.2s + WORD $0x0e0c3f0a // mov w10, v24.s[1] + WORD $0x0e983b39 // zip1 v25.2s, v25.2s, v24.2s + WORD $0x138a396a // extr w10, w11, w10, #14 + WORD $0x2eb74739 // ushl v25.2s, v25.2s, v23.2s + WORD $0x0eb91f58 // orr v24.8b, v26.8b, v25.8b + WORD $0x4e141d58 // mov v24.s[2], w10 + WORD $0x53077d6a // lsr w10, w11, #7 + WORD $0x4e1c1d58 // mov v24.s[3], w10 + WORD $0x6f0777d8 // bic v24.4s, #254, lsl #24 + WORD $0x3d800d18 // str q24, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_41 + JMP LBB0_156 + LBB0_42: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x530d7d4c // lsr w12, w10, #13 - WORD $0x1e270145 // fmov s5, w10 - WORD $0x138a696d // extr w13, w11, w10, #26 - WORD $0x4e0c1d85 // mov v5.s[1], w12 - WORD $0x53077d6b // lsr w11, w11, #7 - WORD $0x4e141da5 // mov v5.s[2], w13 - WORD $0x4e1c1d65 // mov v5.s[3], w11 - WORD $0x4e201ca6 // and v6.16b, v5.16b, v0.16b - WORD $0x3c9c0126 // stur q6, [x9, #-64] - WORD $0x29412c0a // ldp w10, w11, [x0, #8] - WORD $0x53017d4c // lsr w12, w10, #1 - WORD $0x530e7d4d // lsr w13, w10, #14 - WORD $0x4e0c1d85 // mov v5.s[1], w12 - WORD $0x138a6d6a // extr w10, w11, w10, #27 - WORD $0x4e141da5 // mov v5.s[2], w13 - WORD $0x4e1c1d45 // mov v5.s[3], w10 - WORD $0x4e201ca5 // and v5.16b, v5.16b, v0.16b - WORD $0x3c9d0125 // stur q5, [x9, #-48] - WORD $0x2941ac0a // ldp w10, w11, [x0, #12] - WORD $0x53087d4c // lsr w12, w10, #8 - WORD $0x138a556a // extr w10, w11, w10, #21 - WORD $0x0e040d65 // dup v5.2s, w11 - WORD $0x1e270186 // fmov s6, w12 - WORD $0x2ea144a5 // ushl v5.2s, v5.2s, v1.2s - WORD $0x4e0c1d46 // mov v6.s[1], w10 - WORD $0x6e1804a6 // mov v6.d[1], v5.d[0] - WORD $0x4e201cc5 // and v5.16b, v6.16b, v0.16b - WORD $0x3c9e0125 // stur q5, [x9, #-32] - WORD $0x29422c0a // ldp w10, w11, [x0, #16] - WORD $0xb940180c // ldr w12, [x0, #24] - WORD $0x138a716a // extr w10, w11, w10, #28 - WORD $0x53097d6d // lsr w13, w11, #9 - WORD $0x1e270145 // fmov s5, w10 - WORD $0x138b598b // extr w11, w12, w11, #22 - WORD $0x4e0c1da5 // mov v5.s[1], w13 - WORD $0x53037d8c // lsr w12, w12, #3 - WORD $0x4e141d65 // mov v5.s[2], w11 - WORD $0x4e1c1d85 // mov v5.s[3], w12 - WORD $0x4e201ca5 // and v5.16b, v5.16b, v0.16b - WORD $0x3c9f0125 // stur q5, [x9, #-16] - WORD $0x29432c0a // ldp w10, w11, [x0, #24] - WORD $0xb940200c // ldr w12, [x0, #32] - WORD $0x53107d4d // lsr w13, w10, #16 - WORD $0x138a756a // extr w10, w11, w10, #29 - WORD $0x1e2701a5 // fmov s5, w13 - WORD $0x530a7d6e // lsr w14, w11, #10 - WORD $0x4e0c1d45 // mov v5.s[1], w10 - WORD $0x138b5d8b // extr w11, w12, w11, #23 - WORD $0x4e141dc5 // mov v5.s[2], w14 - WORD $0x4e1c1d65 // mov v5.s[3], w11 - WORD $0x4e201ca5 // and v5.16b, v5.16b, v0.16b - WORD $0x3d800125 // str q5, [x9] - WORD $0x29442c0a // ldp w10, w11, [x0, #32] - WORD $0x0e040d45 // dup v5.2s, w10 - WORD $0x138a796a // extr w10, w11, w10, #30 - WORD $0x2ea244a5 // ushl v5.2s, v5.2s, v2.2s - WORD $0x530b7d6b // lsr w11, w11, #11 - WORD $0x4e141d45 // mov v5.s[2], w10 - WORD $0x4e1c1d65 // mov v5.s[3], w11 - WORD $0x4e201ca5 // and v5.16b, v5.16b, v0.16b - WORD $0x3d800525 // str q5, [x9, #16] - WORD $0x2944ac0a // ldp w10, w11, [x0, #36] - WORD $0xb9402c0c // ldr w12, [x0, #44] - WORD $0x138a616a // extr w10, w11, w10, #24 - WORD $0x0e040d65 // dup v5.2s, w11 - WORD $0x2ea344a5 // ushl v5.2s, v5.2s, v3.2s - WORD $0x1e270146 // fmov s6, w10 - WORD $0x6e0c04a6 // mov v6.s[1], v5.s[0] - WORD $0x138b7d8b // extr w11, w12, w11, #31 - WORD $0x6e1424a6 // mov v6.s[2], v5.s[1] - WORD $0x4e1c1d66 // mov v6.s[3], w11 - WORD $0x4e201cc5 // and v5.16b, v6.16b, v0.16b - WORD $0x3d800925 // str q5, [x9, #32] - WORD $0x2945ac0a // ldp w10, w11, [x0, #44] - WORD $0x9100d000 // add x0, x0, #52 - WORD $0x530c7d4c // lsr w12, w10, #12 - WORD $0x138a656a // extr w10, w11, w10, #25 - WORD $0x0e040d65 // dup v5.2s, w11 - WORD $0x1e270186 // fmov s6, w12 - WORD $0x2ea444a5 // ushl v5.2s, v5.2s, v4.2s - WORD $0x4e0c1d46 // mov v6.s[1], w10 - WORD $0x6e1804a6 // mov v6.d[1], v5.d[0] - WORD $0x4e201cc5 // and v5.16b, v6.16b, v0.16b - WORD $0x3d800d25 // str q5, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - BNE LBB0_42 - JMP LBB0_99 -LBB0_43: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - MOVD $0x0000001200000004, R1 // LCPI0_111 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f01c7e0 // movi v0.4s, #63, msl #8 - WORD $0x2ea0b821 // neg v1.2s, v1.2s -LBB0_45: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x530e7d4c // lsr w12, w10, #14 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x138a716d // extr w13, w11, w10, #28 - WORD $0x4e0c1d82 // mov v2.s[1], w12 - WORD $0x530a7d6b // lsr w11, w11, #10 - WORD $0x4e141da2 // mov v2.s[2], w13 - WORD $0x4e1c1d62 // mov v2.s[3], w11 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3c9c0122 // stur q2, [x9, #-64] - WORD $0x2940ac0a // ldp w10, w11, [x0, #4] - WORD $0xb9400c0c // ldr w12, [x0, #12] - WORD $0x138a616a // extr w10, w11, w10, #24 - WORD $0x53067d6d // lsr w13, w11, #6 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x138b518b // extr w11, w12, w11, #20 - WORD $0x4e0c1da2 // mov v2.s[1], w13 - WORD $0x53027d8c // lsr w12, w12, #2 - WORD $0x4e141d62 // mov v2.s[2], w11 - WORD $0x4e1c1d82 // mov v2.s[3], w12 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3c9d0122 // stur q2, [x9, #-48] - WORD $0x2941ac0a // ldp w10, w11, [x0, #12] - WORD $0xb940140c // ldr w12, [x0, #20] - WORD $0x53107d4d // lsr w13, w10, #16 - WORD $0x138a796a // extr w10, w11, w10, #30 - WORD $0x1e2701a2 // fmov s2, w13 - WORD $0x530c7d6e // lsr w14, w11, #12 - WORD $0x4e0c1d42 // mov v2.s[1], w10 - WORD $0x138b698b // extr w11, w12, w11, #26 - WORD $0x4e141dc2 // mov v2.s[2], w14 - WORD $0x4e1c1d62 // mov v2.s[3], w11 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3c9e0122 // stur q2, [x9, #-32] - WORD $0x2942ac0a // ldp w10, w11, [x0, #20] - WORD $0x53087d4c // lsr w12, w10, #8 - WORD $0x138a596a // extr w10, w11, w10, #22 - WORD $0x0e040d62 // dup v2.2s, w11 - WORD $0x1e270183 // fmov s3, w12 - WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s - WORD $0x4e0c1d43 // mov v3.s[1], w10 - WORD $0x6e180443 // mov v3.d[1], v2.d[0] - WORD $0x4e201c62 // and v2.16b, v3.16b, v0.16b - WORD $0x3c9f0122 // stur q2, [x9, #-16] - WORD $0x2943ac0a // ldp w10, w11, [x0, #28] - WORD $0x530e7d4c // lsr w12, w10, #14 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x138a716d // extr w13, w11, w10, #28 - WORD $0x4e0c1d82 // mov v2.s[1], w12 - WORD $0x530a7d6b // lsr w11, w11, #10 - WORD $0x4e141da2 // mov v2.s[2], w13 - WORD $0x4e1c1d62 // mov v2.s[3], w11 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3d800122 // str q2, [x9] - WORD $0x29442c0a // ldp w10, w11, [x0, #32] - WORD $0xb940280c // ldr w12, [x0, #40] - WORD $0x138a616a // extr w10, w11, w10, #24 - WORD $0x53067d6d // lsr w13, w11, #6 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x138b518b // extr w11, w12, w11, #20 - WORD $0x4e0c1da2 // mov v2.s[1], w13 - WORD $0x53027d8c // lsr w12, w12, #2 - WORD $0x4e141d62 // mov v2.s[2], w11 - WORD $0x4e1c1d82 // mov v2.s[3], w12 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3d800522 // str q2, [x9, #16] - WORD $0x29452c0a // ldp w10, w11, [x0, #40] - WORD $0xb940300c // ldr w12, [x0, #48] - WORD $0x53107d4d // lsr w13, w10, #16 - WORD $0x138a796a // extr w10, w11, w10, #30 - WORD $0x1e2701a2 // fmov s2, w13 - WORD $0x530c7d6e // lsr w14, w11, #12 - WORD $0x4e0c1d42 // mov v2.s[1], w10 - WORD $0x138b698b // extr w11, w12, w11, #26 - WORD $0x4e141dc2 // mov v2.s[2], w14 - WORD $0x4e1c1d62 // mov v2.s[3], w11 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3d800922 // str q2, [x9, #32] - WORD $0x29462c0a // ldp w10, w11, [x0, #48] - WORD $0x9100e000 // add x0, x0, #56 - WORD $0x53087d4c // lsr w12, w10, #8 - WORD $0x138a596a // extr w10, w11, w10, #22 - WORD $0x0e040d62 // dup v2.2s, w11 - WORD $0x1e270183 // fmov s3, w12 - WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s - WORD $0x4e0c1d43 // mov v3.s[1], w10 - WORD $0x6e180443 // mov v3.d[1], v2.d[0] - WORD $0x4e201c62 // and v2.16b, v3.16b, v0.16b - WORD $0x3d800d22 // str q2, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - BNE LBB0_45 - JMP LBB0_99 -LBB0_46: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - MOVD $0x0000001100000002, R1 // LCPI0_110 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f03c7e0 // movi v0.4s, #127, msl #8 - WORD $0x2ea0b821 // neg v1.2s, v1.2s + WORD $0x7100147f // cmp w3, #5 + BGT LBB0_85 + + // %bb.43: + WORD $0x7100107f // cmp w3, #4 + BEQ LBB0_115 + + // %bb.44: + WORD $0x7100147f // cmp w3, #5 + BNE LBB0_156 + + // %bb.45: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.46: + // WORD $0x90000008 // adrp x8, .LCPI0_178 + // WORD $0x90000009 // adrp x9, .LCPI0_179 + // WORD $0x9000000a // adrp x10, .LCPI0_180 + WORD $0x4f0007e7 // movi v7.4s, #31 + VMOVD LCPI0_178, V0 + // WORD $0x90000008 // adrp x8, .LCPI0_181 + VMOVD LCPI0_179, V1 + // WORD $0x90000009 // adrp x9, .LCPI0_182 + VMOVQ LCPI0_180L, LCPI0_180H, V2 + // WORD $0x9000000a // adrp x10, .LCPI0_183 + VMOVD LCPI0_181, V3 + // WORD $0x90000008 // adrp x8, .LCPI0_184 + VMOVD LCPI0_182, V4 + // WORD $0x90000009 // adrp x9, .LCPI0_185 + VMOVQ LCPI0_183L, LCPI0_183H, V5 + VMOVD LCPI0_184, V6 + WORD $0x91010348 // add x8, x26, #64 + VMOVQ LCPI0_185L, LCPI0_185H, V16 + WORD $0xaa1303e9 // mov x9, x19 + +LBB0_47: + WORD $0xb940000a // ldr w10, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x0e040d51 // dup v17.2s, w10 + WORD $0x1e270152 // fmov s18, w10 + WORD $0x530f7d4a // lsr w10, w10, #15 + WORD $0x6e122252 // ext v18.16b, v18.16b, v18.16b, #4 + WORD $0x2ea04631 // ushl v17.2s, v17.2s, v0.2s + WORD $0x6e116251 // ext v17.16b, v18.16b, v17.16b, #12 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9c0111 // stur q17, [x8, #-64] + WORD $0x29402c0a // ldp w10, w11, [x0] + WORD $0x0e040d51 // dup v17.2s, w10 + WORD $0x138a796a // extr w10, w11, w10, #30 + WORD $0x2ea14631 // ushl v17.2s, v17.2s, v1.2s + WORD $0x4e141d51 // mov v17.s[2], w10 + WORD $0x53037d6a // lsr w10, w11, #3 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x9100100a // add x10, x0, #4 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9d0111 // stur q17, [x8, #-48] + WORD $0x4d40c951 // ld1r { v17.4s }, [x10] + WORD $0x6ea24631 // ushl v17.4s, v17.4s, v2.4s + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9e0111 // stur q17, [x8, #-32] + WORD $0x2940ac0a // ldp w10, w11, [x0, #4] + WORD $0x138a716a // extr w10, w11, w10, #28 + WORD $0x0e040d71 // dup v17.2s, w11 + WORD $0x1e270152 // fmov s18, w10 + WORD $0x530b7d6a // lsr w10, w11, #11 + WORD $0x2ea34631 // ushl v17.2s, v17.2s, v3.2s + WORD $0x6e122252 // ext v18.16b, v18.16b, v18.16b, #4 + WORD $0x6e116251 // ext v17.16b, v18.16b, v17.16b, #12 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9f0111 // stur q17, [x8, #-16] + WORD $0x29412c0a // ldp w10, w11, [x0, #8] + WORD $0x0e040d51 // dup v17.2s, w10 + WORD $0x531a7d4c // lsr w12, w10, #26 + WORD $0x138a7d6a // extr w10, w11, w10, #31 + WORD $0x2ea44631 // ushl v17.2s, v17.2s, v4.2s + WORD $0x4e141d91 // mov v17.s[2], w12 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x9100300a // add x10, x0, #12 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800111 // str q17, [x8] + WORD $0x4d40c951 // ld1r { v17.4s }, [x10] + WORD $0x6ea54631 // ushl v17.4s, v17.4s, v5.4s + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800511 // str q17, [x8, #16] + WORD $0x2941ac0a // ldp w10, w11, [x0, #12] + WORD $0x53187d4c // lsr w12, w10, #24 + WORD $0x0e040d71 // dup v17.2s, w11 + WORD $0x138a756a // extr w10, w11, w10, #29 + WORD $0x1e270192 // fmov s18, w12 + WORD $0x2ea64631 // ushl v17.2s, v17.2s, v6.2s + WORD $0x4e0c1d52 // mov v18.s[1], w10 + WORD $0x9100400a // add x10, x0, #16 + WORD $0x91005000 // add x0, x0, #20 + WORD $0x6e180632 // mov v18.d[1], v17.d[0] + WORD $0x4e271e51 // and v17.16b, v18.16b, v7.16b + WORD $0x3d800911 // str q17, [x8, #32] + WORD $0x4d40c951 // ld1r { v17.4s }, [x10] + WORD $0x6eb04631 // ushl v17.4s, v17.4s, v16.4s + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800d11 // str q17, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_47 + JMP LBB0_156 + LBB0_48: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x530f7d4c // lsr w12, w10, #15 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x138a796d // extr w13, w11, w10, #30 - WORD $0x4e0c1d82 // mov v2.s[1], w12 - WORD $0x530d7d6b // lsr w11, w11, #13 - WORD $0x4e141da2 // mov v2.s[2], w13 - WORD $0x4e1c1d62 // mov v2.s[3], w11 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3c9c0122 // stur q2, [x9, #-64] - WORD $0x2940ac0a // ldp w10, w11, [x0, #4] - WORD $0xb9400c0c // ldr w12, [x0, #12] - WORD $0x138a716a // extr w10, w11, w10, #28 - WORD $0x530b7d6d // lsr w13, w11, #11 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x138b698b // extr w11, w12, w11, #26 - WORD $0x4e0c1da2 // mov v2.s[1], w13 - WORD $0x53097d8c // lsr w12, w12, #9 - WORD $0x4e141d62 // mov v2.s[2], w11 - WORD $0x4e1c1d82 // mov v2.s[3], w12 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3c9d0122 // stur q2, [x9, #-48] - WORD $0x2941ac0a // ldp w10, w11, [x0, #12] - WORD $0xb940140c // ldr w12, [x0, #20] - WORD $0x138a616a // extr w10, w11, w10, #24 - WORD $0x53077d6d // lsr w13, w11, #7 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x138b598b // extr w11, w12, w11, #22 - WORD $0x4e0c1da2 // mov v2.s[1], w13 - WORD $0x53057d8c // lsr w12, w12, #5 - WORD $0x4e141d62 // mov v2.s[2], w11 - WORD $0x4e1c1d82 // mov v2.s[3], w12 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3c9e0122 // stur q2, [x9, #-32] - WORD $0x2942ac0a // ldp w10, w11, [x0, #20] - WORD $0xb9401c0c // ldr w12, [x0, #28] - WORD $0x138a516a // extr w10, w11, w10, #20 - WORD $0x53037d6d // lsr w13, w11, #3 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x138b498b // extr w11, w12, w11, #18 - WORD $0x4e0c1da2 // mov v2.s[1], w13 - WORD $0x53017d8c // lsr w12, w12, #1 - WORD $0x4e141d62 // mov v2.s[2], w11 - WORD $0x4e1c1d82 // mov v2.s[3], w12 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3c9f0122 // stur q2, [x9, #-16] - WORD $0x2943ac0a // ldp w10, w11, [x0, #28] - WORD $0xb940240c // ldr w12, [x0, #36] - WORD $0x53107d4d // lsr w13, w10, #16 - WORD $0x138a7d6a // extr w10, w11, w10, #31 - WORD $0x1e2701a2 // fmov s2, w13 - WORD $0x530e7d6e // lsr w14, w11, #14 - WORD $0x4e0c1d42 // mov v2.s[1], w10 - WORD $0x138b758b // extr w11, w12, w11, #29 - WORD $0x4e141dc2 // mov v2.s[2], w14 - WORD $0x4e1c1d62 // mov v2.s[3], w11 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3d800122 // str q2, [x9] - WORD $0x2944ac0a // ldp w10, w11, [x0, #36] - WORD $0xb9402c0c // ldr w12, [x0, #44] - WORD $0x530c7d4d // lsr w13, w10, #12 - WORD $0x138a6d6a // extr w10, w11, w10, #27 - WORD $0x1e2701a2 // fmov s2, w13 - WORD $0x530a7d6e // lsr w14, w11, #10 - WORD $0x4e0c1d42 // mov v2.s[1], w10 - WORD $0x138b658b // extr w11, w12, w11, #25 - WORD $0x4e141dc2 // mov v2.s[2], w14 - WORD $0x4e1c1d62 // mov v2.s[3], w11 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3d800522 // str q2, [x9, #16] - WORD $0x2945ac0a // ldp w10, w11, [x0, #44] - WORD $0xb940340c // ldr w12, [x0, #52] - WORD $0x53087d4d // lsr w13, w10, #8 - WORD $0x138a5d6a // extr w10, w11, w10, #23 - WORD $0x1e2701a2 // fmov s2, w13 - WORD $0x53067d6e // lsr w14, w11, #6 - WORD $0x4e0c1d42 // mov v2.s[1], w10 - WORD $0x138b558b // extr w11, w12, w11, #21 - WORD $0x4e141dc2 // mov v2.s[2], w14 - WORD $0x4e1c1d62 // mov v2.s[3], w11 - WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b - WORD $0x3d800922 // str q2, [x9, #32] - WORD $0x2946ac0a // ldp w10, w11, [x0, #52] - WORD $0x9100f000 // add x0, x0, #60 - WORD $0x53047d4c // lsr w12, w10, #4 - WORD $0x138a4d6a // extr w10, w11, w10, #19 - WORD $0x0e040d62 // dup v2.2s, w11 - WORD $0x1e270183 // fmov s3, w12 - WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s - WORD $0x4e0c1d43 // mov v3.s[1], w10 - WORD $0x6e180443 // mov v3.d[1], v2.d[0] - WORD $0x4e201c62 // and v2.16b, v3.16b, v0.16b - WORD $0x3d800d22 // str q2, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - BNE LBB0_48 - JMP LBB0_99 -LBB0_49: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x6f01e660 // movi v0.2d, #0x00ffff0000ffff -LBB0_51: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x4e0c1d81 // mov v1.s[1], w12 - WORD $0x53107d6d // lsr w13, w11, #16 - WORD $0x4e141d61 // mov v1.s[2], w11 - WORD $0x4e1c1da1 // mov v1.s[3], w13 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3c9c0121 // stur q1, [x9, #-64] - WORD $0x29412c0a // ldp w10, w11, [x0, #8] - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x4e0c1d81 // mov v1.s[1], w12 - WORD $0x53107d6d // lsr w13, w11, #16 - WORD $0x4e141d61 // mov v1.s[2], w11 - WORD $0x4e1c1da1 // mov v1.s[3], w13 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3c9d0121 // stur q1, [x9, #-48] - WORD $0x29422c0a // ldp w10, w11, [x0, #16] - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x4e0c1d81 // mov v1.s[1], w12 - WORD $0x53107d6d // lsr w13, w11, #16 - WORD $0x4e141d61 // mov v1.s[2], w11 - WORD $0x4e1c1da1 // mov v1.s[3], w13 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3c9e0121 // stur q1, [x9, #-32] - WORD $0x29432c0a // ldp w10, w11, [x0, #24] - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x4e0c1d81 // mov v1.s[1], w12 - WORD $0x53107d6d // lsr w13, w11, #16 - WORD $0x4e141d61 // mov v1.s[2], w11 - WORD $0x4e1c1da1 // mov v1.s[3], w13 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3c9f0121 // stur q1, [x9, #-16] - WORD $0x29442c0a // ldp w10, w11, [x0, #32] - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x4e0c1d81 // mov v1.s[1], w12 - WORD $0x53107d6d // lsr w13, w11, #16 - WORD $0x4e141d61 // mov v1.s[2], w11 - WORD $0x4e1c1da1 // mov v1.s[3], w13 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3d800121 // str q1, [x9] - WORD $0x29452c0a // ldp w10, w11, [x0, #40] - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x4e0c1d81 // mov v1.s[1], w12 - WORD $0x53107d6d // lsr w13, w11, #16 - WORD $0x4e141d61 // mov v1.s[2], w11 - WORD $0x4e1c1da1 // mov v1.s[3], w13 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3d800521 // str q1, [x9, #16] - WORD $0x29462c0a // ldp w10, w11, [x0, #48] - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x4e0c1d81 // mov v1.s[1], w12 - WORD $0x53107d6d // lsr w13, w11, #16 - WORD $0x4e141d61 // mov v1.s[2], w11 - WORD $0x4e1c1da1 // mov v1.s[3], w13 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3d800921 // str q1, [x9, #32] - WORD $0x29472c0a // ldp w10, w11, [x0, #56] - WORD $0x91010000 // add x0, x0, #64 - WORD $0x53107d4c // lsr w12, w10, #16 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x4e0c1d81 // mov v1.s[1], w12 - WORD $0x53107d6d // lsr w13, w11, #16 - WORD $0x4e141d61 // mov v1.s[2], w11 - WORD $0x4e1c1da1 // mov v1.s[3], w13 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3d800d21 // str q1, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - BNE LBB0_51 - JMP LBB0_99 -LBB0_52: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f00d420 // movi v0.4s, #1, msl #16 + WORD $0x7100547f // cmp w3, #21 + BGT LBB0_90 + + // %bb.49: + WORD $0x7100507f // cmp w3, #20 + BEQ LBB0_118 + + // %bb.50: + WORD $0x7100547f // cmp w3, #21 + BNE LBB0_156 + + // %bb.51: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.52: + // WORD $0x90000008 // adrp x8, .LCPI0_118 + // WORD $0x90000009 // adrp x9, .LCPI0_119 + // WORD $0x9000000a // adrp x10, .LCPI0_120 + WORD $0x4f00d7f3 // movi v19.4s, #31, msl #16 + VMOVD LCPI0_118, V0 + // WORD $0x90000008 // adrp x8, .LCPI0_121 + VMOVD LCPI0_119, V1 + // WORD $0x90000009 // adrp x9, .LCPI0_122 + VMOVD LCPI0_120, V2 + // WORD $0x9000000a // adrp x10, .LCPI0_123 + VMOVD LCPI0_121, V3 + // WORD $0x90000008 // adrp x8, .LCPI0_124 + VMOVD LCPI0_122, V4 + // WORD $0x90000009 // adrp x9, .LCPI0_125 + VMOVD LCPI0_123, V5 + // WORD $0x9000000a // adrp x10, .LCPI0_126 + VMOVD LCPI0_124, V6 + // WORD $0x90000008 // adrp x8, .LCPI0_127 + VMOVD LCPI0_125, V7 + // WORD $0x90000009 // adrp x9, .LCPI0_128 + VMOVD LCPI0_126, V16 + // WORD $0x9000000a // adrp x10, .LCPI0_129 + VMOVD LCPI0_127, V17 + WORD $0x91010348 // add x8, x26, #64 + VMOVD LCPI0_128, V18 + WORD $0xaa1303e9 // mov x9, x19 + VMOVD LCPI0_129, V20 + +LBB0_53: + WORD $0x29402c0a // ldp w10, w11, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x138a556c // extr w12, w11, w10, #21 + WORD $0x1e270155 // fmov s21, w10 + WORD $0x530a7d6a // lsr w10, w11, #10 + WORD $0x4e0c1d95 // mov v21.s[1], w12 + WORD $0xb940080c // ldr w12, [x0, #8] + WORD $0x4e141d55 // mov v21.s[2], w10 + WORD $0x138b7d8a // extr w10, w12, w11, #31 + WORD $0x4e1c1d55 // mov v21.s[3], w10 + WORD $0x4e331eb5 // and v21.16b, v21.16b, v19.16b + WORD $0x3c9c0115 // stur q21, [x8, #-64] + WORD $0x2941280b // ldp w11, w10, [x0, #8] + WORD $0xfd400815 // ldr d21, [x0, #16] + WORD $0x1e270156 // fmov s22, w10 + WORD $0x138b514b // extr w11, w10, w11, #20 + WORD $0x53097d4a // lsr w10, w10, #9 + WORD $0x0e953ad6 // zip1 v22.2s, v22.2s, v21.2s + WORD $0x2ea046b5 // ushl v21.2s, v21.2s, v0.2s + WORD $0x1e270177 // fmov s23, w11 + WORD $0x2ea146d6 // ushl v22.2s, v22.2s, v1.2s + WORD $0x4e0c1d57 // mov v23.s[1], w10 + WORD $0x0eb61eb5 // orr v21.8b, v21.8b, v22.8b + WORD $0x6e1806b7 // mov v23.d[1], v21.d[0] + WORD $0x4e331ef5 // and v21.16b, v23.16b, v19.16b + WORD $0x3c9d0115 // stur q21, [x8, #-48] + WORD $0xb940140a // ldr w10, [x0, #20] + WORD $0xfd400c15 // ldr d21, [x0, #24] + WORD $0x1e270156 // fmov s22, w10 + WORD $0x53087d4a // lsr w10, w10, #8 + WORD $0x2ea246b7 // ushl v23.2s, v21.2s, v2.2s + WORD $0x0e953ad6 // zip1 v22.2s, v22.2s, v21.2s + WORD $0x1e270158 // fmov s24, w10 + WORD $0x0e0c3eaa // mov w10, v21.s[1] + WORD $0x6e182318 // ext v24.16b, v24.16b, v24.16b, #4 + WORD $0x2ea346d6 // ushl v22.2s, v22.2s, v3.2s + WORD $0x53077d4a // lsr w10, w10, #7 + WORD $0x0eb61ef6 // orr v22.8b, v23.8b, v22.8b + WORD $0x6e166315 // ext v21.16b, v24.16b, v22.16b, #12 + WORD $0x4e1c1d55 // mov v21.s[3], w10 + WORD $0x4e331eb5 // and v21.16b, v21.16b, v19.16b + WORD $0x3c9e0115 // stur q21, [x8, #-32] + WORD $0xfd401015 // ldr d21, [x0, #32] + WORD $0xbd401c16 // ldr s22, [x0, #28] + WORD $0xb940280c // ldr w12, [x0, #40] + WORD $0x2ea446b7 // ushl v23.2s, v21.2s, v4.2s + WORD $0x0e0c3eaa // mov w10, v21.s[1] + WORD $0x0e953ad6 // zip1 v22.2s, v22.2s, v21.2s + WORD $0x53067d4b // lsr w11, w10, #6 + WORD $0x138a6d8a // extr w10, w12, w10, #27 + WORD $0x2ea546d6 // ushl v22.2s, v22.2s, v5.2s + WORD $0x0eb61ef5 // orr v21.8b, v23.8b, v22.8b + WORD $0x4e141d75 // mov v21.s[2], w11 + WORD $0x4e1c1d55 // mov v21.s[3], w10 + WORD $0x4e331eb5 // and v21.16b, v21.16b, v19.16b + WORD $0x3c9f0115 // stur q21, [x8, #-16] + WORD $0x2945280b // ldp w11, w10, [x0, #40] + WORD $0xfd401815 // ldr d21, [x0, #48] + WORD $0x1e270156 // fmov s22, w10 + WORD $0x138b414b // extr w11, w10, w11, #16 + WORD $0x53057d4a // lsr w10, w10, #5 + WORD $0x0e953ad6 // zip1 v22.2s, v22.2s, v21.2s + WORD $0x2ea646b5 // ushl v21.2s, v21.2s, v6.2s + WORD $0x1e270177 // fmov s23, w11 + WORD $0x2ea746d6 // ushl v22.2s, v22.2s, v7.2s + WORD $0x4e0c1d57 // mov v23.s[1], w10 + WORD $0x0eb61eb5 // orr v21.8b, v21.8b, v22.8b + WORD $0x6e1806b7 // mov v23.d[1], v21.d[0] + WORD $0x4e331ef5 // and v21.16b, v23.16b, v19.16b + WORD $0x3d800115 // str q21, [x8] + WORD $0xb940340a // ldr w10, [x0, #52] + WORD $0xfd401c15 // ldr d21, [x0, #56] + WORD $0x1e270156 // fmov s22, w10 + WORD $0x53047d4a // lsr w10, w10, #4 + WORD $0x2eb046b7 // ushl v23.2s, v21.2s, v16.2s + WORD $0x0e953ad6 // zip1 v22.2s, v22.2s, v21.2s + WORD $0x1e270158 // fmov s24, w10 + WORD $0x0e0c3eaa // mov w10, v21.s[1] + WORD $0x6e182318 // ext v24.16b, v24.16b, v24.16b, #4 + WORD $0x2eb146d6 // ushl v22.2s, v22.2s, v17.2s + WORD $0x53037d4a // lsr w10, w10, #3 + WORD $0x0eb61ef6 // orr v22.8b, v23.8b, v22.8b + WORD $0x6e166315 // ext v21.16b, v24.16b, v22.16b, #12 + WORD $0x4e1c1d55 // mov v21.s[3], w10 + WORD $0x4e331eb5 // and v21.16b, v21.16b, v19.16b + WORD $0x3d800515 // str q21, [x8, #16] + WORD $0xfd402015 // ldr d21, [x0, #64] + WORD $0xbd403c16 // ldr s22, [x0, #60] + WORD $0xb940480c // ldr w12, [x0, #72] + WORD $0x2eb246b7 // ushl v23.2s, v21.2s, v18.2s + WORD $0x0e0c3eaa // mov w10, v21.s[1] + WORD $0x0e953ad6 // zip1 v22.2s, v22.2s, v21.2s + WORD $0x53027d4b // lsr w11, w10, #2 + WORD $0x138a5d8a // extr w10, w12, w10, #23 + WORD $0x2eb446d6 // ushl v22.2s, v22.2s, v20.2s + WORD $0x0eb61ef5 // orr v21.8b, v23.8b, v22.8b + WORD $0x4e141d75 // mov v21.s[2], w11 + WORD $0x4e1c1d55 // mov v21.s[3], w10 + WORD $0x4e331eb5 // and v21.16b, v21.16b, v19.16b + WORD $0x3d800915 // str q21, [x8, #32] + WORD $0x29492c0a // ldp w10, w11, [x0, #72] + WORD $0x138a316a // extr w10, w11, w10, #12 + WORD $0x53017d6c // lsr w12, w11, #1 + WORD $0x1e270155 // fmov s21, w10 + WORD $0xb940500a // ldr w10, [x0, #80] + WORD $0x91015000 // add x0, x0, #84 + WORD $0x138b594b // extr w11, w10, w11, #22 + WORD $0x4e0c1d95 // mov v21.s[1], w12 + WORD $0x530b7d4a // lsr w10, w10, #11 + WORD $0x4e141d75 // mov v21.s[2], w11 + WORD $0x4e1c1d55 // mov v21.s[3], w10 + WORD $0x4e331eb5 // and v21.16b, v21.16b, v19.16b + WORD $0x3d800d15 // str q21, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_53 + JMP LBB0_156 + LBB0_54: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0xb940080c // ldr w12, [x0, #8] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x138a456d // extr w13, w11, w10, #17 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x53027d6e // lsr w14, w11, #2 - WORD $0x4e0c1da1 // mov v1.s[1], w13 - WORD $0x138b4d8b // extr w11, w12, w11, #19 - WORD $0x4e141dc1 // mov v1.s[2], w14 - WORD $0x4e1c1d61 // mov v1.s[3], w11 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3c9c0121 // stur q1, [x9, #-64] - WORD $0x29412c0a // ldp w10, w11, [x0, #8] - WORD $0xb940100c // ldr w12, [x0, #16] - WORD $0x53047d4d // lsr w13, w10, #4 - WORD $0x138a556a // extr w10, w11, w10, #21 - WORD $0x1e2701a1 // fmov s1, w13 - WORD $0x53067d6e // lsr w14, w11, #6 - WORD $0x4e0c1d41 // mov v1.s[1], w10 - WORD $0x138b5d8b // extr w11, w12, w11, #23 - WORD $0x4e141dc1 // mov v1.s[2], w14 - WORD $0x4e1c1d61 // mov v1.s[3], w11 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3c9d0121 // stur q1, [x9, #-48] - WORD $0x29422c0a // ldp w10, w11, [x0, #16] - WORD $0xb940180c // ldr w12, [x0, #24] - WORD $0x53087d4d // lsr w13, w10, #8 - WORD $0x138a656a // extr w10, w11, w10, #25 - WORD $0x1e2701a1 // fmov s1, w13 - WORD $0x530a7d6e // lsr w14, w11, #10 - WORD $0x4e0c1d41 // mov v1.s[1], w10 - WORD $0x138b6d8b // extr w11, w12, w11, #27 - WORD $0x4e141dc1 // mov v1.s[2], w14 - WORD $0x4e1c1d61 // mov v1.s[3], w11 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3c9e0121 // stur q1, [x9, #-32] - WORD $0x29432c0a // ldp w10, w11, [x0, #24] - WORD $0xb940200c // ldr w12, [x0, #32] - WORD $0x530c7d4d // lsr w13, w10, #12 - WORD $0x138a756a // extr w10, w11, w10, #29 - WORD $0x1e2701a1 // fmov s1, w13 - WORD $0x530e7d6e // lsr w14, w11, #14 - WORD $0x4e0c1d41 // mov v1.s[1], w10 - WORD $0x138b7d8b // extr w11, w12, w11, #31 - WORD $0x4e141dc1 // mov v1.s[2], w14 - WORD $0x4e1c1d61 // mov v1.s[3], w11 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3c9f0121 // stur q1, [x9, #-16] - WORD $0x29442c0a // ldp w10, w11, [x0, #32] - WORD $0xb940280c // ldr w12, [x0, #40] - WORD $0x138a416a // extr w10, w11, w10, #16 - WORD $0x53017d6d // lsr w13, w11, #1 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x138b498b // extr w11, w12, w11, #18 - WORD $0x4e0c1da1 // mov v1.s[1], w13 - WORD $0x53037d8c // lsr w12, w12, #3 - WORD $0x4e141d61 // mov v1.s[2], w11 - WORD $0x4e1c1d81 // mov v1.s[3], w12 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3d800121 // str q1, [x9] - WORD $0x29452c0a // ldp w10, w11, [x0, #40] - WORD $0xb940300c // ldr w12, [x0, #48] - WORD $0x138a516a // extr w10, w11, w10, #20 - WORD $0x53057d6d // lsr w13, w11, #5 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x138b598b // extr w11, w12, w11, #22 - WORD $0x4e0c1da1 // mov v1.s[1], w13 - WORD $0x53077d8c // lsr w12, w12, #7 - WORD $0x4e141d61 // mov v1.s[2], w11 - WORD $0x4e1c1d81 // mov v1.s[3], w12 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3d800521 // str q1, [x9, #16] - WORD $0x29462c0a // ldp w10, w11, [x0, #48] - WORD $0xb940380c // ldr w12, [x0, #56] - WORD $0x138a616a // extr w10, w11, w10, #24 - WORD $0x53097d6d // lsr w13, w11, #9 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x138b698b // extr w11, w12, w11, #26 - WORD $0x4e0c1da1 // mov v1.s[1], w13 - WORD $0x530b7d8c // lsr w12, w12, #11 - WORD $0x4e141d61 // mov v1.s[2], w11 - WORD $0x4e1c1d81 // mov v1.s[3], w12 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3d800921 // str q1, [x9, #32] - WORD $0x29472c0a // ldp w10, w11, [x0, #56] - WORD $0xb940400c // ldr w12, [x0, #64] - WORD $0x91011000 // add x0, x0, #68 - WORD $0x138a716a // extr w10, w11, w10, #28 - WORD $0x530d7d6d // lsr w13, w11, #13 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x138b798b // extr w11, w12, w11, #30 - WORD $0x4e0c1da1 // mov v1.s[1], w13 - WORD $0x530f7d8c // lsr w12, w12, #15 - WORD $0x4e141d61 // mov v1.s[2], w11 - WORD $0x4e1c1d81 // mov v1.s[3], w12 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3d800d21 // str q1, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - BNE LBB0_54 - JMP LBB0_99 -LBB0_55: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f00d460 // movi v0.4s, #3, msl #16 -LBB0_57: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0xb940080c // ldr w12, [x0, #8] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x138a496d // extr w13, w11, w10, #18 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x53047d6e // lsr w14, w11, #4 - WORD $0x4e0c1da1 // mov v1.s[1], w13 - WORD $0x138b598b // extr w11, w12, w11, #22 - WORD $0x4e141dc1 // mov v1.s[2], w14 - WORD $0x4e1c1d61 // mov v1.s[3], w11 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3c9c0121 // stur q1, [x9, #-64] - WORD $0x29412c0a // ldp w10, w11, [x0, #8] - WORD $0xb940100c // ldr w12, [x0, #16] - WORD $0x53087d4d // lsr w13, w10, #8 - WORD $0x138a696a // extr w10, w11, w10, #26 - WORD $0x1e2701a1 // fmov s1, w13 - WORD $0x530c7d6e // lsr w14, w11, #12 - WORD $0x4e0c1d41 // mov v1.s[1], w10 - WORD $0x138b798b // extr w11, w12, w11, #30 - WORD $0x4e141dc1 // mov v1.s[2], w14 - WORD $0x4e1c1d61 // mov v1.s[3], w11 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3c9d0121 // stur q1, [x9, #-48] - WORD $0x29422c0a // ldp w10, w11, [x0, #16] - WORD $0xb940180c // ldr w12, [x0, #24] - WORD $0x138a416a // extr w10, w11, w10, #16 - WORD $0x53027d6d // lsr w13, w11, #2 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x138b518b // extr w11, w12, w11, #20 - WORD $0x4e0c1da1 // mov v1.s[1], w13 - WORD $0x53067d8c // lsr w12, w12, #6 - WORD $0x4e141d61 // mov v1.s[2], w11 - WORD $0x4e1c1d81 // mov v1.s[3], w12 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3c9e0121 // stur q1, [x9, #-32] - WORD $0x29432c0a // ldp w10, w11, [x0, #24] - WORD $0xb940200c // ldr w12, [x0, #32] - WORD $0x138a616a // extr w10, w11, w10, #24 - WORD $0x530a7d6d // lsr w13, w11, #10 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x138b718b // extr w11, w12, w11, #28 - WORD $0x4e0c1da1 // mov v1.s[1], w13 - WORD $0x530e7d8c // lsr w12, w12, #14 - WORD $0x4e141d61 // mov v1.s[2], w11 - WORD $0x4e1c1d81 // mov v1.s[3], w12 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3c9f0121 // stur q1, [x9, #-16] - WORD $0x2944ac0a // ldp w10, w11, [x0, #36] - WORD $0xb9402c0c // ldr w12, [x0, #44] - WORD $0x138a496d // extr w13, w11, w10, #18 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x53047d6e // lsr w14, w11, #4 - WORD $0x4e0c1da1 // mov v1.s[1], w13 - WORD $0x138b598b // extr w11, w12, w11, #22 - WORD $0x4e141dc1 // mov v1.s[2], w14 - WORD $0x4e1c1d61 // mov v1.s[3], w11 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3d800121 // str q1, [x9] - WORD $0x2945ac0a // ldp w10, w11, [x0, #44] - WORD $0xb940340c // ldr w12, [x0, #52] - WORD $0x53087d4d // lsr w13, w10, #8 - WORD $0x138a696a // extr w10, w11, w10, #26 - WORD $0x1e2701a1 // fmov s1, w13 - WORD $0x530c7d6e // lsr w14, w11, #12 - WORD $0x4e0c1d41 // mov v1.s[1], w10 - WORD $0x138b798b // extr w11, w12, w11, #30 - WORD $0x4e141dc1 // mov v1.s[2], w14 - WORD $0x4e1c1d61 // mov v1.s[3], w11 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3d800521 // str q1, [x9, #16] - WORD $0x2946ac0a // ldp w10, w11, [x0, #52] - WORD $0xb9403c0c // ldr w12, [x0, #60] - WORD $0x138a416a // extr w10, w11, w10, #16 - WORD $0x53027d6d // lsr w13, w11, #2 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x138b518b // extr w11, w12, w11, #20 - WORD $0x4e0c1da1 // mov v1.s[1], w13 - WORD $0x53067d8c // lsr w12, w12, #6 - WORD $0x4e141d61 // mov v1.s[2], w11 - WORD $0x4e1c1d81 // mov v1.s[3], w12 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3d800921 // str q1, [x9, #32] - WORD $0x2947ac0a // ldp w10, w11, [x0, #60] - WORD $0xb940440c // ldr w12, [x0, #68] - WORD $0x91012000 // add x0, x0, #72 - WORD $0x138a616a // extr w10, w11, w10, #24 - WORD $0x530a7d6d // lsr w13, w11, #10 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x138b718b // extr w11, w12, w11, #28 - WORD $0x4e0c1da1 // mov v1.s[1], w13 - WORD $0x530e7d8c // lsr w12, w12, #14 - WORD $0x4e141d61 // mov v1.s[2], w11 - WORD $0x4e1c1d81 // mov v1.s[3], w12 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3d800d21 // str q1, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - BNE LBB0_57 - JMP LBB0_99 -LBB0_58: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - MOVD $0x000000120000001f, R5 // LCPI0_102 - MOVD $0x0000000e00000001, R1 // LCPI0_103 - MOVD $0x000000110000001e, R6 // LCPI0_104 - MOVD $0x0000000f00000002, R2 // LCPI0_105 - MOVD $0x0000000f0000001c, R7 // LCPI0_106 - MOVD $0x0000001100000004, R3 // LCPI0_107 - MOVD $0x0000000e0000001b, R16 // LCPI0_108 - MOVD $0x0000001200000005, R4 // LCPI0_109 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f00d4e0 // movi v0.4s, #7, msl #16 - WORD $0x2ea0b8a5 // neg v5.2s, v5.2s - WORD $0x2ea0b8c6 // neg v6.2s, v6.2s - WORD $0x2ea0b8e7 // neg v7.2s, v7.2s - WORD $0x2ea0ba10 // neg v16.2s, v16.2s + WORD $0x7100347f // cmp w3, #13 + BGT LBB0_95 + + // %bb.55: + WORD $0x7100307f // cmp w3, #12 + BEQ LBB0_121 + + // %bb.56: + WORD $0x7100347f // cmp w3, #13 + BNE LBB0_156 + + // %bb.57: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.58: + // WORD $0x90000008 // adrp x8, .LCPI0_140 + // WORD $0x90000009 // adrp x9, .LCPI0_141 + // WORD $0x9000000a // adrp x10, .LCPI0_142 + // WORD $0x9000000b // adrp x11, .LCPI0_143 + // WORD $0x9000000c // adrp x12, .LCPI0_144 + WORD $0x4f00c7e3 // movi v3.4s, #31, msl #8 + VMOVD LCPI0_140, V0 + VMOVD LCPI0_141, V1 + WORD $0x91010348 // add x8, x26, #64 + VMOVD LCPI0_142, V2 + WORD $0xaa1303e9 // mov x9, x19 + VMOVD LCPI0_143, V4 + VMOVD LCPI0_144, V5 + +LBB0_59: + WORD $0x29402c0a // ldp w10, w11, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x530d7d4c // lsr w12, w10, #13 + WORD $0x1e270146 // fmov s6, w10 + WORD $0x138a696a // extr w10, w11, w10, #26 + WORD $0x4e0c1d86 // mov v6.s[1], w12 + WORD $0x4e141d46 // mov v6.s[2], w10 + WORD $0x53077d6a // lsr w10, w11, #7 + WORD $0x4e1c1d46 // mov v6.s[3], w10 + WORD $0x4e231cc6 // and v6.16b, v6.16b, v3.16b + WORD $0x3c9c0106 // stur q6, [x8, #-64] + WORD $0x2940ac0a // ldp w10, w11, [x0, #4] + WORD $0x138a516a // extr w10, w11, w10, #20 + WORD $0x0e040d66 // dup v6.2s, w11 + WORD $0x1e270147 // fmov s7, w10 + WORD $0xb9400c0a // ldr w10, [x0, #12] + WORD $0x2ea044c6 // ushl v6.2s, v6.2s, v0.2s + WORD $0x138b6d4a // extr w10, w10, w11, #27 + WORD $0x6e0720e7 // ext v7.16b, v7.16b, v7.16b, #4 + WORD $0x6e0660e6 // ext v6.16b, v7.16b, v6.16b, #12 + WORD $0x4e1c1d46 // mov v6.s[3], w10 + WORD $0x4e231cc6 // and v6.16b, v6.16b, v3.16b + WORD $0x3c9d0106 // stur q6, [x8, #-48] + WORD $0x2941ac0a // ldp w10, w11, [x0, #12] + WORD $0x53087d4c // lsr w12, w10, #8 + WORD $0x0e040d66 // dup v6.2s, w11 + WORD $0x138a556a // extr w10, w11, w10, #21 + WORD $0x1e270187 // fmov s7, w12 + WORD $0x2ea144c6 // ushl v6.2s, v6.2s, v1.2s + WORD $0x4e0c1d47 // mov v7.s[1], w10 + WORD $0x6e1804c7 // mov v7.d[1], v6.d[0] + WORD $0x4e231ce6 // and v6.16b, v7.16b, v3.16b + WORD $0x3c9e0106 // stur q6, [x8, #-32] + WORD $0x29422c0a // ldp w10, w11, [x0, #16] + WORD $0x138a716a // extr w10, w11, w10, #28 + WORD $0x53097d6c // lsr w12, w11, #9 + WORD $0x1e270146 // fmov s6, w10 + WORD $0xb940180a // ldr w10, [x0, #24] + WORD $0x138b594b // extr w11, w10, w11, #22 + WORD $0x4e0c1d86 // mov v6.s[1], w12 + WORD $0x53037d4a // lsr w10, w10, #3 + WORD $0x4e141d66 // mov v6.s[2], w11 + WORD $0x4e1c1d46 // mov v6.s[3], w10 + WORD $0x4e231cc6 // and v6.16b, v6.16b, v3.16b + WORD $0x3c9f0106 // stur q6, [x8, #-16] + WORD $0x29432c0a // ldp w10, w11, [x0, #24] + WORD $0x53107d4c // lsr w12, w10, #16 + WORD $0x138a756a // extr w10, w11, w10, #29 + WORD $0x1e270186 // fmov s6, w12 + WORD $0xb940200c // ldr w12, [x0, #32] + WORD $0x4e0c1d46 // mov v6.s[1], w10 + WORD $0x530a7d6a // lsr w10, w11, #10 + WORD $0x4e141d46 // mov v6.s[2], w10 + WORD $0x138b5d8a // extr w10, w12, w11, #23 + WORD $0x4e1c1d46 // mov v6.s[3], w10 + WORD $0x4e231cc6 // and v6.16b, v6.16b, v3.16b + WORD $0x3d800106 // str q6, [x8] + WORD $0x29442c0a // ldp w10, w11, [x0, #32] + WORD $0x0e040d46 // dup v6.2s, w10 + WORD $0x138a796a // extr w10, w11, w10, #30 + WORD $0x2ea244c6 // ushl v6.2s, v6.2s, v2.2s + WORD $0x4e141d46 // mov v6.s[2], w10 + WORD $0x530b7d6a // lsr w10, w11, #11 + WORD $0x4e1c1d46 // mov v6.s[3], w10 + WORD $0x4e231cc6 // and v6.16b, v6.16b, v3.16b + WORD $0x3d800506 // str q6, [x8, #16] + WORD $0x2944ac0a // ldp w10, w11, [x0, #36] + WORD $0x138a616a // extr w10, w11, w10, #24 + WORD $0x0e040d66 // dup v6.2s, w11 + WORD $0x1e270147 // fmov s7, w10 + WORD $0xb9402c0a // ldr w10, [x0, #44] + WORD $0x2ea444c6 // ushl v6.2s, v6.2s, v4.2s + WORD $0x138b7d4a // extr w10, w10, w11, #31 + WORD $0x6e0720e7 // ext v7.16b, v7.16b, v7.16b, #4 + WORD $0x6e0660e6 // ext v6.16b, v7.16b, v6.16b, #12 + WORD $0x4e1c1d46 // mov v6.s[3], w10 + WORD $0x4e231cc6 // and v6.16b, v6.16b, v3.16b + WORD $0x3d800906 // str q6, [x8, #32] + WORD $0x2945ac0a // ldp w10, w11, [x0, #44] + WORD $0x9100d000 // add x0, x0, #52 + WORD $0x530c7d4c // lsr w12, w10, #12 + WORD $0x0e040d66 // dup v6.2s, w11 + WORD $0x138a656a // extr w10, w11, w10, #25 + WORD $0x1e270187 // fmov s7, w12 + WORD $0x2ea544c6 // ushl v6.2s, v6.2s, v5.2s + WORD $0x4e0c1d47 // mov v7.s[1], w10 + WORD $0x6e1804c7 // mov v7.d[1], v6.d[0] + WORD $0x4e231ce6 // and v6.16b, v7.16b, v3.16b + WORD $0x3d800d06 // str q6, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_59 + JMP LBB0_156 + LBB0_60: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0xb940080c // ldr w12, [x0, #8] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x138a4d6d // extr w13, w11, w10, #19 - WORD $0x1e270151 // fmov s17, w10 - WORD $0x53067d6e // lsr w14, w11, #6 - WORD $0x4e0c1db1 // mov v17.s[1], w13 - WORD $0x138b658b // extr w11, w12, w11, #25 - WORD $0x4e141dd1 // mov v17.s[2], w14 - WORD $0x4e1c1d71 // mov v17.s[3], w11 - WORD $0x4e201e31 // and v17.16b, v17.16b, v0.16b - WORD $0x3c9c0131 // stur q17, [x9, #-64] - WORD $0xb940080a // ldr w10, [x0, #8] - WORD $0xfc40c011 // ldur d17, [x0, #12] - WORD $0x1e270152 // fmov s18, w10 - WORD $0x0e913a52 // zip1 v25.2s, v25.2s, v17.2s - WORD $0x530c7d4b // lsr w11, w10, #12 - WORD $0x2ea14633 // ushl v19.2s, v17.2s, v1.2s - WORD $0x0e0c3e2a // mov w10, v17.s[1] - WORD $0x2ea54651 // ushl v17.2s, v25.2s, v5.2s - WORD $0x1e270172 // fmov s18, w11 - WORD $0x0eb11e71 // orr v17.8b, v19.8b, v17.8b - WORD $0x6e0c0632 // mov v25.s[1], v17.s[0] - WORD $0x53057d4a // lsr w10, w10, #5 - WORD $0x6e142632 // mov v25.s[2], v17.s[1] - WORD $0x4e1c1d52 // mov v25.s[3], w10 - WORD $0x4e201e51 // and v17.16b, v25.16b, v0.16b - WORD $0x3c9d0131 // stur q17, [x9, #-48] - WORD $0x29422c0a // ldp w10, w11, [x0, #16] - WORD $0xfd400c11 // ldr d17, [x0, #24] - WORD $0x1e270172 // fmov s18, w11 - WORD $0x138a616a // extr w10, w11, w10, #24 - WORD $0x0e913a52 // zip1 v25.2s, v25.2s, v17.2s - WORD $0x530b7d6c // lsr w12, w11, #11 - WORD $0x2ea24631 // ushl v17.2s, v17.2s, v2.2s - WORD $0x1e270153 // fmov s19, w10 - WORD $0x2ea64652 // ushl v25.2s, v25.2s, v6.2s - WORD $0x4e0c1d93 // mov v19.s[1], w12 - WORD $0x0eb21e31 // orr v17.8b, v17.8b, v25.8b - WORD $0x6e180633 // mov v19.d[1], v17.d[0] - WORD $0x4e201e71 // and v17.16b, v19.16b, v0.16b - WORD $0x3c9e0131 // stur q17, [x9, #-32] - WORD $0x2943ac0a // ldp w10, w11, [x0, #28] - WORD $0xb940240c // ldr w12, [x0, #36] - WORD $0x53047d4d // lsr w13, w10, #4 - WORD $0x138a5d6a // extr w10, w11, w10, #23 - WORD $0x1e2701b1 // fmov s17, w13 - WORD $0x530a7d6e // lsr w14, w11, #10 - WORD $0x4e0c1d51 // mov v17.s[1], w10 - WORD $0x138b758b // extr w11, w12, w11, #29 - WORD $0x4e141dd1 // mov v17.s[2], w14 - WORD $0x4e1c1d71 // mov v17.s[3], w11 - WORD $0x4e201e31 // and v17.16b, v17.16b, v0.16b - WORD $0x3c9f0131 // stur q17, [x9, #-16] - WORD $0x2944ac0a // ldp w10, w11, [x0, #36] - WORD $0xb9402c0c // ldr w12, [x0, #44] - WORD $0x138a416a // extr w10, w11, w10, #16 - WORD $0x53037d6d // lsr w13, w11, #3 - WORD $0x1e270151 // fmov s17, w10 - WORD $0x138b598b // extr w11, w12, w11, #22 - WORD $0x4e0c1db1 // mov v17.s[1], w13 - WORD $0x53097d8c // lsr w12, w12, #9 - WORD $0x4e141d71 // mov v17.s[2], w11 - WORD $0x4e1c1d91 // mov v17.s[3], w12 - WORD $0x4e201e31 // and v17.16b, v17.16b, v0.16b - WORD $0x3d800131 // str q17, [x9] - WORD $0xfd401811 // ldr d17, [x0, #48] - WORD $0xbd402c12 // ldr s18, [x0, #44] - WORD $0xb940380a // ldr w10, [x0, #56] - WORD $0x2ea34633 // ushl v19.2s, v17.2s, v3.2s - WORD $0x0e913a52 // zip1 v25.2s, v25.2s, v17.2s - WORD $0x0e0c3e2b // mov w11, v17.s[1] - WORD $0x2ea74651 // ushl v17.2s, v25.2s, v7.2s - WORD $0x53027d6c // lsr w12, w11, #2 - WORD $0x0eb11e71 // orr v17.8b, v19.8b, v17.8b - WORD $0x138b554a // extr w10, w10, w11, #21 - WORD $0x4e141d91 // mov v17.s[2], w12 - WORD $0x4e1c1d51 // mov v17.s[3], w10 - WORD $0x4e201e31 // and v17.16b, v17.16b, v0.16b - WORD $0x3d800531 // str q17, [x9, #16] - WORD $0xb940380a // ldr w10, [x0, #56] - WORD $0xfc43c011 // ldur d17, [x0, #60] - WORD $0x1e270152 // fmov s18, w10 - WORD $0x0e913a52 // zip1 v25.2s, v25.2s, v17.2s - WORD $0x53087d4b // lsr w11, w10, #8 - WORD $0x2ea44633 // ushl v19.2s, v17.2s, v4.2s - WORD $0x0e0c3e2a // mov w10, v17.s[1] - WORD $0x2eb04651 // ushl v17.2s, v25.2s, v16.2s - WORD $0x1e270172 // fmov s18, w11 - WORD $0x0eb11e71 // orr v17.8b, v19.8b, v17.8b - WORD $0x6e0c0632 // mov v25.s[1], v17.s[0] - WORD $0x53017d4a // lsr w10, w10, #1 - WORD $0x6e142632 // mov v25.s[2], v17.s[1] - WORD $0x4e1c1d52 // mov v25.s[3], w10 - WORD $0x4e201e51 // and v17.16b, v25.16b, v0.16b - WORD $0x3d800931 // str q17, [x9, #32] - WORD $0x29482c0a // ldp w10, w11, [x0, #64] - WORD $0xb940480c // ldr w12, [x0, #72] - WORD $0x91013000 // add x0, x0, #76 - WORD $0x138a516a // extr w10, w11, w10, #20 - WORD $0x53077d6d // lsr w13, w11, #7 - WORD $0x1e270151 // fmov s17, w10 - WORD $0x138b698b // extr w11, w12, w11, #26 - WORD $0x4e0c1db1 // mov v17.s[1], w13 - WORD $0x530d7d8c // lsr w12, w12, #13 - WORD $0x4e141d71 // mov v17.s[2], w11 - WORD $0x4e1c1d91 // mov v17.s[3], w12 - WORD $0x4e201e31 // and v17.16b, v17.16b, v0.16b - WORD $0x3d800d31 // str q17, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - BNE LBB0_60 - JMP LBB0_99 -LBB0_61: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f00d5e0 // movi v0.4s, #15, msl #16 -LBB0_63: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0xb940080c // ldr w12, [x0, #8] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x138a516d // extr w13, w11, w10, #20 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x53087d6e // lsr w14, w11, #8 - WORD $0x4e0c1da1 // mov v1.s[1], w13 - WORD $0x138b718b // extr w11, w12, w11, #28 - WORD $0x4e141dc1 // mov v1.s[2], w14 - WORD $0x4e1c1d61 // mov v1.s[3], w11 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3c9c0121 // stur q1, [x9, #-64] - WORD $0x29412c0a // ldp w10, w11, [x0, #8] - WORD $0xb940100c // ldr w12, [x0, #16] - WORD $0x138a416a // extr w10, w11, w10, #16 - WORD $0x53047d6d // lsr w13, w11, #4 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x138b618b // extr w11, w12, w11, #24 - WORD $0x4e0c1da1 // mov v1.s[1], w13 - WORD $0x530c7d8c // lsr w12, w12, #12 - WORD $0x4e141d61 // mov v1.s[2], w11 - WORD $0x4e1c1d81 // mov v1.s[3], w12 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3c9d0121 // stur q1, [x9, #-48] - WORD $0x2942ac0a // ldp w10, w11, [x0, #20] - WORD $0xb9401c0c // ldr w12, [x0, #28] - WORD $0x138a516d // extr w13, w11, w10, #20 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x53087d6e // lsr w14, w11, #8 - WORD $0x4e0c1da1 // mov v1.s[1], w13 - WORD $0x138b718b // extr w11, w12, w11, #28 - WORD $0x4e141dc1 // mov v1.s[2], w14 - WORD $0x4e1c1d61 // mov v1.s[3], w11 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3c9e0121 // stur q1, [x9, #-32] - WORD $0x2943ac0a // ldp w10, w11, [x0, #28] - WORD $0xb940240c // ldr w12, [x0, #36] - WORD $0x138a416a // extr w10, w11, w10, #16 - WORD $0x53047d6d // lsr w13, w11, #4 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x138b618b // extr w11, w12, w11, #24 - WORD $0x4e0c1da1 // mov v1.s[1], w13 - WORD $0x530c7d8c // lsr w12, w12, #12 - WORD $0x4e141d61 // mov v1.s[2], w11 - WORD $0x4e1c1d81 // mov v1.s[3], w12 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3c9f0121 // stur q1, [x9, #-16] - WORD $0x29452c0a // ldp w10, w11, [x0, #40] - WORD $0xb940300c // ldr w12, [x0, #48] - WORD $0x138a516d // extr w13, w11, w10, #20 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x53087d6e // lsr w14, w11, #8 - WORD $0x4e0c1da1 // mov v1.s[1], w13 - WORD $0x138b718b // extr w11, w12, w11, #28 - WORD $0x4e141dc1 // mov v1.s[2], w14 - WORD $0x4e1c1d61 // mov v1.s[3], w11 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3d800121 // str q1, [x9] - WORD $0x29462c0a // ldp w10, w11, [x0, #48] - WORD $0xb940380c // ldr w12, [x0, #56] - WORD $0x138a416a // extr w10, w11, w10, #16 - WORD $0x53047d6d // lsr w13, w11, #4 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x138b618b // extr w11, w12, w11, #24 - WORD $0x4e0c1da1 // mov v1.s[1], w13 - WORD $0x530c7d8c // lsr w12, w12, #12 - WORD $0x4e141d61 // mov v1.s[2], w11 - WORD $0x4e1c1d81 // mov v1.s[3], w12 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3d800521 // str q1, [x9, #16] - WORD $0x2947ac0a // ldp w10, w11, [x0, #60] - WORD $0xb940440c // ldr w12, [x0, #68] - WORD $0x138a516d // extr w13, w11, w10, #20 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x53087d6e // lsr w14, w11, #8 - WORD $0x4e0c1da1 // mov v1.s[1], w13 - WORD $0x138b718b // extr w11, w12, w11, #28 - WORD $0x4e141dc1 // mov v1.s[2], w14 - WORD $0x4e1c1d61 // mov v1.s[3], w11 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3d800921 // str q1, [x9, #32] - WORD $0x2948ac0a // ldp w10, w11, [x0, #68] - WORD $0xb9404c0c // ldr w12, [x0, #76] - WORD $0x91014000 // add x0, x0, #80 - WORD $0x138a416a // extr w10, w11, w10, #16 - WORD $0x53047d6d // lsr w13, w11, #4 - WORD $0x1e270141 // fmov s1, w10 - WORD $0x138b618b // extr w11, w12, w11, #24 - WORD $0x4e0c1da1 // mov v1.s[1], w13 - WORD $0x530c7d8c // lsr w12, w12, #12 - WORD $0x4e141d61 // mov v1.s[2], w11 - WORD $0x4e1c1d81 // mov v1.s[3], w12 - WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b - WORD $0x3d800d21 // str q1, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - BNE LBB0_63 - JMP LBB0_99 + WORD $0x7100707f // cmp w3, #28 + BEQ LBB0_124 + + // %bb.61: + WORD $0x7100747f // cmp w3, #29 + BNE LBB0_156 + + // %bb.62: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.63: + // WORD $0x90000008 // adrp x8, .LCPI0_32 + // WORD $0x90000009 // adrp x9, .LCPI0_33 + // WORD $0x9000000a // adrp x10, .LCPI0_34 + // WORD $0x9000000b // adrp x11, .LCPI0_47 + VMOVD LCPI0_32, V0 + // WORD $0x90000008 // adrp x8, .LCPI0_35 + VMOVD LCPI0_33, V1 + // WORD $0x90000009 // adrp x9, .LCPI0_36 + VMOVQ LCPI0_34L, LCPI0_34H, V2 + // WORD $0x9000000a // adrp x10, .LCPI0_37 + VMOVQ LCPI0_35L, LCPI0_35H, V3 + // WORD $0x90000008 // adrp x8, .LCPI0_38 + VMOVD LCPI0_36, V4 + // WORD $0x90000009 // adrp x9, .LCPI0_39 + VMOVD LCPI0_37, V5 + // WORD $0x9000000a // adrp x10, .LCPI0_40 + VMOVQ LCPI0_38L, LCPI0_38H, V6 + // WORD $0x90000008 // adrp x8, .LCPI0_41 + VMOVQ LCPI0_39L, LCPI0_39H, V7 + // WORD $0x90000009 // adrp x9, .LCPI0_42 + VMOVQ LCPI0_40L, LCPI0_40H, V16 + // WORD $0x9000000a // adrp x10, .LCPI0_43 + VMOVQ LCPI0_41L, LCPI0_41H, V17 + // WORD $0x90000008 // adrp x8, .LCPI0_44 + VMOVD LCPI0_42, V18 + // WORD $0x90000009 // adrp x9, .LCPI0_45 + VMOVD LCPI0_43, V19 + // WORD $0x9000000a // adrp x10, .LCPI0_46 + VMOVQ LCPI0_44L, LCPI0_44H, V20 + WORD $0x91010348 // add x8, x26, #64 + VMOVQ LCPI0_45L, LCPI0_45H, V21 + WORD $0xaa1303e9 // mov x9, x19 + VMOVD LCPI0_46, V22 + VMOVD LCPI0_47, V23 + LBB0_64: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - MOVD $0x000000130000001e, R7 // LCPI0_90 - MOVD $0x0000000d00000002, R1 // LCPI0_91 - MOVD $0x000000120000001d, R16 // LCPI0_92 - MOVD $0x0000000e00000003, R2 // LCPI0_93 - MOVD $0x000000110000001c, R17 // LCPI0_94 - MOVD $0x0000000f00000004, R3 // LCPI0_95 - MOVD $0x0000000f0000001a, R25 // LCPI0_96 - MOVD $0x0000001100000006, R4 // LCPI0_97 - MOVD $0x0000000e00000019, R19 // LCPI0_98 - MOVD $0x0000001200000007, R5 // LCPI0_99 - MOVD $0x0000000d00000018, R20 // LCPI0_100 - MOVD $0x0000001300000008, R6 // LCPI0_101 - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f00d7e0 // movi v0.4s, #31, msl #16 - WORD $0x2ea0b8e7 // neg v7.2s, v7.2s - WORD $0x2ea0ba10 // neg v16.2s, v16.2s - WORD $0x2ea0ba31 // neg v17.2s, v17.2s - WORD $0x2ea0bb39 // neg v25.2s, v25.2s - WORD $0x2ea0ba73 // neg v19.2s, v19.2s - WORD $0x2ea0ba94 // neg v20.2s, v20.2s -LBB0_66: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0xb940080c // ldr w12, [x0, #8] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x138a556d // extr w13, w11, w10, #21 - WORD $0x1e270155 // fmov s21, w10 - WORD $0x530a7d6e // lsr w14, w11, #10 - WORD $0x4e0c1db5 // mov v21.s[1], w13 - WORD $0x138b7d8b // extr w11, w12, w11, #31 - WORD $0x4e141dd5 // mov v21.s[2], w14 - WORD $0x4e1c1d75 // mov v21.s[3], w11 - WORD $0x4e201eb5 // and v21.16b, v21.16b, v0.16b - WORD $0x3c9c0135 // stur q21, [x9, #-64] - WORD $0x29412c0a // ldp w10, w11, [x0, #8] - WORD $0xfd400815 // ldr d21, [x0, #16] - WORD $0x1e270176 // fmov s22, w11 - WORD $0x138a516a // extr w10, w11, w10, #20 - WORD $0x0e953ad6 // zip1 v22.2s, v22.2s, v21.2s - WORD $0x53097d6c // lsr w12, w11, #9 - WORD $0x2ea146b5 // ushl v21.2s, v21.2s, v1.2s - WORD $0x1e270157 // fmov s23, w10 - WORD $0x2ea746d6 // ushl v22.2s, v22.2s, v7.2s - WORD $0x4e0c1d97 // mov v23.s[1], w12 - WORD $0x0eb61eb5 // orr v21.8b, v21.8b, v22.8b - WORD $0x6e1806b7 // mov v23.d[1], v21.d[0] - WORD $0x4e201ef5 // and v21.16b, v23.16b, v0.16b - WORD $0x3c9d0135 // stur q21, [x9, #-48] - WORD $0xb940140a // ldr w10, [x0, #20] - WORD $0xfd400c15 // ldr d21, [x0, #24] - WORD $0x1e270156 // fmov s22, w10 - WORD $0x0e953ad6 // zip1 v22.2s, v22.2s, v21.2s - WORD $0x53087d4b // lsr w11, w10, #8 - WORD $0x2ea246b7 // ushl v23.2s, v21.2s, v2.2s - WORD $0x0e0c3eaa // mov w10, v21.s[1] - WORD $0x2eb046d5 // ushl v21.2s, v22.2s, v16.2s - WORD $0x1e270176 // fmov s22, w11 - WORD $0x0eb51ef5 // orr v21.8b, v23.8b, v21.8b - WORD $0x6e0c06b6 // mov v22.s[1], v21.s[0] - WORD $0x53077d4a // lsr w10, w10, #7 - WORD $0x6e1426b6 // mov v22.s[2], v21.s[1] - WORD $0x4e1c1d56 // mov v22.s[3], w10 - WORD $0x4e201ed5 // and v21.16b, v22.16b, v0.16b - WORD $0x3c9e0135 // stur q21, [x9, #-32] - WORD $0xfd401015 // ldr d21, [x0, #32] - WORD $0xbd401c16 // ldr s22, [x0, #28] - WORD $0xb940280a // ldr w10, [x0, #40] - WORD $0x2ea346b7 // ushl v23.2s, v21.2s, v3.2s - WORD $0x0e953ad6 // zip1 v22.2s, v22.2s, v21.2s - WORD $0x0e0c3eab // mov w11, v21.s[1] - WORD $0x2eb146d5 // ushl v21.2s, v22.2s, v17.2s - WORD $0x53067d6c // lsr w12, w11, #6 - WORD $0x0eb51ef5 // orr v21.8b, v23.8b, v21.8b - WORD $0x138b6d4a // extr w10, w10, w11, #27 - WORD $0x4e141d95 // mov v21.s[2], w12 - WORD $0x4e1c1d55 // mov v21.s[3], w10 - WORD $0x4e201eb5 // and v21.16b, v21.16b, v0.16b - WORD $0x3c9f0135 // stur q21, [x9, #-16] - WORD $0x29452c0a // ldp w10, w11, [x0, #40] - WORD $0xfd401815 // ldr d21, [x0, #48] - WORD $0x1e270176 // fmov s22, w11 - WORD $0x138a416a // extr w10, w11, w10, #16 - WORD $0x0e953ad6 // zip1 v22.2s, v22.2s, v21.2s - WORD $0x53057d6c // lsr w12, w11, #5 - WORD $0x2ea446b5 // ushl v21.2s, v21.2s, v4.2s - WORD $0x1e270157 // fmov s23, w10 - WORD $0x2eb246d6 // ushl v22.2s, v22.2s, v25.2s - WORD $0x4e0c1d97 // mov v23.s[1], w12 - WORD $0x0eb61eb5 // orr v21.8b, v21.8b, v22.8b - WORD $0x6e1806b7 // mov v23.d[1], v21.d[0] - WORD $0x4e201ef5 // and v21.16b, v23.16b, v0.16b - WORD $0x3d800135 // str q21, [x9] - WORD $0xb940340a // ldr w10, [x0, #52] - WORD $0xfd401c15 // ldr d21, [x0, #56] - WORD $0x1e270156 // fmov s22, w10 - WORD $0x0e953ad6 // zip1 v22.2s, v22.2s, v21.2s - WORD $0x53047d4b // lsr w11, w10, #4 - WORD $0x2ea546b7 // ushl v23.2s, v21.2s, v5.2s - WORD $0x0e0c3eaa // mov w10, v21.s[1] - WORD $0x2eb346d5 // ushl v21.2s, v22.2s, v19.2s - WORD $0x1e270176 // fmov s22, w11 - WORD $0x0eb51ef5 // orr v21.8b, v23.8b, v21.8b - WORD $0x6e0c06b6 // mov v22.s[1], v21.s[0] - WORD $0x53037d4a // lsr w10, w10, #3 - WORD $0x6e1426b6 // mov v22.s[2], v21.s[1] - WORD $0x4e1c1d56 // mov v22.s[3], w10 - WORD $0x4e201ed5 // and v21.16b, v22.16b, v0.16b - WORD $0x3d800535 // str q21, [x9, #16] - WORD $0xfd402015 // ldr d21, [x0, #64] - WORD $0xbd403c16 // ldr s22, [x0, #60] - WORD $0xb940480a // ldr w10, [x0, #72] - WORD $0x2ea646b7 // ushl v23.2s, v21.2s, v6.2s - WORD $0x0e953ad6 // zip1 v22.2s, v22.2s, v21.2s - WORD $0x0e0c3eab // mov w11, v21.s[1] - WORD $0x2eb446d5 // ushl v21.2s, v22.2s, v20.2s - WORD $0x53027d6c // lsr w12, w11, #2 - WORD $0x0eb51ef5 // orr v21.8b, v23.8b, v21.8b - WORD $0x138b5d4a // extr w10, w10, w11, #23 - WORD $0x4e141d95 // mov v21.s[2], w12 - WORD $0x4e1c1d55 // mov v21.s[3], w10 - WORD $0x4e201eb5 // and v21.16b, v21.16b, v0.16b - WORD $0x3d800935 // str q21, [x9, #32] - WORD $0x29492c0a // ldp w10, w11, [x0, #72] - WORD $0xb940500c // ldr w12, [x0, #80] - WORD $0x91015000 // add x0, x0, #84 - WORD $0x138a316a // extr w10, w11, w10, #12 - WORD $0x53017d6d // lsr w13, w11, #1 - WORD $0x1e270155 // fmov s21, w10 - WORD $0x138b598b // extr w11, w12, w11, #22 - WORD $0x4e0c1db5 // mov v21.s[1], w13 - WORD $0x530b7d8c // lsr w12, w12, #11 - WORD $0x4e141d75 // mov v21.s[2], w11 - WORD $0x4e1c1d95 // mov v21.s[3], w12 - WORD $0x4e201eb5 // and v21.16b, v21.16b, v0.16b - WORD $0x3d800d35 // str q21, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - - BNE LBB0_66 - JMP LBB0_99 -LBB0_67: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - MOVD $0x0000000e00000018, R4 // LCPI0_84 - MOVD $0x0000001200000008, R1 // LCPI0_85 - MOVD $0x000000120000001c, R5 // LCPI0_86 - MOVD $0x0000000e00000004, R2 // LCPI0_87 - MOVD $0x000000140000001e, R6 // LCPI0_88 - MOVD $0x0000000c00000002, R3 // LCPI0_89 - - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f01d7e0 // movi v0.4s, #63, msl #16 - WORD $0x2ea0b884 // neg v4.2s, v4.2s - WORD $0x2ea0b8a5 // neg v5.2s, v5.2s - WORD $0x2ea0b8c6 // neg v6.2s, v6.2s + WORD $0xb940000a // ldr w10, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0xfc404018 // ldur d24, [x0, #4] + WORD $0xb9400c0b // ldr w11, [x0, #12] + WORD $0x1e270159 // fmov s25, w10 + WORD $0x1e27015a // fmov s26, w10 + WORD $0x2ea0471b // ushl v27.2s, v24.2s, v0.2s + WORD $0x0e0c3f0a // mov w10, v24.s[1] + WORD $0x0e983b39 // zip1 v25.2s, v25.2s, v24.2s + WORD $0x6e1a235a // ext v26.16b, v26.16b, v26.16b, #4 + WORD $0x138a5d6a // extr w10, w11, w10, #23 + WORD $0x2ea14739 // ushl v25.2s, v25.2s, v1.2s + WORD $0x0eb91f79 // orr v25.8b, v27.8b, v25.8b + WORD $0x6e196358 // ext v24.16b, v26.16b, v25.16b, #12 + WORD $0x4e1c1d58 // mov v24.s[3], w10 + WORD $0x6f077418 // bic v24.4s, #224, lsl #24 + WORD $0x3c9c0118 // stur q24, [x8, #-64] + WORD $0xbd400c18 // ldr s24, [x0, #12] + WORD $0x3dc00419 // ldr q25, [x0, #16] + WORD $0x6e182318 // ext v24.16b, v24.16b, v24.16b, #4 + WORD $0x6e196318 // ext v24.16b, v24.16b, v25.16b, #12 + WORD $0x6ea24739 // ushl v25.4s, v25.4s, v2.4s + WORD $0x6ea34718 // ushl v24.4s, v24.4s, v3.4s + WORD $0x4eb81f38 // orr v24.16b, v25.16b, v24.16b + WORD $0x6f077418 // bic v24.4s, #224, lsl #24 + WORD $0x3c9d0118 // stur q24, [x8, #-48] + WORD $0xfd401018 // ldr d24, [x0, #32] + WORD $0xbd401c19 // ldr s25, [x0, #28] + WORD $0xb940280c // ldr w12, [x0, #40] + WORD $0x2ea4471a // ushl v26.2s, v24.2s, v4.2s + WORD $0x0e0c3f0a // mov w10, v24.s[1] + WORD $0x0e983b39 // zip1 v25.2s, v25.2s, v24.2s + WORD $0x53027d4b // lsr w11, w10, #2 + WORD $0x138a7d8a // extr w10, w12, w10, #31 + WORD $0x2ea54739 // ushl v25.2s, v25.2s, v5.2s + WORD $0x0eb91f58 // orr v24.8b, v26.8b, v25.8b + WORD $0x4e141d78 // mov v24.s[2], w11 + WORD $0x4e1c1d58 // mov v24.s[3], w10 + WORD $0x6f077418 // bic v24.4s, #224, lsl #24 + WORD $0x3c9e0118 // stur q24, [x8, #-32] + WORD $0xbd402818 // ldr s24, [x0, #40] + WORD $0x3cc2c019 // ldur q25, [x0, #44] + WORD $0x6e182318 // ext v24.16b, v24.16b, v24.16b, #4 + WORD $0x6e196318 // ext v24.16b, v24.16b, v25.16b, #12 + WORD $0x6ea64739 // ushl v25.4s, v25.4s, v6.4s + WORD $0x6ea74718 // ushl v24.4s, v24.4s, v7.4s + WORD $0x4eb81f38 // orr v24.16b, v25.16b, v24.16b + WORD $0x6f077418 // bic v24.4s, #224, lsl #24 + WORD $0x3c9f0118 // stur q24, [x8, #-16] + WORD $0xbd403818 // ldr s24, [x0, #56] + WORD $0x3cc3c019 // ldur q25, [x0, #60] + WORD $0x6e182318 // ext v24.16b, v24.16b, v24.16b, #4 + WORD $0x6e196318 // ext v24.16b, v24.16b, v25.16b, #12 + WORD $0x6eb04739 // ushl v25.4s, v25.4s, v16.4s + WORD $0x6eb14718 // ushl v24.4s, v24.4s, v17.4s + WORD $0x4eb81f38 // orr v24.16b, v25.16b, v24.16b + WORD $0x6f077418 // bic v24.4s, #224, lsl #24 + WORD $0x3d800118 // str q24, [x8] + WORD $0x2949280b // ldp w11, w10, [x0, #72] + WORD $0xfd402818 // ldr d24, [x0, #80] + WORD $0x1e270159 // fmov s25, w10 + WORD $0x138b114b // extr w11, w10, w11, #4 + WORD $0x53017d4a // lsr w10, w10, #1 + WORD $0x0e983b39 // zip1 v25.2s, v25.2s, v24.2s + WORD $0x2eb24718 // ushl v24.2s, v24.2s, v18.2s + WORD $0x1e27017a // fmov s26, w11 + WORD $0x2eb34739 // ushl v25.2s, v25.2s, v19.2s + WORD $0x4e0c1d5a // mov v26.s[1], w10 + WORD $0x0eb91f18 // orr v24.8b, v24.8b, v25.8b + WORD $0x6e18071a // mov v26.d[1], v24.d[0] + WORD $0x6f07741a // bic v26.4s, #224, lsl #24 + WORD $0x3d80051a // str q26, [x8, #16] + WORD $0xbd405418 // ldr s24, [x0, #84] + WORD $0x3cc58019 // ldur q25, [x0, #88] + WORD $0x6e182318 // ext v24.16b, v24.16b, v24.16b, #4 + WORD $0x6e196318 // ext v24.16b, v24.16b, v25.16b, #12 + WORD $0x6eb44739 // ushl v25.4s, v25.4s, v20.4s + WORD $0x6eb54718 // ushl v24.4s, v24.4s, v21.4s + WORD $0x4eb81f38 // orr v24.16b, v25.16b, v24.16b + WORD $0x6f077418 // bic v24.4s, #224, lsl #24 + WORD $0x3d800918 // str q24, [x8, #32] + WORD $0xfd403418 // ldr d24, [x0, #104] + WORD $0xbd406419 // ldr s25, [x0, #100] + WORD $0xb940700b // ldr w11, [x0, #112] + WORD $0x9101d000 // add x0, x0, #116 + WORD $0x2eb6471a // ushl v26.2s, v24.2s, v22.2s + WORD $0x0e0c3f0a // mov w10, v24.s[1] + WORD $0x0e983b39 // zip1 v25.2s, v25.2s, v24.2s + WORD $0x138a196a // extr w10, w11, w10, #6 + WORD $0x2eb74739 // ushl v25.2s, v25.2s, v23.2s + WORD $0x0eb91f58 // orr v24.8b, v26.8b, v25.8b + WORD $0x4e141d58 // mov v24.s[2], w10 + WORD $0x53037d6a // lsr w10, w11, #3 + WORD $0x4e1c1d58 // mov v24.s[3], w10 + WORD $0x6f077418 // bic v24.4s, #224, lsl #24 + WORD $0x3d800d18 // str q24, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_64 + JMP LBB0_156 + +LBB0_65: + WORD $0x7100087f // cmp w3, #2 + BEQ LBB0_127 + + // %bb.66: + WORD $0x71000c7f // cmp w3, #3 + BNE LBB0_156 + + // %bb.67: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.68: + // WORD $0x90000008 // adrp x8, .LCPI0_188 + // WORD $0x90000009 // adrp x9, .LCPI0_189 + // WORD $0x9000000a // adrp x10, .LCPI0_190 + WORD $0x4f0004e7 // movi v7.4s, #7 + VMOVD LCPI0_188, V0 + // WORD $0x90000008 // adrp x8, .LCPI0_191 + VMOVQ LCPI0_189L, LCPI0_189H, V1 + // WORD $0x90000009 // adrp x9, .LCPI0_192 + VMOVD LCPI0_190, V2 + // WORD $0x9000000a // adrp x10, .LCPI0_193 + VMOVQ LCPI0_191L, LCPI0_191H, V3 + // WORD $0x90000008 // adrp x8, .LCPI0_194 + VMOVQ LCPI0_192L, LCPI0_192H, V4 + // WORD $0x90000009 // adrp x9, .LCPI0_195 + VMOVD LCPI0_193, V5 + VMOVQ LCPI0_194L, LCPI0_194H, V6 + WORD $0x91010348 // add x8, x26, #64 + VMOVQ LCPI0_195L, LCPI0_195H, V16 + WORD $0xaa1303e9 // mov x9, x19 + LBB0_69: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0xb940080c // ldr w12, [x0, #8] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x138a596d // extr w13, w11, w10, #22 - WORD $0x1e270147 // fmov s7, w10 - WORD $0x138b318b // extr w11, w12, w11, #12 - WORD $0x4e0c1da7 // mov v7.s[1], w13 - WORD $0x53027d8c // lsr w12, w12, #2 - WORD $0x4e141d67 // mov v7.s[2], w11 - WORD $0x4e1c1d87 // mov v7.s[3], w12 - WORD $0x4e201ce7 // and v7.16b, v7.16b, v0.16b - WORD $0x3c9c0127 // stur q7, [x9, #-64] - WORD $0xfc40c007 // ldur d7, [x0, #12] - WORD $0xbd400810 // ldr s16, [x0, #8] - WORD $0xb940140a // ldr w10, [x0, #20] - WORD $0x2ea144f1 // ushl v17.2s, v7.2s, v1.2s - WORD $0x0e873a10 // zip1 v16.2s, v16.2s, v7.2s - WORD $0x0e0c3ceb // mov w11, v7.s[1] - WORD $0x2ea44607 // ushl v7.2s, v16.2s, v4.2s - WORD $0x53047d6c // lsr w12, w11, #4 - WORD $0x0ea71e27 // orr v7.8b, v17.8b, v7.8b - WORD $0x138b694a // extr w10, w10, w11, #26 - WORD $0x4e141d87 // mov v7.s[2], w12 - WORD $0x4e1c1d47 // mov v7.s[3], w10 - WORD $0x4e201ce7 // and v7.16b, v7.16b, v0.16b - WORD $0x3c9d0127 // stur q7, [x9, #-48] - WORD $0x2942ac0a // ldp w10, w11, [x0, #20] - WORD $0xfc41c007 // ldur d7, [x0, #28] - WORD $0x1e270170 // fmov s16, w11 - WORD $0x138a416a // extr w10, w11, w10, #16 - WORD $0x0e873a10 // zip1 v16.2s, v16.2s, v7.2s - WORD $0x53067d6c // lsr w12, w11, #6 - WORD $0x2ea244e7 // ushl v7.2s, v7.2s, v2.2s - WORD $0x1e270151 // fmov s17, w10 - WORD $0x2ea54610 // ushl v16.2s, v16.2s, v5.2s - WORD $0x4e0c1d91 // mov v17.s[1], w12 - WORD $0x0eb01ce7 // orr v7.8b, v7.8b, v16.8b - WORD $0x6e1804f1 // mov v17.d[1], v7.d[0] - WORD $0x4e201e27 // and v7.16b, v17.16b, v0.16b - WORD $0x3c9e0127 // stur q7, [x9, #-32] - WORD $0xb940200a // ldr w10, [x0, #32] - WORD $0xfc424007 // ldur d7, [x0, #36] - WORD $0x1e270150 // fmov s16, w10 - WORD $0x0e873a10 // zip1 v16.2s, v16.2s, v7.2s - WORD $0x53087d4b // lsr w11, w10, #8 - WORD $0x2ea344f1 // ushl v17.2s, v7.2s, v3.2s - WORD $0x0e0c3cea // mov w10, v7.s[1] - WORD $0x2ea64607 // ushl v7.2s, v16.2s, v6.2s - WORD $0x1e270170 // fmov s16, w11 - WORD $0x0ea71e27 // orr v7.8b, v17.8b, v7.8b - WORD $0x6e0c04f0 // mov v16.s[1], v7.s[0] - WORD $0x530a7d4a // lsr w10, w10, #10 - WORD $0x6e1424f0 // mov v16.s[2], v7.s[1] - WORD $0x4e1c1d50 // mov v16.s[3], w10 - WORD $0x4e201e07 // and v7.16b, v16.16b, v0.16b - WORD $0x3c9f0127 // stur q7, [x9, #-16] - WORD $0x2945ac0a // ldp w10, w11, [x0, #44] - WORD $0x138a596d // extr w13, w11, w10, #22 - WORD $0x1e270147 // fmov s7, w10 - WORD $0x138b318b // extr w11, w12, w11, #12 - WORD $0x4e0c1da7 // mov v7.s[1], w13 - WORD $0x53027d8c // lsr w12, w12, #2 - WORD $0x4e141d67 // mov v7.s[2], w11 - WORD $0x4e1c1d87 // mov v7.s[3], w12 - WORD $0x4e201ce7 // and v7.16b, v7.16b, v0.16b - WORD $0x3d800127 // str q7, [x9] - WORD $0xfd401c07 // ldr d7, [x0, #56] - WORD $0xbd403410 // ldr s16, [x0, #52] - WORD $0xb940400a // ldr w10, [x0, #64] - WORD $0x2ea144f1 // ushl v17.2s, v7.2s, v1.2s - WORD $0x0e873a10 // zip1 v16.2s, v16.2s, v7.2s - WORD $0x0e0c3ceb // mov w11, v7.s[1] - WORD $0x2ea44607 // ushl v7.2s, v16.2s, v4.2s - WORD $0x53047d6c // lsr w12, w11, #4 - WORD $0x0ea71e27 // orr v7.8b, v17.8b, v7.8b - WORD $0x138b694a // extr w10, w10, w11, #26 - WORD $0x4e141d87 // mov v7.s[2], w12 - WORD $0x4e1c1d47 // mov v7.s[3], w10 - WORD $0x4e201ce7 // and v7.16b, v7.16b, v0.16b - WORD $0x3d800527 // str q7, [x9, #16] - WORD $0x29482c0a // ldp w10, w11, [x0, #64] - WORD $0xfd402407 // ldr d7, [x0, #72] - WORD $0x1e270170 // fmov s16, w11 - WORD $0x138a416a // extr w10, w11, w10, #16 - WORD $0x0e873a10 // zip1 v16.2s, v16.2s, v7.2s - WORD $0x53067d6c // lsr w12, w11, #6 - WORD $0x2ea244e7 // ushl v7.2s, v7.2s, v2.2s - WORD $0x1e270151 // fmov s17, w10 - WORD $0x2ea54610 // ushl v16.2s, v16.2s, v5.2s - WORD $0x4e0c1d91 // mov v17.s[1], w12 - WORD $0x0eb01ce7 // orr v7.8b, v7.8b, v16.8b - WORD $0x6e1804f1 // mov v17.d[1], v7.d[0] - WORD $0x4e201e27 // and v7.16b, v17.16b, v0.16b - WORD $0x3d800927 // str q7, [x9, #32] - WORD $0xb9404c0a // ldr w10, [x0, #76] - WORD $0xfd402807 // ldr d7, [x0, #80] - WORD $0x91016000 // add x0, x0, #88 - WORD $0x1e270150 // fmov s16, w10 - WORD $0x0e873a10 // zip1 v16.2s, v16.2s, v7.2s - WORD $0x53087d4b // lsr w11, w10, #8 - WORD $0x2ea344f1 // ushl v17.2s, v7.2s, v3.2s - WORD $0x0e0c3cea // mov w10, v7.s[1] - WORD $0x2ea64607 // ushl v7.2s, v16.2s, v6.2s - WORD $0x1e270170 // fmov s16, w11 - WORD $0x0ea71e27 // orr v7.8b, v17.8b, v7.8b - WORD $0x6e0c04f0 // mov v16.s[1], v7.s[0] - WORD $0x530a7d4a // lsr w10, w10, #10 - WORD $0x6e1424f0 // mov v16.s[2], v7.s[1] - WORD $0x4e1c1d50 // mov v16.s[3], w10 - WORD $0x4e201e07 // and v7.16b, v16.16b, v0.16b - WORD $0x3d800d27 // str q7, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - - BNE LBB0_69 - JMP LBB0_99 + WORD $0xb940000a // ldr w10, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x0e040d51 // dup v17.2s, w10 + WORD $0x1e270152 // fmov s18, w10 + WORD $0x53097d4a // lsr w10, w10, #9 + WORD $0x6e122252 // ext v18.16b, v18.16b, v18.16b, #4 + WORD $0x2ea04631 // ushl v17.2s, v17.2s, v0.2s + WORD $0x6e116251 // ext v17.16b, v18.16b, v17.16b, #12 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0xaa0003ea // mov x10, x0 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9c0111 // stur q17, [x8, #-64] + WORD $0x4ddfc951 // ld1r { v17.4s }, [x10], #4 + WORD $0x6ea14631 // ushl v17.4s, v17.4s, v1.4s + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9d0111 // stur q17, [x8, #-48] + WORD $0xb940000b // ldr w11, [x0] + WORD $0xb940014c // ldr w12, [x10] + WORD $0x0e040d71 // dup v17.2s, w11 + WORD $0x138b798b // extr w11, w12, w11, #30 + WORD $0x2ea24631 // ushl v17.2s, v17.2s, v2.2s + WORD $0x4e141d71 // mov v17.s[2], w11 + WORD $0x53017d8b // lsr w11, w12, #1 + WORD $0x4e1c1d71 // mov v17.s[3], w11 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9e0111 // stur q17, [x8, #-32] + WORD $0x4d40c951 // ld1r { v17.4s }, [x10] + WORD $0x6ea34631 // ushl v17.4s, v17.4s, v3.4s + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9f0111 // stur q17, [x8, #-16] + WORD $0x4d40c951 // ld1r { v17.4s }, [x10] + WORD $0x6ea44631 // ushl v17.4s, v17.4s, v4.4s + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800111 // str q17, [x8] + WORD $0xb940014a // ldr w10, [x10] + WORD $0xb940080b // ldr w11, [x0, #8] + WORD $0x531c7d4c // lsr w12, w10, #28 + WORD $0x138a7d6a // extr w10, w11, w10, #31 + WORD $0x0e040d71 // dup v17.2s, w11 + WORD $0x1e270192 // fmov s18, w12 + WORD $0x2ea54631 // ushl v17.2s, v17.2s, v5.2s + WORD $0x4e0c1d52 // mov v18.s[1], w10 + WORD $0x9100200a // add x10, x0, #8 + WORD $0x91003000 // add x0, x0, #12 + WORD $0x6e180632 // mov v18.d[1], v17.d[0] + WORD $0x4e271e51 // and v17.16b, v18.16b, v7.16b + WORD $0x3d800511 // str q17, [x8, #16] + WORD $0x4d40c951 // ld1r { v17.4s }, [x10] + WORD $0x6ea64631 // ushl v17.4s, v17.4s, v6.4s + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800911 // str q17, [x8, #32] + WORD $0x4d40c951 // ld1r { v17.4s }, [x10] + WORD $0x6eb04631 // ushl v17.4s, v17.4s, v16.4s + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800d11 // str q17, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_69 + JMP LBB0_156 + LBB0_70: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - MOVD $0x000000130000001c, R16 // LCPI0_70 - MOVD $0x0000000d00000004, R1 // LCPI0_71 - MOVD $0x0000000f00000018, R17 // LCPI0_72 - MOVD $0x0000001100000008, R2 // LCPI0_73 - MOVD $0x0000000b00000014, R25 // LCPI0_74 - MOVD $0x000000150000000c, R3 // LCPI0_75 - MOVD $0x000000150000001e, R19 // LCPI0_76 - MOVD $0x0000000b00000002, R4 // LCPI0_77 - MOVD $0x000000110000001a, R20 // LCPI0_78 - MOVD $0x0000000f00000006, R5 // LCPI0_79 - MOVD $0x000000160000001f, R21 // LCPI0_80 - MOVD $0x0000000a00000001, R6 // LCPI0_81 - MOVD $0x000000120000001b, R22 // LCPI0_82 - MOVD $0x0000000e00000005, R7 // LCPI0_83 - - WORD $0x91010029 // add x9, x1, #64 - WORD $0x4f03d7e0 // movi v0.4s, #127, msl #16 - WORD $0x2ea0ba10 // neg v16.2s, v16.2s - WORD $0x2ea0ba31 // neg v17.2s, v17.2s - WORD $0x2ea0bb39 //neg v25.2s, v25.2s - WORD $0x2ea0ba73 // neg v19.2s, v19.2s - WORD $0x2ea0ba94 // neg v20.2s, v20.2s - WORD $0x2ea0bab5 // neg v21.2s, v21.2s - WORD $0x2ea0bad6 // neg v22.2s, v22.2s -LBB0_72: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0xb940080c // ldr w12, [x0, #8] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x138a5d6d // extr w13, w11, w10, #23 - WORD $0x1e270157 // fmov s23, w10 - WORD $0x138b398b // extr w11, w12, w11, #14 - WORD $0x4e0c1db7 // mov v23.s[1], w13 - WORD $0x53057d8c // lsr w12, w12, #5 - WORD $0x4e141d77 // mov v23.s[2], w11 - WORD $0x4e1c1d97 // mov v23.s[3], w12 - WORD $0x4e201ef7 // and v23.16b, v23.16b, v0.16b - WORD $0x3c9c0137 // stur q23, [x9, #-64] - WORD $0xfc40c017 // ldur d23, [x0, #12] - WORD $0xbd400818 // ldr s24, [x0, #8] - WORD $0xb940140a // ldr w10, [x0, #20] - WORD $0x2ea146f9 // ushl v25.2s, v23.2s, v1.2s - WORD $0x0e973b18 // zip1 v24.2s, v24.2s, v23.2s - WORD $0x0e0c3eeb // mov w11, v23.s[1] - WORD $0x2eb04717 // ushl v23.2s, v24.2s, v16.2s - WORD $0x53017d4c // lsr w12, w10, #1 - WORD $0x138b294a // extr w10, w10, w11, #10 - WORD $0x0eb71f37 // orr v23.8b, v25.8b, v23.8b - WORD $0x4e141d57 // mov v23.s[2], w10 - WORD $0x4e1c1d97 // mov v23.s[3], w12 - WORD $0x4e201ef7 // and v23.16b, v23.16b, v0.16b - WORD $0x3c9d0137 // stur q23, [x9, #-48] - WORD $0xfd400c17 // ldr d23, [x0, #24] - WORD $0xbd401418 // ldr s24, [x0, #20] - WORD $0xb940200a // ldr w10, [x0, #32] - WORD $0x2ea246f9 // ushl v25.2s, v23.2s, v2.2s - WORD $0x0e973b18 // zip1 v24.2s, v24.2s, v23.2s - WORD $0x0e0c3eeb // mov w11, v23.s[1] - WORD $0x2eb14717 // ushl v23.2s, v24.2s, v17.2s - WORD $0x53067d6c // lsr w12, w11, #6 - WORD $0x0eb71f37 // orr v23.8b, v25.8b, v23.8b - WORD $0x138b754a // extr w10, w10, w11, #29 - WORD $0x4e141d97 // mov v23.s[2], w12 - WORD $0x4e1c1d57 // mov v23.s[3], w10 - WORD $0x4e201ef7 // and v23.16b, v23.16b, v0.16b - WORD $0x3c9e0137 // stur q23, [x9, #-32] - WORD $0xfc424017 // ldur d23, [x0, #36] - WORD $0xbd402018 // ldr s24, [x0, #32] - WORD $0xb9402c0a // ldr w10, [x0, #44] - WORD $0x2ea346f9 // ushl v25.2s, v23.2s, v3.2s - WORD $0x0e973b18 // zip1 v24.2s, v24.2s, v23.2s - WORD $0x0e0c3eeb // mov w11, v23.s[1] - WORD $0x2eb24717 // ushl v23.2s, v24.2s, v25.2s - WORD $0x53027d6c // lsr w12, w11, #2 - WORD $0x0eb71f37 // orr v23.8b, v25.8b, v23.8b - WORD $0x138b654a // extr w10, w10, w11, #25 - WORD $0x4e141d97 // mov v23.s[2], w12 - WORD $0x4e1c1d57 // mov v23.s[3], w10 - WORD $0x4e201ef7 // and v23.16b, v23.16b, v0.16b - WORD $0x3c9f0137 // stur q23, [x9, #-16] - WORD $0x2945ac0a // ldp w10, w11, [x0, #44] - WORD $0xfc434017 // ldur d23, [x0, #52] - WORD $0x1e270178 // fmov s24, w11 - WORD $0x138a416a // extr w10, w11, w10, #16 - WORD $0x0e973b18 // zip1 v24.2s, v24.2s, v23.2s - WORD $0x53077d6c // lsr w12, w11, #7 - WORD $0x2ea446f7 // ushl v23.2s, v23.2s, v4.2s - WORD $0x1e270159 // fmov s25, w10 - WORD $0x2eb34718 // ushl v24.2s, v24.2s, v19.2s - WORD $0x4e0c1d99 // mov v25.s[1], w12 - WORD $0x0eb81ef7 // orr v23.8b, v23.8b, v24.8b - WORD $0x6e1806f9 // mov v25.d[1], v23.d[0] - WORD $0x4e201f37 // and v23.16b, v25.16b, v0.16b - WORD $0x3d800137 // str q23, [x9] - WORD $0x29472c0a // ldp w10, w11, [x0, #56] - WORD $0xfd402017 // ldr d23, [x0, #64] - WORD $0x1e270178 // fmov s24, w11 - WORD $0x138a316a // extr w10, w11, w10, #12 - WORD $0x0e973b18 // zip1 v24.2s, v24.2s, v23.2s - WORD $0x53037d6c // lsr w12, w11, #3 - WORD $0x2ea546f7 // ushl v23.2s, v23.2s, v5.2s - WORD $0x1e270159 // fmov s25, w10 - WORD $0x2eb44718 // ushl v24.2s, v24.2s, v20.2s - WORD $0x4e0c1d99 // mov v25.s[1], w12 - WORD $0x0eb81ef7 // orr v23.8b, v23.8b, v24.8b - WORD $0x6e1806f9 // mov v25.d[1], v23.d[0] - WORD $0x4e201f37 // and v23.16b, v25.16b, v0.16b - WORD $0x3d800537 // str q23, [x9, #16] - WORD $0xb940440a // ldr w10, [x0, #68] - WORD $0xfd402417 // ldr d23, [x0, #72] - WORD $0xb940500b // ldr w11, [x0, #80] - WORD $0x1e270158 // fmov s24, w10 - WORD $0x0e973b18 // zip1 v24.2s, v24.2s, v23.2s - WORD $0x53087d4c // lsr w12, w10, #8 - WORD $0x2ea646f9 // ushl v25.2s, v23.2s, v6.2s - WORD $0x0e0c3eea // mov w10, v23.s[1] - WORD $0x2eb54717 // ushl v23.2s, v24.2s, v21.2s - WORD $0x1e270198 // fmov s24, w12 - WORD $0x0eb71f37 // orr v23.8b, v25.8b, v23.8b - WORD $0x6e0c06f8 // mov v24.s[1], v23.s[0] - WORD $0x138a356a // extr w10, w11, w10, #13 - WORD $0x6e1426f8 // mov v24.s[2], v23.s[1] - WORD $0x4e1c1d58 // mov v24.s[3], w10 - WORD $0x4e201f17 // and v23.16b, v24.16b, v0.16b - WORD $0x3d800937 // str q23, [x9, #32] - WORD $0xb940500a // ldr w10, [x0, #80] - WORD $0xfc454017 // ldur d23, [x0, #84] - WORD $0x91017000 // add x0, x0, #92 - WORD $0x1e270158 // fmov s24, w10 - WORD $0x0e973b18 // zip1 v24.2s, v24.2s, v23.2s - WORD $0x53047d4b // lsr w11, w10, #4 - WORD $0x2ea746f9 // ushl v25.2s, v23.2s, v7.2s - WORD $0x0e0c3eea // mov w10, v23.s[1] - WORD $0x2eb64717 // ushl v23.2s, v24.2s, v22.2s - WORD $0x1e270178 // fmov s24, w11 - WORD $0x0eb71f37 // orr v23.8b, v25.8b, v23.8b - WORD $0x6e0c06f8 // mov v24.s[1], v23.s[0] - WORD $0x53097d4a // lsr w10, w10, #9 - WORD $0x6e1426f8 // mov v24.s[2], v23.s[1] - WORD $0x4e1c1d58 // mov v24.s[3], w10 - WORD $0x4e201f17 // and v23.16b, v24.16b, v0.16b - WORD $0x3d800d37 // str q23, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - - BNE LBB0_72 - JMP LBB0_99 -LBB0_73: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - WORD $0x91001829 // add x9, x1, #6 + WORD $0x7100487f // cmp w3, #18 + BEQ LBB0_130 + + // %bb.71: + WORD $0x71004c7f // cmp w3, #19 + BNE LBB0_156 + + // %bb.72: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.73: + // WORD $0x90000008 // adrp x8, .LCPI0_130 + // WORD $0x90000009 // adrp x9, .LCPI0_131 + // WORD $0x9000000a // adrp x10, .LCPI0_132 + WORD $0x4f00d4e7 // movi v7.4s, #7, msl #16 + VMOVD LCPI0_130, V0 + // WORD $0x90000008 // adrp x8, .LCPI0_133 + VMOVD LCPI0_131, V1 + // WORD $0x90000009 // adrp x9, .LCPI0_134 + VMOVD LCPI0_132, V2 + // WORD $0x9000000a // adrp x10, .LCPI0_135 + VMOVD LCPI0_133, V3 + // WORD $0x90000008 // adrp x8, .LCPI0_136 + VMOVD LCPI0_134, V4 + // WORD $0x90000009 // adrp x9, .LCPI0_137 + VMOVD LCPI0_135, V5 + VMOVD LCPI0_136, V6 + WORD $0x91010348 // add x8, x26, #64 + VMOVD LCPI0_137, V16 + WORD $0xaa1303e9 // mov x9, x19 + +LBB0_74: + WORD $0x29402c0a // ldp w10, w11, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x138a4d6c // extr w12, w11, w10, #19 + WORD $0x1e270151 // fmov s17, w10 + WORD $0x53067d6a // lsr w10, w11, #6 + WORD $0x4e0c1d91 // mov v17.s[1], w12 + WORD $0xb940080c // ldr w12, [x0, #8] + WORD $0x4e141d51 // mov v17.s[2], w10 + WORD $0x138b658a // extr w10, w12, w11, #25 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9c0111 // stur q17, [x8, #-64] + WORD $0xb940080a // ldr w10, [x0, #8] + WORD $0xfc40c011 // ldur d17, [x0, #12] + WORD $0x1e270152 // fmov s18, w10 + WORD $0x530c7d4a // lsr w10, w10, #12 + WORD $0x2ea04633 // ushl v19.2s, v17.2s, v0.2s + WORD $0x0e913a52 // zip1 v18.2s, v18.2s, v17.2s + WORD $0x1e270154 // fmov s20, w10 + WORD $0x0e0c3e2a // mov w10, v17.s[1] + WORD $0x6e142294 // ext v20.16b, v20.16b, v20.16b, #4 + WORD $0x2ea14652 // ushl v18.2s, v18.2s, v1.2s + WORD $0x53057d4a // lsr w10, w10, #5 + WORD $0x0eb21e72 // orr v18.8b, v19.8b, v18.8b + WORD $0x6e126291 // ext v17.16b, v20.16b, v18.16b, #12 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9d0111 // stur q17, [x8, #-48] + WORD $0x2942280b // ldp w11, w10, [x0, #16] + WORD $0xfd400c11 // ldr d17, [x0, #24] + WORD $0x1e270152 // fmov s18, w10 + WORD $0x138b614b // extr w11, w10, w11, #24 + WORD $0x530b7d4a // lsr w10, w10, #11 + WORD $0x0e913a52 // zip1 v18.2s, v18.2s, v17.2s + WORD $0x2ea24631 // ushl v17.2s, v17.2s, v2.2s + WORD $0x1e270173 // fmov s19, w11 + WORD $0x2ea34652 // ushl v18.2s, v18.2s, v3.2s + WORD $0x4e0c1d53 // mov v19.s[1], w10 + WORD $0x0eb21e31 // orr v17.8b, v17.8b, v18.8b + WORD $0x6e180633 // mov v19.d[1], v17.d[0] + WORD $0x4e271e71 // and v17.16b, v19.16b, v7.16b + WORD $0x3c9e0111 // stur q17, [x8, #-32] + WORD $0x2943ac0a // ldp w10, w11, [x0, #28] + WORD $0x53047d4c // lsr w12, w10, #4 + WORD $0x138a5d6a // extr w10, w11, w10, #23 + WORD $0x1e270191 // fmov s17, w12 + WORD $0xb940240c // ldr w12, [x0, #36] + WORD $0x4e0c1d51 // mov v17.s[1], w10 + WORD $0x530a7d6a // lsr w10, w11, #10 + WORD $0x4e141d51 // mov v17.s[2], w10 + WORD $0x138b758a // extr w10, w12, w11, #29 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9f0111 // stur q17, [x8, #-16] + WORD $0x2944ac0a // ldp w10, w11, [x0, #36] + WORD $0x138a416a // extr w10, w11, w10, #16 + WORD $0x53037d6c // lsr w12, w11, #3 + WORD $0x1e270151 // fmov s17, w10 + WORD $0xb9402c0a // ldr w10, [x0, #44] + WORD $0x138b594b // extr w11, w10, w11, #22 + WORD $0x4e0c1d91 // mov v17.s[1], w12 + WORD $0x53097d4a // lsr w10, w10, #9 + WORD $0x4e141d71 // mov v17.s[2], w11 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800111 // str q17, [x8] + WORD $0xfd401811 // ldr d17, [x0, #48] + WORD $0xbd402c12 // ldr s18, [x0, #44] + WORD $0xb940380c // ldr w12, [x0, #56] + WORD $0x2ea44633 // ushl v19.2s, v17.2s, v4.2s + WORD $0x0e0c3e2a // mov w10, v17.s[1] + WORD $0x0e913a52 // zip1 v18.2s, v18.2s, v17.2s + WORD $0x53027d4b // lsr w11, w10, #2 + WORD $0x138a558a // extr w10, w12, w10, #21 + WORD $0x2ea54652 // ushl v18.2s, v18.2s, v5.2s + WORD $0x0eb21e71 // orr v17.8b, v19.8b, v18.8b + WORD $0x4e141d71 // mov v17.s[2], w11 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800511 // str q17, [x8, #16] + WORD $0xb940380a // ldr w10, [x0, #56] + WORD $0xfc43c011 // ldur d17, [x0, #60] + WORD $0x1e270152 // fmov s18, w10 + WORD $0x53087d4a // lsr w10, w10, #8 + WORD $0x2ea64633 // ushl v19.2s, v17.2s, v6.2s + WORD $0x0e913a52 // zip1 v18.2s, v18.2s, v17.2s + WORD $0x1e270154 // fmov s20, w10 + WORD $0x0e0c3e2a // mov w10, v17.s[1] + WORD $0x6e142294 // ext v20.16b, v20.16b, v20.16b, #4 + WORD $0x2eb04652 // ushl v18.2s, v18.2s, v16.2s + WORD $0x53017d4a // lsr w10, w10, #1 + WORD $0x0eb21e72 // orr v18.8b, v19.8b, v18.8b + WORD $0x6e126291 // ext v17.16b, v20.16b, v18.16b, #12 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800911 // str q17, [x8, #32] + WORD $0x29482c0a // ldp w10, w11, [x0, #64] + WORD $0x138a516a // extr w10, w11, w10, #20 + WORD $0x53077d6c // lsr w12, w11, #7 + WORD $0x1e270151 // fmov s17, w10 + WORD $0xb940480a // ldr w10, [x0, #72] + WORD $0x91013000 // add x0, x0, #76 + WORD $0x138b694b // extr w11, w10, w11, #26 + WORD $0x4e0c1d91 // mov v17.s[1], w12 + WORD $0x530d7d4a // lsr w10, w10, #13 + WORD $0x4e141d71 // mov v17.s[2], w11 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800d11 // str q17, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_74 + JMP LBB0_156 + LBB0_75: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0xb940080c // ldr w12, [x0, #8] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x138a616d // extr w13, w11, w10, #24 - WORD $0x1e270140 // fmov s0, w10 - WORD $0x138b418b // extr w11, w12, w11, #16 - WORD $0x4e0c1da0 // mov v0.s[1], w13 - WORD $0x53087d8c // lsr w12, w12, #8 - WORD $0x4e141d60 // mov v0.s[2], w11 - WORD $0x4e1c1d80 // mov v0.s[3], w12 - WORD $0x6f0777e0 // bic v0.4s, #255, lsl #24 - WORD $0x3c9c0120 // stur q0, [x9, #-64] - WORD $0x2941ac0a // ldp w10, w11, [x0, #12] - WORD $0xb940140c // ldr w12, [x0, #20] - WORD $0x138a616d // extr w13, w11, w10, #24 - WORD $0x1e270140 // fmov s0, w10 - WORD $0x138b418b // extr w11, w12, w11, #16 - WORD $0x4e0c1da0 // mov v0.s[1], w13 - WORD $0x53087d8c // lsr w12, w12, #8 - WORD $0x4e141d60 // mov v0.s[2], w11 - WORD $0x4e1c1d80 // mov v0.s[3], w12 - WORD $0x6f0777e0 // bic v0.4s, #255, lsl #24 - WORD $0x3c9d0120 // stur q0, [x9, #-48] - WORD $0x29432c0a // ldp w10, w11, [x0, #24] - WORD $0xb940200c // ldr w12, [x0, #32] - WORD $0x138a616d // extr w13, w11, w10, #24 - WORD $0x1e270140 // fmov s0, w10 - WORD $0x138b418b // extr w11, w12, w11, #16 - WORD $0x4e0c1da0 // mov v0.s[1], w13 - WORD $0x53087d8c // lsr w12, w12, #8 - WORD $0x4e141d60 // mov v0.s[2], w11 - WORD $0x4e1c1d80 // mov v0.s[3], w12 - WORD $0x6f0777e0 // bic v0.4s, #255, lsl #24 - WORD $0x3c9e0120 // stur q0, [x9, #-32] - WORD $0x2944ac0a // ldp w10, w11, [x0, #36] - WORD $0xb9402c0c // ldr w12, [x0, #44] - WORD $0x138a616d // extr w13, w11, w10, #24 - WORD $0x1e270140 // fmov s0, w10 - WORD $0x138b418b // extr w11, w12, w11, #16 - WORD $0x4e0c1da0 // mov v0.s[1], w13 - WORD $0x53087d8c // lsr w12, w12, #8 - WORD $0x4e141d60 // mov v0.s[2], w11 - WORD $0x4e1c1d80 // mov v0.s[3], w12 - WORD $0x6f0777e0 // bic v0.4s, #255, lsl #24 - WORD $0x3c9f0120 // stur q0, [x9, #-16] - WORD $0x29462c0a // ldp w10, w11, [x0, #48] - WORD $0xb940380c // ldr w12, [x0, #56] - WORD $0x138a616d // extr w13, w11, w10, #24 - WORD $0x1e270140 // fmov s0, w10 - WORD $0x138b418b // extr w11, w12, w11, #16 - WORD $0x4e0c1da0 // mov v0.s[1], w13 - WORD $0x53087d8c // lsr w12, w12, #8 - WORD $0x4e141d60 // mov v0.s[2], w11 - WORD $0x4e1c1d80 // mov v0.s[3], w12 - WORD $0x6f0777e0 // bic v0.4s, #255, lsl #24 - WORD $0x3d800120 // str q0, [x9] - WORD $0x2947ac0a // ldp w10, w11, [x0, #60] - WORD $0xb940440c // ldr w12, [x0, #68] - WORD $0x138a616d // extr w13, w11, w10, #24 - WORD $0x1e270140 // fmov s0, w10 - WORD $0x138b418b // extr w11, w12, w11, #16 - WORD $0x4e0c1da0 // mov v0.s[1], w13 - WORD $0x53087d8c // lsr w12, w12, #8 - WORD $0x4e141d60 // mov v0.s[2], w11 - WORD $0x4e1c1d80 // mov v0.s[3], w12 - WORD $0x6f0777e0 // bic v0.4s, #255, lsl #24 - WORD $0x3d800520 // str q0, [x9, #16] - WORD $0x29492c0a // ldp w10, w11, [x0, #72] - WORD $0xb940500c // ldr w12, [x0, #80] - WORD $0x138a616d // extr w13, w11, w10, #24 - WORD $0x1e270140 // fmov s0, w10 - WORD $0x138b418b // extr w11, w12, w11, #16 - WORD $0x4e0c1da0 // mov v0.s[1], w13 - WORD $0x53087d8c // lsr w12, w12, #8 - WORD $0x4e141d60 // mov v0.s[2], w11 - WORD $0x4e1c1d80 // mov v0.s[3], w12 - WORD $0x6f0777e0 // bic v0.4s, #255, lsl #24 - WORD $0x3d800920 // str q0, [x9, #32] - WORD $0x294aac0a // ldp w10, w11, [x0, #84] - WORD $0xb9405c0c // ldr w12, [x0, #92] - WORD $0x91018000 // add x0, x0, #96 - WORD $0x138a616d // extr w13, w11, w10, #24 - WORD $0x1e270140 // fmov s0, w10 - WORD $0x138b418b // extr w11, w12, w11, #16 - WORD $0x4e0c1da0 // mov v0.s[1], w13 - WORD $0x53087d8c // lsr w12, w12, #8 - WORD $0x4e141d60 // mov v0.s[2], w11 - WORD $0x4e1c1d80 // mov v0.s[3], w12 - WORD $0x6f0777e0 // bic v0.4s, #255, lsl #24 - WORD $0x3d800d20 // str q0, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - - BNE LBB0_75 - JMP LBB0_99 -LBB0_76: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - MOVD $0x000000160000001d, R7 // LCPI0_56 - MOVD $0x0000000a00000003, R0 // LCPI0_57 - MOVD $0x000000130000001a, R16 // LCPI0_58 - MOVD $0x0000000d00000006, R1 // LCPI0_59 - MOVD $0x000000170000001e, R17 // LCPI0_60 - MOVD $0x0000000900000002, R2 // LCPI0_61 - MOVD $0x0000000900000010, R25 // LCPI0_62 - MOVD $0x0000001700000010, R3 // LCPI0_63 - MOVD $0x0000000d00000014, R19 // LCPI0_64 - MOVD $0x000000130000000c, R4 // LCPI0_65 - MOVD $0x0000001100000018, R20 // LCPI0_66 - MOVD $0x0000000f00000008, R5 // LCPI0_67 - MOVD $0x000000150000001c, R21 // LCPI0_68 - MOVD $0x0000000b00000004, R6 // LCPI0_69 - - WORD $0x91010029 // add x9, x1, #64 - WORD $0x2ea0b8e7 // neg v7.2s, v7.2s - WORD $0x2ea0ba10 // neg v16.2s, v16.2s - WORD $0x2ea0ba31 // neg v17.2s, v17.2s - WORD $0x2ea0bb39 // neg v25.2s, v25.2s - WORD $0x2ea0ba73 // neg v19.2s, v19.2s - WORD $0x2ea0ba94 // neg v20.2s, v20.2s - WORD $0x2ea0bab5 // neg v21.2s, v21.2s -LBB0_78: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0x2941340c // ldp w12, w13, [x0, #8] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x138a656e // extr w14, w11, w10, #25 - WORD $0x1e270156 // fmov s22, w10 - WORD $0x138b498b // extr w11, w12, w11, #18 - WORD $0x4e0c1dd6 // mov v22.s[1], w14 - WORD $0x138c2dac // extr w12, w13, w12, #11 - WORD $0x4e141d76 // mov v22.s[2], w11 - WORD $0x4e1c1d96 // mov v22.s[3], w12 - WORD $0x6f0777d6 // bic v22.4s, #254, lsl #24 - WORD $0x3c9c0136 // stur q22, [x9, #-64] - WORD $0xb9400c0a // ldr w10, [x0, #12] - WORD $0xfd400816 // ldr d22, [x0, #16] - WORD $0xb940180b // ldr w11, [x0, #24] - WORD $0x1e270157 // fmov s23, w10 - WORD $0x0e963af7 // zip1 v23.2s, v23.2s, v22.2s - WORD $0x53047d4c // lsr w12, w10, #4 - WORD $0x2ea046d8 // ushl v24.2s, v22.2s, v0.2s - WORD $0x0e0c3eca // mov w10, v22.s[1] - WORD $0x2ea746f6 // ushl v22.2s, v23.2s, v7.2s - WORD $0x1e270197 // fmov s23, w12 - WORD $0x0eb61f16 // orr v22.8b, v24.8b, v22.8b - WORD $0x6e0c06d7 // mov v23.s[1], v22.s[0] - WORD $0x138a3d6a // extr w10, w11, w10, #15 - WORD $0x6e1426d7 // mov v23.s[2], v22.s[1] - WORD $0x4e1c1d57 // mov v23.s[3], w10 - WORD $0x6f0777d7 // bic v23.4s, #254, lsl #24 - WORD $0x3c9d0137 // stur q23, [x9, #-48] - WORD $0x29432c0a // ldp w10, w11, [x0, #24] - WORD $0xfd401016 // ldr d22, [x0, #32] - WORD $0x1e270177 // fmov s23, w11 - WORD $0x138a216a // extr w10, w11, w10, #8 - WORD $0x0e963af7 // zip1 v23.2s, v23.2s, v22.2s - WORD $0x53017d6c // lsr w12, w11, #1 - WORD $0x2ea146d6 // ushl v22.2s, v22.2s, v1.2s - WORD $0x1e270158 // fmov s24, w10 - WORD $0x2eb046f7 // ushl v23.2s, v23.2s, v16.2s - WORD $0x4e0c1d98 // mov v24.s[1], w12 - WORD $0x0eb71ed6 // orr v22.8b, v22.8b, v23.8b - WORD $0x6e1806d8 // mov v24.d[1], v22.d[0] - WORD $0x6f0777d8 // bic v24.4s, #254, lsl #24 - WORD $0x3c9e0138 // stur q24, [x9, #-32] - WORD $0x2944ac0a // ldp w10, w11, [x0, #36] - WORD $0xfc42c016 // ldur d22, [x0, #44] - WORD $0x1e270177 // fmov s23, w11 - WORD $0x138a316a // extr w10, w11, w10, #12 - WORD $0x0e963af7 // zip1 v23.2s, v23.2s, v22.2s - WORD $0x53057d6c // lsr w12, w11, #5 - WORD $0x2ea246d6 // ushl v22.2s, v22.2s, v2.2s - WORD $0x1e270158 // fmov s24, w10 - WORD $0x2eb146f7 // ushl v23.2s, v23.2s, v17.2s - WORD $0x4e0c1d98 // mov v24.s[1], w12 - WORD $0x0eb71ed6 // orr v22.8b, v22.8b, v23.8b - WORD $0x6e1806d8 // mov v24.d[1], v22.d[0] - WORD $0x6f0777d8 // bic v24.4s, #254, lsl #24 - WORD $0x3c9f0138 // stur q24, [x9, #-16] - WORD $0xfc434016 // ldur d22, [x0, #52] - WORD $0xbd403017 // ldr s23, [x0, #48] - WORD $0xb9403c0a // ldr w10, [x0, #60] - WORD $0x2ea346d8 // ushl v24.2s, v22.2s, v3.2s - WORD $0x0e963af7 // zip1 v23.2s, v23.2s, v22.2s - WORD $0x0e0c3ecb // mov w11, v22.s[1] - WORD $0x2eb246f6 // ushl v22.2s, v23.2s, v25.2s - WORD $0x53027d6c // lsr w12, w11, #2 - WORD $0x0eb61f16 // orr v22.8b, v24.8b, v22.8b - WORD $0x138b6d4a // extr w10, w10, w11, #27 - WORD $0x4e141d96 // mov v22.s[2], w12 - WORD $0x4e1c1d56 // mov v22.s[3], w10 - WORD $0x6f0777d6 // bic v22.4s, #254, lsl #24 - WORD $0x3d800136 // str q22, [x9] - WORD $0xfd402016 // ldr d22, [x0, #64] - WORD $0xbd403c17 // ldr s23, [x0, #60] - WORD $0xb940480a // ldr w10, [x0, #72] - WORD $0x2ea446d8 // ushl v24.2s, v22.2s, v4.2s - WORD $0x0e963af7 // zip1 v23.2s, v23.2s, v22.2s - WORD $0x0e0c3ecb // mov w11, v22.s[1] - WORD $0x2eb346f6 // ushl v22.2s, v23.2s, v19.2s - WORD $0x53067d6c // lsr w12, w11, #6 - WORD $0x0eb61f16 // orr v22.8b, v24.8b, v22.8b - WORD $0x138b7d4a // extr w10, w10, w11, #31 - WORD $0x4e141d96 // mov v22.s[2], w12 - WORD $0x4e1c1d56 // mov v22.s[3], w10 - WORD $0x6f0777d6 // bic v22.4s, #254, lsl #24 - WORD $0x3d800536 // str q22, [x9, #16] - WORD $0xfc44c016 // ldur d22, [x0, #76] - WORD $0xbd404817 // ldr s23, [x0, #72] - WORD $0xb940540a // ldr w10, [x0, #84] - WORD $0x2ea546d8 // ushl v24.2s, v22.2s, v5.2s - WORD $0x0e963af7 // zip1 v23.2s, v23.2s, v22.2s - WORD $0x0e0c3ecb // mov w11, v22.s[1] - WORD $0x2eb446f6 // ushl v22.2s, v23.2s, v20.2s - WORD $0x53037d4c // lsr w12, w10, #3 - WORD $0x138b294a // extr w10, w10, w11, #10 - WORD $0x0eb61f16 // orr v22.8b, v24.8b, v22.8b - WORD $0x4e141d56 // mov v22.s[2], w10 - WORD $0x4e1c1d96 // mov v22.s[3], w12 - WORD $0x6f0777d6 // bic v22.4s, #254, lsl #24 - WORD $0x3d800936 // str q22, [x9, #32] - WORD $0xfd402c16 // ldr d22, [x0, #88] - WORD $0xbd405417 // ldr s23, [x0, #84] - WORD $0xb940600a // ldr w10, [x0, #96] - WORD $0x91019000 // add x0, x0, #100 - WORD $0x2ea646d8 // ushl v24.2s, v22.2s, v6.2s - WORD $0x0e963af7 // zip1 v23.2s, v23.2s, v22.2s - WORD $0x0e0c3ecb // mov w11, v22.s[1] - WORD $0x2eb546f6 // ushl v22.2s, v23.2s, v21.2s - WORD $0x138b394a // extr w10, w10, w11, #14 - WORD $0x0eb61f16 // orr v22.8b, v24.8b, v22.8b - WORD $0x4e141d56 // mov v22.s[2], w10 - WORD $0x4e1c1d96 // mov v22.s[3], w12 - WORD $0x6f0777d6 // bic v22.4s, #254, lsl #24 - WORD $0x3d800d36 // str q22, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - - BNE LBB0_78 - JMP LBB0_99 + WORD $0x7100287f // cmp w3, #10 + BEQ LBB0_133 + + // %bb.76: + WORD $0x71002c7f // cmp w3, #11 + BNE LBB0_156 + + // %bb.77: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.78: + // WORD $0x90000009 // adrp x9, .LCPI0_147 + // WORD $0x90000008 // adrp x8, .LCPI0_146 + // WORD $0x9000000a // adrp x10, .LCPI0_148 + WORD $0x4f00c4e6 // movi v6.4s, #7, msl #8 + VMOVD LCPI0_147, V1 + // WORD $0x90000009 // adrp x9, .LCPI0_150 + VMOVD LCPI0_146, V0 + // WORD $0x90000008 // adrp x8, .LCPI0_149 + VMOVD LCPI0_148, V2 + // WORD $0x9000000a // adrp x10, .LCPI0_151 + VMOVD LCPI0_150, V4 + // WORD $0x90000009 // adrp x9, .LCPI0_152 + VMOVD LCPI0_149, V3 + WORD $0x91010348 // add x8, x26, #64 + VMOVD LCPI0_151, V5 + VMOVD LCPI0_152, V7 + WORD $0xaa1303e9 // mov x9, x19 + LBB0_79: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - MOVD $0x000000070000000c, R7 // LCPI0_36 - MOVD $0x0000001900000014, R0 // LCPI0_37 - VMOVQ $0x0000001300000018, $0x000000090000000e, V16 // LCPI0_38 - VMOVQ $0x0000000d00000008, $0x0000001700000012, V1 // LCPI0_39 - MOVD $0x0000001a0000001f, R17 // LCPI0_40 - MOVD $0x0000000600000001, R2 // LCPI0_41 - MOVD $0x0000000b00000010, R25 // LCPI0_42 - MOVD $0x0000001500000010, R3 // LCPI0_43 - VMOVQ $0x000000170000001c, $0x0000000d00000012, V19 // LCPI0_44 - VMOVQ $0x0000000900000004, $0x000000130000000e, V4 // LCPI0_45 - MOVD $0x000000190000001e, R20 // LCPI0_46 - MOVD $0x0000000700000002, R5 // LCPI0_47 - MOVD $0x0000000f00000014, R21 // LCPI0_48 - MOVD $0x000000110000000c, R6 // LCPI0_49 - - WORD $0x91010029 // add x9, x1, #64 - WORD $0x2ea0b8e7 // neg v7.2s, v7.2s - WORD $0x6ea0ba10 // neg v16.4s, v16.4s - WORD $0x2ea0ba31 // neg v17.2s, v17.2s - WORD $0x2ea0bb39 // neg v25.2s, v25.2s - WORD $0x6ea0ba73 // neg v19.4s, v19.4s - WORD $0x2ea0ba94 // neg v20.2s, v20.2s - WORD $0x2ea0bab5 // neg v21.2s, v21.2s -LBB0_81: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0x2941340c // ldp w12, w13, [x0, #8] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x138a6d6e // extr w14, w11, w10, #27 - WORD $0x1e270156 // fmov s22, w10 - WORD $0x138b598b // extr w11, w12, w11, #22 - WORD $0x4e0c1dd6 // mov v22.s[1], w14 - WORD $0x138c45ac // extr w12, w13, w12, #17 - WORD $0x4e141d76 // mov v22.s[2], w11 - WORD $0x4e1c1d96 // mov v22.s[3], w12 - WORD $0x6f077716 // bic v22.4s, #248, lsl #24 - WORD $0x3c9c0136 // stur q22, [x9, #-64] - WORD $0xfd400816 // ldr d22, [x0, #16] - WORD $0xbd400c17 // ldr s23, [x0, #12] - WORD $0xb940180a // ldr w10, [x0, #24] - WORD $0x2ea046d8 // ushl v24.2s, v22.2s, v0.2s - WORD $0x0e963af7 // zip1 v23.2s, v23.2s, v22.2s - WORD $0x0e0c3ecb // mov w11, v22.s[1] - WORD $0x2ea746f6 // ushl v22.2s, v23.2s, v7.2s - WORD $0x53027d6c // lsr w12, w11, #2 - WORD $0x0eb61f16 // orr v22.8b, v24.8b, v22.8b - WORD $0x138b754a // extr w10, w10, w11, #29 - WORD $0x4e141d96 // mov v22.s[2], w12 - WORD $0x4e1c1d56 // mov v22.s[3], w10 - WORD $0x6f077716 // bic v22.4s, #248, lsl #24 - WORD $0x3c9d0136 // stur q22, [x9, #-48] - WORD $0xbd401816 // ldr s22, [x0, #24] - WORD $0x3cc1c017 // ldur q23, [x0, #28] - WORD $0x6e1622d6 // ext v22.16b, v22.16b, v22.16b, #4 - WORD $0x6e1762d6 // ext v22.16b, v22.16b, v23.16b, #12 - WORD $0x6ea146f8 // ushl v24.4s, v23.4s, v1.4s - WORD $0x6eb046d6 // ushl v22.4s, v22.4s, v16.4s - WORD $0x4eb61f16 // orr v22.16b, v24.16b, v22.16b - WORD $0x6f077716 // bic v22.4s, #248, lsl #24 - WORD $0x3c9e0136 // stur q22, [x9, #-32] - WORD $0xb940280a // ldr w10, [x0, #40] - WORD $0xfc42c016 // ldur d22, [x0, #44] - WORD $0xb940340b // ldr w11, [x0, #52] - WORD $0x1e270157 // fmov s23, w10 - WORD $0x0e963af7 // zip1 v23.2s, v23.2s, v22.2s - WORD $0x53047d4c // lsr w12, w10, #4 - WORD $0x2ea246d8 // ushl v24.2s, v22.2s, v2.2s - WORD $0x0e0c3eca // mov w10, v22.s[1] - WORD $0x2eb146f6 // ushl v22.2s, v23.2s, v17.2s - WORD $0x1e270197 // fmov s23, w12 - WORD $0x0eb61f16 // orr v22.8b, v24.8b, v22.8b - WORD $0x6e0c06d7 // mov v23.s[1], v22.s[0] - WORD $0x138a556a // extr w10, w11, w10, #21 - WORD $0x6e1426d7 // mov v23.s[2], v22.s[1] - WORD $0x4e1c1d57 // mov v23.s[3], w10 - WORD $0x6f077717 // bic v23.4s, #248, lsl #24 - WORD $0x3c9f0137 // stur q23, [x9, #-16] - WORD $0xfd401c16 // ldr d22, [x0, #56] - WORD $0xbd403417 // ldr s23, [x0, #52] - WORD $0xb940400a // ldr w10, [x0, #64] - WORD $0x2ea346d8 // ushl v24.2s, v22.2s, v3.2s - WORD $0x0e963af7 // zip1 v23.2s, v23.2s, v22.2s - WORD $0x0e0c3ecb // mov w11, v22.s[1] - WORD $0x2eb246f6 // ushl v22.2s, v23.2s, v25.2s - WORD $0x53017d4c // lsr w12, w10, #1 - WORD $0x138b194a // extr w10, w10, w11, #6 - WORD $0x0eb61f16 // orr v22.8b, v24.8b, v22.8b - WORD $0x4e141d56 // mov v22.s[2], w10 - WORD $0x4e1c1d96 // mov v22.s[3], w12 - WORD $0x6f077716 // bic v22.4s, #248, lsl #24 - WORD $0x3d800136 // str q22, [x9] - WORD $0xbd404016 // ldr s22, [x0, #64] - WORD $0x3cc44017 // ldur q23, [x0, #68] - WORD $0x6e1622d6 // ext v22.16b, v22.16b, v22.16b, #4 - WORD $0x6e1762d6 // ext v22.16b, v22.16b, v23.16b, #12 - WORD $0x6ea446f8 // ushl v24.4s, v23.4s, v4.4s - WORD $0x6eb346d6 // ushl v22.4s, v22.4s, v19.4s - WORD $0x4eb61f16 // orr v22.16b, v24.16b, v22.16b - WORD $0x6f077716 // bic v22.4s, #248, lsl #24 - WORD $0x3d800536 // str q22, [x9, #16] - WORD $0x294a2c0a // ldp w10, w11, [x0, #80] - WORD $0xfd402c16 // ldr d22, [x0, #88] - WORD $0x1e270177 // fmov s23, w11 - WORD $0x138a216a // extr w10, w11, w10, #8 - WORD $0x0e963af7 // zip1 v23.2s, v23.2s, v22.2s - WORD $0x53037d6c // lsr w12, w11, #3 - WORD $0x2ea546d6 // ushl v22.2s, v22.2s, v5.2s - WORD $0x1e270158 // fmov s24, w10 - WORD $0x2eb446f7 // ushl v23.2s, v23.2s, v20.2s - WORD $0x4e0c1d98 // mov v24.s[1], w12 - WORD $0x0eb71ed6 // orr v22.8b, v22.8b, v23.8b - WORD $0x6e1806d8 // mov v24.d[1], v22.d[0] - WORD $0x6f077718 // bic v24.4s, #248, lsl #24 - WORD $0x3d800938 // str q24, [x9, #32] - WORD $0xfd403016 // ldr d22, [x0, #96] - WORD $0xbd405c17 // ldr s23, [x0, #92] - WORD $0xb940680a // ldr w10, [x0, #104] - WORD $0x9101b000 // add x0, x0, #108 - WORD $0x2ea646d8 // ushl v24.2s, v22.2s, v6.2s - WORD $0x0e963af7 // zip1 v23.2s, v23.2s, v22.2s - WORD $0x0e0c3ecb // mov w11, v22.s[1] - WORD $0x2eb546f6 // ushl v22.2s, v23.2s, v21.2s - WORD $0x53057d4c // lsr w12, w10, #5 - WORD $0x138b294a // extr w10, w10, w11, #10 - WORD $0x0eb61f16 // orr v22.8b, v24.8b, v22.8b - WORD $0x4e141d56 // mov v22.s[2], w10 - WORD $0x4e1c1d96 // mov v22.s[3], w12 - WORD $0x6f077716 // bic v22.4s, #248, lsl #24 - WORD $0x3d800d36 // str q22, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - - BNE LBB0_81 - JMP LBB0_99 -LBB0_82: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - MOVD $0x0000000c00000010, R1 // LCPI0_34 - MOVD $0x0000001400000010, R0 // LCPI0_35 - - WORD $0x91010029 // add x9, x1, #64 - WORD $0x2ea0b821 // neg v1.2s, v1.2s + WORD $0x29402c0a // ldp w10, w11, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x530b7d4c // lsr w12, w10, #11 + WORD $0x1e270150 // fmov s16, w10 + WORD $0x138a596a // extr w10, w11, w10, #22 + WORD $0x4e0c1d90 // mov v16.s[1], w12 + WORD $0x4e141d50 // mov v16.s[2], w10 + WORD $0x53017d6a // lsr w10, w11, #1 + WORD $0x4e1c1d50 // mov v16.s[3], w10 + WORD $0x4e261e10 // and v16.16b, v16.16b, v6.16b + WORD $0x3c9c0110 // stur q16, [x8, #-64] + WORD $0x2940ac0a // ldp w10, w11, [x0, #4] + WORD $0x530c7d4c // lsr w12, w10, #12 + WORD $0x0e040d70 // dup v16.2s, w11 + WORD $0x138a5d6a // extr w10, w11, w10, #23 + WORD $0x1e270191 // fmov s17, w12 + WORD $0x2ea04610 // ushl v16.2s, v16.2s, v0.2s + WORD $0x4e0c1d51 // mov v17.s[1], w10 + WORD $0x6e180611 // mov v17.d[1], v16.d[0] + WORD $0x4e261e30 // and v16.16b, v17.16b, v6.16b + WORD $0x3c9d0110 // stur q16, [x8, #-48] + WORD $0x29412c0a // ldp w10, w11, [x0, #8] + WORD $0x138a616a // extr w10, w11, w10, #24 + WORD $0x0e040d70 // dup v16.2s, w11 + WORD $0x1e270151 // fmov s17, w10 + WORD $0xb940100a // ldr w10, [x0, #16] + WORD $0x2ea14610 // ushl v16.2s, v16.2s, v1.2s + WORD $0x138b654a // extr w10, w10, w11, #25 + WORD $0x6e112231 // ext v17.16b, v17.16b, v17.16b, #4 + WORD $0x6e106230 // ext v16.16b, v17.16b, v16.16b, #12 + WORD $0x4e1c1d50 // mov v16.s[3], w10 + WORD $0x4e261e10 // and v16.16b, v16.16b, v6.16b + WORD $0x3c9e0110 // stur q16, [x8, #-32] + WORD $0x29422c0a // ldp w10, w11, [x0, #16] + WORD $0x0e040d50 // dup v16.2s, w10 + WORD $0x138a696a // extr w10, w11, w10, #26 + WORD $0x2ea24610 // ushl v16.2s, v16.2s, v2.2s + WORD $0x4e141d50 // mov v16.s[2], w10 + WORD $0x53057d6a // lsr w10, w11, #5 + WORD $0x4e1c1d50 // mov v16.s[3], w10 + WORD $0x4e261e10 // and v16.16b, v16.16b, v6.16b + WORD $0x3c9f0110 // stur q16, [x8, #-16] + WORD $0x2942ac0a // ldp w10, w11, [x0, #20] + WORD $0x53107d4c // lsr w12, w10, #16 + WORD $0x0e040d70 // dup v16.2s, w11 + WORD $0x138a6d6a // extr w10, w11, w10, #27 + WORD $0x1e270191 // fmov s17, w12 + WORD $0x2ea34610 // ushl v16.2s, v16.2s, v3.2s + WORD $0x4e0c1d51 // mov v17.s[1], w10 + WORD $0x6e180611 // mov v17.d[1], v16.d[0] + WORD $0x4e261e30 // and v16.16b, v17.16b, v6.16b + WORD $0x3d800110 // str q16, [x8] + WORD $0x29432c0a // ldp w10, w11, [x0, #24] + WORD $0x138a716a // extr w10, w11, w10, #28 + WORD $0x0e040d70 // dup v16.2s, w11 + WORD $0x1e270151 // fmov s17, w10 + WORD $0xb940200a // ldr w10, [x0, #32] + WORD $0x2ea44610 // ushl v16.2s, v16.2s, v4.2s + WORD $0x138b754a // extr w10, w10, w11, #29 + WORD $0x6e112231 // ext v17.16b, v17.16b, v17.16b, #4 + WORD $0x6e106230 // ext v16.16b, v17.16b, v16.16b, #12 + WORD $0x4e1c1d50 // mov v16.s[3], w10 + WORD $0x4e261e10 // and v16.16b, v16.16b, v6.16b + WORD $0x3d800510 // str q16, [x8, #16] + WORD $0x29442c0a // ldp w10, w11, [x0, #32] + WORD $0x0e040d50 // dup v16.2s, w10 + WORD $0x138a796a // extr w10, w11, w10, #30 + WORD $0x2ea54610 // ushl v16.2s, v16.2s, v5.2s + WORD $0x4e141d50 // mov v16.s[2], w10 + WORD $0x53097d6a // lsr w10, w11, #9 + WORD $0x4e1c1d50 // mov v16.s[3], w10 + WORD $0x4e261e10 // and v16.16b, v16.16b, v6.16b + WORD $0x3d800910 // str q16, [x8, #32] + WORD $0x2944ac0a // ldp w10, w11, [x0, #36] + WORD $0x9100b000 // add x0, x0, #44 + WORD $0x53147d4c // lsr w12, w10, #20 + WORD $0x0e040d70 // dup v16.2s, w11 + WORD $0x138a7d6a // extr w10, w11, w10, #31 + WORD $0x1e270191 // fmov s17, w12 + WORD $0x2ea74610 // ushl v16.2s, v16.2s, v7.2s + WORD $0x4e0c1d51 // mov v17.s[1], w10 + WORD $0x6e180611 // mov v17.d[1], v16.d[0] + WORD $0x4e261e30 // and v16.16b, v17.16b, v6.16b + WORD $0x3d800d10 // str q16, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_79 + JMP LBB0_156 + +LBB0_80: + WORD $0x7100687f // cmp w3, #26 + BEQ LBB0_136 + + // %bb.81: + WORD $0x71006c7f // cmp w3, #27 + BNE LBB0_156 + + // %bb.82: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.83: + // WORD $0x90000008 // adrp x8, .LCPI0_52 + // WORD $0x90000009 // adrp x9, .LCPI0_53 + // WORD $0x9000000a // adrp x10, .LCPI0_54 + // WORD $0x9000000b // adrp x11, .LCPI0_67 + VMOVD LCPI0_52, V0 + // WORD $0x90000008 // adrp x8, .LCPI0_55 + VMOVD LCPI0_53, V1 + // WORD $0x90000009 // adrp x9, .LCPI0_56 + VMOVD LCPI0_54, V2 + // WORD $0x9000000a // adrp x10, .LCPI0_57 + VMOVD LCPI0_55, V3 + // WORD $0x90000008 // adrp x8, .LCPI0_58 + VMOVQ LCPI0_56L, LCPI0_56H, V4 + // WORD $0x90000009 // adrp x9, .LCPI0_59 + VMOVQ LCPI0_57L, LCPI0_57H, V5 + // WORD $0x9000000a // adrp x10, .LCPI0_60 + VMOVD LCPI0_58, V6 + // WORD $0x90000008 // adrp x8, .LCPI0_61 + VMOVD LCPI0_59, V7 + // WORD $0x90000009 // adrp x9, .LCPI0_62 + VMOVD LCPI0_60, V16 + // WORD $0x9000000a // adrp x10, .LCPI0_63 + VMOVD LCPI0_61, V17 + // WORD $0x90000008 // adrp x8, .LCPI0_64 + VMOVQ LCPI0_62L, LCPI0_62H, V18 + // WORD $0x90000009 // adrp x9, .LCPI0_65 + VMOVQ LCPI0_63L, LCPI0_63H, V19 + // WORD $0x9000000a // adrp x10, .LCPI0_66 + VMOVD LCPI0_64, V20 + WORD $0x91010348 // add x8, x26, #64 + VMOVD LCPI0_65, V21 + WORD $0xaa1303e9 // mov x9, x19 + VMOVD LCPI0_66, V22 + VMOVD LCPI0_67, V23 + LBB0_84: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0x2941340c // ldp w12, w13, [x0, #8] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x138a716e // extr w14, w11, w10, #28 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x138b618b // extr w11, w12, w11, #24 - WORD $0x4e0c1dc2 // mov v2.s[1], w14 - WORD $0x138c51ac // extr w12, w13, w12, #20 - WORD $0x4e141d62 // mov v2.s[2], w11 - WORD $0x4e1c1d82 // mov v2.s[3], w12 - WORD $0x6f077602 // bic v2.4s, #240, lsl #24 - WORD $0x3c9c0122 // stur q2, [x9, #-64] - WORD $0xfd400802 // ldr d2, [x0, #16] - WORD $0xbd400c03 // ldr s3, [x0, #12] - WORD $0xb940180a // ldr w10, [x0, #24] - WORD $0x2ea04444 // ushl v4.2s, v2.2s, v0.2s - WORD $0x0e823863 // zip1 v3.2s, v3.2s, v2.2s - WORD $0x0e0c3c4b // mov w11, v2.s[1] - WORD $0x2ea14462 // ushl v2.2s, v3.2s, v1.2s - WORD $0x53047d4c // lsr w12, w10, #4 - WORD $0x138b214a // extr w10, w10, w11, #8 - WORD $0x0ea21c82 // orr v2.8b, v4.8b, v2.8b - WORD $0x4e141d42 // mov v2.s[2], w10 - WORD $0x4e1c1d82 // mov v2.s[3], w12 - WORD $0x6f077602 // bic v2.4s, #240, lsl #24 - WORD $0x3c9d0122 // stur q2, [x9, #-48] - WORD $0x2943ac0a // ldp w10, w11, [x0, #28] - WORD $0x2944b40c // ldp w12, w13, [x0, #36] - WORD $0x138a716e // extr w14, w11, w10, #28 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x138b618b // extr w11, w12, w11, #24 - WORD $0x4e0c1dc2 // mov v2.s[1], w14 - WORD $0x138c51ac // extr w12, w13, w12, #20 - WORD $0x4e141d62 // mov v2.s[2], w11 - WORD $0x4e1c1d82 // mov v2.s[3], w12 - WORD $0x6f077602 // bic v2.4s, #240, lsl #24 - WORD $0x3c9e0122 // stur q2, [x9, #-32] - WORD $0xfc42c002 // ldur d2, [x0, #44] - WORD $0xbd402803 // ldr s3, [x0, #40] - WORD $0xb940340a // ldr w10, [x0, #52] - WORD $0x2ea04444 // ushl v4.2s, v2.2s, v0.2s - WORD $0x0e823863 // zip1 v3.2s, v3.2s, v2.2s - WORD $0x0e0c3c4b // mov w11, v2.s[1] - WORD $0x2ea14462 // ushl v2.2s, v3.2s, v1.2s - WORD $0x53047d4c // lsr w12, w10, #4 - WORD $0x138b214a // extr w10, w10, w11, #8 - WORD $0x0ea21c82 // orr v2.8b, v4.8b, v2.8b - WORD $0x4e141d42 // mov v2.s[2], w10 - WORD $0x4e1c1d82 // mov v2.s[3], w12 - WORD $0x6f077602 // bic v2.4s, #240, lsl #24 - WORD $0x3c9f0122 // stur q2, [x9, #-16] - WORD $0x29472c0a // ldp w10, w11, [x0, #56] - WORD $0x2948340c // ldp w12, w13, [x0, #64] - WORD $0x138a716e // extr w14, w11, w10, #28 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x138b618b // extr w11, w12, w11, #24 - WORD $0x4e0c1dc2 // mov v2.s[1], w14 - WORD $0x138c51ac // extr w12, w13, w12, #20 - WORD $0x4e141d62 // mov v2.s[2], w11 - WORD $0x4e1c1d82 // mov v2.s[3], w12 - WORD $0x6f077602 // bic v2.4s, #240, lsl #24 - WORD $0x3d800122 // str q2, [x9] - WORD $0xfd402402 // ldr d2, [x0, #72] - WORD $0xbd404403 // ldr s3, [x0, #68] - WORD $0xb940500a // ldr w10, [x0, #80] - WORD $0x2ea04444 // ushl v4.2s, v2.2s, v0.2s - WORD $0x0e823863 // zip1 v3.2s, v3.2s, v2.2s - WORD $0x0e0c3c4b // mov w11, v2.s[1] - WORD $0x2ea14462 // ushl v2.2s, v3.2s, v1.2s - WORD $0x53047d4c // lsr w12, w10, #4 - WORD $0x138b214a // extr w10, w10, w11, #8 - WORD $0x0ea21c82 // orr v2.8b, v4.8b, v2.8b - WORD $0x4e141d42 // mov v2.s[2], w10 - WORD $0x4e1c1d82 // mov v2.s[3], w12 - WORD $0x6f077602 // bic v2.4s, #240, lsl #24 - WORD $0x3d800522 // str q2, [x9, #16] - WORD $0x294aac0a // ldp w10, w11, [x0, #84] - WORD $0x294bb40c // ldp w12, w13, [x0, #92] - WORD $0x138a716e // extr w14, w11, w10, #28 - WORD $0x1e270142 // fmov s2, w10 - WORD $0x138b618b // extr w11, w12, w11, #24 - WORD $0x4e0c1dc2 // mov v2.s[1], w14 - WORD $0x138c51ac // extr w12, w13, w12, #20 - WORD $0x4e141d62 // mov v2.s[2], w11 - WORD $0x4e1c1d82 // mov v2.s[3], w12 - WORD $0x6f077602 // bic v2.4s, #240, lsl #24 - WORD $0x3d800922 // str q2, [x9, #32] - WORD $0xfc464002 // ldur d2, [x0, #100] - WORD $0xbd406003 // ldr s3, [x0, #96] - WORD $0xb9406c0a // ldr w10, [x0, #108] - WORD $0x9101c000 // add x0, x0, #112 - WORD $0x2ea04444 // ushl v4.2s, v2.2s, v0.2s - WORD $0x0e823863 // zip1 v3.2s, v3.2s, v2.2s - WORD $0x0e0c3c4b // mov w11, v2.s[1] - WORD $0x2ea14462 // ushl v2.2s, v3.2s, v1.2s - WORD $0x53047d4c // lsr w12, w10, #4 - WORD $0x138b214a // extr w10, w10, w11, #8 - WORD $0x0ea21c82 // orr v2.8b, v4.8b, v2.8b - WORD $0x4e141d42 // mov v2.s[2], w10 - WORD $0x4e1c1d82 // mov v2.s[3], w12 - WORD $0x6f077602 // bic v2.4s, #240, lsl #24 - WORD $0x3d800d22 // str q2, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - - BNE LBB0_84 - JMP LBB0_99 + WORD $0xb940000a // ldr w10, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0xfc404018 // ldur d24, [x0, #4] + WORD $0xb9400c0b // ldr w11, [x0, #12] + WORD $0x1e270159 // fmov s25, w10 + WORD $0x1e27015a // fmov s26, w10 + WORD $0x2ea0471b // ushl v27.2s, v24.2s, v0.2s + WORD $0x0e0c3f0a // mov w10, v24.s[1] + WORD $0x0e983b39 // zip1 v25.2s, v25.2s, v24.2s + WORD $0x6e1a235a // ext v26.16b, v26.16b, v26.16b, #4 + WORD $0x138a456a // extr w10, w11, w10, #17 + WORD $0x2ea14739 // ushl v25.2s, v25.2s, v1.2s + WORD $0x0eb91f79 // orr v25.8b, v27.8b, v25.8b + WORD $0x6e196358 // ext v24.16b, v26.16b, v25.16b, #12 + WORD $0x4e1c1d58 // mov v24.s[3], w10 + WORD $0x6f077718 // bic v24.4s, #248, lsl #24 + WORD $0x3c9c0118 // stur q24, [x8, #-64] + WORD $0xfd400818 // ldr d24, [x0, #16] + WORD $0xbd400c19 // ldr s25, [x0, #12] + WORD $0xb940180c // ldr w12, [x0, #24] + WORD $0x2ea2471a // ushl v26.2s, v24.2s, v2.2s + WORD $0x0e0c3f0a // mov w10, v24.s[1] + WORD $0x0e983b39 // zip1 v25.2s, v25.2s, v24.2s + WORD $0x53027d4b // lsr w11, w10, #2 + WORD $0x138a758a // extr w10, w12, w10, #29 + WORD $0x2ea34739 // ushl v25.2s, v25.2s, v3.2s + WORD $0x0eb91f58 // orr v24.8b, v26.8b, v25.8b + WORD $0x4e141d78 // mov v24.s[2], w11 + WORD $0x4e1c1d58 // mov v24.s[3], w10 + WORD $0x6f077718 // bic v24.4s, #248, lsl #24 + WORD $0x3c9d0118 // stur q24, [x8, #-48] + WORD $0xbd401818 // ldr s24, [x0, #24] + WORD $0x3cc1c019 // ldur q25, [x0, #28] + WORD $0x6e182318 // ext v24.16b, v24.16b, v24.16b, #4 + WORD $0x6e196318 // ext v24.16b, v24.16b, v25.16b, #12 + WORD $0x6ea44739 // ushl v25.4s, v25.4s, v4.4s + WORD $0x6ea54718 // ushl v24.4s, v24.4s, v5.4s + WORD $0x4eb81f38 // orr v24.16b, v25.16b, v24.16b + WORD $0x6f077718 // bic v24.4s, #248, lsl #24 + WORD $0x3c9e0118 // stur q24, [x8, #-32] + WORD $0xb940280a // ldr w10, [x0, #40] + WORD $0xfc42c018 // ldur d24, [x0, #44] + WORD $0xb940340b // ldr w11, [x0, #52] + WORD $0x1e270159 // fmov s25, w10 + WORD $0x53047d4a // lsr w10, w10, #4 + WORD $0x2ea6471a // ushl v26.2s, v24.2s, v6.2s + WORD $0x0e983b39 // zip1 v25.2s, v25.2s, v24.2s + WORD $0x1e27015b // fmov s27, w10 + WORD $0x0e0c3f0a // mov w10, v24.s[1] + WORD $0x6e1b237b // ext v27.16b, v27.16b, v27.16b, #4 + WORD $0x2ea74739 // ushl v25.2s, v25.2s, v7.2s + WORD $0x138a556a // extr w10, w11, w10, #21 + WORD $0x0eb91f59 // orr v25.8b, v26.8b, v25.8b + WORD $0x6e196378 // ext v24.16b, v27.16b, v25.16b, #12 + WORD $0x4e1c1d58 // mov v24.s[3], w10 + WORD $0x6f077718 // bic v24.4s, #248, lsl #24 + WORD $0x3c9f0118 // stur q24, [x8, #-16] + WORD $0xfd401c18 // ldr d24, [x0, #56] + WORD $0xbd403419 // ldr s25, [x0, #52] + WORD $0xb940400b // ldr w11, [x0, #64] + WORD $0x2eb0471a // ushl v26.2s, v24.2s, v16.2s + WORD $0x0e0c3f0a // mov w10, v24.s[1] + WORD $0x0e983b39 // zip1 v25.2s, v25.2s, v24.2s + WORD $0x138a196a // extr w10, w11, w10, #6 + WORD $0x2eb14739 // ushl v25.2s, v25.2s, v17.2s + WORD $0x0eb91f58 // orr v24.8b, v26.8b, v25.8b + WORD $0x4e141d58 // mov v24.s[2], w10 + WORD $0x53017d6a // lsr w10, w11, #1 + WORD $0x4e1c1d58 // mov v24.s[3], w10 + WORD $0x6f077718 // bic v24.4s, #248, lsl #24 + WORD $0x3d800118 // str q24, [x8] + WORD $0xbd404018 // ldr s24, [x0, #64] + WORD $0x3cc44019 // ldur q25, [x0, #68] + WORD $0x6e182318 // ext v24.16b, v24.16b, v24.16b, #4 + WORD $0x6e196318 // ext v24.16b, v24.16b, v25.16b, #12 + WORD $0x6eb24739 // ushl v25.4s, v25.4s, v18.4s + WORD $0x6eb34718 // ushl v24.4s, v24.4s, v19.4s + WORD $0x4eb81f38 // orr v24.16b, v25.16b, v24.16b + WORD $0x6f077718 // bic v24.4s, #248, lsl #24 + WORD $0x3d800518 // str q24, [x8, #16] + WORD $0x294a280b // ldp w11, w10, [x0, #80] + WORD $0xfd402c18 // ldr d24, [x0, #88] + WORD $0x1e270159 // fmov s25, w10 + WORD $0x138b214b // extr w11, w10, w11, #8 + WORD $0x53037d4a // lsr w10, w10, #3 + WORD $0x0e983b39 // zip1 v25.2s, v25.2s, v24.2s + WORD $0x2eb44718 // ushl v24.2s, v24.2s, v20.2s + WORD $0x1e27017a // fmov s26, w11 + WORD $0x2eb54739 // ushl v25.2s, v25.2s, v21.2s + WORD $0x4e0c1d5a // mov v26.s[1], w10 + WORD $0x0eb91f18 // orr v24.8b, v24.8b, v25.8b + WORD $0x6e18071a // mov v26.d[1], v24.d[0] + WORD $0x6f07771a // bic v26.4s, #248, lsl #24 + WORD $0x3d80091a // str q26, [x8, #32] + WORD $0xfd403018 // ldr d24, [x0, #96] + WORD $0xbd405c19 // ldr s25, [x0, #92] + WORD $0xb940680b // ldr w11, [x0, #104] + WORD $0x9101b000 // add x0, x0, #108 + WORD $0x2eb6471a // ushl v26.2s, v24.2s, v22.2s + WORD $0x0e0c3f0a // mov w10, v24.s[1] + WORD $0x0e983b39 // zip1 v25.2s, v25.2s, v24.2s + WORD $0x138a296a // extr w10, w11, w10, #10 + WORD $0x2eb74739 // ushl v25.2s, v25.2s, v23.2s + WORD $0x0eb91f58 // orr v24.8b, v26.8b, v25.8b + WORD $0x4e141d58 // mov v24.s[2], w10 + WORD $0x53057d6a // lsr w10, w11, #5 + WORD $0x4e1c1d58 // mov v24.s[3], w10 + WORD $0x6f077718 // bic v24.4s, #248, lsl #24 + WORD $0x3d800d18 // str q24, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_84 + JMP LBB0_156 + LBB0_85: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - VMOVQ $0x0000001100000014, $0x0000000b0000000e, V7 // LCPI0_20 - VMOVQ $0x0000000f0000000c, $0x0000001500000012, V0 // LCPI0_21 - MOVD $0x0000000500000008, R16 // LCPI0_22 - MOVD $0x0000001b00000018, R1 // LCPI0_23 - VMOVQ $0x000000190000001c, $0x0000001300000016, V17 // LCPI0_24 - VMOVQ $0x0000000700000004, $0x0000000d0000000a, V2 // LCPI0_25 - VMOVQ $0x0000000d00000010, $0x000000070000000a, V25 // LCPI0_26 - VMOVQ $0x0000001300000010, $0x0000001900000016, V3 // LCPI0_27 - MOVD $0x0000001b0000001e, R19 // LCPI0_28 - MOVD $0x0000000500000002, R4 // LCPI0_29 - VMOVQ $0x0000001500000018, $0x0000000f00000012, V20 // LCPI0_30 - VMOVQ $0x0000000b00000008, $0x000000110000000e, V5 // LCPI0_31 - MOVD $0x000000090000000c, R21 // LCPI0_32 - MOVD $0x0000001700000014, R6 // LCPI0_33 - - WORD $0x91010029 // add x9, x1, #64 - WORD $0x6ea0b8e7 // neg v7.4s, v7.4s - WORD $0x2ea0ba10 // neg v16.2s, v16.2s - WORD $0x6ea0ba31 // neg v17.4s, v17.4s - WORD $0x6ea0ba52 // neg v25.4s, v25.4s - WORD $0x2ea0ba73 // neg v19.2s, v19.2s - WORD $0x6ea0ba94 // neg v20.4s, v20.4s - WORD $0x2ea0bab5 // neg v21.2s, v21.2s -LBB0_87: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0x2941340c // ldp w12, w13, [x0, #8] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x138a756e // extr w14, w11, w10, #29 - WORD $0x1e270156 // fmov s22, w10 - WORD $0x138b698b // extr w11, w12, w11, #26 - WORD $0x4e0c1dd6 // mov v22.s[1], w14 - WORD $0x138c5dac // extr w12, w13, w12, #23 - WORD $0x4e141d76 // mov v22.s[2], w11 - WORD $0x4e1c1d96 // mov v22.s[3], w12 - WORD $0x6f077416 // bic v22.4s, #224, lsl #24 - WORD $0x3c9c0136 // stur q22, [x9, #-64] - WORD $0xbd400c16 // ldr s22, [x0, #12] - WORD $0x3dc00417 // ldr q23, [x0, #16] - WORD $0x6e1622d6 // ext v22.16b, v22.16b, v22.16b, #4 - WORD $0x6e1762d6 // ext v22.16b, v22.16b, v23.16b, #12 - WORD $0x6ea046f8 // ushl v24.4s, v23.4s, v0.4s - WORD $0x6ea746d6 // ushl v22.4s, v22.4s, v7.4s - WORD $0x4eb61f16 // orr v22.16b, v24.16b, v22.16b - WORD $0x6f077416 // bic v22.4s, #224, lsl #24 - WORD $0x3c9d0136 // stur q22, [x9, #-48] - WORD $0xfd401016 // ldr d22, [x0, #32] - WORD $0xbd401c17 // ldr s23, [x0, #28] - WORD $0xb940280a // ldr w10, [x0, #40] - WORD $0x2ea146d8 // ushl v24.2s, v22.2s, v1.2s - WORD $0x0e963af7 // zip1 v23.2s, v23.2s, v22.2s - WORD $0x0e0c3ecb // mov w11, v22.s[1] - WORD $0x2eb046f6 // ushl v22.2s, v23.2s, v16.2s - WORD $0x53027d6c // lsr w12, w11, #2 - WORD $0x0eb61f16 // orr v22.8b, v24.8b, v22.8b - WORD $0x138b7d4a // extr w10, w10, w11, #31 - WORD $0x4e141d96 // mov v22.s[2], w12 - WORD $0x4e1c1d56 // mov v22.s[3], w10 - WORD $0x6f077416 // bic v22.4s, #224, lsl #24 - WORD $0x3c9e0136 // stur q22, [x9, #-32] - WORD $0xbd402816 // ldr s22, [x0, #40] - WORD $0x3cc2c017 // ldur q23, [x0, #44] - WORD $0x6e1622d6 // ext v22.16b, v22.16b, v22.16b, #4 - WORD $0x6ea246f8 // ushl v24.4s, v23.4s, v2.4s - WORD $0x6e1762d6 // ext v22.16b, v22.16b, v23.16b, #12 - WORD $0x6f077418 // bic v24.4s, #224, lsl #24 - WORD $0x6eb146d6 // ushl v22.4s, v22.4s, v17.4s - WORD $0x4eb61f16 // orr v22.16b, v24.16b, v22.16b - WORD $0x3c9f0136 // stur q22, [x9, #-16] - WORD $0xbd403816 // ldr s22, [x0, #56] - WORD $0x3cc3c017 // ldur q23, [x0, #60] - WORD $0x6e1622d6 // ext v22.16b, v22.16b, v22.16b, #4 - WORD $0x6e1762d6 // ext v22.16b, v22.16b, v23.16b, #12 - WORD $0x6ea346f8 // ushl v24.4s, v23.4s, v3.4s - WORD $0x6eb246d6 // ushl v22.4s, v22.4s, v25.4s - WORD $0x4eb61f16 // orr v22.16b, v24.16b, v22.16b - WORD $0x6f077416 // bic v22.4s, #224, lsl #24 - WORD $0x3d800136 // str q22, [x9] - WORD $0x29492c0a // ldp w10, w11, [x0, #72] - WORD $0xfd402816 // ldr d22, [x0, #80] - WORD $0x1e270177 // fmov s23, w11 - WORD $0x138a116a // extr w10, w11, w10, #4 - WORD $0x0e963af7 // zip1 v23.2s, v23.2s, v22.2s - WORD $0x53017d6c // lsr w12, w11, #1 - WORD $0x2ea446d6 // ushl v22.2s, v22.2s, v4.2s - WORD $0x1e270158 // fmov s24, w10 - WORD $0x2eb346f7 // ushl v23.2s, v23.2s, v19.2s - WORD $0x4e0c1d98 // mov v24.s[1], w12 - WORD $0x0eb71ed6 // orr v22.8b, v22.8b, v23.8b - WORD $0x6e1806d8 // mov v24.d[1], v22.d[0] - WORD $0x6f077418 // bic v24.4s, #224, lsl #24 - WORD $0x3d800538 // str q24, [x9, #16] - WORD $0xbd405416 // ldr s22, [x0, #84] - WORD $0x3cc58017 // ldur q23, [x0, #88] - WORD $0x6e1622d6 // ext v22.16b, v22.16b, v22.16b, #4 - WORD $0x6e1762d6 // ext v22.16b, v22.16b, v23.16b, #12 - WORD $0x6ea546f8 // ushl v24.4s, v23.4s, v5.4s - WORD $0x6eb446d6 // ushl v22.4s, v22.4s, v20.4s - WORD $0x4eb61f16 // orr v22.16b, v24.16b, v22.16b - WORD $0x6f077416 // bic v22.4s, #224, lsl #24 - WORD $0x3d800936 // str q22, [x9, #32] - WORD $0xfd403416 // ldr d22, [x0, #104] - WORD $0xbd406417 // ldr s23, [x0, #100] - WORD $0xb940700a // ldr w10, [x0, #112] - WORD $0x9101d000 // add x0, x0, #116 - WORD $0x2ea646d8 // ushl v24.2s, v22.2s, v6.2s - WORD $0x0e963af7 // zip1 v23.2s, v23.2s, v22.2s - WORD $0x0e0c3ecb // mov w11, v22.s[1] - WORD $0x2eb546f6 // ushl v22.2s, v23.2s, v21.2s - WORD $0x53037d4c // lsr w12, w10, #3 - WORD $0x138b194a // extr w10, w10, w11, #6 - WORD $0x0eb61f16 // orr v22.8b, v24.8b, v22.8b - WORD $0x4e141d56 // mov v22.s[2], w10 - WORD $0x4e1c1d96 // mov v22.s[3], w12 - WORD $0x6f077416 // bic v22.4s, #224, lsl #24 - WORD $0x3d800d36 // str q22, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - - BNE LBB0_87 - JMP LBB0_99 -LBB0_88: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - VMOVQ $0x0000001600000018, $0x0000001200000014, V3 // LCPI0_14 - VMOVQ $0x0000000a00000008, $0x0000000e0000000c, V0 // LCPI0_15 - VMOVQ $0x0000000e00000010, $0x0000000a0000000c, V4 // LCPI0_16 - VMOVQ $0x0000001200000010, $0x0000001600000014, V1 // LCPI0_17 - MOVD $0x0000000600000008, R5 // LCPI0_18 - MOVD $0x0000001a00000018, R2 // LCPI0_19 - - WORD $0x91010029 // add x9, x1, #64 - WORD $0x6ea0b863 // neg v3.4s, v3.4s - WORD $0x6ea0b884 // neg v4.4s, v4.4s - WORD $0x2ea0b8a5 // neg v5.2s, v5.2s + WORD $0x7100187f // cmp w3, #6 + BEQ LBB0_139 + + // %bb.86: + WORD $0x71001c7f // cmp w3, #7 + BNE LBB0_156 + + // %bb.87: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.88: + // WORD $0x90000008 // adrp x8, .LCPI0_166 + // WORD $0x90000009 // adrp x9, .LCPI0_167 + // WORD $0x9000000a // adrp x10, .LCPI0_168 + WORD $0x4f0307e7 // movi v7.4s, #127 + VMOVD LCPI0_166, V0 + // WORD $0x90000008 // adrp x8, .LCPI0_169 + VMOVD LCPI0_167, V1 + // WORD $0x90000009 // adrp x9, .LCPI0_170 + VMOVD LCPI0_168, V2 + // WORD $0x9000000a // adrp x10, .LCPI0_171 + VMOVD LCPI0_169, V3 + // WORD $0x90000008 // adrp x8, .LCPI0_172 + VMOVD LCPI0_170, V4 + // WORD $0x90000009 // adrp x9, .LCPI0_173 + VMOVD LCPI0_171, V5 + VMOVD LCPI0_172, V6 + WORD $0x91010348 // add x8, x26, #64 + VMOVQ LCPI0_173L, LCPI0_173H, V16 + WORD $0xaa1303e9 // mov x9, x19 + +LBB0_89: + WORD $0xb940000a // ldr w10, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x0e040d51 // dup v17.2s, w10 + WORD $0x1e270152 // fmov s18, w10 + WORD $0x53157d4a // lsr w10, w10, #21 + WORD $0x6e122252 // ext v18.16b, v18.16b, v18.16b, #4 + WORD $0x2ea04631 // ushl v17.2s, v17.2s, v0.2s + WORD $0x6e116251 // ext v17.16b, v18.16b, v17.16b, #12 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9c0111 // stur q17, [x8, #-64] + WORD $0x29402c0a // ldp w10, w11, [x0] + WORD $0x138a716a // extr w10, w11, w10, #28 + WORD $0x0e040d71 // dup v17.2s, w11 + WORD $0x1e270152 // fmov s18, w10 + WORD $0x53117d6a // lsr w10, w11, #17 + WORD $0x2ea14631 // ushl v17.2s, v17.2s, v1.2s + WORD $0x6e122252 // ext v18.16b, v18.16b, v18.16b, #4 + WORD $0x6e116251 // ext v17.16b, v18.16b, v17.16b, #12 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9d0111 // stur q17, [x8, #-48] + WORD $0x2940ac0a // ldp w10, w11, [x0, #4] + WORD $0x53187d4c // lsr w12, w10, #24 + WORD $0x0e040d71 // dup v17.2s, w11 + WORD $0x138a7d6a // extr w10, w11, w10, #31 + WORD $0x1e270192 // fmov s18, w12 + WORD $0x2ea24631 // ushl v17.2s, v17.2s, v2.2s + WORD $0x4e0c1d52 // mov v18.s[1], w10 + WORD $0x6e180632 // mov v18.d[1], v17.d[0] + WORD $0x4e271e51 // and v17.16b, v18.16b, v7.16b + WORD $0x3c9e0111 // stur q17, [x8, #-32] + WORD $0x29412c0a // ldp w10, w11, [x0, #8] + WORD $0x53147d4c // lsr w12, w10, #20 + WORD $0x0e040d71 // dup v17.2s, w11 + WORD $0x138a6d6a // extr w10, w11, w10, #27 + WORD $0x1e270192 // fmov s18, w12 + WORD $0x2ea34631 // ushl v17.2s, v17.2s, v3.2s + WORD $0x4e0c1d52 // mov v18.s[1], w10 + WORD $0x6e180632 // mov v18.d[1], v17.d[0] + WORD $0x4e271e51 // and v17.16b, v18.16b, v7.16b + WORD $0x3c9f0111 // stur q17, [x8, #-16] + WORD $0x2941ac0a // ldp w10, w11, [x0, #12] + WORD $0x0e040d51 // dup v17.2s, w10 + WORD $0x138a796a // extr w10, w11, w10, #30 + WORD $0x2ea44631 // ushl v17.2s, v17.2s, v4.2s + WORD $0x4e141d51 // mov v17.s[2], w10 + WORD $0x53057d6a // lsr w10, w11, #5 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800111 // str q17, [x8] + WORD $0x29422c0a // ldp w10, w11, [x0, #16] + WORD $0x0e040d51 // dup v17.2s, w10 + WORD $0x138a696a // extr w10, w11, w10, #26 + WORD $0x2ea54631 // ushl v17.2s, v17.2s, v5.2s + WORD $0x4e141d51 // mov v17.s[2], w10 + WORD $0x53017d6a // lsr w10, w11, #1 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800511 // str q17, [x8, #16] + WORD $0x2942ac0a // ldp w10, w11, [x0, #20] + WORD $0x0e040d51 // dup v17.2s, w10 + WORD $0x53167d4c // lsr w12, w10, #22 + WORD $0x138a756a // extr w10, w11, w10, #29 + WORD $0x2ea64631 // ushl v17.2s, v17.2s, v6.2s + WORD $0x4e141d91 // mov v17.s[2], w12 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x9100600a // add x10, x0, #24 + WORD $0x91007000 // add x0, x0, #28 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800911 // str q17, [x8, #32] + WORD $0x4d40c951 // ld1r { v17.4s }, [x10] + WORD $0x6eb04631 // ushl v17.4s, v17.4s, v16.4s + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800d11 // str q17, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_89 + JMP LBB0_156 + LBB0_90: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0x2941340c // ldp w12, w13, [x0, #8] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x138a796e // extr w14, w11, w10, #30 - WORD $0x1e270146 // fmov s6, w10 - WORD $0x138b718b // extr w11, w12, w11, #28 - WORD $0x4e0c1dc6 // mov v6.s[1], w14 - WORD $0x138c69ac // extr w12, w13, w12, #26 - WORD $0x4e141d66 // mov v6.s[2], w11 - WORD $0x4e1c1d86 // mov v6.s[3], w12 - WORD $0x6f067406 // bic v6.4s, #192, lsl #24 - WORD $0x3c9c0126 // stur q6, [x9, #-64] - WORD $0xbd400c06 // ldr s6, [x0, #12] - WORD $0x3dc00407 // ldr q7, [x0, #16] - WORD $0x6e0620c6 // ext v6.16b, v6.16b, v6.16b, #4 - WORD $0x6ea044f0 // ushl v16.4s, v7.4s, v0.4s - WORD $0x6e0760c6 // ext v6.16b, v6.16b, v7.16b, #12 - WORD $0x6f067410 // bic v16.4s, #192, lsl #24 - WORD $0x6ea344c6 // ushl v6.4s, v6.4s, v3.4s - WORD $0x4ea61e06 // orr v6.16b, v16.16b, v6.16b - WORD $0x3c9d0126 // stur q6, [x9, #-48] - WORD $0xbd401c06 // ldr s6, [x0, #28] - WORD $0x3dc00807 // ldr q7, [x0, #32] - WORD $0x6e0620c6 // ext v6.16b, v6.16b, v6.16b, #4 - WORD $0x6ea144f0 // ushl v16.4s, v7.4s, v1.4s - WORD $0x6e0760c6 // ext v6.16b, v6.16b, v7.16b, #12 - WORD $0x6f067410 // bic v16.4s, #192, lsl #24 - WORD $0x6ea444c6 // ushl v6.4s, v6.4s, v4.4s - WORD $0x4ea61e06 // orr v6.16b, v16.16b, v6.16b - WORD $0x3c9e0126 // stur q6, [x9, #-32] - WORD $0xfd401806 // ldr d6, [x0, #48] - WORD $0xbd402c07 // ldr s7, [x0, #44] - WORD $0xb940380a // ldr w10, [x0, #56] - WORD $0x2ea244d0 // ushl v16.2s, v6.2s, v2.2s - WORD $0x0e8638e7 // zip1 v7.2s, v7.2s, v6.2s - WORD $0x0e0c3ccb // mov w11, v6.s[1] - WORD $0x2ea544e6 // ushl v6.2s, v7.2s, v5.2s - WORD $0x53027d4c // lsr w12, w10, #2 - WORD $0x138b114a // extr w10, w10, w11, #4 - WORD $0x0ea61e06 // orr v6.8b, v16.8b, v6.8b - WORD $0x4e141d46 // mov v6.s[2], w10 - WORD $0x4e1c1d86 // mov v6.s[3], w12 - WORD $0x6f067406 // bic v6.4s, #192, lsl #24 - WORD $0x3c9f0126 // stur q6, [x9, #-16] - WORD $0x2947ac0a // ldp w10, w11, [x0, #60] - WORD $0x2948b40c // ldp w12, w13, [x0, #68] - WORD $0x138a796e // extr w14, w11, w10, #30 - WORD $0x1e270146 // fmov s6, w10 - WORD $0x138b718b // extr w11, w12, w11, #28 - WORD $0x4e0c1dc6 // mov v6.s[1], w14 - WORD $0x138c69ac // extr w12, w13, w12, #26 - WORD $0x4e141d66 // mov v6.s[2], w11 - WORD $0x4e1c1d86 // mov v6.s[3], w12 - WORD $0x6f067406 // bic v6.4s, #192, lsl #24 - WORD $0x3d800126 // str q6, [x9] - WORD $0xbd404806 // ldr s6, [x0, #72] - WORD $0x3cc4c007 // ldur q7, [x0, #76] - WORD $0x6e0620c6 // ext v6.16b, v6.16b, v6.16b, #4 - WORD $0x6ea044f0 // ushl v16.4s, v7.4s, v0.4s - WORD $0x6e0760c6 // ext v6.16b, v6.16b, v7.16b, #12 - WORD $0x6f067410 // bic v16.4s, #192, lsl #24 - WORD $0x6ea344c6 // ushl v6.4s, v6.4s, v3.4s - WORD $0x4ea61e06 // orr v6.16b, v16.16b, v6.16b - WORD $0x3d800526 // str q6, [x9, #16] - WORD $0xbd405806 // ldr s6, [x0, #88] - WORD $0x3cc5c007 // ldur q7, [x0, #92] - WORD $0x6e0620c6 // ext v6.16b, v6.16b, v6.16b, #4 - WORD $0x6ea144f0 // ushl v16.4s, v7.4s, v1.4s - WORD $0x6e0760c6 // ext v6.16b, v6.16b, v7.16b, #12 - WORD $0x6f067410 // bic v16.4s, #192, lsl #24 - WORD $0x6ea444c6 // ushl v6.4s, v6.4s, v4.4s - WORD $0x4ea61e06 // orr v6.16b, v16.16b, v6.16b - WORD $0x3d800926 // str q6, [x9, #32] - WORD $0xfc46c006 // ldur d6, [x0, #108] - WORD $0xbd406807 // ldr s7, [x0, #104] - WORD $0xb940740a // ldr w10, [x0, #116] - WORD $0x9101e000 // add x0, x0, #120 - WORD $0x2ea244d0 // ushl v16.2s, v6.2s, v2.2s - WORD $0x0e8638e7 // zip1 v7.2s, v7.2s, v6.2s - WORD $0x0e0c3ccb // mov w11, v6.s[1] - WORD $0x2ea544e6 // ushl v6.2s, v7.2s, v5.2s - WORD $0x53027d4c // lsr w12, w10, #2 - WORD $0x138b114a // extr w10, w10, w11, #4 - WORD $0x0ea61e06 // orr v6.8b, v16.8b, v6.8b - WORD $0x4e141d46 // mov v6.s[2], w10 - WORD $0x4e1c1d86 // mov v6.s[3], w12 - WORD $0x6f067406 // bic v6.4s, #192, lsl #24 - WORD $0x3d800d26 // str q6, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - - BNE LBB0_90 - JMP LBB0_99 -LBB0_91: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - VMOVQ $0x0000001b0000001c, $0x000000190000001a, V7 // LCPI0_0 - VMOVQ $0x0000000500000004, $0x0000000700000006, V0 // LCPI0_1 - VMOVQ $0x0000001700000018, $0x0000001500000016, V16 // LCPI0_2 - VMOVQ $0x0000000900000008, $0x0000000b0000000a, V1 // LCPI0_3 - VMOVQ $0x0000001300000014, $0x0000001100000012, V17 // LCPI0_4 - VMOVQ $0x0000000d0000000c, $0x0000000f0000000e, V2 // LCPI0_5 - VMOVQ $0x0000000f00000010, $0x0000000d0000000e, V25 // LCPI0_6 - VMOVQ $0x0000001100000010, $0x0000001300000012, V3 // LCPI0_7 - VMOVQ $0x0000000b0000000c, $0x000000090000000a, V19 // LCPI0_8 - VMOVQ $0x0000001500000014, $0x0000001700000016, V4 // LCPI0_9 - VMOVQ $0x0000000700000008, $0x0000000500000006, V20 // LCPI0_10 - VMOVQ $0x0000001900000018, $0x0000001b0000001a, V5 // LCPI0_11 - MOVD $0x0000000300000004, R21 // LCPI0_12 - MOVD $0x0000001d0000001c, R6 // LCPI0_13 - - WORD $0x91010029 // add x9, x1, #64 - WORD $0x6ea0b8e7 // neg v7.4s, v7.4s - WORD $0x6ea0ba10 // neg v16.4s, v16.4s - WORD $0x6ea0ba31 // neg v17.4s, v17.4s - WORD $0x6ea0ba52 // neg v25.4s, v25.4s - WORD $0x6ea0ba73 // neg v19.4s, v19.4s - WORD $0x6ea0ba94 // neg v20.4s, v20.4s - WORD $0x2ea0bab5 // neg v21.2s, v21.2s -LBB0_93: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0x2941340c // ldp w12, w13, [x0, #8] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x138a7d6e // extr w14, w11, w10, #31 - WORD $0x1e270156 // fmov s22, w10 - WORD $0x4e0c1dd6 // mov v22.s[1], w14 - WORD $0x138c75ac // extr w12, w13, w12, #29 - WORD $0x4e141d76 // mov v22.s[2], w11 - WORD $0x4e1c1d96 // mov v22.s[3], w12 - WORD $0x6f047416 // bic v22.4s, #128, lsl #24 - WORD $0x3c9c0136 // stur q22, [x9, #-64] - WORD $0xbd400c16 // ldr s22, [x0, #12] - WORD $0x3dc00417 // ldr q23, [x0, #16] - WORD $0x6e1622d6 // ext v22.16b, v22.16b, v22.16b, #4 - WORD $0x6ea046f8 // ushl v24.4s, v23.4s, v0.4s - WORD $0x6e1762d6 // ext v22.16b, v22.16b, v23.16b, #12 - WORD $0x6f047418 // bic v24.4s, #128, lsl #24 - WORD $0x6ea746d6 // ushl v22.4s, v22.4s, v7.4s - WORD $0x4eb61f16 // orr v22.16b, v24.16b, v22.16b - WORD $0x3c9d0136 // stur q22, [x9, #-48] - WORD $0xbd401c16 // ldr s22, [x0, #28] - WORD $0x3dc00817 // ldr q23, [x0, #32] - WORD $0x6e1622d6 // ext v22.16b, v22.16b, v22.16b, #4 - WORD $0x6ea146f8 // ushl v24.4s, v23.4s, v1.4s - WORD $0x6e1762d6 // ext v22.16b, v22.16b, v23.16b, #12 - WORD $0x6f047418 // bic v24.4s, #128, lsl #24 - WORD $0x6eb046d6 // ushl v22.4s, v22.4s, v16.4s - WORD $0x4eb61f16 // orr v22.16b, v24.16b, v22.16b - WORD $0x3c9e0136 // stur q22, [x9, #-32] - WORD $0xbd402c16 // ldr s22, [x0, #44] - WORD $0x3dc00c17 // ldr q23, [x0, #48] - WORD $0x6e1622d6 // ext v22.16b, v22.16b, v22.16b, #4 - WORD $0x6ea246f8 // ushl v24.4s, v23.4s, v2.4s - WORD $0x6e1762d6 // ext v22.16b, v22.16b, v23.16b, #12 - WORD $0x6f047418 // bic v24.4s, #128, lsl #24 - WORD $0x4eb61f16 // orr v22.16b, v24.16b, v22.16b - WORD $0x3c9f0136 // stur q22, [x9, #-16] - WORD $0xbd403c16 // ldr s22, [x0, #60] - WORD $0x3dc01017 // ldr q23, [x0, #64] - WORD $0x6e1622d6 // ext v22.16b, v22.16b, v22.16b, #4 - WORD $0x6ea346f8 // ushl v24.4s, v23.4s, v3.4s - WORD $0x6e1762d6 // ext v22.16b, v22.16b, v23.16b, #12 - WORD $0x6f047418 // bic v24.4s, #128, lsl #24 - WORD $0x6eb246d6 // ushl v22.4s, v22.4s, v25.4s - WORD $0x4eb61f16 // orr v22.16b, v24.16b, v22.16b - WORD $0x3d800136 // str q22, [x9] - WORD $0xbd404c16 // ldr s22, [x0, #76] - WORD $0x3dc01417 // ldr q23, [x0, #80] - WORD $0x6e1622d6 // ext v22.16b, v22.16b, v22.16b, #4 - WORD $0x6ea446f8 // ushl v24.4s, v23.4s, v4.4s - WORD $0x6e1762d6 // ext v22.16b, v22.16b, v23.16b, #12 - WORD $0x6f047418 // bic v24.4s, #128, lsl #24 - WORD $0x6eb346d6 // ushl v22.4s, v22.4s, v19.4s - WORD $0x4eb61f16 // orr v22.16b, v24.16b, v22.16b - WORD $0x3d800536 // str q22, [x9, #16] - WORD $0xbd405c16 // ldr s22, [x0, #92] - WORD $0x3dc01817 // ldr q23, [x0, #96] - WORD $0x6e1622d6 // ext v22.16b, v22.16b, v22.16b, #4 - WORD $0x6ea546f8 // ushl v24.4s, v23.4s, v5.4s - WORD $0x6e1762d6 // ext v22.16b, v22.16b, v23.16b, #12 - WORD $0x6f047418 // bic v24.4s, #128, lsl #24 - WORD $0x6eb446d6 // ushl v22.4s, v22.4s, v20.4s - WORD $0x4eb61f16 // orr v22.16b, v24.16b, v22.16b - WORD $0x3d800936 // str q22, [x9, #32] - WORD $0xfd403816 // ldr d22, [x0, #112] - WORD $0xbd406c17 // ldr s23, [x0, #108] - WORD $0xb940780a // ldr w10, [x0, #120] - WORD $0x9101f000 // add x0, x0, #124 - WORD $0x2ea646d8 // ushl v24.2s, v22.2s, v6.2s - WORD $0x0e963af7 // zip1 v23.2s, v23.2s, v22.2s - WORD $0x0e0c3ecb // mov w11, v22.s[1] - WORD $0x2eb546f6 // ushl v22.2s, v23.2s, v21.2s - WORD $0x53017d4c // lsr w12, w10, #1 - WORD $0x138b094a // extr w10, w10, w11, #2 - WORD $0x0eb61f16 // orr v22.8b, v24.8b, v22.8b - WORD $0x4e141d56 // mov v22.s[2], w10 - WORD $0x4e1c1d96 // mov v22.s[3], w12 - WORD $0x6f047416 // bic v22.4s, #128, lsl #24 - WORD $0x3d800d36 // str q22, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - - BNE LBB0_93 - JMP LBB0_99 + WORD $0x7100587f // cmp w3, #22 + BEQ LBB0_142 + + // %bb.91: + WORD $0x71005c7f // cmp w3, #23 + BNE LBB0_156 + + // %bb.92: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.93: + // WORD $0x90000009 // adrp x9, .LCPI0_95 + // WORD $0x90000008 // adrp x8, .LCPI0_94 + // WORD $0x9000000a // adrp x10, .LCPI0_96 + WORD $0x4f03d7f7 // movi v23.4s, #127, msl #16 + VMOVD LCPI0_95, V1 + // WORD $0x90000009 // adrp x9, .LCPI0_98 + VMOVD LCPI0_94, V0 + // WORD $0x90000008 // adrp x8, .LCPI0_97 + VMOVD LCPI0_96, V2 + // WORD $0x9000000a // adrp x10, .LCPI0_99 + VMOVD LCPI0_98, V4 + // WORD $0x90000009 // adrp x9, .LCPI0_101 + VMOVD LCPI0_97, V3 + // WORD $0x90000008 // adrp x8, .LCPI0_100 + VMOVD LCPI0_99, V5 + // WORD $0x9000000a // adrp x10, .LCPI0_102 + VMOVD LCPI0_101, V7 + // WORD $0x90000009 // adrp x9, .LCPI0_104 + VMOVD LCPI0_100, V6 + // WORD $0x90000008 // adrp x8, .LCPI0_103 + VMOVD LCPI0_102, V16 + // WORD $0x9000000a // adrp x10, .LCPI0_105 + VMOVD LCPI0_104, V18 + // WORD $0x90000009 // adrp x9, .LCPI0_107 + VMOVD LCPI0_103, V17 + // WORD $0x90000008 // adrp x8, .LCPI0_106 + VMOVD LCPI0_105, V19 + // WORD $0x9000000a // adrp x10, .LCPI0_108 + VMOVD LCPI0_107, V21 + // WORD $0x90000009 // adrp x9, .LCPI0_109 + VMOVD LCPI0_106, V20 + WORD $0x91010348 // add x8, x26, #64 + VMOVD LCPI0_108, V22 + VMOVD LCPI0_109, V24 + WORD $0xaa1303e9 // mov x9, x19 + LBB0_94: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 + WORD $0xb940000a // ldr w10, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0xfc404019 // ldur d25, [x0, #4] + WORD $0x1e27015a // fmov s26, w10 + WORD $0x1e27015b // fmov s27, w10 + WORD $0x2ea0473c // ushl v28.2s, v25.2s, v0.2s + WORD $0x0e0c3f2a // mov w10, v25.s[1] + WORD $0x0e993b5a // zip1 v26.2s, v26.2s, v25.2s + WORD $0x6e1b237b // ext v27.16b, v27.16b, v27.16b, #4 + WORD $0x53057d4a // lsr w10, w10, #5 + WORD $0x2ea1475a // ushl v26.2s, v26.2s, v1.2s + WORD $0x0eba1f9a // orr v26.8b, v28.8b, v26.8b + WORD $0x6e1a6379 // ext v25.16b, v27.16b, v26.16b, #12 + WORD $0x4e1c1d59 // mov v25.s[3], w10 + WORD $0x4e371f39 // and v25.16b, v25.16b, v23.16b + WORD $0x3c9c0119 // stur q25, [x8, #-64] + WORD $0xfc40c019 // ldur d25, [x0, #12] + WORD $0xbd40081a // ldr s26, [x0, #8] + WORD $0xb940140b // ldr w11, [x0, #20] + WORD $0x2ea2473b // ushl v27.2s, v25.2s, v2.2s + WORD $0x0e0c3f2a // mov w10, v25.s[1] + WORD $0x0e993b5a // zip1 v26.2s, v26.2s, v25.2s + WORD $0x138a296a // extr w10, w11, w10, #10 + WORD $0x2ea3475a // ushl v26.2s, v26.2s, v3.2s + WORD $0x0eba1f79 // orr v25.8b, v27.8b, v26.8b + WORD $0x4e141d59 // mov v25.s[2], w10 + WORD $0x53017d6a // lsr w10, w11, #1 + WORD $0x4e1c1d59 // mov v25.s[3], w10 + WORD $0x4e371f39 // and v25.16b, v25.16b, v23.16b + WORD $0x3c9d0119 // stur q25, [x8, #-48] + WORD $0xfd400c19 // ldr d25, [x0, #24] + WORD $0xbd40141a // ldr s26, [x0, #20] + WORD $0xb940200c // ldr w12, [x0, #32] + WORD $0x2ea4473b // ushl v27.2s, v25.2s, v4.2s + WORD $0x0e0c3f2a // mov w10, v25.s[1] + WORD $0x0e993b5a // zip1 v26.2s, v26.2s, v25.2s + WORD $0x53067d4b // lsr w11, w10, #6 + WORD $0x138a758a // extr w10, w12, w10, #29 + WORD $0x2ea5475a // ushl v26.2s, v26.2s, v5.2s + WORD $0x0eba1f79 // orr v25.8b, v27.8b, v26.8b + WORD $0x4e141d79 // mov v25.s[2], w11 + WORD $0x4e1c1d59 // mov v25.s[3], w10 + WORD $0x4e371f39 // and v25.16b, v25.16b, v23.16b + WORD $0x3c9e0119 // stur q25, [x8, #-32] + WORD $0xfc424019 // ldur d25, [x0, #36] + WORD $0xbd40201a // ldr s26, [x0, #32] + WORD $0xb9402c0c // ldr w12, [x0, #44] + WORD $0x2ea6473b // ushl v27.2s, v25.2s, v6.2s + WORD $0x0e0c3f2a // mov w10, v25.s[1] + WORD $0x0e993b5a // zip1 v26.2s, v26.2s, v25.2s + WORD $0x53027d4b // lsr w11, w10, #2 + WORD $0x138a658a // extr w10, w12, w10, #25 + WORD $0x2ea7475a // ushl v26.2s, v26.2s, v7.2s + WORD $0x0eba1f79 // orr v25.8b, v27.8b, v26.8b + WORD $0x4e141d79 // mov v25.s[2], w11 + WORD $0x4e1c1d59 // mov v25.s[3], w10 + WORD $0x4e371f39 // and v25.16b, v25.16b, v23.16b + WORD $0x3c9f0119 // stur q25, [x8, #-16] + WORD $0x2945a80b // ldp w11, w10, [x0, #44] + WORD $0xfc434019 // ldur d25, [x0, #52] + WORD $0x1e27015a // fmov s26, w10 + WORD $0x138b414b // extr w11, w10, w11, #16 + WORD $0x53077d4a // lsr w10, w10, #7 + WORD $0x0e993b5a // zip1 v26.2s, v26.2s, v25.2s + WORD $0x2eb04739 // ushl v25.2s, v25.2s, v16.2s + WORD $0x1e27017b // fmov s27, w11 + WORD $0x2eb1475a // ushl v26.2s, v26.2s, v17.2s + WORD $0x4e0c1d5b // mov v27.s[1], w10 + WORD $0x0eba1f39 // orr v25.8b, v25.8b, v26.8b + WORD $0x6e18073b // mov v27.d[1], v25.d[0] + WORD $0x4e371f79 // and v25.16b, v27.16b, v23.16b + WORD $0x3d800119 // str q25, [x8] + WORD $0x2947280b // ldp w11, w10, [x0, #56] + WORD $0xfd402019 // ldr d25, [x0, #64] + WORD $0x1e27015a // fmov s26, w10 + WORD $0x138b314b // extr w11, w10, w11, #12 + WORD $0x53037d4a // lsr w10, w10, #3 + WORD $0x0e993b5a // zip1 v26.2s, v26.2s, v25.2s + WORD $0x2eb24739 // ushl v25.2s, v25.2s, v18.2s + WORD $0x1e27017b // fmov s27, w11 + WORD $0x2eb3475a // ushl v26.2s, v26.2s, v19.2s + WORD $0x4e0c1d5b // mov v27.s[1], w10 + WORD $0x0eba1f39 // orr v25.8b, v25.8b, v26.8b + WORD $0x6e18073b // mov v27.d[1], v25.d[0] + WORD $0x4e371f79 // and v25.16b, v27.16b, v23.16b + WORD $0x3d800519 // str q25, [x8, #16] + WORD $0xb940440a // ldr w10, [x0, #68] + WORD $0xfd402419 // ldr d25, [x0, #72] + WORD $0xb940500b // ldr w11, [x0, #80] + WORD $0x1e27015a // fmov s26, w10 + WORD $0x53087d4a // lsr w10, w10, #8 + WORD $0x2eb4473b // ushl v27.2s, v25.2s, v20.2s + WORD $0x0e993b5a // zip1 v26.2s, v26.2s, v25.2s + WORD $0x1e27015c // fmov s28, w10 + WORD $0x0e0c3f2a // mov w10, v25.s[1] + WORD $0x6e1c239c // ext v28.16b, v28.16b, v28.16b, #4 + WORD $0x2eb5475a // ushl v26.2s, v26.2s, v21.2s + WORD $0x138a356a // extr w10, w11, w10, #13 + WORD $0x0eba1f7a // orr v26.8b, v27.8b, v26.8b + WORD $0x6e1a6399 // ext v25.16b, v28.16b, v26.16b, #12 + WORD $0x4e1c1d59 // mov v25.s[3], w10 + WORD $0x4e371f39 // and v25.16b, v25.16b, v23.16b + WORD $0x3d800919 // str q25, [x8, #32] + WORD $0xb940500a // ldr w10, [x0, #80] + WORD $0xfc454019 // ldur d25, [x0, #84] + WORD $0x91017000 // add x0, x0, #92 + WORD $0x1e27015a // fmov s26, w10 + WORD $0x53047d4a // lsr w10, w10, #4 + WORD $0x2eb6473b // ushl v27.2s, v25.2s, v22.2s + WORD $0x0e993b5a // zip1 v26.2s, v26.2s, v25.2s + WORD $0x1e27015c // fmov s28, w10 + WORD $0x0e0c3f2a // mov w10, v25.s[1] + WORD $0x6e1c239c // ext v28.16b, v28.16b, v28.16b, #4 + WORD $0x2eb8475a // ushl v26.2s, v26.2s, v24.2s + WORD $0x53097d4a // lsr w10, w10, #9 + WORD $0x0eba1f7a // orr v26.8b, v27.8b, v26.8b + WORD $0x6e1a6399 // ext v25.16b, v28.16b, v26.16b, #12 + WORD $0x4e1c1d59 // mov v25.s[3], w10 + WORD $0x4e371f39 // and v25.16b, v25.16b, v23.16b + WORD $0x3d800d19 // str q25, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_94 + JMP LBB0_156 + LBB0_95: - WORD $0xad410400 // ldp q0, q1, [x0, #32] - WORD $0xad400c02 // ldp q2, q3, [x0] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0xad010420 // stp q0, q1, [x1, #32] - WORD $0xad000c22 // stp q2, q3, [x1] - WORD $0xad430400 // ldp q0, q1, [x0, #96] - WORD $0xad420c02 // ldp q2, q3, [x0, #64] - WORD $0x91020000 // add x0, x0, #128 - WORD $0xad030420 // stp q0, q1, [x1, #96] - WORD $0xad020c22 // stp q2, q3, [x1, #64] - WORD $0x91020021 // add x1, x1, #128 - - BNE LBB0_95 - JMP LBB0_99 -LBB0_96: - WORD $0x7100805f // cmp w2, #32 - BLT LBB0_99 - MOVD $0x000000160000001c, R3 // LCPI0_50 - MOVD $0x0000000a00000004, R0 // LCPI0_51 - MOVD $0x0000000a00000010, R4 // LCPI0_52 - MOVD $0x0000001600000010, R1 // LCPI0_53 - MOVD $0x0000001200000018, R5 // LCPI0_54 - MOVD $0x0000000e00000008, R2 // LCPI0_55 - - WORD $0x91010029 // add x9, x1, #64 - WORD $0x2ea0b863 // neg v3.2s, v3.2s - WORD $0x2ea0b884 // neg v4.2s, v4.2s - WORD $0x2ea0b8a5 // neg v5.2s, v5.2s -LBB0_98: - WORD $0x29402c0a // ldp w10, w11, [x0] - WORD $0x2941340c // ldp w12, w13, [x0, #8] - WORD $0xf1000508 // subs x8, x8, #1 - WORD $0x138a696e // extr w14, w11, w10, #26 - WORD $0x1e270146 // fmov s6, w10 - WORD $0x138b518b // extr w11, w12, w11, #20 - WORD $0x4e0c1dc6 // mov v6.s[1], w14 - WORD $0x138c39ac // extr w12, w13, w12, #14 - WORD $0x4e141d66 // mov v6.s[2], w11 - WORD $0x4e1c1d86 // mov v6.s[3], w12 - WORD $0x6f077786 // bic v6.4s, #252, lsl #24 - WORD $0x3c9c0126 // stur q6, [x9, #-64] - WORD $0x2941ac0a // ldp w10, w11, [x0, #12] - WORD $0xfc414006 // ldur d6, [x0, #20] - WORD $0x1e270167 // fmov s7, w11 - WORD $0x138a216a // extr w10, w11, w10, #8 - WORD $0x0e8638e7 // zip1 v7.2s, v7.2s, v6.2s - WORD $0x53027d6c // lsr w12, w11, #2 - WORD $0x2ea044c6 // ushl v6.2s, v6.2s, v0.2s - WORD $0x1e270150 // fmov s16, w10 - WORD $0x2ea344e7 // ushl v7.2s, v7.2s, v3.2s - WORD $0x4e0c1d90 // mov v16.s[1], w12 - WORD $0x0ea71cc6 // orr v6.8b, v6.8b, v7.8b - WORD $0x6e1804d0 // mov v16.d[1], v6.d[0] - WORD $0x6f077790 // bic v16.4s, #252, lsl #24 - WORD $0x3c9d0130 // stur q16, [x9, #-48] - WORD $0xfc41c006 // ldur d6, [x0, #28] - WORD $0xbd401807 // ldr s7, [x0, #24] - WORD $0xb940240a // ldr w10, [x0, #36] - WORD $0x2ea144d0 // ushl v16.2s, v6.2s, v1.2s - WORD $0x0e8638e7 // zip1 v7.2s, v7.2s, v6.2s - WORD $0x0e0c3ccb // mov w11, v6.s[1] - WORD $0x2ea444e6 // ushl v6.2s, v7.2s, v4.2s - WORD $0x53047d6c // lsr w12, w11, #4 - WORD $0x0ea61e06 // orr v6.8b, v16.8b, v6.8b - WORD $0x138b794a // extr w10, w10, w11, #30 - WORD $0x4e141d86 // mov v6.s[2], w12 - WORD $0x4e1c1d46 // mov v6.s[3], w10 - WORD $0x6f077786 // bic v6.4s, #252, lsl #24 - WORD $0x3c9e0126 // stur q6, [x9, #-32] - WORD $0xfd401406 // ldr d6, [x0, #40] - WORD $0xbd402407 // ldr s7, [x0, #36] - WORD $0xb940300a // ldr w10, [x0, #48] - WORD $0x2ea244d0 // ushl v16.2s, v6.2s, v2.2s - WORD $0x0e8638e7 // zip1 v7.2s, v7.2s, v6.2s - WORD $0x0e0c3ccb // mov w11, v6.s[1] - WORD $0x2ea544e6 // ushl v6.2s, v7.2s, v5.2s - WORD $0x138b314a // extr w10, w10, w11, #12 - WORD $0x0ea61e06 // orr v6.8b, v16.8b, v6.8b - WORD $0x4e141d46 // mov v6.s[2], w10 - WORD $0x4e1c1d86 // mov v6.s[3], w12 - WORD $0x6f077786 // bic v6.4s, #252, lsl #24 - WORD $0x3c9f0126 // stur q6, [x9, #-16] - WORD $0x2946ac0a // ldp w10, w11, [x0, #52] - WORD $0x2947b40c // ldp w12, w13, [x0, #60] - WORD $0x138a696e // extr w14, w11, w10, #26 - WORD $0x1e270146 // fmov s6, w10 - WORD $0x138b518b // extr w11, w12, w11, #20 - WORD $0x4e0c1dc6 // mov v6.s[1], w14 - WORD $0x138c39ac // extr w12, w13, w12, #14 - WORD $0x4e1c1d86 // mov v6.s[3], w12 - WORD $0x6f077786 // bic v6.4s, #252, lsl #24 - WORD $0x3d800126 // str q6, [x9] - WORD $0x29482c0a // ldp w10, w11, [x0, #64] - WORD $0xfd402406 // ldr d6, [x0, #72] - WORD $0x1e270167 // fmov s7, w11 - WORD $0x138a216a // extr w10, w11, w10, #8 - WORD $0x0e8638e7 // zip1 v7.2s, v7.2s, v6.2s - WORD $0x2ea044c6 // ushl v6.2s, v6.2s, v0.2s - WORD $0x1e270150 // fmov s16, w10 - WORD $0x2ea344e7 // ushl v7.2s, v7.2s, v3.2s - WORD $0x4e0c1d90 // mov v16.s[1], w12 - WORD $0x0ea71cc6 // orr v6.8b, v6.8b, v7.8b - WORD $0x6e1804d0 // mov v16.d[1], v6.d[0] - WORD $0x6f077790 // bic v16.4s, #252, lsl #24 - WORD $0x3d800530 // str q16, [x9, #16] - WORD $0xfd402806 // ldr d6, [x0, #80] - WORD $0xbd404c07 // ldr s7, [x0, #76] - WORD $0xb940580a // ldr w10, [x0, #88] - WORD $0x2ea144d0 // ushl v16.2s, v6.2s, v1.2s - WORD $0x0e8638e7 // zip1 v7.2s, v7.2s, v6.2s - WORD $0x0e0c3ccb // mov w11, v6.s[1] - WORD $0x2ea444e6 // ushl v6.2s, v7.2s, v4.2s - WORD $0x53047d6c // lsr w12, w11, #4 - WORD $0x0ea61e06 // orr v6.8b, v16.8b, v6.8b - WORD $0x138b794a // extr w10, w10, w11, #30 - WORD $0x4e141d86 // mov v6.s[2], w12 - WORD $0x4e1c1d46 // mov v6.s[3], w10 - WORD $0x6f077786 // bic v6.4s, #252, lsl #24 - WORD $0x3d800926 // str q6, [x9, #32] - WORD $0xfc45c006 // ldur d6, [x0, #92] - WORD $0xbd405807 // ldr s7, [x0, #88] - WORD $0xb940640a // ldr w10, [x0, #100] - WORD $0x9101a000 // add x0, x0, #104 - WORD $0x2ea244d0 // ushl v16.2s, v6.2s, v2.2s - WORD $0x0e8638e7 // zip1 v7.2s, v7.2s, v6.2s - WORD $0x0e0c3ccb // mov w11, v6.s[1] - WORD $0x2ea544e6 // ushl v6.2s, v7.2s, v5.2s - WORD $0x53067d4c // lsr w12, w10, #6 - WORD $0x138b314a // extr w10, w10, w11, #12 - WORD $0x0ea61e06 // orr v6.8b, v16.8b, v6.8b - WORD $0x4e141d46 // mov v6.s[2], w10 - WORD $0x4e1c1d86 // mov v6.s[3], w12 - WORD $0x6f077786 // bic v6.4s, #252, lsl #24 - WORD $0x3d800d26 // str q6, [x9, #48] - WORD $0x91020129 // add x9, x9, #128 - - BNE LBB0_98 + WORD $0x7100387f // cmp w3, #14 + BEQ LBB0_145 + + // %bb.96: + WORD $0x71003c7f // cmp w3, #15 + BNE LBB0_156 + + // %bb.97: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.98: + // WORD $0x90000009 // adrp x9, .LCPI0_138 + WORD $0x91010348 // add x8, x26, #64 + WORD $0x4f03c7e0 // movi v0.4s, #127, msl #8 + VMOVD LCPI0_138, V1 + WORD $0xaa1303e9 // mov x9, x19 + LBB0_99: - MOVD R19, num+32(FP) - WORD $0xf9400bf3 // ldr x19, [sp, #16] - WORD $0xa8c27bfd // ldp x29, x30, [sp], #32 - RET + WORD $0x29402c0a // ldp w10, w11, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x530f7d4c // lsr w12, w10, #15 + WORD $0x1e270142 // fmov s2, w10 + WORD $0x138a796a // extr w10, w11, w10, #30 + WORD $0x4e0c1d82 // mov v2.s[1], w12 + WORD $0x4e141d42 // mov v2.s[2], w10 + WORD $0x530d7d6a // lsr w10, w11, #13 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3c9c0102 // stur q2, [x8, #-64] + WORD $0x2940ac0a // ldp w10, w11, [x0, #4] + WORD $0x138a716a // extr w10, w11, w10, #28 + WORD $0x530b7d6c // lsr w12, w11, #11 + WORD $0x1e270142 // fmov s2, w10 + WORD $0xb9400c0a // ldr w10, [x0, #12] + WORD $0x138b694b // extr w11, w10, w11, #26 + WORD $0x4e0c1d82 // mov v2.s[1], w12 + WORD $0x53097d4a // lsr w10, w10, #9 + WORD $0x4e141d62 // mov v2.s[2], w11 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3c9d0102 // stur q2, [x8, #-48] + WORD $0x2941ac0a // ldp w10, w11, [x0, #12] + WORD $0x138a616a // extr w10, w11, w10, #24 + WORD $0x53077d6c // lsr w12, w11, #7 + WORD $0x1e270142 // fmov s2, w10 + WORD $0xb940140a // ldr w10, [x0, #20] + WORD $0x138b594b // extr w11, w10, w11, #22 + WORD $0x4e0c1d82 // mov v2.s[1], w12 + WORD $0x53057d4a // lsr w10, w10, #5 + WORD $0x4e141d62 // mov v2.s[2], w11 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3c9e0102 // stur q2, [x8, #-32] + WORD $0x2942ac0a // ldp w10, w11, [x0, #20] + WORD $0x138a516a // extr w10, w11, w10, #20 + WORD $0x53037d6c // lsr w12, w11, #3 + WORD $0x1e270142 // fmov s2, w10 + WORD $0xb9401c0a // ldr w10, [x0, #28] + WORD $0x138b494b // extr w11, w10, w11, #18 + WORD $0x4e0c1d82 // mov v2.s[1], w12 + WORD $0x53017d4a // lsr w10, w10, #1 + WORD $0x4e141d62 // mov v2.s[2], w11 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3c9f0102 // stur q2, [x8, #-16] + WORD $0x2943ac0a // ldp w10, w11, [x0, #28] + WORD $0x53107d4c // lsr w12, w10, #16 + WORD $0x138a7d6a // extr w10, w11, w10, #31 + WORD $0x1e270182 // fmov s2, w12 + WORD $0xb940240c // ldr w12, [x0, #36] + WORD $0x4e0c1d42 // mov v2.s[1], w10 + WORD $0x530e7d6a // lsr w10, w11, #14 + WORD $0x4e141d42 // mov v2.s[2], w10 + WORD $0x138b758a // extr w10, w12, w11, #29 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3d800102 // str q2, [x8] + WORD $0x2944ac0a // ldp w10, w11, [x0, #36] + WORD $0x530c7d4c // lsr w12, w10, #12 + WORD $0x138a6d6a // extr w10, w11, w10, #27 + WORD $0x1e270182 // fmov s2, w12 + WORD $0xb9402c0c // ldr w12, [x0, #44] + WORD $0x4e0c1d42 // mov v2.s[1], w10 + WORD $0x530a7d6a // lsr w10, w11, #10 + WORD $0x4e141d42 // mov v2.s[2], w10 + WORD $0x138b658a // extr w10, w12, w11, #25 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3d800502 // str q2, [x8, #16] + WORD $0x2945ac0a // ldp w10, w11, [x0, #44] + WORD $0x53087d4c // lsr w12, w10, #8 + WORD $0x138a5d6a // extr w10, w11, w10, #23 + WORD $0x1e270182 // fmov s2, w12 + WORD $0xb940340c // ldr w12, [x0, #52] + WORD $0x4e0c1d42 // mov v2.s[1], w10 + WORD $0x53067d6a // lsr w10, w11, #6 + WORD $0x4e141d42 // mov v2.s[2], w10 + WORD $0x138b558a // extr w10, w12, w11, #21 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3d800902 // str q2, [x8, #32] + WORD $0x2946ac0a // ldp w10, w11, [x0, #52] + WORD $0x9100f000 // add x0, x0, #60 + WORD $0x53047d4c // lsr w12, w10, #4 + WORD $0x0e040d62 // dup v2.2s, w11 + WORD $0x138a4d6a // extr w10, w11, w10, #19 + WORD $0x1e270183 // fmov s3, w12 + WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s + WORD $0x4e0c1d43 // mov v3.s[1], w10 + WORD $0x6e180443 // mov v3.d[1], v2.d[0] + WORD $0x4e201c62 // and v2.16b, v3.16b, v0.16b + WORD $0x3d800d02 // str q2, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_99 + JMP LBB0_156 + +LBB0_100: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.101: + // WORD $0x90000008 // adrp x8, .LCPI0_8 + // WORD $0x90000009 // adrp x9, .LCPI0_9 + // WORD $0x9000000a // adrp x10, .LCPI0_10 + // WORD $0x9000000b // adrp x11, .LCPI0_23 + VMOVD LCPI0_8, V0 + // WORD $0x90000008 // adrp x8, .LCPI0_11 + VMOVD LCPI0_9, V1 + // WORD $0x90000009 // adrp x9, .LCPI0_12 + VMOVQ LCPI0_10L, LCPI0_10H, V2 + // WORD $0x9000000a // adrp x10, .LCPI0_13 + VMOVQ LCPI0_11L, LCPI0_11H, V3 + // WORD $0x90000008 // adrp x8, .LCPI0_14 + VMOVQ LCPI0_12L, LCPI0_12H, V4 + // WORD $0x90000009 // adrp x9, .LCPI0_15 + VMOVQ LCPI0_13L, LCPI0_13H, V5 + // WORD $0x9000000a // adrp x10, .LCPI0_16 + VMOVQ LCPI0_14L, LCPI0_14H, V6 + // WORD $0x90000008 // adrp x8, .LCPI0_17 + VMOVQ LCPI0_15L, LCPI0_15H, V7 + // WORD $0x90000009 // adrp x9, .LCPI0_18 + VMOVQ LCPI0_16L, LCPI0_16H, V16 + // WORD $0x9000000a // adrp x10, .LCPI0_19 + VMOVQ LCPI0_17L, LCPI0_17H, V17 + // WORD $0x90000008 // adrp x8, .LCPI0_20 + VMOVQ LCPI0_18L, LCPI0_18H, V18 + // WORD $0x90000009 // adrp x9, .LCPI0_21 + VMOVQ LCPI0_19L, LCPI0_19H, V19 + // WORD $0x9000000a // adrp x10, .LCPI0_22 + VMOVQ LCPI0_20L, LCPI0_20H, V20 + WORD $0x91010348 // add x8, x26, #64 + VMOVQ LCPI0_21L, LCPI0_21H, V21 + WORD $0xaa1303e9 // mov x9, x19 + VMOVD LCPI0_22, V22 + VMOVD LCPI0_23, V23 + +LBB0_102: + WORD $0xb940000a // ldr w10, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0xfc404018 // ldur d24, [x0, #4] + WORD $0xb9400c0b // ldr w11, [x0, #12] + WORD $0x1e270159 // fmov s25, w10 + WORD $0x1e27015a // fmov s26, w10 + WORD $0x2ea0471b // ushl v27.2s, v24.2s, v0.2s + WORD $0x0e0c3f0a // mov w10, v24.s[1] + WORD $0x0e983b39 // zip1 v25.2s, v25.2s, v24.2s + WORD $0x6e1a235a // ext v26.16b, v26.16b, v26.16b, #4 + WORD $0x138a756a // extr w10, w11, w10, #29 + WORD $0x2ea14739 // ushl v25.2s, v25.2s, v1.2s + WORD $0x0eb91f79 // orr v25.8b, v27.8b, v25.8b + WORD $0x6e196358 // ext v24.16b, v26.16b, v25.16b, #12 + WORD $0x4e1c1d58 // mov v24.s[3], w10 + WORD $0x6f047418 // bic v24.4s, #128, lsl #24 + WORD $0x3c9c0118 // stur q24, [x8, #-64] + WORD $0xbd400c18 // ldr s24, [x0, #12] + WORD $0x3dc00419 // ldr q25, [x0, #16] + WORD $0x6e182318 // ext v24.16b, v24.16b, v24.16b, #4 + WORD $0x6e196318 // ext v24.16b, v24.16b, v25.16b, #12 + WORD $0x6ea24739 // ushl v25.4s, v25.4s, v2.4s + WORD $0x6ea34718 // ushl v24.4s, v24.4s, v3.4s + WORD $0x4eb81f38 // orr v24.16b, v25.16b, v24.16b + WORD $0x6f047418 // bic v24.4s, #128, lsl #24 + WORD $0x3c9d0118 // stur q24, [x8, #-48] + WORD $0xbd401c18 // ldr s24, [x0, #28] + WORD $0x3dc00819 // ldr q25, [x0, #32] + WORD $0x6e182318 // ext v24.16b, v24.16b, v24.16b, #4 + WORD $0x6e196318 // ext v24.16b, v24.16b, v25.16b, #12 + WORD $0x6ea44739 // ushl v25.4s, v25.4s, v4.4s + WORD $0x6ea54718 // ushl v24.4s, v24.4s, v5.4s + WORD $0x4eb81f38 // orr v24.16b, v25.16b, v24.16b + WORD $0x6f047418 // bic v24.4s, #128, lsl #24 + WORD $0x3c9e0118 // stur q24, [x8, #-32] + WORD $0xbd402c18 // ldr s24, [x0, #44] + WORD $0x3dc00c19 // ldr q25, [x0, #48] + WORD $0x6e182318 // ext v24.16b, v24.16b, v24.16b, #4 + WORD $0x6e196318 // ext v24.16b, v24.16b, v25.16b, #12 + WORD $0x6ea64739 // ushl v25.4s, v25.4s, v6.4s + WORD $0x6ea74718 // ushl v24.4s, v24.4s, v7.4s + WORD $0x4eb81f38 // orr v24.16b, v25.16b, v24.16b + WORD $0x6f047418 // bic v24.4s, #128, lsl #24 + WORD $0x3c9f0118 // stur q24, [x8, #-16] + WORD $0xbd403c18 // ldr s24, [x0, #60] + WORD $0x3dc01019 // ldr q25, [x0, #64] + WORD $0x6e182318 // ext v24.16b, v24.16b, v24.16b, #4 + WORD $0x6e196318 // ext v24.16b, v24.16b, v25.16b, #12 + WORD $0x6eb04739 // ushl v25.4s, v25.4s, v16.4s + WORD $0x6eb14718 // ushl v24.4s, v24.4s, v17.4s + WORD $0x4eb81f38 // orr v24.16b, v25.16b, v24.16b + WORD $0x6f047418 // bic v24.4s, #128, lsl #24 + WORD $0x3d800118 // str q24, [x8] + WORD $0xbd404c18 // ldr s24, [x0, #76] + WORD $0x3dc01419 // ldr q25, [x0, #80] + WORD $0x6e182318 // ext v24.16b, v24.16b, v24.16b, #4 + WORD $0x6e196318 // ext v24.16b, v24.16b, v25.16b, #12 + WORD $0x6eb24739 // ushl v25.4s, v25.4s, v18.4s + WORD $0x6eb34718 // ushl v24.4s, v24.4s, v19.4s + WORD $0x4eb81f38 // orr v24.16b, v25.16b, v24.16b + WORD $0x6f047418 // bic v24.4s, #128, lsl #24 + WORD $0x3d800518 // str q24, [x8, #16] + WORD $0xbd405c18 // ldr s24, [x0, #92] + WORD $0x3dc01819 // ldr q25, [x0, #96] + WORD $0x6e182318 // ext v24.16b, v24.16b, v24.16b, #4 + WORD $0x6e196318 // ext v24.16b, v24.16b, v25.16b, #12 + WORD $0x6eb44739 // ushl v25.4s, v25.4s, v20.4s + WORD $0x6eb54718 // ushl v24.4s, v24.4s, v21.4s + WORD $0x4eb81f38 // orr v24.16b, v25.16b, v24.16b + WORD $0x6f047418 // bic v24.4s, #128, lsl #24 + WORD $0x3d800918 // str q24, [x8, #32] + WORD $0xfd403818 // ldr d24, [x0, #112] + WORD $0xbd406c19 // ldr s25, [x0, #108] + WORD $0xb940780b // ldr w11, [x0, #120] + WORD $0x9101f000 // add x0, x0, #124 + WORD $0x2eb6471a // ushl v26.2s, v24.2s, v22.2s + WORD $0x0e0c3f0a // mov w10, v24.s[1] + WORD $0x0e983b39 // zip1 v25.2s, v25.2s, v24.2s + WORD $0x138a096a // extr w10, w11, w10, #2 + WORD $0x2eb74739 // ushl v25.2s, v25.2s, v23.2s + WORD $0x0eb91f58 // orr v24.8b, v26.8b, v25.8b + WORD $0x4e141d58 // mov v24.s[2], w10 + WORD $0x53017d6a // lsr w10, w11, #1 + WORD $0x4e1c1d58 // mov v24.s[3], w10 + WORD $0x6f047418 // bic v24.4s, #128, lsl #24 + WORD $0x3d800d18 // str q24, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_102 + JMP LBB0_156 + +LBB0_103: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.104: + WORD $0x7100427f // cmp w19, #16 + WORD $0x54000002 // b.hs .LBB0_151 + + // %bb.105: + WORD $0xaa1f03e8 // mov x8, xzr + JMP LBB0_154 + +LBB0_106: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.107: + WORD $0x6f01e660 // movi v0.2d, #0x00ffff0000ffff + WORD $0x91010348 // add x8, x26, #64 + WORD $0xaa1303e9 // mov x9, x19 + +LBB0_108: + WORD $0x29402c0a // ldp w10, w11, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x53107d4c // lsr w12, w10, #16 + WORD $0x1e270141 // fmov s1, w10 + WORD $0x53107d6a // lsr w10, w11, #16 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0x4e141d61 // mov v1.s[2], w11 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3c9c0101 // stur q1, [x8, #-64] + WORD $0x29412c0a // ldp w10, w11, [x0, #8] + WORD $0x53107d4c // lsr w12, w10, #16 + WORD $0x1e270141 // fmov s1, w10 + WORD $0x53107d6a // lsr w10, w11, #16 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0x4e141d61 // mov v1.s[2], w11 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3c9d0101 // stur q1, [x8, #-48] + WORD $0x29422c0a // ldp w10, w11, [x0, #16] + WORD $0x53107d4c // lsr w12, w10, #16 + WORD $0x1e270141 // fmov s1, w10 + WORD $0x53107d6a // lsr w10, w11, #16 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0x4e141d61 // mov v1.s[2], w11 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3c9e0101 // stur q1, [x8, #-32] + WORD $0x29432c0a // ldp w10, w11, [x0, #24] + WORD $0x53107d4c // lsr w12, w10, #16 + WORD $0x1e270141 // fmov s1, w10 + WORD $0x53107d6a // lsr w10, w11, #16 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0x4e141d61 // mov v1.s[2], w11 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3c9f0101 // stur q1, [x8, #-16] + WORD $0x29442c0a // ldp w10, w11, [x0, #32] + WORD $0x53107d4c // lsr w12, w10, #16 + WORD $0x1e270141 // fmov s1, w10 + WORD $0x53107d6a // lsr w10, w11, #16 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0x4e141d61 // mov v1.s[2], w11 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3d800101 // str q1, [x8] + WORD $0x29452c0a // ldp w10, w11, [x0, #40] + WORD $0x53107d4c // lsr w12, w10, #16 + WORD $0x1e270141 // fmov s1, w10 + WORD $0x53107d6a // lsr w10, w11, #16 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0x4e141d61 // mov v1.s[2], w11 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3d800501 // str q1, [x8, #16] + WORD $0x29462c0a // ldp w10, w11, [x0, #48] + WORD $0x53107d4c // lsr w12, w10, #16 + WORD $0x1e270141 // fmov s1, w10 + WORD $0x53107d6a // lsr w10, w11, #16 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0x4e141d61 // mov v1.s[2], w11 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3d800901 // str q1, [x8, #32] + WORD $0x29472c0a // ldp w10, w11, [x0, #56] + WORD $0x91010000 // add x0, x0, #64 + WORD $0x53107d4c // lsr w12, w10, #16 + WORD $0x1e270141 // fmov s1, w10 + WORD $0x53107d6a // lsr w10, w11, #16 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0x4e141d61 // mov v1.s[2], w11 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3d800d01 // str q1, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_108 + JMP LBB0_156 + +LBB0_109: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.110: + // WORD $0x90000009 // adrp x9, .LCPI0_165 + WORD $0x91010348 // add x8, x26, #64 + WORD $0x6f00e620 // movi v0.2d, #0x0000ff000000ff + VMOVD LCPI0_165, V1 + WORD $0xaa1303e9 // mov x9, x19 + +LBB0_111: + WORD $0xb940000a // ldr w10, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x0e040d42 // dup v2.2s, w10 + WORD $0x1e270143 // fmov s3, w10 + WORD $0x53187d4a // lsr w10, w10, #24 + WORD $0x6e032063 // ext v3.16b, v3.16b, v3.16b, #4 + WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s + WORD $0x6e026062 // ext v2.16b, v3.16b, v2.16b, #12 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3c9c0102 // stur q2, [x8, #-64] + WORD $0xb940040a // ldr w10, [x0, #4] + WORD $0x0e040d42 // dup v2.2s, w10 + WORD $0x1e270143 // fmov s3, w10 + WORD $0x53187d4a // lsr w10, w10, #24 + WORD $0x6e032063 // ext v3.16b, v3.16b, v3.16b, #4 + WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s + WORD $0x6e026062 // ext v2.16b, v3.16b, v2.16b, #12 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3c9d0102 // stur q2, [x8, #-48] + WORD $0xb940080a // ldr w10, [x0, #8] + WORD $0x0e040d42 // dup v2.2s, w10 + WORD $0x1e270143 // fmov s3, w10 + WORD $0x53187d4a // lsr w10, w10, #24 + WORD $0x6e032063 // ext v3.16b, v3.16b, v3.16b, #4 + WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s + WORD $0x6e026062 // ext v2.16b, v3.16b, v2.16b, #12 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3c9e0102 // stur q2, [x8, #-32] + WORD $0xb9400c0a // ldr w10, [x0, #12] + WORD $0x0e040d42 // dup v2.2s, w10 + WORD $0x1e270143 // fmov s3, w10 + WORD $0x53187d4a // lsr w10, w10, #24 + WORD $0x6e032063 // ext v3.16b, v3.16b, v3.16b, #4 + WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s + WORD $0x6e026062 // ext v2.16b, v3.16b, v2.16b, #12 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3c9f0102 // stur q2, [x8, #-16] + WORD $0xb940100a // ldr w10, [x0, #16] + WORD $0x0e040d42 // dup v2.2s, w10 + WORD $0x1e270143 // fmov s3, w10 + WORD $0x53187d4a // lsr w10, w10, #24 + WORD $0x6e032063 // ext v3.16b, v3.16b, v3.16b, #4 + WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s + WORD $0x6e026062 // ext v2.16b, v3.16b, v2.16b, #12 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3d800102 // str q2, [x8] + WORD $0xb940140a // ldr w10, [x0, #20] + WORD $0x0e040d42 // dup v2.2s, w10 + WORD $0x1e270143 // fmov s3, w10 + WORD $0x53187d4a // lsr w10, w10, #24 + WORD $0x6e032063 // ext v3.16b, v3.16b, v3.16b, #4 + WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s + WORD $0x6e026062 // ext v2.16b, v3.16b, v2.16b, #12 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3d800502 // str q2, [x8, #16] + WORD $0xb940180a // ldr w10, [x0, #24] + WORD $0x0e040d42 // dup v2.2s, w10 + WORD $0x1e270143 // fmov s3, w10 + WORD $0x53187d4a // lsr w10, w10, #24 + WORD $0x6e032063 // ext v3.16b, v3.16b, v3.16b, #4 + WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s + WORD $0x6e026062 // ext v2.16b, v3.16b, v2.16b, #12 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3d800902 // str q2, [x8, #32] + WORD $0xb9401c0a // ldr w10, [x0, #28] + WORD $0x91008000 // add x0, x0, #32 + WORD $0x0e040d42 // dup v2.2s, w10 + WORD $0x1e270143 // fmov s3, w10 + WORD $0x53187d4a // lsr w10, w10, #24 + WORD $0x6e032063 // ext v3.16b, v3.16b, v3.16b, #4 + WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s + WORD $0x6e026062 // ext v2.16b, v3.16b, v2.16b, #12 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3d800d02 // str q2, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_111 + JMP LBB0_156 + +LBB0_112: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.113: + // WORD $0x90000009 // adrp x9, .LCPI0_92 + // WORD $0x9000000a // adrp x10, .LCPI0_93 + WORD $0x91010348 // add x8, x26, #64 + VMOVD LCPI0_92, V0 + WORD $0xaa1303e9 // mov x9, x19 + VMOVD LCPI0_93, V1 + +LBB0_114: + WORD $0xb940000a // ldr w10, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0xfc404002 // ldur d2, [x0, #4] + WORD $0x1e270143 // fmov s3, w10 + WORD $0x1e270144 // fmov s4, w10 + WORD $0x2ea04445 // ushl v5.2s, v2.2s, v0.2s + WORD $0x0e0c3c4a // mov w10, v2.s[1] + WORD $0x0e823863 // zip1 v3.2s, v3.2s, v2.2s + WORD $0x6e042084 // ext v4.16b, v4.16b, v4.16b, #4 + WORD $0x53087d4a // lsr w10, w10, #8 + WORD $0x2ea14463 // ushl v3.2s, v3.2s, v1.2s + WORD $0x0ea31ca3 // orr v3.8b, v5.8b, v3.8b + WORD $0x6e036082 // ext v2.16b, v4.16b, v3.16b, #12 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x6f0777e2 // bic v2.4s, #255, lsl #24 + WORD $0x3c9c0102 // stur q2, [x8, #-64] + WORD $0xb9400c0a // ldr w10, [x0, #12] + WORD $0xfd400802 // ldr d2, [x0, #16] + WORD $0x1e270143 // fmov s3, w10 + WORD $0x1e270144 // fmov s4, w10 + WORD $0x2ea04445 // ushl v5.2s, v2.2s, v0.2s + WORD $0x0e0c3c4a // mov w10, v2.s[1] + WORD $0x0e823863 // zip1 v3.2s, v3.2s, v2.2s + WORD $0x6e042084 // ext v4.16b, v4.16b, v4.16b, #4 + WORD $0x53087d4a // lsr w10, w10, #8 + WORD $0x2ea14463 // ushl v3.2s, v3.2s, v1.2s + WORD $0x0ea31ca3 // orr v3.8b, v5.8b, v3.8b + WORD $0x6e036082 // ext v2.16b, v4.16b, v3.16b, #12 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x6f0777e2 // bic v2.4s, #255, lsl #24 + WORD $0x3c9d0102 // stur q2, [x8, #-48] + WORD $0xb940180a // ldr w10, [x0, #24] + WORD $0xfc41c002 // ldur d2, [x0, #28] + WORD $0x1e270143 // fmov s3, w10 + WORD $0x1e270144 // fmov s4, w10 + WORD $0x2ea04445 // ushl v5.2s, v2.2s, v0.2s + WORD $0x0e0c3c4a // mov w10, v2.s[1] + WORD $0x0e823863 // zip1 v3.2s, v3.2s, v2.2s + WORD $0x6e042084 // ext v4.16b, v4.16b, v4.16b, #4 + WORD $0x53087d4a // lsr w10, w10, #8 + WORD $0x2ea14463 // ushl v3.2s, v3.2s, v1.2s + WORD $0x0ea31ca3 // orr v3.8b, v5.8b, v3.8b + WORD $0x6e036082 // ext v2.16b, v4.16b, v3.16b, #12 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x6f0777e2 // bic v2.4s, #255, lsl #24 + WORD $0x3c9e0102 // stur q2, [x8, #-32] + WORD $0xb940240a // ldr w10, [x0, #36] + WORD $0xfd401402 // ldr d2, [x0, #40] + WORD $0x1e270143 // fmov s3, w10 + WORD $0x1e270144 // fmov s4, w10 + WORD $0x2ea04445 // ushl v5.2s, v2.2s, v0.2s + WORD $0x0e0c3c4a // mov w10, v2.s[1] + WORD $0x0e823863 // zip1 v3.2s, v3.2s, v2.2s + WORD $0x6e042084 // ext v4.16b, v4.16b, v4.16b, #4 + WORD $0x53087d4a // lsr w10, w10, #8 + WORD $0x2ea14463 // ushl v3.2s, v3.2s, v1.2s + WORD $0x0ea31ca3 // orr v3.8b, v5.8b, v3.8b + WORD $0x6e036082 // ext v2.16b, v4.16b, v3.16b, #12 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x6f0777e2 // bic v2.4s, #255, lsl #24 + WORD $0x3c9f0102 // stur q2, [x8, #-16] + WORD $0xb940300a // ldr w10, [x0, #48] + WORD $0xfc434002 // ldur d2, [x0, #52] + WORD $0x1e270143 // fmov s3, w10 + WORD $0x1e270144 // fmov s4, w10 + WORD $0x2ea04445 // ushl v5.2s, v2.2s, v0.2s + WORD $0x0e0c3c4a // mov w10, v2.s[1] + WORD $0x0e823863 // zip1 v3.2s, v3.2s, v2.2s + WORD $0x6e042084 // ext v4.16b, v4.16b, v4.16b, #4 + WORD $0x53087d4a // lsr w10, w10, #8 + WORD $0x2ea14463 // ushl v3.2s, v3.2s, v1.2s + WORD $0x0ea31ca3 // orr v3.8b, v5.8b, v3.8b + WORD $0x6e036082 // ext v2.16b, v4.16b, v3.16b, #12 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x6f0777e2 // bic v2.4s, #255, lsl #24 + WORD $0x3d800102 // str q2, [x8] + WORD $0xb9403c0a // ldr w10, [x0, #60] + WORD $0xfd402002 // ldr d2, [x0, #64] + WORD $0x1e270143 // fmov s3, w10 + WORD $0x1e270144 // fmov s4, w10 + WORD $0x2ea04445 // ushl v5.2s, v2.2s, v0.2s + WORD $0x0e0c3c4a // mov w10, v2.s[1] + WORD $0x0e823863 // zip1 v3.2s, v3.2s, v2.2s + WORD $0x6e042084 // ext v4.16b, v4.16b, v4.16b, #4 + WORD $0x53087d4a // lsr w10, w10, #8 + WORD $0x2ea14463 // ushl v3.2s, v3.2s, v1.2s + WORD $0x0ea31ca3 // orr v3.8b, v5.8b, v3.8b + WORD $0x6e036082 // ext v2.16b, v4.16b, v3.16b, #12 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x6f0777e2 // bic v2.4s, #255, lsl #24 + WORD $0x3d800502 // str q2, [x8, #16] + WORD $0xb940480a // ldr w10, [x0, #72] + WORD $0xfc44c002 // ldur d2, [x0, #76] + WORD $0x1e270143 // fmov s3, w10 + WORD $0x1e270144 // fmov s4, w10 + WORD $0x2ea04445 // ushl v5.2s, v2.2s, v0.2s + WORD $0x0e0c3c4a // mov w10, v2.s[1] + WORD $0x0e823863 // zip1 v3.2s, v3.2s, v2.2s + WORD $0x6e042084 // ext v4.16b, v4.16b, v4.16b, #4 + WORD $0x53087d4a // lsr w10, w10, #8 + WORD $0x2ea14463 // ushl v3.2s, v3.2s, v1.2s + WORD $0x0ea31ca3 // orr v3.8b, v5.8b, v3.8b + WORD $0x6e036082 // ext v2.16b, v4.16b, v3.16b, #12 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x6f0777e2 // bic v2.4s, #255, lsl #24 + WORD $0x3d800902 // str q2, [x8, #32] + WORD $0xb940540a // ldr w10, [x0, #84] + WORD $0xfd402c02 // ldr d2, [x0, #88] + WORD $0x91018000 // add x0, x0, #96 + WORD $0x1e270143 // fmov s3, w10 + WORD $0x1e270144 // fmov s4, w10 + WORD $0x2ea04445 // ushl v5.2s, v2.2s, v0.2s + WORD $0x0e0c3c4a // mov w10, v2.s[1] + WORD $0x0e823863 // zip1 v3.2s, v3.2s, v2.2s + WORD $0x6e042084 // ext v4.16b, v4.16b, v4.16b, #4 + WORD $0x53087d4a // lsr w10, w10, #8 + WORD $0x2ea14463 // ushl v3.2s, v3.2s, v1.2s + WORD $0x0ea31ca3 // orr v3.8b, v5.8b, v3.8b + WORD $0x6e036082 // ext v2.16b, v4.16b, v3.16b, #12 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x6f0777e2 // bic v2.4s, #255, lsl #24 + WORD $0x3d800d02 // str q2, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_114 + JMP LBB0_156 + +LBB0_115: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.116: + // WORD $0x90000009 // adrp x9, .LCPI0_186 + // WORD $0x9000000a // adrp x10, .LCPI0_187 + WORD $0x4f0005e0 // movi v0.4s, #15 + WORD $0x91010348 // add x8, x26, #64 + VMOVD LCPI0_186, V1 + WORD $0xaa1303e9 // mov x9, x19 + VMOVQ LCPI0_187L, LCPI0_187H, V2 + +LBB0_117: + WORD $0xb940000a // ldr w10, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x0e040d43 // dup v3.2s, w10 + WORD $0x1e270144 // fmov s4, w10 + WORD $0x530c7d4a // lsr w10, w10, #12 + WORD $0x6e042084 // ext v4.16b, v4.16b, v4.16b, #4 + WORD $0x2ea14463 // ushl v3.2s, v3.2s, v1.2s + WORD $0x6e036083 // ext v3.16b, v4.16b, v3.16b, #12 + WORD $0x4e1c1d43 // mov v3.s[3], w10 + WORD $0xaa0003ea // mov x10, x0 + WORD $0x4e201c63 // and v3.16b, v3.16b, v0.16b + WORD $0x3c9c0103 // stur q3, [x8, #-64] + WORD $0x4ddfc943 // ld1r { v3.4s }, [x10], #4 + WORD $0x6ea24463 // ushl v3.4s, v3.4s, v2.4s + WORD $0x4e201c63 // and v3.16b, v3.16b, v0.16b + WORD $0x3c9d0103 // stur q3, [x8, #-48] + WORD $0xb940014b // ldr w11, [x10] + WORD $0x0e040d63 // dup v3.2s, w11 + WORD $0x1e270164 // fmov s4, w11 + WORD $0x530c7d6b // lsr w11, w11, #12 + WORD $0x6e042084 // ext v4.16b, v4.16b, v4.16b, #4 + WORD $0x2ea14463 // ushl v3.2s, v3.2s, v1.2s + WORD $0x6e036083 // ext v3.16b, v4.16b, v3.16b, #12 + WORD $0x4e1c1d63 // mov v3.s[3], w11 + WORD $0x4e201c63 // and v3.16b, v3.16b, v0.16b + WORD $0x3c9e0103 // stur q3, [x8, #-32] + WORD $0x4d40c943 // ld1r { v3.4s }, [x10] + WORD $0x6ea24463 // ushl v3.4s, v3.4s, v2.4s + WORD $0x4e201c63 // and v3.16b, v3.16b, v0.16b + WORD $0x3c9f0103 // stur q3, [x8, #-16] + WORD $0xb940080a // ldr w10, [x0, #8] + WORD $0x0e040d43 // dup v3.2s, w10 + WORD $0x1e270144 // fmov s4, w10 + WORD $0x530c7d4a // lsr w10, w10, #12 + WORD $0x6e042084 // ext v4.16b, v4.16b, v4.16b, #4 + WORD $0x2ea14463 // ushl v3.2s, v3.2s, v1.2s + WORD $0x6e036083 // ext v3.16b, v4.16b, v3.16b, #12 + WORD $0x4e1c1d43 // mov v3.s[3], w10 + WORD $0x9100200a // add x10, x0, #8 + WORD $0x4e201c63 // and v3.16b, v3.16b, v0.16b + WORD $0x3d800103 // str q3, [x8] + WORD $0x4d40c943 // ld1r { v3.4s }, [x10] + WORD $0x6ea24463 // ushl v3.4s, v3.4s, v2.4s + WORD $0x4e201c63 // and v3.16b, v3.16b, v0.16b + WORD $0x3d800503 // str q3, [x8, #16] + WORD $0xb9400c0a // ldr w10, [x0, #12] + WORD $0x0e040d43 // dup v3.2s, w10 + WORD $0x1e270144 // fmov s4, w10 + WORD $0x530c7d4a // lsr w10, w10, #12 + WORD $0x6e042084 // ext v4.16b, v4.16b, v4.16b, #4 + WORD $0x2ea14463 // ushl v3.2s, v3.2s, v1.2s + WORD $0x6e036083 // ext v3.16b, v4.16b, v3.16b, #12 + WORD $0x4e1c1d43 // mov v3.s[3], w10 + WORD $0x9100300a // add x10, x0, #12 + WORD $0x91004000 // add x0, x0, #16 + WORD $0x4e201c63 // and v3.16b, v3.16b, v0.16b + WORD $0x3d800903 // str q3, [x8, #32] + WORD $0x4d40c943 // ld1r { v3.4s }, [x10] + WORD $0x6ea24463 // ushl v3.4s, v3.4s, v2.4s + WORD $0x4e201c63 // and v3.16b, v3.16b, v0.16b + WORD $0x3d800d03 // str q3, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_117 + JMP LBB0_156 + +LBB0_118: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.119: + WORD $0x4f00d5e0 // movi v0.4s, #15, msl #16 + WORD $0x91010348 // add x8, x26, #64 + WORD $0xaa1303e9 // mov x9, x19 + +LBB0_120: + WORD $0x29402c0a // ldp w10, w11, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x138a516c // extr w12, w11, w10, #20 + WORD $0x1e270141 // fmov s1, w10 + WORD $0x53087d6a // lsr w10, w11, #8 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0xb940080c // ldr w12, [x0, #8] + WORD $0x4e141d41 // mov v1.s[2], w10 + WORD $0x138b718a // extr w10, w12, w11, #28 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3c9c0101 // stur q1, [x8, #-64] + WORD $0x29412c0a // ldp w10, w11, [x0, #8] + WORD $0x138a416a // extr w10, w11, w10, #16 + WORD $0x53047d6c // lsr w12, w11, #4 + WORD $0x1e270141 // fmov s1, w10 + WORD $0xb940100a // ldr w10, [x0, #16] + WORD $0x138b614b // extr w11, w10, w11, #24 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0x530c7d4a // lsr w10, w10, #12 + WORD $0x4e141d61 // mov v1.s[2], w11 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3c9d0101 // stur q1, [x8, #-48] + WORD $0x2942ac0a // ldp w10, w11, [x0, #20] + WORD $0x138a516c // extr w12, w11, w10, #20 + WORD $0x1e270141 // fmov s1, w10 + WORD $0x53087d6a // lsr w10, w11, #8 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0xb9401c0c // ldr w12, [x0, #28] + WORD $0x4e141d41 // mov v1.s[2], w10 + WORD $0x138b718a // extr w10, w12, w11, #28 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3c9e0101 // stur q1, [x8, #-32] + WORD $0x2943ac0a // ldp w10, w11, [x0, #28] + WORD $0x138a416a // extr w10, w11, w10, #16 + WORD $0x53047d6c // lsr w12, w11, #4 + WORD $0x1e270141 // fmov s1, w10 + WORD $0xb940240a // ldr w10, [x0, #36] + WORD $0x138b614b // extr w11, w10, w11, #24 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0x530c7d4a // lsr w10, w10, #12 + WORD $0x4e141d61 // mov v1.s[2], w11 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3c9f0101 // stur q1, [x8, #-16] + WORD $0x29452c0a // ldp w10, w11, [x0, #40] + WORD $0x138a516c // extr w12, w11, w10, #20 + WORD $0x1e270141 // fmov s1, w10 + WORD $0x53087d6a // lsr w10, w11, #8 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0xb940300c // ldr w12, [x0, #48] + WORD $0x4e141d41 // mov v1.s[2], w10 + WORD $0x138b718a // extr w10, w12, w11, #28 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3d800101 // str q1, [x8] + WORD $0x29462c0a // ldp w10, w11, [x0, #48] + WORD $0x138a416a // extr w10, w11, w10, #16 + WORD $0x53047d6c // lsr w12, w11, #4 + WORD $0x1e270141 // fmov s1, w10 + WORD $0xb940380a // ldr w10, [x0, #56] + WORD $0x138b614b // extr w11, w10, w11, #24 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0x530c7d4a // lsr w10, w10, #12 + WORD $0x4e141d61 // mov v1.s[2], w11 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3d800501 // str q1, [x8, #16] + WORD $0x2947ac0a // ldp w10, w11, [x0, #60] + WORD $0x138a516c // extr w12, w11, w10, #20 + WORD $0x1e270141 // fmov s1, w10 + WORD $0x53087d6a // lsr w10, w11, #8 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0xb940440c // ldr w12, [x0, #68] + WORD $0x4e141d41 // mov v1.s[2], w10 + WORD $0x138b718a // extr w10, w12, w11, #28 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3d800901 // str q1, [x8, #32] + WORD $0x2948ac0a // ldp w10, w11, [x0, #68] + WORD $0x138a416a // extr w10, w11, w10, #16 + WORD $0x53047d6c // lsr w12, w11, #4 + WORD $0x1e270141 // fmov s1, w10 + WORD $0xb9404c0a // ldr w10, [x0, #76] + WORD $0x91014000 // add x0, x0, #80 + WORD $0x138b614b // extr w11, w10, w11, #24 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0x530c7d4a // lsr w10, w10, #12 + WORD $0x4e141d61 // mov v1.s[2], w11 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3d800d01 // str q1, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_120 + JMP LBB0_156 + +LBB0_121: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.122: + // WORD $0x90000009 // adrp x9, .LCPI0_145 + WORD $0x91010348 // add x8, x26, #64 + WORD $0x4f00c5e0 // movi v0.4s, #15, msl #8 + VMOVD LCPI0_145, V1 + WORD $0xaa1303e9 // mov x9, x19 + +LBB0_123: + WORD $0x29402c0a // ldp w10, w11, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x530c7d4c // lsr w12, w10, #12 + WORD $0x1e270142 // fmov s2, w10 + WORD $0x138a616a // extr w10, w11, w10, #24 + WORD $0x4e0c1d82 // mov v2.s[1], w12 + WORD $0x4e141d42 // mov v2.s[2], w10 + WORD $0x53047d6a // lsr w10, w11, #4 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3c9c0102 // stur q2, [x8, #-64] + WORD $0x2940ac0a // ldp w10, w11, [x0, #4] + WORD $0x53107d4c // lsr w12, w10, #16 + WORD $0x0e040d62 // dup v2.2s, w11 + WORD $0x138a716a // extr w10, w11, w10, #28 + WORD $0x1e270183 // fmov s3, w12 + WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s + WORD $0x4e0c1d43 // mov v3.s[1], w10 + WORD $0x6e180443 // mov v3.d[1], v2.d[0] + WORD $0x4e201c62 // and v2.16b, v3.16b, v0.16b + WORD $0x3c9d0102 // stur q2, [x8, #-48] + WORD $0x2941ac0a // ldp w10, w11, [x0, #12] + WORD $0x530c7d4c // lsr w12, w10, #12 + WORD $0x1e270142 // fmov s2, w10 + WORD $0x138a616a // extr w10, w11, w10, #24 + WORD $0x4e0c1d82 // mov v2.s[1], w12 + WORD $0x4e141d42 // mov v2.s[2], w10 + WORD $0x53047d6a // lsr w10, w11, #4 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3c9e0102 // stur q2, [x8, #-32] + WORD $0x29422c0a // ldp w10, w11, [x0, #16] + WORD $0x53107d4c // lsr w12, w10, #16 + WORD $0x0e040d62 // dup v2.2s, w11 + WORD $0x138a716a // extr w10, w11, w10, #28 + WORD $0x1e270183 // fmov s3, w12 + WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s + WORD $0x4e0c1d43 // mov v3.s[1], w10 + WORD $0x6e180443 // mov v3.d[1], v2.d[0] + WORD $0x4e201c62 // and v2.16b, v3.16b, v0.16b + WORD $0x3c9f0102 // stur q2, [x8, #-16] + WORD $0x29432c0a // ldp w10, w11, [x0, #24] + WORD $0x530c7d4c // lsr w12, w10, #12 + WORD $0x1e270142 // fmov s2, w10 + WORD $0x138a616a // extr w10, w11, w10, #24 + WORD $0x4e0c1d82 // mov v2.s[1], w12 + WORD $0x4e141d42 // mov v2.s[2], w10 + WORD $0x53047d6a // lsr w10, w11, #4 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3d800102 // str q2, [x8] + WORD $0x2943ac0a // ldp w10, w11, [x0, #28] + WORD $0x53107d4c // lsr w12, w10, #16 + WORD $0x0e040d62 // dup v2.2s, w11 + WORD $0x138a716a // extr w10, w11, w10, #28 + WORD $0x1e270183 // fmov s3, w12 + WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s + WORD $0x4e0c1d43 // mov v3.s[1], w10 + WORD $0x6e180443 // mov v3.d[1], v2.d[0] + WORD $0x4e201c62 // and v2.16b, v3.16b, v0.16b + WORD $0x3d800502 // str q2, [x8, #16] + WORD $0x2944ac0a // ldp w10, w11, [x0, #36] + WORD $0x530c7d4c // lsr w12, w10, #12 + WORD $0x1e270142 // fmov s2, w10 + WORD $0x138a616a // extr w10, w11, w10, #24 + WORD $0x4e0c1d82 // mov v2.s[1], w12 + WORD $0x4e141d42 // mov v2.s[2], w10 + WORD $0x53047d6a // lsr w10, w11, #4 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3d800902 // str q2, [x8, #32] + WORD $0x29452c0a // ldp w10, w11, [x0, #40] + WORD $0x9100c000 // add x0, x0, #48 + WORD $0x53107d4c // lsr w12, w10, #16 + WORD $0x0e040d62 // dup v2.2s, w11 + WORD $0x138a716a // extr w10, w11, w10, #28 + WORD $0x1e270183 // fmov s3, w12 + WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s + WORD $0x4e0c1d43 // mov v3.s[1], w10 + WORD $0x6e180443 // mov v3.d[1], v2.d[0] + WORD $0x4e201c62 // and v2.16b, v3.16b, v0.16b + WORD $0x3d800d02 // str q2, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_123 + JMP LBB0_156 + +LBB0_124: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.125: + // WORD $0x90000008 // adrp x8, .LCPI0_48 + // WORD $0x90000009 // adrp x9, .LCPI0_49 + // WORD $0x9000000a // adrp x10, .LCPI0_50 + // WORD $0x9000000b // adrp x11, .LCPI0_51 + VMOVD LCPI0_48, V0 + WORD $0x91010348 // add x8, x26, #64 + VMOVD LCPI0_49, V1 + WORD $0xaa1303e9 // mov x9, x19 + VMOVD LCPI0_50, V2 + VMOVD LCPI0_51, V3 + +LBB0_126: + WORD $0xb940000a // ldr w10, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0xfc404004 // ldur d4, [x0, #4] + WORD $0xb9400c0b // ldr w11, [x0, #12] + WORD $0x1e270145 // fmov s5, w10 + WORD $0x1e270146 // fmov s6, w10 + WORD $0x2ea04487 // ushl v7.2s, v4.2s, v0.2s + WORD $0x0e0c3c8a // mov w10, v4.s[1] + WORD $0x0e8438a5 // zip1 v5.2s, v5.2s, v4.2s + WORD $0x6e0620c6 // ext v6.16b, v6.16b, v6.16b, #4 + WORD $0x138a516a // extr w10, w11, w10, #20 + WORD $0x2ea144a5 // ushl v5.2s, v5.2s, v1.2s + WORD $0x0ea51ce5 // orr v5.8b, v7.8b, v5.8b + WORD $0x6e0560c4 // ext v4.16b, v6.16b, v5.16b, #12 + WORD $0x4e1c1d44 // mov v4.s[3], w10 + WORD $0x6f077604 // bic v4.4s, #240, lsl #24 + WORD $0x3c9c0104 // stur q4, [x8, #-64] + WORD $0xfd400804 // ldr d4, [x0, #16] + WORD $0xbd400c05 // ldr s5, [x0, #12] + WORD $0xb940180b // ldr w11, [x0, #24] + WORD $0x2ea24486 // ushl v6.2s, v4.2s, v2.2s + WORD $0x0e0c3c8a // mov w10, v4.s[1] + WORD $0x0e8438a5 // zip1 v5.2s, v5.2s, v4.2s + WORD $0x138a216a // extr w10, w11, w10, #8 + WORD $0x2ea344a5 // ushl v5.2s, v5.2s, v3.2s + WORD $0x0ea51cc4 // orr v4.8b, v6.8b, v5.8b + WORD $0x4e141d44 // mov v4.s[2], w10 + WORD $0x53047d6a // lsr w10, w11, #4 + WORD $0x4e1c1d44 // mov v4.s[3], w10 + WORD $0x6f077604 // bic v4.4s, #240, lsl #24 + WORD $0x3c9d0104 // stur q4, [x8, #-48] + WORD $0xb9401c0a // ldr w10, [x0, #28] + WORD $0xfd401004 // ldr d4, [x0, #32] + WORD $0xb940280b // ldr w11, [x0, #40] + WORD $0x1e270145 // fmov s5, w10 + WORD $0x1e270146 // fmov s6, w10 + WORD $0x2ea04487 // ushl v7.2s, v4.2s, v0.2s + WORD $0x0e0c3c8a // mov w10, v4.s[1] + WORD $0x0e8438a5 // zip1 v5.2s, v5.2s, v4.2s + WORD $0x6e0620c6 // ext v6.16b, v6.16b, v6.16b, #4 + WORD $0x138a516a // extr w10, w11, w10, #20 + WORD $0x2ea144a5 // ushl v5.2s, v5.2s, v1.2s + WORD $0x0ea51ce5 // orr v5.8b, v7.8b, v5.8b + WORD $0x6e0560c4 // ext v4.16b, v6.16b, v5.16b, #12 + WORD $0x4e1c1d44 // mov v4.s[3], w10 + WORD $0x6f077604 // bic v4.4s, #240, lsl #24 + WORD $0x3c9e0104 // stur q4, [x8, #-32] + WORD $0xfc42c004 // ldur d4, [x0, #44] + WORD $0xbd402805 // ldr s5, [x0, #40] + WORD $0xb940340b // ldr w11, [x0, #52] + WORD $0x2ea24486 // ushl v6.2s, v4.2s, v2.2s + WORD $0x0e0c3c8a // mov w10, v4.s[1] + WORD $0x0e8438a5 // zip1 v5.2s, v5.2s, v4.2s + WORD $0x138a216a // extr w10, w11, w10, #8 + WORD $0x2ea344a5 // ushl v5.2s, v5.2s, v3.2s + WORD $0x0ea51cc4 // orr v4.8b, v6.8b, v5.8b + WORD $0x4e141d44 // mov v4.s[2], w10 + WORD $0x53047d6a // lsr w10, w11, #4 + WORD $0x4e1c1d44 // mov v4.s[3], w10 + WORD $0x6f077604 // bic v4.4s, #240, lsl #24 + WORD $0x3c9f0104 // stur q4, [x8, #-16] + WORD $0xb940380a // ldr w10, [x0, #56] + WORD $0xfc43c004 // ldur d4, [x0, #60] + WORD $0xb940440b // ldr w11, [x0, #68] + WORD $0x1e270145 // fmov s5, w10 + WORD $0x1e270146 // fmov s6, w10 + WORD $0x2ea04487 // ushl v7.2s, v4.2s, v0.2s + WORD $0x0e0c3c8a // mov w10, v4.s[1] + WORD $0x0e8438a5 // zip1 v5.2s, v5.2s, v4.2s + WORD $0x6e0620c6 // ext v6.16b, v6.16b, v6.16b, #4 + WORD $0x138a516a // extr w10, w11, w10, #20 + WORD $0x2ea144a5 // ushl v5.2s, v5.2s, v1.2s + WORD $0x0ea51ce5 // orr v5.8b, v7.8b, v5.8b + WORD $0x6e0560c4 // ext v4.16b, v6.16b, v5.16b, #12 + WORD $0x4e1c1d44 // mov v4.s[3], w10 + WORD $0x6f077604 // bic v4.4s, #240, lsl #24 + WORD $0x3d800104 // str q4, [x8] + WORD $0xfd402404 // ldr d4, [x0, #72] + WORD $0xbd404405 // ldr s5, [x0, #68] + WORD $0xb940500b // ldr w11, [x0, #80] + WORD $0x2ea24486 // ushl v6.2s, v4.2s, v2.2s + WORD $0x0e0c3c8a // mov w10, v4.s[1] + WORD $0x0e8438a5 // zip1 v5.2s, v5.2s, v4.2s + WORD $0x138a216a // extr w10, w11, w10, #8 + WORD $0x2ea344a5 // ushl v5.2s, v5.2s, v3.2s + WORD $0x0ea51cc4 // orr v4.8b, v6.8b, v5.8b + WORD $0x4e141d44 // mov v4.s[2], w10 + WORD $0x53047d6a // lsr w10, w11, #4 + WORD $0x4e1c1d44 // mov v4.s[3], w10 + WORD $0x6f077604 // bic v4.4s, #240, lsl #24 + WORD $0x3d800504 // str q4, [x8, #16] + WORD $0xb940540a // ldr w10, [x0, #84] + WORD $0xfd402c04 // ldr d4, [x0, #88] + WORD $0xb940600b // ldr w11, [x0, #96] + WORD $0x1e270145 // fmov s5, w10 + WORD $0x1e270146 // fmov s6, w10 + WORD $0x2ea04487 // ushl v7.2s, v4.2s, v0.2s + WORD $0x0e0c3c8a // mov w10, v4.s[1] + WORD $0x0e8438a5 // zip1 v5.2s, v5.2s, v4.2s + WORD $0x6e0620c6 // ext v6.16b, v6.16b, v6.16b, #4 + WORD $0x138a516a // extr w10, w11, w10, #20 + WORD $0x2ea144a5 // ushl v5.2s, v5.2s, v1.2s + WORD $0x0ea51ce5 // orr v5.8b, v7.8b, v5.8b + WORD $0x6e0560c4 // ext v4.16b, v6.16b, v5.16b, #12 + WORD $0x4e1c1d44 // mov v4.s[3], w10 + WORD $0x6f077604 // bic v4.4s, #240, lsl #24 + WORD $0x3d800904 // str q4, [x8, #32] + WORD $0xfc464004 // ldur d4, [x0, #100] + WORD $0xbd406005 // ldr s5, [x0, #96] + WORD $0xb9406c0b // ldr w11, [x0, #108] + WORD $0x9101c000 // add x0, x0, #112 + WORD $0x2ea24486 // ushl v6.2s, v4.2s, v2.2s + WORD $0x0e0c3c8a // mov w10, v4.s[1] + WORD $0x0e8438a5 // zip1 v5.2s, v5.2s, v4.2s + WORD $0x138a216a // extr w10, w11, w10, #8 + WORD $0x2ea344a5 // ushl v5.2s, v5.2s, v3.2s + WORD $0x0ea51cc4 // orr v4.8b, v6.8b, v5.8b + WORD $0x4e141d44 // mov v4.s[2], w10 + WORD $0x53047d6a // lsr w10, w11, #4 + WORD $0x4e1c1d44 // mov v4.s[3], w10 + WORD $0x6f077604 // bic v4.4s, #240, lsl #24 + WORD $0x3d800d04 // str q4, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_126 + JMP LBB0_156 + +LBB0_127: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.128: + // WORD $0x90000008 // adrp x8, .LCPI0_196 + // WORD $0x90000009 // adrp x9, .LCPI0_197 + // WORD $0x9000000a // adrp x10, .LCPI0_198 + // WORD $0x9000000b // adrp x11, .LCPI0_199 + WORD $0x4f000462 // movi v2.4s, #3 + VMOVD LCPI0_196, V0 + WORD $0x91010348 // add x8, x26, #64 + VMOVQ LCPI0_197L, LCPI0_197H, V1 + WORD $0xaa1303e9 // mov x9, x19 + VMOVQ LCPI0_198L, LCPI0_198H, V3 + VMOVQ LCPI0_199L, LCPI0_199H, V4 + +LBB0_129: + WORD $0xb940000a // ldr w10, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x0e040d45 // dup v5.2s, w10 + WORD $0x1e270146 // fmov s6, w10 + WORD $0x53067d4a // lsr w10, w10, #6 + WORD $0x6e0620c6 // ext v6.16b, v6.16b, v6.16b, #4 + WORD $0x2ea044a5 // ushl v5.2s, v5.2s, v0.2s + WORD $0x6e0560c5 // ext v5.16b, v6.16b, v5.16b, #12 + WORD $0x4e1c1d45 // mov v5.s[3], w10 + WORD $0xaa0003ea // mov x10, x0 + WORD $0x4e221ca5 // and v5.16b, v5.16b, v2.16b + WORD $0x3c9c0105 // stur q5, [x8, #-64] + WORD $0x4ddfc945 // ld1r { v5.4s }, [x10], #4 + WORD $0x6ea144a5 // ushl v5.4s, v5.4s, v1.4s + WORD $0x4e221ca5 // and v5.16b, v5.16b, v2.16b + WORD $0x3c9d0105 // stur q5, [x8, #-48] + WORD $0x4d40c805 // ld1r { v5.4s }, [x0] + WORD $0x6ea344a5 // ushl v5.4s, v5.4s, v3.4s + WORD $0x4e221ca5 // and v5.16b, v5.16b, v2.16b + WORD $0x3c9e0105 // stur q5, [x8, #-32] + WORD $0xb840840b // ldr w11, [x0], #8 + WORD $0x4e040d65 // dup v5.4s, w11 + WORD $0x6ea444a5 // ushl v5.4s, v5.4s, v4.4s + WORD $0x4e221ca5 // and v5.16b, v5.16b, v2.16b + WORD $0x3c9f0105 // stur q5, [x8, #-16] + WORD $0xb940014b // ldr w11, [x10] + WORD $0x0e040d65 // dup v5.2s, w11 + WORD $0x1e270166 // fmov s6, w11 + WORD $0x53067d6b // lsr w11, w11, #6 + WORD $0x6e0620c6 // ext v6.16b, v6.16b, v6.16b, #4 + WORD $0x2ea044a5 // ushl v5.2s, v5.2s, v0.2s + WORD $0x6e0560c5 // ext v5.16b, v6.16b, v5.16b, #12 + WORD $0x4e1c1d65 // mov v5.s[3], w11 + WORD $0x4e221ca5 // and v5.16b, v5.16b, v2.16b + WORD $0x3d800105 // str q5, [x8] + WORD $0x4d40c945 // ld1r { v5.4s }, [x10] + WORD $0x6ea144a5 // ushl v5.4s, v5.4s, v1.4s + WORD $0x4e221ca5 // and v5.16b, v5.16b, v2.16b + WORD $0x3d800505 // str q5, [x8, #16] + WORD $0x4d40c945 // ld1r { v5.4s }, [x10] + WORD $0x6ea344a5 // ushl v5.4s, v5.4s, v3.4s + WORD $0x4e221ca5 // and v5.16b, v5.16b, v2.16b + WORD $0x3d800905 // str q5, [x8, #32] + WORD $0x4d40c945 // ld1r { v5.4s }, [x10] + WORD $0x6ea444a5 // ushl v5.4s, v5.4s, v4.4s + WORD $0x4e221ca5 // and v5.16b, v5.16b, v2.16b + WORD $0x3d800d05 // str q5, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_129 + JMP LBB0_156 + +LBB0_130: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.131: + WORD $0x4f00d460 // movi v0.4s, #3, msl #16 + WORD $0x91010348 // add x8, x26, #64 + WORD $0xaa1303e9 // mov x9, x19 + +LBB0_132: + WORD $0x29402c0a // ldp w10, w11, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x138a496c // extr w12, w11, w10, #18 + WORD $0x1e270141 // fmov s1, w10 + WORD $0x53047d6a // lsr w10, w11, #4 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0xb940080c // ldr w12, [x0, #8] + WORD $0x4e141d41 // mov v1.s[2], w10 + WORD $0x138b598a // extr w10, w12, w11, #22 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3c9c0101 // stur q1, [x8, #-64] + WORD $0x29412c0a // ldp w10, w11, [x0, #8] + WORD $0x53087d4c // lsr w12, w10, #8 + WORD $0x138a696a // extr w10, w11, w10, #26 + WORD $0x1e270181 // fmov s1, w12 + WORD $0xb940100c // ldr w12, [x0, #16] + WORD $0x4e0c1d41 // mov v1.s[1], w10 + WORD $0x530c7d6a // lsr w10, w11, #12 + WORD $0x4e141d41 // mov v1.s[2], w10 + WORD $0x138b798a // extr w10, w12, w11, #30 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3c9d0101 // stur q1, [x8, #-48] + WORD $0x29422c0a // ldp w10, w11, [x0, #16] + WORD $0x138a416a // extr w10, w11, w10, #16 + WORD $0x53027d6c // lsr w12, w11, #2 + WORD $0x1e270141 // fmov s1, w10 + WORD $0xb940180a // ldr w10, [x0, #24] + WORD $0x138b514b // extr w11, w10, w11, #20 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0x53067d4a // lsr w10, w10, #6 + WORD $0x4e141d61 // mov v1.s[2], w11 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3c9e0101 // stur q1, [x8, #-32] + WORD $0x29432c0a // ldp w10, w11, [x0, #24] + WORD $0x138a616a // extr w10, w11, w10, #24 + WORD $0x530a7d6c // lsr w12, w11, #10 + WORD $0x1e270141 // fmov s1, w10 + WORD $0xb940200a // ldr w10, [x0, #32] + WORD $0x138b714b // extr w11, w10, w11, #28 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0x530e7d4a // lsr w10, w10, #14 + WORD $0x4e141d61 // mov v1.s[2], w11 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3c9f0101 // stur q1, [x8, #-16] + WORD $0x2944ac0a // ldp w10, w11, [x0, #36] + WORD $0x138a496c // extr w12, w11, w10, #18 + WORD $0x1e270141 // fmov s1, w10 + WORD $0x53047d6a // lsr w10, w11, #4 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0xb9402c0c // ldr w12, [x0, #44] + WORD $0x4e141d41 // mov v1.s[2], w10 + WORD $0x138b598a // extr w10, w12, w11, #22 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3d800101 // str q1, [x8] + WORD $0x2945ac0a // ldp w10, w11, [x0, #44] + WORD $0x53087d4c // lsr w12, w10, #8 + WORD $0x138a696a // extr w10, w11, w10, #26 + WORD $0x1e270181 // fmov s1, w12 + WORD $0xb940340c // ldr w12, [x0, #52] + WORD $0x4e0c1d41 // mov v1.s[1], w10 + WORD $0x530c7d6a // lsr w10, w11, #12 + WORD $0x4e141d41 // mov v1.s[2], w10 + WORD $0x138b798a // extr w10, w12, w11, #30 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3d800501 // str q1, [x8, #16] + WORD $0x2946ac0a // ldp w10, w11, [x0, #52] + WORD $0x138a416a // extr w10, w11, w10, #16 + WORD $0x53027d6c // lsr w12, w11, #2 + WORD $0x1e270141 // fmov s1, w10 + WORD $0xb9403c0a // ldr w10, [x0, #60] + WORD $0x138b514b // extr w11, w10, w11, #20 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0x53067d4a // lsr w10, w10, #6 + WORD $0x4e141d61 // mov v1.s[2], w11 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3d800901 // str q1, [x8, #32] + WORD $0x2947ac0a // ldp w10, w11, [x0, #60] + WORD $0x138a616a // extr w10, w11, w10, #24 + WORD $0x530a7d6c // lsr w12, w11, #10 + WORD $0x1e270141 // fmov s1, w10 + WORD $0xb940440a // ldr w10, [x0, #68] + WORD $0x91012000 // add x0, x0, #72 + WORD $0x138b714b // extr w11, w10, w11, #28 + WORD $0x4e0c1d81 // mov v1.s[1], w12 + WORD $0x530e7d4a // lsr w10, w10, #14 + WORD $0x4e141d61 // mov v1.s[2], w11 + WORD $0x4e1c1d41 // mov v1.s[3], w10 + WORD $0x4e201c21 // and v1.16b, v1.16b, v0.16b + WORD $0x3d800d01 // str q1, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_132 + JMP LBB0_156 + +LBB0_133: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.134: + // WORD $0x90000008 // adrp x8, .LCPI0_153 + // WORD $0x90000009 // adrp x9, .LCPI0_154 + // WORD $0x9000000a // adrp x10, .LCPI0_155 + // WORD $0x9000000b // adrp x11, .LCPI0_156 + WORD $0x4f00c462 // movi v2.4s, #3, msl #8 + VMOVD LCPI0_153, V0 + WORD $0x91010348 // add x8, x26, #64 + VMOVD LCPI0_154, V1 + WORD $0xaa1303e9 // mov x9, x19 + VMOVD LCPI0_155, V3 + VMOVD LCPI0_156, V4 + +LBB0_135: + WORD $0x29402c0a // ldp w10, w11, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x0e040d45 // dup v5.2s, w10 + WORD $0x1e270146 // fmov s6, w10 + WORD $0x138a796a // extr w10, w11, w10, #30 + WORD $0x6e0620c6 // ext v6.16b, v6.16b, v6.16b, #4 + WORD $0x2ea044a5 // ushl v5.2s, v5.2s, v0.2s + WORD $0x6e0560c5 // ext v5.16b, v6.16b, v5.16b, #12 + WORD $0x4e1c1d45 // mov v5.s[3], w10 + WORD $0x4e221ca5 // and v5.16b, v5.16b, v2.16b + WORD $0x3c9c0105 // stur q5, [x8, #-64] + WORD $0x2940ac0a // ldp w10, w11, [x0, #4] + WORD $0x0e040d45 // dup v5.2s, w10 + WORD $0x138a716a // extr w10, w11, w10, #28 + WORD $0x2ea144a5 // ushl v5.2s, v5.2s, v1.2s + WORD $0x4e141d45 // mov v5.s[2], w10 + WORD $0x53067d6a // lsr w10, w11, #6 + WORD $0x4e1c1d45 // mov v5.s[3], w10 + WORD $0x4e221ca5 // and v5.16b, v5.16b, v2.16b + WORD $0x3c9d0105 // stur q5, [x8, #-48] + WORD $0x29412c0a // ldp w10, w11, [x0, #8] + WORD $0x53107d4c // lsr w12, w10, #16 + WORD $0x0e040d65 // dup v5.2s, w11 + WORD $0x138a696a // extr w10, w11, w10, #26 + WORD $0x1e270186 // fmov s6, w12 + WORD $0x2ea344a5 // ushl v5.2s, v5.2s, v3.2s + WORD $0x4e0c1d46 // mov v6.s[1], w10 + WORD $0x6e1804a6 // mov v6.d[1], v5.d[0] + WORD $0x4e221cc5 // and v5.16b, v6.16b, v2.16b + WORD $0x3c9e0105 // stur q5, [x8, #-32] + WORD $0x2941ac0a // ldp w10, w11, [x0, #12] + WORD $0x138a616a // extr w10, w11, w10, #24 + WORD $0x0e040d65 // dup v5.2s, w11 + WORD $0x1e270146 // fmov s6, w10 + WORD $0x53167d6a // lsr w10, w11, #22 + WORD $0x2ea444a5 // ushl v5.2s, v5.2s, v4.2s + WORD $0x6e0620c6 // ext v6.16b, v6.16b, v6.16b, #4 + WORD $0x6e0560c5 // ext v5.16b, v6.16b, v5.16b, #12 + WORD $0x4e1c1d45 // mov v5.s[3], w10 + WORD $0x4e221ca5 // and v5.16b, v5.16b, v2.16b + WORD $0x3c9f0105 // stur q5, [x8, #-16] + WORD $0x2942ac0a // ldp w10, w11, [x0, #20] + WORD $0x0e040d45 // dup v5.2s, w10 + WORD $0x1e270146 // fmov s6, w10 + WORD $0x138a796a // extr w10, w11, w10, #30 + WORD $0x6e0620c6 // ext v6.16b, v6.16b, v6.16b, #4 + WORD $0x2ea044a5 // ushl v5.2s, v5.2s, v0.2s + WORD $0x6e0560c5 // ext v5.16b, v6.16b, v5.16b, #12 + WORD $0x4e1c1d45 // mov v5.s[3], w10 + WORD $0x4e221ca5 // and v5.16b, v5.16b, v2.16b + WORD $0x3d800105 // str q5, [x8] + WORD $0x29432c0a // ldp w10, w11, [x0, #24] + WORD $0x0e040d45 // dup v5.2s, w10 + WORD $0x138a716a // extr w10, w11, w10, #28 + WORD $0x2ea144a5 // ushl v5.2s, v5.2s, v1.2s + WORD $0x4e141d45 // mov v5.s[2], w10 + WORD $0x53067d6a // lsr w10, w11, #6 + WORD $0x4e1c1d45 // mov v5.s[3], w10 + WORD $0x4e221ca5 // and v5.16b, v5.16b, v2.16b + WORD $0x3d800505 // str q5, [x8, #16] + WORD $0x2943ac0a // ldp w10, w11, [x0, #28] + WORD $0x53107d4c // lsr w12, w10, #16 + WORD $0x0e040d65 // dup v5.2s, w11 + WORD $0x138a696a // extr w10, w11, w10, #26 + WORD $0x1e270186 // fmov s6, w12 + WORD $0x2ea344a5 // ushl v5.2s, v5.2s, v3.2s + WORD $0x4e0c1d46 // mov v6.s[1], w10 + WORD $0x6e1804a6 // mov v6.d[1], v5.d[0] + WORD $0x4e221cc5 // and v5.16b, v6.16b, v2.16b + WORD $0x3d800905 // str q5, [x8, #32] + WORD $0x29442c0a // ldp w10, w11, [x0, #32] + WORD $0x9100a000 // add x0, x0, #40 + WORD $0x138a616a // extr w10, w11, w10, #24 + WORD $0x0e040d65 // dup v5.2s, w11 + WORD $0x1e270146 // fmov s6, w10 + WORD $0x53167d6a // lsr w10, w11, #22 + WORD $0x2ea444a5 // ushl v5.2s, v5.2s, v4.2s + WORD $0x6e0620c6 // ext v6.16b, v6.16b, v6.16b, #4 + WORD $0x6e0560c5 // ext v5.16b, v6.16b, v5.16b, #12 + WORD $0x4e1c1d45 // mov v5.s[3], w10 + WORD $0x4e221ca5 // and v5.16b, v5.16b, v2.16b + WORD $0x3d800d05 // str q5, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_135 + JMP LBB0_156 + +LBB0_136: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.137: + // WORD $0x90000008 // adrp x8, .LCPI0_68 + // WORD $0x90000009 // adrp x9, .LCPI0_69 + // WORD $0x9000000a // adrp x10, .LCPI0_70 + VMOVD LCPI0_68, V0 + // WORD $0x90000008 // adrp x8, .LCPI0_71 + VMOVD LCPI0_69, V1 + // WORD $0x90000009 // adrp x9, .LCPI0_72 + VMOVD LCPI0_70, V2 + // WORD $0x9000000a // adrp x10, .LCPI0_73 + VMOVD LCPI0_71, V3 + // WORD $0x90000008 // adrp x8, .LCPI0_74 + VMOVD LCPI0_72, V4 + // WORD $0x90000009 // adrp x9, .LCPI0_75 + VMOVD LCPI0_73, V5 + VMOVD LCPI0_74, V6 + WORD $0x91010348 // add x8, x26, #64 + VMOVD LCPI0_75, V7 + WORD $0xaa1303e9 // mov x9, x19 + +LBB0_138: + WORD $0xb940000a // ldr w10, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0xfc404010 // ldur d16, [x0, #4] + WORD $0xb9400c0b // ldr w11, [x0, #12] + WORD $0x1e270151 // fmov s17, w10 + WORD $0x1e270152 // fmov s18, w10 + WORD $0x2ea04613 // ushl v19.2s, v16.2s, v0.2s + WORD $0x0e0c3e0a // mov w10, v16.s[1] + WORD $0x0e903a31 // zip1 v17.2s, v17.2s, v16.2s + WORD $0x6e122252 // ext v18.16b, v18.16b, v18.16b, #4 + WORD $0x138a396a // extr w10, w11, w10, #14 + WORD $0x2ea14631 // ushl v17.2s, v17.2s, v1.2s + WORD $0x0eb11e71 // orr v17.8b, v19.8b, v17.8b + WORD $0x6e116250 // ext v16.16b, v18.16b, v17.16b, #12 + WORD $0x4e1c1d50 // mov v16.s[3], w10 + WORD $0x6f077790 // bic v16.4s, #252, lsl #24 + WORD $0x3c9c0110 // stur q16, [x8, #-64] + WORD $0x2941a80b // ldp w11, w10, [x0, #12] + WORD $0xfc414010 // ldur d16, [x0, #20] + WORD $0x1e270151 // fmov s17, w10 + WORD $0x138b214b // extr w11, w10, w11, #8 + WORD $0x53027d4a // lsr w10, w10, #2 + WORD $0x0e903a31 // zip1 v17.2s, v17.2s, v16.2s + WORD $0x2ea24610 // ushl v16.2s, v16.2s, v2.2s + WORD $0x1e270172 // fmov s18, w11 + WORD $0x2ea34631 // ushl v17.2s, v17.2s, v3.2s + WORD $0x4e0c1d52 // mov v18.s[1], w10 + WORD $0x0eb11e10 // orr v16.8b, v16.8b, v17.8b + WORD $0x6e180612 // mov v18.d[1], v16.d[0] + WORD $0x6f077792 // bic v18.4s, #252, lsl #24 + WORD $0x3c9d0112 // stur q18, [x8, #-48] + WORD $0xfc41c010 // ldur d16, [x0, #28] + WORD $0xbd401811 // ldr s17, [x0, #24] + WORD $0xb940240c // ldr w12, [x0, #36] + WORD $0x2ea44612 // ushl v18.2s, v16.2s, v4.2s + WORD $0x0e0c3e0a // mov w10, v16.s[1] + WORD $0x0e903a31 // zip1 v17.2s, v17.2s, v16.2s + WORD $0x53047d4b // lsr w11, w10, #4 + WORD $0x138a798a // extr w10, w12, w10, #30 + WORD $0x2ea54631 // ushl v17.2s, v17.2s, v5.2s + WORD $0x0eb11e50 // orr v16.8b, v18.8b, v17.8b + WORD $0x4e141d70 // mov v16.s[2], w11 + WORD $0x4e1c1d50 // mov v16.s[3], w10 + WORD $0x6f077790 // bic v16.4s, #252, lsl #24 + WORD $0x3c9e0110 // stur q16, [x8, #-32] + WORD $0xfd401410 // ldr d16, [x0, #40] + WORD $0xbd402411 // ldr s17, [x0, #36] + WORD $0xb940300b // ldr w11, [x0, #48] + WORD $0x2ea64612 // ushl v18.2s, v16.2s, v6.2s + WORD $0x0e0c3e0a // mov w10, v16.s[1] + WORD $0x0e903a31 // zip1 v17.2s, v17.2s, v16.2s + WORD $0x138a316a // extr w10, w11, w10, #12 + WORD $0x2ea74631 // ushl v17.2s, v17.2s, v7.2s + WORD $0x0eb11e50 // orr v16.8b, v18.8b, v17.8b + WORD $0x4e141d50 // mov v16.s[2], w10 + WORD $0x53067d6a // lsr w10, w11, #6 + WORD $0x4e1c1d50 // mov v16.s[3], w10 + WORD $0x6f077790 // bic v16.4s, #252, lsl #24 + WORD $0x3c9f0110 // stur q16, [x8, #-16] + WORD $0xb940340a // ldr w10, [x0, #52] + WORD $0xfd401c10 // ldr d16, [x0, #56] + WORD $0xb940400b // ldr w11, [x0, #64] + WORD $0x1e270151 // fmov s17, w10 + WORD $0x1e270152 // fmov s18, w10 + WORD $0x2ea04613 // ushl v19.2s, v16.2s, v0.2s + WORD $0x0e0c3e0a // mov w10, v16.s[1] + WORD $0x0e903a31 // zip1 v17.2s, v17.2s, v16.2s + WORD $0x6e122252 // ext v18.16b, v18.16b, v18.16b, #4 + WORD $0x138a396a // extr w10, w11, w10, #14 + WORD $0x2ea14631 // ushl v17.2s, v17.2s, v1.2s + WORD $0x0eb11e71 // orr v17.8b, v19.8b, v17.8b + WORD $0x6e116250 // ext v16.16b, v18.16b, v17.16b, #12 + WORD $0x4e1c1d50 // mov v16.s[3], w10 + WORD $0x6f077790 // bic v16.4s, #252, lsl #24 + WORD $0x3d800110 // str q16, [x8] + WORD $0x2948280b // ldp w11, w10, [x0, #64] + WORD $0xfd402410 // ldr d16, [x0, #72] + WORD $0x1e270151 // fmov s17, w10 + WORD $0x138b214b // extr w11, w10, w11, #8 + WORD $0x53027d4a // lsr w10, w10, #2 + WORD $0x0e903a31 // zip1 v17.2s, v17.2s, v16.2s + WORD $0x2ea24610 // ushl v16.2s, v16.2s, v2.2s + WORD $0x1e270172 // fmov s18, w11 + WORD $0x2ea34631 // ushl v17.2s, v17.2s, v3.2s + WORD $0x4e0c1d52 // mov v18.s[1], w10 + WORD $0x0eb11e10 // orr v16.8b, v16.8b, v17.8b + WORD $0x6e180612 // mov v18.d[1], v16.d[0] + WORD $0x6f077792 // bic v18.4s, #252, lsl #24 + WORD $0x3d800512 // str q18, [x8, #16] + WORD $0xfd402810 // ldr d16, [x0, #80] + WORD $0xbd404c11 // ldr s17, [x0, #76] + WORD $0xb940580c // ldr w12, [x0, #88] + WORD $0x2ea44612 // ushl v18.2s, v16.2s, v4.2s + WORD $0x0e0c3e0a // mov w10, v16.s[1] + WORD $0x0e903a31 // zip1 v17.2s, v17.2s, v16.2s + WORD $0x53047d4b // lsr w11, w10, #4 + WORD $0x138a798a // extr w10, w12, w10, #30 + WORD $0x2ea54631 // ushl v17.2s, v17.2s, v5.2s + WORD $0x0eb11e50 // orr v16.8b, v18.8b, v17.8b + WORD $0x4e141d70 // mov v16.s[2], w11 + WORD $0x4e1c1d50 // mov v16.s[3], w10 + WORD $0x6f077790 // bic v16.4s, #252, lsl #24 + WORD $0x3d800910 // str q16, [x8, #32] + WORD $0xfc45c010 // ldur d16, [x0, #92] + WORD $0xbd405811 // ldr s17, [x0, #88] + WORD $0xb940640b // ldr w11, [x0, #100] + WORD $0x9101a000 // add x0, x0, #104 + WORD $0x2ea64612 // ushl v18.2s, v16.2s, v6.2s + WORD $0x0e0c3e0a // mov w10, v16.s[1] + WORD $0x0e903a31 // zip1 v17.2s, v17.2s, v16.2s + WORD $0x138a316a // extr w10, w11, w10, #12 + WORD $0x2ea74631 // ushl v17.2s, v17.2s, v7.2s + WORD $0x0eb11e50 // orr v16.8b, v18.8b, v17.8b + WORD $0x4e141d50 // mov v16.s[2], w10 + WORD $0x53067d6a // lsr w10, w11, #6 + WORD $0x4e1c1d50 // mov v16.s[3], w10 + WORD $0x6f077790 // bic v16.4s, #252, lsl #24 + WORD $0x3d800d10 // str q16, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_138 + JMP LBB0_156 + +LBB0_139: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.140: + // WORD $0x90000008 // adrp x8, .LCPI0_174 + // WORD $0x90000009 // adrp x9, .LCPI0_175 + // WORD $0x9000000a // adrp x10, .LCPI0_176 + // WORD $0x9000000b // adrp x11, .LCPI0_177 + WORD $0x4f0107e2 // movi v2.4s, #63 + VMOVD LCPI0_174, V0 + WORD $0x91010348 // add x8, x26, #64 + VMOVD LCPI0_175, V1 + WORD $0xaa1303e9 // mov x9, x19 + VMOVD LCPI0_176, V3 + VMOVQ LCPI0_177L, LCPI0_177H, V4 + +LBB0_141: + WORD $0xb940000a // ldr w10, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x0e040d45 // dup v5.2s, w10 + WORD $0x1e270146 // fmov s6, w10 + WORD $0x53127d4a // lsr w10, w10, #18 + WORD $0x6e0620c6 // ext v6.16b, v6.16b, v6.16b, #4 + WORD $0x2ea044a5 // ushl v5.2s, v5.2s, v0.2s + WORD $0x6e0560c5 // ext v5.16b, v6.16b, v5.16b, #12 + WORD $0x4e1c1d45 // mov v5.s[3], w10 + WORD $0x4e221ca5 // and v5.16b, v5.16b, v2.16b + WORD $0x3c9c0105 // stur q5, [x8, #-64] + WORD $0x29402c0a // ldp w10, w11, [x0] + WORD $0x53187d4c // lsr w12, w10, #24 + WORD $0x0e040d65 // dup v5.2s, w11 + WORD $0x138a796a // extr w10, w11, w10, #30 + WORD $0x1e270186 // fmov s6, w12 + WORD $0x2ea144a5 // ushl v5.2s, v5.2s, v1.2s + WORD $0x4e0c1d46 // mov v6.s[1], w10 + WORD $0x6e1804a6 // mov v6.d[1], v5.d[0] + WORD $0x4e221cc5 // and v5.16b, v6.16b, v2.16b + WORD $0x3c9d0105 // stur q5, [x8, #-48] + WORD $0x2940ac0a // ldp w10, w11, [x0, #4] + WORD $0x0e040d45 // dup v5.2s, w10 + WORD $0x138a716a // extr w10, w11, w10, #28 + WORD $0x2ea344a5 // ushl v5.2s, v5.2s, v3.2s + WORD $0x4e141d45 // mov v5.s[2], w10 + WORD $0x53027d6a // lsr w10, w11, #2 + WORD $0x4e1c1d45 // mov v5.s[3], w10 + WORD $0x9100200a // add x10, x0, #8 + WORD $0x4e221ca5 // and v5.16b, v5.16b, v2.16b + WORD $0x3c9e0105 // stur q5, [x8, #-32] + WORD $0x4d40c945 // ld1r { v5.4s }, [x10] + WORD $0x6ea444a5 // ushl v5.4s, v5.4s, v4.4s + WORD $0x4e221ca5 // and v5.16b, v5.16b, v2.16b + WORD $0x3c9f0105 // stur q5, [x8, #-16] + WORD $0xb9400c0a // ldr w10, [x0, #12] + WORD $0x0e040d45 // dup v5.2s, w10 + WORD $0x1e270146 // fmov s6, w10 + WORD $0x53127d4a // lsr w10, w10, #18 + WORD $0x6e0620c6 // ext v6.16b, v6.16b, v6.16b, #4 + WORD $0x2ea044a5 // ushl v5.2s, v5.2s, v0.2s + WORD $0x6e0560c5 // ext v5.16b, v6.16b, v5.16b, #12 + WORD $0x4e1c1d45 // mov v5.s[3], w10 + WORD $0x4e221ca5 // and v5.16b, v5.16b, v2.16b + WORD $0x3d800105 // str q5, [x8] + WORD $0x2941ac0a // ldp w10, w11, [x0, #12] + WORD $0x53187d4c // lsr w12, w10, #24 + WORD $0x0e040d65 // dup v5.2s, w11 + WORD $0x138a796a // extr w10, w11, w10, #30 + WORD $0x1e270186 // fmov s6, w12 + WORD $0x2ea144a5 // ushl v5.2s, v5.2s, v1.2s + WORD $0x4e0c1d46 // mov v6.s[1], w10 + WORD $0x6e1804a6 // mov v6.d[1], v5.d[0] + WORD $0x4e221cc5 // and v5.16b, v6.16b, v2.16b + WORD $0x3d800505 // str q5, [x8, #16] + WORD $0x29422c0a // ldp w10, w11, [x0, #16] + WORD $0x0e040d45 // dup v5.2s, w10 + WORD $0x138a716a // extr w10, w11, w10, #28 + WORD $0x2ea344a5 // ushl v5.2s, v5.2s, v3.2s + WORD $0x4e141d45 // mov v5.s[2], w10 + WORD $0x53027d6a // lsr w10, w11, #2 + WORD $0x4e1c1d45 // mov v5.s[3], w10 + WORD $0x9100500a // add x10, x0, #20 + WORD $0x91006000 // add x0, x0, #24 + WORD $0x4e221ca5 // and v5.16b, v5.16b, v2.16b + WORD $0x3d800905 // str q5, [x8, #32] + WORD $0x4d40c945 // ld1r { v5.4s }, [x10] + WORD $0x6ea444a5 // ushl v5.4s, v5.4s, v4.4s + WORD $0x4e221ca5 // and v5.16b, v5.16b, v2.16b + WORD $0x3d800d05 // str q5, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_141 + JMP LBB0_156 + +LBB0_142: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.143: + // WORD $0x90000008 // adrp x8, .LCPI0_110 + // WORD $0x90000009 // adrp x9, .LCPI0_111 + // WORD $0x9000000a // adrp x10, .LCPI0_112 + WORD $0x4f01d7e7 // movi v7.4s, #63, msl #16 + VMOVD LCPI0_110, V0 + // WORD $0x90000008 // adrp x8, .LCPI0_113 + VMOVD LCPI0_111, V1 + // WORD $0x90000009 // adrp x9, .LCPI0_114 + VMOVD LCPI0_112, V2 + // WORD $0x9000000a // adrp x10, .LCPI0_115 + VMOVD LCPI0_113, V3 + // WORD $0x90000008 // adrp x8, .LCPI0_116 + VMOVD LCPI0_114, V4 + // WORD $0x90000009 // adrp x9, .LCPI0_117 + VMOVD LCPI0_115, V5 + VMOVD LCPI0_116, V6 + WORD $0x91010348 // add x8, x26, #64 + VMOVD LCPI0_117, V16 + WORD $0xaa1303e9 // mov x9, x19 + +LBB0_144: + WORD $0xb940000a // ldr w10, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0xfc404011 // ldur d17, [x0, #4] + WORD $0x1e270152 // fmov s18, w10 + WORD $0x1e270153 // fmov s19, w10 + WORD $0x2ea04634 // ushl v20.2s, v17.2s, v0.2s + WORD $0x0e0c3e2a // mov w10, v17.s[1] + WORD $0x0e913a52 // zip1 v18.2s, v18.2s, v17.2s + WORD $0x6e132273 // ext v19.16b, v19.16b, v19.16b, #4 + WORD $0x53027d4a // lsr w10, w10, #2 + WORD $0x2ea14652 // ushl v18.2s, v18.2s, v1.2s + WORD $0x0eb21e92 // orr v18.8b, v20.8b, v18.8b + WORD $0x6e126271 // ext v17.16b, v19.16b, v18.16b, #12 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9c0111 // stur q17, [x8, #-64] + WORD $0xfc40c011 // ldur d17, [x0, #12] + WORD $0xbd400812 // ldr s18, [x0, #8] + WORD $0xb940140c // ldr w12, [x0, #20] + WORD $0x2ea24633 // ushl v19.2s, v17.2s, v2.2s + WORD $0x0e0c3e2a // mov w10, v17.s[1] + WORD $0x0e913a52 // zip1 v18.2s, v18.2s, v17.2s + WORD $0x53047d4b // lsr w11, w10, #4 + WORD $0x138a698a // extr w10, w12, w10, #26 + WORD $0x2ea34652 // ushl v18.2s, v18.2s, v3.2s + WORD $0x0eb21e71 // orr v17.8b, v19.8b, v18.8b + WORD $0x4e141d71 // mov v17.s[2], w11 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9d0111 // stur q17, [x8, #-48] + WORD $0x2942a80b // ldp w11, w10, [x0, #20] + WORD $0xfc41c011 // ldur d17, [x0, #28] + WORD $0x1e270152 // fmov s18, w10 + WORD $0x138b414b // extr w11, w10, w11, #16 + WORD $0x53067d4a // lsr w10, w10, #6 + WORD $0x0e913a52 // zip1 v18.2s, v18.2s, v17.2s + WORD $0x2ea44631 // ushl v17.2s, v17.2s, v4.2s + WORD $0x1e270173 // fmov s19, w11 + WORD $0x2ea54652 // ushl v18.2s, v18.2s, v5.2s + WORD $0x4e0c1d53 // mov v19.s[1], w10 + WORD $0x0eb21e31 // orr v17.8b, v17.8b, v18.8b + WORD $0x6e180633 // mov v19.d[1], v17.d[0] + WORD $0x4e271e71 // and v17.16b, v19.16b, v7.16b + WORD $0x3c9e0111 // stur q17, [x8, #-32] + WORD $0xb940200a // ldr w10, [x0, #32] + WORD $0xfc424011 // ldur d17, [x0, #36] + WORD $0x1e270152 // fmov s18, w10 + WORD $0x53087d4a // lsr w10, w10, #8 + WORD $0x2ea64633 // ushl v19.2s, v17.2s, v6.2s + WORD $0x0e913a52 // zip1 v18.2s, v18.2s, v17.2s + WORD $0x1e270154 // fmov s20, w10 + WORD $0x0e0c3e2a // mov w10, v17.s[1] + WORD $0x6e142294 // ext v20.16b, v20.16b, v20.16b, #4 + WORD $0x2eb04652 // ushl v18.2s, v18.2s, v16.2s + WORD $0x530a7d4a // lsr w10, w10, #10 + WORD $0x0eb21e72 // orr v18.8b, v19.8b, v18.8b + WORD $0x6e126291 // ext v17.16b, v20.16b, v18.16b, #12 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3c9f0111 // stur q17, [x8, #-16] + WORD $0xb9402c0a // ldr w10, [x0, #44] + WORD $0xfd401811 // ldr d17, [x0, #48] + WORD $0x1e270152 // fmov s18, w10 + WORD $0x1e270153 // fmov s19, w10 + WORD $0x2ea04634 // ushl v20.2s, v17.2s, v0.2s + WORD $0x0e0c3e2a // mov w10, v17.s[1] + WORD $0x0e913a52 // zip1 v18.2s, v18.2s, v17.2s + WORD $0x6e132273 // ext v19.16b, v19.16b, v19.16b, #4 + WORD $0x53027d4a // lsr w10, w10, #2 + WORD $0x2ea14652 // ushl v18.2s, v18.2s, v1.2s + WORD $0x0eb21e92 // orr v18.8b, v20.8b, v18.8b + WORD $0x6e126271 // ext v17.16b, v19.16b, v18.16b, #12 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800111 // str q17, [x8] + WORD $0xfd401c11 // ldr d17, [x0, #56] + WORD $0xbd403412 // ldr s18, [x0, #52] + WORD $0xb940400c // ldr w12, [x0, #64] + WORD $0x2ea24633 // ushl v19.2s, v17.2s, v2.2s + WORD $0x0e0c3e2a // mov w10, v17.s[1] + WORD $0x0e913a52 // zip1 v18.2s, v18.2s, v17.2s + WORD $0x53047d4b // lsr w11, w10, #4 + WORD $0x138a698a // extr w10, w12, w10, #26 + WORD $0x2ea34652 // ushl v18.2s, v18.2s, v3.2s + WORD $0x0eb21e71 // orr v17.8b, v19.8b, v18.8b + WORD $0x4e141d71 // mov v17.s[2], w11 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800511 // str q17, [x8, #16] + WORD $0x2948280b // ldp w11, w10, [x0, #64] + WORD $0xfd402411 // ldr d17, [x0, #72] + WORD $0x1e270152 // fmov s18, w10 + WORD $0x138b414b // extr w11, w10, w11, #16 + WORD $0x53067d4a // lsr w10, w10, #6 + WORD $0x0e913a52 // zip1 v18.2s, v18.2s, v17.2s + WORD $0x2ea44631 // ushl v17.2s, v17.2s, v4.2s + WORD $0x1e270173 // fmov s19, w11 + WORD $0x2ea54652 // ushl v18.2s, v18.2s, v5.2s + WORD $0x4e0c1d53 // mov v19.s[1], w10 + WORD $0x0eb21e31 // orr v17.8b, v17.8b, v18.8b + WORD $0x6e180633 // mov v19.d[1], v17.d[0] + WORD $0x4e271e71 // and v17.16b, v19.16b, v7.16b + WORD $0x3d800911 // str q17, [x8, #32] + WORD $0xb9404c0a // ldr w10, [x0, #76] + WORD $0xfd402811 // ldr d17, [x0, #80] + WORD $0x91016000 // add x0, x0, #88 + WORD $0x1e270152 // fmov s18, w10 + WORD $0x53087d4a // lsr w10, w10, #8 + WORD $0x2ea64633 // ushl v19.2s, v17.2s, v6.2s + WORD $0x0e913a52 // zip1 v18.2s, v18.2s, v17.2s + WORD $0x1e270154 // fmov s20, w10 + WORD $0x0e0c3e2a // mov w10, v17.s[1] + WORD $0x6e142294 // ext v20.16b, v20.16b, v20.16b, #4 + WORD $0x2eb04652 // ushl v18.2s, v18.2s, v16.2s + WORD $0x530a7d4a // lsr w10, w10, #10 + WORD $0x0eb21e72 // orr v18.8b, v19.8b, v18.8b + WORD $0x6e126291 // ext v17.16b, v20.16b, v18.16b, #12 + WORD $0x4e1c1d51 // mov v17.s[3], w10 + WORD $0x4e271e31 // and v17.16b, v17.16b, v7.16b + WORD $0x3d800d11 // str q17, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_144 + JMP LBB0_156 + +LBB0_145: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.146: + // WORD $0x90000009 // adrp x9, .LCPI0_139 + WORD $0x91010348 // add x8, x26, #64 + WORD $0x4f01c7e0 // movi v0.4s, #63, msl #8 + VMOVD LCPI0_139, V1 + WORD $0xaa1303e9 // mov x9, x19 + +LBB0_147: + WORD $0x29402c0a // ldp w10, w11, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0x530e7d4c // lsr w12, w10, #14 + WORD $0x1e270142 // fmov s2, w10 + WORD $0x138a716a // extr w10, w11, w10, #28 + WORD $0x4e0c1d82 // mov v2.s[1], w12 + WORD $0x4e141d42 // mov v2.s[2], w10 + WORD $0x530a7d6a // lsr w10, w11, #10 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3c9c0102 // stur q2, [x8, #-64] + WORD $0x2940ac0a // ldp w10, w11, [x0, #4] + WORD $0x138a616a // extr w10, w11, w10, #24 + WORD $0x53067d6c // lsr w12, w11, #6 + WORD $0x1e270142 // fmov s2, w10 + WORD $0xb9400c0a // ldr w10, [x0, #12] + WORD $0x138b514b // extr w11, w10, w11, #20 + WORD $0x4e0c1d82 // mov v2.s[1], w12 + WORD $0x53027d4a // lsr w10, w10, #2 + WORD $0x4e141d62 // mov v2.s[2], w11 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3c9d0102 // stur q2, [x8, #-48] + WORD $0x2941ac0a // ldp w10, w11, [x0, #12] + WORD $0x53107d4c // lsr w12, w10, #16 + WORD $0x138a796a // extr w10, w11, w10, #30 + WORD $0x1e270182 // fmov s2, w12 + WORD $0xb940140c // ldr w12, [x0, #20] + WORD $0x4e0c1d42 // mov v2.s[1], w10 + WORD $0x530c7d6a // lsr w10, w11, #12 + WORD $0x4e141d42 // mov v2.s[2], w10 + WORD $0x138b698a // extr w10, w12, w11, #26 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3c9e0102 // stur q2, [x8, #-32] + WORD $0x2942ac0a // ldp w10, w11, [x0, #20] + WORD $0x53087d4c // lsr w12, w10, #8 + WORD $0x0e040d62 // dup v2.2s, w11 + WORD $0x138a596a // extr w10, w11, w10, #22 + WORD $0x1e270183 // fmov s3, w12 + WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s + WORD $0x4e0c1d43 // mov v3.s[1], w10 + WORD $0x6e180443 // mov v3.d[1], v2.d[0] + WORD $0x4e201c62 // and v2.16b, v3.16b, v0.16b + WORD $0x3c9f0102 // stur q2, [x8, #-16] + WORD $0x2943ac0a // ldp w10, w11, [x0, #28] + WORD $0x530e7d4c // lsr w12, w10, #14 + WORD $0x1e270142 // fmov s2, w10 + WORD $0x138a716a // extr w10, w11, w10, #28 + WORD $0x4e0c1d82 // mov v2.s[1], w12 + WORD $0x4e141d42 // mov v2.s[2], w10 + WORD $0x530a7d6a // lsr w10, w11, #10 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3d800102 // str q2, [x8] + WORD $0x29442c0a // ldp w10, w11, [x0, #32] + WORD $0x138a616a // extr w10, w11, w10, #24 + WORD $0x53067d6c // lsr w12, w11, #6 + WORD $0x1e270142 // fmov s2, w10 + WORD $0xb940280a // ldr w10, [x0, #40] + WORD $0x138b514b // extr w11, w10, w11, #20 + WORD $0x4e0c1d82 // mov v2.s[1], w12 + WORD $0x53027d4a // lsr w10, w10, #2 + WORD $0x4e141d62 // mov v2.s[2], w11 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3d800502 // str q2, [x8, #16] + WORD $0x29452c0a // ldp w10, w11, [x0, #40] + WORD $0x53107d4c // lsr w12, w10, #16 + WORD $0x138a796a // extr w10, w11, w10, #30 + WORD $0x1e270182 // fmov s2, w12 + WORD $0xb940300c // ldr w12, [x0, #48] + WORD $0x4e0c1d42 // mov v2.s[1], w10 + WORD $0x530c7d6a // lsr w10, w11, #12 + WORD $0x4e141d42 // mov v2.s[2], w10 + WORD $0x138b698a // extr w10, w12, w11, #26 + WORD $0x4e1c1d42 // mov v2.s[3], w10 + WORD $0x4e201c42 // and v2.16b, v2.16b, v0.16b + WORD $0x3d800902 // str q2, [x8, #32] + WORD $0x29462c0a // ldp w10, w11, [x0, #48] + WORD $0x9100e000 // add x0, x0, #56 + WORD $0x53087d4c // lsr w12, w10, #8 + WORD $0x0e040d62 // dup v2.2s, w11 + WORD $0x138a596a // extr w10, w11, w10, #22 + WORD $0x1e270183 // fmov s3, w12 + WORD $0x2ea14442 // ushl v2.2s, v2.2s, v1.2s + WORD $0x4e0c1d43 // mov v3.s[1], w10 + WORD $0x6e180443 // mov v3.d[1], v2.d[0] + WORD $0x4e201c62 // and v2.16b, v3.16b, v0.16b + WORD $0x3d800d02 // str q2, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_147 + JMP LBB0_156 + +LBB0_148: + WORD $0x7100805f // cmp w2, #32 + BLT LBB0_156 + + // %bb.149: + // WORD $0x90000008 // adrp x8, .LCPI0_24 + // WORD $0x90000009 // adrp x9, .LCPI0_25 + // WORD $0x9000000a // adrp x10, .LCPI0_26 + VMOVD LCPI0_24, V0 + // WORD $0x90000008 // adrp x8, .LCPI0_27 + VMOVD LCPI0_25, V1 + // WORD $0x90000009 // adrp x9, .LCPI0_28 + VMOVQ LCPI0_26L, LCPI0_26H, V2 + // WORD $0x9000000a // adrp x10, .LCPI0_29 + VMOVQ LCPI0_27L, LCPI0_27H, V3 + // WORD $0x90000008 // adrp x8, .LCPI0_30 + VMOVQ LCPI0_28L, LCPI0_28H, V4 + // WORD $0x90000009 // adrp x9, .LCPI0_31 + VMOVQ LCPI0_29L, LCPI0_29H, V5 + VMOVD LCPI0_30, V6 + WORD $0x91010348 // add x8, x26, #64 + VMOVD LCPI0_31, V7 + WORD $0xaa1303e9 // mov x9, x19 + +LBB0_150: + WORD $0xb940000a // ldr w10, [x0] + WORD $0xf1000529 // subs x9, x9, #1 + WORD $0xfc404010 // ldur d16, [x0, #4] + WORD $0xb9400c0b // ldr w11, [x0, #12] + WORD $0x1e270151 // fmov s17, w10 + WORD $0x1e270152 // fmov s18, w10 + WORD $0x2ea04613 // ushl v19.2s, v16.2s, v0.2s + WORD $0x0e0c3e0a // mov w10, v16.s[1] + WORD $0x0e903a31 // zip1 v17.2s, v17.2s, v16.2s + WORD $0x6e122252 // ext v18.16b, v18.16b, v18.16b, #4 + WORD $0x138a696a // extr w10, w11, w10, #26 + WORD $0x2ea14631 // ushl v17.2s, v17.2s, v1.2s + WORD $0x0eb11e71 // orr v17.8b, v19.8b, v17.8b + WORD $0x6e116250 // ext v16.16b, v18.16b, v17.16b, #12 + WORD $0x4e1c1d50 // mov v16.s[3], w10 + WORD $0x6f067410 // bic v16.4s, #192, lsl #24 + WORD $0x3c9c0110 // stur q16, [x8, #-64] + WORD $0xbd400c10 // ldr s16, [x0, #12] + WORD $0x3dc00411 // ldr q17, [x0, #16] + WORD $0x6e102210 // ext v16.16b, v16.16b, v16.16b, #4 + WORD $0x6e116210 // ext v16.16b, v16.16b, v17.16b, #12 + WORD $0x6ea24631 // ushl v17.4s, v17.4s, v2.4s + WORD $0x6ea34610 // ushl v16.4s, v16.4s, v3.4s + WORD $0x4eb01e30 // orr v16.16b, v17.16b, v16.16b + WORD $0x6f067410 // bic v16.4s, #192, lsl #24 + WORD $0x3c9d0110 // stur q16, [x8, #-48] + WORD $0xbd401c10 // ldr s16, [x0, #28] + WORD $0x3dc00811 // ldr q17, [x0, #32] + WORD $0x6e102210 // ext v16.16b, v16.16b, v16.16b, #4 + WORD $0x6e116210 // ext v16.16b, v16.16b, v17.16b, #12 + WORD $0x6ea44631 // ushl v17.4s, v17.4s, v4.4s + WORD $0x6ea54610 // ushl v16.4s, v16.4s, v5.4s + WORD $0x4eb01e30 // orr v16.16b, v17.16b, v16.16b + WORD $0x6f067410 // bic v16.4s, #192, lsl #24 + WORD $0x3c9e0110 // stur q16, [x8, #-32] + WORD $0xfd401810 // ldr d16, [x0, #48] + WORD $0xbd402c11 // ldr s17, [x0, #44] + WORD $0xb940380b // ldr w11, [x0, #56] + WORD $0x2ea64612 // ushl v18.2s, v16.2s, v6.2s + WORD $0x0e0c3e0a // mov w10, v16.s[1] + WORD $0x0e903a31 // zip1 v17.2s, v17.2s, v16.2s + WORD $0x138a116a // extr w10, w11, w10, #4 + WORD $0x2ea74631 // ushl v17.2s, v17.2s, v7.2s + WORD $0x0eb11e50 // orr v16.8b, v18.8b, v17.8b + WORD $0x4e141d50 // mov v16.s[2], w10 + WORD $0x53027d6a // lsr w10, w11, #2 + WORD $0x4e1c1d50 // mov v16.s[3], w10 + WORD $0x6f067410 // bic v16.4s, #192, lsl #24 + WORD $0x3c9f0110 // stur q16, [x8, #-16] + WORD $0xb9403c0a // ldr w10, [x0, #60] + WORD $0xfd402010 // ldr d16, [x0, #64] + WORD $0xb940480b // ldr w11, [x0, #72] + WORD $0x1e270151 // fmov s17, w10 + WORD $0x1e270152 // fmov s18, w10 + WORD $0x2ea04613 // ushl v19.2s, v16.2s, v0.2s + WORD $0x0e0c3e0a // mov w10, v16.s[1] + WORD $0x0e903a31 // zip1 v17.2s, v17.2s, v16.2s + WORD $0x6e122252 // ext v18.16b, v18.16b, v18.16b, #4 + WORD $0x138a696a // extr w10, w11, w10, #26 + WORD $0x2ea14631 // ushl v17.2s, v17.2s, v1.2s + WORD $0x0eb11e71 // orr v17.8b, v19.8b, v17.8b + WORD $0x6e116250 // ext v16.16b, v18.16b, v17.16b, #12 + WORD $0x4e1c1d50 // mov v16.s[3], w10 + WORD $0x6f067410 // bic v16.4s, #192, lsl #24 + WORD $0x3d800110 // str q16, [x8] + WORD $0xbd404810 // ldr s16, [x0, #72] + WORD $0x3cc4c011 // ldur q17, [x0, #76] + WORD $0x6e102210 // ext v16.16b, v16.16b, v16.16b, #4 + WORD $0x6e116210 // ext v16.16b, v16.16b, v17.16b, #12 + WORD $0x6ea24631 // ushl v17.4s, v17.4s, v2.4s + WORD $0x6ea34610 // ushl v16.4s, v16.4s, v3.4s + WORD $0x4eb01e30 // orr v16.16b, v17.16b, v16.16b + WORD $0x6f067410 // bic v16.4s, #192, lsl #24 + WORD $0x3d800510 // str q16, [x8, #16] + WORD $0xbd405810 // ldr s16, [x0, #88] + WORD $0x3cc5c011 // ldur q17, [x0, #92] + WORD $0x6e102210 // ext v16.16b, v16.16b, v16.16b, #4 + WORD $0x6e116210 // ext v16.16b, v16.16b, v17.16b, #12 + WORD $0x6ea44631 // ushl v17.4s, v17.4s, v4.4s + WORD $0x6ea54610 // ushl v16.4s, v16.4s, v5.4s + WORD $0x4eb01e30 // orr v16.16b, v17.16b, v16.16b + WORD $0x6f067410 // bic v16.4s, #192, lsl #24 + WORD $0x3d800910 // str q16, [x8, #32] + WORD $0xfc46c010 // ldur d16, [x0, #108] + WORD $0xbd406811 // ldr s17, [x0, #104] + WORD $0xb940740b // ldr w11, [x0, #116] + WORD $0x9101e000 // add x0, x0, #120 + WORD $0x2ea64612 // ushl v18.2s, v16.2s, v6.2s + WORD $0x0e0c3e0a // mov w10, v16.s[1] + WORD $0x0e903a31 // zip1 v17.2s, v17.2s, v16.2s + WORD $0x138a116a // extr w10, w11, w10, #4 + WORD $0x2ea74631 // ushl v17.2s, v17.2s, v7.2s + WORD $0x0eb11e50 // orr v16.8b, v18.8b, v17.8b + WORD $0x4e141d50 // mov v16.s[2], w10 + WORD $0x53027d6a // lsr w10, w11, #2 + WORD $0x4e1c1d50 // mov v16.s[3], w10 + WORD $0x6f067410 // bic v16.4s, #192, lsl #24 + WORD $0x3d800d10 // str q16, [x8, #48] + WORD $0x91020108 // add x8, x8, #128 + BNE LBB0_150 + JMP LBB0_156 + +LBB0_151: + // WORD $0x90000008 // adrp x8, .LCPI0_0 + // WORD $0x90000009 // adrp x9, .LCPI0_1 + // WORD $0x9000000a // adrp x10, .LCPI0_2 + // WORD $0x9000000b // adrp x11, .LCPI0_3 + WORD $0x5280020c // mov w12, #16 + VMOVQ LCPI0_0L, LCPI0_0H, V0 + // WORD $0x90000008 // adrp x8, .LCPI0_4 + VMOVQ LCPI0_1L, LCPI0_1H, V1 + // WORD $0x90000009 // adrp x9, .LCPI0_5 + VMOVQ LCPI0_2L, LCPI0_2H, V2 + // WORD $0x9000000a // adrp x10, .LCPI0_6 + VMOVQ LCPI0_3L, LCPI0_3H, V3 + // WORD $0x9000000b // adrp x11, .LCPI0_7 + VMOVQ LCPI0_4L, LCPI0_4H, V4 + WORD $0x927c6e68 // and x8, x19, #0xfffffff0 + VMOVQ LCPI0_5L, LCPI0_5H, V5 + WORD $0xaa0803e9 // mov x9, x8 + VMOVQ LCPI0_6L, LCPI0_6H, V6 + WORD $0x4e080d90 // dup v16.2d, x12 + VMOVQ LCPI0_7L, LCPI0_7H, V7 + +LBB0_152: + WORD $0x4f4554f1 // shl v17.2d, v7.2d, #5 + WORD $0xf1004129 // subs x9, x9, #16 + WORD $0x4f4554d2 // shl v18.2d, v6.2d, #5 + WORD $0x4f4554b3 // shl v19.2d, v5.2d, #5 + WORD $0x4f455494 // shl v20.2d, v4.2d, #5 + WORD $0x4e183e2d // mov x13, v17.d[1] + WORD $0x9e66022a // fmov x10, d17 + WORD $0x4e183e4e // mov x14, v18.d[1] + WORD $0x9e66026f // fmov x15, d19 + WORD $0x4e183e70 // mov x16, v19.d[1] + WORD $0x4f455471 // shl v17.2d, v3.2d, #5 + WORD $0x8b0a0b4c // add x12, x26, x10, lsl #2 + WORD $0x9e660280 // fmov x0, d20 + WORD $0x8b0f0b4a // add x10, x26, x15, lsl #2 + WORD $0x4f455453 // shl v19.2d, v2.2d, #5 + WORD $0x9e66024b // fmov x11, d18 + WORD $0x8b0d0b51 // add x17, x26, x13, lsl #2 + WORD $0x8b0e0b4f // add x15, x26, x14, lsl #2 + WORD $0x4f455412 // shl v18.2d, v0.2d, #5 + WORD $0x8b100b4d // add x13, x26, x16, lsl #2 + WORD $0x8b000b4e // add x14, x26, x0, lsl #2 + WORD $0x9e660230 // fmov x16, d17 + WORD $0x4e183e20 // mov x0, v17.d[1] + WORD $0x9e660263 // fmov x3, d19 + WORD $0x4f455431 // shl v17.2d, v1.2d, #5 + WORD $0x8b0b0b4b // add x11, x26, x11, lsl #2 + WORD $0x4e183e92 // mov x18, v20.d[1] + WORD $0x8b100b50 // add x16, x26, x16, lsl #2 + WORD $0x4e183e62 // mov x2, v19.d[1] + WORD $0x8b030b54 // add x20, x26, x3, lsl #2 + WORD $0x4e183e46 // mov x6, v18.d[1] + WORD $0x8b000b40 // add x0, x26, x0, lsl #2 + WORD $0x4e183e23 // mov x3, v17.d[1] + WORD $0xb900019f // str wzr, [x12] + WORD $0x9e660225 // fmov x5, d17 + WORD $0x8b120b52 // add x18, x26, x18, lsl #2 + WORD $0x9e660247 // fmov x7, d18 + WORD $0x8b020b44 // add x4, x26, x2, lsl #2 + WORD $0x4ef084a5 // add v5.2d, v5.2d, v16.2d + WORD $0x8b060b46 // add x6, x26, x6, lsl #2 + WORD $0x4ef084c6 // add v6.2d, v6.2d, v16.2d + WORD $0x8b050b45 // add x5, x26, x5, lsl #2 + WORD $0x4ef084e7 // add v7.2d, v7.2d, v16.2d + WORD $0x8b030b42 // add x2, x26, x3, lsl #2 + WORD $0x4ef08484 // add v4.2d, v4.2d, v16.2d + WORD $0x8b070b43 // add x3, x26, x7, lsl #2 + WORD $0x4ef08463 // add v3.2d, v3.2d, v16.2d + WORD $0xb900023f // str wzr, [x17] + WORD $0x4ef08442 // add v2.2d, v2.2d, v16.2d + WORD $0xb900017f // str wzr, [x11] + WORD $0x4ef08421 // add v1.2d, v1.2d, v16.2d + WORD $0xb90001ff // str wzr, [x15] + WORD $0x4ef08400 // add v0.2d, v0.2d, v16.2d + WORD $0xb900015f // str wzr, [x10] + WORD $0xb90001bf // str wzr, [x13] + WORD $0xb90001df // str wzr, [x14] + WORD $0xb900025f // str wzr, [x18] + WORD $0xb900021f // str wzr, [x16] + WORD $0xb900001f // str wzr, [x0] + WORD $0xb900029f // str wzr, [x20] + WORD $0xb900009f // str wzr, [x4] + WORD $0xb90000bf // str wzr, [x5] + WORD $0xb900005f // str wzr, [x2] + WORD $0xb900007f // str wzr, [x3] + WORD $0xb90000df // str wzr, [x6] + WORD $0xb900059f // str wzr, [x12, #4] + WORD $0xb900063f // str wzr, [x17, #4] + WORD $0xb900057f // str wzr, [x11, #4] + WORD $0xb90005ff // str wzr, [x15, #4] + WORD $0xb900055f // str wzr, [x10, #4] + WORD $0xb90005bf // str wzr, [x13, #4] + WORD $0xb90005df // str wzr, [x14, #4] + WORD $0xb900065f // str wzr, [x18, #4] + WORD $0xb900061f // str wzr, [x16, #4] + WORD $0xb900041f // str wzr, [x0, #4] + WORD $0xb900069f // str wzr, [x20, #4] + WORD $0xb900049f // str wzr, [x4, #4] + WORD $0xb90004bf // str wzr, [x5, #4] + WORD $0xb900045f // str wzr, [x2, #4] + WORD $0xb900047f // str wzr, [x3, #4] + WORD $0xb90004df // str wzr, [x6, #4] + WORD $0xb900099f // str wzr, [x12, #8] + WORD $0xb9000a3f // str wzr, [x17, #8] + WORD $0xb900097f // str wzr, [x11, #8] + WORD $0xb90009ff // str wzr, [x15, #8] + WORD $0xb900095f // str wzr, [x10, #8] + WORD $0xb90009bf // str wzr, [x13, #8] + WORD $0xb90009df // str wzr, [x14, #8] + WORD $0xb9000a5f // str wzr, [x18, #8] + WORD $0xb9000a1f // str wzr, [x16, #8] + WORD $0xb900081f // str wzr, [x0, #8] + WORD $0xb9000a9f // str wzr, [x20, #8] + WORD $0xb900089f // str wzr, [x4, #8] + WORD $0xb90008bf // str wzr, [x5, #8] + WORD $0xb900085f // str wzr, [x2, #8] + WORD $0xb900087f // str wzr, [x3, #8] + WORD $0xb90008df // str wzr, [x6, #8] + WORD $0xb9000d9f // str wzr, [x12, #12] + WORD $0xb9000e3f // str wzr, [x17, #12] + WORD $0xb9000d7f // str wzr, [x11, #12] + WORD $0xb9000dff // str wzr, [x15, #12] + WORD $0xb9000d5f // str wzr, [x10, #12] + WORD $0xb9000dbf // str wzr, [x13, #12] + WORD $0xb9000ddf // str wzr, [x14, #12] + WORD $0xb9000e5f // str wzr, [x18, #12] + WORD $0xb9000e1f // str wzr, [x16, #12] + WORD $0xb9000c1f // str wzr, [x0, #12] + WORD $0xb9000e9f // str wzr, [x20, #12] + WORD $0xb9000c9f // str wzr, [x4, #12] + WORD $0xb9000cbf // str wzr, [x5, #12] + WORD $0xb9000c5f // str wzr, [x2, #12] + WORD $0xb9000c7f // str wzr, [x3, #12] + WORD $0xb9000cdf // str wzr, [x6, #12] + WORD $0xb900119f // str wzr, [x12, #16] + WORD $0xb900123f // str wzr, [x17, #16] + WORD $0xb900117f // str wzr, [x11, #16] + WORD $0xb90011ff // str wzr, [x15, #16] + WORD $0xb900115f // str wzr, [x10, #16] + WORD $0xb90011bf // str wzr, [x13, #16] + WORD $0xb90011df // str wzr, [x14, #16] + WORD $0xb900125f // str wzr, [x18, #16] + WORD $0xb900121f // str wzr, [x16, #16] + WORD $0xb900101f // str wzr, [x0, #16] + WORD $0xb900129f // str wzr, [x20, #16] + WORD $0xb900109f // str wzr, [x4, #16] + WORD $0xb90010bf // str wzr, [x5, #16] + WORD $0xb900105f // str wzr, [x2, #16] + WORD $0xb900107f // str wzr, [x3, #16] + WORD $0xb90010df // str wzr, [x6, #16] + WORD $0xb900159f // str wzr, [x12, #20] + WORD $0xb900163f // str wzr, [x17, #20] + WORD $0xb900157f // str wzr, [x11, #20] + WORD $0xb90015ff // str wzr, [x15, #20] + WORD $0xb900155f // str wzr, [x10, #20] + WORD $0xb90015bf // str wzr, [x13, #20] + WORD $0xb90015df // str wzr, [x14, #20] + WORD $0xb900165f // str wzr, [x18, #20] + WORD $0xb900161f // str wzr, [x16, #20] + WORD $0xb900141f // str wzr, [x0, #20] + WORD $0xb900169f // str wzr, [x20, #20] + WORD $0xb900149f // str wzr, [x4, #20] + WORD $0xb90014bf // str wzr, [x5, #20] + WORD $0xb900145f // str wzr, [x2, #20] + WORD $0xb900147f // str wzr, [x3, #20] + WORD $0xb90014df // str wzr, [x6, #20] + WORD $0xb900199f // str wzr, [x12, #24] + WORD $0xb9001a3f // str wzr, [x17, #24] + WORD $0xb900197f // str wzr, [x11, #24] + WORD $0xb90019ff // str wzr, [x15, #24] + WORD $0xb900195f // str wzr, [x10, #24] + WORD $0xb90019bf // str wzr, [x13, #24] + WORD $0xb90019df // str wzr, [x14, #24] + WORD $0xb9001a5f // str wzr, [x18, #24] + WORD $0xb9001a1f // str wzr, [x16, #24] + WORD $0xb900181f // str wzr, [x0, #24] + WORD $0xb9001a9f // str wzr, [x20, #24] + WORD $0xb900189f // str wzr, [x4, #24] + WORD $0xb90018bf // str wzr, [x5, #24] + WORD $0xb900185f // str wzr, [x2, #24] + WORD $0xb900187f // str wzr, [x3, #24] + WORD $0xb90018df // str wzr, [x6, #24] + WORD $0xb9001d9f // str wzr, [x12, #28] + WORD $0xb9001e3f // str wzr, [x17, #28] + WORD $0xb9001d7f // str wzr, [x11, #28] + WORD $0xb9001dff // str wzr, [x15, #28] + WORD $0xb9001d5f // str wzr, [x10, #28] + WORD $0xb9001dbf // str wzr, [x13, #28] + WORD $0xb9001ddf // str wzr, [x14, #28] + WORD $0xb9001e5f // str wzr, [x18, #28] + WORD $0xb9001e1f // str wzr, [x16, #28] + WORD $0xb9001c1f // str wzr, [x0, #28] + WORD $0xb9001e9f // str wzr, [x20, #28] + WORD $0xb9001c9f // str wzr, [x4, #28] + WORD $0xb9001cbf // str wzr, [x5, #28] + WORD $0xb9001c5f // str wzr, [x2, #28] + WORD $0xb9001c7f // str wzr, [x3, #28] + WORD $0xb9001cdf // str wzr, [x6, #28] + WORD $0xb900219f // str wzr, [x12, #32] + WORD $0xb900223f // str wzr, [x17, #32] + WORD $0xb900217f // str wzr, [x11, #32] + WORD $0xb90021ff // str wzr, [x15, #32] + WORD $0xb900215f // str wzr, [x10, #32] + WORD $0xb90021bf // str wzr, [x13, #32] + WORD $0xb90021df // str wzr, [x14, #32] + WORD $0xb900225f // str wzr, [x18, #32] + WORD $0xb900221f // str wzr, [x16, #32] + WORD $0xb900201f // str wzr, [x0, #32] + WORD $0xb900229f // str wzr, [x20, #32] + WORD $0xb900209f // str wzr, [x4, #32] + WORD $0xb90020bf // str wzr, [x5, #32] + WORD $0xb900205f // str wzr, [x2, #32] + WORD $0xb900207f // str wzr, [x3, #32] + WORD $0xb90020df // str wzr, [x6, #32] + WORD $0xb900259f // str wzr, [x12, #36] + WORD $0xb900263f // str wzr, [x17, #36] + WORD $0xb900257f // str wzr, [x11, #36] + WORD $0xb90025ff // str wzr, [x15, #36] + WORD $0xb900255f // str wzr, [x10, #36] + WORD $0xb90025bf // str wzr, [x13, #36] + WORD $0xb90025df // str wzr, [x14, #36] + WORD $0xb900265f // str wzr, [x18, #36] + WORD $0xb900261f // str wzr, [x16, #36] + WORD $0xb900241f // str wzr, [x0, #36] + WORD $0xb900269f // str wzr, [x20, #36] + WORD $0xb900249f // str wzr, [x4, #36] + WORD $0xb90024bf // str wzr, [x5, #36] + WORD $0xb900245f // str wzr, [x2, #36] + WORD $0xb900247f // str wzr, [x3, #36] + WORD $0xb90024df // str wzr, [x6, #36] + WORD $0xb900299f // str wzr, [x12, #40] + WORD $0xb9002a3f // str wzr, [x17, #40] + WORD $0xb900297f // str wzr, [x11, #40] + WORD $0xb90029ff // str wzr, [x15, #40] + WORD $0xb900295f // str wzr, [x10, #40] + WORD $0xb90029bf // str wzr, [x13, #40] + WORD $0xb90029df // str wzr, [x14, #40] + WORD $0xb9002a5f // str wzr, [x18, #40] + WORD $0xb9002a1f // str wzr, [x16, #40] + WORD $0xb900281f // str wzr, [x0, #40] + WORD $0xb9002a9f // str wzr, [x20, #40] + WORD $0xb900289f // str wzr, [x4, #40] + WORD $0xb90028bf // str wzr, [x5, #40] + WORD $0xb900285f // str wzr, [x2, #40] + WORD $0xb900287f // str wzr, [x3, #40] + WORD $0xb90028df // str wzr, [x6, #40] + WORD $0xb9002d9f // str wzr, [x12, #44] + WORD $0xb9002e3f // str wzr, [x17, #44] + WORD $0xb9002d7f // str wzr, [x11, #44] + WORD $0xb9002dff // str wzr, [x15, #44] + WORD $0xb9002d5f // str wzr, [x10, #44] + WORD $0xb9002dbf // str wzr, [x13, #44] + WORD $0xb9002ddf // str wzr, [x14, #44] + WORD $0xb9002e5f // str wzr, [x18, #44] + WORD $0xb9002e1f // str wzr, [x16, #44] + WORD $0xb9002c1f // str wzr, [x0, #44] + WORD $0xb9002e9f // str wzr, [x20, #44] + WORD $0xb9002c9f // str wzr, [x4, #44] + WORD $0xb9002cbf // str wzr, [x5, #44] + WORD $0xb9002c5f // str wzr, [x2, #44] + WORD $0xb9002c7f // str wzr, [x3, #44] + WORD $0xb9002cdf // str wzr, [x6, #44] + WORD $0xb900319f // str wzr, [x12, #48] + WORD $0xb900323f // str wzr, [x17, #48] + WORD $0xb900317f // str wzr, [x11, #48] + WORD $0xb90031ff // str wzr, [x15, #48] + WORD $0xb900315f // str wzr, [x10, #48] + WORD $0xb90031bf // str wzr, [x13, #48] + WORD $0xb90031df // str wzr, [x14, #48] + WORD $0xb900325f // str wzr, [x18, #48] + WORD $0xb900321f // str wzr, [x16, #48] + WORD $0xb900301f // str wzr, [x0, #48] + WORD $0xb900329f // str wzr, [x20, #48] + WORD $0xb900309f // str wzr, [x4, #48] + WORD $0xb90030bf // str wzr, [x5, #48] + WORD $0xb900305f // str wzr, [x2, #48] + WORD $0xb900307f // str wzr, [x3, #48] + WORD $0xb90030df // str wzr, [x6, #48] + WORD $0xb900359f // str wzr, [x12, #52] + WORD $0xb900363f // str wzr, [x17, #52] + WORD $0xb900357f // str wzr, [x11, #52] + WORD $0xb90035ff // str wzr, [x15, #52] + WORD $0xb900355f // str wzr, [x10, #52] + WORD $0xb90035bf // str wzr, [x13, #52] + WORD $0xb90035df // str wzr, [x14, #52] + WORD $0xb900365f // str wzr, [x18, #52] + WORD $0xb900361f // str wzr, [x16, #52] + WORD $0xb900341f // str wzr, [x0, #52] + WORD $0xb900369f // str wzr, [x20, #52] + WORD $0xb900349f // str wzr, [x4, #52] + WORD $0xb90034bf // str wzr, [x5, #52] + WORD $0xb900345f // str wzr, [x2, #52] + WORD $0xb900347f // str wzr, [x3, #52] + WORD $0xb90034df // str wzr, [x6, #52] + WORD $0xb900399f // str wzr, [x12, #56] + WORD $0xb9003a3f // str wzr, [x17, #56] + WORD $0xb900397f // str wzr, [x11, #56] + WORD $0xb90039ff // str wzr, [x15, #56] + WORD $0xb900395f // str wzr, [x10, #56] + WORD $0xb90039bf // str wzr, [x13, #56] + WORD $0xb90039df // str wzr, [x14, #56] + WORD $0xb9003a5f // str wzr, [x18, #56] + WORD $0xb9003a1f // str wzr, [x16, #56] + WORD $0xb900381f // str wzr, [x0, #56] + WORD $0xb9003a9f // str wzr, [x20, #56] + WORD $0xb900389f // str wzr, [x4, #56] + WORD $0xb90038bf // str wzr, [x5, #56] + WORD $0xb900385f // str wzr, [x2, #56] + WORD $0xb900387f // str wzr, [x3, #56] + WORD $0xb90038df // str wzr, [x6, #56] + WORD $0xb9003d9f // str wzr, [x12, #60] + WORD $0xb9003e3f // str wzr, [x17, #60] + WORD $0xb9003d7f // str wzr, [x11, #60] + WORD $0xb9003dff // str wzr, [x15, #60] + WORD $0xb9003d5f // str wzr, [x10, #60] + WORD $0xb9003dbf // str wzr, [x13, #60] + WORD $0xb9003ddf // str wzr, [x14, #60] + WORD $0xb9003e5f // str wzr, [x18, #60] + WORD $0xb9003e1f // str wzr, [x16, #60] + WORD $0xb9003c1f // str wzr, [x0, #60] + WORD $0xb9003e9f // str wzr, [x20, #60] + WORD $0xb9003c9f // str wzr, [x4, #60] + WORD $0xb9003cbf // str wzr, [x5, #60] + WORD $0xb9003c5f // str wzr, [x2, #60] + WORD $0xb9003c7f // str wzr, [x3, #60] + WORD $0xb9003cdf // str wzr, [x6, #60] + WORD $0xb900419f // str wzr, [x12, #64] + WORD $0xb900423f // str wzr, [x17, #64] + WORD $0xb900417f // str wzr, [x11, #64] + WORD $0xb90041ff // str wzr, [x15, #64] + WORD $0xb900415f // str wzr, [x10, #64] + WORD $0xb90041bf // str wzr, [x13, #64] + WORD $0xb90041df // str wzr, [x14, #64] + WORD $0xb900425f // str wzr, [x18, #64] + WORD $0xb900421f // str wzr, [x16, #64] + WORD $0xb900401f // str wzr, [x0, #64] + WORD $0xb900429f // str wzr, [x20, #64] + WORD $0xb900409f // str wzr, [x4, #64] + WORD $0xb90040bf // str wzr, [x5, #64] + WORD $0xb900405f // str wzr, [x2, #64] + WORD $0xb900407f // str wzr, [x3, #64] + WORD $0xb90040df // str wzr, [x6, #64] + WORD $0xb900459f // str wzr, [x12, #68] + WORD $0xb900463f // str wzr, [x17, #68] + WORD $0xb900457f // str wzr, [x11, #68] + WORD $0xb90045ff // str wzr, [x15, #68] + WORD $0xb900455f // str wzr, [x10, #68] + WORD $0xb90045bf // str wzr, [x13, #68] + WORD $0xb90045df // str wzr, [x14, #68] + WORD $0xb900465f // str wzr, [x18, #68] + WORD $0xb900461f // str wzr, [x16, #68] + WORD $0xb900441f // str wzr, [x0, #68] + WORD $0xb900469f // str wzr, [x20, #68] + WORD $0xb900449f // str wzr, [x4, #68] + WORD $0xb90044bf // str wzr, [x5, #68] + WORD $0xb900445f // str wzr, [x2, #68] + WORD $0xb900447f // str wzr, [x3, #68] + WORD $0xb90044df // str wzr, [x6, #68] + WORD $0xb900499f // str wzr, [x12, #72] + WORD $0xb9004a3f // str wzr, [x17, #72] + WORD $0xb900497f // str wzr, [x11, #72] + WORD $0xb90049ff // str wzr, [x15, #72] + WORD $0xb900495f // str wzr, [x10, #72] + WORD $0xb90049bf // str wzr, [x13, #72] + WORD $0xb90049df // str wzr, [x14, #72] + WORD $0xb9004a5f // str wzr, [x18, #72] + WORD $0xb9004a1f // str wzr, [x16, #72] + WORD $0xb900481f // str wzr, [x0, #72] + WORD $0xb9004a9f // str wzr, [x20, #72] + WORD $0xb900489f // str wzr, [x4, #72] + WORD $0xb90048bf // str wzr, [x5, #72] + WORD $0xb900485f // str wzr, [x2, #72] + WORD $0xb900487f // str wzr, [x3, #72] + WORD $0xb90048df // str wzr, [x6, #72] + WORD $0xb9004d9f // str wzr, [x12, #76] + WORD $0xb9004e3f // str wzr, [x17, #76] + WORD $0xb9004d7f // str wzr, [x11, #76] + WORD $0xb9004dff // str wzr, [x15, #76] + WORD $0xb9004d5f // str wzr, [x10, #76] + WORD $0xb9004dbf // str wzr, [x13, #76] + WORD $0xb9004ddf // str wzr, [x14, #76] + WORD $0xb9004e5f // str wzr, [x18, #76] + WORD $0xb9004e1f // str wzr, [x16, #76] + WORD $0xb9004c1f // str wzr, [x0, #76] + WORD $0xb9004e9f // str wzr, [x20, #76] + WORD $0xb9004c9f // str wzr, [x4, #76] + WORD $0xb9004cbf // str wzr, [x5, #76] + WORD $0xb9004c5f // str wzr, [x2, #76] + WORD $0xb9004c7f // str wzr, [x3, #76] + WORD $0xb9004cdf // str wzr, [x6, #76] + WORD $0xb900519f // str wzr, [x12, #80] + WORD $0xb900523f // str wzr, [x17, #80] + WORD $0xb900517f // str wzr, [x11, #80] + WORD $0xb90051ff // str wzr, [x15, #80] + WORD $0xb900515f // str wzr, [x10, #80] + WORD $0xb90051bf // str wzr, [x13, #80] + WORD $0xb90051df // str wzr, [x14, #80] + WORD $0xb900525f // str wzr, [x18, #80] + WORD $0xb900521f // str wzr, [x16, #80] + WORD $0xb900501f // str wzr, [x0, #80] + WORD $0xb900529f // str wzr, [x20, #80] + WORD $0xb900509f // str wzr, [x4, #80] + WORD $0xb90050bf // str wzr, [x5, #80] + WORD $0xb900505f // str wzr, [x2, #80] + WORD $0xb900507f // str wzr, [x3, #80] + WORD $0xb90050df // str wzr, [x6, #80] + WORD $0xb900559f // str wzr, [x12, #84] + WORD $0xb900563f // str wzr, [x17, #84] + WORD $0xb900557f // str wzr, [x11, #84] + WORD $0xb90055ff // str wzr, [x15, #84] + WORD $0xb900555f // str wzr, [x10, #84] + WORD $0xb90055bf // str wzr, [x13, #84] + WORD $0xb90055df // str wzr, [x14, #84] + WORD $0xb900565f // str wzr, [x18, #84] + WORD $0xb900561f // str wzr, [x16, #84] + WORD $0xb900541f // str wzr, [x0, #84] + WORD $0xb900569f // str wzr, [x20, #84] + WORD $0xb900549f // str wzr, [x4, #84] + WORD $0xb90054bf // str wzr, [x5, #84] + WORD $0xb900545f // str wzr, [x2, #84] + WORD $0xb900547f // str wzr, [x3, #84] + WORD $0xb90054df // str wzr, [x6, #84] + WORD $0xb900599f // str wzr, [x12, #88] + WORD $0xb9005a3f // str wzr, [x17, #88] + WORD $0xb900597f // str wzr, [x11, #88] + WORD $0xb90059ff // str wzr, [x15, #88] + WORD $0xb900595f // str wzr, [x10, #88] + WORD $0xb90059bf // str wzr, [x13, #88] + WORD $0xb90059df // str wzr, [x14, #88] + WORD $0xb9005a5f // str wzr, [x18, #88] + WORD $0xb9005a1f // str wzr, [x16, #88] + WORD $0xb900581f // str wzr, [x0, #88] + WORD $0xb9005a9f // str wzr, [x20, #88] + WORD $0xb900589f // str wzr, [x4, #88] + WORD $0xb90058bf // str wzr, [x5, #88] + WORD $0xb900585f // str wzr, [x2, #88] + WORD $0xb900587f // str wzr, [x3, #88] + WORD $0xb90058df // str wzr, [x6, #88] + WORD $0xb9005d9f // str wzr, [x12, #92] + WORD $0xb9005e3f // str wzr, [x17, #92] + WORD $0xb9005d7f // str wzr, [x11, #92] + WORD $0xb9005dff // str wzr, [x15, #92] + WORD $0xb9005d5f // str wzr, [x10, #92] + WORD $0xb9005dbf // str wzr, [x13, #92] + WORD $0xb9005ddf // str wzr, [x14, #92] + WORD $0xb9005e5f // str wzr, [x18, #92] + WORD $0xb9005e1f // str wzr, [x16, #92] + WORD $0xb9005c1f // str wzr, [x0, #92] + WORD $0xb9005e9f // str wzr, [x20, #92] + WORD $0xb9005c9f // str wzr, [x4, #92] + WORD $0xb9005cbf // str wzr, [x5, #92] + WORD $0xb9005c5f // str wzr, [x2, #92] + WORD $0xb9005c7f // str wzr, [x3, #92] + WORD $0xb9005cdf // str wzr, [x6, #92] + WORD $0xb900619f // str wzr, [x12, #96] + WORD $0xb900623f // str wzr, [x17, #96] + WORD $0xb900617f // str wzr, [x11, #96] + WORD $0xb90061ff // str wzr, [x15, #96] + WORD $0xb900615f // str wzr, [x10, #96] + WORD $0xb90061bf // str wzr, [x13, #96] + WORD $0xb90061df // str wzr, [x14, #96] + WORD $0xb900625f // str wzr, [x18, #96] + WORD $0xb900621f // str wzr, [x16, #96] + WORD $0xb900601f // str wzr, [x0, #96] + WORD $0xb900629f // str wzr, [x20, #96] + WORD $0xb900609f // str wzr, [x4, #96] + WORD $0xb90060bf // str wzr, [x5, #96] + WORD $0xb900605f // str wzr, [x2, #96] + WORD $0xb900607f // str wzr, [x3, #96] + WORD $0xb90060df // str wzr, [x6, #96] + WORD $0xb900659f // str wzr, [x12, #100] + WORD $0xb900663f // str wzr, [x17, #100] + WORD $0xb900657f // str wzr, [x11, #100] + WORD $0xb90065ff // str wzr, [x15, #100] + WORD $0xb900655f // str wzr, [x10, #100] + WORD $0xb90065bf // str wzr, [x13, #100] + WORD $0xb90065df // str wzr, [x14, #100] + WORD $0xb900665f // str wzr, [x18, #100] + WORD $0xb900661f // str wzr, [x16, #100] + WORD $0xb900641f // str wzr, [x0, #100] + WORD $0xb900669f // str wzr, [x20, #100] + WORD $0xb900649f // str wzr, [x4, #100] + WORD $0xb90064bf // str wzr, [x5, #100] + WORD $0xb900645f // str wzr, [x2, #100] + WORD $0xb900647f // str wzr, [x3, #100] + WORD $0xb90064df // str wzr, [x6, #100] + WORD $0xb900699f // str wzr, [x12, #104] + WORD $0xb9006a3f // str wzr, [x17, #104] + WORD $0xb900697f // str wzr, [x11, #104] + WORD $0xb90069ff // str wzr, [x15, #104] + WORD $0xb900695f // str wzr, [x10, #104] + WORD $0xb90069bf // str wzr, [x13, #104] + WORD $0xb90069df // str wzr, [x14, #104] + WORD $0xb9006a5f // str wzr, [x18, #104] + WORD $0xb9006a1f // str wzr, [x16, #104] + WORD $0xb900681f // str wzr, [x0, #104] + WORD $0xb9006a9f // str wzr, [x20, #104] + WORD $0xb900689f // str wzr, [x4, #104] + WORD $0xb90068bf // str wzr, [x5, #104] + WORD $0xb900685f // str wzr, [x2, #104] + WORD $0xb900687f // str wzr, [x3, #104] + WORD $0xb90068df // str wzr, [x6, #104] + WORD $0xb9006d9f // str wzr, [x12, #108] + WORD $0xb9006e3f // str wzr, [x17, #108] + WORD $0xb9006d7f // str wzr, [x11, #108] + WORD $0xb9006dff // str wzr, [x15, #108] + WORD $0xb9006d5f // str wzr, [x10, #108] + WORD $0xb9006dbf // str wzr, [x13, #108] + WORD $0xb9006ddf // str wzr, [x14, #108] + WORD $0xb9006e5f // str wzr, [x18, #108] + WORD $0xb9006e1f // str wzr, [x16, #108] + WORD $0xb9006c1f // str wzr, [x0, #108] + WORD $0xb9006e9f // str wzr, [x20, #108] + WORD $0xb9006c9f // str wzr, [x4, #108] + WORD $0xb9006cbf // str wzr, [x5, #108] + WORD $0xb9006c5f // str wzr, [x2, #108] + WORD $0xb9006c7f // str wzr, [x3, #108] + WORD $0xb9006cdf // str wzr, [x6, #108] + WORD $0xb900719f // str wzr, [x12, #112] + WORD $0xb900723f // str wzr, [x17, #112] + WORD $0xb900717f // str wzr, [x11, #112] + WORD $0xb90071ff // str wzr, [x15, #112] + WORD $0xb900715f // str wzr, [x10, #112] + WORD $0xb90071bf // str wzr, [x13, #112] + WORD $0xb90071df // str wzr, [x14, #112] + WORD $0xb900725f // str wzr, [x18, #112] + WORD $0xb900721f // str wzr, [x16, #112] + WORD $0xb900701f // str wzr, [x0, #112] + WORD $0xb900729f // str wzr, [x20, #112] + WORD $0xb900709f // str wzr, [x4, #112] + WORD $0xb90070bf // str wzr, [x5, #112] + WORD $0xb900705f // str wzr, [x2, #112] + WORD $0xb900707f // str wzr, [x3, #112] + WORD $0xb90070df // str wzr, [x6, #112] + WORD $0xb900759f // str wzr, [x12, #116] + WORD $0xb900763f // str wzr, [x17, #116] + WORD $0xb900757f // str wzr, [x11, #116] + WORD $0xb90075ff // str wzr, [x15, #116] + WORD $0xb900755f // str wzr, [x10, #116] + WORD $0xb90075bf // str wzr, [x13, #116] + WORD $0xb90075df // str wzr, [x14, #116] + WORD $0xb900765f // str wzr, [x18, #116] + WORD $0xb900761f // str wzr, [x16, #116] + WORD $0xb900741f // str wzr, [x0, #116] + WORD $0xb900769f // str wzr, [x20, #116] + WORD $0xb900749f // str wzr, [x4, #116] + WORD $0xb90074bf // str wzr, [x5, #116] + WORD $0xb900745f // str wzr, [x2, #116] + WORD $0xb900747f // str wzr, [x3, #116] + WORD $0xb90074df // str wzr, [x6, #116] + WORD $0xb900799f // str wzr, [x12, #120] + WORD $0xb9007a3f // str wzr, [x17, #120] + WORD $0xb900797f // str wzr, [x11, #120] + WORD $0xb90079ff // str wzr, [x15, #120] + WORD $0xb900795f // str wzr, [x10, #120] + WORD $0xb90079bf // str wzr, [x13, #120] + WORD $0xb90079df // str wzr, [x14, #120] + WORD $0xb9007a5f // str wzr, [x18, #120] + WORD $0xb9007a1f // str wzr, [x16, #120] + WORD $0xb900781f // str wzr, [x0, #120] + WORD $0xb9007a9f // str wzr, [x20, #120] + WORD $0xb900789f // str wzr, [x4, #120] + WORD $0xb90078bf // str wzr, [x5, #120] + WORD $0xb900785f // str wzr, [x2, #120] + WORD $0xb900787f // str wzr, [x3, #120] + WORD $0xb90078df // str wzr, [x6, #120] + WORD $0xb9007d9f // str wzr, [x12, #124] + WORD $0xb9007e3f // str wzr, [x17, #124] + WORD $0xb9007d7f // str wzr, [x11, #124] + WORD $0xb9007dff // str wzr, [x15, #124] + WORD $0xb9007d5f // str wzr, [x10, #124] + WORD $0xb9007dbf // str wzr, [x13, #124] + WORD $0xb9007ddf // str wzr, [x14, #124] + WORD $0xb9007e5f // str wzr, [x18, #124] + WORD $0xb9007e1f // str wzr, [x16, #124] + WORD $0xb9007c1f // str wzr, [x0, #124] + WORD $0xb9007e9f // str wzr, [x20, #124] + WORD $0xb9007c9f // str wzr, [x4, #124] + WORD $0xb9007cbf // str wzr, [x5, #124] + WORD $0xb9007c5f // str wzr, [x2, #124] + WORD $0xb9007c7f // str wzr, [x3, #124] + WORD $0xb9007cdf // str wzr, [x6, #124] + BNE LBB0_152 + + // %bb.153: + WORD $0xeb13011f // cmp x8, x19 + BEQ LBB0_156 + +LBB0_154: + WORD $0x8b081f49 // add x9, x26, x8, lsl #7 + WORD $0xcb080268 // sub x8, x19, x8 + WORD $0x6f00e400 // movi v0.2d, #0000000000000000 + WORD $0x91010129 // add x9, x9, #64 + +LBB0_155: + WORD $0xad3e0120 // stp q0, q0, [x9, #-64] + WORD $0xf1000508 // subs x8, x8, #1 + WORD $0xad3f0120 // stp q0, q0, [x9, #-32] + WORD $0xad000120 // stp q0, q0, [x9] + WORD $0xad010120 // stp q0, q0, [x9, #32] + WORD $0x91020129 // add x9, x9, #128 + BNE LBB0_155 + +LBB0_157: + // WORD $0x90000008 // adrp x8, .LCPI0_0 + // WORD $0x90000009 // adrp x9, .LCPI0_1 + // WORD $0x9000000a // adrp x10, .LCPI0_2 + // WORD $0x9000000b // adrp x11, .LCPI0_3 + WORD $0xaa1f03ec // mov x12, xzr + WORD $0xf9000bf3 // str x19, [sp, #16] + VMOVQ LCPI0_0L, LCPI0_0H, V0 + // WORD $0x90000008 // adrp x8, .LCPI0_4 + VMOVQ LCPI0_1L, LCPI0_1H, V1 + // WORD $0x90000009 // adrp x9, .LCPI0_5 + VMOVQ LCPI0_2L, LCPI0_2H, V2 + // WORD $0x9000000a // adrp x10, .LCPI0_6 + VMOVQ LCPI0_4L, LCPI0_4H, V4 + // WORD $0x90000008 // adrp x8, .LCPI0_7 + VMOVQ LCPI0_3L, LCPI0_3H, V3 + WORD $0x927c6e6b // and x11, x19, #0xfffffff0 + VMOVQ LCPI0_5L, LCPI0_5H, V5 + WORD $0xf90047fa // str x26, [sp, #136] + VMOVQ LCPI0_7L, LCPI0_7H, V7 + WORD $0x52800208 // mov w8, #16 + VMOVQ LCPI0_6L, LCPI0_6H, V6 + WORD $0x8b0b1c09 // add x9, x0, x11, lsl #7 + WORD $0xf9000feb // str x11, [sp, #24] + WORD $0x4e080d10 // dup v16.2d, x8 + WORD $0xf90007e9 // str x9, [sp, #8] + +LBB0_158: + WORD $0x4f4554f2 // shl v18.2d, v7.2d, #5 + WORD $0xd379e188 // lsl x8, x12, #7 + WORD $0x4f4554d3 // shl v19.2d, v6.2d, #5 + WORD $0xb278010b // orr x11, x8, #0x100 + WORD $0x4f4554b4 // shl v20.2d, v5.2d, #5 + WORD $0xf90043ec // str x12, [sp, #128] + WORD $0x8b0b0010 // add x16, x0, x11 + WORD $0x8b080003 // add x3, x0, x8 + WORD $0x4e183e4b // mov x11, v18.d[1] + WORD $0x9e66024c // fmov x12, d18 + WORD $0x4f455492 // shl v18.2d, v4.2d, #5 + WORD $0xb279010a // orr x10, x8, #0x80 + WORD $0x4e183e6d // mov x13, v19.d[1] + WORD $0x8b0a0014 // add x20, x0, x10 + WORD $0x8b0c0b49 // add x9, x26, x12, lsl #2 + WORD $0x9e66028c // fmov x12, d20 + WORD $0x8b0b0b5b // add x27, x26, x11, lsl #2 + WORD $0xb279050a // orr x10, x8, #0x180 + WORD $0x4e183e8b // mov x11, v20.d[1] + WORD $0x9e66026e // fmov x14, d19 + WORD $0x9e66024f // fmov x15, d18 + WORD $0x8b0a0013 // add x19, x0, x10 + WORD $0xb277010a // orr x10, x8, #0x200 + WORD $0x8b0d0b57 // add x23, x26, x13, lsl #2 + WORD $0x8b0c0b5c // add x28, x26, x12, lsl #2 + WORD $0x8b0a0011 // add x17, x0, x10 + WORD $0x2940306d // ldp w13, w12, [x3] + WORD $0x5280500a // mov w10, #640 + WORD $0x8b0e0b41 // add x1, x26, x14, lsl #2 + WORD $0xaa0a010a // orr x10, x8, x10 + WORD $0xf900bbe3 // str x3, [sp, #368] + WORD $0x2940168e // ldp w14, w5, [x20] + WORD $0x8b0b0b43 // add x3, x26, x11, lsl #2 + WORD $0x8b0f0b44 // add x4, x26, x15, lsl #2 + WORD $0x29403e0b // ldp w11, w15, [x16] + WORD $0x8b0a0006 // add x6, x0, x10 + WORD $0xb90057ec // str w12, [sp, #84] + WORD $0x4e183e4c // mov x12, v18.d[1] + WORD $0xb278050a // orr x10, x8, #0x300 + WORD $0x8b0a0007 // add x7, x0, x10 + WORD $0xb900012d // str w13, [x9] + WORD $0xb900036e // str w14, [x27] + WORD $0xb279090a // orr x10, x8, #0x380 + WORD $0xb900002b // str w11, [x1] + WORD $0x29402ccd // ldp w13, w11, [x6] + WORD $0x4f455471 // shl v17.2d, v3.2d, #5 + WORD $0xa91453f0 // stp x16, x20, [sp, #320] + WORD $0x290f17ef // stp w15, w5, [sp, #120] + WORD $0x8b0c0b45 // add x5, x26, x12, lsl #2 + WORD $0x2940426c // ldp w12, w16, [x19] + WORD $0x8b0a0012 // add x18, x0, x10 + WORD $0xf9009ff3 // str x19, [sp, #312] + WORD $0xaa1103f3 // mov x19, x17 + WORD $0xa9181ff1 // stp x17, x7, [sp, #384] + WORD $0xb9400231 // ldr w17, [x17] + WORD $0xb90067eb // str w11, [sp, #100] + WORD $0xb276010a // orr x10, x8, #0x400 + WORD $0xb94000eb // ldr w11, [x7] + WORD $0x8b0a0002 // add x2, x0, x10 + WORD $0xb90077f0 // str w16, [sp, #116] + WORD $0x9e660230 // fmov x16, d17 + WORD $0xb90002ec // str w12, [x23] + WORD $0xb94004ee // ldr w14, [x7, #4] + WORD $0xb9000391 // str w17, [x28] + WORD $0x5280900a // mov w10, #1152 + WORD $0xb900006d // str w13, [x3] + WORD $0xaa0a010a // orr x10, x8, x10 + WORD $0xb900008b // str w11, [x4] + WORD $0x29402e4c // ldp w12, w11, [x18] + WORD $0x4e183e2f // mov x15, v17.d[1] + WORD $0x8b100b4d // add x13, x26, x16, lsl #2 + WORD $0xa90c27f7 // stp x23, x9, [sp, #192] + WORD $0x290bbbeb // stp w11, w14, [sp, #92] + WORD $0xb940004b // ldr w11, [x2] + WORD $0x8b0a000e // add x14, x0, x10 + WORD $0x5280a00a // mov w10, #1280 + WORD $0x4f455451 // shl v17.2d, v2.2d, #5 + WORD $0xf9004fed // str x13, [sp, #152] + WORD $0xb90000ac // str w12, [x5] + WORD $0xaa0a010a // orr x10, x8, x10 + WORD $0xb90001ab // str w11, [x13] + WORD $0xb9400669 // ldr w9, [x19, #4] + WORD $0x294035cb // ldp w11, w13, [x14] + WORD $0x8b0a0011 // add x17, x0, x10 + WORD $0x8b0f0b4c // add x12, x26, x15, lsl #2 + WORD $0x9e660230 // fmov x16, d17 + WORD $0x5280b00a // mov w10, #1408 + WORD $0xaa0a010a // orr x10, x8, x10 + WORD $0xb9006fe9 // str w9, [sp, #108] + WORD $0xaa0103e9 // mov x9, x1 + WORD $0xaa0603e1 // mov x1, x6 + WORD $0xa911cbe6 // stp x6, x18, [sp, #280] + WORD $0x8b0a0006 // add x6, x0, x10 + WORD $0xf9006fec // str x12, [sp, #216] + WORD $0xb9400452 // ldr w18, [x2, #4] + WORD $0x4e183e2f // mov x15, v17.d[1] + WORD $0xb900018b // str w11, [x12] + WORD $0x4f455431 // shl v17.2d, v1.2d, #5 + WORD $0x8b100b4c // add x12, x26, x16, lsl #2 + WORD $0x2940422a // ldp w10, w16, [x17] + WORD $0xb277050b // orr x11, x8, #0x600 + WORD $0xaa0c03fe // mov x30, x12 + WORD $0x8b0b000b // add x11, x0, x11 + WORD $0xf90073ec // str x12, [sp, #224] + WORD $0x2909cbed // stp w13, w18, [sp, #76] + WORD $0x8b0f0b4d // add x13, x26, x15, lsl #2 + WORD $0xb900018a // str w10, [x12] + WORD $0x9e66022a // fmov x10, d17 + WORD $0x294030cf // ldp w15, w12, [x6] + WORD $0xaa0e03f3 // mov x19, x14 + WORD $0xf900b3ee // str x14, [sp, #352] + WORD $0x8b0a0b4e // add x14, x26, x10, lsl #2 + WORD $0xb940016a // ldr w10, [x11] + WORD $0xb9006bec // str w12, [sp, #104] + WORD $0xaa0b03ec // mov x12, x11 + WORD $0x5280d00b // mov w11, #1664 + WORD $0xb90001af // str w15, [x13] + WORD $0xaa0d03f9 // mov x25, x13 + WORD $0xf9005fed // str x13, [sp, #184] + WORD $0xaa0b010d // orr x13, x8, x11 + WORD $0xb90073f0 // str w16, [sp, #112] + WORD $0x8b0d0012 // add x18, x0, x13 + WORD $0xb90001ca // str w10, [x14] + WORD $0x4e183e30 // mov x16, v17.d[1] + WORD $0xb278090a // orr x10, x8, #0x700 + WORD $0x4f455412 // shl v18.2d, v0.2d, #5 + WORD $0xb2790d08 // orr x8, x8, #0x780 + WORD $0xf90053e5 // str x5, [sp, #160] + WORD $0xb940058b // ldr w11, [x12, #4] + WORD $0xaa0c03f6 // mov x22, x12 + WORD $0xf9009bec // str x12, [sp, #304] + WORD $0x8b08000c // add x12, x0, x8 + WORD $0x8b0a0007 // add x7, x0, x10 + WORD $0x29401648 // ldp w8, w5, [x18] + WORD $0x8b100b4d // add x13, x26, x16, lsl #2 + WORD $0xf90077e3 // str x3, [sp, #232] + WORD $0x9e660243 // fmov x3, d18 + WORD $0xf900abe2 // str x2, [sp, #336] + WORD $0x4e183e42 // mov x2, v18.d[1] + WORD $0xb9005beb // str w11, [sp, #88] + WORD $0xf94047eb // ldr x11, [sp, #136] + WORD $0xb90001a8 // str w8, [x13] + WORD $0x294040ea // ldp w10, w16, [x7] + WORD $0xa9103be4 // stp x4, x14, [sp, #256] + WORD $0xb9400588 // ldr w8, [x12, #4] + WORD $0x8b030b4e // add x14, x26, x3, lsl #2 + WORD $0xa94c0fe4 // ldp x4, x3, [sp, #192] + WORD $0x8b02096f // add x15, x11, x2, lsl #2 + WORD $0x290843e8 // stp w8, w16, [sp, #64] + WORD $0xb940018b // ldr w11, [x12] + WORD $0xb90001ca // str w10, [x14] + WORD $0xb94057e8 // ldr w8, [sp, #84] + WORD $0xf90097f1 // str x17, [sp, #296] + WORD $0xf940a3f1 // ldr x17, [sp, #320] + WORD $0xaa1203f7 // mov x23, x18 + WORD $0xb90001eb // str w11, [x15] + WORD $0xf94077eb // ldr x11, [sp, #232] + WORD $0xb9000468 // str w8, [x3, #4] + WORD $0xb9400a88 // ldr w8, [x20, #8] + WORD $0xaa0903f4 // mov x20, x9 + WORD $0xf900b7f2 // str x18, [sp, #360] + WORD $0xa9580bf2 // ldp x18, x2, [sp, #384] + WORD $0xb90057e8 // str w8, [sp, #84] + WORD $0xaa0d03f8 // mov x24, x13 + WORD $0xb9407fe8 // ldr w8, [sp, #124] + WORD $0xf900bfec // str x12, [sp, #376] + WORD $0xa95243ed // ldp x13, x16, [sp, #288] + WORD $0xaa0f03fa // mov x26, x15 + WORD $0xf9006bef // str x15, [sp, #208] + WORD $0xb9000768 // str w8, [x27, #4] + WORD $0xb9400a28 // ldr w8, [x17, #8] + WORD $0xb9400a4a // ldr w10, [x18, #8] + WORD $0xa90f3bfb // stp x27, x14, [sp, #240] + WORD $0xaa0703f5 // mov x21, x7 + WORD $0xb9004be8 // str w8, [sp, #72] + WORD $0xb9407be8 // ldr w8, [sp, #120] + WORD $0xf940abee // ldr x14, [sp, #336] + WORD $0xa90ae3f4 // stp x20, x24, [sp, #168] + WORD $0xa9501fec // ldp x12, x7, [sp, #256] + WORD $0xf900aff5 // str x21, [sp, #344] + WORD $0xb9000528 // str w8, [x9, #4] + WORD $0xf9409fe8 // ldr x8, [sp, #312] + WORD $0xf9004bfc // str x28, [sp, #144] + WORD $0xb9400909 // ldr w9, [x8, #8] + WORD $0x4ef084a5 // add v5.2d, v5.2d, v16.2d + WORD $0x4ef084c6 // add v6.2d, v6.2d, v16.2d + WORD $0xb90033e9 // str w9, [sp, #48] + WORD $0xb94077e9 // ldr w9, [sp, #116] + WORD $0x4ef084e7 // add v7.2d, v7.2d, v16.2d + WORD $0x4ef08484 // add v4.2d, v4.2d, v16.2d + WORD $0xb9000489 // str w9, [x4, #4] + WORD $0xb9406fe9 // ldr w9, [sp, #108] + WORD $0x4ef08463 // add v3.2d, v3.2d, v16.2d + WORD $0x4ef08442 // add v2.2d, v2.2d, v16.2d + WORD $0xb9000789 // str w9, [x28, #4] + WORD $0xb9400829 // ldr w9, [x1, #8] + WORD $0xf9406fe1 // ldr x1, [sp, #216] + WORD $0x4ef08421 // add v1.2d, v1.2d, v16.2d + WORD $0x29072be9 // stp w9, w10, [sp, #56] + WORD $0xb94067e9 // ldr w9, [sp, #100] + WORD $0xa949abef // ldp x15, x10, [sp, #152] + WORD $0x4ef08400 // add v0.2d, v0.2d, v16.2d + WORD $0xb9000569 // str w9, [x11, #4] + WORD $0xb9400849 // ldr w9, [x2, #8] + WORD $0xb9007be9 // str w9, [sp, #120] + WORD $0xb94063e9 // ldr w9, [sp, #96] + WORD $0xb9000589 // str w9, [x12, #4] + WORD $0xb94009a9 // ldr w9, [x13, #8] + WORD $0xb90037e9 // str w9, [sp, #52] + WORD $0xb9405fe9 // ldr w9, [sp, #92] + WORD $0xb9000549 // str w9, [x10, #4] + WORD $0xb94009c9 // ldr w9, [x14, #8] + WORD $0xb9005fe9 // str w9, [sp, #92] + WORD $0xb94053e9 // ldr w9, [sp, #80] + WORD $0xb90005e9 // str w9, [x15, #4] + WORD $0xb9400a69 // ldr w9, [x19, #8] + WORD $0xb94047f3 // ldr w19, [sp, #68] + WORD $0xb90067e9 // str w9, [sp, #100] + WORD $0xb9404fe9 // ldr w9, [sp, #76] + WORD $0xb9000429 // str w9, [x1, #4] + WORD $0xb9400a09 // ldr w9, [x16, #8] + WORD $0xb90077e9 // str w9, [sp, #116] + WORD $0xb94073e9 // ldr w9, [sp, #112] + WORD $0xb90007c9 // str w9, [x30, #4] + WORD $0xb9406be9 // ldr w9, [sp, #104] + WORD $0xb94008de // ldr w30, [x6, #8] + WORD $0xb9000729 // str w9, [x25, #4] + WORD $0xb9400ac9 // ldr w9, [x22, #8] + WORD $0xaa1803f6 // mov x22, x24 + WORD $0xb9007fe9 // str w9, [sp, #124] + WORD $0xb9405be9 // ldr w9, [sp, #88] + WORD $0xb90004e9 // str w9, [x7, #4] + WORD $0xb9400ae9 // ldr w9, [x23, #8] + WORD $0xf9407ff7 // ldr x23, [sp, #248] + WORD $0xb9000705 // str w5, [x24, #4] + WORD $0xaa1503f8 // mov x24, x21 + WORD $0xb9006be9 // str w9, [sp, #104] + WORD $0xf940bbe9 // ldr x9, [sp, #368] + WORD $0xb90006f3 // str w19, [x23, #4] + WORD $0xb9400ab3 // ldr w19, [x21, #8] + WORD $0xf9408ff5 // ldr x21, [sp, #280] + WORD $0x29416525 // ldp w5, w25, [x9, #8] + WORD $0xb90073f3 // str w19, [sp, #112] + WORD $0xb94043f3 // ldr w19, [sp, #64] + WORD $0xb9000753 // str w19, [x26, #4] + WORD $0xaa0f03f3 // mov x19, x15 + WORD $0xb9000865 // str w5, [x3, #8] + WORD $0xf940a7e3 // ldr x3, [sp, #328] + WORD $0xaa0403fa // mov x26, x4 + WORD $0xb9400c69 // ldr w9, [x3, #12] + WORD $0xaa0603e3 // mov x3, x6 + WORD $0xb9006fe9 // str w9, [sp, #108] + WORD $0xb94057e9 // ldr w9, [sp, #84] + WORD $0xb9000b69 // str w9, [x27, #8] + WORD $0xb9404be9 // ldr w9, [sp, #72] + WORD $0xb9400e3b // ldr w27, [x17, #12] + WORD $0xaa0703f1 // mov x17, x7 + WORD $0xb9000a89 // str w9, [x20, #8] + WORD $0xb9400d09 // ldr w9, [x8, #12] + WORD $0xb94033e8 // ldr w8, [sp, #48] + WORD $0xb9000888 // str w8, [x4, #8] + WORD $0xb9400e48 // ldr w8, [x18, #12] + WORD $0xaa0103e4 // mov x4, x1 + WORD $0x2908a7e8 // stp w8, w9, [sp, #68] + WORD $0xb9403fe8 // ldr w8, [sp, #60] + WORD $0xaa0a03e9 // mov x9, x10 + WORD $0xb9000b88 // str w8, [x28, #8] + WORD $0xb9400ea8 // ldr w8, [x21, #12] + WORD $0xb90063e8 // str w8, [sp, #96] + WORD $0xb9403be8 // ldr w8, [sp, #56] + WORD $0xb9000968 // str w8, [x11, #8] + WORD $0xb9407be8 // ldr w8, [sp, #120] + WORD $0xb9400c4b // ldr w11, [x2, #12] + WORD $0xaa1003e2 // mov x2, x16 + WORD $0xb9000988 // str w8, [x12, #8] + WORD $0xb9400da8 // ldr w8, [x13, #12] + WORD $0xf94073ec // ldr x12, [sp, #224] + WORD $0xb9407fed // ldr w13, [sp, #124] + WORD $0xb9007be8 // str w8, [sp, #120] + WORD $0xb94037e8 // ldr w8, [sp, #52] + WORD $0xb9000948 // str w8, [x10, #8] + WORD $0xb9400dc8 // ldr w8, [x14, #12] + WORD $0xf940b3ea // ldr x10, [sp, #352] + WORD $0x290623eb // stp w11, w8, [sp, #48] + WORD $0xb9405fe8 // ldr w8, [sp, #92] + WORD $0xb9400e0b // ldr w11, [x16, #12] + WORD $0xb90009e8 // str w8, [x15, #8] + WORD $0xb9400d48 // ldr w8, [x10, #12] + WORD $0xb9002fe8 // str w8, [sp, #44] + WORD $0xb94067e8 // ldr w8, [sp, #100] + WORD $0xb9000828 // str w8, [x1, #8] + WORD $0xb94077e8 // ldr w8, [sp, #116] + WORD $0xaa1703e1 // mov x1, x23 + WORD $0xb9000988 // str w8, [x12, #8] + WORD $0xb9400cc8 // ldr w8, [x6, #12] + WORD $0x290aafe8 // stp w8, w11, [sp, #84] + WORD $0xf9405feb // ldr x11, [sp, #184] + WORD $0xf9409be8 // ldr x8, [sp, #304] + WORD $0xb900097e // str w30, [x11, #8] + WORD $0xf940b7fe // ldr x30, [sp, #360] + WORD $0xb9400d0f // ldr w15, [x8, #12] + WORD $0xb90008ed // str w13, [x7, #8] + WORD $0xf940bfed // ldr x13, [sp, #376] + WORD $0xb9400fce // ldr w14, [x30, #12] + WORD $0xf940a7e7 // ldr x7, [sp, #328] + WORD $0xb94009a5 // ldr w5, [x13, #8] + WORD $0x2909bfee // stp w14, w15, [sp, #76] + WORD $0xb9406bee // ldr w14, [sp, #104] + WORD $0xb94010ef // ldr w15, [x7, #16] + WORD $0xb9000ace // str w14, [x22, #8] + WORD $0xb9400f0e // ldr w14, [x24, #12] + WORD $0xa94ec3f6 // ldp x22, x16, [sp, #232] + WORD $0xb9006bee // str w14, [sp, #104] + WORD $0xb9400db8 // ldr w24, [x13, #12] + WORD $0x294dbbed // ldp w13, w14, [sp, #108] + WORD $0xb9000aee // str w14, [x23, #8] + WORD $0xa94cdff2 // ldp x18, x23, [sp, #200] + WORD $0xb9000ae5 // str w5, [x23, #8] + WORD $0xb9000e59 // str w25, [x18, #12] + WORD $0xb9000e0d // str w13, [x16, #12] + WORD $0xa953b7e5 // ldp x5, x13, [sp, #312] + WORD $0xb9000e9b // str w27, [x20, #12] + WORD $0xf940c3fb // ldr x27, [sp, #384] + WORD $0xb94011ae // ldr w14, [x13, #16] + WORD $0x29073fee // stp w14, w15, [sp, #56] + WORD $0xb94010ae // ldr w14, [x5, #16] + WORD $0xb94012af // ldr w15, [x21, #16] + WORD $0xb90067ee // str w14, [sp, #100] + WORD $0xb9404bee // ldr w14, [sp, #72] + WORD $0xb90043ef // str w15, [sp, #64] + WORD $0xb94063ef // ldr w15, [sp, #96] + WORD $0xb9000f4e // str w14, [x26, #12] + WORD $0xb940136e // ldr w14, [x27, #16] + WORD $0xb9005fee // str w14, [sp, #92] + WORD $0xb94047ee // ldr w14, [sp, #68] + WORD $0xb9000f8e // str w14, [x28, #12] + WORD $0xaa1503ee // mov x14, x21 + WORD $0xb9000ecf // str w15, [x22, #12] + WORD $0xf940c7ef // ldr x15, [sp, #392] + WORD $0xf94083f5 // ldr x21, [sp, #256] + WORD $0xb94011e6 // ldr w6, [x15, #16] + WORD $0xb9006fe6 // str w6, [sp, #108] + WORD $0xb94033e6 // ldr w6, [sp, #48] + WORD $0xb9000ea6 // str w6, [x21, #12] + WORD $0xf94093e6 // ldr x6, [sp, #288] + WORD $0xb94010d9 // ldr w25, [x6, #16] + WORD $0xb90047f9 // str w25, [sp, #68] + WORD $0xb9407bf9 // ldr w25, [sp, #120] + WORD $0xb9000d39 // str w25, [x9, #12] + WORD $0xf940abf9 // ldr x25, [sp, #336] + WORD $0xb9401329 // ldr w9, [x25, #16] + WORD $0xb90077e9 // str w9, [sp, #116] + WORD $0xb94037e9 // ldr w9, [sp, #52] + WORD $0xb9000e69 // str w9, [x19, #12] + WORD $0xb9401149 // ldr w9, [x10, #16] + WORD $0xf940bbea // ldr x10, [sp, #368] + WORD $0xaa1603f3 // mov x19, x22 + WORD $0xb90063e9 // str w9, [sp, #96] + WORD $0xb9402fe9 // ldr w9, [sp, #44] + WORD $0xb9000c89 // str w9, [x4, #12] + WORD $0xb9401049 // ldr w9, [x2, #16] + WORD $0xb9401544 // ldr w4, [x10, #20] + WORD $0xaa1403e2 // mov x2, x20 + WORD $0xb9004be9 // str w9, [sp, #72] + WORD $0xb9405be9 // ldr w9, [sp, #88] + WORD $0xb9000d89 // str w9, [x12, #12] + WORD $0xb9401069 // ldr w9, [x3, #16] + WORD $0xaa0303ec // mov x12, x3 + WORD $0xaa0b03e3 // mov x3, x11 + WORD $0xb90073e9 // str w9, [sp, #112] + WORD $0xb94057e9 // ldr w9, [sp, #84] + WORD $0xf9008bec // str x12, [sp, #272] + WORD $0xb9000d69 // str w9, [x11, #12] + WORD $0xb9401109 // ldr w9, [x8, #16] + WORD $0xb94053e8 // ldr w8, [sp, #80] + WORD $0xb9406beb // ldr w11, [sp, #104] + WORD $0xb9000e28 // str w8, [x17, #12] + WORD $0xb94013c8 // ldr w8, [x30, #16] + WORD $0xf94087fe // ldr x30, [sp, #264] + WORD $0x290f23e9 // stp w9, w8, [sp, #120] + WORD $0xf9405be9 // ldr x9, [sp, #176] + WORD $0xb9404fe8 // ldr w8, [sp, #76] + WORD $0xb9000d28 // str w8, [x9, #12] + WORD $0xb9401148 // ldr w8, [x10, #16] + WORD $0xb9000c2b // str w11, [x1, #12] + WORD $0xb94015aa // ldr w10, [x13, #20] + WORD $0xb9000ef8 // str w24, [x23, #12] + WORD $0xb940172d // ldr w13, [x25, #20] + WORD $0xb9001248 // str w8, [x18, #16] + WORD $0xb94014e8 // ldr w8, [x7, #20] + WORD $0xa9559fe1 // ldp x1, x7, [sp, #344] + WORD $0xaa0503eb // mov x11, x5 + WORD $0xb9006be8 // str w8, [sp, #104] + WORD $0xb9403fe8 // ldr w8, [sp, #60] + WORD $0xb9401031 // ldr w17, [x1, #16] + WORD $0xb9001208 // str w8, [x16, #16] + WORD $0xb9403be8 // ldr w8, [sp, #56] + WORD $0xb94014d0 // ldr w16, [x6, #20] + WORD $0xb9001288 // str w8, [x20, #16] + WORD $0xb94014a8 // ldr w8, [x5, #20] + WORD $0x2909c3ed // stp w13, w16, [sp, #76] + WORD $0xb94077ed // ldr w13, [sp, #116] + WORD $0xaa0f03e5 // mov x5, x15 + WORD $0xf940bff0 // ldr x16, [sp, #376] + WORD $0x29062be8 // stp w8, w10, [sp, #48] + WORD $0xb94067e8 // ldr w8, [sp, #100] + WORD $0xb94015ca // ldr w10, [x14, #20] + WORD $0xb9001348 // str w8, [x26, #16] + WORD $0xb9401768 // ldr w8, [x27, #20] + WORD $0xaa0903fb // mov x27, x9 + WORD $0xb9407fe9 // ldr w9, [sp, #124] + WORD $0xb9002fe8 // str w8, [sp, #44] + WORD $0xb9405fe8 // ldr w8, [sp, #92] + WORD $0xb9001388 // str w8, [x28, #16] + WORD $0xb94043e8 // ldr w8, [sp, #64] + WORD $0xaa0e03fc // mov x28, x14 + WORD $0xa94dbbf8 // ldp x24, x14, [sp, #216] + WORD $0xb90012c8 // str w8, [x22, #16] + WORD $0xb94015e8 // ldr w8, [x15, #20] + WORD $0xa949dff6 // ldp x22, x23, [sp, #152] + WORD $0x290aabe8 // stp w8, w10, [sp, #84] + WORD $0xb9406fe8 // ldr w8, [sp, #108] + WORD $0xb94047ea // ldr w10, [sp, #68] + WORD $0xa952bff4 // ldp x20, x15, [sp, #296] + WORD $0xb90012a8 // str w8, [x21, #16] + WORD $0xaa0603e8 // mov x8, x6 + WORD $0xb90012ea // str w10, [x23, #16] + WORD $0xaa1903ea // mov x10, x25 + WORD $0xb90012cd // str w13, [x22, #16] + WORD $0xb94014ed // ldr w13, [x7, #20] + WORD $0xa94f67fa // ldp x26, x25, [sp, #240] + WORD $0xb90077ed // str w13, [sp, #116] + WORD $0xb94063ed // ldr w13, [sp, #96] + WORD $0xb900130d // str w13, [x24, #16] + WORD $0xb940168d // ldr w13, [x20, #20] + WORD $0xb9003fed // str w13, [sp, #60] + WORD $0xb9404bed // ldr w13, [sp, #72] + WORD $0xb90011cd // str w13, [x14, #16] + WORD $0xb940158d // ldr w13, [x12, #20] + WORD $0xb90067ed // str w13, [sp, #100] + WORD $0xb94073ed // ldr w13, [sp, #112] + WORD $0xb900106d // str w13, [x3, #16] + WORD $0xb94015ed // ldr w13, [x15, #20] + WORD $0xb9401203 // ldr w3, [x16, #16] + WORD $0xb9004bed // str w13, [sp, #72] + WORD $0xb9407bed // ldr w13, [sp, #120] + WORD $0xb90013cd // str w13, [x30, #16] + WORD $0xf940b7ed // ldr x13, [sp, #360] + WORD $0xb9001369 // str w9, [x27, #16] + WORD $0xb9401429 // ldr w9, [x1, #20] + WORD $0xb9001331 // str w17, [x25, #16] + WORD $0xaa1403e1 // mov x1, x20 + WORD $0xb94015a6 // ldr w6, [x13, #20] + WORD $0xb9007fe9 // str w9, [sp, #124] + WORD $0xb9003be6 // str w6, [sp, #56] + WORD $0xb9401606 // ldr w6, [x16, #20] + WORD $0xf9406bf0 // ldr x16, [sp, #208] + WORD $0xb9001203 // str w3, [x16, #16] + WORD $0xa95447e3 // ldp x3, x17, [sp, #320] + WORD $0xb9001644 // str w4, [x18, #20] + WORD $0xaa0d03e4 // mov x4, x13 + WORD $0xb9401a29 // ldr w9, [x17, #24] + WORD $0xb90073e9 // str w9, [sp, #112] + WORD $0xb9406be9 // ldr w9, [sp, #104] + WORD $0xb9001749 // str w9, [x26, #20] + WORD $0xb9401869 // ldr w9, [x3, #24] + WORD $0xb9005fe9 // str w9, [sp, #92] + WORD $0xb94037e9 // ldr w9, [sp, #52] + WORD $0xb9001449 // str w9, [x2, #20] + WORD $0xb9401969 // ldr w9, [x11, #24] + WORD $0xf94063e2 // ldr x2, [sp, #192] + WORD $0xf940c3eb // ldr x11, [sp, #384] + WORD $0xb9006fe9 // str w9, [sp, #108] + WORD $0xb94033e9 // ldr w9, [sp, #48] + WORD $0xb9001449 // str w9, [x2, #20] + WORD $0xb9401969 // ldr w9, [x11, #24] + WORD $0xf9404beb // ldr x11, [sp, #144] + WORD $0xb9006be9 // str w9, [sp, #104] + WORD $0xb9402fe9 // ldr w9, [sp, #44] + WORD $0xb9001569 // str w9, [x11, #20] + WORD $0xb9401b89 // ldr w9, [x28, #24] + WORD $0xf940bbfc // ldr x28, [sp, #368] + WORD $0xb90063e9 // str w9, [sp, #96] + WORD $0xb9405be9 // ldr w9, [sp, #88] + WORD $0xb9001669 // str w9, [x19, #20] + WORD $0xb94018a9 // ldr w9, [x5, #24] + WORD $0xaa1803e5 // mov x5, x24 + WORD $0xaa1603f3 // mov x19, x22 + WORD $0xb9005be9 // str w9, [sp, #88] + WORD $0xb94057e9 // ldr w9, [sp, #84] + WORD $0xb90016a9 // str w9, [x21, #20] + WORD $0xb9401909 // ldr w9, [x8, #24] + WORD $0xb94053e8 // ldr w8, [sp, #80] + WORD $0xaa1203f5 // mov x21, x18 + WORD $0xb90016e8 // str w8, [x23, #20] + WORD $0xb9401948 // ldr w8, [x10, #24] + WORD $0xb940198a // ldr w10, [x12, #24] + WORD $0xf940afec // ldr x12, [sp, #344] + WORD $0x290a27e8 // stp w8, w9, [sp, #80] + WORD $0xb9404fe8 // ldr w8, [sp, #76] + WORD $0xb94018e9 // ldr w9, [x7, #24] + WORD $0xb90016c8 // str w8, [x22, #20] + WORD $0xb94077e8 // ldr w8, [sp, #116] + WORD $0xb9001708 // str w8, [x24, #20] + WORD $0xb9401a88 // ldr w8, [x20, #24] + WORD $0xa9585ff8 // ldp x24, x23, [sp, #384] + WORD $0xaa0203f4 // mov x20, x2 + WORD $0x290827e8 // stp w8, w9, [sp, #64] + WORD $0xb9403fe8 // ldr w8, [sp, #60] + WORD $0xb94067e9 // ldr w9, [sp, #100] + WORD $0xb90015c8 // str w8, [x14, #20] + WORD $0xf9405fe8 // ldr x8, [sp, #184] + WORD $0xb9405bee // ldr w14, [sp, #88] + WORD $0xb9001509 // str w9, [x8, #20] + WORD $0xb94019e9 // ldr w9, [x15, #24] + WORD $0xf9409fef // ldr x15, [sp, #312] + WORD $0x290ea7ea // stp w10, w9, [sp, #116] + WORD $0xb9404be9 // ldr w9, [sp, #72] + WORD $0xb9401b8a // ldr w10, [x28, #24] + WORD $0xb90017c9 // str w9, [x30, #20] + WORD $0xb94019a9 // ldr w9, [x13, #24] + WORD $0xf94053fe // ldr x30, [sp, #160] + WORD $0xb9004fe9 // str w9, [sp, #76] + WORD $0xb9403be9 // ldr w9, [sp, #56] + WORD $0xb9001769 // str w9, [x27, #20] + WORD $0xb9407fe9 // ldr w9, [sp, #124] + WORD $0xaa0803fb // mov x27, x8 + WORD $0xb9001729 // str w9, [x25, #20] + WORD $0xb9401989 // ldr w9, [x12, #24] + WORD $0xb9001606 // str w6, [x16, #20] + WORD $0xb9401df0 // ldr w16, [x15, #28] + WORD $0xb9001a4a // str w10, [x18, #24] + WORD $0xb9401e2a // ldr w10, [x17, #28] + WORD $0xaa1a03f2 // mov x18, x26 + WORD $0xb9007fe9 // str w9, [sp, #124] + WORD $0xb9401f86 // ldr w6, [x28, #28] + WORD $0xaa1c03e9 // mov x9, x28 + WORD $0xb90067ea // str w10, [sp, #100] + WORD $0xb94073ea // ldr w10, [sp, #112] + WORD $0xaa1103fc // mov x28, x17 + WORD $0xa94e37f9 // ldp x25, x13, [sp, #224] + WORD $0xa951c7f6 // ldp x22, x17, [sp, #280] + WORD $0xb9001b4a // str w10, [x26, #24] + WORD $0xaa0303fa // mov x26, x3 + WORD $0xb9401c6a // ldr w10, [x3, #28] + WORD $0xf94057e3 // ldr x3, [sp, #168] + WORD $0xb9401d8c // ldr w12, [x12, #28] + WORD $0xb9004bea // str w10, [sp, #72] + WORD $0xb9405fea // ldr w10, [sp, #92] + WORD $0xb900186a // str w10, [x3, #24] + WORD $0xb9406fea // ldr w10, [sp, #108] + WORD $0xb900184a // str w10, [x2, #24] + WORD $0xb9401f0a // ldr w10, [x24, #28] + WORD $0xaa0703e2 // mov x2, x7 + WORD $0x2906c3ea // stp w10, w16, [sp, #52] + WORD $0xaa0b03ea // mov x10, x11 + WORD $0xb9406beb // ldr w11, [sp, #104] + WORD $0xb9401ef0 // ldr w16, [x23, #28] + WORD $0xb900194b // str w11, [x10, #24] + WORD $0xb9401ec8 // ldr w8, [x22, #28] + WORD $0xb94063eb // ldr w11, [sp, #96] + WORD $0xb90019ab // str w11, [x13, #24] + WORD $0xf94083eb // ldr x11, [sp, #256] + WORD $0xb900196e // str w14, [x11, #24] + WORD $0xb9401e2e // ldr w14, [x17, #28] + WORD $0x2905bbf0 // stp w16, w14, [sp, #44] + WORD $0xb94057ee // ldr w14, [sp, #84] + WORD $0xb90057ec // str w12, [sp, #84] + WORD $0xf9407fec // ldr x12, [sp, #248] + WORD $0xb9001bce // str w14, [x30, #24] + WORD $0xf940abee // ldr x14, [sp, #336] + WORD $0xb9401dd0 // ldr w16, [x14, #28] + WORD $0xb9003ff0 // str w16, [sp, #60] + WORD $0xb94053f0 // ldr w16, [sp, #80] + WORD $0xb9001a70 // str w16, [x19, #24] + WORD $0xb9401cf0 // ldr w16, [x7, #28] + WORD $0xf9409be7 // ldr x7, [sp, #304] + WORD $0x290b23f0 // stp w16, w8, [sp, #88] + WORD $0xb94047f0 // ldr w16, [sp, #68] + WORD $0xb90018b0 // str w16, [x5, #24] + WORD $0xb9401c30 // ldr w16, [x1, #28] + WORD $0xf9408be5 // ldr x5, [sp, #272] + WORD $0xb90063f0 // str w16, [sp, #96] + WORD $0xb94043f0 // ldr w16, [sp, #64] + WORD $0xb9001b30 // str w16, [x25, #24] + WORD $0xb9401cb0 // ldr w16, [x5, #28] + WORD $0xb90053f0 // str w16, [sp, #80] + WORD $0x294ec3e8 // ldp w8, w16, [sp, #116] + WORD $0xb9001b68 // str w8, [x27, #24] + WORD $0xb9401ce8 // ldr w8, [x7, #28] + WORD $0xb90077e8 // str w8, [sp, #116] + WORD $0xf94087e8 // ldr x8, [sp, #264] + WORD $0xb9001910 // str w16, [x8, #24] + WORD $0xb9401c90 // ldr w16, [x4, #28] + WORD $0xf940bfe8 // ldr x8, [sp, #376] + WORD $0xb9404fe4 // ldr w4, [sp, #76] + WORD $0xb9006bf0 // str w16, [sp, #104] + WORD $0xf9405bf0 // ldr x16, [sp, #176] + WORD $0x29432101 // ldp w1, w8, [x8, #24] + WORD $0xb9001a04 // str w4, [x16, #24] + WORD $0xb9407fe4 // ldr w4, [sp, #124] + WORD $0xb90073e8 // str w8, [sp, #112] + WORD $0xf9406be8 // ldr x8, [sp, #208] + WORD $0xb9001984 // str w4, [x12, #24] + WORD $0xb94067e4 // ldr w4, [sp, #100] + WORD $0xb9001901 // str w1, [x8, #24] + WORD $0xb9402381 // ldr w1, [x28, #32] + WORD $0xb9001ea6 // str w6, [x21, #28] + WORD $0xaa0703f5 // mov x21, x7 + WORD $0xb9001e44 // str w4, [x18, #28] + WORD $0xb9402352 // ldr w18, [x26, #32] + WORD $0xf94097fa // ldr x26, [sp, #296] + WORD $0xb9006fe1 // str w1, [sp, #108] + WORD $0xaa1c03e1 // mov x1, x28 + WORD $0xb9402126 // ldr w6, [x9, #32] + WORD $0xb9007ff2 // str w18, [sp, #124] + WORD $0xb9404bf2 // ldr w18, [sp, #72] + WORD $0xf940affc // ldr x28, [sp, #344] + WORD $0xb9001c72 // str w18, [x3, #28] + WORD $0xb94021f2 // ldr w18, [x15, #32] + WORD $0xb9402384 // ldr w4, [x28, #32] + WORD $0xb90067f2 // str w18, [sp, #100] + WORD $0xaa0f03f2 // mov x18, x15 + WORD $0x2946bfe3 // ldp w3, w15, [sp, #52] + WORD $0xb9001e8f // str w15, [x20, #28] + WORD $0xf94057f4 // ldr x20, [sp, #168] + WORD $0xb9001d43 // str w3, [x10, #28] + WORD $0xaa0a03e3 // mov x3, x10 + WORD $0xb94022ca // ldr w10, [x22, #32] + WORD $0xb940230f // ldr w15, [x24, #32] + WORD $0x29093fea // stp w10, w15, [sp, #72] + WORD $0xb9405fea // ldr w10, [sp, #92] + WORD $0xaa1803ef // mov x15, x24 + WORD $0xaa0203f8 // mov x24, x2 + WORD $0xb9001daa // str w10, [x13, #28] + WORD $0xb94022ea // ldr w10, [x23, #32] + WORD $0xf9406ff7 // ldr x23, [sp, #216] + WORD $0xb9003bea // str w10, [sp, #56] + WORD $0x2945b7ea // ldp w10, w13, [sp, #44] + WORD $0xb9001d6a // str w10, [x11, #28] + WORD $0xb940222a // ldr w10, [x17, #32] + WORD $0xb9001fcd // str w13, [x30, #28] + WORD $0xb94021cd // ldr w13, [x14, #32] + WORD $0xb940204e // ldr w14, [x2, #32] + WORD $0xaa1103eb // mov x11, x17 + WORD $0xb90037ea // str w10, [sp, #52] + WORD $0xaa1e03ea // mov x10, x30 + WORD $0xb9005fed // str w13, [sp, #92] + WORD $0xb9403fed // ldr w13, [sp, #60] + WORD $0xaa1b03f1 // mov x17, x27 + WORD $0xf94087fe // ldr x30, [sp, #264] + WORD $0xaa1903e2 // mov x2, x25 + WORD $0xb940256b // ldr w11, [x11, #36] + WORD $0xb9001e6d // str w13, [x19, #28] + WORD $0xb9405bed // ldr w13, [sp, #88] + WORD $0xb9001eed // str w13, [x23, #28] + WORD $0xb940234d // ldr w13, [x26, #32] + WORD $0xb9005bed // str w13, [sp, #88] + WORD $0xb94063ed // ldr w13, [sp, #96] + WORD $0xb9001f2d // str w13, [x25, #28] + WORD $0xb94020ad // ldr w13, [x5, #32] + WORD $0xaa0503f9 // mov x25, x5 + WORD $0x29083bed // stp w13, w14, [sp, #64] + WORD $0xb94020ee // ldr w14, [x7, #32] + WORD $0xaa0903e7 // mov x7, x9 + WORD $0x294a27ed // ldp w13, w9, [sp, #80] + WORD $0xb9001f6d // str w13, [x27, #28] + WORD $0xb94077ed // ldr w13, [sp, #116] + WORD $0xf940b7fb // ldr x27, [sp, #360] + WORD $0xb94024e5 // ldr w5, [x7, #36] + WORD $0xb9001fcd // str w13, [x30, #28] + WORD $0xb940236d // ldr w13, [x27, #32] + WORD $0x290ebbed // stp w13, w14, [sp, #116] + WORD $0xb9406bed // ldr w13, [sp, #104] + WORD $0xb9006beb // str w11, [sp, #104] + WORD $0xb94037eb // ldr w11, [sp, #52] + WORD $0xb9001e0d // str w13, [x16, #28] + WORD $0xf94083f0 // ldr x16, [sp, #256] + WORD $0xb9001d89 // str w9, [x12, #28] + WORD $0xb940242c // ldr w12, [x1, #36] + WORD $0x294da7ed // ldp w13, w9, [sp, #108] + WORD $0xb90073ec // str w12, [sp, #112] + WORD $0xa94eb3e1 // ldp x1, x12, [sp, #232] + WORD $0xb9001d09 // str w9, [x8, #28] + WORD $0xaa0703e9 // mov x9, x7 + WORD $0xf94067e8 // ldr x8, [sp, #200] + WORD $0xaa0f03e7 // mov x7, x15 + WORD $0xb9002106 // str w6, [x8, #32] + WORD $0xf94063e6 // ldr x6, [sp, #192] + WORD $0xb900218d // str w13, [x12, #32] + WORD $0xf940a3ed // ldr x13, [sp, #320] + WORD $0xb94025ae // ldr w14, [x13, #36] + WORD $0xb90053ee // str w14, [sp, #80] + WORD $0xb9407fee // ldr w14, [sp, #124] + WORD $0xb900228e // str w14, [x20, #32] + WORD $0xb940264e // ldr w14, [x18, #36] + WORD $0xaa0a03f2 // mov x18, x10 + WORD $0xb90063ee // str w14, [sp, #96] + WORD $0xb94067ee // ldr w14, [sp, #100] + WORD $0xb90020ce // str w14, [x6, #32] + WORD $0xb94025ee // ldr w14, [x15, #36] + WORD $0xb9006fee // str w14, [sp, #108] + WORD $0xb9404fee // ldr w14, [sp, #76] + WORD $0xb900206e // str w14, [x3, #32] + WORD $0xb94026ce // ldr w14, [x22, #36] + WORD $0xb9007fee // str w14, [sp, #124] + WORD $0xb9404bee // ldr w14, [sp, #72] + WORD $0xb900202e // str w14, [x1, #32] + WORD $0xf940c7ee // ldr x14, [sp, #392] + WORD $0xb94025cf // ldr w15, [x14, #36] + WORD $0xb9003fef // str w15, [sp, #60] + WORD $0xb9403bef // ldr w15, [sp, #56] + WORD $0xb900220f // str w15, [x16, #32] + WORD $0xaa0203ef // mov x15, x2 + WORD $0xb900214b // str w11, [x10, #32] + WORD $0xf940abea // ldr x10, [sp, #336] + WORD $0xb940254b // ldr w11, [x10, #36] + WORD $0xb9004feb // str w11, [sp, #76] + WORD $0xb9405feb // ldr w11, [sp, #92] + WORD $0xb900226b // str w11, [x19, #32] + WORD $0xb940270b // ldr w11, [x24, #36] + WORD $0xaa1503f3 // mov x19, x21 + WORD $0xaa1e03f8 // mov x24, x30 + WORD $0xb9004beb // str w11, [sp, #72] + WORD $0xb94047eb // ldr w11, [sp, #68] + WORD $0xb90022eb // str w11, [x23, #32] + WORD $0xb940274b // ldr w11, [x26, #36] + WORD $0xf9405bfa // ldr x26, [sp, #176] + WORD $0xb90067eb // str w11, [sp, #100] + WORD $0xb9405beb // ldr w11, [sp, #88] + WORD $0xb900204b // str w11, [x2, #32] + WORD $0xb940272b // ldr w11, [x25, #36] + WORD $0xb9402762 // ldr w2, [x27, #36] + WORD $0xb9005feb // str w11, [sp, #92] + WORD $0xaa1103eb // mov x11, x17 + WORD $0xb94043f1 // ldr w17, [sp, #64] + WORD $0xb9002171 // str w17, [x11, #32] + WORD $0xb94026b1 // ldr w17, [x21, #36] + WORD $0xf940bff5 // ldr x21, [sp, #376] + WORD $0xb9005bf1 // str w17, [sp, #88] + WORD $0x294ec7f9 // ldp w25, w17, [sp, #116] + WORD $0xb9007be2 // str w2, [sp, #120] + WORD $0xaa1b03e2 // mov x2, x27 + WORD $0xf9407ffb // ldr x27, [sp, #248] + WORD $0xb90023d1 // str w17, [x30, #32] + WORD $0xb94022b1 // ldr w17, [x21, #32] + WORD $0xb9002359 // str w25, [x26, #32] + WORD $0xb9402799 // ldr w25, [x28, #36] + WORD $0xb9002364 // str w4, [x27, #32] + WORD $0xb94026a4 // ldr w4, [x21, #36] + WORD $0xf9409ffe // ldr x30, [sp, #312] + WORD $0xb90057f9 // str w25, [sp, #84] + WORD $0xf9406bf9 // ldr x25, [sp, #208] + WORD $0xb90077e4 // str w4, [sp, #116] + WORD $0xaa0803e4 // mov x4, x8 + WORD $0xf940a7f5 // ldr x21, [sp, #328] + WORD $0xb9002331 // str w17, [x25, #32] + WORD $0xb9002505 // str w5, [x8, #36] + WORD $0xb94073e8 // ldr w8, [sp, #112] + WORD $0xb9402ab1 // ldr w17, [x21, #40] + WORD $0xaa1603e5 // mov x5, x22 + WORD $0xb9002588 // str w8, [x12, #36] + WORD $0xb94029a8 // ldr w8, [x13, #40] + WORD $0xb90073e8 // str w8, [sp, #112] + WORD $0xb94053e8 // ldr w8, [sp, #80] + WORD $0xb9002688 // str w8, [x20, #36] + WORD $0xb9402bc8 // ldr w8, [x30, #40] + WORD $0xaa0303f4 // mov x20, x3 + WORD $0xb90047e8 // str w8, [sp, #68] + WORD $0xb94063e8 // ldr w8, [sp, #96] + WORD $0xb90024c8 // str w8, [x6, #36] + WORD $0xb94028e8 // ldr w8, [x7, #40] + WORD $0xaa1a03e7 // mov x7, x26 + WORD $0xb90063e8 // str w8, [sp, #96] + WORD $0xb9406fe8 // ldr w8, [sp, #108] + WORD $0xb9002468 // str w8, [x3, #36] + WORD $0xb9402ac8 // ldr w8, [x22, #40] + WORD $0xaa1303f6 // mov x22, x19 + WORD $0xb90053e8 // str w8, [sp, #80] + WORD $0xb9407fe8 // ldr w8, [sp, #124] + WORD $0xb9002428 // str w8, [x1, #36] + WORD $0xb9403fe8 // ldr w8, [sp, #60] + WORD $0xb94029c1 // ldr w1, [x14, #40] + WORD $0xf940b3ee // ldr x14, [sp, #352] + WORD $0xb9002608 // str w8, [x16, #36] + WORD $0xa95243e3 // ldp x3, x16, [sp, #288] + WORD $0xb9402868 // ldr w8, [x3, #40] + WORD $0xb9003be8 // str w8, [sp, #56] + WORD $0xb9406be8 // ldr w8, [sp, #104] + WORD $0xb9002648 // str w8, [x18, #36] + WORD $0xb9402948 // ldr w8, [x10, #40] + WORD $0xf9404fea // ldr x10, [sp, #152] + WORD $0xb9402932 // ldr w18, [x9, #40] + WORD $0xb90043e8 // str w8, [sp, #64] + WORD $0xb9404fe8 // ldr w8, [sp, #76] + WORD $0xb9002548 // str w8, [x10, #36] + WORD $0xb94029c8 // ldr w8, [x14, #40] + WORD $0xb90037e8 // str w8, [sp, #52] + WORD $0xb9404be8 // ldr w8, [sp, #72] + WORD $0xb90026e8 // str w8, [x23, #36] + WORD $0xb9402a08 // ldr w8, [x16, #40] + WORD $0xb9004fe8 // str w8, [sp, #76] + WORD $0xb94067e8 // ldr w8, [sp, #100] + WORD $0xb90025e8 // str w8, [x15, #36] + WORD $0xf9408bef // ldr x15, [sp, #272] + WORD $0xb94029e8 // ldr w8, [x15, #40] + WORD $0xb90067e8 // str w8, [sp, #100] + WORD $0xb9405fe8 // ldr w8, [sp, #92] + WORD $0xb9002568 // str w8, [x11, #36] + WORD $0xb9405be8 // ldr w8, [sp, #88] + WORD $0xb9402a6b // ldr w11, [x19, #40] + WORD $0xf9405ff3 // ldr x19, [sp, #184] + WORD $0xb9002708 // str w8, [x24, #36] + WORD $0xb9402848 // ldr w8, [x2, #40] + WORD $0xaa1403f8 // mov x24, x20 + WORD $0xb9006fe8 // str w8, [sp, #108] + WORD $0xb9407be8 // ldr w8, [sp, #120] + WORD $0xb9002748 // str w8, [x26, #36] + WORD $0xaa0903e8 // mov x8, x9 + WORD $0xb94057e9 // ldr w9, [sp, #84] + WORD $0xaa1c03fa // mov x26, x28 + WORD $0xb9402d02 // ldr w2, [x8, #44] + WORD $0xaa0403e8 // mov x8, x4 + WORD $0xb9002769 // str w9, [x27, #36] + WORD $0xb9402b89 // ldr w9, [x28, #40] + WORD $0xaa0303fb // mov x27, x3 + WORD $0x290f2fe9 // stp w9, w11, [sp, #120] + WORD $0xb94077e9 // ldr w9, [sp, #116] + WORD $0xaa1503eb // mov x11, x21 + WORD $0xb9002729 // str w9, [x25, #36] + WORD $0xb9402ea9 // ldr w9, [x21, #44] + WORD $0xb9002892 // str w18, [x4, #40] + WORD $0xf94057f2 // ldr x18, [sp, #168] + WORD $0xb9002991 // str w17, [x12, #40] + WORD $0xaa0603e4 // mov x4, x6 + WORD $0xb9003fe9 // str w9, [sp, #60] + WORD $0xb9402da9 // ldr w9, [x13, #44] + WORD $0xaa0c03f9 // mov x25, x12 + WORD $0xb9402cb1 // ldr w17, [x5, #44] + WORD $0xb9005be9 // str w9, [sp, #88] + WORD $0xb94073e9 // ldr w9, [sp, #112] + WORD $0xa95037ec // ldp x12, x13, [sp, #256] + WORD $0xb9002a49 // str w9, [x18, #40] + WORD $0xb9402fc9 // ldr w9, [x30, #44] + WORD $0xf940abfe // ldr x30, [sp, #336] + WORD $0xb90073e9 // str w9, [sp, #112] + WORD $0xb94047e9 // ldr w9, [sp, #68] + WORD $0xb90028c9 // str w9, [x6, #40] + WORD $0xa9581bfc // ldp x28, x6, [sp, #384] + WORD $0xb9402f89 // ldr w9, [x28, #44] + WORD $0xb9006be9 // str w9, [sp, #104] + WORD $0xb94063e9 // ldr w9, [sp, #96] + WORD $0xb9002a89 // str w9, [x20, #40] + WORD $0xb94053e9 // ldr w9, [sp, #80] + WORD $0xa94e57f4 // ldp x20, x21, [sp, #224] + WORD $0xb9002aa9 // str w9, [x21, #40] + WORD $0xb9402cc9 // ldr w9, [x6, #44] + WORD $0xb9002981 // str w1, [x12, #40] + WORD $0xaa1703e1 // mov x1, x23 + WORD $0x290bc7e9 // stp w9, w17, [sp, #92] + WORD $0xb9402c69 // ldr w9, [x3, #44] + WORD $0xf94053f1 // ldr x17, [sp, #160] + WORD $0xaa0a03e3 // mov x3, x10 + WORD $0xb90033e9 // str w9, [sp, #48] + WORD $0xb9403be9 // ldr w9, [sp, #56] + WORD $0xb9002a29 // str w9, [x17, #40] + WORD $0xb9402fc9 // ldr w9, [x30, #44] + WORD $0xb90077e9 // str w9, [sp, #116] + WORD $0xb94043e9 // ldr w9, [sp, #64] + WORD $0xb9002949 // str w9, [x10, #40] + WORD $0xb94037e9 // ldr w9, [sp, #52] + WORD $0xb9402dca // ldr w10, [x14, #44] + WORD $0xf9406bee // ldr x14, [sp, #208] + WORD $0xb9002ae9 // str w9, [x23, #40] + WORD $0xb9402e09 // ldr w9, [x16, #44] + WORD $0xf940b7f0 // ldr x16, [sp, #360] + WORD $0xaa0303f7 // mov x23, x3 + WORD $0x2906abe9 // stp w9, w10, [sp, #52] + WORD $0xb9404fe9 // ldr w9, [sp, #76] + WORD $0xb9402dea // ldr w10, [x15, #44] + WORD $0xb9002a89 // str w9, [x20, #40] + WORD $0xb94067e9 // ldr w9, [sp, #100] + WORD $0xb9002a69 // str w9, [x19, #40] + WORD $0xb9402ec9 // ldr w9, [x22, #44] + WORD $0xaa1c03f6 // mov x22, x28 + WORD $0x29082be9 // stp w9, w10, [sp, #64] + WORD $0xb9407fe9 // ldr w9, [sp, #124] + WORD $0xf940bfea // ldr x10, [sp, #376] + WORD $0xb90029a9 // str w9, [x13, #40] + WORD $0xb9402e09 // ldr w9, [x16, #44] + WORD $0xb940294f // ldr w15, [x10, #40] + WORD $0xb90067e9 // str w9, [sp, #100] + WORD $0xb9406fe9 // ldr w9, [sp, #108] + WORD $0xb90028e9 // str w9, [x7, #40] + WORD $0xb9402f49 // ldr w9, [x26, #44] + WORD $0xf9407ffa // ldr x26, [sp, #248] + WORD $0xb9004be9 // str w9, [sp, #72] + WORD $0xb9407be9 // ldr w9, [sp, #120] + WORD $0xb9002b49 // str w9, [x26, #40] + WORD $0xb9402d49 // ldr w9, [x10, #44] + WORD $0xb90029cf // str w15, [x14, #40] + WORD $0xf940a3ea // ldr x10, [sp, #320] + WORD $0xb9002d02 // str w2, [x8, #44] + WORD $0xb9403168 // ldr w8, [x11, #48] + WORD $0xaa0c03e2 // mov x2, x12 + WORD $0xf940afef // ldr x15, [sp, #344] + WORD $0xb9004fe8 // str w8, [sp, #76] + WORD $0xb9403fe8 // ldr w8, [sp, #60] + WORD $0xb9002f28 // str w8, [x25, #44] + WORD $0xb9403148 // ldr w8, [x10, #48] + WORD $0x290a27e8 // stp w8, w9, [sp, #80] + WORD $0xb9405be8 // ldr w8, [sp, #88] + WORD $0xb9403389 // ldr w9, [x28, #48] + WORD $0xaa0503fc // mov x28, x5 + WORD $0xb9002e48 // str w8, [x18, #44] + WORD $0xf9409ff2 // ldr x18, [sp, #312] + WORD $0xb9403248 // ldr w8, [x18, #48] + WORD $0xb9005be8 // str w8, [sp, #88] + WORD $0xb94073e8 // ldr w8, [sp, #112] + WORD $0xb9002c88 // str w8, [x4, #44] + WORD $0xb9406be8 // ldr w8, [sp, #104] + WORD $0xaa0e03e4 // mov x4, x14 + WORD $0xb9002f08 // str w8, [x24, #44] + WORD $0xb94030a8 // ldr w8, [x5, #48] + WORD $0xf9408bf8 // ldr x24, [sp, #272] + WORD $0xaa1a03e5 // mov x5, x26 + WORD $0xb9006be8 // str w8, [sp, #104] + WORD $0xb94063e8 // ldr w8, [sp, #96] + WORD $0xb9002ea8 // str w8, [x21, #44] + WORD $0xb94030c8 // ldr w8, [x6, #48] + WORD $0x290f27e8 // stp w8, w9, [sp, #120] + WORD $0xb9405fe8 // ldr w8, [sp, #92] + WORD $0xb9002d88 // str w8, [x12, #44] + WORD $0xb9403368 // ldr w8, [x27, #48] + WORD $0xa952b3f5 // ldp x21, x12, [sp, #296] + WORD $0xb90073e8 // str w8, [sp, #112] + WORD $0xb94033e8 // ldr w8, [sp, #48] + WORD $0xb9002e28 // str w8, [x17, #44] + WORD $0xb94033c8 // ldr w8, [x30, #48] + WORD $0xb90033e8 // str w8, [sp, #48] + WORD $0xb94077e8 // ldr w8, [sp, #116] + WORD $0xb9002c68 // str w8, [x3, #44] + WORD $0xf940b3e8 // ldr x8, [sp, #352] + WORD $0xaa1303e3 // mov x3, x19 + WORD $0x29462109 // ldp w9, w8, [x8, #48] + WORD $0xb90077e9 // str w9, [sp, #116] + WORD $0xb9403be9 // ldr w9, [sp, #56] + WORD $0xb9002c29 // str w9, [x1, #44] + WORD $0xb94032a9 // ldr w9, [x21, #48] + WORD $0xf94077e1 // ldr x1, [sp, #232] + WORD $0xb9003fe9 // str w9, [sp, #60] + WORD $0xb94037e9 // ldr w9, [sp, #52] + WORD $0xb9002e89 // str w9, [x20, #44] + WORD $0xb9403309 // ldr w9, [x24, #48] + WORD $0xb9003be9 // str w9, [sp, #56] + WORD $0xb94047e9 // ldr w9, [sp, #68] + WORD $0xb9002e69 // str w9, [x19, #44] + WORD $0xb9403189 // ldr w9, [x12, #48] + WORD $0xb9006fe9 // str w9, [sp, #108] + WORD $0xb94043e9 // ldr w9, [sp, #64] + WORD $0xb90043e8 // str w8, [sp, #64] + WORD $0xb94077e8 // ldr w8, [sp, #116] + WORD $0xb9002da9 // str w9, [x13, #44] + WORD $0xb9403209 // ldr w9, [x16, #48] + WORD $0xb9404bed // ldr w13, [sp, #72] + WORD $0xb90047e9 // str w9, [sp, #68] + WORD $0xb94067e9 // ldr w9, [sp, #100] + WORD $0xb9002ce9 // str w9, [x7, #44] + WORD $0xf940bbe9 // ldr x9, [sp, #368] + WORD $0xb9002f4d // str w13, [x26, #44] + WORD $0xb94031ed // ldr w13, [x15, #48] + WORD $0xa94c6bf4 // ldp x20, x26, [sp, #192] + WORD $0x29464126 // ldp w6, w16, [x9, #48] + WORD $0xb90063ed // str w13, [sp, #96] + WORD $0xb9403569 // ldr w9, [x11, #52] + WORD $0xb94057ed // ldr w13, [sp, #84] + WORD $0xb940364b // ldr w11, [x18, #52] + WORD $0xb9005fe9 // str w9, [sp, #92] + WORD $0xb9404fe9 // ldr w9, [sp, #76] + WORD $0xb9002dcd // str w13, [x14, #44] + WORD $0xb9403772 // ldr w18, [x27, #52] + WORD $0xb9003346 // str w6, [x26, #48] + WORD $0xaa1603ed // mov x13, x22 + WORD $0xb9003329 // str w9, [x25, #48] + WORD $0xb9403549 // ldr w9, [x10, #52] + WORD $0xf94057ea // ldr x10, [sp, #168] + WORD $0xaa1803e6 // mov x6, x24 + WORD $0xaa0203ee // mov x14, x2 + WORD $0xb90037e9 // str w9, [sp, #52] + WORD $0xb94053e9 // ldr w9, [sp, #80] + WORD $0xb9003149 // str w9, [x10, #48] + WORD $0xb9405be9 // ldr w9, [sp, #88] + WORD $0xb9003289 // str w9, [x20, #48] + WORD $0xb94036c9 // ldr w9, [x22, #52] + WORD $0xaa1103f6 // mov x22, x17 + WORD $0x2909afe9 // stp w9, w11, [sp, #76] + WORD $0xf9404beb // ldr x11, [sp, #144] + WORD $0xb9407fe9 // ldr w9, [sp, #124] + WORD $0xb9003169 // str w9, [x11, #48] + WORD $0xb9403789 // ldr w9, [x28, #52] + WORD $0xf940c7fc // ldr x28, [sp, #392] + WORD $0xb90067e9 // str w9, [sp, #100] + WORD $0xb9406be9 // ldr w9, [sp, #104] + WORD $0xb9003029 // str w9, [x1, #48] + WORD $0xb9403789 // ldr w9, [x28, #52] + WORD $0xb9004be9 // str w9, [sp, #72] + WORD $0xb9407be9 // ldr w9, [sp, #120] + WORD $0xb9003049 // str w9, [x2, #48] + WORD $0xb94073e9 // ldr w9, [sp, #112] + WORD $0xaa0c03e2 // mov x2, x12 + WORD $0xb9003229 // str w9, [x17, #48] + WORD $0xb94037c9 // ldr w9, [x30, #52] + WORD $0xaa1703f1 // mov x17, x23 + WORD $0x290acbe9 // stp w9, w18, [sp, #84] + WORD $0xb94033e9 // ldr w9, [sp, #48] + WORD $0xf94087f2 // ldr x18, [sp, #264] + WORD $0xb90032e9 // str w9, [x23, #48] + WORD $0xb9403709 // ldr w9, [x24, #52] + WORD $0xa94ddff3 // ldp x19, x23, [sp, #216] + WORD $0xf940b7f8 // ldr x24, [sp, #360] + WORD $0xb9003268 // str w8, [x19, #48] + WORD $0xb94036a8 // ldr w8, [x21, #52] + WORD $0xb9006be8 // str w8, [sp, #104] + WORD $0xb9403fe8 // ldr w8, [sp, #60] + WORD $0xb90032e8 // str w8, [x23, #48] + WORD $0xb9403be8 // ldr w8, [sp, #56] + WORD $0xb9003068 // str w8, [x3, #48] + WORD $0xb9403588 // ldr w8, [x12, #52] + WORD $0x2904a7e8 // stp w8, w9, [sp, #36] + WORD $0xb9403709 // ldr w9, [x24, #52] + WORD $0xb9406fe8 // ldr w8, [sp, #108] + WORD $0xb90023e9 // str w9, [sp, #32] + WORD $0xb94047e9 // ldr w9, [sp, #68] + WORD $0xb9003248 // str w8, [x18, #48] + WORD $0xf940bfe8 // ldr x8, [sp, #376] + WORD $0xb90030e9 // str w9, [x7, #48] + WORD $0xb94035e9 // ldr w9, [x15, #52] + WORD $0xb940310c // ldr w12, [x8, #48] + WORD $0xaa0103ef // mov x15, x1 + WORD $0xb9003be9 // str w9, [sp, #56] + WORD $0xb94063e9 // ldr w9, [sp, #96] + WORD $0xb90030a9 // str w9, [x5, #48] + WORD $0xb9403509 // ldr w9, [x8, #52] + WORD $0xb900308c // str w12, [x4, #48] + WORD $0xaa1c03e5 // mov x5, x28 + WORD $0xb9003750 // str w16, [x26, #52] + WORD $0xf9409ffa // ldr x26, [sp, #312] + WORD $0xa95433f0 // ldp x16, x12, [sp, #320] + WORD $0xb9006fe9 // str w9, [sp, #108] + WORD $0xaa0803e9 // mov x9, x8 + WORD $0xaa1b03e4 // mov x4, x27 + WORD $0xb9403988 // ldr w8, [x12, #56] + WORD $0xb90033e8 // str w8, [sp, #48] + WORD $0xb9405fe8 // ldr w8, [sp, #92] + WORD $0xb9003728 // str w8, [x25, #52] + WORD $0xb9403a08 // ldr w8, [x16, #56] + WORD $0xaa1203f9 // mov x25, x18 + WORD $0xb9007be8 // str w8, [sp, #120] + WORD $0xb94037e8 // ldr w8, [sp, #52] + WORD $0xb9003548 // str w8, [x10, #52] + WORD $0xb9403b48 // ldr w8, [x26, #56] + WORD $0xf9408fea // ldr x10, [sp, #280] + WORD $0xb9005fe8 // str w8, [sp, #92] + WORD $0xb94053e8 // ldr w8, [sp, #80] + WORD $0xb9003688 // str w8, [x20, #52] + WORD $0xb94039a8 // ldr w8, [x13, #56] + WORD $0xaa1e03ed // mov x13, x30 + WORD $0xf94057f4 // ldr x20, [sp, #168] + WORD $0xb9007fe8 // str w8, [sp, #124] + WORD $0xb9404fe8 // ldr w8, [sp, #76] + WORD $0xb9003568 // str w8, [x11, #52] + WORD $0x29472948 // ldp w8, w10, [x10, #56] + WORD $0xb9403b8b // ldr w11, [x28, #56] + WORD $0xb90047e8 // str w8, [sp, #68] + WORD $0xb94067e8 // ldr w8, [sp, #100] + WORD $0xb9003428 // str w8, [x1, #52] + WORD $0xb9404be8 // ldr w8, [sp, #72] + WORD $0xb90035c8 // str w8, [x14, #52] + WORD $0xb9403b68 // ldr w8, [x27, #56] + WORD $0xb9003fe8 // str w8, [sp, #60] + WORD $0xb9405be8 // ldr w8, [sp, #88] + WORD $0xb90036c8 // str w8, [x22, #52] + WORD $0xb9403bc8 // ldr w8, [x30, #56] + WORD $0xa95587fe // ldp x30, x1, [sp, #344] + WORD $0xb9403e16 // ldr w22, [x16, #60] + WORD $0x290e2fe8 // stp w8, w11, [sp, #112] + WORD $0xb94057e8 // ldr w8, [sp, #84] + WORD $0xb9402beb // ldr w11, [sp, #40] + WORD $0xb9003628 // str w8, [x17, #52] + WORD $0xb9403828 // ldr w8, [x1, #56] + WORD $0xaa0603f1 // mov x17, x6 + WORD $0xb9004be8 // str w8, [sp, #72] + WORD $0xb94043e8 // ldr w8, [sp, #64] + WORD $0xb9003668 // str w8, [x19, #52] + WORD $0xb9403aa8 // ldr w8, [x21, #56] + WORD $0xa94f4ffc // ldp x28, x19, [sp, #240] + WORD $0xb90043e8 // str w8, [sp, #64] + WORD $0xb9406be8 // ldr w8, [sp, #104] + WORD $0xb90036e8 // str w8, [x23, #52] + WORD $0xb94038c8 // ldr w8, [x6, #56] + WORD $0xb900346b // str w11, [x3, #52] + WORD $0xb940384b // ldr w11, [x2, #56] + WORD $0xa94ceff7 // ldp x23, x27, [sp, #200] + WORD $0xb9002fe8 // str w8, [sp, #44] + WORD $0xaa0303e8 // mov x8, x3 + WORD $0xb90063eb // str w11, [sp, #96] + WORD $0xf94083e3 // ldr x3, [sp, #256] + WORD $0x29442fee // ldp w14, w11, [sp, #32] + WORD $0xa94943e2 // ldp x2, x16, [sp, #144] + WORD $0xb900364b // str w11, [x18, #52] + WORD $0xb9403bf2 // ldr w18, [sp, #56] + WORD $0xb90034ee // str w14, [x7, #52] + WORD $0xf940bbee // ldr x14, [sp, #368] + WORD $0xb9403b0b // ldr w11, [x24, #56] + WORD $0xb9003672 // str w18, [x19, #52] + WORD $0xb9403bd2 // ldr w18, [x30, #56] + WORD $0x294739c6 // ldp w6, w14, [x14, #56] + WORD $0xb90037eb // str w11, [sp, #52] + WORD $0xaa1803eb // mov x11, x24 + WORD $0xb9004ff2 // str w18, [sp, #76] + WORD $0xb9406ff2 // ldr w18, [sp, #108] + WORD $0xaa0703f8 // mov x24, x7 + WORD $0xf94063e7 // ldr x7, [sp, #192] + WORD $0xb9003772 // str w18, [x27, #52] + WORD $0xf94053f2 // ldr x18, [sp, #160] + WORD $0xb9003ae6 // str w6, [x23, #56] + WORD $0xb9403d86 // ldr w6, [x12, #60] + WORD $0xb94033ec // ldr w12, [sp, #48] + WORD $0xb9003b8c // str w12, [x28, #56] + WORD $0xb9407bec // ldr w12, [sp, #120] + WORD $0xb9007bea // str w10, [sp, #120] + WORD $0xb94047ea // ldr w10, [sp, #68] + WORD $0xb9003a8c // str w12, [x20, #56] + WORD $0xb9403f4c // ldr w12, [x26, #60] + WORD $0xb90053ec // str w12, [sp, #80] + WORD $0xb9405fec // ldr w12, [sp, #92] + WORD $0xb90038ec // str w12, [x7, #56] + WORD $0xf940c3ec // ldr x12, [sp, #384] + WORD $0xb9403d8c // ldr w12, [x12, #60] + WORD $0xb90057ec // str w12, [sp, #84] + WORD $0xb9407fec // ldr w12, [sp, #124] + WORD $0xb900384c // str w12, [x2, #56] + WORD $0xb940392c // ldr w12, [x9, #56] + WORD $0xb90039ea // str w10, [x15, #56] + WORD $0xb9403caa // ldr w10, [x5, #60] + WORD $0xb9403ea5 // ldr w5, [x21, #60] + WORD $0xb9005bea // str w10, [sp, #88] + WORD $0xb94077ea // ldr w10, [sp, #116] + WORD $0xb900386a // str w10, [x3, #56] + WORD $0xb9403c8a // ldr w10, [x4, #60] + WORD $0xb90067ea // str w10, [sp, #100] + WORD $0xb9403fea // ldr w10, [sp, #60] + WORD $0xb9003a4a // str w10, [x18, #56] + WORD $0xb9403daa // ldr w10, [x13, #60] + WORD $0xaa1203ed // mov x13, x18 + WORD $0xb9005fea // str w10, [sp, #92] + WORD $0xb94073ea // ldr w10, [sp, #112] + WORD $0xb9003a0a // str w10, [x16, #56] + WORD $0xb9403c2a // ldr w10, [x1, #60] + WORD $0xa94d93e1 // ldp x1, x4, [sp, #216] + WORD $0xb90073ea // str w10, [sp, #112] + WORD $0xb9404bea // ldr w10, [sp, #72] + WORD $0xb900382a // str w10, [x1, #56] + WORD $0xb94043ea // ldr w10, [sp, #64] + WORD $0xb900388a // str w10, [x4, #56] + WORD $0xb9403e2a // ldr w10, [x17, #60] + WORD $0xb9006bea // str w10, [sp, #104] + WORD $0xb9402fea // ldr w10, [sp, #44] + WORD $0xb900390a // str w10, [x8, #56] + WORD $0xf9409bea // ldr x10, [sp, #304] + WORD $0xb9403d48 // ldr w8, [x10, #60] + WORD $0xb9006fe8 // str w8, [sp, #108] + WORD $0xb94063e8 // ldr w8, [sp, #96] + WORD $0xb9003b28 // str w8, [x25, #56] + WORD $0xaa0903e8 // mov x8, x9 + WORD $0xb9403d69 // ldr w9, [x11, #60] + WORD $0xb9403fcb // ldr w11, [x30, #60] + WORD $0xb9403d08 // ldr w8, [x8, #60] + WORD $0xb90063e9 // str w9, [sp, #96] + WORD $0xb94037e9 // ldr w9, [sp, #52] + WORD $0xb90077eb // str w11, [sp, #116] + WORD $0xaa0303eb // mov x11, x3 + WORD $0xb9007fe8 // str w8, [sp, #124] + WORD $0xf940bbe8 // ldr x8, [sp, #368] + WORD $0xb9003b09 // str w9, [x24, #56] + WORD $0xb9404fe9 // ldr w9, [sp, #76] + WORD $0xf9405ffe // ldr x30, [sp, #184] + WORD $0xb9404515 // ldr w21, [x8, #68] + WORD $0xb9003a69 // str w9, [x19, #56] + WORD $0xb9404149 // ldr w9, [x10, #64] + WORD $0xb9404113 // ldr w19, [x8, #64] + WORD $0xb9003b6c // str w12, [x27, #56] + WORD $0x294a23ea // ldp w10, w8, [sp, #80] + WORD $0xb9003eee // str w14, [x23, #60] + WORD $0xb9003f86 // str w6, [x28, #60] + WORD $0xb9003e96 // str w22, [x20, #60] + WORD $0xb94073ec // ldr w12, [sp, #112] + WORD $0xb9003cea // str w10, [x7, #60] + WORD $0xb9407bea // ldr w10, [sp, #120] + WORD $0xb9003c48 // str w8, [x2, #60] + WORD $0xf940a7e8 // ldr x8, [sp, #328] + WORD $0xaa1903fc // mov x28, x25 + WORD $0xaa0203ee // mov x14, x2 + WORD $0xb9003dea // str w10, [x15, #60] + WORD $0xb94067ea // ldr w10, [sp, #100] + WORD $0x29485116 // ldp w22, w20, [x8, #64] + WORD $0xaa0403f7 // mov x23, x4 + WORD $0xb9405be8 // ldr w8, [sp, #88] + WORD $0xb940435b // ldr w27, [x26, #64] + WORD $0xb9003c68 // str w8, [x3, #60] + WORD $0xf940a3e8 // ldr x8, [sp, #320] + WORD $0xb9003e4a // str w10, [x18, #60] + WORD $0xaa1003ea // mov x10, x16 + WORD $0x29482111 // ldp w17, w8, [x8, #64] + WORD $0xb9007be8 // str w8, [sp, #120] + WORD $0xb9405fe8 // ldr w8, [sp, #92] + WORD $0xb9003e08 // str w8, [x16, #60] + WORD $0xb9406bf0 // ldr w16, [sp, #104] + WORD $0xb9003c2c // str w12, [x1, #60] + WORD $0xb940474c // ldr w12, [x26, #68] + WORD $0xb9003c85 // str w5, [x4, #60] + WORD $0xaa0103e8 // mov x8, x1 + WORD $0xb9003fd0 // str w16, [x30, #60] + WORD $0xb94063f0 // ldr w16, [sp, #96] + WORD $0xb90073ec // str w12, [sp, #112] + WORD $0xb9407fe1 // ldr w1, [sp, #124] + WORD $0xa9584bec // ldp x12, x18, [sp, #384] + WORD $0xa94cebe5 // ldp x5, x26, [sp, #200] + WORD $0x29483183 // ldp w3, w12, [x12, #64] + WORD $0xf940abe4 // ldr x4, [sp, #336] + WORD $0xb9006bec // str w12, [sp, #104] + WORD $0xb9406fec // ldr w12, [sp, #108] + WORD $0xb9003f2c // str w12, [x25, #60] + WORD $0xf9408fec // ldr x12, [sp, #280] + WORD $0xb9003f10 // str w16, [x24, #60] + WORD $0xa94f43e6 // ldp x6, x16, [sp, #240] + WORD $0x29483199 // ldp w25, w12, [x12, #64] + WORD $0xb90063ec // str w12, [sp, #96] + WORD $0xb94077ec // ldr w12, [sp, #116] + WORD $0xb9003e0c // str w12, [x16, #60] + WORD $0x29484a4c // ldp w12, w18, [x18, #64] + WORD $0xb9003f41 // str w1, [x26, #60] + WORD $0xb90040b3 // str w19, [x5, #64] + WORD $0xaa0703e1 // mov x1, x7 + WORD $0xb90040d6 // str w22, [x6, #64] + WORD $0xaa1e03f6 // mov x22, x30 + WORD $0xb9007ff2 // str w18, [sp, #124] + WORD $0xf94093f2 // ldr x18, [sp, #288] + WORD $0x29484a42 // ldp w2, w18, [x18, #64] + WORD $0xb9006ff2 // str w18, [sp, #108] + WORD $0xf94057f2 // ldr x18, [sp, #168] + WORD $0xb9004251 // str w17, [x18, #64] + WORD $0xb9404091 // ldr w17, [x4, #64] + WORD $0xb90040fb // str w27, [x7, #64] + WORD $0xb9404487 // ldr w7, [x4, #68] + WORD $0xb90041c3 // str w3, [x14, #64] + WORD $0xf940b3e4 // ldr x4, [sp, #352] + WORD $0xb90041f9 // str w25, [x15, #64] + WORD $0xaa0b03f9 // mov x25, x11 + WORD $0xb900416c // str w12, [x11, #64] + WORD $0xf94097ec // ldr x12, [sp, #296] + WORD $0xb9404083 // ldr w3, [x4, #64] + WORD $0xb90041a2 // str w2, [x13, #64] + WORD $0xb9004151 // str w17, [x10, #64] + WORD $0xf940afe2 // ldr x2, [sp, #344] + WORD $0x2948318b // ldp w11, w12, [x12, #64] + WORD $0xb9004103 // str w3, [x8, #64] + WORD $0xf940b7e3 // ldr x3, [sp, #360] + WORD $0xb90042eb // str w11, [x23, #64] + WORD $0xb9404484 // ldr w4, [x4, #68] + WORD $0xb9005fec // str w12, [sp, #92] + WORD $0xf9408bec // ldr x12, [sp, #272] + WORD $0x29480c6b // ldp w11, w3, [x3, #64] + WORD $0xb90067e4 // str w4, [sp, #100] + WORD $0x29482191 // ldp w17, w8, [x12, #64] + WORD $0xb9005be8 // str w8, [sp, #88] + WORD $0xf940bfe8 // ldr x8, [sp, #376] + WORD $0xb90043d1 // str w17, [x30, #64] + WORD $0xb9404051 // ldr w17, [x2, #64] + WORD $0xb9004389 // str w9, [x28, #64] + WORD $0xaa0e03fc // mov x28, x14 + WORD $0xb940410c // ldr w12, [x8, #64] + WORD $0xb900430b // str w11, [x24, #64] + WORD $0xb9004211 // str w17, [x16, #64] + WORD $0xb9404513 // ldr w19, [x8, #68] + WORD $0xaa0503e8 // mov x8, x5 + WORD $0xb94073f1 // ldr w17, [sp, #112] + WORD $0xb900434c // str w12, [x26, #64] + WORD $0xb9406bee // ldr w14, [sp, #104] + WORD $0xb90044b5 // str w21, [x5, #68] + WORD $0xf9409be5 // ldr x5, [sp, #304] + WORD $0xb90044d4 // str w20, [x6, #68] + WORD $0xb94063e9 // ldr w9, [sp, #96] + WORD $0xb940444b // ldr w11, [x2, #68] + WORD $0xaa0f03fe // mov x30, x15 + WORD $0x2948c0ac // ldp w12, w16, [x5, #68] + WORD $0xaa1703f5 // mov x21, x23 + WORD $0xaa0503e6 // mov x6, x5 + WORD $0xf940c3e5 // ldr x5, [sp, #384] + WORD $0xb90077f0 // str w16, [sp, #116] + WORD $0xb9407bf0 // ldr w16, [sp, #120] + WORD $0xb9004650 // str w16, [x18, #68] + WORD $0xaa1203f0 // mov x16, x18 + WORD $0xb9004431 // str w17, [x1, #68] + WORD $0xf940bbf2 // ldr x18, [sp, #368] + WORD $0xb900478e // str w14, [x28, #68] + WORD $0xf940a7ee // ldr x14, [sp, #328] + WORD $0xb90045e9 // str w9, [x15, #68] + WORD $0xb9406fe9 // ldr w9, [sp, #108] + WORD $0x29490a5b // ldp w27, w2, [x18, #72] + WORD $0xaa1903e1 // mov x1, x25 + WORD $0x294911d4 // ldp w20, w4, [x14, #72] + WORD $0xb9407fee // ldr w14, [sp, #124] + WORD $0xaa0a03f2 // mov x18, x10 + WORD $0xf940a3ef // ldr x15, [sp, #320] + WORD $0xb900472e // str w14, [x25, #68] + WORD $0xaa0d03f9 // mov x25, x13 + WORD $0xb90045a9 // str w9, [x13, #68] + WORD $0xb94067e9 // ldr w9, [sp, #100] + WORD $0xb9004547 // str w7, [x10, #68] + WORD $0xf9406fea // ldr x10, [sp, #216] + WORD $0xb9404ded // ldr w13, [x15, #76] + WORD $0xf9407fe7 // ldr x7, [sp, #248] + WORD $0xb9004549 // str w9, [x10, #68] + WORD $0xb9405fe9 // ldr w9, [sp, #92] + WORD $0xb9007bed // str w13, [sp, #120] + WORD $0xf9409fed // ldr x13, [sp, #312] + WORD $0xb94049ee // ldr w14, [x15, #72] + WORD $0xb90046e9 // str w9, [x23, #68] + WORD $0xb9405be9 // ldr w9, [sp, #88] + WORD $0xf94087f7 // ldr x23, [sp, #264] + WORD $0xb94049af // ldr w15, [x13, #72] + WORD $0xb90046c9 // str w9, [x22, #68] + WORD $0xb9404db1 // ldr w17, [x13, #76] + WORD $0xb90046ec // str w12, [x23, #68] + WORD $0xb94048ad // ldr w13, [x5, #72] + WORD $0xb9004703 // str w3, [x24, #68] + WORD $0xf940c7e3 // ldr x3, [sp, #392] + WORD $0xb9404ca9 // ldr w9, [x5, #76] + WORD $0xb90044eb // str w11, [x7, #68] + WORD $0xf9408fe5 // ldr x5, [sp, #280] + WORD $0xb9004753 // str w19, [x26, #68] + WORD $0xb940486b // ldr w11, [x3, #72] + WORD $0xb900491b // str w27, [x8, #72] + WORD $0xb9404c63 // ldr w3, [x3, #76] + WORD $0xb9006fe9 // str w9, [sp, #108] + WORD $0x294924ac // ldp w12, w9, [x5, #72] + WORD $0xaa0803fb // mov x27, x8 + WORD $0xf9407be8 // ldr x8, [sp, #240] + WORD $0xb9007fe3 // str w3, [sp, #124] + WORD $0xf94093e3 // ldr x3, [sp, #288] + WORD $0xb90063e9 // str w9, [sp, #96] + WORD $0xb9004914 // str w20, [x8, #72] + WORD $0xaa1003f4 // mov x20, x16 + WORD $0xb9404c69 // ldr w9, [x3, #76] + WORD $0xb9004a0e // str w14, [x16, #72] + WORD $0xf940abf0 // ldr x16, [sp, #336] + WORD $0xaa1a03e5 // mov x5, x26 + WORD $0xb940487a // ldr w26, [x3, #72] + WORD $0xb90073e9 // str w9, [sp, #112] + WORD $0xf94063e3 // ldr x3, [sp, #192] + WORD $0x2949260e // ldp w14, w9, [x16, #72] + WORD $0xb900486f // str w15, [x3, #72] + WORD $0xf94097ef // ldr x15, [sp, #296] + WORD $0xb90067e9 // str w9, [sp, #100] + WORD $0xf940b3e9 // ldr x9, [sp, #352] + WORD $0xb9004b8d // str w13, [x28, #72] + WORD $0xb9004bcc // str w12, [x30, #72] + WORD $0xaa1e03ec // mov x12, x30 + WORD $0xb940492d // ldr w13, [x9, #72] + WORD $0xb900482b // str w11, [x1, #72] + WORD $0xb94049eb // ldr w11, [x15, #72] + WORD $0xb9004b3a // str w26, [x25, #72] + WORD $0xb9404dfe // ldr w30, [x15, #76] + WORD $0xb9004a4e // str w14, [x18, #72] + WORD $0xf9408bef // ldr x15, [sp, #272] + WORD $0xb900494d // str w13, [x10, #72] + WORD $0xb9004aab // str w11, [x21, #72] + WORD $0xf940b7ed // ldr x13, [sp, #360] + WORD $0xaa1703fa // mov x26, x23 + WORD $0xaa1903e1 // mov x1, x25 + WORD $0x294929ee // ldp w14, w10, [x15, #72] + WORD $0xaa1403f9 // mov x25, x20 + WORD $0xaa0103f5 // mov x21, x1 + WORD $0xf940afef // ldr x15, [sp, #344] + WORD $0xb9005fea // str w10, [sp, #92] + WORD $0xb94077ea // ldr w10, [sp, #116] + WORD $0xb9004ace // str w14, [x22, #72] + WORD $0xb94049ab // ldr w11, [x13, #72] + WORD $0xb94049ee // ldr w14, [x15, #72] + WORD $0xaa0503f6 // mov x22, x5 + WORD $0xb9004aea // str w10, [x23, #72] + WORD $0xf940bfea // ldr x10, [sp, #376] + WORD $0xb9004b0b // str w11, [x24, #72] + WORD $0xb9404deb // ldr w11, [x15, #76] + WORD $0xb90048ee // str w14, [x7, #72] + WORD $0xf94083f7 // ldr x23, [sp, #256] + WORD $0x29493950 // ldp w16, w14, [x10, #72] + WORD $0xaa1203e7 // mov x7, x18 + WORD $0xaa0603ea // mov x10, x6 + WORD $0xb94063ea // ldr w10, [sp, #96] + WORD $0xb90077eb // str w11, [sp, #116] + WORD $0xb90048b0 // str w16, [x5, #72] + WORD $0xb9404d29 // ldr w9, [x9, #76] + WORD $0xb9004f62 // str w2, [x27, #76] + WORD $0xaa0303e2 // mov x2, x3 + WORD $0xb9004d04 // str w4, [x8, #76] + WORD $0x2949a0d0 // ldp w16, w8, [x6, #76] + WORD $0xaa0c03f8 // mov x24, x12 + WORD $0xb9404dad // ldr w13, [x13, #76] + WORD $0xaa1c03e6 // mov x6, x28 + WORD $0xb9006be8 // str w8, [sp, #104] + WORD $0xb9407be8 // ldr w8, [sp, #120] + WORD $0xf940c3eb // ldr x11, [sp, #384] + WORD $0xaa1603e4 // mov x4, x22 + WORD $0xb9004e88 // str w8, [x20, #76] + WORD $0xf940bbe8 // ldr x8, [sp, #368] + WORD $0xb9004c71 // str w17, [x3, #76] + WORD $0x294a4d0f // ldp w15, w19, [x8, #80] + WORD $0xb9406fe8 // ldr w8, [sp, #108] + WORD $0xb9004f88 // str w8, [x28, #76] + WORD $0xf940a7e8 // ldr x8, [sp, #328] + WORD $0xb9004d8a // str w10, [x12, #76] + WORD $0xb94073ea // ldr w10, [sp, #112] + WORD $0xaa1a03fc // mov x28, x26 + WORD $0x294a1503 // ldp w3, w5, [x8, #80] + WORD $0xb9407fe8 // ldr w8, [sp, #124] + WORD $0xb9004ee8 // str w8, [x23, #76] + WORD $0xf940a3e8 // ldr x8, [sp, #320] + WORD $0xb9004c2a // str w10, [x1, #76] + WORD $0xa94dabf4 // ldp x20, x10, [sp, #216] + WORD $0x294a2111 // ldp w17, w8, [x8, #80] + WORD $0xb9007be8 // str w8, [sp, #120] + WORD $0xb94067e8 // ldr w8, [sp, #100] + WORD $0xb9004e48 // str w8, [x18, #76] + WORD $0xf9409fe8 // ldr x8, [sp, #312] + WORD $0xb9004e89 // str w9, [x20, #76] + WORD $0xb9405fe9 // ldr w9, [sp, #92] + WORD $0xb9004d5e // str w30, [x10, #76] + WORD $0xb9405172 // ldr w18, [x11, #80] + WORD $0x294a2101 // ldp w1, w8, [x8, #80] + WORD $0xb9006fe8 // str w8, [sp, #108] + WORD $0xf9405fe8 // ldr x8, [sp, #184] + WORD $0xb9004d09 // str w9, [x8, #76] + WORD $0xb9405569 // ldr w9, [x11, #84] + WORD $0xb9004f50 // str w16, [x26, #76] + WORD $0xf9405bf0 // ldr x16, [sp, #176] + WORD $0xf9408feb // ldr x11, [sp, #280] + WORD $0xaa1703fa // mov x26, x23 + WORD $0xb90067e9 // str w9, [sp, #100] + WORD $0xb9004e0d // str w13, [x16, #76] + WORD $0xf940c7ed // ldr x13, [sp, #392] + WORD $0x294a257e // ldp w30, w9, [x11, #80] + WORD $0x294a35ac // ldp w12, w13, [x13, #80] + WORD $0xb90063e9 // str w9, [sp, #96] + WORD $0xf9407feb // ldr x11, [sp, #248] + WORD $0xb94077e9 // ldr w9, [sp, #116] + WORD $0xb9007fed // str w13, [sp, #124] + WORD $0xf94093ed // ldr x13, [sp, #288] + WORD $0xb9004d69 // str w9, [x11, #76] + WORD $0xb9004ece // str w14, [x22, #76] + WORD $0xf9407bee // ldr x14, [sp, #240] + WORD $0xb900536f // str w15, [x27, #80] + WORD $0x294a35af // ldp w15, w13, [x13, #80] + WORD $0xaa1b03f6 // mov x22, x27 + WORD $0xb90051c3 // str w3, [x14, #80] + WORD $0xaa1903e3 // mov x3, x25 + WORD $0xb9005331 // str w17, [x25, #80] + WORD $0xaa0b03fb // mov x27, x11 + WORD $0xb90073ed // str w13, [sp, #112] + WORD $0xf940abed // ldr x13, [sp, #336] + WORD $0xb9005041 // str w1, [x2, #80] + WORD $0xaa0203e1 // mov x1, x2 + WORD $0xb90050d2 // str w18, [x6, #80] + WORD $0xaa0603f9 // mov x25, x6 + WORD $0xb94051b1 // ldr w17, [x13, #80] + WORD $0xb900531e // str w30, [x24, #80] + WORD $0xb94055a9 // ldr w9, [x13, #84] + WORD $0xb90052ec // str w12, [x23, #80] + WORD $0xf940b3ed // ldr x13, [sp, #352] + WORD $0xb90052af // str w15, [x21, #80] + WORD $0xb90050f1 // str w17, [x7, #80] + WORD $0xaa0a03fe // mov x30, x10 + WORD $0xaa0703ef // mov x15, x7 + WORD $0xaa0e03e7 // mov x7, x14 + WORD $0x294a35b2 // ldp w18, w13, [x13, #80] + WORD $0xaa0103f7 // mov x23, x1 + WORD $0xb9005292 // str w18, [x20, #80] + WORD $0xb90077ed // str w13, [sp, #116] + WORD $0xf94097ed // ldr x13, [sp, #296] + WORD $0x294a35ac // ldp w12, w13, [x13, #80] + WORD $0xb900514c // str w12, [x10, #80] + WORD $0xb9406bec // ldr w12, [sp, #104] + WORD $0xb9005fed // str w13, [sp, #92] + WORD $0xf9408bed // ldr x13, [sp, #272] + WORD $0x294a35b1 // ldp w17, w13, [x13, #80] + WORD $0xb9005111 // str w17, [x8, #80] + WORD $0xf940afe8 // ldr x8, [sp, #344] + WORD $0xb9005bed // str w13, [sp, #88] + WORD $0xf940b7ed // ldr x13, [sp, #360] + WORD $0xb900538c // str w12, [x28, #80] + WORD $0xf940bfec // ldr x12, [sp, #376] + WORD $0x294a2111 // ldp w17, w8, [x8, #80] + WORD $0xaa1903fc // mov x28, x25 + WORD $0xb94051aa // ldr w10, [x13, #80] + WORD $0xb9405182 // ldr w2, [x12, #80] + WORD $0xb90057e8 // str w8, [sp, #84] + WORD $0xf9409be8 // ldr x8, [sp, #304] + WORD $0xb900520a // str w10, [x16, #80] + WORD $0xb9405586 // ldr w6, [x12, #84] + WORD $0xb9005171 // str w17, [x11, #80] + WORD $0xb94055b2 // ldr w18, [x13, #84] + WORD $0xb9005082 // str w2, [x4, #80] + WORD $0x294a890b // ldp w11, w2, [x8, #84] + WORD $0xb90056d3 // str w19, [x22, #84] + WORD $0x294ea3ed // ldp w13, w8, [sp, #116] + WORD $0xb90055c5 // str w5, [x14, #84] + WORD $0x294db3ea // ldp w10, w12, [sp, #108] + WORD $0xb9005468 // str w8, [x3, #84] + WORD $0xf940bbe8 // ldr x8, [sp, #368] + WORD $0xf9406be5 // ldr x5, [sp, #208] + WORD $0xb900542a // str w10, [x1, #84] + WORD $0x294b2110 // ldp w16, w8, [x8, #88] + WORD $0xb9006fe8 // str w8, [sp, #108] + WORD $0x294c23ea // ldp w10, w8, [sp, #96] + WORD $0xb9005728 // str w8, [x25, #84] + WORD $0xf940a7e8 // ldr x8, [sp, #328] + WORD $0xb900570a // str w10, [x24, #84] + WORD $0xaa1503ea // mov x10, x21 + WORD $0x294b1111 // ldp w17, w4, [x8, #88] + WORD $0xb9407fe8 // ldr w8, [sp, #124] + WORD $0xb9005748 // str w8, [x26, #84] + WORD $0xf940a3e8 // ldr x8, [sp, #320] + WORD $0xb90056ac // str w12, [x21, #84] + WORD $0xaa1403ec // mov x12, x20 + WORD $0xb90055e9 // str w9, [x15, #84] + WORD $0xb940590e // ldr w14, [x8, #88] + WORD $0xb900568d // str w13, [x20, #84] + WORD $0xb9405d09 // ldr w9, [x8, #92] + WORD $0xf940c3ed // ldr x13, [sp, #384] + WORD $0xf9409fe8 // ldr x8, [sp, #312] + WORD $0xb94059b4 // ldr w20, [x13, #88] + WORD $0x294b2101 // ldp w1, w8, [x8, #88] + WORD $0x290ca7e8 // stp w8, w9, [sp, #100] + WORD $0x294b23e9 // ldp w9, w8, [sp, #88] + WORD $0xb90057c8 // str w8, [x30, #84] + WORD $0xa94b23f3 // ldp x19, x8, [sp, #176] + WORD $0xb9005509 // str w9, [x8, #84] + WORD $0xb9405da9 // ldr w9, [x13, #92] + WORD $0xf94087ed // ldr x13, [sp, #264] + WORD $0xb90077e9 // str w9, [sp, #116] + WORD $0xb90055ab // str w11, [x13, #84] + WORD $0xf9408feb // ldr x11, [sp, #280] + WORD $0xb9005672 // str w18, [x19, #84] + WORD $0xf940c7f2 // ldr x18, [sp, #392] + WORD $0x294b2575 // ldp w21, w9, [x11, #88] + WORD $0xb9405a59 // ldr w25, [x18, #88] + WORD $0xb90073e9 // str w9, [sp, #112] + WORD $0xb94057e9 // ldr w9, [sp, #84] + WORD $0xb9005769 // str w9, [x27, #84] + WORD $0xb9405e49 // ldr w9, [x18, #92] + WORD $0xf94093f2 // ldr x18, [sp, #288] + WORD $0xb90054a6 // str w6, [x5, #84] + WORD $0xb9005ad0 // str w16, [x22, #88] + WORD $0xaa0a03e6 // mov x6, x10 + WORD $0xb90058f1 // str w17, [x7, #88] + WORD $0xaa1703f1 // mov x17, x23 + WORD $0xb9405a50 // ldr w16, [x18, #88] + WORD $0xb900586e // str w14, [x3, #88] + WORD $0xb9405e4b // ldr w11, [x18, #92] + WORD $0xb9005ae1 // str w1, [x23, #88] + WORD $0xf940abf2 // ldr x18, [sp, #336] + WORD $0xb9005b94 // str w20, [x28, #88] + WORD $0xb9005b15 // str w21, [x24, #88] + WORD $0xb9005b59 // str w25, [x26, #88] + WORD $0xaa0803f5 // mov x21, x8 + WORD $0xb9405a4e // ldr w14, [x18, #88] + WORD $0xb9005950 // str w16, [x10, #88] + WORD $0xb9405e52 // ldr w18, [x18, #92] + WORD $0xaa1b03f8 // mov x24, x27 + WORD $0xf9408bea // ldr x10, [sp, #272] + WORD $0xaa1e03f4 // mov x20, x30 + WORD $0xb90059ee // str w14, [x15, #88] + WORD $0xa95587f0 // ldp x16, x1, [sp, #344] + WORD $0x290f2ff2 // stp w18, w11, [sp, #120] + WORD $0x294b0432 // ldp w18, w1, [x1, #88] + WORD $0x294b294e // ldp w14, w10, [x10, #88] + WORD $0xb9005992 // str w18, [x12, #88] + WORD $0x290b87ea // stp w10, w1, [sp, #92] + WORD $0xf94097e1 // ldr x1, [sp, #296] + WORD $0xaa0603f2 // mov x18, x6 + WORD $0x294b6437 // ldp w23, w25, [x1, #88] + WORD $0xaa0f03e1 // mov x1, x15 + WORD $0xf940b7ef // ldr x15, [sp, #360] + WORD $0xb9005bd7 // str w23, [x30, #88] + WORD $0xb9405e1e // ldr w30, [x16, #92] + WORD $0xb900590e // str w14, [x8, #88] + WORD $0xf940bfe8 // ldr x8, [sp, #376] + WORD $0xb94059ea // ldr w10, [x15, #88] + WORD $0xb90059a2 // str w2, [x13, #88] + WORD $0xb9405a0e // ldr w14, [x16, #88] + WORD $0xaa1103f0 // mov x16, x17 + WORD $0xb9405902 // ldr w2, [x8, #88] + WORD $0xaa0503f7 // mov x23, x5 + WORD $0xb9005a6a // str w10, [x19, #88] + WORD $0xb9405d0a // ldr w10, [x8, #92] + WORD $0xb9406fe8 // ldr w8, [sp, #108] + WORD $0xb9005b6e // str w14, [x27, #88] + WORD $0xb90058a2 // str w2, [x5, #88] + WORD $0xaa0303fb // mov x27, x3 + WORD $0xb9407fe5 // ldr w5, [sp, #124] + WORD $0xb9005ec8 // str w8, [x22, #92] + WORD $0xf9409be8 // ldr x8, [sp, #304] + WORD $0xb9005ce4 // str w4, [x7, #92] + WORD $0xb9405def // ldr w15, [x15, #92] + WORD $0xaa1503e7 // mov x7, x21 + WORD $0x294b891a // ldp w26, w2, [x8, #92] + WORD $0x294ca3eb // ldp w11, w8, [sp, #100] + WORD $0xb9005c68 // str w8, [x3, #92] + WORD $0xf940bbe8 // ldr x8, [sp, #368] + WORD $0xb9005e2b // str w11, [x17, #92] + WORD $0xf94077eb // ldr x11, [sp, #232] + WORD $0x294c2103 // ldp w3, w8, [x8, #96] + WORD $0xb9006fe8 // str w8, [sp, #108] + WORD $0x294e23ed // ldp w13, w8, [sp, #112] + WORD $0xb9005f88 // str w8, [x28, #92] + WORD $0xb9005d6d // str w13, [x11, #92] + WORD $0xa95423ed // ldp x13, x8, [sp, #320] + WORD $0x294c110e // ldp w14, w4, [x8, #96] + WORD $0x294c35b1 // ldp w17, w13, [x13, #96] + WORD $0xf94083e8 // ldr x8, [sp, #256] + WORD $0xb90077ed // str w13, [sp, #116] + WORD $0xb9407bed // ldr w13, [sp, #120] + WORD $0xb9005d09 // str w9, [x8, #92] + WORD $0xb94063e9 // ldr w9, [sp, #96] + WORD $0xb9005cc5 // str w5, [x6, #92] + WORD $0xf940c3e5 // ldr x5, [sp, #384] + WORD $0xb9005c2d // str w13, [x1, #92] + WORD $0xf9409fed // ldr x13, [sp, #312] + WORD $0xb9005d89 // str w9, [x12, #92] + WORD $0xb9405fe9 // ldr w9, [sp, #92] + WORD $0xb9005e99 // str w25, [x20, #92] + WORD $0x294c35a6 // ldp w6, w13, [x13, #96] + WORD $0xb9005ea9 // str w9, [x21, #92] + WORD $0xf94087f5 // ldr x21, [sp, #264] + WORD $0xb9007fed // str w13, [sp, #124] + WORD $0x294c24ad // ldp w13, w9, [x5, #96] + WORD $0xf9408fe5 // ldr x5, [sp, #280] + WORD $0xb9006be9 // str w9, [sp, #104] + WORD $0xb9005eba // str w26, [x21, #92] + WORD $0xb9005e6f // str w15, [x19, #92] + WORD $0xf940c7ef // ldr x15, [sp, #392] + WORD $0xb94064a9 // ldr w9, [x5, #100] + WORD $0xb9005f1e // str w30, [x24, #92] + WORD $0xb9005eea // str w10, [x23, #92] + WORD $0xf9407bea // ldr x10, [sp, #240] + WORD $0xb94061f9 // ldr w25, [x15, #96] + WORD $0xb90062c3 // str w3, [x22, #96] + WORD $0xb90067e9 // str w9, [sp, #100] + WORD $0xb94065e9 // ldr w9, [x15, #100] + WORD $0xb900614e // str w14, [x10, #96] + WORD $0xb9006371 // str w17, [x27, #96] + WORD $0xb94060ba // ldr w26, [x5, #96] + WORD $0xb9006206 // str w6, [x16, #96] + WORD $0xa9521bef // ldp x15, x6, [sp, #288] + WORD $0xb94061e3 // ldr w3, [x15, #96] + WORD $0xb900638d // str w13, [x28, #96] + WORD $0xb94065ee // ldr w14, [x15, #100] + WORD $0xb900617a // str w26, [x11, #96] + WORD $0xf940abef // ldr x15, [sp, #336] + WORD $0xb9006119 // str w25, [x8, #96] + WORD $0xb94060cb // ldr w11, [x6, #96] + WORD $0xb9006243 // str w3, [x18, #96] + WORD $0xf9408be8 // ldr x8, [sp, #272] + WORD $0xaa1803e5 // mov x5, x24 + WORD $0x294c3df1 // ldp w17, w15, [x15, #96] + WORD $0xb9007bee // str w14, [sp, #120] + WORD $0xaa1b03ee // mov x14, x27 + WORD $0xb9406510 // ldr w16, [x8, #100] + WORD $0xb90063e9 // str w9, [sp, #96] + WORD $0xb9006031 // str w17, [x1, #96] + WORD $0xb9406111 // ldr w17, [x8, #96] + WORD $0xb90073ef // str w15, [sp, #112] + WORD $0xa955bfe8 // ldp x8, x15, [sp, #344] + WORD $0xaa0503fe // mov x30, x5 + WORD $0xaa1203e3 // mov x3, x18 + WORD $0xaa1503f8 // mov x24, x21 + WORD $0x294c25ed // ldp w13, w9, [x15, #96] + WORD $0xaa1703f2 // mov x18, x23 + WORD $0xaa0603fc // mov x28, x6 + WORD $0xf94063ef // ldr x15, [sp, #192] + WORD $0xaa1403fa // mov x26, x20 + WORD $0xb900618d // str w13, [x12, #96] + WORD $0xf940b7ec // ldr x12, [sp, #360] + WORD $0xb900628b // str w11, [x20, #96] + WORD $0xf940bfed // ldr x13, [sp, #376] + WORD $0xb90060f1 // str w17, [x7, #96] + WORD $0xb9406111 // ldr w17, [x8, #96] + WORD $0xb940618b // ldr w11, [x12, #96] + WORD $0xb90062a2 // str w2, [x21, #96] + WORD $0xb940658c // ldr w12, [x12, #100] + WORD $0xaa0703f4 // mov x20, x7 + WORD $0xb94061a2 // ldr w2, [x13, #96] + WORD $0xaa0103e7 // mov x7, x1 + WORD $0xb900626b // str w11, [x19, #96] + WORD $0xb94065b9 // ldr w25, [x13, #100] + WORD $0x290b33f0 // stp w16, w12, [sp, #88] + WORD $0xb940650c // ldr w12, [x8, #100] + WORD $0xb9406fe8 // ldr w8, [sp, #108] + WORD $0xb90060b1 // str w17, [x5, #96] + WORD $0xb90062e2 // str w2, [x23, #96] + WORD $0xaa0a03f1 // mov x17, x10 + WORD $0xaa0e03e5 // mov x5, x14 + WORD $0xf940a7eb // ldr x11, [sp, #328] + WORD $0xb90066c8 // str w8, [x22, #100] + WORD $0xf9409be8 // ldr x8, [sp, #304] + WORD $0xb9006544 // str w4, [x10, #100] + WORD $0xb9407fea // ldr w10, [sp, #124] + WORD $0xf94077f7 // ldr x23, [sp, #232] + WORD $0x294c8910 // ldp w16, w2, [x8, #100] + WORD $0xb94077e8 // ldr w8, [sp, #116] + WORD $0xb9406d64 // ldr w4, [x11, #108] + WORD $0xf94083f5 // ldr x21, [sp, #256] + WORD $0xb90065c8 // str w8, [x14, #100] + WORD $0xf940bbe8 // ldr x8, [sp, #368] + WORD $0xb90065ea // str w10, [x15, #100] + WORD $0xf9404bea // ldr x10, [sp, #144] + WORD $0xb94064db // ldr w27, [x6, #100] + WORD $0xaa1303e6 // mov x6, x19 + WORD $0x294d210d // ldp w13, w8, [x8, #104] + WORD $0xaa0303f3 // mov x19, x3 + WORD $0xb9407be3 // ldr w3, [sp, #120] + WORD $0xf9406ff6 // ldr x22, [sp, #216] + WORD $0xb9006fe8 // str w8, [sp, #108] + WORD $0x294ca3ee // ldp w14, w8, [sp, #100] + WORD $0xb9006548 // str w8, [x10, #100] + WORD $0xb9406968 // ldr w8, [x11, #104] + WORD $0xb94063eb // ldr w11, [sp, #96] + WORD $0xb90066ee // str w14, [x23, #100] + WORD $0xb90066ab // str w11, [x21, #100] + WORD $0xf940a3eb // ldr x11, [sp, #320] + WORD $0xb9006663 // str w3, [x19, #100] + WORD $0x294d2d6e // ldp w14, w11, [x11, #104] + WORD $0xb9007feb // str w11, [sp, #124] + WORD $0xb94073eb // ldr w11, [sp, #112] + WORD $0xb900642b // str w11, [x1, #100] + WORD $0xf9409feb // ldr x11, [sp, #312] + WORD $0xb90066c9 // str w9, [x22, #100] + WORD $0xb9405be9 // ldr w9, [sp, #88] + WORD $0xb900675b // str w27, [x26, #100] + WORD $0x294d2d61 // ldp w1, w11, [x11, #104] + WORD $0xb9006689 // str w9, [x20, #100] + WORD $0xb9006710 // str w16, [x24, #100] + WORD $0xb9007beb // str w11, [sp, #120] + WORD $0xaa1a03eb // mov x11, x26 + WORD $0xf940c3fa // ldr x26, [sp, #384] + WORD $0x294d2743 // ldp w3, w9, [x26, #104] + WORD $0xf9408ffa // ldr x26, [sp, #280] + WORD $0xb90073e9 // str w9, [sp, #112] + WORD $0xb9405fe9 // ldr w9, [sp, #92] + WORD $0xb9406b50 // ldr w16, [x26, #104] + WORD $0xb90064c9 // str w9, [x6, #100] + WORD $0xb9406f49 // ldr w9, [x26, #108] + WORD $0xb90067cc // str w12, [x30, #100] + WORD $0xf940c7ec // ldr x12, [sp, #392] + WORD $0xb9006659 // str w25, [x18, #100] + WORD $0xf94093f9 // ldr x25, [sp, #288] + WORD $0xb90067e9 // str w9, [sp, #100] + WORD $0xaa1503fa // mov x26, x21 + WORD $0x294d259b // ldp w27, w9, [x12, #104] + WORD $0xaa1e03fa // mov x26, x30 + WORD $0xb9006be9 // str w9, [sp, #104] + WORD $0xf94067e9 // ldr x9, [sp, #200] + WORD $0xb900692d // str w13, [x9, #104] + WORD $0xb9406b2d // ldr w13, [x25, #104] + WORD $0xb9006a28 // str w8, [x17, #104] + WORD $0xb9406f28 // ldr w8, [x25, #108] + WORD $0xb90068ae // str w14, [x5, #104] + WORD $0xaa1303f9 // mov x25, x19 + WORD $0xb90069e1 // str w1, [x15, #104] + WORD $0xaa0a03e1 // mov x1, x10 + WORD $0xb90063e8 // str w8, [sp, #96] + WORD $0xf940abe8 // ldr x8, [sp, #336] + WORD $0xb9006943 // str w3, [x10, #104] + WORD $0xb9406b8a // ldr w10, [x28, #104] + WORD $0xb9006af0 // str w16, [x23, #104] + WORD $0xb940690e // ldr w14, [x8, #104] + WORD $0xb9006abb // str w27, [x21, #104] + WORD $0xb9406d08 // ldr w8, [x8, #108] + WORD $0xb9006a6d // str w13, [x19, #104] + WORD $0xaa0703fb // mov x27, x7 + WORD $0xb9406f8d // ldr w13, [x28, #108] + WORD $0xb90068ee // str w14, [x7, #104] + WORD $0xaa0103e7 // mov x7, x1 + WORD $0xb90077e8 // str w8, [sp, #116] + WORD $0xf940b3e8 // ldr x8, [sp, #352] + WORD $0xaa1403f3 // mov x19, x20 + WORD $0x294d4103 // ldp w3, w16, [x8, #104] + WORD $0xaa1c03e8 // mov x8, x28 + WORD $0xf9408be8 // ldr x8, [sp, #272] + WORD $0xaa1603fc // mov x28, x22 + WORD $0xb9006ac3 // str w3, [x22, #104] + WORD $0xf940bfe3 // ldr x3, [sp, #376] + WORD $0xb900696a // str w10, [x11, #104] + WORD $0xaa1803eb // mov x11, x24 + WORD $0x294d210e // ldp w14, w8, [x8, #104] + WORD $0xaa1103f6 // mov x22, x17 + WORD $0xf9405beb // ldr x11, [sp, #176] + WORD $0xb9006a8e // str w14, [x20, #104] + WORD $0xf94073f4 // ldr x20, [sp, #224] + WORD $0x290a23f0 // stp w16, w8, [sp, #80] + WORD $0xf940afe8 // ldr x8, [sp, #344] + WORD $0xf940b7f0 // ldr x16, [sp, #360] + WORD $0xb9006b02 // str w2, [x24, #104] + WORD $0xb9406862 // ldr w2, [x3, #104] + WORD $0x294d210e // ldp w14, w8, [x8, #104] + WORD $0x294d320a // ldp w10, w12, [x16, #104] + WORD $0xaa0503f0 // mov x16, x5 + WORD $0xb9005fe8 // str w8, [sp, #92] + WORD $0xb9406fe8 // ldr w8, [sp, #108] + WORD $0xb90068ca // str w10, [x6, #104] + WORD $0xaa0f03e6 // mov x6, x15 + WORD $0xb9006bce // str w14, [x30, #104] + WORD $0xb9406c6e // ldr w14, [x3, #108] + WORD $0xb9006a42 // str w2, [x18, #104] + WORD $0xaa1203e3 // mov x3, x18 + WORD $0xb9006d28 // str w8, [x9, #108] + WORD $0xf9409be8 // ldr x8, [sp, #304] + WORD $0xb9004bec // str w12, [sp, #72] + WORD $0xaa1503e2 // mov x2, x21 + WORD $0xb9006e24 // str w4, [x17, #108] + WORD $0xaa1903e4 // mov x4, x25 + WORD $0x294da50a // ldp w10, w9, [x8, #108] + WORD $0x294f23ec // ldp w12, w8, [sp, #120] + WORD $0xb9006ca8 // str w8, [x5, #108] + WORD $0xf940bbe8 // ldr x8, [sp, #368] + WORD $0xb9006dec // str w12, [x15, #108] + WORD $0xb94067ef // ldr w15, [sp, #100] + WORD $0xa95433e5 // ldp x5, x12, [sp, #320] + WORD $0x294e2112 // ldp w18, w8, [x8, #112] + WORD $0xb94070b1 // ldr w17, [x5, #112] + WORD $0xb9005be8 // str w8, [sp, #88] + WORD $0xb94073e8 // ldr w8, [sp, #112] + WORD $0xb9006c28 // str w8, [x1, #108] + WORD $0x294e3188 // ldp w8, w12, [x12, #112] + WORD $0xb9006eef // str w15, [x23, #108] + WORD $0xb94053ef // ldr w15, [sp, #80] + WORD $0xb9004fec // str w12, [sp, #76] + WORD $0xb9406bec // ldr w12, [sp, #104] + WORD $0xb9006eac // str w12, [x21, #108] + WORD $0xb94063ec // ldr w12, [sp, #96] + WORD $0xb9006f2c // str w12, [x25, #108] + WORD $0xb94074ac // ldr w12, [x5, #116] + WORD $0xaa1b03f9 // mov x25, x27 + WORD $0xb9007fec // str w12, [sp, #124] + WORD $0xb94077ec // ldr w12, [sp, #116] + WORD $0xb9006f6c // str w12, [x27, #108] + WORD $0xf9409fec // ldr x12, [sp, #312] + WORD $0xb9006f8f // str w15, [x28, #108] + WORD $0xb94057ef // ldr w15, [sp, #84] + WORD $0xb9006e8d // str w13, [x20, #108] + WORD $0xaa1c03fb // mov x27, x28 + WORD $0x294e3181 // ldp w1, w12, [x12, #112] + WORD $0xaa1603fc // mov x28, x22 + WORD $0xb9006e6f // str w15, [x19, #108] + WORD $0xb9006f0a // str w10, [x24, #108] + WORD $0xf9408fea // ldr x10, [sp, #280] + WORD $0xb9404bef // ldr w15, [sp, #72] + WORD $0xb90067ec // str w12, [sp, #100] + WORD $0xb9006d6f // str w15, [x11, #108] + WORD $0xa9583fec // ldp x12, x15, [sp, #384] + WORD $0x294e318d // ldp w13, w12, [x12, #112] + WORD $0xb9007bec // str w12, [sp, #120] + WORD $0x294e294c // ldp w12, w10, [x10, #112] + WORD $0xb90077ea // str w10, [sp, #116] + WORD $0xb9405fea // ldr w10, [sp, #92] + WORD $0xb9006fca // str w10, [x30, #108] + WORD $0xb94071ea // ldr w10, [x15, #112] + WORD $0xb9006c6e // str w14, [x3, #108] + WORD $0xb94075ee // ldr w14, [x15, #116] + WORD $0xf94067ef // ldr x15, [sp, #200] + WORD $0xb90057ee // str w14, [sp, #84] + WORD $0xf94093ee // ldr x14, [sp, #288] + WORD $0xb90071f2 // str w18, [x15, #112] + WORD $0xb90072c8 // str w8, [x22, #112] + WORD $0xaa1703f6 // mov x22, x23 + WORD $0xb94075c8 // ldr w8, [x14, #116] + WORD $0xb9007211 // str w17, [x16, #112] + WORD $0xb90070c1 // str w1, [x6, #112] + WORD $0xb94071d2 // ldr w18, [x14, #112] + WORD $0xb90070ed // str w13, [x7, #112] + WORD $0xaa0603ee // mov x14, x6 + WORD $0xb90073e8 // str w8, [sp, #112] + WORD $0xb90072ec // str w12, [x23, #112] + WORD $0xaa0703e1 // mov x1, x7 + WORD $0xb90072aa // str w10, [x21, #112] + WORD $0xa9552be8 // ldp x8, x10, [sp, #336] + WORD $0xb9407111 // ldr w17, [x8, #112] + WORD $0xb9007092 // str w18, [x4, #112] + WORD $0xb9407508 // ldr w8, [x8, #116] + WORD $0xaa1903f2 // mov x18, x25 + WORD $0xaa0403f7 // mov x23, x4 + WORD $0xaa1803e7 // mov x7, x24 + WORD $0xb9007331 // str w17, [x25, #112] + WORD $0xaa1403f9 // mov x25, x20 + WORD $0xb9006fe8 // str w8, [sp, #108] + WORD $0xf940b3e8 // ldr x8, [sp, #352] + WORD $0xaa1003e4 // mov x4, x16 + WORD $0xaa1303e6 // mov x6, x19 + WORD $0x294e210d // ldp w13, w8, [x8, #112] + WORD $0xb900736d // str w13, [x27, #112] + WORD $0xb9404fed // ldr w13, [sp, #76] + WORD $0xb90053e8 // str w8, [sp, #80] + WORD $0xf94097e8 // ldr x8, [sp, #296] + WORD $0x294e210c // ldp w12, w8, [x8, #112] + WORD $0xb900728c // str w12, [x20, #112] + WORD $0xaa0303f4 // mov x20, x3 + WORD $0xb9005fe8 // str w8, [sp, #92] + WORD $0xf9408be8 // ldr x8, [sp, #272] + WORD $0x294e2111 // ldp w17, w8, [x8, #112] + WORD $0xb9007271 // str w17, [x19, #112] + WORD $0xb9407151 // ldr w17, [x10, #112] + WORD $0xb9006be8 // str w8, [sp, #104] + WORD $0xf940b7e8 // ldr x8, [sp, #360] + WORD $0xb9007309 // str w9, [x24, #112] + WORD $0xf940bfe9 // ldr x9, [sp, #376] + WORD $0xb940754a // ldr w10, [x10, #116] + WORD $0xaa1c03f8 // mov x24, x28 + WORD $0x294e210c // ldp w12, w8, [x8, #112] + WORD $0xb9407122 // ldr w2, [x9, #112] + WORD $0xb900716c // str w12, [x11, #112] + WORD $0xb90063e8 // str w8, [sp, #96] + WORD $0xb9407528 // ldr w8, [x9, #116] + WORD $0xb90073d1 // str w17, [x30, #112] + WORD $0xaa0f03fe // mov x30, x15 + WORD $0xb9007062 // str w2, [x3, #112] + WORD $0xb94078a3 // ldr w3, [x5, #120] + WORD $0xb9004be8 // str w8, [sp, #72] + WORD $0xb9405be8 // ldr w8, [sp, #88] + WORD $0xb90075e8 // str w8, [x15, #116] + WORD $0xf940bbe8 // ldr x8, [sp, #368] + WORD $0xb900778d // str w13, [x28, #116] + WORD $0xf940a7ed // ldr x13, [sp, #328] + WORD $0xf940c3ef // ldr x15, [sp, #384] + WORD $0xaa1a03fc // mov x28, x26 + WORD $0x294f210c // ldp w12, w8, [x8, #120] + WORD $0x294f35b1 // ldp w17, w13, [x13, #120] + WORD $0xb90173e8 // str w8, [sp, #368] + WORD $0xb9014bed // str w13, [sp, #328] + WORD $0x294f23ed // ldp w13, w8, [sp, #120] + WORD $0xb9007608 // str w8, [x16, #116] + WORD $0xaa0e03e8 // mov x8, x14 + WORD $0xb94067ee // ldr w14, [sp, #100] + WORD $0xb9405ff0 // ldr w16, [sp, #92] + WORD $0xb900750e // str w14, [x8, #116] + WORD $0xb900742d // str w13, [x1, #116] + WORD $0x294e37ee // ldp w14, w13, [sp, #112] + WORD $0xb90076cd // str w13, [x22, #116] + WORD $0xb9407cad // ldr w13, [x5, #124] + WORD $0xb90143ed // str w13, [sp, #320] + WORD $0xb94057ed // ldr w13, [sp, #84] + WORD $0xb90076ad // str w13, [x21, #116] + WORD $0xa95337e5 // ldp x5, x13, [sp, #304] + WORD $0xb90076ee // str w14, [x23, #116] + WORD $0xb94074ae // ldr w14, [x5, #116] + WORD $0x294f35a2 // ldp w2, w13, [x13, #120] + WORD $0xb9007fed // str w13, [sp, #124] + WORD $0xb9406fed // ldr w13, [sp, #108] + WORD $0xb900764d // str w13, [x18, #116] + WORD $0xb94053ed // ldr w13, [sp, #80] + WORD $0xb900776d // str w13, [x27, #116] + WORD $0x294f3ded // ldp w13, w15, [x15, #120] + WORD $0xb9007730 // str w16, [x25, #116] + WORD $0xb9013bef // str w15, [sp, #312] + WORD $0xb9406bef // ldr w15, [sp, #104] + WORD $0xb900766f // str w15, [x19, #116] + WORD $0xb94078b3 // ldr w19, [x5, #120] + WORD $0xb90074ee // str w14, [x7, #116] + WORD $0xf9408fee // ldr x14, [sp, #280] + WORD $0xb94063ef // ldr w15, [sp, #96] + WORD $0xf940c7e5 // ldr x5, [sp, #392] + WORD $0x294f39d0 // ldp w16, w14, [x14, #120] + WORD $0xb900756f // str w15, [x11, #116] + WORD $0xb9404bef // ldr w15, [sp, #72] + WORD $0xb900774a // str w10, [x26, #116] + WORD $0xaa1403ea // mov x10, x20 + WORD $0xb90183ee // str w14, [sp, #384] + WORD $0x294f68ae // ldp w14, w26, [x5, #120] + WORD $0xb900768f // str w15, [x20, #116] + WORD $0xf94093e5 // ldr x5, [sp, #288] + WORD $0xb9007bcc // str w12, [x30, #120] + WORD $0xaa1e03ef // mov x15, x30 + WORD $0xb9007b11 // str w17, [x24, #120] + WORD $0xf940abf1 // ldr x17, [sp, #336] + WORD $0xb9007883 // str w3, [x4, #120] + WORD $0xb94078ac // ldr w12, [x5, #120] + WORD $0xb9007902 // str w2, [x8, #120] + WORD $0xaa0803e2 // mov x2, x8 + WORD $0xb900782d // str w13, [x1, #120] + WORD $0xf940b3e8 // ldr x8, [sp, #352] + WORD $0xb9007ad0 // str w16, [x22, #120] + WORD $0xaa1803fe // mov x30, x24 + WORD $0xb9007aae // str w14, [x21, #120] + WORD $0xf94097ee // ldr x14, [sp, #296] + WORD $0xb9407cb8 // ldr w24, [x5, #124] + WORD $0xb9007aec // str w12, [x23, #120] + WORD $0x294f5223 // ldp w3, w20, [x17, #120] + WORD $0x294f150d // ldp w13, w5, [x8, #120] + WORD $0xb9007a43 // str w3, [x18, #120] + WORD $0x294f45c8 // ldp w8, w17, [x14, #120] + WORD $0xb9007b6d // str w13, [x27, #120] + WORD $0xf9408bee // ldr x14, [sp, #272] + WORD $0xf940b7f0 // ldr x16, [sp, #360] + WORD $0xb9007b28 // str w8, [x25, #120] + WORD $0xf940afe8 // ldr x8, [sp, #344] + WORD $0xb94079c3 // ldr w3, [x14, #120] + WORD $0xb9407a0c // ldr w12, [x16, #120] + WORD $0xb940792d // ldr w13, [x9, #120] + WORD $0xb90078c3 // str w3, [x6, #120] + WORD $0xb9407903 // ldr w3, [x8, #120] + WORD $0xb90078f3 // str w19, [x7, #120] + WORD $0xb9407e13 // ldr w19, [x16, #124] + WORD $0xb900796c // str w12, [x11, #120] + WORD $0xaa0b03f0 // mov x16, x11 + WORD $0xb9407d0b // ldr w11, [x8, #124] + WORD $0xb9007b83 // str w3, [x28, #120] + WORD $0xb94173e8 // ldr w8, [sp, #368] + WORD $0xb900794d // str w13, [x10, #120] + WORD $0xb9407dce // ldr w14, [x14, #124] + WORD $0xb9407d23 // ldr w3, [x9, #124] + WORD $0xb9007de8 // str w8, [x15, #124] + WORD $0xb9414be8 // ldr w8, [sp, #328] + WORD $0xb9007fc8 // str w8, [x30, #124] + WORD $0xb94143e8 // ldr w8, [sp, #320] + WORD $0xb9007c88 // str w8, [x4, #124] + WORD $0xb9407fe8 // ldr w8, [sp, #124] + WORD $0xb9007c48 // str w8, [x2, #124] + WORD $0xb9413be8 // ldr w8, [sp, #312] + WORD $0xb9007c28 // str w8, [x1, #124] + WORD $0xb94183e8 // ldr w8, [sp, #384] + WORD $0xb9007ec8 // str w8, [x22, #124] + WORD $0xf9409be8 // ldr x8, [sp, #304] + WORD $0xb9007eba // str w26, [x21, #124] + WORD $0xa9486bec // ldp x12, x26, [sp, #128] + WORD $0xb9007ef8 // str w24, [x23, #124] + WORD $0xb9407d08 // ldr w8, [x8, #124] + WORD $0xb9007e54 // str w20, [x18, #124] + WORD $0xb9007f65 // str w5, [x27, #124] + WORD $0xb9007f31 // str w17, [x25, #124] + WORD $0x9100418c // add x12, x12, #16 + WORD $0xb9007cce // str w14, [x6, #124] + WORD $0xb9007ce8 // str w8, [x7, #124] + WORD $0xf9400fe8 // ldr x8, [sp, #24] + WORD $0xb9007e13 // str w19, [x16, #124] + WORD $0xb9007f8b // str w11, [x28, #124] + WORD $0xeb08019f // cmp x12, x8 + WORD $0xb9007d43 // str w3, [x10, #124] + BNE LBB0_158 + + // %bb.159: + WORD $0xa94123f3 // ldp x19, x8, [sp, #16] + WORD $0xf94007e0 // ldr x0, [sp, #8] + WORD $0xeb13011f // cmp x8, x19 + BEQ LBB0_156 + JMP LBB0_12 +LBB0_156: + WORD $0x531b6a60 // lsl w0, w19, #5 + WORD $0x910003bf // mov sp, x29 + WORD $0xa9454ff4 // ldp x20, x19, [sp, #80] + WORD $0xa94457f6 // ldp x22, x21, [sp, #64] + WORD $0xa9435ff8 // ldp x24, x23, [sp, #48] + WORD $0xa94267fa // ldp x26, x25, [sp, #32] + WORD $0xa9416ffc // ldp x28, x27, [sp, #16] + WORD $0xa8c67bfd // ldp x29, x30, [sp], #96 + MOVD R0, num+32(FP) + RET diff --git a/go/parquet/internal/utils/clib_amd64.s b/go/parquet/internal/utils/clib_amd64.s index 07258bd2f9652..b1534d4cf18f6 100644 --- a/go/parquet/internal/utils/clib_amd64.s +++ b/go/parquet/internal/utils/clib_amd64.s @@ -44,6 +44,15 @@ MEMCPY_BYTE_DONE: POPQ R8 RET +// func _ClibMemcpy(dst, src unsafe.Pointer, n uint) unsafe.Pointer +TEXT ·_ClibMemcpy(SB), NOSPLIT|NOFRAME, $16-24 + MOVQ arg1+0(FP), DI + MOVQ arg2+8(FP), SI + MOVQ arg3+16(FP), DX + CALL clib·_memcpy(SB) + MOVQ AX, ret+24(FP) + RET + // void *memset(void *str, int c, size_t n) // DI = str, SI = c, DX = size TEXT clib·_memset(SB), $16-0 @@ -85,3 +94,12 @@ MEMSET_BYTE_DONE: MOVQ DI, AX // set return value POPQ CX RET + +// func _ClibMemset(dst unsafe.Pointer, c int, n uint) unsafe.Pointer +TEXT ·_ClibMemset(SB), NOSPLIT|NOFRAME, $16-24 + MOVQ arg1+0(FP), DI + MOVQ arg2+8(FP), SI + MOVQ arg3+16(FP), DX + CALL clib·_memset(SB) + MOVQ AX, ret+24(FP) + RET From 161510e4131976712ea1588c7649b4ccdebdb5e0 Mon Sep 17 00:00:00 2001 From: Alenka Frim Date: Thu, 5 Oct 2023 17:16:09 +0200 Subject: [PATCH 51/56] GH-37145: [Python] support boolean columns with bitsize 1 in from_dataframe (#37975) ### Rationale for this change Bit-packed booleans are currently not supported in the `from_dataframe` of the Dataframe Interchange Protocol. Note: We currently represent booleans in the pyarrow implementation as `uint8` which will also need to be changed in a follow-up PR (see https://github.com/data-apis/dataframe-api/issues/227). ### What changes are included in this PR? This PR adds the support for bit-packed booleans when consuming a dataframe interchange object. ### Are these changes tested? Only locally, currently! * Closes: #37145 Lead-authored-by: AlenkaF Co-authored-by: Alenka Frim Signed-off-by: AlenkaF --- python/pyarrow/interchange/from_dataframe.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/python/pyarrow/interchange/from_dataframe.py b/python/pyarrow/interchange/from_dataframe.py index d653054e910a6..e97e91e44fb52 100644 --- a/python/pyarrow/interchange/from_dataframe.py +++ b/python/pyarrow/interchange/from_dataframe.py @@ -54,7 +54,8 @@ DtypeKind.FLOAT: {16: pa.float16(), 32: pa.float32(), 64: pa.float64()}, - DtypeKind.BOOL: {8: pa.uint8()}, + DtypeKind.BOOL: {1: pa.bool_(), + 8: pa.uint8()}, DtypeKind.STRING: {8: pa.string()}, } @@ -232,19 +233,23 @@ def bool_column_to_array( ------- pa.Array """ - if not allow_copy: + buffers = col.get_buffers() + size = buffers["data"][1][1] + + # If booleans are byte-packed a copy to bit-packed will be made + if size == 8 and not allow_copy: raise RuntimeError( "Boolean column will be casted from uint8 and a copy " "is required which is forbidden by allow_copy=False" ) - buffers = col.get_buffers() data_type = col.dtype data = buffers_to_array(buffers, data_type, col.size(), col.describe_null, col.offset) - data = pc.cast(data, pa.bool_()) + if size == 8: + data = pc.cast(data, pa.bool_()) return data From 1b262a29e5cddb2534457fadfe0b77bd7767f297 Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Thu, 5 Oct 2023 17:27:20 +0200 Subject: [PATCH 52/56] GH-37437: [C++] Fix MakeArrayOfNull for list array with large string values type (#37467) ### Rationale for this change `MakeArrayOfNull` for list type was assuming that the values child field didn't need to be considered, but those values could also require a minimum buffer size (eg for offsets) and which could be of greater size than the list offsets if those are int32 offsets. ### Are these changes tested? Yes * Closes: #37437 Authored-by: Joris Van den Bossche Signed-off-by: Antoine Pitrou --- cpp/src/arrow/array/array_test.cc | 5 +++++ cpp/src/arrow/array/util.cc | 6 ++++-- cpp/src/arrow/array/validate.cc | 4 +++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/cpp/src/arrow/array/array_test.cc b/cpp/src/arrow/array/array_test.cc index 0b82a82fbdb26..2bef9d725d37f 100644 --- a/cpp/src/arrow/array/array_test.cc +++ b/cpp/src/arrow/array/array_test.cc @@ -388,7 +388,12 @@ static std::vector> TestArrayUtilitiesAgainstTheseType large_utf8(), list(utf8()), list(int64()), // NOTE: Regression case for ARROW-9071/MakeArrayOfNull + list(large_utf8()), + list(list(int64())), + list(list(large_utf8())), + large_list(utf8()), large_list(large_utf8()), + large_list(list(large_utf8())), fixed_size_list(utf8(), 3), fixed_size_list(int64(), 4), dictionary(int32(), utf8()), diff --git a/cpp/src/arrow/array/util.cc b/cpp/src/arrow/array/util.cc index e84ab404ad6e3..98e9d51b5fc75 100644 --- a/cpp/src/arrow/array/util.cc +++ b/cpp/src/arrow/array/util.cc @@ -366,9 +366,11 @@ class NullArrayFactory { } template - enable_if_var_size_list Visit(const T&) { + enable_if_var_size_list Visit(const T& type) { // values array may be empty, but there must be at least one offset of 0 - return MaxOf(sizeof(typename T::offset_type) * (length_ + 1)); + RETURN_NOT_OK(MaxOf(sizeof(typename T::offset_type) * (length_ + 1))); + RETURN_NOT_OK(MaxOf(GetBufferLength(type.value_type(), length_))); + return Status::OK(); } template diff --git a/cpp/src/arrow/array/validate.cc b/cpp/src/arrow/array/validate.cc index 0f2bd4583574e..19ff8e28b536c 100644 --- a/cpp/src/arrow/array/validate.cc +++ b/cpp/src/arrow/array/validate.cc @@ -713,8 +713,10 @@ struct ValidateArrayImpl { } // An empty list array can have 0 offsets - const auto required_offsets = (data.length > 0) ? data.length + data.offset + 1 : 0; const auto offsets_byte_size = data.buffers[1]->size(); + const auto required_offsets = ((data.length > 0) || (offsets_byte_size > 0)) + ? data.length + data.offset + 1 + : 0; if (offsets_byte_size / static_cast(sizeof(offset_type)) < required_offsets) { return Status::Invalid("Offsets buffer size (bytes): ", offsets_byte_size, From 1eec38d833ca57ad826cea57f85d68532172c88c Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Thu, 5 Oct 2023 09:24:40 -0700 Subject: [PATCH 53/56] GH-37574: [Python] Compatibilty with numpy 2.0 (#38040) ### What changes are included in this PR? support for numpy 2 install numpy 2 and pandas 2.2.0.dev0 from scientific-python-nightly-wheels ### Are these changes tested? I tested this locally with numpy==2.0.0.dev0 and pandas==2.2.0.dev0+325.g6c58a217f5 ### Are there any user-facing changes? No * Closes: #37574 Authored-by: Thomas Grainger Signed-off-by: Joris Van den Bossche --- ci/scripts/install_pandas.sh | 4 ++-- python/pyarrow/pandas_compat.py | 7 ++++--- python/pyarrow/tests/test_pandas.py | 22 +++++++++++++++------- python/pyarrow/tests/test_scalars.py | 4 +++- 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/ci/scripts/install_pandas.sh b/ci/scripts/install_pandas.sh index f0cb76fb663e0..6a506a86514fa 100755 --- a/ci/scripts/install_pandas.sh +++ b/ci/scripts/install_pandas.sh @@ -28,7 +28,7 @@ pandas=$1 numpy=${2:-"latest"} if [ "${numpy}" = "nightly" ]; then - pip install --extra-index-url https://pypi.anaconda.org/scipy-wheels-nightly/simple --pre numpy + pip install --extra-index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple --pre numpy elif [ "${numpy}" = "latest" ]; then pip install numpy else @@ -38,7 +38,7 @@ fi if [ "${pandas}" = "upstream_devel" ]; then pip install git+https://github.com/pandas-dev/pandas.git elif [ "${pandas}" = "nightly" ]; then - pip install --extra-index-url https://pypi.anaconda.org/scipy-wheels-nightly/simple --pre pandas + pip install --extra-index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple --pre pandas elif [ "${pandas}" = "latest" ]; then pip install pandas else diff --git a/python/pyarrow/pandas_compat.py b/python/pyarrow/pandas_compat.py index 4e5c868efd4c8..e232603ba45ac 100644 --- a/python/pyarrow/pandas_compat.py +++ b/python/pyarrow/pandas_compat.py @@ -31,6 +31,7 @@ import warnings import numpy as np +from numpy.core.numerictypes import sctypes as _np_sctypes import pyarrow as pa from pyarrow.lib import _pandas_api, frombytes # noqa @@ -98,7 +99,7 @@ def get_logical_type(arrow_type): np.float32: 'float32', np.float64: 'float64', 'datetime64[D]': 'date', - np.unicode_: 'string', + np.str_: 'string', np.bytes_: 'bytes', } @@ -780,7 +781,7 @@ def table_to_blockmanager(options, table, categories=None, # dataframe (complex not included since not supported by Arrow) _pandas_supported_numpy_types = { str(np.dtype(typ)) - for typ in (np.sctypes['int'] + np.sctypes['uint'] + np.sctypes['float'] + + for typ in (_np_sctypes['int'] + _np_sctypes['uint'] + _np_sctypes['float'] + ['object', 'bool']) } @@ -1010,7 +1011,7 @@ def _is_generated_index_name(name): 'date': 'datetime64[D]', 'datetime': 'datetime64[ns]', 'datetimetz': 'datetime64[ns]', - 'unicode': np.unicode_, + 'unicode': np.str_, 'bytes': np.bytes_, 'string': np.str_, 'integer': np.int64, diff --git a/python/pyarrow/tests/test_pandas.py b/python/pyarrow/tests/test_pandas.py index 67502af443302..0d01928f44734 100644 --- a/python/pyarrow/tests/test_pandas.py +++ b/python/pyarrow/tests/test_pandas.py @@ -50,6 +50,14 @@ pass +try: + _np_VisibleDeprecationWarning = np.VisibleDeprecationWarning +except AttributeError: + from numpy.exceptions import ( + VisibleDeprecationWarning as _np_VisibleDeprecationWarning + ) + + # Marks all of the tests in this module pytestmark = pytest.mark.pandas @@ -706,7 +714,7 @@ def test_float_nulls(self): def test_float_nulls_to_ints(self): # ARROW-2135 - df = pd.DataFrame({"a": [1.0, 2.0, np.NaN]}) + df = pd.DataFrame({"a": [1.0, 2.0, np.nan]}) schema = pa.schema([pa.field("a", pa.int16(), nullable=True)]) table = pa.Table.from_pandas(df, schema=schema, safe=False) assert table[0].to_pylist() == [1, 2, None] @@ -2329,7 +2337,7 @@ def test_nested_large_list(self): with warnings.catch_warnings(): warnings.filterwarnings("ignore", "Creating an ndarray from ragged nested", - np.VisibleDeprecationWarning) + _np_VisibleDeprecationWarning) warnings.filterwarnings("ignore", "elementwise comparison failed", DeprecationWarning) tm.assert_series_equal( @@ -2441,26 +2449,26 @@ def test_list_no_duplicate_base(self): np_arr = chunked_arr.to_numpy() expected = np.array([[1., 2.], [3., 4., 5.], None, - [6., np.NaN]], dtype="object") + [6., np.nan]], dtype="object") for left, right in zip(np_arr, expected): if right is None: assert left == right else: npt.assert_array_equal(left, right) - expected_base = np.array([[1., 2., 3., 4., 5., 6., np.NaN]]) + expected_base = np.array([[1., 2., 3., 4., 5., 6., np.nan]]) npt.assert_array_equal(np_arr[0].base, expected_base) np_arr_sliced = chunked_arr.slice(1, 3).to_numpy() - expected = np.array([[3, 4, 5], None, [6, np.NaN]], dtype="object") + expected = np.array([[3, 4, 5], None, [6, np.nan]], dtype="object") for left, right in zip(np_arr_sliced, expected): if right is None: assert left == right else: npt.assert_array_equal(left, right) - expected_base = np.array([[3., 4., 5., 6., np.NaN]]) + expected_base = np.array([[3., 4., 5., 6., np.nan]]) npt.assert_array_equal(np_arr_sliced[0].base, expected_base) def test_list_values_behind_null(self): @@ -2471,7 +2479,7 @@ def test_list_values_behind_null(self): ) np_arr = arr.to_numpy(zero_copy_only=False) - expected = np.array([[1., 2.], None, [3., np.NaN]], dtype="object") + expected = np.array([[1., 2.], None, [3., np.nan]], dtype="object") for left, right in zip(np_arr, expected): if right is None: assert left == right diff --git a/python/pyarrow/tests/test_scalars.py b/python/pyarrow/tests/test_scalars.py index 8a1dcfb057f74..1d8d77f50dac8 100644 --- a/python/pyarrow/tests/test_scalars.py +++ b/python/pyarrow/tests/test_scalars.py @@ -204,7 +204,9 @@ def test_numerics(): # float16 s = pa.scalar(np.float16(0.5), type='float16') assert isinstance(s, pa.HalfFloatScalar) - assert repr(s) == "" + # on numpy2 repr(np.float16(0.5)) == "np.float16(0.5)" + # on numpy1 repr(np.float16(0.5)) == "0.5" + assert repr(s) == f"" assert str(s) == "0.5" assert s.as_py() == 0.5 From f5e40dc45ba3465dfaf1c32af020b63a294b6982 Mon Sep 17 00:00:00 2001 From: Kevin Gurney Date: Thu, 5 Oct 2023 12:25:56 -0400 Subject: [PATCH 54/56] GH-37978: [C++] Add support for specifying custom Array element delimiter to `arrow::PrettyPrintOptions` (#37981) ### Rationale for this change In order to make the [`arrow::PrettyPrint`](https://github.com/apache/arrow/blob/7667b81bffcb5b361fab6d61c42ce396d98cc6e1/cpp/src/arrow/pretty_print.h#L101) functionality for `arrow::Array`/`arrow::ChunkedArray` more flexible, it would be useful to be able to specify a custom element delimiter other than `","`. For example, the MATLAB interface wraps the Arrow C++ libraries and being able to specify a custom `Array` element delimiter, would make it possible to make the display of MATLAB `arrow.array.Array` objects more MATLAB-like. For the MATLAB interface, we would like to enable display that looks something like the following (note the ` | ` between individual `Array` elements): ```matlab % Make a MATLAB array. >> A = 1:5 A = 1 2 3 4 5 % Make an Arrow array from the MATLAB array. >> B = arrow.array(A) B = [ 1 | 2 | 3 | 4 | 5 ] ``` In order to support custom `Array` element delimiters, this pull request adds a new `struct` type `PrettyPrintDelimiters`. The `PrettyPrintDelimiters` type has one property `element` (of type `std::string`), which allows client code to control the delimiter used to distinguish between individual elements of an `arrow::Array` / `arrow::ChunkedArray`. In a future pull request, we plan to add more properties like `open` and `close` to allow client code to specify the opening and closing delimiters to use when printing an `arrow::Array` / `arrow::ChunkedArray` (e.g. `"<"` rather than `"["` and `">"` rather than `"]"`). ### What changes are included in this PR? 1. Added a new `struct` type `PrettyPrintDelimiters` with one property `element` (of type `std::string`). The `element` property allows client code to specify any string value as the delimiter to distinguish between individual elements of an `arrow::Array` or `arrow::ChunkedArray` when printing using `arrow::PrettyPrint`. 2. Added two new properties to `arrow::PrettyPrintOptions` - (1) `array_delimiters` (of type `arrow::PrettyPrintDelimiters`) and `chunked_array_delimiters` (of type `arrow::PrettyPrintDelimiters`). These properties can be modified to customize how `arrow::Arrow`/`arrow::ChunkedArray` are printed when using `arrow::PrettyPrint`. ### Are these changes tested? Yes. 1. Added new tests `ArrayCustomElementDelimiter` and `ChunkedArrayCustomElementDelimiter` to `pretty_print_test.cc`. 2. All existing `PrettyPrint`-related C++ tests pass. ### Are there any user-facing changes? Yes. 1. User's can now specify a custom element delimiter to use when printing `arrow::Array`s / `arrow::ChunkedArray`s using [`arrow::PrettyPrint`](https://github.com/apache/arrow/blob/7667b81bffcb5b361fab6d61c42ce396d98cc6e1/cpp/src/arrow/pretty_print.h#L101) by modifying the `array_delimiters` or `chunked_array_delimiters` properties of `arrow::PrettyPrintOptions`. **Example**: ```cpp auto array = ...; auto stream = ... arrow::PrettyPrintOptions options = arrow::PrettyPrintOptions::Defaults(); // Use " | " as the element-wise (element = scalar value) delimiter for arrow::Array. options.array_delimiters.element = " | "; // Use "';" as the element-wise (element = chunk) delimiter for arrow::ChunkedArray. options.chunked_array_delimiters.element = ";"; arrow::PrettyPrint(array, options, stream); ``` ### Future Directions 1. To keep this pull request small and focused, I intentionally chose not to include changes related to specifying custom opening and closing `Array` delimiters (e.g. use `<` and `>` instead of `[` and `]`). I've captured the idea of supporting custom opening and closing `Array` delimiters in #37979. I will follow up with a future PR to address this. ### Notes 1. This pull request was motivated by our desire to improve the display of Arrow related classes in the MATLAB interface, but it is hopefully a generic enough change that it may benefit other use cases too. 3. @ rok helpfully pointed out in https://github.com/apache/arrow/issues/37978#issuecomment-1743715458 that a similar attempt to modify the default `Array` element delimiter to be `", "` (note the space after the comma) was taken in #30951. However, this issue appears to have gone stale and the PR (https://github.com/apache/arrow/pull/12420) that was opened also seems to have gone stale. If these changes get merged, it may make sense to close out this issue since this one seems to at least partially address it (although, it isn't exactly the same, since it doesn't change the default delimiter to be `", "`. However, for `PyArrow`, `array_delimiters.element` and `chunked_array_delimiters.element` could just be set to `", "` after merging these changes to change the default display if that is still desirable). * Closes: #37978 Authored-by: Kevin Gurney Signed-off-by: Kevin Gurney --- cpp/src/arrow/pretty_print.cc | 19 ++--- cpp/src/arrow/pretty_print.h | 23 +++++- cpp/src/arrow/pretty_print_test.cc | 111 +++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+), 10 deletions(-) diff --git a/cpp/src/arrow/pretty_print.cc b/cpp/src/arrow/pretty_print.cc index 03e2051c2fb88..a4a1fa90c2878 100644 --- a/cpp/src/arrow/pretty_print.cc +++ b/cpp/src/arrow/pretty_print.cc @@ -151,14 +151,14 @@ class ArrayPrinter : public PrettyPrinter { IndentAfterNewline(); (*sink_) << "..."; if (!is_last && options_.skip_new_lines) { - (*sink_) << ","; + (*sink_) << options_.array_delimiters.element; } i = array.length() - window - 1; } else if (array.IsNull(i)) { IndentAfterNewline(); (*sink_) << options_.null_rep; if (!is_last) { - (*sink_) << ","; + (*sink_) << options_.array_delimiters.element; } } else { if (indent_non_null_values) { @@ -166,7 +166,7 @@ class ArrayPrinter : public PrettyPrinter { } RETURN_NOT_OK(func(i)); if (!is_last) { - (*sink_) << ","; + (*sink_) << options_.array_delimiters.element; } } Newline(); @@ -453,12 +453,12 @@ Status PrettyPrint(const ChunkedArray& chunked_arr, const PrettyPrintOptions& op if (!skip_new_lines) { *sink << "\n"; } - bool skip_comma = true; + bool skip_element_delimiter = true; for (int i = 0; i < num_chunks; ++i) { - if (skip_comma) { - skip_comma = false; + if (skip_element_delimiter) { + skip_element_delimiter = false; } else { - (*sink) << ","; + (*sink) << options.chunked_array_delimiters.element; if (!skip_new_lines) { *sink << "\n"; } @@ -467,12 +467,13 @@ Status PrettyPrint(const ChunkedArray& chunked_arr, const PrettyPrintOptions& op for (int i = 0; i < indent; ++i) { (*sink) << " "; } - (*sink) << "...,"; + (*sink) << "..."; + (*sink) << options.chunked_array_delimiters.element; if (!skip_new_lines) { *sink << "\n"; } i = num_chunks - window - 1; - skip_comma = true; + skip_element_delimiter = true; } else { PrettyPrintOptions chunk_options = options; chunk_options.indent += options.indent_size; diff --git a/cpp/src/arrow/pretty_print.h b/cpp/src/arrow/pretty_print.h index 5d22fd5c51ab8..96a214c68b8a6 100644 --- a/cpp/src/arrow/pretty_print.h +++ b/cpp/src/arrow/pretty_print.h @@ -32,7 +32,21 @@ class Schema; class Status; class Table; -struct PrettyPrintOptions { +/// \class PrettyPrintDelimiters +/// \brief Options for controlling which delimiters to use when printing +/// an Array or ChunkedArray. +struct ARROW_EXPORT PrettyPrintDelimiters { + /// Delimiter for separating individual elements of an Array (e.g. ","), + /// or individual chunks of a ChunkedArray + std::string element = ","; + + /// Create a PrettyPrintDelimiters instance with default values + static PrettyPrintDelimiters Defaults() { return PrettyPrintDelimiters(); } +}; + +/// \class PrettyPrintOptions +/// \brief Options for controlling how various Arrow types should be printed. +struct ARROW_EXPORT PrettyPrintOptions { PrettyPrintOptions() = default; PrettyPrintOptions(int indent, // NOLINT runtime/explicit @@ -47,6 +61,7 @@ struct PrettyPrintOptions { skip_new_lines(skip_new_lines), truncate_metadata(truncate_metadata) {} + /// Create a PrettyPrintOptions instance with default values static PrettyPrintOptions Defaults() { return PrettyPrintOptions(); } /// Number of spaces to shift entire formatted object to the right @@ -77,6 +92,12 @@ struct PrettyPrintOptions { /// If true, display schema metadata when pretty-printing a Schema bool show_schema_metadata = true; + + /// Delimiters to use when printing an Array + PrettyPrintDelimiters array_delimiters = PrettyPrintDelimiters::Defaults(); + + /// Delimiters to use when printing a ChunkedArray + PrettyPrintDelimiters chunked_array_delimiters = PrettyPrintDelimiters::Defaults(); }; /// \brief Print human-readable representation of RecordBatch diff --git a/cpp/src/arrow/pretty_print_test.cc b/cpp/src/arrow/pretty_print_test.cc index 9a6e347c0bdb2..45bb4ecffe054 100644 --- a/cpp/src/arrow/pretty_print_test.cc +++ b/cpp/src/arrow/pretty_print_test.cc @@ -200,6 +200,65 @@ TEST_F(TestPrettyPrint, PrimitiveTypeNoNewlines) { CheckPrimitive(options, is_valid, values, expected, false); } +TEST_F(TestPrettyPrint, ArrayCustomElementDelimiter) { + PrettyPrintOptions options{}; + // Use a custom array element delimiter of " | ", + // rather than the default delimiter (i.e. ","). + options.array_delimiters.element = " | "; + + // Short array without ellipsis + { + std::vector is_valid = {true, true, false, true, false}; + std::vector values = {1, 2, 3, 4, 5}; + static const char* expected = R"expected([ + 1 | + 2 | + null | + 4 | + null +])expected"; + CheckPrimitive(options, is_valid, values, expected, false); + } + + // Longer array with ellipsis + { + std::vector is_valid = {true, false, true}; + std::vector values = {1, 2, 3}; + // Append 20 copies of the value "10" to the end of the values vector. + values.insert(values.end(), 20, 10); + // Append 20 copies of the value "true" to the end of the validity bitmap vector. + is_valid.insert(is_valid.end(), 20, true); + // Append the values 4, 5, and 6 to the end of the values vector. + values.insert(values.end(), {4, 5, 6}); + // Append the values true, false, and true to the end of the validity bitmap vector. + is_valid.insert(is_valid.end(), {true, false, true}); + static const char* expected = R"expected([ + 1 | + null | + 3 | + 10 | + 10 | + 10 | + 10 | + 10 | + 10 | + 10 | + ... + 10 | + 10 | + 10 | + 10 | + 10 | + 10 | + 10 | + 4 | + null | + 6 +])expected"; + CheckPrimitive(options, is_valid, values, expected, false); + } +} + TEST_F(TestPrettyPrint, Int8) { static const char* expected = R"expected([ 0, @@ -1020,6 +1079,58 @@ TEST_F(TestPrettyPrint, ChunkedArrayPrimitiveType) { CheckStream(chunked_array_2, {0}, expected_2); } +TEST_F(TestPrettyPrint, ChunkedArrayCustomElementDelimiter) { + PrettyPrintOptions options{}; + // Use a custom ChunkedArray element delimiter of ";", + // rather than the default delimiter (i.e. ","). + options.chunked_array_delimiters.element = ";"; + // Use a custom Array element delimiter of " | ", + // rather than the default delimiter (i.e. ","). + options.array_delimiters.element = " | "; + + const auto chunk = ArrayFromJSON(int32(), "[1, 2, null, 4, null]"); + + // ChunkedArray with 1 chunk + { + const ChunkedArray chunked_array(chunk); + + static const char* expected = R"expected([ + [ + 1 | + 2 | + null | + 4 | + null + ] +])expected"; + CheckStream(chunked_array, options, expected); + } + + // ChunkedArray with 2 chunks + { + const ChunkedArray chunked_array({chunk, chunk}); + + static const char* expected = R"expected([ + [ + 1 | + 2 | + null | + 4 | + null + ]; + [ + 1 | + 2 | + null | + 4 | + null + ] +])expected"; + + CheckStream(chunked_array, options, expected); + } +} + TEST_F(TestPrettyPrint, TablePrimitive) { std::shared_ptr int_field = field("column", int32()); auto array = ArrayFromJSON(int_field->type(), "[0, 1, null, 3, null]"); From 4b795ece70a424c4b9f163d07f1dbac5bc9f7f33 Mon Sep 17 00:00:00 2001 From: Curt Hagenlocher Date: Thu, 5 Oct 2023 09:42:46 -0700 Subject: [PATCH 55/56] GH-35243: [C#] Implement MapType (#37885) ### What changes are included in this PR? This change includes the original work by `@ Platob` from #35263, updated with the latest changes in the main branch. Additionally, it includes support in the C API for the Map type and fills a few gaps in functionality from the original change (for instance, ArrowArrayConcentrator support). Finally, it fixes a bug in the ArrowArrayConcentrator.Concatenate which prevented it from working correctly for structs. (This bug was discovered in the course of creating a test for concatenating maps.) ### Are these changes tested? Yes. ### Are there any user-facing changes? Maps are now supported in the C# implementation. Closes #35243 * Closes: #35243 Lead-authored-by: Platob Co-authored-by: Curt Hagenlocher Signed-off-by: David Li --- .../Arrays/ArrayDataConcatenator.cs | 28 +-- .../Arrays/ArrayDataTypeComparer.cs | 13 +- .../Apache.Arrow/Arrays/ArrowArrayFactory.cs | 3 +- csharp/src/Apache.Arrow/Arrays/BinaryArray.cs | 4 +- .../Arrays/FixedSizeBinaryArray.cs | 4 +- csharp/src/Apache.Arrow/Arrays/ListArray.cs | 12 +- csharp/src/Apache.Arrow/Arrays/MapArray.cs | 174 ++++++++++++++++++ .../src/Apache.Arrow/C/CArrowArrayImporter.cs | 3 + .../Apache.Arrow/C/CArrowSchemaExporter.cs | 6 +- .../Apache.Arrow/C/CArrowSchemaImporter.cs | 8 +- .../Ipc/ArrowTypeFlatbufferBuilder.cs | 10 +- .../src/Apache.Arrow/Ipc/MessageSerializer.cs | 7 + csharp/src/Apache.Arrow/Types/ListType.cs | 2 - csharp/src/Apache.Arrow/Types/MapType.cs | 58 ++++++ .../Apache.Arrow.IntegrationTest/JsonFile.cs | 25 +++ .../Apache.Arrow.Tests/ArrayTypeComparer.cs | 13 +- .../ArrowArrayConcatenatorTests.cs | 51 ++++- .../CDataInterfacePythonTests.cs | 15 +- .../test/Apache.Arrow.Tests/MapArrayTests.cs | 92 +++++++++ csharp/test/Apache.Arrow.Tests/TableTests.cs | 2 +- csharp/test/Apache.Arrow.Tests/TestData.cs | 23 ++- .../Apache.Arrow.Tests/Types/MapTypeTests.cs | 57 ++++++ dev/archery/archery/integration/datagen.py | 3 +- docs/source/status.rst | 2 +- 24 files changed, 577 insertions(+), 38 deletions(-) create mode 100644 csharp/src/Apache.Arrow/Arrays/MapArray.cs create mode 100644 csharp/src/Apache.Arrow/Types/MapType.cs create mode 100644 csharp/test/Apache.Arrow.Tests/MapArrayTests.cs create mode 100644 csharp/test/Apache.Arrow.Tests/Types/MapTypeTests.cs diff --git a/csharp/src/Apache.Arrow/Arrays/ArrayDataConcatenator.cs b/csharp/src/Apache.Arrow/Arrays/ArrayDataConcatenator.cs index 806defdc7ce66..a3b39923809bb 100644 --- a/csharp/src/Apache.Arrow/Arrays/ArrayDataConcatenator.cs +++ b/csharp/src/Apache.Arrow/Arrays/ArrayDataConcatenator.cs @@ -50,7 +50,8 @@ private class ArrayDataConcatenationVisitor : IArrowTypeVisitor, IArrowTypeVisitor, IArrowTypeVisitor, - IArrowTypeVisitor + IArrowTypeVisitor, + IArrowTypeVisitor { public ArrayData Result { get; private set; } private readonly IReadOnlyList _arrayDataList; @@ -92,15 +93,7 @@ public void Visit(FixedWidthType type) public void Visit(StringType type) => ConcatenateVariableBinaryArrayData(type); - public void Visit(ListType type) - { - CheckData(type, 2); - ArrowBuffer validityBuffer = ConcatenateValidityBuffer(); - ArrowBuffer offsetBuffer = ConcatenateOffsetBuffer(); - ArrayData child = Concatenate(SelectChildren(0), _allocator); - - Result = new ArrayData(type, _totalLength, _totalNullCount, 0, new ArrowBuffer[] { validityBuffer, offsetBuffer }, new[] { child }); - } + public void Visit(ListType type) => ConcatenateLists(type); public void Visit(FixedSizeListType type) { @@ -114,6 +107,7 @@ public void Visit(FixedSizeListType type) public void Visit(StructType type) { CheckData(type, 1); + ArrowBuffer validityBuffer = ConcatenateValidityBuffer(); List children = new List(type.Fields.Count); for (int i = 0; i < type.Fields.Count; i++) @@ -121,7 +115,7 @@ public void Visit(StructType type) children.Add(Concatenate(SelectChildren(i), _allocator)); } - Result = new ArrayData(type, _arrayDataList[0].Length, _arrayDataList[0].NullCount, 0, _arrayDataList[0].Buffers, children); + Result = new ArrayData(type, _totalLength, _totalNullCount, 0, new ArrowBuffer[] { validityBuffer }, children); } public void Visit(UnionType type) @@ -151,6 +145,8 @@ public void Visit(UnionType type) Result = new ArrayData(type, _totalLength, _totalNullCount, 0, buffers, children); } + public void Visit(MapType type) => ConcatenateLists(type.UnsortedKey()); /* Can't tell if the output is still sorted */ + public void Visit(IArrowType type) { throw new NotImplementedException($"Concatenation for {type.Name} is not supported yet."); @@ -175,6 +171,16 @@ private void ConcatenateVariableBinaryArrayData(IArrowType type) Result = new ArrayData(type, _totalLength, _totalNullCount, 0, new ArrowBuffer[] { validityBuffer, offsetBuffer, valueBuffer }); } + private void ConcatenateLists(NestedType type) + { + CheckData(type, 2); + ArrowBuffer validityBuffer = ConcatenateValidityBuffer(); + ArrowBuffer offsetBuffer = ConcatenateOffsetBuffer(); + ArrayData child = Concatenate(SelectChildren(0), _allocator); + + Result = new ArrayData(type, _totalLength, _totalNullCount, 0, new ArrowBuffer[] { validityBuffer, offsetBuffer }, new[] { child }); + } + private ArrowBuffer ConcatenateValidityBuffer() { if (_totalNullCount == 0) diff --git a/csharp/src/Apache.Arrow/Arrays/ArrayDataTypeComparer.cs b/csharp/src/Apache.Arrow/Arrays/ArrayDataTypeComparer.cs index 6b54ec1edb573..1698e0672fb60 100644 --- a/csharp/src/Apache.Arrow/Arrays/ArrayDataTypeComparer.cs +++ b/csharp/src/Apache.Arrow/Arrays/ArrayDataTypeComparer.cs @@ -28,7 +28,8 @@ internal sealed class ArrayDataTypeComparer : IArrowTypeVisitor, IArrowTypeVisitor, IArrowTypeVisitor, - IArrowTypeVisitor + IArrowTypeVisitor, + IArrowTypeVisitor { private readonly IArrowType _expectedType; private bool _dataTypeMatch; @@ -132,6 +133,16 @@ public void Visit(UnionType actualType) } } + public void Visit(MapType actualType) + { + if (_expectedType is MapType expectedType + && expectedType.KeySorted == actualType.KeySorted + && CompareNested(expectedType, actualType)) + { + _dataTypeMatch = true; + } + } + private static bool CompareNested(NestedType expectedType, NestedType actualType) { if (expectedType.Fields.Count != actualType.Fields.Count) diff --git a/csharp/src/Apache.Arrow/Arrays/ArrowArrayFactory.cs b/csharp/src/Apache.Arrow/Arrays/ArrowArrayFactory.cs index aa407203d1858..d3b7d65185abe 100644 --- a/csharp/src/Apache.Arrow/Arrays/ArrowArrayFactory.cs +++ b/csharp/src/Apache.Arrow/Arrays/ArrowArrayFactory.cs @@ -59,6 +59,8 @@ public static IArrowArray BuildArray(ArrayData data) return new TimestampArray(data); case ArrowTypeId.List: return new ListArray(data); + case ArrowTypeId.Map: + return new MapArray(data); case ArrowTypeId.Struct: return new StructArray(data); case ArrowTypeId.Union: @@ -86,7 +88,6 @@ public static IArrowArray BuildArray(ArrayData data) case ArrowTypeId.FixedSizeList: return new FixedSizeListArray(data); case ArrowTypeId.Interval: - case ArrowTypeId.Map: default: throw new NotSupportedException($"An ArrowArray cannot be built for type {data.DataType.TypeId}."); } diff --git a/csharp/src/Apache.Arrow/Arrays/BinaryArray.cs b/csharp/src/Apache.Arrow/Arrays/BinaryArray.cs index 4fd8059f6fe70..20fe0342cca40 100644 --- a/csharp/src/Apache.Arrow/Arrays/BinaryArray.cs +++ b/csharp/src/Apache.Arrow/Arrays/BinaryArray.cs @@ -237,7 +237,7 @@ public TBuilder Reserve(int capacity) // TODO: [ARROW-9366] Reserve capacity in the value buffer in a more sensible way. ValueOffsets.Reserve(capacity + 1); ValueBuffer.Reserve(capacity); - ValidityBuffer.Reserve(capacity + 1); + ValidityBuffer.Reserve(capacity); return Instance; } @@ -246,7 +246,7 @@ public TBuilder Resize(int length) // TODO: [ARROW-9366] Resize the value buffer to a safe length based on offsets, not `length`. ValueOffsets.Resize(length + 1); ValueBuffer.Resize(length); - ValidityBuffer.Resize(length + 1); + ValidityBuffer.Resize(length); return Instance; } diff --git a/csharp/src/Apache.Arrow/Arrays/FixedSizeBinaryArray.cs b/csharp/src/Apache.Arrow/Arrays/FixedSizeBinaryArray.cs index 7d3d8754747e9..866a674bc9df8 100644 --- a/csharp/src/Apache.Arrow/Arrays/FixedSizeBinaryArray.cs +++ b/csharp/src/Apache.Arrow/Arrays/FixedSizeBinaryArray.cs @@ -111,14 +111,14 @@ public TArray Build(MemoryAllocator allocator = default) public TBuilder Reserve(int capacity) { ValueBuffer.Reserve(capacity * ByteWidth); - ValidityBuffer.Reserve(capacity + 1); + ValidityBuffer.Reserve(capacity); return Instance; } public TBuilder Resize(int length) { ValueBuffer.Resize(length * ByteWidth); - ValidityBuffer.Resize(length + 1); + ValidityBuffer.Resize(length); return Instance; } diff --git a/csharp/src/Apache.Arrow/Arrays/ListArray.cs b/csharp/src/Apache.Arrow/Arrays/ListArray.cs index 97673cb48e6a8..4d2ff96a3d005 100644 --- a/csharp/src/Apache.Arrow/Arrays/ListArray.cs +++ b/csharp/src/Apache.Arrow/Arrays/ListArray.cs @@ -91,14 +91,14 @@ public ListArray Build(MemoryAllocator allocator = default) public Builder Reserve(int capacity) { ValueOffsetsBufferBuilder.Reserve(capacity + 1); - ValidityBufferBuilder.Reserve(capacity + 1); + ValidityBufferBuilder.Reserve(capacity); return this; } public Builder Resize(int length) { ValueOffsetsBufferBuilder.Resize(length + 1); - ValidityBufferBuilder.Resize(length + 1); + ValidityBufferBuilder.Resize(length); return this; } @@ -139,6 +139,14 @@ private ListArray(ArrayData data, IArrowArray values) : base(data) Values = values; } + // Constructor for child MapArray + internal ListArray(ArrayData data, IArrowArray values, ArrowTypeId typeId) : base(data) + { + data.EnsureBufferCount(2); + data.EnsureDataType(typeId); + Values = values; + } + public override void Accept(IArrowArrayVisitor visitor) => Accept(this, visitor); diff --git a/csharp/src/Apache.Arrow/Arrays/MapArray.cs b/csharp/src/Apache.Arrow/Arrays/MapArray.cs new file mode 100644 index 0000000000000..a6676b134e34a --- /dev/null +++ b/csharp/src/Apache.Arrow/Arrays/MapArray.cs @@ -0,0 +1,174 @@ +// 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 System; +using System.Collections.Generic; +using Apache.Arrow.Memory; +using Apache.Arrow.Types; + +namespace Apache.Arrow +{ + public class MapArray : ListArray // MapArray = ListArray(StructArray("key", "value")) + { + // Same as ListArray.Builder, but with KeyBuilder + public new class Builder : IArrowArrayBuilder + { + public IArrowArrayBuilder> KeyBuilder { get; } + public IArrowArrayBuilder> ValueBuilder { get; } + + public int Length => ValueOffsetsBufferBuilder.Length; + + private ArrowBuffer.Builder ValueOffsetsBufferBuilder { get; } + + private ArrowBuffer.BitmapBuilder ValidityBufferBuilder { get; } + + public int NullCount { get; protected set; } + + public MapType DataType { get; } + + public Builder(MapType type) + { + KeyBuilder = ArrowArrayBuilderFactory.Build(type.KeyField.DataType); + ValueBuilder = ArrowArrayBuilderFactory.Build(type.ValueField.DataType); + ValueOffsetsBufferBuilder = new ArrowBuffer.Builder(); + ValidityBufferBuilder = new ArrowBuffer.BitmapBuilder(); + DataType = type; + } + + /// + /// Start a new variable-length list slot + /// + /// This function should be called before beginning to append elements to the + /// value builder + /// + /// + public Builder Append() + { + ValueOffsetsBufferBuilder.Append(KeyBuilder.Length); + ValidityBufferBuilder.Append(true); + + return this; + } + + public Builder AppendNull() + { + ValueOffsetsBufferBuilder.Append(KeyBuilder.Length); + ValidityBufferBuilder.Append(false); + NullCount++; + + return this; + } + + public MapArray Build(MemoryAllocator allocator = default) + { + ValueOffsetsBufferBuilder.Append(KeyBuilder.Length); + + ArrowBuffer validityBuffer = NullCount > 0 ? ValidityBufferBuilder.Build(allocator) : ArrowBuffer.Empty; + + StructArray structs = new StructArray( + DataType.KeyValueType, KeyBuilder.Length, + new IArrowArray[] { KeyBuilder.Build(allocator), ValueBuilder.Build(allocator) }, + ArrowBuffer.Empty, 0 + ); + + return new MapArray(DataType, Length - 1, ValueOffsetsBufferBuilder.Build(allocator), structs, validityBuffer, NullCount); + } + + public Builder Reserve(int capacity) + { + ValueOffsetsBufferBuilder.Reserve(capacity + 1); + ValidityBufferBuilder.Reserve(capacity); + return this; + } + + public Builder Resize(int length) + { + ValueOffsetsBufferBuilder.Resize(length + 1); + ValidityBufferBuilder.Resize(length); + return this; + } + + public Builder Clear() + { + ValueOffsetsBufferBuilder.Clear(); + KeyBuilder.Clear(); + ValueBuilder.Clear(); + ValidityBufferBuilder.Clear(); + return this; + } + + } + + public StructArray KeyValues => base.Values as StructArray; + public IArrowArray Keys => KeyValues.Fields[0]; + public new IArrowArray Values => KeyValues.Fields[1]; + + public MapArray(IArrowType dataType, int length, + ArrowBuffer valueOffsetsBuffer, IArrowArray structs, + ArrowBuffer nullBitmapBuffer, int nullCount = 0, int offset = 0) + : this( + new ArrayData( + dataType, length, nullCount, offset, new[] { nullBitmapBuffer, valueOffsetsBuffer }, + new[] { structs.Data } + ), structs) + { + } + + public MapArray(ArrayData data) + : this(data, ArrowArrayFactory.BuildArray(data.Children[0])) + { + } + + private MapArray(ArrayData data, IArrowArray structs) : base(data, structs, ArrowTypeId.Map) + { + } + + public IEnumerable> GetTuples(int index, Func getKey, Func getValue) + where TKeyArray : Array where TValueArray : Array + { + ReadOnlySpan offsets = ValueOffsets; + // Get key values + int start = offsets[index]; + int end = offsets[index + 1]; + StructArray array = KeyValues.Slice(start, end - start) as StructArray; + + TKeyArray keyArray = array.Fields[0] as TKeyArray; + TValueArray valueArray = array.Fields[1] as TValueArray; + + for (int i = start; i < end; i++) + { + yield return new Tuple(getKey(keyArray, i), getValue(valueArray, i)); + } + } + + public IEnumerable> GetKeyValuePairs(int index, Func getKey, Func getValue) + where TKeyArray : Array where TValueArray : Array + { + ReadOnlySpan offsets = ValueOffsets; + // Get key values + int start = offsets[index]; + int end = offsets[index + 1]; + StructArray array = KeyValues.Slice(start, end - start) as StructArray; + + TKeyArray keyArray = array.Fields[0] as TKeyArray; + TValueArray valueArray = array.Fields[1] as TValueArray; + + for (int i = start; i < end; i++) + { + yield return new KeyValuePair(getKey(keyArray, i), getValue(valueArray, i)); + } + } + } +} diff --git a/csharp/src/Apache.Arrow/C/CArrowArrayImporter.cs b/csharp/src/Apache.Arrow/C/CArrowArrayImporter.cs index da1b0f31b8f08..1b40ec49658bb 100644 --- a/csharp/src/Apache.Arrow/C/CArrowArrayImporter.cs +++ b/csharp/src/Apache.Arrow/C/CArrowArrayImporter.cs @@ -180,6 +180,9 @@ private ArrayData GetAsArrayData(CArrowArray* cArray, IArrowType type) }; ; break; case ArrowTypeId.Map: + MapType mapType = (MapType)type; + children = ProcessListChildren(cArray, mapType.Fields[0].DataType); + buffers = ImportListBuffers(cArray); break; case ArrowTypeId.Null: buffers = System.Array.Empty(); diff --git a/csharp/src/Apache.Arrow/C/CArrowSchemaExporter.cs b/csharp/src/Apache.Arrow/C/CArrowSchemaExporter.cs index c1a12362a942a..f3479903889d1 100644 --- a/csharp/src/Apache.Arrow/C/CArrowSchemaExporter.cs +++ b/csharp/src/Apache.Arrow/C/CArrowSchemaExporter.cs @@ -188,6 +188,7 @@ private static string GetFormat(IArrowType datatype) return $"+w:{fixedListType.ListSize}"; case StructType _: return "+s"; case UnionType u: return FormatUnion(u); + case MapType _: return "+m"; // Dictionary case DictionaryType dictionaryType: return GetFormat(dictionaryType.IndexType); @@ -212,10 +213,9 @@ private static long GetFlags(IArrowType datatype, bool nullable = true) } } - if (datatype.TypeId == ArrowTypeId.Map) + if (datatype is MapType mapType && mapType.KeySorted) { - // TODO: when we implement MapType, make sure to set the KEYS_SORTED flag. - throw new NotSupportedException("Exporting MapTypes is not supported."); + flags |= CArrowSchema.ArrowFlagMapKeysSorted; } return flags; diff --git a/csharp/src/Apache.Arrow/C/CArrowSchemaImporter.cs b/csharp/src/Apache.Arrow/C/CArrowSchemaImporter.cs index f7216df869abd..f2a08f5e4a40b 100644 --- a/csharp/src/Apache.Arrow/C/CArrowSchemaImporter.cs +++ b/csharp/src/Apache.Arrow/C/CArrowSchemaImporter.cs @@ -206,8 +206,14 @@ public ArrowType GetAsType() return new FixedSizeListType(childField, width); } + else if (format == "+m") + { + return new MapType( + ParseChildren("map").Single(), + (_cSchema->flags & CArrowSchema.ArrowFlagMapKeysSorted) != 0); + } - // TODO: Map type and large list type + // TODO: Large list type // Decimals if (format.StartsWith("d:")) diff --git a/csharp/src/Apache.Arrow/Ipc/ArrowTypeFlatbufferBuilder.cs b/csharp/src/Apache.Arrow/Ipc/ArrowTypeFlatbufferBuilder.cs index b11467538dd04..425d9326addfe 100644 --- a/csharp/src/Apache.Arrow/Ipc/ArrowTypeFlatbufferBuilder.cs +++ b/csharp/src/Apache.Arrow/Ipc/ArrowTypeFlatbufferBuilder.cs @@ -67,6 +67,7 @@ class TypeVisitor : IArrowTypeVisitor, IArrowTypeVisitor, IArrowTypeVisitor, + IArrowTypeVisitor, IArrowTypeVisitor { private FlatBufferBuilder Builder { get; } @@ -229,6 +230,13 @@ public void Visit(FixedSizeBinaryType type) Flatbuf.FixedSizeBinary.CreateFixedSizeBinary(Builder, type.ByteWidth)); } + public void Visit(MapType type) + { + Result = FieldType.Build( + Flatbuf.Type.Map, + Flatbuf.Map.CreateMap(Builder, type.KeySorted)); + } + public void Visit(NullType type) { Flatbuf.Null.StartNull(Builder); @@ -239,7 +247,7 @@ public void Visit(NullType type) public void Visit(IArrowType type) { - throw new NotImplementedException(); + throw new NotImplementedException($"Cannot visit type {type}"); } } diff --git a/csharp/src/Apache.Arrow/Ipc/MessageSerializer.cs b/csharp/src/Apache.Arrow/Ipc/MessageSerializer.cs index 6249063ba81f4..9847c376cf82e 100644 --- a/csharp/src/Apache.Arrow/Ipc/MessageSerializer.cs +++ b/csharp/src/Apache.Arrow/Ipc/MessageSerializer.cs @@ -207,6 +207,13 @@ private static Types.IArrowType GetFieldArrowType(Flatbuf.Field field, Field[] c Debug.Assert(childFields != null); Flatbuf.Union unionMetadata = field.Type().Value; return new Types.UnionType(childFields, unionMetadata.GetTypeIdsArray(), unionMetadata.Mode.ToArrow()); + case Flatbuf.Type.Map: + if (childFields == null || childFields.Length != 1) + { + throw new InvalidDataException($"Map type must have exactly one struct child."); + } + Flatbuf.Map meta = field.Type().Value; + return new Types.MapType(childFields[0], meta.KeysSorted); default: throw new InvalidDataException($"Arrow primitive '{field.TypeType}' is unsupported."); } diff --git a/csharp/src/Apache.Arrow/Types/ListType.cs b/csharp/src/Apache.Arrow/Types/ListType.cs index a006c2282dd11..b467934ec541d 100644 --- a/csharp/src/Apache.Arrow/Types/ListType.cs +++ b/csharp/src/Apache.Arrow/Types/ListType.cs @@ -13,8 +13,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; - namespace Apache.Arrow.Types { public sealed class ListType : NestedType diff --git a/csharp/src/Apache.Arrow/Types/MapType.cs b/csharp/src/Apache.Arrow/Types/MapType.cs new file mode 100644 index 0000000000000..73112c815bfbf --- /dev/null +++ b/csharp/src/Apache.Arrow/Types/MapType.cs @@ -0,0 +1,58 @@ +// 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 System.Collections.Generic; + +namespace Apache.Arrow.Types +{ + public sealed class MapType : NestedType // MapType = ListType(StructType("key", "value")) + { + public override ArrowTypeId TypeId => ArrowTypeId.Map; + public override string Name => "map"; + public readonly bool KeySorted; + + public StructType KeyValueType => Fields[0].DataType as StructType; + public Field KeyField => KeyValueType.Fields[0]; + public Field ValueField => KeyValueType.Fields[1]; + + public MapType(IArrowType key, IArrowType value, bool nullable = true, bool keySorted = false) + : this(new Field("key", key, false), new Field("value", value, nullable), keySorted) + { + } + + public MapType(Field key, Field value, bool keySorted = false) + : this(new StructType(new List() { key, value }), keySorted) + { + } + + public MapType(StructType entries, bool keySorted = false) : this(new Field("entries", entries, false), keySorted) + { + } + + public MapType(Field entries, bool keySorted = false) : base(entries) + { + KeySorted = keySorted; + } + + public override void Accept(IArrowTypeVisitor visitor) => Accept(this, visitor); + + public MapType UnsortedKey() + { + if (!KeySorted) { return this; } + + return new MapType(Fields[0], keySorted: false); + } + } +} diff --git a/csharp/test/Apache.Arrow.IntegrationTest/JsonFile.cs b/csharp/test/Apache.Arrow.IntegrationTest/JsonFile.cs index 85f66890edf47..d06249bef2661 100644 --- a/csharp/test/Apache.Arrow.IntegrationTest/JsonFile.cs +++ b/csharp/test/Apache.Arrow.IntegrationTest/JsonFile.cs @@ -124,6 +124,7 @@ private static IArrowType ToArrowType(JsonArrowType type, Field[] children) "fixedsizelist" => ToFixedSizeListArrowType(type, children), "struct" => ToStructArrowType(type, children), "union" => ToUnionArrowType(type, children), + "map" => ToMapArrowType(type, children), "null" => NullType.Default, _ => throw new NotSupportedException($"JsonArrowType not supported: {type.Name}") }; @@ -227,6 +228,11 @@ private static IArrowType ToUnionArrowType(JsonArrowType type, Field[] children) }; return new UnionType(children, type.TypeIds, mode); } + + private static IArrowType ToMapArrowType(JsonArrowType type, Field[] children) + { + return new MapType(children[0], type.KeysSorted); + } } public class JsonField @@ -271,6 +277,9 @@ public class JsonArrowType public string Mode { get; set; } public int[] TypeIds { get; set; } + // map fields + public bool KeysSorted { get; set; } + [JsonExtensionData] public Dictionary ExtensionData { get; set; } } @@ -345,6 +354,7 @@ private class ArrayCreator : IArrowTypeVisitor, IArrowTypeVisitor, IArrowTypeVisitor, + IArrowTypeVisitor, IArrowTypeVisitor { private JsonFieldData JsonFieldData { get; set; } @@ -616,6 +626,21 @@ public void Visit(UnionType type) Array = UnionArray.Create(arrayData); } + public void Visit(MapType type) + { + ArrowBuffer validityBuffer = GetValidityBuffer(out int nullCount); + ArrowBuffer offsetBuffer = GetOffsetBuffer(); + + var data = JsonFieldData; + JsonFieldData = data.Children[0]; + type.KeyValueType.Accept(this); + JsonFieldData = data; + + ArrayData arrayData = new ArrayData(type, JsonFieldData.Count, nullCount, 0, + new[] { validityBuffer, offsetBuffer }, new[] { Array.Data }); + Array = new MapArray(arrayData); + } + private ArrayData[] GetChildren(NestedType type) { ArrayData[] children = new ArrayData[type.Fields.Count]; diff --git a/csharp/test/Apache.Arrow.Tests/ArrayTypeComparer.cs b/csharp/test/Apache.Arrow.Tests/ArrayTypeComparer.cs index c8bcc3cee0f99..ad3527c47807b 100644 --- a/csharp/test/Apache.Arrow.Tests/ArrayTypeComparer.cs +++ b/csharp/test/Apache.Arrow.Tests/ArrayTypeComparer.cs @@ -29,7 +29,8 @@ public class ArrayTypeComparer : IArrowTypeVisitor, IArrowTypeVisitor, IArrowTypeVisitor, - IArrowTypeVisitor + IArrowTypeVisitor, + IArrowTypeVisitor { private readonly IArrowType _expectedType; @@ -131,6 +132,16 @@ public void Visit(UnionType actualType) CompareNested(expectedType, actualType); } + public void Visit(MapType actualType) + { + Assert.IsAssignableFrom(_expectedType); + var expectedType = (MapType)_expectedType; + + Assert.Equal(expectedType.KeySorted, actualType.KeySorted); + + CompareNested(expectedType, actualType); + } + private static void CompareNested(NestedType expectedType, NestedType actualType) { Assert.Equal(expectedType.Fields.Count, actualType.Fields.Count); diff --git a/csharp/test/Apache.Arrow.Tests/ArrowArrayConcatenatorTests.cs b/csharp/test/Apache.Arrow.Tests/ArrowArrayConcatenatorTests.cs index f5a2c345e2ae6..f1dcbb5d37b8f 100644 --- a/csharp/test/Apache.Arrow.Tests/ArrowArrayConcatenatorTests.cs +++ b/csharp/test/Apache.Arrow.Tests/ArrowArrayConcatenatorTests.cs @@ -93,6 +93,10 @@ private static IEnumerable, IArrowArray>> GenerateTestDa new[] { 0, 1 }, UnionMode.Dense ), + new MapType( + new Field.Builder().Name("key").DataType(StringType.Default).Nullable(false).Build(), + new Field.Builder().Name("value").DataType(Int32Type.Default).Nullable(true).Build(), + keySorted: false), }; foreach (IArrowType type in targetTypes) @@ -136,7 +140,8 @@ private class TestDataGenerator : IArrowTypeVisitor, IArrowTypeVisitor, IArrowTypeVisitor, - IArrowTypeVisitor + IArrowTypeVisitor, + IArrowTypeVisitor { private List> _baseData; @@ -310,7 +315,6 @@ public void Visit(StringType type) public void Visit(ListType type) { ListArray.Builder resultBuilder = new ListArray.Builder(type.ValueDataType).Reserve(_baseDataTotalElementCount); - //Todo : Support various types Int64Array.Builder resultValueBuilder = (Int64Array.Builder)resultBuilder.ValueBuilder.Reserve(_baseDataTotalElementCount); for (int i = 0; i < _baseDataListCount; i++) @@ -346,7 +350,6 @@ public void Visit(ListType type) public void Visit(FixedSizeListType type) { FixedSizeListArray.Builder resultBuilder = new FixedSizeListArray.Builder(type.ValueDataType, type.ListSize).Reserve(_baseDataTotalElementCount); - //Todo : Support various types Int32Array.Builder resultValueBuilder = (Int32Array.Builder)resultBuilder.ValueBuilder.Reserve(_baseDataTotalElementCount); for (int i = 0; i < _baseDataListCount; i++) @@ -406,7 +409,7 @@ public void Visit(StructType type) StringArray resultStringArray = resultStringBuilder.Build(); Int32Array resultInt32Array = resultInt32Builder.Build(); - ExpectedArray = new StructArray(type, 3, new List { resultStringArray, resultInt32Array }, nullBitmapBuffer, 1); + ExpectedArray = new StructArray(type, 9, new List { resultStringArray, resultInt32Array }, nullBitmapBuffer, 3); } public void Visit(UnionType type) @@ -495,6 +498,46 @@ public void Visit(UnionType type) new[] { stringResultBuilder.Build().Data, intResultBuilder.Build().Data })); } + public void Visit(MapType type) + { + MapArray.Builder resultBuilder = new MapArray.Builder(type).Reserve(_baseDataTotalElementCount); + StringArray.Builder resultKeyBuilder = (StringArray.Builder)resultBuilder.KeyBuilder.Reserve(_baseDataTotalElementCount); + Int32Array.Builder resultValueBuilder = (Int32Array.Builder)resultBuilder.ValueBuilder.Reserve(_baseDataTotalElementCount); + ArrowBuffer nullBitmapBuilder = new ArrowBuffer.BitmapBuilder().Append(true).Append(true).Append(false).Build(); + + for (int i = 0; i < _baseData.Count; i++) + { + List dataList = _baseData[i]; + + MapArray.Builder builder = new MapArray.Builder(type).Reserve(dataList.Count); + StringArray.Builder keyBuilder = (StringArray.Builder)builder.KeyBuilder.Reserve(dataList.Count); + Int32Array.Builder valueBuilder = (Int32Array.Builder)builder.ValueBuilder.Reserve(dataList.Count); + + foreach (int? value in dataList) + { + if (value.HasValue) + { + builder.Append(); + resultBuilder.Append(); + + keyBuilder.Append(value.Value.ToString()); + valueBuilder.Append(value.Value); + resultKeyBuilder.Append(value.Value.ToString()); + resultValueBuilder.Append(value.Value); + } + else + { + builder.AppendNull(); + resultBuilder.AppendNull(); + } + } + + TestTargetArrayList.Add(builder.Build()); + } + + ExpectedArray = resultBuilder.Build(); + } + public void Visit(IArrowType type) { throw new NotImplementedException(); diff --git a/csharp/test/Apache.Arrow.Tests/CDataInterfacePythonTests.cs b/csharp/test/Apache.Arrow.Tests/CDataInterfacePythonTests.cs index b6b65a582d953..7aee37b8212c3 100644 --- a/csharp/test/Apache.Arrow.Tests/CDataInterfacePythonTests.cs +++ b/csharp/test/Apache.Arrow.Tests/CDataInterfacePythonTests.cs @@ -115,6 +115,8 @@ private static Schema GetTestSchema() .Field(f => f.Name("dense_union").DataType(new UnionType(new[] { new Field("i64", Int64Type.Default, false), new Field("f32", FloatType.Default, true), }, new[] { 0, 1 }, UnionMode.Dense))) .Field(f => f.Name("sparse_union").DataType(new UnionType(new[] { new Field("i32", Int32Type.Default, true), new Field("f64", DoubleType.Default, false), }, new[] { 0, 1 }, UnionMode.Sparse))) + .Field(f => f.Name("map").DataType(new MapType(StringType.Default, Int32Type.Default)).Nullable(false)) + // Checking wider characters. .Field(f => f.Name("hello 你好 😄").DataType(BooleanType.Default).Nullable(true)) @@ -178,6 +180,8 @@ private static IEnumerable GetPythonFields() yield return pa.field("dense_union", pa.dense_union(List(pa.field("i64", pa.int64(), false), pa.field("f32", pa.float32(), true)))); yield return pa.field("sparse_union", pa.sparse_union(List(pa.field("i32", pa.int32(), true), pa.field("f64", pa.float64(), false)))); + yield return pa.field("map", pa.map_(pa.@string(), pa.int32()), false); + yield return pa.field("hello 你好 😄", pa.bool_(), true); } } @@ -512,8 +516,12 @@ public unsafe void ImportRecordBatch() ), /* field name */ List("i32", "s"), /* type codes */ List(3, 2)), + pa.MapArray.from_arrays( + List(0, 0, 1, 2, 4, 10), + pa.array(List("one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten")), + pa.array(List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))), }), - new[] { "col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8", "col9" }); + new[] { "col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8", "col9", "col10" }); dynamic batch = table.to_batches()[0]; @@ -585,6 +593,11 @@ public unsafe void ImportRecordBatch() UnionArray col9 = (UnionArray)recordBatch.Column("col9"); Assert.Equal(5, col9.Length); Assert.True(col9 is DenseUnionArray); + + MapArray col10 = (MapArray)recordBatch.Column("col10"); + Assert.Equal(5, col10.Length); + Assert.Equal(new int[] { 0, 0, 1, 2, 4, 10}, col10.ValueOffsets.ToArray()); + Assert.Equal(new long?[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, ((Int64Array)col10.Values).ToList().ToArray()); } [SkippableFact] diff --git a/csharp/test/Apache.Arrow.Tests/MapArrayTests.cs b/csharp/test/Apache.Arrow.Tests/MapArrayTests.cs new file mode 100644 index 0000000000000..034f120f3f016 --- /dev/null +++ b/csharp/test/Apache.Arrow.Tests/MapArrayTests.cs @@ -0,0 +1,92 @@ +// 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 System; +using System.Collections.Generic; +using System.Linq; +using Apache.Arrow.Types; +using Xunit; + +namespace Apache.Arrow.Tests +{ + public class MapArrayTests + { + [Fact] + public void MapArray_Should_GetTuple() + { + MapType type = new MapType(StringType.Default, Int64Type.Default); + MapArray.Builder builder = new MapArray.Builder(type); + var keyBuilder = builder.KeyBuilder as StringArray.Builder; + var valueBuilder = builder.ValueBuilder as Int64Array.Builder; + + Tuple kv0 = Tuple.Create("test", (long?)1); + Tuple kv1 = Tuple.Create("other", (long?)123); + Tuple kv2 = Tuple.Create("kv", (long?)null); + + builder.Append(); + keyBuilder.Append("test"); + valueBuilder.Append(1); + + builder.AppendNull(); + + builder.Append(); + keyBuilder.Append("other"); + valueBuilder.Append(123); + keyBuilder.Append("kv"); + valueBuilder.AppendNull(); + + MapArray array = builder.Build(); + + Assert.Equal(new Tuple[] { kv0 }, array.GetTuples(0, GetKey, GetValue).ToArray()); + Assert.True(array.IsNull(1)); + Assert.Equal(new Tuple[] { kv1, kv2 }, array.GetTuples(2, GetKey, GetValue).ToArray()); + } + + [Fact] + public void MapArray_Should_GetKeyValuePairs() + { + MapType type = new MapType(StringType.Default, Int32Type.Default); + MapArray.Builder builder = new MapArray.Builder(type); + var keyBuilder = builder.KeyBuilder as StringArray.Builder; + var valueBuilder = builder.ValueBuilder as Int32Array.Builder; + + KeyValuePair kv0 = KeyValuePair.Create("test", (int?)1); + KeyValuePair kv1 = KeyValuePair.Create("other", (int?)123); + KeyValuePair kv2 = KeyValuePair.Create("kv", (int?)null); + + builder.Append(); + keyBuilder.Append("test"); + valueBuilder.Append(1); + + builder.AppendNull(); + + builder.Append(); + keyBuilder.Append("other"); + valueBuilder.Append(123); + keyBuilder.Append("kv"); + valueBuilder.AppendNull(); + + MapArray array = builder.Build(); + + Assert.Equal(new KeyValuePair[] { kv0 }, array.GetKeyValuePairs(0, GetKey, GetValue).ToArray()); + Assert.True(array.IsNull(1)); + Assert.Equal(new KeyValuePair[] { kv1, kv2 }, array.GetKeyValuePairs(2, GetKey, GetValue).ToArray()); + } + + private static string GetKey(StringArray array, int index) => array.GetString(index); + private static int? GetValue(Int32Array array, int index) => array.GetValue(index); + private static long? GetValue(Int64Array array, int index) => array.GetValue(index); + } +} diff --git a/csharp/test/Apache.Arrow.Tests/TableTests.cs b/csharp/test/Apache.Arrow.Tests/TableTests.cs index 8b07a38c1b8c0..234dd63a79cd2 100644 --- a/csharp/test/Apache.Arrow.Tests/TableTests.cs +++ b/csharp/test/Apache.Arrow.Tests/TableTests.cs @@ -60,7 +60,7 @@ public void TestTableFromRecordBatches() Table table1 = Table.TableFromRecordBatches(recordBatch1.Schema, recordBatches); Assert.Equal(20, table1.RowCount); - Assert.Equal(26, table1.ColumnCount); + Assert.Equal(27, table1.ColumnCount); FixedSizeBinaryType type = new FixedSizeBinaryType(17); Field newField1 = new Field(type.Name, type, false); diff --git a/csharp/test/Apache.Arrow.Tests/TestData.cs b/csharp/test/Apache.Arrow.Tests/TestData.cs index 9e2061e3428a9..e3a40dbdafd61 100644 --- a/csharp/test/Apache.Arrow.Tests/TestData.cs +++ b/csharp/test/Apache.Arrow.Tests/TestData.cs @@ -54,6 +54,7 @@ public static RecordBatch CreateSampleRecordBatch(int length, int columnSetCount builder.Field(CreateField(new StructType(new List { CreateField(StringType.Default, i), CreateField(Int32Type.Default, i) }), i)); builder.Field(CreateField(new Decimal128Type(10, 6), i)); builder.Field(CreateField(new Decimal256Type(16, 8), i)); + builder.Field(CreateField(new MapType(StringType.Default, Int32Type.Default), i)); if (createAdvancedTypeArrays) { @@ -132,6 +133,7 @@ private class ArrayCreator : IArrowTypeVisitor, IArrowTypeVisitor, IArrowTypeVisitor, + IArrowTypeVisitor, IArrowTypeVisitor { private int Length { get; } @@ -261,7 +263,6 @@ public void Visit(ListType type) { var builder = new ListArray.Builder(type.ValueField).Reserve(Length); - //Todo : Support various types var valueBuilder = (Int64Array.Builder)builder.ValueBuilder.Reserve(Length + 1); for (var i = 0; i < Length; i++) @@ -279,7 +280,6 @@ public void Visit(FixedSizeListType type) { var builder = new FixedSizeListArray.Builder(type.ValueField, type.ListSize).Reserve(Length); - //Todo : Support various types var valueBuilder = (Int32Array.Builder)builder.ValueBuilder; for (var i = 0; i < Length; i++) @@ -410,6 +410,25 @@ public void Visit(FixedSizeBinaryType type) Array = new FixedSizeBinaryArray(arrayData); } + public void Visit(MapType type) + { + MapArray.Builder builder = new MapArray.Builder(type).Reserve(Length); + var keyBuilder = builder.KeyBuilder.Reserve(Length + 1) as StringArray.Builder; + var valueBuilder = builder.ValueBuilder.Reserve(Length + 1) as Int32Array.Builder; + + for (var i = 0; i < Length; i++) + { + builder.Append(); + keyBuilder.Append(i.ToString()); + valueBuilder.Append(i); + } + //Add a value to check if Values.Length can exceed MapArray.Length + keyBuilder.Append("0"); + valueBuilder.Append(0); + + Array = builder.Build(); + } + public void Visit(NullType type) { Array = new NullArray(Length); diff --git a/csharp/test/Apache.Arrow.Tests/Types/MapTypeTests.cs b/csharp/test/Apache.Arrow.Tests/Types/MapTypeTests.cs new file mode 100644 index 0000000000000..ba306ec104e79 --- /dev/null +++ b/csharp/test/Apache.Arrow.Tests/Types/MapTypeTests.cs @@ -0,0 +1,57 @@ +// 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 Xunit; + +namespace Apache.Arrow.Tests.Types +{ + public class MapTypeTests + { + [Fact] + public void MapType_Should_HaveCorrectTypeId() + { + var type = new MapType(StringType.Default, Int32Type.Default); + Assert.Equal(ArrowTypeId.Map, type.TypeId); + } + + [Fact] + public void MapType_Should_HaveCorrectStructType() + { + var type = new MapType(BooleanType.Default, Int32Type.Default, true); + Assert.IsType(type.Fields[0].DataType); + Assert.Equal(2, type.KeyValueType.Fields.Count); + + Assert.Equal("entries", type.Fields[0].Name); + Assert.Equal("key", type.KeyField.Name); + Assert.Equal("value", type.ValueField.Name); + + Assert.False(type.Fields[0].IsNullable); + Assert.False(type.KeyField.IsNullable); + Assert.True(type.ValueField.IsNullable); + Assert.False(new MapType(BooleanType.Default, Int32Type.Default, false).ValueField.IsNullable); + + Assert.IsType(type.KeyField.DataType); + Assert.IsType(type.ValueField.DataType); + } + + [Fact] + public void MapType_Should_SetKeySorted() + { + Assert.False(new MapType(BooleanType.Default, Int32Type.Default).KeySorted); + Assert.True(new MapType(StringType.Default, Int32Type.Default, true, true).KeySorted); + } + } +} diff --git a/dev/archery/archery/integration/datagen.py b/dev/archery/archery/integration/datagen.py index 8d0cc6b0b01a8..01672fbe7488a 100644 --- a/dev/archery/archery/integration/datagen.py +++ b/dev/archery/archery/integration/datagen.py @@ -1815,8 +1815,7 @@ def _temp_path(): .skip_tester('C#') .skip_tester('JS'), - generate_map_case() - .skip_tester('C#'), + generate_map_case(), generate_non_canonical_map_case() .skip_tester('C#') diff --git a/docs/source/status.rst b/docs/source/status.rst index e2b3852e2229f..6024c1d3172bb 100644 --- a/docs/source/status.rst +++ b/docs/source/status.rst @@ -81,7 +81,7 @@ Data Types +-------------------+-------+-------+-------+------------+-------+-------+-------+-------+ | Struct | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | +-------------------+-------+-------+-------+------------+-------+-------+-------+-------+ -| Map | ✓ | ✓ | ✓ | ✓ | | ✓ | ✓ | | +| Map | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | +-------------------+-------+-------+-------+------------+-------+-------+-------+-------+ | Dense Union | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | +-------------------+-------+-------+-------+------------+-------+-------+-------+-------+ From 1cad7a787847add45261abe5acdd3ba080e54a75 Mon Sep 17 00:00:00 2001 From: Matt Topol Date: Thu, 5 Oct 2023 12:49:15 -0400 Subject: [PATCH 56/56] GH-35328: [Go][FlightSQL] Fix flaky test for FlightSql driver (#38044) ### Rationale for this change Fixing a flaky test that is *very* difficult to reproduce. ### What changes are included in this PR? Adding an explicit call to drain the remaining batches from the parameter batch reader in the `DoPutPreparedStatementQuery` of the `MockServer` in the tests. This ensures that the gRPC connection doesn't close on us in between the client writing the schema message and writing the record batch message producing an `io.EOF` error. This is an extremely rare occurence based on goroutine scheduling due to the client and mockserver both running in the same process for the tests, in local testing i was only able to get it to happen 1 - 4 times per 5000 runs of the test. ### Are there any user-facing changes? No * Closes: #35328 Authored-by: Matt Topol Signed-off-by: Matt Topol --- go/arrow/flight/flightsql/driver/driver_test.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/go/arrow/flight/flightsql/driver/driver_test.go b/go/arrow/flight/flightsql/driver/driver_test.go index 3ec8533979a32..4449b390974a7 100644 --- a/go/arrow/flight/flightsql/driver/driver_test.go +++ b/go/arrow/flight/flightsql/driver/driver_test.go @@ -812,6 +812,17 @@ func (s *MockServer) DoPutPreparedStatementQuery(ctx context.Context, qry flight return fmt.Errorf("parameter schema: %w", arrow.ErrInvalid) } + // GH-35328: it's rare, but this function can complete execution and return + // closing the reader *after* the schema is written but *before* the parameter batch + // is written (race condition based on goroutine scheduling). In that situation, + // the client call to Write the parameter record batch will return an io.EOF because + // this end of the connection will have closed before it attempted to send the batch. + // This created a flaky test situation that was difficult to reproduce (1-4 failures + // in 5000 runs). We can avoid this flakiness by simply *explicitly* draining the + // record batch messages from the reader before returning. + for r.Next() { + } + return nil }