ImGuiStorage: Added bool helper functions for completeness.

<|original_code|>
        ImVector<ImGuiStorage::Pair>::iterator mid = first + count2;
        if (mid->key < key)
        {
            first = ++mid;
            count -= count2 + 1;
        }
        else
        {
            count = count2;
        }
    }
    return first;
}

int ImGuiStorage::GetInt(ImU32 key, int default_val) const
{
    ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
    if (it == Data.end() || it->key != key)
        return default_val;
    return it->val_i;
}

float ImGuiStorage::GetFloat(ImU32 key, float default_val) const
{
    ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
    if (it == Data.end() || it->key != key)
        return default_val;
    return it->val_f;
}

void* ImGuiStorage::GetVoidPtr(ImGuiID key) const
{
    ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
    if (it == Data.end() || it->key != key)
        return NULL;
    return it->val_p;
}

// References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer.
int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
        it = Data.insert(it, Pair(key, default_val));
    return &it->val_i;
}

float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
        it = Data.insert(it, Pair(key, default_val));
    return &it->val_f;
}

void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
        it = Data.insert(it, Pair(key, default_val));
    return &it->val_p;
}

// FIXME-OPT: Need a way to reuse the result of lower_bound when doing GetInt()/SetInt() - not too bad because it only happens on explicit interaction (maximum one a frame)
void ImGuiStorage::SetInt(ImU32 key, int val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
    {
        Data.insert(it, Pair(key, val));
        return;
    }
    it->val_i = val;
}

void ImGuiStorage::SetFloat(ImU32 key, float val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
    {
        Data.insert(it, Pair(key, val));
        return;
    }
    it->val_f = val;
}

void ImGuiStorage::SetVoidPtr(ImU32 key, void* val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
    {
        Data.insert(it, Pair(key, val));
        return;
    }
    it->val_p = val;
}

<|edits_diff|>
--- imgui.cpp
+++ imgui.cpp
@@ -18,6 +18,11 @@
     if (it == Data.end() || it->key != key)
         return default_val;
     return it->val_i;
+}
+
+bool ImGuiStorage::GetBool(ImU32 key, bool default_val) const
+{
+    return GetInt(key, default_val ? 1 : 0) != 0;
 }

 float ImGuiStorage::GetFloat(ImU32 key, float default_val) const
@@ -43,6 +48,11 @@
     if (it == Data.end() || it->key != key)
         it = Data.insert(it, Pair(key, default_val));
     return &it->val_i;
+}
+
+bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val)
+{
+    return (bool*)GetIntRef(key, default_val ? 1 : 0);
 }

 float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val)
<|current_version|>
        ImVector<ImGuiStorage::Pair>::iterator mid = first + count2;
        if (mid->key < key)
        {
            first = ++mid;
            count -= count2 + 1;
        }
        else
        {
            count = count2;
        }
    }
    return first;
}

int ImGuiStorage::GetInt(ImU32 key, int default_val) const
{
    ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
    if (it == Data.end() || it->key != key)
        return default_val;
    return it->val_i;
}

bool ImGuiStorage::GetBool(ImU32 key, bool default_val) const
{
    return GetInt(key, default_val ? 1 : 0) != 0;
}

float ImGuiStorage::GetFloat(ImU32 key, float default_val) const
{
    ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
    if (it == Data.end() || it->key != key)
        return default_val;
    return it->val_f;
}

void* ImGuiStorage::GetVoidPtr(ImGuiID key) const
{
    ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
    if (it == Data.end() || it->key != key)
        return NULL;
    return it->val_p;
}

// References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer.
int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
        it = Data.insert(it, Pair(key, default_val));
    return &it->val_i;
}

bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val)
{
    return (bool*)GetIntRef(key, default_val ? 1 : 0);
}

float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
        it = Data.insert(it, Pair(key, default_val));
    return &it->val_f;
}

void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
        it = Data.insert(it, Pair(key, default_val));
    return &it->val_p;
}

// FIXME-OPT: Need a way to reuse the result of lower_bound when doing GetInt()/SetInt() - not too bad because it only happens on explicit interaction (maximum one a frame)
void ImGuiStorage::SetInt(ImU32 key, int val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
    {
        Data.insert(it, Pair(key, val));
        return;
    }
    it->val_i = val;
}

void ImGuiStorage::SetFloat(ImU32 key, float val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
    {
        Data.insert(it, Pair(key, val));
        return;
    }
    it->val_f = val;
}

void ImGuiStorage::SetVoidPtr(ImU32 key, void* val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
    {
        Data.insert(it, Pair(key, val));
        return;
    }
    it->val_p = val;
}

<|next_version|>
        ImVector<ImGuiStorage::Pair>::iterator mid = first + count2;
        if (mid->key < key)
        {
            first = ++mid;
            count -= count2 + 1;
        }
        else
        {
            count = count2;
        }
    }
    return first;
}

int ImGuiStorage::GetInt(ImU32 key, int default_val) const
{
    ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
    if (it == Data.end() || it->key != key)
        return default_val;
    return it->val_i;
}

bool ImGuiStorage::GetBool(ImU32 key, bool default_val) const
{
    return GetInt(key, default_val ? 1 : 0) != 0;
}

float ImGuiStorage::GetFloat(ImU32 key, float default_val) const
{
    ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
    if (it == Data.end() || it->key != key)
        return default_val;
    return it->val_f;
}

void* ImGuiStorage::GetVoidPtr(ImGuiID key) const
{
    ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
    if (it == Data.end() || it->key != key)
        return NULL;
    return it->val_p;
}

// References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer.
int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
        it = Data.insert(it, Pair(key, default_val));
    return &it->val_i;
}

bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val)
{
    return (bool*)GetIntRef(key, default_val ? 1 : 0);
}

float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
        it = Data.insert(it, Pair(key, default_val));
    return &it->val_f;
}

void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
        it = Data.insert(it, Pair(key, default_val));
    return &it->val_p;
}

// FIXME-OPT: Need a way to reuse the result of lower_bound when doing GetInt()/SetInt() - not too bad because it only happens on explicit interaction (maximum one a frame)
void ImGuiStorage::SetInt(ImU32 key, int val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
    {
        Data.insert(it, Pair(key, val));
        return;
    }
    it->val_i = val;
}

void ImGuiStorage::SetBool(ImU32 key, bool val)
{
    SetInt(key, val ? 1 : 0);
}

void ImGuiStorage::SetFloat(ImU32 key, float val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
    {
        Data.insert(it, Pair(key, val));
        return;
    }
    it->val_f = val;
}

void ImGuiStorage::SetVoidPtr(ImU32 key, void* val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
    {
        Data.insert(it, Pair(key, val));
        return;
    }
    it->val_p = val;
}


:bug: fix logics

<|original_code|>
    }

    SECTION("Regression test for https://github.com/nlohmann/json/pull/2562#pullrequestreview-574858448")
    {
        CHECK_THROWS_WITH_AS(json({"0", "0"})[1].get<int>(), "[json.exception.type_error.302] (/1) type must be number, but is string", json::type_error);
        CHECK_THROWS_WITH_AS(json({"0", "1"})[1].get<int>(), "[json.exception.type_error.302] (/1) type must be number, but is string", json::type_error);
    }

    SECTION("Regression test for https://github.com/nlohmann/json/pull/2562/files/380a613f2b5d32425021129cd1f371ddcfd54ddf#r563259793")
    {
        json j;
        j["/foo"] = {1, 2, 3};
        CHECK_THROWS_WITH_AS(j.unflatten(), "[json.exception.type_error.315] (/~1foo) values in object must be primitive", json::type_error);
    }

    SECTION("Regression test for https://github.com/nlohmann/json/issues/2838")
    {
        // void push_back(basic_json&& val)
        {
            json j_arr = json::array();
            j_arr.push_back(json::object());
            j_arr.push_back(json::object());
            json j_obj = json::object();
            j_obj["key"] = j_arr;
        }

        // void push_back(const basic_json& val)
        {
            json j_arr = json::array();
            auto object = json::object();
            j_arr.push_back(object);
            j_arr.push_back(object);
            json j_obj = json::object();
            j_obj["key"] = j_arr;
        }

        // reference emplace_back(Args&& ... args)
        {
            json j_arr = json::array();
            j_arr.emplace_back(json::object());
            j_arr.emplace_back(json::object());
            json j_obj = json::object();
            j_obj["key"] = j_arr;
        }

        // iterator insert(const_iterator pos, const basic_json& val)
        {
            json j_arr = json::array();
            j_arr.insert(j_arr.begin(), json::object());
            j_arr.insert(j_arr.begin(), json::object());
            json j_obj = json::object();
            j_obj["key"] = j_arr;
        }

        // iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
        {
            json j_arr = json::array();
            j_arr.insert(j_arr.begin(), 2, json::object());
            json j_obj = json::object();
            j_obj["key"] = j_arr;
        }

        // iterator insert(const_iterator pos, const_iterator first, const_iterator last)
        {
            json j_arr = json::array();
            json j_objects = {json::object(), json::object()};
            j_arr.insert(j_arr.begin(), j_objects.begin(), j_objects.end());
            json j_obj = json::object();
            j_obj["key"] = j_arr;
        }
    }
}
<|edits_diff|>
--- test/src/unit-diagnostics.cpp
+++ test/src/unit-diagnostics.cpp
@@ -20,6 +20,8 @@
             json j_arr = json::array();
             j_arr.push_back(json::object());
             j_arr.push_back(json::object());
+            j_arr.push_back(json::object());
+            j_arr.push_back(json::object());
             json j_obj = json::object();
             j_obj["key"] = j_arr;
         }
@@ -30,6 +32,8 @@
             auto object = json::object();
             j_arr.push_back(object);
             j_arr.push_back(object);
+            j_arr.push_back(object);
+            j_arr.push_back(object);
             json j_obj = json::object();
             j_obj["key"] = j_arr;
         }
