Support HybridFileDetector

Bug: b/222647019
Change-Id: I9f6987d4bf68e314168b4e1a125a41be7e2948c8
diff --git a/src/library_desugar/java/desugar/sun/nio/fs/DesugarDefaultFileTypeDetector.java b/src/library_desugar/java/desugar/sun/nio/fs/DesugarDefaultFileTypeDetector.java
new file mode 100644
index 0000000..916d6e0
--- /dev/null
+++ b/src/library_desugar/java/desugar/sun/nio/fs/DesugarDefaultFileTypeDetector.java
@@ -0,0 +1,13 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package desugar.sun.nio.fs;
+
+import java.nio.file.spi.FileTypeDetector;
+
+public class DesugarDefaultFileTypeDetector {
+  public static FileTypeDetector create() {
+    return null;
+  }
+}
diff --git a/src/library_desugar/java/j$/nio/file/Files.java b/src/library_desugar/java/j$/nio/file/Files.java
new file mode 100644
index 0000000..2825d24
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/Files.java
@@ -0,0 +1,14 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package j$.nio.file;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+public class Files {
+  public static String probeContentType(Path path) throws IOException {
+    return null;
+  }
+}
diff --git a/src/library_desugar/java/java/adapter/HybridFileTypeDetector.java b/src/library_desugar/java/java/adapter/HybridFileTypeDetector.java
new file mode 100644
index 0000000..1caf2f1
--- /dev/null
+++ b/src/library_desugar/java/java/adapter/HybridFileTypeDetector.java
@@ -0,0 +1,35 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package java.adapter;
+
+import android.os.Build.VERSION;
+import desugar.sun.nio.fs.DesugarDefaultFileTypeDetector;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.spi.FileTypeDetector;
+
+/**
+ * A hybrid file type detector adapter that delegates different implementations based on the runtime
+ * environment.
+ */
+public final class HybridFileTypeDetector {
+  private HybridFileTypeDetector() {}
+
+  public static FileTypeDetector create() {
+    if (VERSION.SDK_INT >= 26) {
+      return new PlatformFileTypeDetector();
+    } else {
+      return DesugarDefaultFileTypeDetector.create();
+    }
+  }
+
+  static class PlatformFileTypeDetector extends java.nio.file.spi.FileTypeDetector {
+    @Override
+    public String probeContentType(Path path) throws IOException {
+      // Relies at runtime on java.nio.file.Files.
+      return j$.nio.file.Files.probeContentType(path);
+    }
+  }
+}
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_path.json b/src/library_desugar/jdk11/desugar_jdk_libs_path.json
index d8bf9f2..092b976 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs_path.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_path.json
@@ -342,6 +342,9 @@
       "rewrite_derived_prefix": {
         "java.nio.file.attribute.FileTime": {
           "j$.nio.file.attribute.FileTime": "java.nio.file.attribute.FileTime"
+        },
+        "java.nio.file.Files": {
+          "j$.nio.file.Files": "java.nio.file.Files"
         }
       },
       "retarget_method": {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
index f452df5..d9154e7 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
@@ -49,7 +49,7 @@
 
 public class DesugaredLibraryTestBase extends TestBase {
 
-  private static final boolean FORCE_JDK11_DESUGARED_LIB = false;
+  private static final boolean FORCE_JDK11_DESUGARED_LIB = true;
 
   @BeforeClass
   public static void setUpDesugaredLibrary() {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/DesugaredLibraryJDK11Undesugarer.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/DesugaredLibraryJDK11Undesugarer.java
index 1331e08..dc9725a 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/DesugaredLibraryJDK11Undesugarer.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/DesugaredLibraryJDK11Undesugarer.java
@@ -36,6 +36,7 @@
           .put("java/io/DesugarBufferedReader", "java/io/BufferedReader")
           .put("java/io/DesugarInputStream", "java/io/InputStream")
           .put("wrapper/adapter/HybridFileSystemProvider", "java/adapter/HybridFileSystemProvider")
+          .put("wrapper/adapter/HybridFileTypeDetector", "java/adapter/HybridFileTypeDetector")
           .build();
 
   public static void main(String[] args) throws Exception {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/FileTypeDetectorTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/FileTypeDetectorTest.java
new file mode 100644
index 0000000..b168992
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/FileTypeDetectorTest.java
@@ -0,0 +1,173 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.desugar.desugaredlibrary.jdk11;
+
+import static com.android.tools.r8.ToolHelper.DexVm.Version.V12_0_0;
+
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.LibraryDesugaringTestConfiguration;
+import com.android.tools.r8.StringResource;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
+import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.StringUtils;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.spi.FileTypeDetector;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ServiceLoader;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class FileTypeDetectorTest extends DesugaredLibraryTestBase {
+
+  private static final String EXPECTED_RESULT_DEFAULT_PNG_TYPE_DETECTOR =
+      StringUtils.lines("false", "text/plain", "image/png", "null", "image/png");
+  private static final String EXPECTED_RESULT_NO_DEFAULT_PNG_TYPE_DETECTOR =
+      StringUtils.lines("false", "text/plain", "null", "null", "image/png");
+  private final TestParameters parameters;
+  private final boolean shrinkDesugaredLibrary;
+
+  @Parameters(name = "{1}, shrinkDesugaredLibrary: {0}")
+  public static List<Object[]> data() {
+    // Skip Android 4.4.4 due to missing libjavacrypto.
+    return buildParameters(
+        BooleanUtils.values(),
+        getTestParameters()
+            .withDexRuntime(Version.V4_0_4)
+            .withDexRuntimesStartingFromIncluding(Version.V5_1_1)
+            .withAllApiLevels()
+            .build());
+  }
+
+  public FileTypeDetectorTest(boolean shrinkDesugaredLibrary, TestParameters parameters) {
+    this.shrinkDesugaredLibrary = shrinkDesugaredLibrary;
+    this.parameters = parameters;
+  }
+
+  private boolean hasDefaultPNGTypeDetector() {
+    return parameters.getDexRuntimeVersion().compareTo(V12_0_0) < 0;
+  }
+
+  private String getExpectedResult() {
+    return hasDefaultPNGTypeDetector()
+        ? EXPECTED_RESULT_DEFAULT_PNG_TYPE_DETECTOR
+        : EXPECTED_RESULT_NO_DEFAULT_PNG_TYPE_DETECTOR;
+  }
+
+  private LibraryDesugaringTestConfiguration pathConfiguration() {
+    return LibraryDesugaringTestConfiguration.builder()
+        .setMinApi(parameters.getApiLevel())
+        .addDesugaredLibraryConfiguration(
+            StringResource.fromFile(ToolHelper.getDesugarLibJsonForTestingWithPath()))
+        .setMode(shrinkDesugaredLibrary ? CompilationMode.RELEASE : CompilationMode.DEBUG)
+        .withKeepRuleConsumer()
+        .build();
+  }
+
+  @Test
+  public void testD8() throws Exception {
+    Assume.assumeTrue(isJDK11DesugaredLibrary());
+    testForD8(parameters.getBackend())
+        .addLibraryFiles(getLibraryFile())
+        .addInnerClasses(getClass())
+        .addProgramClasses(GoogleIcon.class)
+        .setMinApi(parameters.getApiLevel())
+        .enableCoreLibraryDesugaring(pathConfiguration())
+        .compile()
+        .withArt6Plus64BitsLib()
+        .withArtFrameworks()
+        .run(parameters.getRuntime(), TestClass.class)
+        .assertSuccessWithOutput(getExpectedResult());
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    Assume.assumeTrue(isJDK11DesugaredLibrary());
+    testForR8(Backend.DEX)
+        .addLibraryFiles(getLibraryFile())
+        .addInnerClasses(getClass())
+        .addProgramClasses(GoogleIcon.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(TestClass.class)
+        .enableCoreLibraryDesugaring(pathConfiguration())
+        .compile()
+        .withArt6Plus64BitsLib()
+        .withArtFrameworks()
+        .run(parameters.getRuntime(), TestClass.class)
+        .assertSuccessWithOutput(getExpectedResult());
+  }
+
+  public static class TestClass {
+
+    public static void main(String[] args) throws Throwable {
+      // FileTypeDetector usage through ServiceLoader.
+      ServiceLoader<FileTypeDetector> serviceLoader = ServiceLoader.load(FileTypeDetector.class);
+      Iterator<FileTypeDetector> iterator = serviceLoader.iterator();
+      System.out.println(iterator.hasNext());
+      while (iterator.hasNext()) {
+        FileTypeDetector fileTypeDetector = iterator.next();
+        System.out.println((fileTypeDetector == null));
+      }
+
+      Path emptyText = Files.createTempFile("example", ".txt");
+      Path png = getGoogleIconPng();
+
+      // FileTypeDetector usage through Files.
+      System.out.println(Files.probeContentType(emptyText));
+      System.out.println(Files.probeContentType(png));
+
+      // Custom file type detector usage.
+      FileTypeDetector fileTypeDetector = new PngFileTypeDetector();
+      System.out.println(fileTypeDetector.probeContentType(emptyText));
+      System.out.println(fileTypeDetector.probeContentType(png));
+    }
+
+    private static Path getGoogleIconPng() throws IOException {
+      Path picture = Files.createTempFile("art", ".png");
+      Files.write(picture, GoogleIcon.GOOGLE_ICON_PNG);
+      return picture;
+    }
+  }
+
+  public static class PngFileTypeDetector extends FileTypeDetector {
+
+    private static final byte[] PNG_HEADER = {
+      (byte) 0x89,
+      (byte) 0x50,
+      (byte) 0x4E,
+      (byte) 0x47,
+      (byte) 0x0D,
+      (byte) 0x0A,
+      (byte) 0x1A,
+      (byte) 0x0A
+    };
+
+    private static final int PNG_HEADER_SIZE = PNG_HEADER.length;
+
+    @Override
+    public String probeContentType(final Path path) throws IOException {
+      final byte[] buf = new byte[PNG_HEADER_SIZE];
+
+      try (final InputStream in = Files.newInputStream(path); ) {
+        if (in.read(buf) != PNG_HEADER_SIZE) {
+          return null;
+        }
+      }
+
+      return Arrays.equals(buf, PNG_HEADER) ? "image/png" : null;
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/GoogleIcon.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/GoogleIcon.java
new file mode 100644
index 0000000..ce0be4d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/GoogleIcon.java
@@ -0,0 +1,168 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.desugar.desugaredlibrary.jdk11;
+
+public class GoogleIcon {
+  static final byte[] GOOGLE_ICON_PNG =
+      new byte[] {
+        -119, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 1, 0, 0, 0, 1, 0, 8, 3,
+        0, 0, 0, 107, -84, 88, 84, 0, 0, 2, -21, 80, 76, 84, 69, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 10, 33, -74, 0, 0,
+        0, -8, 116, 82, 78, 83, 0, 0, 14, -25, -109, -6, -3, 5, 1, 22, -4, 3, -34, 47, -2, -33, -27,
+        -13, 4, -5, 20, 16, 13, -19, -12, -18, 21, -10, -30, 18, 2, 7, -97, -99, -121, 42, 6, -114,
+        35, -35, -123, 68, -65, -26, -119, -21, -29, 45, 8, -38, 59, -96, -56, -14, -17, 10, -43,
+        108, -16, -85, -55, 28, -22, 52, -46, 115, 112, 93, 26, 17, -52, -58, 36, 75, 27, -103, -15,
+        -83, 23, -95, 84, -64, 78, -66, -105, 34, -127, -117, 99, -60, -101, 40, 79, -54, -91, 44,
+        -126, 89, -24, -128, -7, 15, -39, 70, -80, 33, -111, 24, -53, 88, 110, 60, -122, -87, 90,
+        25, 9, -41, -59, -84, -108, -102, -75, 58, -31, 51, -61, 113, -20, 57, 122, -74, 29, -113,
+        54, 87, -107, -104, -73, 74, 39, -48, -50, -32, 65, -86, -67, 83, -76, -70, -23, 114, 71,
+        -71, 119, -100, 11, 111, 127, -110, -37, 50, 73, 69, 86, -9, -11, 116, 66, -68, 19, 107,
+        -81, 63, -89, -124, 37, -79, 53, 56, -98, -62, 46, 38, 12, 64, 117, 106, 77, 32, 126, -49,
+        -69, -125, 123, -93, -92, 91, -106, 67, 62, -57, 95, 125, -82, -90, 97, 100, 121, 104, -44,
+        -77, -78, -36, 85, 30, 92, 82, 109, 102, -115, 103, 94, 41, -40, -47, -94, 105, 48, 124,
+        -63, 120, -8, 118, 43, 61, -72, -116, 31, -45, -51, 72, 76, -28, -42, -118, 55, 101, -29,
+        -118, -16, -44, 0, 0, 9, 41, 73, 68, 65, 84, 120, 94, -20, -64, -127, 0, 0, 0, 0, -61, -96,
+        -5, 83, -33, 96, 4, -75, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -100, -68, -69, -118, 110, -28,
+        -56, -30, 56, -68, -41, -79, 100, 102, 102, 26, -77, -57, 8, 51, -29, -79, 61, 100, 28, 102,
+        102, 102, 102, 102, 102, 74, -122, 25, 2, 67, 73, 6, -126, -80, 97, 102, -50, 38, 89, 102,
+        -90, -1, -29, -66, -84, -114, -70, -69, 74, 114, 89, -3, -94, 43, 125, -49, 122, -47, -81,
+        79, 67, -99, 62, 125, -117, 92, -107, -102, -42, 41, -42, 71, 89, 99, -17, 52, 15, 9, -48,
+        105, -40, -115, 94, -101, 119, 118, 125, 116, 92, -25, -36, -28, -16, -121, 20, 77, -114,
+        56, -80, -39, -121, 127, -128, -56, 49, -117, -77, 15, 31, -8, 29, 92, 112, 116, 59, 17,
+        -13, 0, -3, -113, -84, -22, 28, 5, -41, 84, 94, 36, -30, 29, 32, 102, -57, -118, -115, 112,
+        85, -16, -121, 65, -60, 59, 64, 73, 118, 49, 92, 86, 51, -79, -111, -120, 117, -128, -14,
+        -82, 22, -72, -52, -102, -34, 66, -60, 58, -64, -70, 126, -48, -78, 86, -121, 23, 86, 91,
+        -95, -22, 88, 57, 17, -21, 0, 1, -66, -102, -93, 31, -11, 118, -34, -32, -84, -128, -40,
+        -40, -128, -84, -25, 111, 53, 7, 66, 42, -12, -77, 17, -66, 54, 43, 125, 7, 18, -15, 14,
+        -80, 56, 25, 54, 40, -52, 44, 33, -115, -112, -20, 56, -56, 116, -1, 3, 9, -72, 6, -120,
+        126, 21, 54, -120, -97, 24, 64, 6, 95, -82, -76, 66, 34, 126, -96, -89, 4, 88, 80, 6, 27,
+        20, 76, 32, -119, 103, 58, 67, 34, -12, 91, -49, 8, -16, -31, 21, -40, 96, -74, 31, 73, -91,
+        -84, -128, -52, 25, 79, 8, -16, 107, -40, -67, 75, 14, -51, -122, -52, 115, -4, 3, -28, -63,
+        -18, -49, -28, -60, 8, -56, -52, -29, 30, 96, 10, -20, 94, -10, 39, 103, 86, 65, -30, 74,
+        57, -17, 0, 93, 96, -41, 119, 22, 57, 21, 121, 12, 18, -55, 75, 56, 7, 104, -75, -62, 110,
+        51, -75, -95, 127, 50, 36, -74, -8, -13, 13, -48, -78, 17, 118, -123, 62, -44, -106, -4, 80,
+        72, 124, -61, 54, -128, -33, 114, 104, -68, 66, 2, -75, 91, 65, -43, 44, -82, 1, -90, 64,
+        35, 106, 12, -75, -51, 39, 12, 18, -117, -104, 6, 8, -103, 10, -115, 90, 82, -79, 3, 50,
+        107, 88, 6, -16, 47, -128, 86, 30, -87, -16, 31, 5, -119, -35, 44, 3, 124, 1, -99, 61, -92,
+        -28, 77, 72, -124, 94, 96, 24, -96, -61, 39, -48, -102, 58, -116, -44, 12, -126, 68, 31,
+        -122, 1, 22, 67, 39, 121, 41, -87, 121, 30, 18, 29, 99, -40, 5, 72, -99, 11, -99, 113, -92,
+        40, -78, 51, 36, -114, -80, 11, -16, 22, -12, -74, -112, -86, -121, 33, 49, -128, 93, -128,
+        116, -24, -35, 36, 85, -67, -29, 33, -54, -19, -64, 44, 64, 76, 71, -24, 61, 77, -54, 102,
+        66, 100, -51, 98, 22, 96, 44, 12, 78, -111, -78, 73, -112, -40, -63, 44, 64, 31, 24, -92,
+        -109, -78, -128, -66, 16, 77, -28, 21, 32, -88, -77, -8, 60, -81, 110, 55, 68, -29, 121, 5,
+        24, 102, -127, -63, 9, 82, -41, 19, -94, 2, 94, 1, 6, -61, -88, -119, -44, -83, -125, 104,
+        31, -81, 0, 31, -63, 104, -19, 82, 82, -74, -76, 24, -126, 50, 63, 86, 1, 50, 96, 116, -75,
+        -114, -44, 29, -123, 32, -84, -108, 85, -128, 63, 65, -80, -119, -44, 77, 100, 31, 96, 28,
+        4, 31, -112, -70, 35, 16, -108, 69, 114, 10, -112, -38, 25, -126, -39, -92, 46, 36, 20, 70,
+        47, 17, -89, 0, -111, -45, 33, 88, 79, -22, -94, -85, 97, 52, -124, 85, -128, -96, 101, 16,
+        36, 60, 70, 106, -28, 1, 95, 99, 21, -128, -10, 65, -12, 38, -87, 91, 15, -93, -31, -68, 2,
+        12, -126, 40, -113, -52, 44, 8, 47, -13, 10, -80, 8, -94, -71, -92, 110, 0, 12, 2, -57, -16,
+        10, -112, 9, -111, -27, 62, 41, 27, 42, 62, 8, -14, 10, -48, 11, 18, -41, 72, -103, 47, 12,
+        70, 19, -81, 0, -65, -126, -60, 92, 127, 82, -75, 19, 6, -83, -52, 2, 116, 42, -122, 40,
+        -76, 27, -87, 122, 26, 122, -59, -89, -103, 5, -96, -82, -112, 24, 74, -86, -6, 65, 47,
+        -109, -72, 5, 120, 7, 18, 9, 1, -92, 104, 20, 116, -110, 94, 96, 23, 96, 78, 4, 36, 54,
+        -109, -102, -76, 48, -24, -68, 65, -20, 2, -56, -49, -127, -62, 105, -92, 100, -42, 84, 104,
+        -43, -44, 49, 12, 112, 9, 50, 63, 37, 37, 99, -95, -77, -127, 24, 6, 8, -38, 15, -119, -124,
+        6, 82, 113, 14, 90, -93, 34, 57, 6, -96, -53, -112, -87, 32, 5, 29, -50, 67, -93, -26, 62,
+        -79, 12, 16, 52, 14, 50, -113, 80, -37, 102, 64, -21, 11, -30, 25, -128, -98, -127, 76, 88,
+        10, -75, 105, 11, 52, -34, 37, -82, 1, -24, 20, 100, 14, 81, 91, 14, 66, 99, 39, -15, 13,
+        -48, 24, -20, -46, -99, -96, -12, -25, -80, 75, 39, -58, 1, -24, 70, 20, 100, -34, 33, -89,
+        86, -62, -18, -108, 63, -21, 0, 52, 31, 50, -127, -109, -56, -119, 30, -80, -37, -58, -2,
+        -117, -111, 108, -56, 88, 63, 38, -121, 78, -62, -18, 36, -79, 15, 64, -93, 33, -11, 93, 7,
+        -110, -118, -47, -84, -125, -29, 39, -111, 7, 4, -96, -95, -112, 90, -66, -99, 36, -58, 46,
+        -125, 13, 114, -97, 34, -113, 8, 64, -61, 33, 101, -15, -51, 33, -125, -21, -85, 97, 119,
+        -94, -127, 60, 36, 0, 45, 78, -128, 84, 85, -59, -116, 88, -78, -95, -100, -57, -105, 67,
+        35, 59, -110, 60, 38, 0, 101, 21, -64, -127, -28, 39, 94, -100, -108, -65, 102, -63, 63,
+        126, -71, -77, 54, 73, 120, 13, -30, 57, 1, 40, -75, 103, 61, -38, 101, 33, -15, 14, 32,
+        -38, 122, 46, 2, -22, 86, 17, -5, 0, -94, -37, 35, -62, -95, 104, -67, 31, -9, 0, 114, 41,
+        -33, 127, 90, 3, 5, 17, -9, -119, 113, 0, -25, 26, 6, -82, -84, -115, 67, 27, 110, 17, -37,
+        0, 74, 18, -69, 13, -36, 80, 52, -6, -3, 21, 93, 95, -37, -107, 121, -19, -85, 93, 48, -118,
+        -24, -19, -63, 1, 68, 67, 96, -76, -101, -68, 41, -64, 83, 16, 12, -9, -86, 0, -25, 32, -8,
+        -42, -101, 2, -8, 77, -121, -32, -65, -34, 20, -32, 118, 20, 4, 103, -67, 41, -64, 35, 16,
+        -83, -10, -90, 0, 95, 65, 20, 81, -25, 69, 1, 70, 66, 98, -101, 23, 5, 120, 29, 18, -106,
+        63, 122, -9, 53, 0, 40, 110, -15, -102, 0, 99, 2, 33, -13, 121, -106, -73, 4, 40, 13, -125,
+        -44, -28, 124, 47, 9, 64, -65, -128, -100, -27, -116, -105, 4, 104, -123, 35, 3, 98, -67,
+        34, 64, -38, -113, 112, -28, 111, 37, -34, 16, -128, 70, -62, -95, -124, 121, -34, 16, -64,
+        111, 63, 28, 43, 10, -14, -4, 0, 84, 110, -123, 99, 39, -22, 60, 63, 0, 45, -124, 19, -63,
+        -37, 61, 63, -128, -33, 93, 56, 81, 53, -48, -29, 3, 80, 98, 46, -100, -23, -31, -47, 1, -4,
+        -90, -11, -34, 27, -78, 16, 78, 101, 123, 96, -128, -46, -70, 110, 99, 31, -49, -84, -40,
+        50, -82, 108, 114, 68, 32, -38, 50, 62, -51, -125, 2, 68, -66, 48, 99, -61, -24, -126, -36,
+        8, -76, -57, -22, 7, -98, 17, 96, 90, -7, -61, -117, -106, 37, -63, 5, 67, 124, -8, 7, -104,
+        48, -1, 78, 33, 92, 54, -28, 1, -17, 0, 23, -122, 55, 5, -62, -108, -43, 126, 124, 3, 44,
+        -23, -46, 28, 10, 7, 44, 113, -63, -5, 11, -18, -68, -97, -79, 106, 116, -6, -94, 71, -29,
+        -31, 68, 58, -41, 0, 33, 111, 108, -124, 68, 84, -14, 111, 50, 126, 59, 111, -63, -19, -24,
+        82, -51, 79, -101, -31, -60, 71, 44, 3, 116, -69, 105, -127, -96, -2, -47, -123, 95, -113,
+        57, 77, -94, -76, 34, 56, 22, 122, -119, 95, -128, 97, 25, 81, 48, -22, 62, 98, 70, 52, 57,
+        -76, -25, 0, 28, 42, -114, 102, 22, -96, -61, -17, 19, 96, 112, 124, -24, -126, 32, 114,
+        -86, -31, 61, 56, 84, -63, 43, -64, 83, -75, 48, -104, -34, -77, 63, -75, -19, -38, 84, 56,
+        114, -112, 83, -128, -109, -58, -1, -79, -74, -53, 105, 82, -14, 86, 25, 28, -88, 76, 101,
+        19, -96, 113, 5, -12, -84, -37, -94, 73, 85, -64, 19, 112, 96, 48, -105, 0, -61, -10, 67,
+        111, -6, 117, 106, -113, 41, -112, 27, -60, 36, -64, -124, 3, -48, -5, 44, -111, -38, -25,
+        114, 95, -56, 88, 67, 88, 4, -56, -6, 39, -12, -6, -92, 82, 123, 61, 25, 12, -103, 76, 14,
+        1, -74, 6, 67, 111, 23, -71, -32, 47, 77, -112, -24, -50, 96, -81, -79, 78, -107, -48, -101,
+        -23, 79, -82, 72, 25, 4, 81, -32, 94, -9, 15, -112, 1, -67, -13, 49, -28, -102, -40, -61,
+        16, -11, 114, -5, 0, -117, -95, 23, -6, 12, -71, 106, -38, -37, 16, 108, 115, -9, 0, 115,
+        -22, -123, -25, 87, -41, 45, -55, -123, -47, 110, 119, 15, -112, 1, -67, -92, 28, 50, -95,
+        91, 18, 12, -2, -22, -17, -34, 1, 46, 4, 10, -61, 96, 77, -23, 2, -125, -16, 7, -18, 29,
+        -96, 31, 12, -14, -55, -100, 65, -48, -85, 14, 112, -21, 0, 89, 81, -48, 43, -18, 68, -26,
+        116, 11, -124, 78, 124, -99, 91, 7, -8, 14, 6, 93, -55, -84, 39, -96, -109, -76, -43, -99,
+        3, 44, 93, 11, -125, 103, -55, -84, 124, -24, 68, 52, -72, 115, -128, -21, -110, -11, -85,
+        89, 105, -63, -48, -22, -40, -24, -50, 1, -118, 96, -12, 36, -103, -106, 1, -83, -49, -3,
+        -36, 57, -64, 40, 24, 88, -9, -110, 105, 35, -95, 53, -118, -36, 56, -128, -80, -87, 2, 44,
+        57, 100, 90, 57, -76, 42, -36, 57, 64, 73, -88, 100, -15, 102, 90, 75, 20, 52, 122, -70,
+        115, -128, -65, 67, -80, -114, 76, 91, 82, 5, -115, 5, -18, 28, -96, 23, 4, -83, 100, 90,
+        98, 2, -20, -114, -5, -72, 115, -128, -97, 65, -80, -127, 76, -101, 83, 5, -69, 126, -60,
+        44, -64, 120, 50, 45, -57, 2, -69, -41, -119, -39, 41, 16, -100, 70, 102, 109, -126, 93, 92,
+        -118, 91, 7, -72, 8, 81, 57, -103, -11, 61, -20, -6, -112, 91, 7, -72, 7, -47, 80, 50, -53,
+        87, 120, 45, -64, -32, 65, 72, 55, 71, -43, 28, -1, 125, -80, -63, 76, 114, -17, 0, -76, 30,
+        -94, 91, 100, 78, 73, 32, 108, -84, -21, -36, 61, 64, -98, 124, -53, 88, 83, -118, -124,
+        -55, 114, 110, 28, 96, 13, 36, 62, 37, 51, 26, 39, -61, 38, -82, -63, -19, 3, -8, -3, 11,
+        18, -13, -55, -124, -77, -80, -63, 72, 6, -13, 3, -98, -123, -124, 37, -97, 92, -42, 82, 5,
+        -101, -9, -120, 65, -128, -60, 56, 72, -60, 61, 73, 46, 74, 29, 2, -101, -32, 68, 14, 1,
+        -24, 69, -56, -44, 111, 34, -41, -4, 27, 54, 73, -1, 33, 22, 1, 124, -62, 32, -45, -9, 107,
+        114, 69, 79, -19, 126, -117, 60, 2, -48, 88, -56, 77, 9, 34, 117, -30, 112, -51, 46, -60,
+        37, 0, -19, -126, 92, 65, 8, -75, 79, -121, -39, -62, 103, 51, 44, 2, 44, -83, -123, 92,
+        -46, -62, 104, 106, -121, 123, 119, -123, -29, -49, 35, 0, 125, 25, 6, 7, -110, -97, 85, 78,
+        16, 51, 37, 30, 54, 87, -25, 17, -85, 0, 52, 33, 28, -114, -124, 23, -107, -112, -126, -57,
+        122, 6, -61, 6, -71, 107, -120, 89, 0, 42, 9, -125, 67, 81, -121, -97, 107, 33, -89, 82,
+        -73, 103, 107, 11, -34, 89, 66, -20, 2, -48, -84, 90, 56, 113, -91, 57, -77, 117, -85, 63,
+        73, 5, -52, 40, 122, 9, 26, -15, 15, -13, -100, 31, 16, 91, 1, -25, -30, -69, 31, -102, -40,
+        -21, -58, 15, 115, 98, -3, -2, 127, -55, -9, -23, 29, -78, 103, 126, -97, -26, 56, -24, -68,
+        124, -113, -19, -4, -128, -111, 27, -47, -74, -64, -66, -31, 101, -35, -101, 42, 43, -25,
+        118, 63, -1, 80, 4, 4, 97, 31, 112, -98, 31, -112, 115, 8, -26, -44, -97, 77, 97, 62, 63,
+        -96, -75, 18, -82, 43, 124, -91, 55, -1, 17, 26, 65, -109, 92, 77, -80, -17, 76, -94, 103,
+        12, 81, -15, -65, -40, -17, 42, -38, -21, -8, -128, 75, -111, 30, 52, 71, 40, -89, -57, 114,
+        11, -44, -123, -33, -100, -105, -24, 113, -77, -60, 126, 120, 124, 102, 56, 20, 36, -36,
+        -51, -53, -113, 33, 1, -61, 0, 34, -97, 77, -33, 12, 104, -22, 8, 71, 66, -21, -101, 94,
+        -19, 113, -80, 63, 9, 56, 7, 16, 61, 22, 50, 120, -2, -120, -15, -57, -26, 46, 91, 59, 57,
+        -82, -70, -90, -90, -70, 99, 97, -16, 39, -51, 71, -45, -13, 62, -34, 51, 33, -123, 4, 28,
+        3, 40, 10, -22, 52, 45, 58, 96, 78, -1, -128, -108, -40, 82, 127, 114, -55, -1, -38, -127,
+        3, 1, 0, 0, 0, -122, 65, -9, -89, -66, -63, 8, 106, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,
+        -31, -37, 22, 69, 99, -29, 53, -11, 0, 0, 0, 0, 73, 69, 78, 68, -82, 66, 96, -126
+      };
+}