('/**\\n     *
Copies a buffer to a native memory.
\\n     *\\n     *
If the buffer is direct, it will be attached to the model directly without copying.\\n     * Otherwise, it copies the content of the buffer to a newly allocated memory in the native heap ranging\\n     * from position() to (limit() - 1) without changing its position.
\\n     *\\n     *
Note that the order() of the buffer should be {@link ByteOrder#nativeOrder()} because\\n     * the native byte order of your platform may differ from JVM.
\\n     *\\n     * @param buffer the non-empty byte buffer from which to copy\\n     *\\n     * @return the pointer to the allocated native memory\\n     * @throws IllegalArgumentException if buffer is null or empty\\n     */', '')

('', '// return a pointer to the direct buffer without copying\n')

('', '// it is array-backed and not read-only\n')

('', '// use duplicated buffer to avoid changing `position`\n')

b'/**\n     *
Copies a buffer to a native memory.
\n     *\n     *
If the buffer is direct, it will be attached to the model directly without copying.\n     * Otherwise, it copies the content of the buffer to a newly allocated memory in the native heap ranging\n     * from position() to (limit() - 1) without changing its position.
\n     *\n     *
Note that the order() of the buffer should be {@link ByteOrder#nativeOrder()} because\n     * the native byte order of your platform may differ from JVM.
\n     *\n     * @param buffer the non-empty byte buffer from which to copy\n     *\n     * @return the pointer to the allocated native memory\n     * @throws IllegalArgumentException if buffer is null or empty\n     */'static Pointer copyToNativeMemory(final ByteBuffer buffer) {
        if (buffer == null || buffer.remaining() <= 0) {
            throw new IllegalArgumentException("buffer must not be null or empty");
        }

        final int length = buffer.remaining();

        if (buffer.isDirect()) {
            final int offset = buffer.position();

            // return a pointer to the direct buffer without copying
            return Native.getDirectBufferPointer(buffer).share(offset, length);
        } else {
            final Memory mem = new Memory(length);

            int index;
            byte[] bytes;
            if (buffer.hasArray()) { // it is array-backed and not read-only
                index = buffer.arrayOffset() + buffer.position();
                bytes = buffer.array();
            } else {
                index = 0;
                // use duplicated buffer to avoid changing `position`
                bytes = new byte[length];
                buffer.duplicate().get(bytes);
            }
            mem.write(0, bytes, index, length);

            return mem.share(0, length);
        }
    }

@Test
    public void copyDirectBufferToNativeMemory() {
        final byte[] bytes = new byte[] {0, 1, 2, 3, 4, 5, 6, 7};

        final ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
        buf.put(bytes).rewind();
        assertEquals(8, buf.remaining());

        final Pointer ptr = BufferUtils.copyToNativeMemory(buf);
        assertNotNull(ptr);
        assertArrayEquals(bytes, ptr.getByteArray(0, bytes.length));
        assertAll("buffer's state",
                () -> assertEquals(0, buf.position()),
                () -> assertEquals(8, buf.limit())
        );
    }


@Test
    public void copySlicedDirectBufferToNativeMemory() {
        final byte[] bytes = new byte[] {0, 1, 2, 3, 4, 5, 6, 7};
        final byte[] slicedBytes = new byte[] {2, 3, 4, 5};

        final ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
        buf.put(bytes).rewind();

        // slice 4 bytes
        buf.position(2).limit(6);
        assertEquals(4, buf.remaining());

        final Pointer ptr = BufferUtils.copyToNativeMemory(buf);
        assertNotNull(ptr);
        assertArrayEquals(slicedBytes, ptr.getByteArray(0, slicedBytes.length));
        assertAll("buffer's state",
                () -> assertEquals(2, buf.position()),
                () -> assertEquals(6, buf.limit())
        );
    }


@Test
    public void copyNullFloatArrayToNativeMemory() {
        final float[] values = null; // test case
        final int offset = 0;
        final int length = 0;

        assertThrows(
                IllegalArgumentException.class,
                () -> BufferUtils.copyToNativeMemory(values, offset, length));
    }


@Test
    public void copyNegativeOffsetFloatArrayToNativeMemory() {
        final float[] values = new float[] {0f, 1f, 2f, 3f};
        final int offset = -1; // test case
        final int length = values.length;

        assertThrows(
                ArrayIndexOutOfBoundsException.class,
                () -> BufferUtils.copyToNativeMemory(values, offset, length));
    }


@Test
    public void copyNegativeLengthFloatArrayToNativeMemory() {
        final float[] values = new float[] {0f, 1f, 2f, 3f};
        final int offset = 0;
        final int length = -1; // test case

        assertThrows(
                IllegalArgumentException.class,
                () -> BufferUtils.copyToNativeMemory(values, offset, length));
    }


('/**\\n     * Throws {@link MenohException} if the errorCode of a native Menoh function is\\n     * non-zero. This method must be called right after the invocation because it uses \\n     * menoh_get_last_error_message.\\n     *\\n     * @param errorCode an error code returned from the Menoh function\\n     */', '')

('', '// ErrorCode.valueOf() throws MenohException if the error code is undefined\n')

b'/**\n     * Throws {@link MenohException} if the errorCode of a native Menoh function is\n     * non-zero. This method must be called right after the invocation because it uses \n     * menoh_get_last_error_message.\n     *\n     * @param errorCode an error code returned from the Menoh function\n     */'static void checkError(int errorCode) throws MenohException {
        if (errorCode != ErrorCode.SUCCESS.getId()) {
            final String errorMessage = MenohNative.INSTANCE.menoh_get_last_error_message();

            ErrorCode ec;
            try {
                ec = ErrorCode.valueOf(errorCode);
            } catch (MenohException e) {
                // ErrorCode.valueOf() throws MenohException if the error code is undefined
                throw new MenohException(ErrorCode.UNDEFINED, String.format("%s (%d)", errorMessage, errorCode), e);
            }

            final String errorCodeName = ec.toString().toLowerCase(Locale.ENGLISH);
            throw new MenohException(ec, String.format("%s (%s)", errorMessage, errorCodeName));
        }
    }

@Test
    public void checkErrorSuccess() {
        checkError(ErrorCode.SUCCESS.getId());
    }


('/**\\n     * Loads an ONNX model from the specified file.\\n     */', '')

b'/**\n     * Loads an ONNX model from the specified file.\n     */'public static ModelData fromOnnxFile(String onnxModelPath) throws MenohException {
        final PointerByReference handle = new PointerByReference();
        checkError(MenohNative.INSTANCE.menoh_make_model_data_from_onnx(onnxModelPath, handle));

        return new ModelData(handle.getValue());
    }

@Test
    public void makeFromNonExistentOnnxFile() {
        MenohException e = assertThrows(
                MenohException.class, () -> ModelData.fromOnnxFile("__NON_EXISTENT_FILENAME__"));
        assertAll("non-existent onnx file",
                () -> assertEquals(ErrorCode.INVALID_FILENAME, e.getErrorCode()),
                () -> assertEquals(
                        "menoh invalid filename error: __NON_EXISTENT_FILENAME__ (invalid_filename)",
                        e.getMessage())
        );
    }


@Test
    public void makeFromInvalidOnnxFile() throws Exception {
        final String path = getResourceFilePath("models/invalid_format.onnx");

        MenohException e = assertThrows(MenohException.class, () -> ModelData.fromOnnxFile(path));
        assertAll("invalid onnx file",
                () -> assertEquals(ErrorCode.ONNX_PARSE_ERROR, e.getErrorCode()),
                () -> assertEquals(
                        String.format("menoh onnx parse error: %s (onnx_parse_error)", path),
                        e.getMessage())
        );
    }


@Test
    public void makeFromUnsupportedOnnxOpsetVersionFile() throws Exception {
        // Note: This file is a copy of and_op.onnx which is edited the last byte to 127 (0x7e)
        final String path = getResourceFilePath("models/unsupported_onnx_opset_version.onnx");

        MenohException e = assertThrows(MenohException.class, () -> ModelData.fromOnnxFile(path));
        assertAll("invalid onnx file",
                () -> assertEquals(ErrorCode.UNSUPPORTED_ONNX_OPSET_VERSION, e.getErrorCode()),
                () -> assertEquals(
                        String.format(
                                "menoh unsupported onnx opset version error: %s has "
                                        + "onnx opset version %d > %d (unsupported_onnx_opset_version)",
                                path, 127, 7),
                        e.getMessage())
        );
    }


('/**\\n     * Creates a {@link ModelBuilder}.\\n     */', '')

b'/**\n     * Creates a {@link ModelBuilder}.\n     */'public static ModelBuilder builder(VariableProfileTable vpt) throws MenohException {
        final PointerByReference ref = new PointerByReference();
        checkError(MenohNative.INSTANCE.menoh_make_model_builder(vpt.nativeHandle(), ref));

        return new ModelBuilder(ref.getValue());
    }

@Test
    public void buildModelIfBackendNotFound() throws Exception {
        final String path = getResourceFilePath("models/and_op.onnx");
        final int batchSize = 4;
        final int inputDim = 2;
        final String backendName = "__non_existent_backend__"; // test case
        final String backendConfig = "";

        try (
                ModelData modelData = ModelData.fromOnnxFile(path);
                VariableProfileTableBuilder vptBuilder = VariableProfileTable.builder()
                        .addInputProfile("input", DType.FLOAT, new int[] {batchSize, inputDim})
                        .addOutputProfile("output", DType.FLOAT);
                VariableProfileTable vpt = vptBuilder.build(modelData);
                ModelBuilder modelBuilder = Model.builder(vpt)
        ) {
            modelBuilder.attachExternalBuffer("input", new float[] {0f, 0f, 0f, 1f, 1f, 0f, 1f, 1f});

            MenohException e = assertThrows(
                    MenohException.class, () -> modelBuilder.build(modelData, backendName, backendConfig));
            assertAll("backendName is invalid",
                    () -> assertEquals(ErrorCode.INVALID_BACKEND_NAME, e.getErrorCode()),
                    () -> assertEquals(
                            String.format("menoh invalid backend name error: %s (invalid_backend_name)", backendName),
                            e.getMessage())
            );
        }
    }


('/**\\n     * Creates a {@link VariableProfileTableBuilder}.\\n     */', '')

b'/**\n     * Creates a {@link VariableProfileTableBuilder}.\n     */'public static VariableProfileTableBuilder builder() throws MenohException {
        final PointerByReference ref = new PointerByReference();
        checkError(MenohNative.INSTANCE.menoh_make_variable_profile_table_builder(ref));

        return new VariableProfileTableBuilder(ref.getValue());
    }

@Test
    public void addValidInputProfile() {
        try (VariableProfileTableBuilder builder = VariableProfileTable.builder()) {
            builder.addInputProfile("foo", DType.FLOAT, new int[] {1, 1});
        }
    }


@Test
    public void addValidInputProfileWithInvalidDims() {
        try (VariableProfileTableBuilder builder = VariableProfileTable.builder()) {
            MenohException e = assertThrows(MenohException.class,
                    // test case: dims.length == 1
                    () -> builder.addInputProfile("foo", DType.FLOAT, new int[] {1, 1, 1, 1, 1}));
            assertAll("invalid dim size",
                    () -> assertEquals(ErrorCode.UNDEFINED, e.getErrorCode()),
                    () -> assertTrue(e.getMessage().startsWith("foo has an invalid dims size: 5"),
                            String.format("%s doesn't start with \"foo has an invalid dims size: 5\"",
                                    e.getMessage())));
        }
    }


@Test
    public void copyEmptyDirectBufferToNativeMemory() {
        final ByteBuffer buf = ByteBuffer.allocateDirect(0);
        assertEquals(0, buf.remaining());

        assertThrows(
                IllegalArgumentException.class,
                () -> BufferUtils.copyToNativeMemory(buf));
    }


@Test
    public void addValidOutputProfile() {
        try (VariableProfileTableBuilder builder = VariableProfileTable.builder()) {
            builder.addOutputProfile("foo", DType.FLOAT);
        }
    }


@Test
    public void buildVariableProfileTableIfInputProfileNameNotFound() throws Exception {
        final String path = getResourceFilePath("models/and_op.onnx");
        final int batchSize = 1;
        final int inputDim = 2;
        final String inputProfileName = "__non_existent_variable__"; // test case
        final String inputVariableNameInModel = "input";
        final String outputProfileName = "output";

        try (
                ModelData modelData = ModelData.fromOnnxFile(path);
                VariableProfileTableBuilder vptBuilder = VariableProfileTable.builder()
                        .addInputProfile(inputProfileName, DType.FLOAT, new int[] {batchSize, inputDim})
                        .addOutputProfile(outputProfileName, DType.FLOAT)
        ) {
            MenohException e = assertThrows(MenohException.class, () -> vptBuilder.build(modelData));
            assertAll("input profile name not found",
                    () -> assertEquals(ErrorCode.VARIABLE_NOT_FOUND, e.getErrorCode()),
                    () -> assertEquals(
                            String.format("menoh variable not found error: %s (variable_not_found)",
                                    inputVariableNameInModel), // not `inputProfileName`
                            e.getMessage())
            );
        }
    }


@Test
    public void buildVariableProfileTableIfInputProfileDimsMismatched() throws Exception {
        final String path = getResourceFilePath("models/and_op.onnx");
        final int batchSize = 1;
        final int inputDim = 3; // test case
        final String inputProfileName = "input";
        final String outputProfileName = "output";

        try (
                ModelData modelData = ModelData.fromOnnxFile(path);
                VariableProfileTableBuilder vptBuilder = VariableProfileTable.builder()
                        .addInputProfile(inputProfileName, DType.FLOAT, new int[] {batchSize, inputDim})
                        .addOutputProfile(outputProfileName, DType.FLOAT)
        ) {
            MenohException e = assertThrows(MenohException.class, () -> vptBuilder.build(modelData));
            assertAll("mismatched input dims",
                    () -> assertEquals(ErrorCode.DIMENSION_MISMATCH, e.getErrorCode()),
                    () -> assertEquals(
                            String.format(
                                    "menoh dimension mismatch error: Gemm issuing \"%s\": input[1] and weight[1] "
                                            + "actual value: %d valid value: %d (dimension_mismatch)",
                                    "140211424823896", // the name of output[0] in Gemm layer
                                    3, 2),
                            e.getMessage())
            );
        }
    }


@Test
    public void buildVariableProfileTableIfOutputProfileNameNotFound() throws Exception {
        final String path = getResourceFilePath("models/and_op.onnx");
        final int batchSize = 1;
        final int inputDim = 2;
        final String inputProfileName = "input";
        final String outputProfileName = "__non_existent_variable__"; // test case

        try (
                ModelData modelData = ModelData.fromOnnxFile(path);
                VariableProfileTableBuilder vptBuilder = VariableProfileTable.builder()
                        .addInputProfile(inputProfileName, DType.FLOAT, new int[] {batchSize, inputDim})
                        .addOutputProfile(outputProfileName, DType.FLOAT)
        ) {
            MenohException e = assertThrows(MenohException.class, () -> vptBuilder.build(modelData));
            assertAll("output profile name not found",
                    () -> assertEquals(ErrorCode.VARIABLE_NOT_FOUND, e.getErrorCode()),
                    () -> assertEquals(
                            String.format("menoh variable not found error: %s (variable_not_found)", outputProfileName),
                            e.getMessage())
            );
        }
    }


@Test
    public void copyArrayBackedBufferToNativeMemory() {
        final byte[] bytes = new byte[] {0, 1, 2, 3, 4, 5, 6, 7};

        final ByteBuffer buf = ByteBuffer.wrap(bytes);
        assertEquals(8, buf.remaining());

        final Pointer ptr = BufferUtils.copyToNativeMemory(buf);
        assertNotNull(ptr);
        assertArrayEquals(bytes, ptr.getByteArray(0, bytes.length));
        assertAll("buffer's state",
                () -> assertEquals(0, buf.position()),
                () -> assertEquals(8, buf.limit())
        );
    }


@Test
    public void copySlicedArrayBackedBufferToNativeMemory() {
        final byte[] bytes = new byte[] {0, 1, 2, 3, 4, 5, 6, 7};
        final byte[] slicedBytes = new byte[] {2, 3, 4, 5};

        final ByteBuffer buf = ByteBuffer.wrap(bytes, 1, 6).slice();
        assertAll("non-zero array offset",
                () -> assertEquals(1, buf.arrayOffset()),
                () -> assertEquals(0, buf.position()),
                () -> assertEquals(6, buf.limit())
        );

        // slice 4 bytes
        buf.position(1).limit(5);
        assertEquals(4, buf.remaining());

        final Pointer ptr = BufferUtils.copyToNativeMemory(buf);
        assertNotNull(ptr);
        assertArrayEquals(slicedBytes, ptr.getByteArray(0, slicedBytes.length));
        assertAll("buffer's state",
                () -> assertEquals(1, buf.position()),
                () -> assertEquals(5, buf.limit())
        );
    }


@Test
    public void copyReadOnlyBufferToNativeMemory() {
        final byte[] bytes = new byte[] {0, 1, 2, 3, 4, 5, 6, 7};

        final ByteBuffer buf = ByteBuffer.wrap(bytes).asReadOnlyBuffer();
        assertEquals(8, buf.remaining());

        final Pointer ptr = BufferUtils.copyToNativeMemory(buf);
        assertNotNull(ptr);
        assertArrayEquals(bytes, ptr.getByteArray(0, bytes.length));
        assertAll("buffer's state",
                () -> assertEquals(0, buf.position()),
                () -> assertEquals(8, buf.limit())
        );
    }


@Test
    public void copySlicedReadOnlyBufferToNativeMemory() {
        final byte[] bytes = new byte[] {0, 1, 2, 3, 4, 5, 6, 7};
        final byte[] slicedBytes = new byte[] {2, 3, 4, 5};

        final ByteBuffer buf = ByteBuffer.wrap(bytes).asReadOnlyBuffer();

        // slice 4 bytes
        buf.position(2).limit(6);
        assertEquals(4, buf.remaining());

        final Pointer ptr = BufferUtils.copyToNativeMemory(buf);
        assertNotNull(ptr);
        assertArrayEquals(slicedBytes, ptr.getByteArray(0, slicedBytes.length));
        assertAll("buffer's state",
                () -> assertEquals(2, buf.position()),
                () -> assertEquals(6, buf.limit())
        );
    }


@Test
    public void copyFloatArrayToNativeMemory() {
        final float[] values = new float[] {0f, 1f, 2f, 3f};
        final ByteBuffer valuesBuf = ByteBuffer.allocate(values.length * 4).order(ByteOrder.nativeOrder());
        valuesBuf.asFloatBuffer().put(values);
        final int offset = 0;
        final int length = values.length;

        final Pointer ptr = BufferUtils.copyToNativeMemory(values, offset, length);
        assertNotNull(ptr);
        assertAll("copied values in native memory",
                () -> assertArrayEquals(values, ptr.getFloatArray(0, length)),
                // check the byte order
                () -> assertArrayEquals(valuesBuf.array(), ptr.getByteArray(0, length * 4))
        );
    }


@Test
    public void copySlicedFloatArrayToNativeMemory() {
        final float[] values = new float[] {0f, 1f, 2f, 3f};
        final float[] slicedValues = new float[] {1f, 2f};
        final ByteBuffer slicedValuesBuf = ByteBuffer.allocate(slicedValues.length * 4).order(ByteOrder.nativeOrder());
        slicedValuesBuf.asFloatBuffer().put(slicedValues);
        final int offset = 1;
        final int length = slicedValues.length;

        // slice 2 elements (8 bytes)
        final Pointer ptr = BufferUtils.copyToNativeMemory(values, offset, length);
        assertNotNull(ptr);
        assertAll("copied values in native memory",
                () -> assertArrayEquals(slicedValues, ptr.getFloatArray(0, length)),
                // check the byte order
                () -> assertArrayEquals(slicedValuesBuf.array(), ptr.getByteArray(0, length * 4))
        );
    }


@Test
    public void copyEmptyFloatArrayToNativeMemory() {
        final float[] values = new float[] {}; // test case
        final int offset = 0;
        final int length = values.length;

        assertThrows(
                IllegalArgumentException.class,
                () -> BufferUtils.copyToNativeMemory(values, offset, length));
    }


('', '// Append meta data.\n')

Uri getAuthorizationUri(URL baseOAuthUrl, String clientId) {
        try {
            final Uri.Builder builder = Uri.parse(new URL(baseOAuthUrl, ApiConstants.AUTHORIZE).toURI().toString())
                    .buildUpon()
                    .appendQueryParameter(ARG_RESPONSE_TYPE, "code")
                    .appendQueryParameter(ARG_CLIENT_ID, clientId)
                    .appendQueryParameter(ARG_REDIRECT_URI, redirectUri.toString())
                    .appendQueryParameter(ARG_SCOPE, scope);

            if (showSignUp) {
                builder.appendQueryParameter(ARG_LAYOUT, LAYOUT_SIGNUP);
            }

            appendIfNotNull(builder, ARG_ACCOUNT, account);
            appendIfNotNull(builder, ARG_ACCOUNT_CURRENCY, accountCurrency);
            appendIfNotNull(builder, ARG_REFERRAL, referralId);

            // Append meta data.
            appendIfNotNull(builder, META_NAME, metaName);
            appendIfNotNull(builder, META_SEND_LIMIT_AMOUNT, sendLimitAmount);
            appendIfNotNull(builder, META_SEND_LIMIT_CURRENCY, sendLimitCurrency);
            appendIfNotNull(builder, META_SEND_LIMIT_PERIOD, sendLimitPeriod);

            return builder.build();
        } catch (URISyntaxException | MalformedURLException e) {
            throw new IllegalArgumentException(e);
        }
    }

@Test
    public void shouldBuildCorrectUri() throws Exception {
        // Given
        final String clientId = "clientId";
        final Uri redirectUri = Uri.parse("coinbase://some-app");
        final String scope = "user:read";
        final String baseOauthUrl = "https://www.coinbase.com/authorize";
        final URL url = new URL(baseOauthUrl);
        final Uri wantedUri = Uri.parse(baseOauthUrl)
                .buildUpon()
                .path(ApiConstants.AUTHORIZE)
                // Add from request
                .appendQueryParameter(AuthorizationRequest.ARG_RESPONSE_TYPE, "code")
                .appendQueryParameter(AuthorizationRequest.ARG_CLIENT_ID, clientId)
                .appendQueryParameter(AuthorizationRequest.ARG_REDIRECT_URI, redirectUri.toString())
                .appendQueryParameter(AuthorizationRequest.ARG_SCOPE, scope)
                .build();

        // When
        final Uri authorizationUri = new AuthorizationRequest(redirectUri, scope)
                .getAuthorizationUri(url, clientId);

        // Then
        assertThat(authorizationUri).isEqualTo(wantedUri);
    }


('/**\\n     * Creates an instance of {@link PaginationParams} to get next page items.\\n     *
\\n     * Keeps limit and order from original {@link PaginationParams}.\\n     *\\n     * @param pagination current page pagination params.\\n     * @return {@link PaginationParams} to get next items page.\\n     * @throws IllegalArgumentException when {@link PagedResponse.Pagination#getNextUri()}\\n     *                                  returns null, which means, the end of the items\\n     *                                  list is already reached.\\n     */', '')

b'/**\n     * Creates an instance of {@link PaginationParams} to get next page items.\n     *
\n     * Keeps limit and order from original {@link PaginationParams}.\n     *\n     * @param pagination current page pagination params.\n     * @return {@link PaginationParams} to get next items page.\n     * @throws IllegalArgumentException when {@link PagedResponse.Pagination#getNextUri()}\n     *                                  returns null, which means, the end of the items\n     *                                  list is already reached.\n     */'@SuppressWarnings("checkstyle:MultipleStringLiterals")
    public static PaginationParams nextPage(@NonNull PagedResponse.Pagination pagination) throws IllegalArgumentException {
        if (pagination.getNextUri() == null) {
            return null;
        }
        try {
            String startingAfterId = getQueryParameter(pagination.getNextUri(), STARTING_AFTER_KEY);
            return copyLimitAndOrder(fromStartingAfter(startingAfterId), pagination);
        } catch (Exception e) {
            throw new IllegalArgumentException("Malformed url", e);
        }
    }

@Test
    public void noNextPageNull_ParamsNull() {
        // Given
        PagedResponse.Pagination pagination = new PagedResponse.Pagination();

        // When
        PaginationParams paginationParams = PaginationParams.nextPage(pagination);

        // Then
        assertThat(paginationParams).isNull();
    }


('/**\\n     * Creates an instance of {@link PaginationParams} to get previous page items.\\n     *
\\n     * Keeps limit and order from original {@link PaginationParams}.\\n     *\\n     * @param pagination current page pagination params.\\n     * @return {@link PaginationParams} to get previous items page.\\n     * @throws IllegalArgumentException when {@link PagedResponse.Pagination#getPreviousUri()}\\n     *                                  returns null, which means, the beginning of the\\n     *                                  items list is already reached.\\n     */', '')

b'/**\n     * Creates an instance of {@link PaginationParams} to get previous page items.\n     *
\n     * Keeps limit and order from original {@link PaginationParams}.\n     *\n     * @param pagination current page pagination params.\n     * @return {@link PaginationParams} to get previous items page.\n     * @throws IllegalArgumentException when {@link PagedResponse.Pagination#getPreviousUri()}\n     *                                  returns null, which means, the beginning of the\n     *                                  items list is already reached.\n     */'@SuppressWarnings("checkstyle:MultipleStringLiterals")
    public static PaginationParams previousPage(@NonNull PagedResponse.Pagination pagination) throws IllegalArgumentException {
        if (pagination.getPreviousUri() == null) {
            return null;
        }
        try {
            String endingBeforeId = getQueryParameter(pagination.getPreviousUri(), ENDING_BEFORE_KEY);
            return copyLimitAndOrder(fromEndingBefore(endingBeforeId), pagination);
        } catch (Exception e) {
            throw new IllegalArgumentException("Malformed url", e);
        }
    }

@Test
    public void noPreviousPageNull_ParamsNull() {
        // Given
        PagedResponse.Pagination pagination = new PagedResponse.Pagination();

        // When
        PaginationParams paginationParams = PaginationParams.previousPage(pagination);

        // Then
        assertThat(paginationParams).isNull();
    }


@Test(expected = IllegalArgumentException.class)
    public void noNextPage_nextIdNotProvided_ExceptionThrown() {
        // Given
        PagedResponse.Pagination pagination = new PagedResponse.Pagination();
        pagination.setNextUri("/path");

        // When
        PaginationParams.nextPage(pagination);

        // Then
        Assertions.fail("Should throw an " + IllegalArgumentException.class);
    }


@Test(expected = IllegalArgumentException.class)
    public void noPreviousPage_previousIdNotProvided_ExceptionThrown() {
        // Given
        PagedResponse.Pagination pagination = new PagedResponse.Pagination();
        pagination.setPreviousUri("/path");

        // When
        PaginationParams.previousPage(pagination);

        // Then
        Assertions.fail("Should throw an " + IllegalArgumentException.class);
    }


('/**\\n     * Create a {@link ServiceElement}.\\n     *\\n     * @param signature The {@link ServiceSignature}, must not be {@code null}.\\n     *\\n     * @return A {@code ServiceElement}\\n     *\\n     * @throws ConfigurationException if there are problem reading the configuration\\n     */', '')

b'/**\n     * Create a {@link ServiceElement}.\n     *\n     * @param signature The {@link ServiceSignature}, must not be {@code null}.\n     *\n     * @return A {@code ServiceElement}\n     *\n     * @throws ConfigurationException if there are problem reading the configuration\n     */'public static ServiceElement create(final ServiceSignature signature, File configFile) throws IOException,
                                                                                ConfigurationException,
                                                                                ResolverException,
                                                                                URISyntaxException {
        return create(signature.getDeployment(), configFile);
    }

@Test
    public void testUsingDeploymentForService() throws Exception {
        ServiceDeployment deployment = new ServiceDeployment();
        deployment.setImpl("foo.Impl");
        deployment.setConfig("-");
        deployment.setServiceType("foo.Interface");
        deployment.setName("The Great and wonderful Oz");
        deployment.setMultiplicity(10);
        ServiceElement serviceElement = ServiceElementFactory.create(deployment, null);
        Assert.assertEquals(10, serviceElement.getPlanned());
        Assert.assertEquals(SorcerEnv.getActualName("The Great and wonderful Oz"),
                            serviceElement.getName());
        Assert.assertEquals("foo.Impl", serviceElement.getComponentBundle().getClassName());
        Assert.assertTrue(serviceElement.getExportBundles().length==1);
        Assert.assertEquals("foo.Interface", serviceElement.getExportBundles()[0].getClassName());
    }


@Test
    public void setDeploymentWebsterUrl() throws IOException, ConfigurationException, URISyntaxException, ResolverException {
        ServiceDeployment deployment = new ServiceDeployment();
        deployment.setConfig(getConfigDir() + "/TestIP.groovy");
        deployment.setWebsterUrl("http://spongebob:8080");
        ServiceElement serviceElement = ServiceElementFactory.create(deployment, new File(getConfigDir() + "/TestIP.groovy"));
        Assert.assertTrue(serviceElement.getExportURLs().length > 1);
        Assert.assertEquals(serviceElement.getExportURLs()[0].getHost(), "spongebob");
        Assert.assertEquals(serviceElement.getExportURLs()[0].getPort(), 8080);
    }


@Test
    public void testFixedUsingConfiguration() throws URISyntaxException, ResolverException, ConfigurationException, IOException {
        ServiceDeployment deployment = new ServiceDeployment();
        deployment.setConfig(getConfigDir()+"/fixedConfig.config");
        ServiceElement service = ServiceElementFactory.create(deployment, new File(getConfigDir()+"/fixedConfig.config"));
        Assert.assertTrue(service.getPlanned()==10);
        Assert.assertTrue(service.getProvisionType() == ServiceElement.ProvisionType.FIXED);
        Assert.assertTrue(service.getMaxPerMachine()==-1);
    }


Get the DataService data directory The @link DataServiceDATADIR system property is first consulted if that property is not setValue the default is either the TMPDIR SystemgetPropertyjavaiotmpdirsorceruserdata is used and the @link DataServiceDATADIR system property is setValue @return The DataService data directory

b'/**\n     * Get the DataService data directory. The {@link DataService#DATA_DIR} system property is first\n     * consulted, if that property is not setValue, the default is either the TMPDIR\n     * System.getProperty("java.io.tmpdir")/sorcer/user/data is used and the {@link DataService#DATA_DIR}\n     * system property is setValue.\n     *\n     * @return The DataService data directory.\n     */'public static String getDataDir() {
        String dataDir = System.getProperty(DATA_DIR);
        if(dataDir==null) {
            dataDir = getDefaultDataDir();
            System.setProperty(DATA_DIR, dataDir);
        }
        return dataDir;
    }

@Test
    public void testGetDataDir() {
        String tmpDir = System.getenv("TMPDIR")==null?System.getProperty("java.io.tmpdir"):System.getenv("TMPDIR");
        String dataDirName = new File(String.format(String.format("%s%ssorcer-%s%sdata",
                                                                  tmpDir,
                                                                  File.separator,
                                                                  System.getProperty("user.name"),
                                                                  File.separator))).getAbsolutePath();
        System.err.println("===> "+dataDirName);
        assertTrue(dataDirName.equals(DataService.getDataDir()));
    }


@Test
    public void setDeploymentWebsterOperator() throws IOException, ConfigurationException, URISyntaxException, ResolverException {
        NetSignature methodEN = new NetSignature("executeFoo",
                                                 ServiceProvider.class,
                                                 "Yogi");
        methodEN.setDeployment(deploy(configuration(getConfigDir() + "/TestIP.groovy"),
                                      webster("http://spongebob:8080")));

        ServiceElement serviceElement = ServiceElementFactory.create(methodEN.getDeployment(),
                                                                     new File(getConfigDir() + "/TestIP.groovy"));
        Assert.assertTrue(serviceElement.getExportURLs().length>1);
        Assert.assertEquals(serviceElement.getExportURLs()[0].getHost(), "spongebob");
        Assert.assertEquals(serviceElement.getExportURLs()[0].getPort(), 8080);
    }


@Test
    public void setDeploymentWebsterFromConfig() throws IOException, ConfigurationException, URISyntaxException, ResolverException {
        ServiceDeployment deployment = new ServiceDeployment();
        deployment.setConfig(getConfigDir() + "/testWebster.config");
        ServiceElement serviceElement = ServiceElementFactory.create(deployment, new File(getConfigDir() + "/testWebster.config"));
        Assert.assertTrue(serviceElement.getExportURLs().length > 1);
        Assert.assertEquals(serviceElement.getExportURLs()[0].getHost(), "127.0.0.1");
        Assert.assertEquals(serviceElement.getExportURLs()[0].getPort(), 8080);
    }


@Test
    public void testIPAddresses() throws Exception {
        ServiceDeployment deployment = new ServiceDeployment();
        deployment.setIps("10.0.1.9", "canebay.local");
        deployment.setExcludeIps("10.0.1.7", "stingray.foo.local.net");
        deployment.setConfig("-");
        ServiceElement serviceElement = ServiceElementFactory.create(deployment, null);
        SystemRequirements systemRequirements = serviceElement.getServiceLevelAgreements().getSystemRequirements();
        Assert.assertEquals(4, systemRequirements.getSystemComponents().length);

        verify(get("10.0.1.9", false, systemRequirements.getSystemComponents()), false);
        verify(get("canebay.local", true, systemRequirements.getSystemComponents()), false);
        verify(get("10.0.1.7", false, systemRequirements.getSystemComponents()), true);
        verify(get("stingray.foo.local.net", true, systemRequirements.getSystemComponents()), true);
    }


@Test
    public void testIPAddressestisingConfiguration() throws IOException, ConfigurationException, URISyntaxException, ResolverException {
        ServiceDeployment deployment = new ServiceDeployment();
        deployment.setConfig(getConfigDir() + "/testIP.config");
        verifyServiceElement(ServiceElementFactory.create(deployment, new File(getConfigDir() + "/testIP.config")));
    }


@Test
    public void testIPAddressesUsingGroovyConfiguration() throws IOException, ConfigurationException, URISyntaxException, ResolverException {
        ServiceDeployment deployment = new ServiceDeployment();
        deployment.setConfig(getConfigDir()+"/TestIP.groovy");
        verifyServiceElement(ServiceElementFactory.create(deployment, new File(getConfigDir()+"/TestIP.groovy")));
    }


@Test
    public void testPlannedUsingGroovyConfiguration() throws URISyntaxException, ResolverException, ConfigurationException, IOException {
        ServiceDeployment deployment = new ServiceDeployment();
        deployment.setConfig(getConfigDir()+"/PlannedConfig.groovy");
        ServiceElement service = ServiceElementFactory.create(deployment, new File(getConfigDir()+"/PlannedConfig.groovy"));
        Assert.assertTrue(service.getPlanned()==10);
        Assert.assertTrue(service.getMaxPerMachine()==1);
        Assert.assertTrue(service.getProvisionType() == ServiceElement.ProvisionType.DYNAMIC);
    }


@Test
    public void testFixedUsingGroovyConfiguration() throws URISyntaxException, ResolverException, ConfigurationException, IOException {
        ServiceDeployment deployment = new ServiceDeployment();
        deployment.setConfig(getConfigDir()+"/FixedConfig.groovy");
        ServiceElement service = ServiceElementFactory.create(deployment, new File(getConfigDir()+"/FixedConfig.groovy"));
        Assert.assertTrue(service.getPlanned()==10);
        Assert.assertTrue(service.getProvisionType() == ServiceElement.ProvisionType.FIXED);
    }


@Test
    public void testPlannedUsingConfiguration() throws URISyntaxException, ResolverException, ConfigurationException, IOException {
        ServiceDeployment deployment = new ServiceDeployment();
        deployment.setConfig(getConfigDir()+"/plannedConfig.config");
        ServiceElement service = ServiceElementFactory.create(deployment, new File(getConfigDir()+"/plannedConfig.config"));
        Assert.assertTrue(service.getPlanned()==10);
        Assert.assertTrue(service.getMaxPerMachine()==2);
        Assert.assertTrue(service.getProvisionType() == ServiceElement.ProvisionType.DYNAMIC);
    }


('/**\\n     * Compute the set of literals common to all models of the formula.\\n     * \\n     * @param s\\n     *            a solver already feeded\\n     * @return the set of literals common to all models of the formula contained\\n     *         in the solver, in dimacs format.\\n     * @throws TimeoutException\\n     */', '')

('', '// i is in the backbone\n')

('', '// -i is in the backbone\n')

b'/**\n     * Compute the set of literals common to all models of the formula.\n     * \n     * @param s\n     *            a solver already feeded\n     * @return the set of literals common to all models of the formula contained\n     *         in the solver, in dimacs format.\n     * @throws TimeoutException\n     */'public static IVecInt backbone(ISolver s) throws TimeoutException {
        IVecInt backbone = new VecInt();
        int nvars = s.nVars();
        for (int i = 1; i <= nvars; i++) {
            backbone.push(i);
            if (s.isSatisfiable(backbone)) {
                backbone.pop().push(-i);
                if (s.isSatisfiable(backbone)) {
                    backbone.pop();
                } else {
                    // i is in the backbone
                    backbone.pop().push(i);
                }
            } else {
                // -i is in the backbone
                backbone.pop().push(-i);
            }
        }
        return backbone;
    }

@Test
    public void testBugUnitClauses() throws ContradictionException,
            TimeoutException {
        ISolver solver1 = SolverFactory.newDefault();
        ISolver solver2 = SolverFactory.newDefault();
        ISolver solver3 = SolverFactory.newDefault();

        int[][] cnf1 = new int[][] { new int[] { 1 }, new int[] { 1, -2 },
                new int[] { 1, -3 }, new int[] { -1, 2 } };
        // A & (A v -B) & (A v -C) & (-A v B)
        // (-A v B) & (A v -B) & (A v -C) & A | using a different order
        int[][] cnf2 = new int[][] { new int[] { -1, 2 }, new int[] { 1, -2 },
                new int[] { 1, -3 }, new int[] { 1 } };
        // (-A v B) & (A v -B) & (A v -C) & A
        // (-A v C) & (A v -C) & (A v -B) & A | swap B and C (2 <-> 3)
        // (A v -B) & (-A v C) & (A v -C) & A | shift the first 3 clauses to the
        // right
        int[][] cnf3 = new int[][] { new int[] { 1, -2 }, new int[] { -1, 3 },
                new int[] { 1, -3 }, new int[] { 1 } };

        for (int[] is : cnf1) {
            solver1.addClause(new VecInt(is));
        }
        for (int[] is : cnf2) {
            solver2.addClause(new VecInt(is));
        }
        for (int[] is : cnf3) {
            solver3.addClause(new VecInt(is));
        }

        IVecInt vecInt1 = RemiUtils.backbone(solver1);
        assertEquals(vecInt1.size(), 2);
        assertTrue(vecInt1.contains(1));
        assertTrue(vecInt1.contains(2));

        IVecInt vecInt2 = RemiUtils.backbone(solver2);
        assertEquals(vecInt2.size(), 2);
        assertTrue(vecInt2.contains(1));
        assertTrue(vecInt2.contains(2));

        IVecInt vecInt3 = RemiUtils.backbone(solver3);
        assertEquals(vecInt3.size(), 2);
        assertTrue(vecInt3.contains(1));
        assertTrue(vecInt3.contains(3));
    }


('/**\\n     * Translate an optimization function into constraints and provides the\\n     * binary literals in results. Works only when the value of the objective\\n     * function is positive.\\n     * \\n     * @since 2.2\\n     */', '')

('', '// filling the buckets\n')

('', '// creating the adder\n')

b'/**\n     * Translate an optimization function into constraints and provides the\n     * binary literals in results. Works only when the value of the objective\n     * function is positive.\n     * \n     * @since 2.2\n     */'public void optimisationFunction(IVecInt literals, IVec<BigInteger> coefs,
            IVecInt result) throws ContradictionException {
        IVec<IVecInt> buckets = new Vec<IVecInt>();
        IVecInt bucket;
        // filling the buckets
        for (int i = 0; i < literals.size(); i++) {
            int p = literals.get(i);
            BigInteger a = coefs.get(i);
            for (int j = 0; j < a.bitLength(); j++) {
                bucket = createIfNull(buckets, j);
                if (a.testBit(j)) {
                    bucket.push(p);
                }
            }
        }
        // creating the adder
        int x, y, z;
        int sum, carry;
        for (int i = 0; i < buckets.size(); i++) {
            bucket = buckets.get(i);
            while (bucket.size() >= 3) {
                x = bucket.get(0);
                y = bucket.get(1);
                z = bucket.get(2);
                bucket.remove(x);
                bucket.remove(y);
                bucket.remove(z);
                sum = nextFreeVarId(true);
                carry = nextFreeVarId(true);
                fullAdderSum(sum, x, y, z);
                fullAdderCarry(carry, x, y, z);
                additionalFullAdderConstraints(carry, sum, x, y, z);
                bucket.push(sum);
                createIfNull(buckets, i + 1).push(carry);
            }
            while (bucket.size() == 2) {
                x = bucket.get(0);
                y = bucket.get(1);
                bucket.remove(x);
                bucket.remove(y);
                sum = nextFreeVarId(true);
                carry = nextFreeVarId(true);
                halfAdderSum(sum, x, y);
                halfAdderCarry(carry, x, y);
                bucket.push(sum);
                createIfNull(buckets, i + 1).push(carry);
            }
            assert bucket.size() == 1;
            result.push(bucket.last());
            bucket.pop();
            assert bucket.isEmpty();
        }
    }

@Test
    public void testTwoValues() throws ContradictionException {
        IVecInt literals = new VecInt().push(1).push(2);
        IVec<BigInteger> coefs = new Vec<BigInteger>().push(
                BigInteger.valueOf(3)).push(BigInteger.valueOf(6));
        IVecInt result = new VecInt();
        this.gator.optimisationFunction(literals, coefs, result);
        System.out.println(result);
        assertEquals(4, result.size());

    }


('/**\\n     * translate y <=> (x1 => x2)\\n     * \\n     * @param y\\n     * @param x1\\n     *            the selector variable\\n     * @param x2\\n     * @return\\n     * @throws ContradictionException\\n     * @since 2.3.6\\n     */', '')

('', '// y <=> (x1 -> x2)\n')

('', '// y -> (x1 -> x2)\n')

('', '// y <- (x1 -> x2)\n')

('', '// not(x1 -> x2) or y\n')

('', '// x1 and not x2 or y\n')

('', '// (x1 or y) and (not x2 or y)\n')

b'/**\n     * translate y <=> (x1 => x2)\n     * \n     * @param y\n     * @param x1\n     *            the selector variable\n     * @param x2\n     * @return\n     * @throws ContradictionException\n     * @since 2.3.6\n     */'public IConstr[] it(int y, int x1, int x2) throws ContradictionException {
        IConstr[] constrs = new IConstr[3];
        IVecInt clause = new VecInt(5);
        // y <=> (x1 -> x2)
        // y -> (x1 -> x2)
        clause.push(-y).push(-x1).push(x2);
        constrs[0] = processClause(clause);
        clause.clear();
        // y <- (x1 -> x2)
        // not(x1 -> x2) or y
        // x1 and not x2 or y
        // (x1 or y) and (not x2 or y)
        clause.push(x1).push(y);
        constrs[1] = processClause(clause);
        clause.clear();
        clause.push(-x2).push(y);
        constrs[2] = processClause(clause);

        return constrs;
    }

@Test
    public void testSATIfThen1() throws ContradictionException,
            TimeoutException {
        gator.it(1, 2, 3);
        assertTrue(gator.isSatisfiable(new VecInt(new int[] { 1, 2, 3 })));

    }


('', '// y <=> (x1 -> x2)\n')

('', '// y -> (x1 -> x2)\n')

('', '// y <- (x1 -> x2)\n')

('', '// not(x1 -> x2) or y\n')

('', '// x1 and not x2 or y\n')

@Test
    public void testSATIfThen2() throws ContradictionException,
            TimeoutException {
        gator.it(1, 2, 3);
        assertFalse(gator.isSatisfiable(new VecInt(new int[] { 1, 2, -3 })));
    }


('', '// y <=> (x1 -> x2)\n')

('', '// y -> (x1 -> x2)\n')

('', '// y <- (x1 -> x2)\n')

('', '// not(x1 -> x2) or y\n')

('', '// x1 and not x2 or y\n')

@Test
    public void testSATIfThen3() throws ContradictionException,
            TimeoutException {
        gator.it(1, 2, 3);
        assertTrue(gator.isSatisfiable(new VecInt(new int[] { 1, -2, 3 })));
    }


('', '// y <=> (x1 -> x2)\n')

('', '// y -> (x1 -> x2)\n')

('', '// y <- (x1 -> x2)\n')

('', '// not(x1 -> x2) or y\n')

('', '// x1 and not x2 or y\n')

@Test
    public void testSATIfThen() throws ContradictionException, TimeoutException {
        gator.it(1, 2, 3);
        assertTrue(gator.isSatisfiable(new VecInt(new int[] { 1, -2, -3 })));
    }


('', '// y <=> (x1 -> x2)\n')

('', '// y -> (x1 -> x2)\n')

('', '// y <- (x1 -> x2)\n')

('', '// not(x1 -> x2) or y\n')

('', '// x1 and not x2 or y\n')

@Test
    public void testSATIfThen5() throws ContradictionException,
            TimeoutException {
        gator.it(1, 2, 3);
        assertFalse(gator.isSatisfiable(new VecInt(new int[] { -1, 2, 3 })));
    }


('', '// y <=> (x1 -> x2)\n')

('', '// y -> (x1 -> x2)\n')

('', '// y <- (x1 -> x2)\n')

('', '// not(x1 -> x2) or y\n')

('', '// x1 and not x2 or y\n')

@Test
    public void testSATIfThen6() throws ContradictionException,
            TimeoutException {
        gator.it(1, 2, 3);
        assertTrue(gator.isSatisfiable(new VecInt(new int[] { -1, 2, -3 })));
    }


('', '// y <=> (x1 -> x2)\n')

('', '// y -> (x1 -> x2)\n')

('', '// y <- (x1 -> x2)\n')

('', '// not(x1 -> x2) or y\n')

('', '// x1 and not x2 or y\n')

@Test
    public void testSATIfThen7() throws ContradictionException,
            TimeoutException {
        gator.it(1, 2, 3);
        assertFalse(gator.isSatisfiable(new VecInt(new int[] { -1, -2, 3 })));
    }


('', '// y <=> (x1 -> x2)\n')

('', '// y -> (x1 -> x2)\n')

('', '// y <- (x1 -> x2)\n')

('', '// not(x1 -> x2) or y\n')

('', '// x1 and not x2 or y\n')

@Test
    public void testSATIfThen8() throws ContradictionException,
            TimeoutException {
        gator.it(1, 2, 3);
        assertFalse(gator.isSatisfiable(new VecInt(new int[] { -1, -2, -3 })));
    }


Get the date of the first day of the current year @return date

b'/**\n   * Get the date of the first day of the current year\n   *\n   * @return date\n   */'public static Date yearStart() {
    final GregorianCalendar calendar = new GregorianCalendar(US);
    calendar.set(DAY_OF_YEAR, 1);
    return calendar.getTime();
  }

@Test
  public void yearStart() {
    Date date = DateUtils.yearStart();
    assertNotNull(date);
    GregorianCalendar calendar = new GregorianCalendar();
    calendar.setTime(date);
    assertEquals(1, calendar.get(DAY_OF_YEAR));
  }


Get the date of the last day of the current year @return date

b'/**\n   * Get the date of the last day of the current year\n   *\n   * @return date\n   */'public static Date yearEnd() {
    final GregorianCalendar calendar = new GregorianCalendar(US);
    calendar.add(YEAR, 1);
    calendar.set(DAY_OF_YEAR, 1);
    calendar.add(DAY_OF_YEAR, -1);
    return calendar.getTime();
  }

@Test
  public void yearEnd() {
    Date date = DateUtils.yearEnd();
    assertNotNull(date);
    GregorianCalendar calendar = new GregorianCalendar();
    calendar.setTime(date);
    assertEquals(11, calendar.get(MONTH));
    assertEquals(31, calendar.get(DAY_OF_MONTH));
  }


('/**\\n\\t * Returns true if the double is a denormal.\\n\\t */', '')

b'/**\n\t * Returns true if the double is a denormal.\n\t */'public static boolean isDenormal(@Unsigned long v) {
		return (v & EXPONENT_MASK) == 0L;
	}

@Test
	public void double_IsDenormal() {
		@Unsigned long min_double64 = 0x00000000_00000001L;
		CHECK(Doubles.isDenormal(min_double64));
		@Unsigned long bits = 0x000FFFFF_FFFFFFFFL;
		CHECK(Doubles.isDenormal(bits));
		bits = 0x00100000_00000000L;
		CHECK(!Doubles.isDenormal(bits));
	}


('/**\\n\\t * We consider denormals not to be special.\\n\\t * Hence only Infinity and NaN are special.\\n\\t */', '')

b'/**\n\t * We consider denormals not to be special.\n\t * Hence only Infinity and NaN are special.\n\t */'public static boolean isSpecial(@Unsigned long value) {
		return (value & EXPONENT_MASK) == EXPONENT_MASK;
	}

@Test
	public void double_IsSpecial() {
		CHECK(Doubles.isSpecial(Double.POSITIVE_INFINITY));
		CHECK(Doubles.isSpecial(-Double.POSITIVE_INFINITY));
		CHECK(Doubles.isSpecial(Double.NaN));
		@Unsigned long bits = 0xFFF12345_00000000L;
		CHECK(Doubles.isSpecial(bits));
		// Denormals are not special:
		CHECK(!Doubles.isSpecial(5e-324));
		CHECK(!Doubles.isSpecial(-5e-324));
		// And some random numbers:
		CHECK(!Doubles.isSpecial(0.0));
		CHECK(!Doubles.isSpecial(-0.0));
		CHECK(!Doubles.isSpecial(1.0));
		CHECK(!Doubles.isSpecial(-1.0));
		CHECK(!Doubles.isSpecial(1000000.0));
		CHECK(!Doubles.isSpecial(-1000000.0));
		CHECK(!Doubles.isSpecial(1e23));
		CHECK(!Doubles.isSpecial(-1e23));
		CHECK(!Doubles.isSpecial(1.7976931348623157e308));
		CHECK(!Doubles.isSpecial(-1.7976931348623157e308));
	}


t Computes a decimal representation with a fixed number of digits after thet decimal point The last emitted digit is roundedt pt bExamplesbbrt codet toFixed312 1  31brt toFixed31415 3  3142brt toFixed123456789 4  12345679brt toFixed123 5  123000brt toFixed01 4  01000brt toFixed1e30 2  100000000000000001988462483865600brt toFixed01 30  0100000000000000005551115123126brt toFixed01 17  010000000000000001brt codet pt If coderequestedDigitscode equals 0 then the tail of the result depends ont the codeEMITTRAILINGDECIMALPOINTcode and codeEMITTRAILINGZEROAFTERPOINTcodet pt Examples for requestedDigits  0t let codeEMITTRAILINGDECIMALPOINTcode and codeEMITTRAILINGZEROAFTERPOINTcode bebrt tablet trtdfalse and false thentd td 12345  123 tdtrt trtd td 0678  1 tdtrt trtdtrue and false thentd td 12345  123 tdtrt trtd td 0678  1 tdtrt trtdtrue and true thentd td 12345  1230 tdtrt trtd td 0678  10 tdtrt tablet pt t @param requestedDigits the number of digits to the right of the decimal point the last emitted digit is roundedt @param formatOptionst @throws IllegalArgumentException if coderequestedDigits  MAXFIXEDDIGITSBEFOREPOINTcode ort if codevalue  10MAXFIXEDDIGITSBEFOREPOINTcodet pt These two conditions imply that the result for nonspecial valuest never contains more thanbrt code1  MAXFIXEDDIGITSBEFOREPOINT  1 t MAXFIXEDDIGITSAFTERPOINTcodebrt characters one additional character for the sign and one for the decimal pointt     DOUBLECONVERSIONASSERTMAXFIXEDDIGITSBEFOREPOINT  60   Find a sufficiently precise decimal representation of n

b'/**\n\t * Computes a decimal representation with a fixed number of digits after the\n\t * decimal point. The last emitted digit is rounded.\n\t *
\n\t * Examples:
\n\t * \n\t * toFixed(3.12, 1) -> "3.1"
\n\t * toFixed(3.1415, 3) -> "3.142"
\n\t * toFixed(1234.56789, 4) -> "1234.5679"
\n\t * toFixed(1.23, 5) -> "1.23000"
\n\t * toFixed(0.1, 4) -> "0.1000"
\n\t * toFixed(1e30, 2) -> "1000000000000000019884624838656.00"
\n\t * toFixed(0.1, 30) -> "0.100000000000000005551115123126"
\n\t * toFixed(0.1, 17) -> "0.10000000000000001"
\n\t * \n\t *
\n\t * If requestedDigits equals 0, then the tail of the result depends on\n\t * the EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT.\n\t *
\n\t * Examples, for requestedDigits == 0,\n\t * let EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT be
\n\t *
\n\t *
false and false: then	  123.45 -> 123
\n\t *
                           0.678 -> 1
\n\t *
true and false: then	   123.45 -> 123.
\n\t *
                           0.678 -> 1.
\n\t *
true and true: then	    123.45 -> 123.0
\n\t *
                           0.678 -> 1.0
\n\t *
\n\t *
\n\t *\n\t * @param requestedDigits the number of digits to the right of the decimal point, the last emitted digit is rounded\n\t * @param formatOptions\n\t * @throws IllegalArgumentException if requestedDigits > MAX_FIXED_DIGITS_BEFORE_POINT or\n\t *                                  if value > 10^MAX_FIXED_DIGITS_BEFORE_POINT\n\t *
\n\t *                                  These two conditions imply that the result for non-special values\n\t *                                  never contains more than
\n\t *                                  1 + MAX_FIXED_DIGITS_BEFORE_POINT + 1 +\n\t *                                  MAX_FIXED_DIGITS_AFTER_POINT
\n\t *                                  characters (one additional character for the sign, and one for the decimal point).\n\t */'public static void toFixed(double value, int requestedDigits, FormatOptions formatOptions, CharBuffer resultBuilder) {
		// DOUBLE_CONVERSION_ASSERT(MAX_FIXED_DIGITS_BEFORE_POINT == 60);

		if (Doubles.isSpecial(value)) {
			handleSpecialValues(value, formatOptions, resultBuilder);
			return;
		}

		if (requestedDigits > MAX_FIXED_DIGITS_AFTER_POINT) {
			throw new IllegalArgumentException("requestedDigits too large. max: " + MAX_FIXED_DIGITS_BEFORE_POINT +
				"(MAX_FIXED_DIGITS_BEFORE_POINT) got: " + requestedDigits);
		}
		if (value > FIRST_NON_FIXED || value < -FIRST_NON_FIXED) {
			throw new IllegalArgumentException("value >= 10^" + MAX_FIXED_DIGITS_BEFORE_POINT +
				"(10^MAX_FIXED_DIGITS_BEFORE_POINT) got: " + value);
		}

		// Find a sufficiently precise decimal representation of n.
		DecimalRepBuf decimalRep = new DecimalRepBuf(FIXED_REP_CAPACITY);
		doubleToAscii(value, DtoaMode.FIXED, requestedDigits, decimalRep);

		createDecimalRepresentation(decimalRep, value, requestedDigits, formatOptions, resultBuilder);
	}

@Test
	void toFixed() {
		// TODO: conv = DoubleToStringConverter.ecmaScriptConverter();

		testFixed("3.1", 3.12, 1);
		testFixed("3.142", 3.1415, 3);
		testFixed("1234.5679", 1234.56789, 4);
		testFixed("1.23000", 1.23, 5);
		testFixed("0.1000", 0.1, 4);
		testFixed("1000000000000000019884624838656.00", 1e30, 2);
		testFixed("0.100000000000000005551115123126", 0.1, 30);
		testFixed("0.10000000000000001", 0.1, 17);

		// TODO: conv = newConv(Flags.NO_FLAGS);
		testFixed("123", 123.45, 0);
		testFixed("1", 0.678, 0);

		testFixed("123.", 123.45, 0, WITH_TRAILING);
		testFixed("1.", 0.678, 0, WITH_TRAILING);

		// from string-issues.lua:3
		testFixed("20.00", 20.0, 2, padding(5, false, false)); // %5.2f
		testFixed(" 0.05", 5.2e-2, 2, padding(5, false, false)); // %5.2f
		testFixed("52.30", 52.3, 2, padding(5, false, false)); // %5.2f

		// padding
		testFixed("      1.0", 1.0, 1, padding(9, false, false));
		testFixed("1.0      ", 1.0, 1, padding(9, false, true));
		testFixed("0000001.0", 1.0, 1, padding(9, true, false));

		boolean zeroPad = true;
		testFixed("1", 1.0, 0, padding(1, zeroPad, false));
		testFixed("0", 0.1, 0, padding(1, zeroPad, false));
		testFixed("01", 1.0, 0, padding(2, zeroPad, false));
		testFixed("-1", -1.0, 0, padding(2, zeroPad, false));
		testFixed("001", 1.0, 0, padding(3, zeroPad, false));
		testFixed("-01", -1.0, 0, padding(3, zeroPad, false));

		testFixed("123", 123.456, 0, padding(1, zeroPad, false));
		testFixed("0", 1.23456e-05, 0, padding(1, zeroPad, false));

		testFixed("100", 100.0, 0, padding(2, zeroPad, false));
		testFixed("1000", 1000.0, 0, padding(2, zeroPad, false));

		testFixed("000100", 100.0, 0, padding(6, zeroPad, false));
		testFixed("001000", 1000.0, 0, padding(6, zeroPad, false));
		testFixed("010000", 10000.0, 0, padding(6, zeroPad, false));
		testFixed("100000", 100000.0, 0, padding(6, zeroPad, false));
		testFixed("1000000", 1000000.0, 0, padding(6, zeroPad, false));

		testFixed("00", 0.01, 0, padding(2, zeroPad, false));

		testFixed("0.0", 0.01, 1, padding(2, false, false));

		testFixed("            0.010000", 0.01, 6, padding(20, false, false));

	}


t Computes a representation in exponential format with coderequestedDigitscodet after the decimal point The last emitted digit is roundedt pt Examples with bEMITPOSITIVEEXPONENTSIGNb deactivated andt exponentcharacter set to codeecodet pt codet toExponential312 1  31e0brt toExponential50 3  5000e0brt toExponential0001 2  100e3brt toExponential31415 4  31415e0brt toExponential31415 3  3142e0brt toExponential123456789000000 3  1235e14brt toExponential10000000000000000198846248386560 32 t 100000000000000001988462483865600e30brt toExponential1234 0  1e3brt codet t @param requestedDigits number of digits after the decimal pointlast digit roundedt @param formatOptionst @throws IllegalArgumentException if coderequestedDigits  MAXEXPONENTIALDIGITScodet     DOUBLECONVERSIONASSERTEXPONENTIALREPCAPACITY  BASE10MAXIMALLENGTH

b'/**\n\t * Computes a representation in exponential format with requestedDigits\n\t * after the decimal point. The last emitted digit is rounded.\n\t *
\n\t * Examples with EMIT_POSITIVE_EXPONENT_SIGN deactivated, and\n\t * exponent_character set to \'e\'.\n\t *
\n\t * \n\t * toExponential(3.12, 1) -> "3.1e0"
\n\t * toExponential(5.0, 3) -> "5.000e0"
\n\t * toExponential(0.001, 2) -> "1.00e-3"
\n\t * toExponential(3.1415, 4) -> "3.1415e0"
\n\t * toExponential(3.1415, 3) -> "3.142e0"
\n\t * toExponential(123456789000000, 3) -> "1.235e14"
\n\t * toExponential(1000000000000000019884624838656.0, 32) ->\n\t * "1.00000000000000001988462483865600e30"
\n\t * toExponential(1234, 0) -> "1e3"
\n\t * \n\t *\n\t * @param requestedDigits number of digits after the decimal point(last digit rounded)\n\t * @param formatOptions\n\t * @throws IllegalArgumentException if requestedDigits > MAX_EXPONENTIAL_DIGITS\n\t */'public static void toExponential(double value, int requestedDigits, FormatOptions formatOptions, CharBuffer resultBuilder) {
		if (Doubles.isSpecial(value)) {
			handleSpecialValues(value, formatOptions, resultBuilder);
			return;
		}

		if (requestedDigits < 0) {
			throw new IllegalArgumentException(String.format("requestedDigits must be >= 0. got: %d", requestedDigits));
		}

		if (requestedDigits > MAX_EXPONENTIAL_DIGITS) {
			throw new IllegalArgumentException(String.format("requestedDigits must be less than %d. got: %d", MAX_EXPONENTIAL_DIGITS, requestedDigits));
		}

		// DOUBLE_CONVERSION_ASSERT(EXPONENTIAL_REP_CAPACITY > BASE_10_MAXIMAL_LENGTH);
		DecimalRepBuf decimalRep = new DecimalRepBuf(EXPONENTIAL_REP_CAPACITY);

		doubleToAscii(value, DtoaMode.PRECISION, requestedDigits + 1, decimalRep);
		assert decimalRep.length() <= requestedDigits + 1;

		decimalRep.zeroExtend(requestedDigits + 1);

		int exponent = decimalRep.getPointPosition() - 1;
		createExponentialRepresentation(decimalRep, value, decimalRep.length(), exponent, formatOptions, resultBuilder);
	}


t Computes precision leading digits of the given value and returns themt either in exponential or decimal format depending ont PrecisionPolicymaxLeadingTrailingZeros given to thet constructort pt The last computed digit is roundedt pt Example with PrecisionPolicymaxLeadingZeros  6t pt codet toPrecision00000012345 2  00000012brt toPrecision000000012345 2  12e7brt codet pt Similarily the converter may add up tot PrecisionPolicymaxTrailingZeros in precision mode to avoidt returning an exponential representation A zero added by thet bEMITTRAILINGZEROAFTERPOINTb flag is counted for this limitt pt Examples for PrecisionPolicymaxTrailingZeros  1t pt codet toPrecision2300 2  230brt toPrecision2300 2  230 with EMITTRAILINGDECIMALPOINTbrt toPrecision2300 2  23e2 with EMITTRAILINGZEROAFTERPOINTbrt codet pt Examples for PrecisionPolicymaxTrailingZeros  3 and not EMITTRAILINGZEROAFTERPOINTt pt codet toPrecision1234500 6  123450brt toPrecision1234500 5  123450brt toPrecision1234500 4  123500brt toPrecision1234500 3  123000brt toPrecision1234500 2  12e5brt codet pt t @throws IllegalArgumentException when codeprecision  MINPRECISIONDIGITScode ort codeprecision  MAXPRECISIONDIGITScodet     Find a sufficiently precise decimal representation of n   Add one for the terminating null character   The exponent if we print the number as xxxeyyy That is with the   decimal point after the first digit   Truncate trailing zeros that occur after the decimal point if exponential   that is everything after the first digit   Clamp precision to avoid the code below readding the zeros   Fill buffer to contain precision digits   Usually the buffer is already at the correct length but doubleToAscii   is allowed to return less characters

b'/**\n\t * Computes \'precision\' leading digits of the given \'value\' and returns them\n\t * either in exponential or decimal format, depending on\n\t * PrecisionPolicy.max{Leading|Trailing}Zeros (given to the\n\t * constructor).\n\t *
\n\t * The last computed digit is rounded.\n\t *
\n\t * Example with PrecisionPolicy.maxLeadingZeros = 6.\n\t *
\n\t * \n\t * toPrecision(0.0000012345, 2) -> "0.0000012"
\n\t * toPrecision(0.00000012345, 2) -> "1.2e-7"
\n\t * \n\t *
\n\t * Similarily the converter may add up to\n\t * PrecisionPolicy.maxTrailingZeros in precision mode to avoid\n\t * returning an exponential representation. A zero added by the\n\t * EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.\n\t *
\n\t * Examples for PrecisionPolicy.maxTrailingZeros = 1:\n\t *
\n\t * \n\t * toPrecision(230.0, 2) -> "230"
\n\t * toPrecision(230.0, 2) -> "230."  with EMIT_TRAILING_DECIMAL_POINT.
\n\t * toPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT.
\n\t * \n\t *
\n\t * Examples for PrecisionPolicy.maxTrailingZeros = 3, and no\n\t * EMIT_TRAILING_ZERO_AFTER_POINT:\n\t *
\n\t * \n\t * toPrecision(123450.0, 6) -> "123450"
\n\t * toPrecision(123450.0, 5) -> "123450"
\n\t * toPrecision(123450.0, 4) -> "123500"
\n\t * toPrecision(123450.0, 3) -> "123000"
\n\t * toPrecision(123450.0, 2) -> "1.2e5"
\n\t * \n\t *
\n\t *\n\t * @throws IllegalArgumentException when precision < MIN_PRECISION_DIGITS or\n\t *                                  precision > MAX_PRECISION_DIGITS\n\t */'public static void toPrecision(double value, int precision, FormatOptions formatOptions, CharBuffer resultBuilder) {
		if (Doubles.isSpecial(value)) {
			handleSpecialValues(value, formatOptions, resultBuilder);
			return;
		}

		if (precision < MIN_PRECISION_DIGITS || precision > MAX_PRECISION_DIGITS) {
			throw new IllegalArgumentException(String.format("argument precision must be in range (%d,%d)", MIN_PRECISION_DIGITS, MAX_PRECISION_DIGITS));
		}

		// Find a sufficiently precise decimal representation of n.
		// Add one for the terminating null character.
		DecimalRepBuf decimalRep = new DecimalRepBuf(PRECISION_REP_CAPACITY);
		doubleToAscii(value, DtoaMode.PRECISION, precision, decimalRep);
		assert decimalRep.length() <= precision;

		// The exponent if we print the number as x.xxeyyy. That is with the
		// decimal point after the first digit.
		int decimalPoint = decimalRep.getPointPosition();
		int exponent = decimalPoint - 1;

		boolean asExponential = (-decimalPoint + 1 > MAX_LEADING_ZEROS) || (decimalPoint - precision > MAX_TRAILING_ZEROS);
		if (!formatOptions.alternateForm()) {
			// Truncate trailing zeros that occur after the decimal point (if exponential,
			// that is everything after the first digit).
			decimalRep.truncateZeros(asExponential);
			// Clamp precision to avoid the code below re-adding the zeros.
			precision = Math.min(precision, decimalRep.length());
		}
		if (asExponential) {
			// Fill buffer to contain 'precision' digits.
			// Usually the buffer is already at the correct length, but 'doubleToAscii'
			// is allowed to return less characters.
			decimalRep.zeroExtend(precision);

			createExponentialRepresentation(decimalRep, value, precision, exponent, formatOptions, resultBuilder);
		} else {
			createDecimalRepresentation(decimalRep, value, Math.max(0, precision - decimalRep.getPointPosition()), formatOptions, resultBuilder);
		}
	}


t Computes a representation in hexadecimal exponential format with coderequestedDigitscode after the decimalt point The last emitted digit is roundedt t @param value The value to formatt @param requestedDigits The number of digits after the decimal place or @code 1t @param formatOptions Additional options for this numbers formattingt @param resultBuilder The buffer to output tot

b"/**\n\t * Computes a representation in hexadecimal exponential format with requestedDigits after the decimal\n\t * point. The last emitted digit is rounded.\n\t *\n\t * @param value           The value to format.\n\t * @param requestedDigits The number of digits after the decimal place, or {@code -1}.\n\t * @param formatOptions   Additional options for this number's formatting.\n\t * @param resultBuilder   The buffer to output to.\n\t */"public static void toHex(double value, int requestedDigits, FormatOptions formatOptions, CharBuffer resultBuilder) {
		if (Doubles.isSpecial(value)) {
			handleSpecialValues(value, formatOptions, resultBuilder);
			return;
		}

		boolean negative = shouldEmitMinus(value);

		double absValue = Math.abs(value);
		ExponentPart significand = createHexSignificand(absValue, requestedDigits, formatOptions);

		int exponentValue = absValue == 0 ? 0 : Doubles.exponent(absValue) + Doubles.PHYSICAL_SIGNIFICAND_SIZE;
		ExponentPart exponent = createExponentPart(exponentValue, 1);

		int valueWidth = significand.length() + exponent.length() + 3;
		if (negative || formatOptions.explicitPlus() || formatOptions.spaceWhenPositive()) valueWidth++;
		int padWidth = formatOptions.width() <= 0 ? 0 : formatOptions.width() - valueWidth;

		if (padWidth > 0 && !formatOptions.leftAdjust() && !formatOptions.zeroPad()) {
			addPadding(resultBuilder, ' ', padWidth);
		}

		appendSign(value, formatOptions, resultBuilder);
		resultBuilder.append('0');
		resultBuilder.append(formatOptions.symbols().hexSeparator());

		if (padWidth > 0 && !formatOptions.leftAdjust() && formatOptions.zeroPad()) {
			addPadding(resultBuilder, '0', padWidth);
		}

		resultBuilder.append(significand.buffer(), significand.start(), significand.length());
		resultBuilder.append(formatOptions.symbols().hexExponent());
		resultBuilder.append(exponent.buffer(), exponent.start(), exponent.length());

		if (padWidth > 0 && formatOptions.leftAdjust()) addPadding(resultBuilder, ' ', padWidth);
	}


('/**\\n\\t * Provides a decimal representation of v.\\n\\t * The result should be interpreted as buffer * 10^(point - outLength).\\n\\t * <p>\\n\\t * Precondition:\\n\\t * * v must be a strictly positive finite double.\\n\\t * <p>\\n\\t * Returns true if it succeeds, otherwise the result can not be trusted.\\n\\t * If the function returns true and mode equals\\n\\t * - FAST_DTOA_PRECISION, then\\n\\t * the buffer contains requestedDigits digits.\\n\\t * the difference v - (buffer * 10^(point-outLength)) is closest to zero for\\n\\t * all possible representations of requestedDigits digits.\\n\\t * If there are two values that are equally close, then fastDtoa returns\\n\\t * false.\\n\\t * For both modes the buffer must be large enough to hold the result.\\n\\t */', '')

('', '// initialized to 0\n')

b'/**\n\t * Provides a decimal representation of v.\n\t * The result should be interpreted as buffer * 10^(point - outLength).\n\t * <p>\n\t * Precondition:\n\t * * v must be a strictly positive finite double.\n\t * <p>\n\t * Returns true if it succeeds, otherwise the result can not be trusted.\n\t * If the function returns true and mode equals\n\t * - FAST_DTOA_PRECISION, then\n\t * the buffer contains requestedDigits digits.\n\t * the difference v - (buffer * 10^(point-outLength)) is closest to zero for\n\t * all possible representations of requestedDigits digits.\n\t * If there are two values that are equally close, then fastDtoa returns\n\t * false.\n\t * For both modes the buffer must be large enough to hold the result.\n\t */'public static boolean fastDtoa(double v, int requestedDigits, DecimalRepBuf buf) {
		assert v > 0.0;
		assert !Doubles.isSpecial(v);

		boolean result;
		int[] decimalExponent = new int[1]; // initialized to 0
		result = grisu3Counted(v, requestedDigits, buf, decimalExponent);
		if (result) {
			buf.setPointPosition(buf.length() + decimalExponent[0]);
		} else {
			buf.reset();
		}
		return result;
	}

@Test
	public void precisionVariousDoubles() {
		DecimalRepBuf buffer = new DecimalRepBuf(BUFFER_SIZE);
		boolean status;

		status = FastDtoa.fastDtoa(1.0, 3, buffer);
		CHECK(status);
		CHECK_GE(3, buffer.length());
		buffer.truncateAllZeros();
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		status = FastDtoa.fastDtoa(1.5, 10, buffer);
		if (status) {
			CHECK_GE(10, buffer.length());
			buffer.truncateAllZeros();
			CHECK_EQ("15", buffer);
			CHECK_EQ(1, buffer.getPointPosition());
		}

		double min_double = 5e-324;
		status = FastDtoa.fastDtoa(min_double, 5,
			buffer);
		CHECK(status);
		CHECK_EQ("49407", buffer);
		CHECK_EQ(-323, buffer.getPointPosition());

		double max_double = 1.7976931348623157e308;
		status = FastDtoa.fastDtoa(max_double, 7,
			buffer);
		CHECK(status);
		CHECK_EQ("1797693", buffer);
		CHECK_EQ(309, buffer.getPointPosition());

		status = FastDtoa.fastDtoa(4294967272.0, 14,
			buffer);
		if (status) {
			CHECK_GE(14, buffer.length());
			buffer.truncateAllZeros();
			CHECK_EQ("4294967272", buffer);
			CHECK_EQ(10, buffer.getPointPosition());
		}

		status = FastDtoa.fastDtoa(4.1855804968213567e298, 17,
			buffer);
		CHECK(status);
		CHECK_EQ("41855804968213567", buffer);
		CHECK_EQ(299, buffer.getPointPosition());

		status = FastDtoa.fastDtoa(5.5626846462680035e-309, 1,
			buffer);
		CHECK(status);
		CHECK_EQ("6", buffer);
		CHECK_EQ(-308, buffer.getPointPosition());

		status = FastDtoa.fastDtoa(2147483648.0, 5,
			buffer);
		CHECK(status);
		CHECK_EQ("21475", buffer);
		CHECK_EQ(10, buffer.getPointPosition());

		status = FastDtoa.fastDtoa(3.5844466002796428e+298, 10,
			buffer);
		CHECK(status);
		CHECK_GE(10, buffer.length());
		buffer.truncateAllZeros();
		CHECK_EQ("35844466", buffer);
		CHECK_EQ(299, buffer.getPointPosition());

		long smallest_normal64 = 0x00100000_00000000L;
		double v = Double.longBitsToDouble(smallest_normal64);
		status = FastDtoa.fastDtoa(v, 17, buffer);
		CHECK(status);
		CHECK_EQ("22250738585072014", buffer);
		CHECK_EQ(-307, buffer.getPointPosition());

		long largest_denormal64 = 0x000FFFFF_FFFFFFFFL;
		v = Double.longBitsToDouble(largest_denormal64);
		status = FastDtoa.fastDtoa(v, 17, buffer);
		CHECK(status);
		CHECK_GE(20, buffer.length());
		buffer.truncateAllZeros();
		CHECK_EQ("22250738585072009", buffer);
		CHECK_EQ(-307, buffer.getPointPosition());

		v = 3.3161339052167390562200598e-237;
		status = FastDtoa.fastDtoa(v, 18, buffer);
		CHECK(status);
		CHECK_EQ("331613390521673906", buffer);
		CHECK_EQ(-236, buffer.getPointPosition());

		v = 7.9885183916008099497815232e+191;
		status = FastDtoa.fastDtoa(v, 4, buffer);
		CHECK(status);
		CHECK_EQ("7989", buffer);
		CHECK_EQ(192, buffer.getPointPosition());
	}


('', '// initialized to 0\n')

@Test
	public void gayPrecision() throws Exception {
		PrecisionState state = new PrecisionState();

		DoubleTestHelper.eachPrecision(state, (st, v, numberDigits, representation, decimalPoint) -> {
			boolean status;

			st.total++;
			st.underTest = String.format("Using {%g, %d, \"%s\", %d}", v, numberDigits, representation, decimalPoint);
			if (numberDigits <= 15) st.total15++;

			status = FastDtoa.fastDtoa(v, numberDigits, st.buffer);
			CHECK_GE(numberDigits, st.buffer.length());
			if (status) {
				st.succeeded++;
				if (numberDigits <= 15) st.succeeded15++;
				st.buffer.truncateAllZeros();
				assertThat(st.underTest, st.buffer.getPointPosition(), is(equalTo(decimalPoint)));
				assertThat(st.underTest, stringOf(st.buffer), is(equalTo(representation)));
			}
		});

		// The precomputed numbers contain many entries with many requested
		// digits. These have a high failure rate and we therefore expect a lower
		// success rate than for the shortest representation.
		assertThat("85% should succeed", state.succeeded * 1.0 / state.total, is(greaterThan(0.85)));
		// However with less than 15 digits almost the algorithm should almost always
		// succeed.
		assertThat(state.succeeded15 * 1.0 / state.total15, is(greaterThan(0.9999)));

		System.out.println("gay-precision tests run :" + Integer.toString(state.total));
	}


["('', '// v = significand * 2^exponent (with significand a 53bit integer).\\n')", "('', '// If the exponent is larger than 20 (i.e. we may have a 73bit number) then we\\n')", '(\'\', "// don\'t know how to compute the representation. 2^73 ~= 9.5*10^21.\\n")', '(\'\', "// If necessary this limit could probably be increased, but we don\'t need\\n")', "('', '// more.\\n')", "('', '// At most DOUBLE_SIGNIFICAND_SIZE bits of the significand are non-zero.\\n')", "('', '// Given a 64 bit integer we have 11 0s followed by 53 potentially non-zero\\n')", "('', '// bits:  0..11*..0xxx..53*..xx\\n')", "('', '// compile-time promise that exponent is positive\\n')", "('', '// The exponent must be > 11.\\n')", "('', '//\\n')", "('', '// We know that v = significand * 2^exponent.\\n')", "('', '// And the exponent > 11.\\n')", "('', '// We simplify the task by dividing v by 10^17.\\n')", "('', '// The quotient delivers the first digits, and the remainder fits into a 64\\n')", "('', '// bit number.\\n')", "('', '// Dividing by 10^17 is equivalent to dividing by 5^17*2^17.\\n')", "('', '// 5^17\\n')", "('', '// Let v = f * 2^e with f == significand and e == exponent.\\n')", "('', '// Then need q (quotient) and r (remainder) as follows:\\n')", "('', '//   v            = q * 10^17       + r\\n')", "('', '//   f * 2^e      = q * 10^17       + r\\n')", "('', '//   f * 2^e      = q * 5^17 * 2^17 + r\\n')", "('', '// If e > 17 then\\n')", "('', '//   f * 2^(e-17) = q * 5^17        + r/2^17\\n')", "('', '// else\\n')", "('', '//   f  = q * 5^17 * 2^(17-e) + r/2^e\\n')", "('', '// We only allow exponents of up to 20 and therefore (17 - e) <= 3\\n')", "('', '// 0 <= exponent <= 11\\n')", "('', '// We have to cut the number.\\n')", "('', '// This configuration (with at most 20 digits) means that all digits must be\\n')", "('', '// 0.\\n')", "('', '// The string is empty and the decimalPoint thus has no importance. Mimick\\n')", '(\'\', "// Gay\'s dtoa and and set it to -fractionalCount.\\n")']

public static boolean fastFixedDtoa(double v, int fractionalCount, DecimalRepBuf buf) {
		final @Unsigned long kMaxUInt32 = 0xFFFF_FFFFL;
		@Unsigned long significand = Doubles.significand(v);
		int exponent = Doubles.exponent(v);
		// v = significand * 2^exponent (with significand a 53bit integer).
		// If the exponent is larger than 20 (i.e. we may have a 73bit number) then we
		// don't know how to compute the representation. 2^73 ~= 9.5*10^21.
		// If necessary this limit could probably be increased, but we don't need
		// more.
		if (exponent > 20) return false;
		if (fractionalCount > 20) return false;

		buf.clearBuf();
		// At most DOUBLE_SIGNIFICAND_SIZE bits of the significand are non-zero.
		// Given a 64 bit integer we have 11 0s followed by 53 potentially non-zero
		// bits:  0..11*..0xxx..53*..xx
		if (exponent + DOUBLE_SIGNIFICAND_SIZE > 64) {
			// compile-time promise that exponent is positive
			@SuppressWarnings("cast.unsafe")
			@SignedPositive int positiveExponent = (@SignedPositive int) exponent;
			// The exponent must be > 11.
			//
			// We know that v = significand * 2^exponent.
			// And the exponent > 11.
			// We simplify the task by dividing v by 10^17.
			// The quotient delivers the first digits, and the remainder fits into a 64
			// bit number.
			// Dividing by 10^17 is equivalent to dividing by 5^17*2^17.
			final @Unsigned long kFive17 = 0xB1_A2BC2EC5L;  // 5^17
			@Unsigned long divisor = kFive17;
			@SignedPositive int divisorPower = 17;
			@Unsigned long dividend = significand;
			@Unsigned int quotient;
			@Unsigned long remainder;
			// Let v = f * 2^e with f == significand and e == exponent.
			// Then need q (quotient) and r (remainder) as follows:
			//   v            = q * 10^17       + r
			//   f * 2^e      = q * 10^17       + r
			//   f * 2^e      = q * 5^17 * 2^17 + r
			// If e > 17 then
			//   f * 2^(e-17) = q * 5^17        + r/2^17
			// else
			//   f  = q * 5^17 * 2^(17-e) + r/2^e
			if (exponent > divisorPower) {
				// We only allow exponents of up to 20 and therefore (17 - e) <= 3
				dividend <<= toUlongFromSigned(positiveExponent - divisorPower);
				quotient = toUint(uDivide(dividend, divisor));
				remainder = uRemainder(dividend, divisor) << divisorPower;
			} else {
				divisor <<= toUlongFromSigned(divisorPower - positiveExponent);
				quotient = toUint(uDivide(dividend, divisor));
				remainder = uRemainder(dividend, divisor) << exponent;
			}
			fillDigits32(quotient, buf);
			fillDigits64FixedLength(remainder, buf);
			buf.setPointPosition(buf.length());
		} else if (exponent >= 0) {
			// 0 <= exponent <= 11
			significand = significand << exponent;
			fillDigits64(significand, buf);
			buf.setPointPosition(buf.length());
		} else if (exponent > -DOUBLE_SIGNIFICAND_SIZE) {
			// We have to cut the number.
			@Unsigned long integrals = significand >>> -exponent;
			@Unsigned long fractionals = significand - (integrals << -exponent);
			if (!isAssignableToUint(integrals)) {
				fillDigits64(integrals, buf);
			} else {
				fillDigits32(toUint(integrals), buf);
			}
			buf.setPointPosition(buf.length());
			fillFractionals(fractionals, exponent, fractionalCount, buf);
		} else if (exponent < -128) {
			// This configuration (with at most 20 digits) means that all digits must be
			// 0.
			assert fractionalCount <= 20;
			buf.clearBuf();
			buf.setPointPosition(-fractionalCount);
		} else {
			buf.setPointPosition(0);
			fillFractionals(significand, exponent, fractionalCount, buf);
		}
		buf.trimZeros();
		if (buf.length() == 0) {
			// The string is empty and the decimalPoint thus has no importance. Mimick
			// Gay's dtoa and and set it to -fractionalCount.
			buf.setPointPosition(-fractionalCount);
		}
		return true;
	}

@Test
	public void variousDoubles() {
		DecimalRepBuf buffer = new DecimalRepBuf(kBufferSize);

		CHECK(FixedDtoa.fastFixedDtoa(1.0, 1, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(1.0, 15, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(1.0, 0, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		// FIXME  Doesn't seem to convert in java
//		CHECK(FixedDtoa.fastFixedDtoa(0xFFFFFFFF, 5, buffer));
//		CHECK_EQ("4294967295", buffer);
//		CHECK_EQ(10, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(4294967296.0, 5, buffer));
		CHECK_EQ("4294967296", buffer);
		CHECK_EQ(10, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(1e21, 5, buffer));
		CHECK_EQ("1", buffer);
		// CHECK_EQ(22, buffer.getPointPosition());
		CHECK_EQ(22, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(999999999999999868928.00, 2, buffer));
		CHECK_EQ("999999999999999868928", buffer);
		CHECK_EQ(21, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(6.9999999999999989514240000e+21, 5, buffer));
		CHECK_EQ("6999999999999998951424", buffer);
		CHECK_EQ(22, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(1.5, 5, buffer));
		CHECK_EQ("15", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(1.55, 5, buffer));
		CHECK_EQ("155", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(1.55, 1, buffer));
		CHECK_EQ("16", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(1.00000001, 15, buffer));
		CHECK_EQ("100000001", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.1, 10, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(0, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.01, 10, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.001, 10, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-2, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.0001, 10, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-3, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00001, 10, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-4, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.000001, 10, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-5, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.0000001, 10, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-6, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00000001, 10, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-7, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.000000001, 10, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-8, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.0000000001, 15, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-9, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00000000001, 15, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-10, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.000000000001, 15, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-11, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.0000000000001, 15, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-12, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00000000000001, 15, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-13, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.000000000000001, 20, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-14, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.0000000000000001, 20, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-15, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00000000000000001, 20, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-16, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.000000000000000001, 20, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-17, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.0000000000000000001, 20, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-18, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00000000000000000001, 20, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-19, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.10000000004, 10, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(0, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.01000000004, 10, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00100000004, 10, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-2, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00010000004, 10, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-3, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00001000004, 10, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-4, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00000100004, 10, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-5, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00000010004, 10, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-6, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00000001004, 10, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-7, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00000000104, 10, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-8, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.0000000001000004, 15, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-9, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.0000000000100004, 15, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-10, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.0000000000010004, 15, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-11, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.0000000000001004, 15, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-12, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.0000000000000104, 15, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-13, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.000000000000001000004, 20, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-14, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.000000000000000100004, 20, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-15, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.000000000000000010004, 20, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-16, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.000000000000000001004, 20, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-17, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.000000000000000000104, 20, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-18, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.000000000000000000014, 20, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-19, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.10000000006, 10, buffer));
		CHECK_EQ("1000000001", buffer);
		CHECK_EQ(0, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.01000000006, 10, buffer));
		CHECK_EQ("100000001", buffer);
		CHECK_EQ(-1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00100000006, 10, buffer));
		CHECK_EQ("10000001", buffer);
		CHECK_EQ(-2, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00010000006, 10, buffer));
		CHECK_EQ("1000001", buffer);
		CHECK_EQ(-3, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00001000006, 10, buffer));
		CHECK_EQ("100001", buffer);
		CHECK_EQ(-4, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00000100006, 10, buffer));
		CHECK_EQ("10001", buffer);
		CHECK_EQ(-5, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00000010006, 10, buffer));
		CHECK_EQ("1001", buffer);
		CHECK_EQ(-6, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00000001006, 10, buffer));
		CHECK_EQ("101", buffer);
		CHECK_EQ(-7, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00000000106, 10, buffer));
		CHECK_EQ("11", buffer);
		CHECK_EQ(-8, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.0000000001000006, 15, buffer));
		CHECK_EQ("100001", buffer);
		CHECK_EQ(-9, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.0000000000100006, 15, buffer));
		CHECK_EQ("10001", buffer);
		CHECK_EQ(-10, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.0000000000010006, 15, buffer));
		CHECK_EQ("1001", buffer);
		CHECK_EQ(-11, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.0000000000001006, 15, buffer));
		CHECK_EQ("101", buffer);
		CHECK_EQ(-12, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.0000000000000106, 15, buffer));
		CHECK_EQ("11", buffer);
		CHECK_EQ(-13, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.000000000000001000006, 20, buffer));
		CHECK_EQ("100001", buffer);
		CHECK_EQ(-14, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.000000000000000100006, 20, buffer));
		CHECK_EQ("10001", buffer);
		CHECK_EQ(-15, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.000000000000000010006, 20, buffer));
		CHECK_EQ("1001", buffer);
		CHECK_EQ(-16, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.000000000000000001006, 20, buffer));
		CHECK_EQ("101", buffer);
		CHECK_EQ(-17, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.000000000000000000106, 20, buffer));
		CHECK_EQ("11", buffer);
		CHECK_EQ(-18, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.000000000000000000016, 20, buffer));
		CHECK_EQ("2", buffer);
		CHECK_EQ(-19, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.6, 0, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.96, 1, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.996, 2, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.9996, 3, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.99996, 4, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.999996, 5, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.9999996, 6, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.99999996, 7, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.999999996, 8, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.9999999996, 9, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.99999999996, 10, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.999999999996, 11, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.9999999999996, 12, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.99999999999996, 13, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.999999999999996, 14, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.9999999999999996, 15, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00999999999999996, 16, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.000999999999999996, 17, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-2, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.0000999999999999996, 18, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-3, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.00000999999999999996, 19, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-4, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.000000999999999999996, 20, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-5, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(323423.234234, 10, buffer));
		CHECK_EQ("323423234234", buffer);
		CHECK_EQ(6, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(12345678.901234, 4, buffer));
		CHECK_EQ("123456789012", buffer);
		CHECK_EQ(8, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(98765.432109, 5, buffer));
		CHECK_EQ("9876543211", buffer);
		CHECK_EQ(5, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(42, 20, buffer));
		CHECK_EQ("42", buffer);
		CHECK_EQ(2, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(0.5, 0, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(1, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(1e-23, 10, buffer));
		CHECK_EQ("", buffer);
		CHECK_EQ(-10, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(1e-123, 2, buffer));
		CHECK_EQ("", buffer);
		CHECK_EQ(-2, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(1e-123, 0, buffer));
		CHECK_EQ("", buffer);
		CHECK_EQ(0, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(1e-23, 20, buffer));
		CHECK_EQ("", buffer);
		CHECK_EQ(-20, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(1e-21, 20, buffer));
		CHECK_EQ("", buffer);
		CHECK_EQ(-20, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(1e-22, 20, buffer));
		CHECK_EQ("", buffer);
		CHECK_EQ(-20, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(6e-21, 20, buffer));
		CHECK_EQ("1", buffer);
		CHECK_EQ(-19, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(9.1193616301674545152000000e+19, 0,
			buffer));
		CHECK_EQ("91193616301674545152", buffer);
		CHECK_EQ(20, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(4.8184662102767651659096515e-04, 19,
			buffer));
		CHECK_EQ("4818466210276765", buffer);
		CHECK_EQ(-3, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(1.9023164229540652612705182e-23, 8,
			buffer));
		CHECK_EQ("", buffer);
		CHECK_EQ(-8, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(1000000000000000128.0, 0,
			buffer));
		CHECK_EQ("1000000000000000128", buffer);
		CHECK_EQ(19, buffer.getPointPosition());

		CHECK(FixedDtoa.fastFixedDtoa(2.10861548515811875e+15, 17, buffer));
		CHECK_EQ("210861548515811875", buffer);
		CHECK_EQ(16, buffer.getPointPosition());
	}


@Test
	public void gayFixed() throws Exception {
		DtoaTest.DataTestState state = new DtoaTest.DataTestState();
		DoubleTestHelper.eachFixed(state, (st, v, numberDigits, representation, decimalPoint) -> {
			st.total++;

			st.underTest = String.format("Using {%g, \"%s\", %d}", v, representation, decimalPoint);
			boolean status = FixedDtoa.fastFixedDtoa(v, numberDigits, st.buffer);

			assertThat(st.underTest, status, is(true));
			assertThat(st.underTest, st.buffer.getPointPosition(), is(equalTo(decimalPoint)));

			assertThat(st.underTest, st.buffer.getPointPosition(), is(equalTo(decimalPoint)));
			assertThat(st.underTest, (st.buffer.length() - st.buffer.getPointPosition()), is(lessThanOrEqualTo(numberDigits)));
			assertThat(st.underTest, stringOf(st.buffer), is(equalTo(representation)));
		});

		System.out.println("day-precision tests run :" + Integer.toString(state.total));
	}


values verified positive at beginning of method   remainder   quotient

@SuppressWarnings("return.type.incompatible") // values verified positive at beginning of method
	@Unsigned int divideModuloIntBignum(Bignum other) {
		requireState(val.signum() >= 0 && other.val.signum() >= 0, "values must be positive");
		BigInteger[] rets = val.divideAndRemainder(other.val);
		val = rets[1]; // remainder

		return toUint(rets[0]); // quotient
	}

@Test
	public void divideModuloIntBignum() {
		char[] buffer = new char[kBufferSize];
		Bignum bignum = new Bignum();
		Bignum other = new Bignum();
		Bignum third = new Bignum();

		bignum.assignUInt16((short) 10);
		other.assignUInt16((short) 2);
		CHECK_EQ(5, bignum.divideModuloIntBignum(other));
		CHECK_EQ("0", bignum.toHexString());

		bignum.assignUInt16((short) 10);
		bignum.shiftLeft(500);
		other.assignUInt16((short) 2);
		other.shiftLeft(500);
		CHECK_EQ(5, bignum.divideModuloIntBignum(other));
		CHECK_EQ("0", bignum.toHexString());

		bignum.assignUInt16((short) 11);
		other.assignUInt16((short) 2);
		CHECK_EQ(5, bignum.divideModuloIntBignum(other));
		CHECK_EQ("1", bignum.toHexString());

		bignum.assignUInt16((short) 10);
		bignum.shiftLeft(500);
		other.assignUInt16((short) 1);
		bignum.addBignum(other);
		other.assignUInt16((short) 2);
		other.shiftLeft(500);
		CHECK_EQ(5, bignum.divideModuloIntBignum(other));
		CHECK_EQ("1", bignum.toHexString());

		bignum.assignUInt16((short) 10);
		bignum.shiftLeft(500);
		other.assignBignum(bignum);
		bignum.multiplyByUInt32(0x1234);
		third.assignUInt16((short) 0xFFF);
		bignum.addBignum(third);
		CHECK_EQ(0x1234, bignum.divideModuloIntBignum(other));
		CHECK_EQ("FFF", bignum.toHexString());

		bignum.assignUInt16((short) 10);
		assignHexString(other, "1234567890");
		CHECK_EQ(0, bignum.divideModuloIntBignum(other));
		CHECK_EQ("A", bignum.toHexString());

		assignHexString(bignum, "12345678");
		assignHexString(other, "3789012");
		CHECK_EQ(5, bignum.divideModuloIntBignum(other));
		CHECK_EQ("D9861E", bignum.toHexString());

		assignHexString(bignum, "70000001");
		assignHexString(other, "1FFFFFFF");
		CHECK_EQ(3, bignum.divideModuloIntBignum(other));
		CHECK_EQ("10000004", bignum.toHexString());

		assignHexString(bignum, "28000000");
		assignHexString(other, "12A05F20");
		CHECK_EQ(2, bignum.divideModuloIntBignum(other));
		CHECK_EQ("2BF41C0", bignum.toHexString());

		bignum.assignUInt16((short) 10);
		bignum.shiftLeft(500);
		other.assignBignum(bignum);
		bignum.multiplyByUInt32(0x1234);
		third.assignUInt16((short) 0xFFF);
		other.subtractBignum(third);
		CHECK_EQ(0x1234, bignum.divideModuloIntBignum(other));
		CHECK_EQ("1232DCC", bignum.toHexString());
		CHECK_EQ(0, bignum.divideModuloIntBignum(other));
		CHECK_EQ("1232DCC", bignum.toHexString());
	}