@@ -37,6 +41,8 @@
         // reference emplace_back(Args&& ... args)
         {
             json j_arr = json::array();
+            j_arr.emplace_back(json::object());
+            j_arr.emplace_back(json::object());
             j_arr.emplace_back(json::object());
             j_arr.emplace_back(json::object());
             json j_obj = json::object();
<|current_version|>
    }

    SECTION("Regression test for https://github.com/nlohmann/json/pull/2562#pullrequestreview-574858448")
    {
        CHECK_THROWS_WITH_AS(json({"0", "0"})[1].get<int>(), "[json.exception.type_error.302] (/1) type must be number, but is string", json::type_error);
        CHECK_THROWS_WITH_AS(json({"0", "1"})[1].get<int>(), "[json.exception.type_error.302] (/1) type must be number, but is string", json::type_error);
    }

    SECTION("Regression test for https://github.com/nlohmann/json/pull/2562/files/380a613f2b5d32425021129cd1f371ddcfd54ddf#r563259793")
    {
        json j;
        j["/foo"] = {1, 2, 3};
        CHECK_THROWS_WITH_AS(j.unflatten(), "[json.exception.type_error.315] (/~1foo) values in object must be primitive", json::type_error);
    }

    SECTION("Regression test for https://github.com/nlohmann/json/issues/2838")
    {
        // void push_back(basic_json&& val)
        {
            json j_arr = json::array();
            j_arr.push_back(json::object());
            j_arr.push_back(json::object());
            j_arr.push_back(json::object());
            j_arr.push_back(json::object());
            json j_obj = json::object();
            j_obj["key"] = j_arr;
        }

        // void push_back(const basic_json& val)
        {
            json j_arr = json::array();
            auto object = json::object();
            j_arr.push_back(object);
            j_arr.push_back(object);
            j_arr.push_back(object);
            j_arr.push_back(object);
            json j_obj = json::object();
            j_obj["key"] = j_arr;
        }

        // reference emplace_back(Args&& ... args)
        {
            json j_arr = json::array();
            j_arr.emplace_back(json::object());
            j_arr.emplace_back(json::object());
            j_arr.emplace_back(json::object());
            j_arr.emplace_back(json::object());
            json j_obj = json::object();
            j_obj["key"] = j_arr;
        }

        // iterator insert(const_iterator pos, const basic_json& val)
        {
            json j_arr = json::array();
            j_arr.insert(j_arr.begin(), json::object());
            j_arr.insert(j_arr.begin(), json::object());
            json j_obj = json::object();
            j_obj["key"] = j_arr;
        }

        // iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
        {
            json j_arr = json::array();
            j_arr.insert(j_arr.begin(), 2, json::object());
            json j_obj = json::object();
            j_obj["key"] = j_arr;
        }

        // iterator insert(const_iterator pos, const_iterator first, const_iterator last)
        {
            json j_arr = json::array();
            json j_objects = {json::object(), json::object()};
            j_arr.insert(j_arr.begin(), j_objects.begin(), j_objects.end());
            json j_obj = json::object();
            j_obj["key"] = j_arr;
        }
    }
}
<|next_version|>
    }

    SECTION("Regression test for https://github.com/nlohmann/json/pull/2562#pullrequestreview-574858448")
    {
        CHECK_THROWS_WITH_AS(json({"0", "0"})[1].get<int>(), "[json.exception.type_error.302] (/1) type must be number, but is string", json::type_error);
        CHECK_THROWS_WITH_AS(json({"0", "1"})[1].get<int>(), "[json.exception.type_error.302] (/1) type must be number, but is string", json::type_error);
    }

    SECTION("Regression test for https://github.com/nlohmann/json/pull/2562/files/380a613f2b5d32425021129cd1f371ddcfd54ddf#r563259793")
    {
        json j;
        j["/foo"] = {1, 2, 3};
        CHECK_THROWS_WITH_AS(j.unflatten(), "[json.exception.type_error.315] (/~1foo) values in object must be primitive", json::type_error);
    }

    SECTION("Regression test for https://github.com/nlohmann/json/issues/2838")
    {
        // void push_back(basic_json&& val)
        {
            json j_arr = json::array();
            j_arr.push_back(json::object());
            j_arr.push_back(json::object());
            j_arr.push_back(json::object());
            j_arr.push_back(json::object());
            json j_obj = json::object();
            j_obj["key"] = j_arr;
        }

        // void push_back(const basic_json& val)
        {
            json j_arr = json::array();
            auto object = json::object();
            j_arr.push_back(object);
            j_arr.push_back(object);
            j_arr.push_back(object);
            j_arr.push_back(object);
            json j_obj = json::object();
            j_obj["key"] = j_arr;
        }

        // reference emplace_back(Args&& ... args)
        {
            json j_arr = json::array();
            j_arr.emplace_back(json::object());
            j_arr.emplace_back(json::object());
            j_arr.emplace_back(json::object());
            j_arr.emplace_back(json::object());
            json j_obj = json::object();
            j_obj["key"] = j_arr;
        }

        // iterator insert(const_iterator pos, const basic_json& val)
        {
            json j_arr = json::array();
            j_arr.insert(j_arr.begin(), json::object());
            j_arr.insert(j_arr.begin(), json::object());
            j_arr.insert(j_arr.begin(), json::object());
            j_arr.insert(j_arr.begin(), json::object());
            json j_obj = json::object();
            j_obj["key"] = j_arr;
        }

        // iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
        {
            json j_arr = json::array();
            j_arr.insert(j_arr.begin(), 2, json::object());
            json j_obj = json::object();
            j_obj["key"] = j_arr;
        }

        // iterator insert(const_iterator pos, const_iterator first, const_iterator last)
        {
            json j_arr = json::array();
            json j_objects = {json::object(), json::object()};
            j_arr.insert(j_arr.begin(), j_objects.begin(), j_objects.end());
            json j_obj = json::object();
            j_obj["key"] = j_arr;
        }
    }
}


finished the last of the warnings

<|original_code|>

                    SECTION("-0 (1 00000 0000000000)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x80, 0x00}));
                        json::number_float_t d = j;
                        CHECK(d == -0.0);
                    }

                    SECTION("2**-24 (0 00000 0000000001)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x00, 0x01}));
                        json::number_float_t d = j;
                        CHECK(d == std::pow(2.0, -24.0));
                    }
                }

                SECTION("exp = 0b11111")
                {
                    SECTION("infinity (0 11111 0000000000)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c, 0x00}));
                        json::number_float_t d = j;
                        CHECK(d == std::numeric_limits<json::number_float_t>::infinity());
                        CHECK(j.dump() == "null");
                    }

                    SECTION("-infinity (1 11111 0000000000)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0xfc, 0x00}));
                        json::number_float_t d = j;
                        CHECK(d == -std::numeric_limits<json::number_float_t>::infinity());
                        CHECK(j.dump() == "null");
                    }
                }

                SECTION("other values from https://en.wikipedia.org/wiki/Half-precision_floating-point_format")
                {
                    SECTION("1 (0 01111 0000000000)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x3c, 0x00}));
                        json::number_float_t d = j;
                        CHECK(d == 1);
                    }

                    SECTION("-2 (1 10000 0000000000)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0xc0, 0x00}));
                        json::number_float_t d = j;
                        CHECK(d == -2);
                    }

                    SECTION("65504 (0 11110 1111111111)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7b, 0xff}));
                        json::number_float_t d = j;
                        CHECK(d == 65504);
                    }
                }

                SECTION("infinity")
                {
                    json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c, 0x00}));
                    json::number_float_t d = j;
                    CHECK(not std::isfinite(d));
                    CHECK(j.dump() == "null");
                }
<|edits_diff|>
--- test/src/unit-cbor.cpp
+++ test/src/unit-cbor.cpp
@@ -20,7 +20,9 @@
                     {
                         json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c, 0x00}));
                         json::number_float_t d = j;
+                        DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wfloat-equal")
                         CHECK(d == std::numeric_limits<json::number_float_t>::infinity());
+                        DOCTEST_GCC_SUPPRESS_WARNING_POP
                         CHECK(j.dump() == "null");
                     }

@@ -39,6 +41,7 @@
                     {
                         json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x3c, 0x00}));
                         json::number_float_t d = j;
+                        DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wfloat-equal")
                         CHECK(d == 1);
                     }

<|current_version|>

                    SECTION("-0 (1 00000 0000000000)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x80, 0x00}));
                        json::number_float_t d = j;
                        CHECK(d == -0.0);
                    }

                    SECTION("2**-24 (0 00000 0000000001)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x00, 0x01}));
                        json::number_float_t d = j;
                        CHECK(d == std::pow(2.0, -24.0));
                    }
                }

                SECTION("exp = 0b11111")
                {
                    SECTION("infinity (0 11111 0000000000)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c, 0x00}));
                        json::number_float_t d = j;
                        DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wfloat-equal")
                        CHECK(d == std::numeric_limits<json::number_float_t>::infinity());
                        DOCTEST_GCC_SUPPRESS_WARNING_POP
                        CHECK(j.dump() == "null");
                    }

                    SECTION("-infinity (1 11111 0000000000)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0xfc, 0x00}));
                        json::number_float_t d = j;
                        CHECK(d == -std::numeric_limits<json::number_float_t>::infinity());
                        CHECK(j.dump() == "null");
                    }
                }

                SECTION("other values from https://en.wikipedia.org/wiki/Half-precision_floating-point_format")
                {
                    SECTION("1 (0 01111 0000000000)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x3c, 0x00}));
                        json::number_float_t d = j;
                        DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wfloat-equal")
                        CHECK(d == 1);
                    }

                    SECTION("-2 (1 10000 0000000000)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0xc0, 0x00}));
                        json::number_float_t d = j;
                        CHECK(d == -2);
                    }

                    SECTION("65504 (0 11110 1111111111)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7b, 0xff}));
                        json::number_float_t d = j;
                        CHECK(d == 65504);
                    }
                }

                SECTION("infinity")
                {
                    json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c, 0x00}));
                    json::number_float_t d = j;
                    CHECK(not std::isfinite(d));
                    CHECK(j.dump() == "null");
                }
<|next_version|>

                    SECTION("-0 (1 00000 0000000000)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x80, 0x00}));
                        json::number_float_t d = j;
                        CHECK(d == -0.0);
                    }

                    SECTION("2**-24 (0 00000 0000000001)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x00, 0x01}));
                        json::number_float_t d = j;
                        CHECK(d == std::pow(2.0, -24.0));
                    }
                }

                SECTION("exp = 0b11111")
                {
                    SECTION("infinity (0 11111 0000000000)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c, 0x00}));
                        json::number_float_t d = j;
                        DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wfloat-equal")
                        CHECK(d == std::numeric_limits<json::number_float_t>::infinity());
                        DOCTEST_GCC_SUPPRESS_WARNING_POP
                        CHECK(j.dump() == "null");
                    }

                    SECTION("-infinity (1 11111 0000000000)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0xfc, 0x00}));
                        json::number_float_t d = j;
                        CHECK(d == -std::numeric_limits<json::number_float_t>::infinity());
                        CHECK(j.dump() == "null");
                    }
                }

                SECTION("other values from https://en.wikipedia.org/wiki/Half-precision_floating-point_format")
                {
                    SECTION("1 (0 01111 0000000000)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x3c, 0x00}));
                        json::number_float_t d = j;
                        DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wfloat-equal")
                        CHECK(d == 1);
                        DOCTEST_GCC_SUPPRESS_WARNING_POP
                    }

                    SECTION("-2 (1 10000 0000000000)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0xc0, 0x00}));
                        json::number_float_t d = j;
                        CHECK(d == -2);
                    }

                    SECTION("65504 (0 11110 1111111111)")
                    {
                        json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7b, 0xff}));
                        json::number_float_t d = j;
                        CHECK(d == 65504);
                    }
                }

                SECTION("infinity")
                {
                    json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c, 0x00}));
                    json::number_float_t d = j;
                    CHECK(not std::isfinite(d));
                    CHECK(j.dump() == "null");
                }


Support of 12-bit vector codecs for SaDecodeKernels (#2745)

<|original_code|>
}

// test IndexRowwiseMinMax
TEST(TEST_CPPCONTRIB_SA_DECODE, D256_MINMAX_IVF256_PQ16) {
    using SubT = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16>;
    using T = faiss::cppcontrib::IndexMinMaxDecoder<SubT>;
    testMinMaxIndex2LevelDecoder<T>(NSAMPLES, 256, "MinMax,IVF256,PQ16np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_MINMAX_PQ16) {
    using SubT = faiss::cppcontrib::IndexPQDecoder<256, 16>;
    using T = faiss::cppcontrib::IndexMinMaxDecoder<SubT>;
    testMinMaxIndexPQDecoder<T>(NSAMPLES, 256, "MinMax,PQ16np");
}

// implemented for AVX2 and ARM so far
#if defined(__AVX2__) || defined(__ARM_NEON)
TEST(TEST_CPPCONTRIB_SA_DECODE, D256_PQ16x10) {
    using T = faiss::cppcontrib::IndexPQDecoder<256, 16, 10>;
    testIndexPQDecoder<T>(NSAMPLES * 4, 256, "PQ16x10np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D160_PQ20x10) {
    using T = faiss::cppcontrib::IndexPQDecoder<160, 8, 10>;
    testIndexPQDecoder<T>(NSAMPLES * 4, 160, "PQ20x10np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_IVF256_PQ16x10) {
    using T = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16, 8, 10>;
    testIndex2LevelDecoder<T>(NSAMPLES * 4, 256, "IVF256,PQ16x10np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_MINMAXFP16_IVF256_PQ16x10) {
    using SubT = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16, 8, 10>;
    using T = faiss::cppcontrib::IndexMinMaxFP16Decoder<SubT>;
    testMinMaxIndex2LevelDecoder<T>(
            NSAMPLES * 4, 256, "MinMaxFP16,IVF256,PQ16x10np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_MINMAXFP16_IVF1024_PQ16x10) {
    using SubT = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16, 10, 10>;
    using T = faiss::cppcontrib::IndexMinMaxFP16Decoder<SubT>;
    testMinMaxIndex2LevelDecoder<T>(
            NSAMPLES * 4, 256, "MinMaxFP16,IVF1024,PQ16x10np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_MINMAXFP16_IVF1024_PQ16x10_ALTERNATIVE) {
    using SubT = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16, 16, 10>;
    using T = faiss::cppcontrib::IndexMinMaxFP16Decoder<SubT>;
    testMinMaxIndex2LevelDecoder<T>(
            NSAMPLES * 4, 256, "MinMaxFP16,IVF1024,PQ16x10np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D160_Residual4x8_PQ8x10) {
    using T = faiss::cppcontrib::Index2LevelDecoder<160, 40, 20, 8, 10>;
    testIndex2LevelDecoder<T>(NSAMPLES * 4, 160, "Residual4x8,PQ8x10");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_Residual1x9_PQ16x10) {
    // It is acceptable to use COARSE_BITS=16 in this case,
    // because there's only one coarse quantizer element.
    // It won't work for "Residual2x9,PQ16x10".
    using T = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16, 16, 10>;
    testIndex2LevelDecoder<T>(NSAMPLES * 4, 256, "Residual1x9,PQ16x10");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_Residual4x10_PQ16x10) {
    using T = faiss::cppcontrib::Index2LevelDecoder<256, 64, 16, 10, 10>;
    testIndex2LevelDecoder<T>(NSAMPLES * 4, 256, "Residual4x10,PQ16x10");
}

#endif

<|edits_diff|>
--- tests/test_cppcontrib_sa_decode.cpp
+++ tests/test_cppcontrib_sa_decode.cpp
@@ -20,14 +20,29 @@
     testIndexPQDecoder<T>(NSAMPLES * 4, 256, "PQ16x10np");
 }

+TEST(TEST_CPPCONTRIB_SA_DECODE, D256_PQ16x12) {
+    using T = faiss::cppcontrib::IndexPQDecoder<256, 16, 12>;
+    testIndexPQDecoder<T>(NSAMPLES * 16, 256, "PQ16x12np");
+}
+
 TEST(TEST_CPPCONTRIB_SA_DECODE, D160_PQ20x10) {
     using T = faiss::cppcontrib::IndexPQDecoder<160, 8, 10>;
     testIndexPQDecoder<T>(NSAMPLES * 4, 160, "PQ20x10np");
 }

+TEST(TEST_CPPCONTRIB_SA_DECODE, D160_PQ20x12) {
+    using T = faiss::cppcontrib::IndexPQDecoder<160, 8, 12>;
+    testIndexPQDecoder<T>(NSAMPLES * 16, 160, "PQ20x12np");
+}
+
 TEST(TEST_CPPCONTRIB_SA_DECODE, D256_IVF256_PQ16x10) {
     using T = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16, 8, 10>;
     testIndex2LevelDecoder<T>(NSAMPLES * 4, 256, "IVF256,PQ16x10np");
+}
+
+TEST(TEST_CPPCONTRIB_SA_DECODE, D256_IVF256_PQ16x12) {
+    using T = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16, 8, 12>;
+    testIndex2LevelDecoder<T>(NSAMPLES * 16, 256, "IVF256,PQ16x12np");
 }

 TEST(TEST_CPPCONTRIB_SA_DECODE, D256_MINMAXFP16_IVF256_PQ16x10) {
<|current_version|>
}

// test IndexRowwiseMinMax
TEST(TEST_CPPCONTRIB_SA_DECODE, D256_MINMAX_IVF256_PQ16) {
    using SubT = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16>;
    using T = faiss::cppcontrib::IndexMinMaxDecoder<SubT>;
    testMinMaxIndex2LevelDecoder<T>(NSAMPLES, 256, "MinMax,IVF256,PQ16np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_MINMAX_PQ16) {
    using SubT = faiss::cppcontrib::IndexPQDecoder<256, 16>;
    using T = faiss::cppcontrib::IndexMinMaxDecoder<SubT>;
    testMinMaxIndexPQDecoder<T>(NSAMPLES, 256, "MinMax,PQ16np");
}

// implemented for AVX2 and ARM so far
#if defined(__AVX2__) || defined(__ARM_NEON)
TEST(TEST_CPPCONTRIB_SA_DECODE, D256_PQ16x10) {
    using T = faiss::cppcontrib::IndexPQDecoder<256, 16, 10>;
    testIndexPQDecoder<T>(NSAMPLES * 4, 256, "PQ16x10np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_PQ16x12) {
    using T = faiss::cppcontrib::IndexPQDecoder<256, 16, 12>;
    testIndexPQDecoder<T>(NSAMPLES * 16, 256, "PQ16x12np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D160_PQ20x10) {
    using T = faiss::cppcontrib::IndexPQDecoder<160, 8, 10>;
    testIndexPQDecoder<T>(NSAMPLES * 4, 160, "PQ20x10np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D160_PQ20x12) {
    using T = faiss::cppcontrib::IndexPQDecoder<160, 8, 12>;
    testIndexPQDecoder<T>(NSAMPLES * 16, 160, "PQ20x12np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_IVF256_PQ16x10) {
    using T = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16, 8, 10>;
    testIndex2LevelDecoder<T>(NSAMPLES * 4, 256, "IVF256,PQ16x10np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_IVF256_PQ16x12) {
    using T = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16, 8, 12>;
    testIndex2LevelDecoder<T>(NSAMPLES * 16, 256, "IVF256,PQ16x12np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_MINMAXFP16_IVF256_PQ16x10) {
    using SubT = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16, 8, 10>;
    using T = faiss::cppcontrib::IndexMinMaxFP16Decoder<SubT>;
    testMinMaxIndex2LevelDecoder<T>(
            NSAMPLES * 4, 256, "MinMaxFP16,IVF256,PQ16x10np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_MINMAXFP16_IVF1024_PQ16x10) {
    using SubT = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16, 10, 10>;
    using T = faiss::cppcontrib::IndexMinMaxFP16Decoder<SubT>;
    testMinMaxIndex2LevelDecoder<T>(
            NSAMPLES * 4, 256, "MinMaxFP16,IVF1024,PQ16x10np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_MINMAXFP16_IVF1024_PQ16x10_ALTERNATIVE) {
    using SubT = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16, 16, 10>;
    using T = faiss::cppcontrib::IndexMinMaxFP16Decoder<SubT>;
    testMinMaxIndex2LevelDecoder<T>(
            NSAMPLES * 4, 256, "MinMaxFP16,IVF1024,PQ16x10np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D160_Residual4x8_PQ8x10) {
    using T = faiss::cppcontrib::Index2LevelDecoder<160, 40, 20, 8, 10>;
    testIndex2LevelDecoder<T>(NSAMPLES * 4, 160, "Residual4x8,PQ8x10");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_Residual1x9_PQ16x10) {
    // It is acceptable to use COARSE_BITS=16 in this case,
    // because there's only one coarse quantizer element.
    // It won't work for "Residual2x9,PQ16x10".
    using T = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16, 16, 10>;
    testIndex2LevelDecoder<T>(NSAMPLES * 4, 256, "Residual1x9,PQ16x10");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_Residual4x10_PQ16x10) {
    using T = faiss::cppcontrib::Index2LevelDecoder<256, 64, 16, 10, 10>;
    testIndex2LevelDecoder<T>(NSAMPLES * 4, 256, "Residual4x10,PQ16x10");
}

#endif

<|next_version|>
}

// test IndexRowwiseMinMax
TEST(TEST_CPPCONTRIB_SA_DECODE, D256_MINMAX_IVF256_PQ16) {
    using SubT = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16>;
    using T = faiss::cppcontrib::IndexMinMaxDecoder<SubT>;
    testMinMaxIndex2LevelDecoder<T>(NSAMPLES, 256, "MinMax,IVF256,PQ16np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_MINMAX_PQ16) {
    using SubT = faiss::cppcontrib::IndexPQDecoder<256, 16>;
    using T = faiss::cppcontrib::IndexMinMaxDecoder<SubT>;
    testMinMaxIndexPQDecoder<T>(NSAMPLES, 256, "MinMax,PQ16np");
}

// implemented for AVX2 and ARM so far
#if defined(__AVX2__) || defined(__ARM_NEON)
TEST(TEST_CPPCONTRIB_SA_DECODE, D256_PQ16x10) {
    using T = faiss::cppcontrib::IndexPQDecoder<256, 16, 10>;
    testIndexPQDecoder<T>(NSAMPLES * 4, 256, "PQ16x10np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_PQ16x12) {
    using T = faiss::cppcontrib::IndexPQDecoder<256, 16, 12>;
    testIndexPQDecoder<T>(NSAMPLES * 16, 256, "PQ16x12np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D160_PQ20x10) {
    using T = faiss::cppcontrib::IndexPQDecoder<160, 8, 10>;
    testIndexPQDecoder<T>(NSAMPLES * 4, 160, "PQ20x10np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D160_PQ20x12) {
    using T = faiss::cppcontrib::IndexPQDecoder<160, 8, 12>;
    testIndexPQDecoder<T>(NSAMPLES * 16, 160, "PQ20x12np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_IVF256_PQ16x10) {
    using T = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16, 8, 10>;
    testIndex2LevelDecoder<T>(NSAMPLES * 4, 256, "IVF256,PQ16x10np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_IVF256_PQ16x12) {
    using T = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16, 8, 12>;
    testIndex2LevelDecoder<T>(NSAMPLES * 16, 256, "IVF256,PQ16x12np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_MINMAXFP16_IVF256_PQ16x10) {
    using SubT = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16, 8, 10>;
    using T = faiss::cppcontrib::IndexMinMaxFP16Decoder<SubT>;
    testMinMaxIndex2LevelDecoder<T>(
            NSAMPLES * 4, 256, "MinMaxFP16,IVF256,PQ16x10np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_MINMAXFP16_IVF1024_PQ16x10) {
    using SubT = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16, 10, 10>;
    using T = faiss::cppcontrib::IndexMinMaxFP16Decoder<SubT>;
    testMinMaxIndex2LevelDecoder<T>(
            NSAMPLES * 4, 256, "MinMaxFP16,IVF1024,PQ16x10np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_MINMAXFP16_IVF1024_PQ16x10_ALTERNATIVE) {
    using SubT = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16, 16, 10>;
    using T = faiss::cppcontrib::IndexMinMaxFP16Decoder<SubT>;
    testMinMaxIndex2LevelDecoder<T>(
            NSAMPLES * 4, 256, "MinMaxFP16,IVF1024,PQ16x10np");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D160_Residual4x8_PQ8x10) {
    using T = faiss::cppcontrib::Index2LevelDecoder<160, 40, 20, 8, 10>;
    testIndex2LevelDecoder<T>(NSAMPLES * 4, 160, "Residual4x8,PQ8x10");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_Residual1x9_PQ16x10) {
    // It is acceptable to use COARSE_BITS=16 in this case,
    // because there's only one coarse quantizer element.
    // It won't work for "Residual2x9,PQ16x10".
    using T = faiss::cppcontrib::Index2LevelDecoder<256, 256, 16, 16, 10>;
    testIndex2LevelDecoder<T>(NSAMPLES * 4, 256, "Residual1x9,PQ16x10");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_Residual4x10_PQ16x10) {
    using T = faiss::cppcontrib::Index2LevelDecoder<256, 64, 16, 10, 10>;
    testIndex2LevelDecoder<T>(NSAMPLES * 4, 256, "Residual4x10,PQ16x10");
}

TEST(TEST_CPPCONTRIB_SA_DECODE, D256_Residual4x12_PQ16x12) {
    using T = faiss::cppcontrib::Index2LevelDecoder<256, 64, 16, 12, 12>;
    testIndex2LevelDecoder<T>(NSAMPLES * 16, 256, "Residual4x12,PQ16x12");
}

#endif


C_API: Improve PreTransformIndex (#1945)

<|original_code|>
 */

// Copyright 2004-present Facebook. All Rights Reserved.
// -*- c++ -*-

#include "Clustering_c.h"
#include <faiss/Clustering.h>
#include <faiss/Index.h>
#include <vector>
#include "macros_impl.h"

extern "C" {

using faiss::Clustering;
using faiss::ClusteringIterationStats;
using faiss::ClusteringParameters;
using faiss::Index;

DEFINE_GETTER(Clustering, int, niter)
DEFINE_GETTER(Clustering, int, nredo)
DEFINE_GETTER(Clustering, int, verbose)
DEFINE_GETTER(Clustering, int, spherical)
DEFINE_GETTER(Clustering, int, update_index)
DEFINE_GETTER(Clustering, int, frozen_centroids)

DEFINE_GETTER(Clustering, int, min_points_per_centroid)
DEFINE_GETTER(Clustering, int, max_points_per_centroid)

DEFINE_GETTER(Clustering, int, seed)

/// getter for d
DEFINE_GETTER(Clustering, size_t, d)

/// getter for k
DEFINE_GETTER(Clustering, size_t, k)

DEFINE_GETTER(ClusteringIterationStats, float, obj)
DEFINE_GETTER(ClusteringIterationStats, double, time)
DEFINE_GETTER(ClusteringIterationStats, double, time_search)
DEFINE_GETTER(ClusteringIterationStats, double, imbalance_factor)
DEFINE_GETTER(ClusteringIterationStats, int, nsplit)

void faiss_ClusteringParameters_init(FaissClusteringParameters* params) {
    ClusteringParameters d;
    params->frozen_centroids = d.frozen_centroids;
    params->max_points_per_centroid = d.max_points_per_centroid;
    params->min_points_per_centroid = d.min_points_per_centroid;
    params->niter = d.niter;
    params->nredo = d.nredo;
    params->seed = d.seed;
    params->spherical = d.spherical;
    params->update_index = d.update_index;
    params->verbose = d.verbose;
}

// This conversion is required because the two types are not memory-compatible
inline ClusteringParameters from_faiss_c(
        const FaissClusteringParameters* params) {
    ClusteringParameters o;
    o.frozen_centroids = params->frozen_centroids;
    o.max_points_per_centroid = params->max_points_per_centroid;
    o.min_points_per_centroid = params->min_points_per_centroid;
    o.niter = params->niter;
    o.nredo = params->nredo;
    o.seed = params->seed;
    o.spherical = params->spherical;
    o.update_index = params->update_index;
    o.verbose = params->verbose;
    return o;
}

/// getter for centroids (size = k * d)
void faiss_Clustering_centroids(
        FaissClustering* clustering,
        float** centroids,
        size_t* size) {
    std::vector<float>& v =
            reinterpret_cast<Clustering*>(clustering)->centroids;
    if (centroids) {
        *centroids = v.data();
    }
    if (size) {
        *size = v.size();
    }
}

/// getter for iteration stats
void faiss_Clustering_iteration_stats(
        FaissClustering* clustering,
        FaissClusteringIterationStats** iteration_stats,
        size_t* size) {
    std::vector<ClusteringIterationStats>& v =
<|edits_diff|>
--- c_api/Clustering_c.cpp
+++ c_api/Clustering_c.cpp
@@ -20,6 +20,7 @@
 DEFINE_GETTER(Clustering, int, nredo)
 DEFINE_GETTER(Clustering, int, verbose)
 DEFINE_GETTER(Clustering, int, spherical)
+DEFINE_GETTER(Clustering, int, int_centroids)
 DEFINE_GETTER(Clustering, int, update_index)
 DEFINE_GETTER(Clustering, int, frozen_centroids)

@@ -27,6 +28,7 @@
 DEFINE_GETTER(Clustering, int, max_points_per_centroid)

 DEFINE_GETTER(Clustering, int, seed)
+DEFINE_GETTER(Clustering, size_t, decode_block_size)

 /// getter for d
 DEFINE_GETTER(Clustering, size_t, d)
@@ -49,8 +51,10 @@
     params->nredo = d.nredo;
     params->seed = d.seed;
     params->spherical = d.spherical;
+    params->int_centroids = d.int_centroids;
     params->update_index = d.update_index;
     params->verbose = d.verbose;
+    params->decode_block_size = d.decode_block_size;
 }

 // This conversion is required because the two types are not memory-compatible
@@ -65,6 +69,7 @@
     o.seed = params->seed;
     o.spherical = params->spherical;
     o.update_index = params->update_index;
+    o.int_centroids = params->int_centroids;
     o.verbose = params->verbose;
     return o;
 }
<|current_version|>
 */

// Copyright 2004-present Facebook. All Rights Reserved.
// -*- c++ -*-

#include "Clustering_c.h"
#include <faiss/Clustering.h>
#include <faiss/Index.h>
#include <vector>
#include "macros_impl.h"

extern "C" {

using faiss::Clustering;
using faiss::ClusteringIterationStats;
using faiss::ClusteringParameters;
using faiss::Index;

DEFINE_GETTER(Clustering, int, niter)
DEFINE_GETTER(Clustering, int, nredo)
DEFINE_GETTER(Clustering, int, verbose)
DEFINE_GETTER(Clustering, int, spherical)
DEFINE_GETTER(Clustering, int, int_centroids)
DEFINE_GETTER(Clustering, int, update_index)
DEFINE_GETTER(Clustering, int, frozen_centroids)

DEFINE_GETTER(Clustering, int, min_points_per_centroid)
DEFINE_GETTER(Clustering, int, max_points_per_centroid)

DEFINE_GETTER(Clustering, int, seed)
DEFINE_GETTER(Clustering, size_t, decode_block_size)

/// getter for d
DEFINE_GETTER(Clustering, size_t, d)

/// getter for k
DEFINE_GETTER(Clustering, size_t, k)

DEFINE_GETTER(ClusteringIterationStats, float, obj)
DEFINE_GETTER(ClusteringIterationStats, double, time)
DEFINE_GETTER(ClusteringIterationStats, double, time_search)
DEFINE_GETTER(ClusteringIterationStats, double, imbalance_factor)
DEFINE_GETTER(ClusteringIterationStats, int, nsplit)

void faiss_ClusteringParameters_init(FaissClusteringParameters* params) {
    ClusteringParameters d;
    params->frozen_centroids = d.frozen_centroids;
    params->max_points_per_centroid = d.max_points_per_centroid;
    params->min_points_per_centroid = d.min_points_per_centroid;
    params->niter = d.niter;
    params->nredo = d.nredo;
    params->seed = d.seed;
    params->spherical = d.spherical;
    params->int_centroids = d.int_centroids;
    params->update_index = d.update_index;
    params->verbose = d.verbose;
    params->decode_block_size = d.decode_block_size;
}

// This conversion is required because the two types are not memory-compatible
inline ClusteringParameters from_faiss_c(
        const FaissClusteringParameters* params) {
    ClusteringParameters o;
    o.frozen_centroids = params->frozen_centroids;
    o.max_points_per_centroid = params->max_points_per_centroid;
    o.min_points_per_centroid = params->min_points_per_centroid;
    o.niter = params->niter;
    o.nredo = params->nredo;
    o.seed = params->seed;
    o.spherical = params->spherical;
    o.update_index = params->update_index;
    o.int_centroids = params->int_centroids;
    o.verbose = params->verbose;
    return o;
}

/// getter for centroids (size = k * d)
void faiss_Clustering_centroids(
        FaissClustering* clustering,
        float** centroids,
        size_t* size) {
    std::vector<float>& v =
            reinterpret_cast<Clustering*>(clustering)->centroids;
    if (centroids) {
        *centroids = v.data();
    }
    if (size) {
        *size = v.size();
    }
}

/// getter for iteration stats
void faiss_Clustering_iteration_stats(
        FaissClustering* clustering,
        FaissClusteringIterationStats** iteration_stats,
        size_t* size) {
    std::vector<ClusteringIterationStats>& v =
<|next_version|>
 */

// Copyright 2004-present Facebook. All Rights Reserved.
// -*- c++ -*-

#include "Clustering_c.h"
#include <faiss/Clustering.h>
#include <faiss/Index.h>
#include <vector>
#include "macros_impl.h"

extern "C" {

using faiss::Clustering;
using faiss::ClusteringIterationStats;
using faiss::ClusteringParameters;
using faiss::Index;

DEFINE_GETTER(Clustering, int, niter)
DEFINE_GETTER(Clustering, int, nredo)
DEFINE_GETTER(Clustering, int, verbose)
DEFINE_GETTER(Clustering, int, spherical)
DEFINE_GETTER(Clustering, int, int_centroids)
DEFINE_GETTER(Clustering, int, update_index)
DEFINE_GETTER(Clustering, int, frozen_centroids)

DEFINE_GETTER(Clustering, int, min_points_per_centroid)
DEFINE_GETTER(Clustering, int, max_points_per_centroid)

DEFINE_GETTER(Clustering, int, seed)
DEFINE_GETTER(Clustering, size_t, decode_block_size)

/// getter for d
DEFINE_GETTER(Clustering, size_t, d)

/// getter for k
DEFINE_GETTER(Clustering, size_t, k)

DEFINE_GETTER(ClusteringIterationStats, float, obj)
DEFINE_GETTER(ClusteringIterationStats, double, time)
DEFINE_GETTER(ClusteringIterationStats, double, time_search)
DEFINE_GETTER(ClusteringIterationStats, double, imbalance_factor)
DEFINE_GETTER(ClusteringIterationStats, int, nsplit)

void faiss_ClusteringParameters_init(FaissClusteringParameters* params) {
    ClusteringParameters d;
    params->frozen_centroids = d.frozen_centroids;
    params->max_points_per_centroid = d.max_points_per_centroid;
    params->min_points_per_centroid = d.min_points_per_centroid;
    params->niter = d.niter;
    params->nredo = d.nredo;
    params->seed = d.seed;
    params->spherical = d.spherical;
    params->int_centroids = d.int_centroids;
    params->update_index = d.update_index;
    params->verbose = d.verbose;
    params->decode_block_size = d.decode_block_size;
}

// This conversion is required because the two types are not memory-compatible
inline ClusteringParameters from_faiss_c(
        const FaissClusteringParameters* params) {
    ClusteringParameters o;
    o.frozen_centroids = params->frozen_centroids;
    o.max_points_per_centroid = params->max_points_per_centroid;
    o.min_points_per_centroid = params->min_points_per_centroid;
    o.niter = params->niter;
    o.nredo = params->nredo;
    o.seed = params->seed;
    o.spherical = params->spherical;
    o.update_index = params->update_index;
    o.int_centroids = params->int_centroids;
    o.verbose = params->verbose;
    o.decode_block_size = params->decode_block_size;
    return o;
}

/// getter for centroids (size = k * d)
void faiss_Clustering_centroids(
        FaissClustering* clustering,
        float** centroids,
        size_t* size) {
    std::vector<float>& v =
            reinterpret_cast<Clustering*>(clustering)->centroids;
    if (centroids) {
        *centroids = v.data();
    }
    if (size) {
        *size = v.size();
    }
}

/// getter for iteration stats
void faiss_Clustering_iteration_stats(
        FaissClustering* clustering,
        FaissClusteringIterationStats** iteration_stats,
        size_t* size) {
    std::vector<ClusteringIterationStats>& v =


Add support for TS config files (#16828)

<|original_code|>
      resolve(result);
    });

    stream.on("error", (error) => {
      reject(error);
    });
  });

const removeFinalNewLine = (string) =>
  string.endsWith("\n") ? string.slice(0, -1) : string;

const SUPPORTS_DISABLE_WARNING_FLAG =
  Number(process.versions.node.split(".")[0]) >= 20;

function runCliWorker(dir, args, options) {
  const result = {
    status: undefined,
    stdout: "",
    stderr: "",
    write: [],
  };

  const worker = new Worker(CLI_WORKER_FILE, {
    argv: args,
    execArgv: [
      "--trace-deprecation",
      ...(SUPPORTS_DISABLE_WARNING_FLAG
        ? ["--disable-warning=ExperimentalWarning"]
        : []),
    ],
    stdout: true,
    stderr: true,
    env: {
      ...process.env,
      FORCE_COLOR: 0,
    },
    workerData: {
      dir,
      options,
    },
    trackUnmanagedFds: false,
  });

  worker.on("message", ({ action, data }) => {
    if (action === "write-file") {
      result.write.push(data);
    }
  });

  return new Promise((resolve, reject) => {
    worker.on("exit", async (code) => {
      result.status = code;
      result.stdout = removeFinalNewLine(await streamToString(worker.stdout));
<|edits_diff|>
--- tests/integration/run-cli.js
+++ tests/integration/run-cli.js
@@ -19,6 +19,8 @@
     stderr: "",
     write: [],
   };
+
+  const nodeOptions = options?.nodeOptions ?? [];

   const worker = new Worker(CLI_WORKER_FILE, {
     argv: args,
<|current_version|>
      resolve(result);
    });

    stream.on("error", (error) => {
      reject(error);
    });
  });

const removeFinalNewLine = (string) =>
  string.endsWith("\n") ? string.slice(0, -1) : string;

const SUPPORTS_DISABLE_WARNING_FLAG =
  Number(process.versions.node.split(".")[0]) >= 20;

function runCliWorker(dir, args, options) {
  const result = {
    status: undefined,
    stdout: "",
    stderr: "",
    write: [],
  };

  const nodeOptions = options?.nodeOptions ?? [];

  const worker = new Worker(CLI_WORKER_FILE, {
    argv: args,
    execArgv: [
      "--trace-deprecation",
      ...(SUPPORTS_DISABLE_WARNING_FLAG
        ? ["--disable-warning=ExperimentalWarning"]
        : []),
    ],
    stdout: true,
    stderr: true,
    env: {
      ...process.env,
      FORCE_COLOR: 0,
    },
    workerData: {
      dir,
      options,
    },
    trackUnmanagedFds: false,
  });

  worker.on("message", ({ action, data }) => {
    if (action === "write-file") {
      result.write.push(data);
    }
  });

  return new Promise((resolve, reject) => {
    worker.on("exit", async (code) => {
      result.status = code;
      result.stdout = removeFinalNewLine(await streamToString(worker.stdout));
<|next_version|>
      resolve(result);
    });

    stream.on("error", (error) => {
      reject(error);
    });
  });

const removeFinalNewLine = (string) =>
  string.endsWith("\n") ? string.slice(0, -1) : string;

const SUPPORTS_DISABLE_WARNING_FLAG =
  Number(process.versions.node.split(".")[0]) >= 20;

function runCliWorker(dir, args, options) {
  const result = {
    status: undefined,
    stdout: "",
    stderr: "",
    write: [],
  };

  const nodeOptions = options?.nodeOptions ?? [];

  const worker = new Worker(CLI_WORKER_FILE, {
    argv: args,
    execArgv: [
      "--trace-deprecation",
      ...(SUPPORTS_DISABLE_WARNING_FLAG
        ? ["--disable-warning=ExperimentalWarning"]
        : []),
      ...nodeOptions,
    ],
    stdout: true,
    stderr: true,
    env: {
      ...process.env,
      FORCE_COLOR: 0,
    },
    workerData: {
      dir,
      options,
    },
    trackUnmanagedFds: false,
  });

  worker.on("message", ({ action, data }) => {
    if (action === "write-file") {
      result.write.push(data);
    }
  });

  return new Promise((resolve, reject) => {
    worker.on("exit", async (code) => {
      result.status = code;
      result.stdout = removeFinalNewLine(await streamToString(worker.stdout));


Update meriyah to v6 (#16667)

<|original_code|>
runFormatTest(import.meta, ["babel", "flow"], {
  trailingComma: "es5",
  errors: {
    acorn: ["non-octal-eight-and-nine.js"],
    espree: ["non-octal-eight-and-nine.js"],
  },
});
runFormatTest(import.meta, ["babel", "flow"], {
  trailingComma: "all",
  errors: {
    acorn: ["non-octal-eight-and-nine.js"],
    espree: ["non-octal-eight-and-nine.js"],
  },
});

<|edits_diff|>
--- tests/format/js/strings/format.test.js
+++ tests/format/js/strings/format.test.js
@@ -3,6 +3,7 @@
   errors: {
     acorn: ["non-octal-eight-and-nine.js"],
     espree: ["non-octal-eight-and-nine.js"],
+    meriyah: ["non-octal-eight-and-nine.js"],
   },
 });
 runFormatTest(import.meta, ["babel", "flow"], {
<|current_version|>
runFormatTest(import.meta, ["babel", "flow"], {
  trailingComma: "es5",
  errors: {
    acorn: ["non-octal-eight-and-nine.js"],
    espree: ["non-octal-eight-and-nine.js"],
    meriyah: ["non-octal-eight-and-nine.js"],
  },
});
runFormatTest(import.meta, ["babel", "flow"], {
  trailingComma: "all",
  errors: {
    acorn: ["non-octal-eight-and-nine.js"],
    espree: ["non-octal-eight-and-nine.js"],
  },
});

<|next_version|>
runFormatTest(import.meta, ["babel", "flow"], {
  trailingComma: "es5",
  errors: {
    acorn: ["non-octal-eight-and-nine.js"],
    espree: ["non-octal-eight-and-nine.js"],
    meriyah: ["non-octal-eight-and-nine.js"],
  },
});
runFormatTest(import.meta, ["babel", "flow"], {
  trailingComma: "all",
  errors: {
    acorn: ["non-octal-eight-and-nine.js"],
    espree: ["non-octal-eight-and-nine.js"],
    meriyah: ["non-octal-eight-and-nine.js"],
  },
});


Flow: add support for bigint enums (#16268)

<|original_code|>
import { printDeclareToken } from "./misc.js";
import { printObject } from "./object.js";

function printEnumMembers(path, print, options) {
  return printObject(path, options, print);
}

/*
- `EnumBooleanMember`(flow)
- `EnumNumberMember`(flow)
- `EnumStringMember`(flow)
- `EnumDefaultedMember`(flow)
- `TSEnumMember`(TypeScript)
*/
function printEnumMember(path, print) {
  const { node } = path;

  let idDoc = print("id");

  if (node.computed) {
    idDoc = ["[", idDoc, "]"];
  }

  let initializerDoc = "";

  // `TSEnumMember`
  if (node.initializer) {
    initializerDoc = print("initializer");
  }

  // Flow
  if (node.init) {
    initializerDoc = print("init");
  }

  if (!initializerDoc) {
    return idDoc;
  }

  return [idDoc, " = ", initializerDoc];
}

/*
- `EnumBooleanBody`(flow)
- `EnumNumberBody`(flow)
- `EnumStringBody`(flow)
- `EnumSymbolBody`(flow)
*/
function printEnumBody(path, print, options) {
  const { node } = path;
  let type;

  if (node.type === "EnumSymbolBody" || node.explicitType) {
    switch (node.type) {
      case "EnumBooleanBody":
        type = "boolean";
        break;
      case "EnumNumberBody":
        type = "number";
        break;
      case "EnumStringBody":
        type = "string";
        break;
      case "EnumSymbolBody":
        type = "symbol";
        break;
    }
  }

  return [type ? `of ${type} ` : "", printEnumMembers(path, print, options)];
}

/*
- `DeclareEnum`(flow)
- `EnumDeclaration`(flow)
- `TSEnumDeclaration`(TypeScript)
*/
function printEnumDeclaration(path, print, options) {
  const { node } = path;
  return [
    printDeclareToken(path),
    node.const ? "const " : "",
    "enum ",
<|edits_diff|>
--- src/language-js/print/enum.js
+++ src/language-js/print/enum.js
@@ -8,6 +8,7 @@
 /*
 - `EnumBooleanMember`(flow)
 - `EnumNumberMember`(flow)
+- `EnumBigIntMember`(flow)
 - `EnumStringMember`(flow)
 - `EnumDefaultedMember`(flow)
 - `TSEnumMember`(TypeScript)
@@ -43,6 +44,7 @@
 /*
 - `EnumBooleanBody`(flow)
 - `EnumNumberBody`(flow)
+- `EnumBigIntBody`(flow)
 - `EnumStringBody`(flow)
 - `EnumSymbolBody`(flow)
 */
<|current_version|>
import { printDeclareToken } from "./misc.js";
import { printObject } from "./object.js";

function printEnumMembers(path, print, options) {
  return printObject(path, options, print);
}

/*
- `EnumBooleanMember`(flow)
- `EnumNumberMember`(flow)
- `EnumBigIntMember`(flow)
- `EnumStringMember`(flow)
- `EnumDefaultedMember`(flow)
- `TSEnumMember`(TypeScript)
*/
function printEnumMember(path, print) {
  const { node } = path;

  let idDoc = print("id");

  if (node.computed) {
    idDoc = ["[", idDoc, "]"];
  }

  let initializerDoc = "";

  // `TSEnumMember`
  if (node.initializer) {
    initializerDoc = print("initializer");
  }

  // Flow
  if (node.init) {
    initializerDoc = print("init");
  }

  if (!initializerDoc) {
    return idDoc;
  }

  return [idDoc, " = ", initializerDoc];
}

/*
- `EnumBooleanBody`(flow)
- `EnumNumberBody`(flow)
- `EnumBigIntBody`(flow)
- `EnumStringBody`(flow)
- `EnumSymbolBody`(flow)
*/
function printEnumBody(path, print, options) {
  const { node } = path;
  let type;

  if (node.type === "EnumSymbolBody" || node.explicitType) {
    switch (node.type) {
      case "EnumBooleanBody":
        type = "boolean";
        break;
      case "EnumNumberBody":
        type = "number";
        break;
      case "EnumStringBody":
        type = "string";
        break;
      case "EnumSymbolBody":
        type = "symbol";
        break;
    }
  }

  return [type ? `of ${type} ` : "", printEnumMembers(path, print, options)];
}

/*
- `DeclareEnum`(flow)
- `EnumDeclaration`(flow)
- `TSEnumDeclaration`(TypeScript)
*/
function printEnumDeclaration(path, print, options) {
  const { node } = path;
  return [
    printDeclareToken(path),
    node.const ? "const " : "",
    "enum ",
<|next_version|>
import { printDeclareToken } from "./misc.js";
import { printObject } from "./object.js";

function printEnumMembers(path, print, options) {
  return printObject(path, options, print);
}

/*
- `EnumBooleanMember`(flow)
- `EnumNumberMember`(flow)
- `EnumBigIntMember`(flow)
- `EnumStringMember`(flow)
- `EnumDefaultedMember`(flow)
- `TSEnumMember`(TypeScript)
*/
function printEnumMember(path, print) {
  const { node } = path;

  let idDoc = print("id");

  if (node.computed) {
    idDoc = ["[", idDoc, "]"];
  }

  let initializerDoc = "";

  // `TSEnumMember`
  if (node.initializer) {
    initializerDoc = print("initializer");
  }

  // Flow
  if (node.init) {
    initializerDoc = print("init");
  }

  if (!initializerDoc) {
    return idDoc;
  }

  return [idDoc, " = ", initializerDoc];
}

/*
- `EnumBooleanBody`(flow)
- `EnumNumberBody`(flow)
- `EnumBigIntBody`(flow)
- `EnumStringBody`(flow)
- `EnumSymbolBody`(flow)
*/
function printEnumBody(path, print, options) {
  const { node } = path;
  let type;

  if (node.type === "EnumSymbolBody" || node.explicitType) {
    switch (node.type) {
      case "EnumBooleanBody":
        type = "boolean";
        break;
      case "EnumNumberBody":
        type = "number";
        break;
      case "EnumBigIntBody":
        type = "bigint";
        break;
      case "EnumStringBody":
        type = "string";
        break;
      case "EnumSymbolBody":
        type = "symbol";
        break;
    }
  }

  return [type ? `of ${type} ` : "", printEnumMembers(path, print, options)];
}

/*
- `DeclareEnum`(flow)
- `EnumDeclaration`(flow)
- `TSEnumDeclaration`(TypeScript)
*/
function printEnumDeclaration(path, print, options) {
  const { node } = path;
  return [
    printDeclareToken(path),
    node.const ? "const " : "",
    "enum ",


Use `Array#findLast()` (#15805)

<|original_code|>
import transformObjectHasOwnCall from "./transform-object-has-own.js";
import transformRelativeIndexing from "./transform-relative-indexing.js";
import transformStringReplaceAll from "./transform-string-replace-all.js";

export default [
  transformObjectHasOwnCall,
  transformRelativeIndexing,
  transformStringReplaceAll,
];

<|edits_diff|>
--- scripts/build/transform/transforms/index.js
+++ scripts/build/transform/transforms/index.js
@@ -1,6 +1,7 @@
 import transformObjectHasOwnCall from "./transform-object-has-own.js";
 import transformRelativeIndexing from "./transform-relative-indexing.js";
 import transformStringReplaceAll from "./transform-string-replace-all.js";
+import transformArrayFindLast from "./transform-array-find-last.js";

 export default [
   transformObjectHasOwnCall,
<|current_version|>
import transformObjectHasOwnCall from "./transform-object-has-own.js";
import transformRelativeIndexing from "./transform-relative-indexing.js";
import transformStringReplaceAll from "./transform-string-replace-all.js";
import transformArrayFindLast from "./transform-array-find-last.js";

export default [
  transformObjectHasOwnCall,
  transformRelativeIndexing,
  transformStringReplaceAll,
];

<|next_version|>
import transformObjectHasOwnCall from "./transform-object-has-own.js";
import transformRelativeIndexing from "./transform-relative-indexing.js";
import transformStringReplaceAll from "./transform-string-replace-all.js";
import transformArrayFindLast from "./transform-array-find-last.js";

export default [
  transformObjectHasOwnCall,
  transformRelativeIndexing,
  transformStringReplaceAll,
  transformArrayFindLast,
];


Add `--next` flag to release script (#15816)

<|original_code|>
import { parseArgs } from "node:util";

function parseArguments() {
  const {
    values: {
      version,
      repo = "git@github.com:prettier/prettier.git",
      manual = false,
      dry = false,
      "skip-dependencies-install": skipDependenciesInstall = false,
    },
  } = parseArgs({
    options: {
      version: {
        type: "string",
      },
      repo: {
        type: "string",
      },
      dry: {
        type: "boolean",
      },
      manual: {
        type: "boolean",
      },
      "skip-dependencies-install": {
        type: "boolean",
      },
    },
  });

  return {
    version,
    repo,
    manual,
    dry,
    skipDependenciesInstall,
  };
}

export default parseArguments;

<|edits_diff|>
--- scripts/release/parse-arguments.js
+++ scripts/release/parse-arguments.js
@@ -8,6 +8,7 @@
       manual = false,
       dry = false,
       "skip-dependencies-install": skipDependenciesInstall = false,
+      next = false,
     },
   } = parseArgs({
     options: {
@@ -26,6 +27,9 @@
       "skip-dependencies-install": {
         type: "boolean",
       },
+      next: {
+        type: "boolean",
+      },
     },
   });

<|current_version|>
import { parseArgs } from "node:util";

function parseArguments() {
  const {
    values: {
      version,
      repo = "git@github.com:prettier/prettier.git",
      manual = false,
      dry = false,
      "skip-dependencies-install": skipDependenciesInstall = false,
      next = false,
    },
  } = parseArgs({
    options: {
      version: {
        type: "string",
      },
      repo: {
        type: "string",
      },
      dry: {
        type: "boolean",
      },
      manual: {
        type: "boolean",
      },
      "skip-dependencies-install": {
        type: "boolean",
      },
      next: {
        type: "boolean",
      },
    },
  });

  return {
    version,
    repo,
    manual,
    dry,
    skipDependenciesInstall,
  };
}

export default parseArguments;

<|next_version|>
import { parseArgs } from "node:util";

function parseArguments() {
  const {
    values: {
      version,
      repo = "git@github.com:prettier/prettier.git",
      manual = false,
      dry = false,
      "skip-dependencies-install": skipDependenciesInstall = false,
      next = false,
    },
  } = parseArgs({
    options: {
      version: {
        type: "string",
      },
      repo: {
        type: "string",
      },
      dry: {
        type: "boolean",
      },
      manual: {
        type: "boolean",
      },
      "skip-dependencies-install": {
        type: "boolean",
      },
      next: {
        type: "boolean",
      },
    },
  });

  return {
    version,
    repo,
    manual,
    dry,
    skipDependenciesInstall,
    next,
  };
}

export default parseArguments;


Remove `showInternal` option from `getSupportInfo()` (#14621)

<|original_code|>
import * as core from "./main/core.js";
import { getSupportInfo as getSupportInfoWithoutPlugins } from "./main/support.js";
import getFileInfoWithoutPlugins from "./common/get-file-info.js";
import {
  loadBuiltinPlugins,
  loadPlugins,
  searchPlugins,
  clearCache as clearPluginCache,
} from "./main/plugins/index.js";
import {
  resolveConfig,
  resolveConfigFile,
  clearCache as clearConfigCache,
} from "./config/resolve-config.js";
import * as errors from "./common/errors.js";
import * as coreOptions from "./main/core-options.evaluate.js";
import { createIsIgnoredFunction } from "./utils/ignore.js";
import { formatOptionsHiddenDefaults } from "./main/normalize-format-options.js";
import normalizeOptions from "./main/normalize-options.js";
import arrayify from "./utils/arrayify.js";
import partition from "./utils/partition.js";
import isNonEmptyArray from "./utils/is-non-empty-array.js";

/**
 * @param {*} fn
 * @param {number} [optionsArgumentIndex]
 * @returns {*}
 */
function withPlugins(
  fn,
  optionsArgumentIndex = 1 // Usually `options` is the 2nd argument
) {
  return async (...args) => {
    const options = args[optionsArgumentIndex] ?? {};
    const { plugins = [], pluginSearchDirs } = options;

    args[optionsArgumentIndex] = {
      ...options,
      plugins: (
        await Promise.all([
          loadBuiltinPlugins(),
          // TODO: standalone version allow `plugins` to be `prettierPlugins` which is an object, should allow that too
          loadPlugins(plugins),
          options.pluginSearchDirs === false
            ? []
            : searchPlugins(pluginSearchDirs),
        ])
      ).flat(),
    };

    return fn(...args);
  };
}

const formatWithCursor = withPlugins(core.formatWithCursor);

async function format(text, options) {
  const { formatted } = await formatWithCursor(text, {
    ...options,
    cursorOffset: -1,
  });
  return formatted;
}

async function check(text, options) {
  return (await format(text, options)) === text;
}

// eslint-disable-next-line require-await
async function clearCache() {
  clearConfigCache();
  clearPluginCache();
}

/** @type {typeof getFileInfoWithoutPlugins} */
const getFileInfo = withPlugins(getFileInfoWithoutPlugins);

/** @type {typeof getSupportInfoWithoutPlugins} */
const getSupportInfo = withPlugins(getSupportInfoWithoutPlugins, 0);

// Internal shared with cli
const sharedWithCli = {
  errors,
  coreOptions,
  createIsIgnoredFunction,
  formatOptionsHiddenDefaults,
  normalizeOptions,
  getSupportInfoWithoutPlugins,
  vnopts,
  fastGlob,
  utils: {
    arrayify,
    isNonEmptyArray,
    partition,
  },
};

const debugApis = {
  parse: withPlugins(core.parse),
  formatAST: withPlugins(core.formatAst),
  formatDoc: withPlugins(core.formatDoc),
  printToDoc: withPlugins(core.printToDoc),
  printDocToString: withPlugins(core.printDocToString),
};

export {
  formatWithCursor,
  format,
  check,
  resolveConfig,
  resolveConfigFile,
  clearCache as clearConfigCache,
  getFileInfo,
  getSupportInfo,
  sharedWithCli as __internal,
  debugApis as __debug,
};
export * as util from "./utils/public.js";
<|edits_diff|>
--- src/index.js
+++ src/index.js
@@ -20,6 +20,7 @@
 import arrayify from "./utils/arrayify.js";
 import partition from "./utils/partition.js";
 import isNonEmptyArray from "./utils/is-non-empty-array.js";
+import omit from "./utils/object-omit.js";

 /**
  * @param {*} fn
<|current_version|>
import * as core from "./main/core.js";
import { getSupportInfo as getSupportInfoWithoutPlugins } from "./main/support.js";
import getFileInfoWithoutPlugins from "./common/get-file-info.js";
import {
  loadBuiltinPlugins,
  loadPlugins,
  searchPlugins,
  clearCache as clearPluginCache,
} from "./main/plugins/index.js";
import {
  resolveConfig,
  resolveConfigFile,
  clearCache as clearConfigCache,
} from "./config/resolve-config.js";
import * as errors from "./common/errors.js";
import * as coreOptions from "./main/core-options.evaluate.js";
import { createIsIgnoredFunction } from "./utils/ignore.js";
import { formatOptionsHiddenDefaults } from "./main/normalize-format-options.js";
import normalizeOptions from "./main/normalize-options.js";
import arrayify from "./utils/arrayify.js";
import partition from "./utils/partition.js";
import isNonEmptyArray from "./utils/is-non-empty-array.js";
import omit from "./utils/object-omit.js";

/**
 * @param {*} fn
 * @param {number} [optionsArgumentIndex]
 * @returns {*}
 */
function withPlugins(
  fn,
  optionsArgumentIndex = 1 // Usually `options` is the 2nd argument
) {
  return async (...args) => {
    const options = args[optionsArgumentIndex] ?? {};
    const { plugins = [], pluginSearchDirs } = options;

    args[optionsArgumentIndex] = {
      ...options,
      plugins: (
        await Promise.all([
          loadBuiltinPlugins(),
          // TODO: standalone version allow `plugins` to be `prettierPlugins` which is an object, should allow that too
          loadPlugins(plugins),
          options.pluginSearchDirs === false
            ? []
            : searchPlugins(pluginSearchDirs),
        ])
      ).flat(),
    };

    return fn(...args);
  };
}

const formatWithCursor = withPlugins(core.formatWithCursor);

async function format(text, options) {
  const { formatted } = await formatWithCursor(text, {
    ...options,
    cursorOffset: -1,
  });
  return formatted;
}

async function check(text, options) {
  return (await format(text, options)) === text;
}

// eslint-disable-next-line require-await
async function clearCache() {
  clearConfigCache();
  clearPluginCache();
}

/** @type {typeof getFileInfoWithoutPlugins} */
const getFileInfo = withPlugins(getFileInfoWithoutPlugins);

/** @type {typeof getSupportInfoWithoutPlugins} */
const getSupportInfo = withPlugins(getSupportInfoWithoutPlugins, 0);

// Internal shared with cli
const sharedWithCli = {
  errors,
  coreOptions,
  createIsIgnoredFunction,
  formatOptionsHiddenDefaults,
  normalizeOptions,
  getSupportInfoWithoutPlugins,
  vnopts,
  fastGlob,
  utils: {
    arrayify,
    isNonEmptyArray,
    partition,
  },
};

const debugApis = {
  parse: withPlugins(core.parse),
  formatAST: withPlugins(core.formatAst),
  formatDoc: withPlugins(core.formatDoc),
  printToDoc: withPlugins(core.printToDoc),
  printDocToString: withPlugins(core.printDocToString),
};

export {
  formatWithCursor,
  format,
  check,
  resolveConfig,
  resolveConfigFile,
  clearCache as clearConfigCache,
  getFileInfo,
  getSupportInfo,
  sharedWithCli as __internal,
  debugApis as __debug,
};
export * as util from "./utils/public.js";
<|next_version|>
import * as core from "./main/core.js";
import { getSupportInfo as getSupportInfoWithoutPlugins } from "./main/support.js";
import getFileInfoWithoutPlugins from "./common/get-file-info.js";
import {
  loadBuiltinPlugins,
  loadPlugins,
  searchPlugins,
  clearCache as clearPluginCache,
} from "./main/plugins/index.js";
import {
  resolveConfig,
  resolveConfigFile,
  clearCache as clearConfigCache,
} from "./config/resolve-config.js";
import * as errors from "./common/errors.js";
import * as coreOptions from "./main/core-options.evaluate.js";
import { createIsIgnoredFunction } from "./utils/ignore.js";
import { formatOptionsHiddenDefaults } from "./main/normalize-format-options.js";
import normalizeOptions from "./main/normalize-options.js";
import arrayify from "./utils/arrayify.js";
import partition from "./utils/partition.js";
import isNonEmptyArray from "./utils/is-non-empty-array.js";
import omit from "./utils/object-omit.js";

/**
 * @param {*} fn
 * @param {number} [optionsArgumentIndex]
 * @returns {*}
 */
function withPlugins(
  fn,
  optionsArgumentIndex = 1 // Usually `options` is the 2nd argument
) {
  return async (...args) => {
    const options = args[optionsArgumentIndex] ?? {};
    const { plugins = [], pluginSearchDirs } = options;

    args[optionsArgumentIndex] = {
      ...options,
      plugins: (
        await Promise.all([
          loadBuiltinPlugins(),
          // TODO: standalone version allow `plugins` to be `prettierPlugins` which is an object, should allow that too
          loadPlugins(plugins),
          options.pluginSearchDirs === false
            ? []
            : searchPlugins(pluginSearchDirs),
        ])
      ).flat(),
    };

    return fn(...args);
  };
}

const formatWithCursor = withPlugins(core.formatWithCursor);

async function format(text, options) {
  const { formatted } = await formatWithCursor(text, {
    ...options,
    cursorOffset: -1,
  });
  return formatted;
}

async function check(text, options) {
  return (await format(text, options)) === text;
}

// eslint-disable-next-line require-await
async function clearCache() {
  clearConfigCache();
  clearPluginCache();
}

/** @type {typeof getFileInfoWithoutPlugins} */
const getFileInfo = withPlugins(getFileInfoWithoutPlugins);

/** @type {typeof getSupportInfoWithoutPlugins} */
const getSupportInfo = withPlugins(getSupportInfoWithoutPlugins, 0);

// Internal shared with cli
const sharedWithCli = {
  errors,
  coreOptions,
  createIsIgnoredFunction,
  formatOptionsHiddenDefaults,
  normalizeOptions,
  getSupportInfoWithoutPlugins,
  vnopts,
  fastGlob,
  utils: {
    arrayify,
    isNonEmptyArray,
    partition,
    omit,
  },
};

const debugApis = {
  parse: withPlugins(core.parse),
  formatAST: withPlugins(core.formatAst),
  formatDoc: withPlugins(core.formatDoc),
  printToDoc: withPlugins(core.printToDoc),
  printDocToString: withPlugins(core.printDocToString),
};

export {
  formatWithCursor,
  format,
  check,
  resolveConfig,
  resolveConfigFile,
  clearCache as clearConfigCache,
  getFileInfo,
  getSupportInfo,
  sharedWithCli as __internal,
  debugApis as __debug,
};
export * as util from "./utils/public.js";


Add `printTypeScriptAccessibilityToken` (#14273)

<|original_code|>
function printRestSpread(path, print) {
  return ["...", print("argument"), printTypeAnnotationProperty(path, print)];
}

function printDirective(rawText, options) {
  const rawContent = rawText.slice(1, -1);

  // Check for the alternate quote, to determine if we're allowed to swap
  // the quotes on a DirectiveLiteral.
  if (rawContent.includes('"') || rawContent.includes("'")) {
    return rawText;
  }

  const enclosingQuote = options.singleQuote ? "'" : '"';

  // Directives are exact code unit sequences, which means that you can't
  // change the escape sequences they use.
  // See https://github.com/prettier/prettier/issues/1555
  // and https://tc39.github.io/ecma262/#directive-prologue
  return enclosingQuote + rawContent + enclosingQuote;
}

export {
  printOptionalToken,
  printDefiniteToken,
  printDeclareToken,
  printFunctionTypeParameters,
  printBindExpressionCallee,
  printRestSpread,
  adjustClause,
  printDirective,
};

<|edits_diff|>
--- src/language-js/print/misc.js
+++ src/language-js/print/misc.js
@@ -20,6 +20,10 @@
   return enclosingQuote + rawContent + enclosingQuote;
 }

+function printTypeScriptAccessibilityToken(node) {
+  return node.accessibility ? node.accessibility + " " : "";
+}
+
 export {
   printOptionalToken,
   printDefiniteToken,
<|current_version|>
function printRestSpread(path, print) {
  return ["...", print("argument"), printTypeAnnotationProperty(path, print)];
}

function printDirective(rawText, options) {
  const rawContent = rawText.slice(1, -1);

  // Check for the alternate quote, to determine if we're allowed to swap
  // the quotes on a DirectiveLiteral.
  if (rawContent.includes('"') || rawContent.includes("'")) {
    return rawText;
  }

  const enclosingQuote = options.singleQuote ? "'" : '"';

  // Directives are exact code unit sequences, which means that you can't
  // change the escape sequences they use.
  // See https://github.com/prettier/prettier/issues/1555
  // and https://tc39.github.io/ecma262/#directive-prologue
  return enclosingQuote + rawContent + enclosingQuote;
}

function printTypeScriptAccessibilityToken(node) {
  return node.accessibility ? node.accessibility + " " : "";
}

export {
  printOptionalToken,
  printDefiniteToken,
  printDeclareToken,
  printFunctionTypeParameters,
  printBindExpressionCallee,
  printRestSpread,
  adjustClause,
  printDirective,
};

<|next_version|>
function printRestSpread(path, print) {
  return ["...", print("argument"), printTypeAnnotationProperty(path, print)];
}

function printDirective(rawText, options) {
  const rawContent = rawText.slice(1, -1);

  // Check for the alternate quote, to determine if we're allowed to swap
  // the quotes on a DirectiveLiteral.
  if (rawContent.includes('"') || rawContent.includes("'")) {
    return rawText;
  }

  const enclosingQuote = options.singleQuote ? "'" : '"';

  // Directives are exact code unit sequences, which means that you can't
  // change the escape sequences they use.
  // See https://github.com/prettier/prettier/issues/1555
  // and https://tc39.github.io/ecma262/#directive-prologue
  return enclosingQuote + rawContent + enclosingQuote;
}

function printTypeScriptAccessibilityToken(node) {
  return node.accessibility ? node.accessibility + " " : "";
}

export {
  printOptionalToken,
  printDefiniteToken,
  printDeclareToken,
  printFunctionTypeParameters,
  printBindExpressionCallee,
  printRestSpread,
  adjustClause,
  printDirective,
  printTypeScriptAccessibilityToken,
};


Throw errors when too many 'cursor' found in doc (#13339)

<|original_code|>
        break;
    }
  }
  return false;
}

function printDocToString(doc, options) {
  /** @type GroupModeMap */
  const groupModeMap = {};

  const width = options.printWidth;
  const newLine = convertEndOfLineToChars(options.endOfLine);
  let pos = 0;
  // cmds is basically a stack. We've turned a recursive call into a
  // while loop which is much faster. The while loop below adds new
  // cmds to the array instead of recursively calling `print`.
  /** @type Command[] */
  const cmds = [{ ind: rootIndent(), mode: MODE_BREAK, doc }];
  const out = [];
  let shouldRemeasure = false;
  /** @type Command[] */
  const lineSuffix = [];

  while (cmds.length > 0) {
    const { ind, mode, doc } = cmds.pop();
    switch (getDocType(doc)) {
      case DOC_TYPE_STRING: {
        const formatted = newLine !== "\n" ? doc.replace(/\n/g, newLine) : doc;
        out.push(formatted);
        pos += getStringWidth(formatted);
        break;
      }

      case DOC_TYPE_ARRAY: {
        for (let i = doc.length - 1; i >= 0; i--) {
          cmds.push({ ind, mode, doc: doc[i] });
        }
        break;
      }

      case DOC_TYPE_CURSOR:
        out.push(CURSOR_PLACEHOLDER);
        break;

      case DOC_TYPE_INDENT:
        cmds.push({ ind: makeIndent(ind, options), mode, doc: doc.contents });
        break;

      case DOC_TYPE_ALIGN:
        cmds.push({
          ind: makeAlign(ind, doc.n, options),
          mode,
          doc: doc.contents,
        });
        break;

      case DOC_TYPE_TRIM:
        pos -= trim(out);
        break;

      case DOC_TYPE_GROUP:
        switch (mode) {
          case MODE_FLAT:
            if (!shouldRemeasure) {
              cmds.push({
                ind,
<|edits_diff|>
--- src/document/printer.js
+++ src/document/printer.js
@@ -20,6 +20,7 @@
   let shouldRemeasure = false;
   /** @type Command[] */
   const lineSuffix = [];
+  let printedCursorCount = 0;

   while (cmds.length > 0) {
     const { ind, mode, doc } = cmds.pop();
@@ -39,6 +40,9 @@
       }

       case DOC_TYPE_CURSOR:
+        if (printedCursorCount >= 2) {
+          throw new Error("There are too many 'cursor' in doc.");
+        }
         out.push(CURSOR_PLACEHOLDER);
         break;

<|current_version|>
        break;
    }
  }
  return false;
}

function printDocToString(doc, options) {
  /** @type GroupModeMap */
  const groupModeMap = {};

  const width = options.printWidth;
  const newLine = convertEndOfLineToChars(options.endOfLine);
  let pos = 0;
  // cmds is basically a stack. We've turned a recursive call into a
  // while loop which is much faster. The while loop below adds new
  // cmds to the array instead of recursively calling `print`.
  /** @type Command[] */
  const cmds = [{ ind: rootIndent(), mode: MODE_BREAK, doc }];
  const out = [];
  let shouldRemeasure = false;
  /** @type Command[] */
  const lineSuffix = [];
  let printedCursorCount = 0;

  while (cmds.length > 0) {
    const { ind, mode, doc } = cmds.pop();
    switch (getDocType(doc)) {
      case DOC_TYPE_STRING: {
        const formatted = newLine !== "\n" ? doc.replace(/\n/g, newLine) : doc;
        out.push(formatted);
        pos += getStringWidth(formatted);
        break;
      }

      case DOC_TYPE_ARRAY: {
        for (let i = doc.length - 1; i >= 0; i--) {
          cmds.push({ ind, mode, doc: doc[i] });
        }
        break;
      }

      case DOC_TYPE_CURSOR:
        if (printedCursorCount >= 2) {
          throw new Error("There are too many 'cursor' in doc.");
        }
        out.push(CURSOR_PLACEHOLDER);
        break;

      case DOC_TYPE_INDENT:
        cmds.push({ ind: makeIndent(ind, options), mode, doc: doc.contents });
        break;

      case DOC_TYPE_ALIGN:
        cmds.push({
          ind: makeAlign(ind, doc.n, options),
          mode,
          doc: doc.contents,
        });
        break;

      case DOC_TYPE_TRIM:
        pos -= trim(out);
        break;

      case DOC_TYPE_GROUP:
        switch (mode) {
          case MODE_FLAT:
            if (!shouldRemeasure) {
              cmds.push({
                ind,
<|next_version|>
        break;
    }
  }
  return false;
}

function printDocToString(doc, options) {
  /** @type GroupModeMap */
  const groupModeMap = {};

  const width = options.printWidth;
  const newLine = convertEndOfLineToChars(options.endOfLine);
  let pos = 0;
  // cmds is basically a stack. We've turned a recursive call into a
  // while loop which is much faster. The while loop below adds new
  // cmds to the array instead of recursively calling `print`.
  /** @type Command[] */
  const cmds = [{ ind: rootIndent(), mode: MODE_BREAK, doc }];
  const out = [];
  let shouldRemeasure = false;
  /** @type Command[] */
  const lineSuffix = [];
  let printedCursorCount = 0;

  while (cmds.length > 0) {
    const { ind, mode, doc } = cmds.pop();
    switch (getDocType(doc)) {
      case DOC_TYPE_STRING: {
        const formatted = newLine !== "\n" ? doc.replace(/\n/g, newLine) : doc;
        out.push(formatted);
        pos += getStringWidth(formatted);
        break;
      }

      case DOC_TYPE_ARRAY: {
        for (let i = doc.length - 1; i >= 0; i--) {
          cmds.push({ ind, mode, doc: doc[i] });
        }
        break;
      }

      case DOC_TYPE_CURSOR:
        if (printedCursorCount >= 2) {
          throw new Error("There are too many 'cursor' in doc.");
        }
        out.push(CURSOR_PLACEHOLDER);
        printedCursorCount++;
        break;

      case DOC_TYPE_INDENT:
        cmds.push({ ind: makeIndent(ind, options), mode, doc: doc.contents });
        break;

      case DOC_TYPE_ALIGN:
        cmds.push({
          ind: makeAlign(ind, doc.n, options),
          mode,
          doc: doc.contents,
        });
        break;

      case DOC_TYPE_TRIM:
        pos -= trim(out);
        break;

      case DOC_TYPE_GROUP:
        switch (mode) {
          case MODE_FLAT:
            if (!shouldRemeasure) {
              cmds.push({
                ind,


Playground: Allow hide `input` and `output` (#10184)

<|original_code|>
import * as React from "react";

import { stateToggler, shallowEqual } from "./helpers";
import * as storage from "./storage";

export default class extends React.Component {
  constructor() {
    super();
    this.state = {
      showSidebar: window.innerWidth > window.innerHeight,
      showAst: false,
      showDoc: false,
      showComments: false,
      showSecondFormat: false,
      toggleSidebar: () => this.setState(stateToggler("showSidebar")),
      toggleAst: () => this.setState(stateToggler("showAst")),
      toggleDoc: () => this.setState(stateToggler("showDoc")),
      toggleComments: () => this.setState(stateToggler("showComments")),
      toggleSecondFormat: () => this.setState(stateToggler("showSecondFormat")),
      ...storage.get("editor_state"),
    };
  }

  componentDidUpdate(_, prevState) {
    if (!shallowEqual(this.state, prevState)) {
      storage.set("editor_state", this.state);
    }
  }

  render() {
    return this.props.children(this.state);
  }
}

<|edits_diff|>
--- website/playground/EditorState.js
+++ website/playground/EditorState.js
@@ -12,6 +12,8 @@
       showDoc: false,
       showComments: false,
       showSecondFormat: false,
+      showInput: true,
+      showOutput: true,
       toggleSidebar: () => this.setState(stateToggler("showSidebar")),
       toggleAst: () => this.setState(stateToggler("showAst")),
       toggleDoc: () => this.setState(stateToggler("showDoc")),
<|current_version|>
import * as React from "react";

import { stateToggler, shallowEqual } from "./helpers";
import * as storage from "./storage";

export default class extends React.Component {
  constructor() {
    super();
    this.state = {
      showSidebar: window.innerWidth > window.innerHeight,
      showAst: false,
      showDoc: false,
      showComments: false,
      showSecondFormat: false,
      showInput: true,
      showOutput: true,
      toggleSidebar: () => this.setState(stateToggler("showSidebar")),
      toggleAst: () => this.setState(stateToggler("showAst")),
      toggleDoc: () => this.setState(stateToggler("showDoc")),
      toggleComments: () => this.setState(stateToggler("showComments")),
      toggleSecondFormat: () => this.setState(stateToggler("showSecondFormat")),
      ...storage.get("editor_state"),
    };
  }

  componentDidUpdate(_, prevState) {
    if (!shallowEqual(this.state, prevState)) {
      storage.set("editor_state", this.state);
    }
  }

  render() {
    return this.props.children(this.state);
  }
}

<|next_version|>
import * as React from "react";

import { stateToggler, shallowEqual } from "./helpers";
import * as storage from "./storage";

export default class extends React.Component {
  constructor() {
    super();
    this.state = {
      showSidebar: window.innerWidth > window.innerHeight,
      showAst: false,
      showDoc: false,
      showComments: false,
      showSecondFormat: false,
      showInput: true,
      showOutput: true,
      toggleSidebar: () => this.setState(stateToggler("showSidebar")),
      toggleAst: () => this.setState(stateToggler("showAst")),
      toggleDoc: () => this.setState(stateToggler("showDoc")),
      toggleComments: () => this.setState(stateToggler("showComments")),
      toggleSecondFormat: () => this.setState(stateToggler("showSecondFormat")),
      toggleInput: () => this.setState(stateToggler("showInput")),
      toggleOutput: () => this.setState(stateToggler("showOutput")),
      ...storage.get("editor_state"),
    };
  }

  componentDidUpdate(_, prevState) {
    if (!shallowEqual(this.state, prevState)) {
      storage.set("editor_state", this.state);
    }
  }

  render() {
    return this.props.children(this.state);
  }
}